File Coverage

blib/lib/HTML/Widgets/NavMenu.pm
Criterion Covered Total %
statement 310 313 99.0
branch 83 90 92.2
condition 38 43 88.3
subroutine 54 54 100.0
pod 4 4 100.0
total 489 504 97.0


line stmt bran cond sub pod time code
1             package HTML::Widgets::NavMenu;
2             $HTML::Widgets::NavMenu::VERSION = '1.0902';
3 11     11   589919 use strict;
  11         99  
  11         269  
4 11     11   50 use warnings;
  11         18  
  11         260  
5              
6 11     11   211 use 5.012;
  11         31  
7              
8             package HTML::Widgets::NavMenu::Error;
9             $HTML::Widgets::NavMenu::Error::VERSION = '1.0902';
10 11     11   3604 use parent "HTML::Widgets::NavMenu::Object";
  11         2585  
  11         44  
11              
12             package HTML::Widgets::NavMenu::Error::Redirect;
13             $HTML::Widgets::NavMenu::Error::Redirect::VERSION = '1.0902';
14 11     11   594 use strict;
  11         23  
  11         200  
15 11     11   44 use vars qw(@ISA);
  11         17  
  11         1118  
16             @ISA = ("HTML::Widgets::NavMenu::Error");
17              
18             sub CGIpm_perform_redirect
19             {
20 2     2   754 my $self = shift;
21              
22 2         3 my $cgi = shift;
23              
24 2         5 print $cgi->redirect( $cgi->script_name() . $self->{-redirect_path} );
25 2         93 exit;
26             }
27              
28             package HTML::Widgets::NavMenu::NodeDescription;
29             $HTML::Widgets::NavMenu::NodeDescription::VERSION = '1.0902';
30 11     11   61 use strict;
  11         18  
  11         234  
31              
32 11     11   47 use parent qw(HTML::Widgets::NavMenu::Object);
  11         16  
  11         51  
33              
34             __PACKAGE__->mk_acc_ref( [qw(host host_url title label direct_url url_type)] );
35              
36             sub _init
37             {
38 238     238   375 my ( $self, $args ) = @_;
39              
40 238         757 while ( my ( $k, $v ) = each(%$args) )
41             {
42 1428         3905 $self->$k($v);
43             }
44              
45 238         377 return 0;
46             }
47              
48             1;
49              
50             package HTML::Widgets::NavMenu::LeadingPath::Component;
51             $HTML::Widgets::NavMenu::LeadingPath::Component::VERSION = '1.0902';
52 11     11   1725 use vars qw(@ISA);
  11         18  
  11         736  
53              
54             @ISA = (qw(HTML::Widgets::NavMenu::NodeDescription));
55              
56             package HTML::Widgets::NavMenu::Iterator::GetCurrentlyActive;
57             $HTML::Widgets::NavMenu::Iterator::GetCurrentlyActive::VERSION = '1.0902';
58 11     11   69 use parent 'HTML::Widgets::NavMenu::Iterator::Base';
  11         19  
  11         40  
59              
60             __PACKAGE__->mk_acc_ref(
61             [
62             qw(
63             _item_found
64             _leading_path_coords
65             _ret_coords
66             _temp_coords
67             _tree
68             )
69             ]
70             );
71              
72             sub _init
73             {
74 52     52   83 my $self = shift;
75 52         69 my $args = shift;
76              
77 52         233 $self->SUPER::_init($args);
78              
79 52         120 $self->_tree( $args->{'tree'} );
80              
81 52         100 $self->_item_found(0);
82              
83 52         98 return 0;
84             }
85              
86             sub get_initial_node
87             {
88 52     52   79 my $self = shift;
89              
90 52         163 return $self->_tree;
91             }
92              
93             sub item_matches
94             {
95 270     270   375 my $self = shift;
96 270         468 my $item = $self->top();
97 270         491 my $url = $item->_node()->url();
98 270         438 my $nav_menu = $self->nav_menu();
99 270   66     1429 return ( ( $item->_accum_state()->{'host'} eq $nav_menu->current_host() )
100             && ( defined($url) && ( $url eq $nav_menu->path_info() ) ) );
101             }
102              
103             sub does_item_expand
104             {
105 243     243   322 my $self = shift;
106 243         461 my $item = $self->top();
107 243         546 return $item->_node()->capture_expanded();
108             }
109              
110             sub node_start
111             {
112 270     270   445 my $self = shift;
113              
114 270 100       401 if ( $self->item_matches() )
    100          
115             {
116 27         48 my @coords = @{ $self->get_coords() };
  27         78  
117 27         74 $self->_ret_coords( [@coords] );
118 27         72 $self->_temp_coords( [ @coords, (-1) ] );
119 27         62 $self->top()->_node()->mark_as_current();
120 27         67 $self->_item_found(1);
121             }
122             elsif ( $self->does_item_expand() )
123             {
124 23         39 my @coords = @{ $self->get_coords() };
  23         48  
125 23         74 $self->_leading_path_coords( [@coords] );
126             }
127             }
128              
129             sub node_end
130             {
131 270     270   319 my $self = shift;
132 270 100       591 if ( $self->_item_found() )
133             {
134             # Skip the first node, because the coords refer
135             # to the nodes below it.
136 61         72 my $idx = pop( @{ $self->_temp_coords() } );
  61         100  
137 61 100       135 if ( $idx >= 0 )
138             {
139 34         64 my $node = $self->top()->_node();
140 34         84 $node->update_based_on_sub( $node->get_nth_sub($idx) );
141             }
142             }
143             }
144              
145             sub node_should_recurse
146             {
147 488     488   636 my $self = shift;
148 488         1279 return ( !$self->_item_found() );
149             }
150              
151             sub get_final_coords
152             {
153 52     52   78 my $self = shift;
154              
155 52         169 return $self->_ret_coords();
156             }
157              
158             sub _get_leading_path_coords
159             {
160 52     52   83 my $self = shift;
161              
162 52   100     214 return ( $self->_ret_coords() || $self->_leading_path_coords() );
163             }
164              
165             package HTML::Widgets::NavMenu;
166              
167 11     11   4522 use parent 'HTML::Widgets::NavMenu::Object';
  11         31  
  11         37  
168              
169 11     11   4737 use HTML::Widgets::NavMenu::Url ();
  11         27  
  11         28149  
170              
171             require HTML::Widgets::NavMenu::Iterator::NavMenu;
172             require HTML::Widgets::NavMenu::Iterator::SiteMap;
173             require HTML::Widgets::NavMenu::Tree::Node;
174             require HTML::Widgets::NavMenu::Predicate;
175              
176             __PACKAGE__->mk_acc_ref(
177             [
178             qw(
179             _current_coords
180             coords_stop
181             current_host
182             _hosts
183             _no_leading_dot
184             _leading_path_coords
185             path_info
186             _traversed_tree
187             _tree_contents
188             _ul_classes
189             )
190             ]
191             );
192              
193             sub _init
194             {
195 56     56   100 my $self = shift;
196              
197 56         246 my %args = (@_);
198              
199 56         203 $self->_register_path_info( \%args );
200              
201 54         139 $self->_hosts( $args{hosts} );
202 54         118 $self->_tree_contents( $args{tree_contents} );
203              
204             $self->current_host( $args{current_host} )
205 54 100       177 or die "Current host was not specified.";
206              
207 53   100     222 $self->_ul_classes( $args{'ul_classes'} || [] );
208              
209             $self->_no_leading_dot(
210 53 100       168 exists( $args{'no_leading_dot'} ) ? $args{'no_leading_dot'} : 0 );
211              
212 53   50     198 $self->coords_stop( $args{coords_stop} || 0 );
213              
214 53         130 return 0;
215             }
216              
217             sub _get_nav_menu_traverser_args
218             {
219 295     295   391 my $self = shift;
220              
221             return {
222 295         1067 'nav_menu' => $self,
223             'ul_classes' => $self->_ul_classes(),
224             };
225             }
226              
227             sub _get_nav_menu_traverser
228             {
229 245     245   299 my $self = shift;
230              
231 245         412 return HTML::Widgets::NavMenu::Iterator::NavMenu->new(
232             $self->_get_nav_menu_traverser_args() );
233             }
234              
235             sub _get_current_coords
236             {
237 188     188   243 my $self = shift;
238              
239             # This is to make sure $self->_current_coords() is generated.
240 188         388 $self->_get_traversed_tree();
241              
242 188         217 return [ @{ $self->_current_coords() } ];
  188         522  
243             }
244              
245             sub _register_path_info
246             {
247 56     56   94 my $self = shift;
248 56         72 my $args = shift;
249              
250 56         110 my $path_info = $args->{path_info};
251              
252 56         89 my $redir_path = undef;
253              
254 56 100       266 if ( $path_info eq "" )
    100          
255             {
256 1         3 $redir_path = "";
257             }
258             elsif ( $path_info =~ m/\/\/$/ )
259             {
260 1         2 my $path = $path_info;
261 1         6 $path =~ s{\/+$}{};
262 1         2 $redir_path = $path;
263             }
264              
265 56 100       139 if ( defined($redir_path) )
266             {
267 2         11 my $error = HTML::Widgets::NavMenu::Error::Redirect->new();
268              
269 2         7 $error->{'-redirect_path'} = ( $redir_path . "/" );
270 2         5 $error->{'msg'} = "Need to redirect";
271              
272 2         11 die $error;
273             }
274              
275 54         213 $path_info =~ s!^\/!!;
276              
277 54         205 $self->path_info($path_info);
278              
279 54         90 return 0;
280             }
281              
282             sub _is_slash_terminated
283             {
284 1207     1207   1403 my $string = shift;
285 1207 100       4638 return ( ( $string =~ /\/$/ ) ? 1 : 0 );
286             }
287              
288             sub _text_to_url_obj
289             {
290 805     805   1046 my $text = shift;
291 805   100     1093 my $url =
292             HTML::Widgets::NavMenu::Url->new( $text,
293             ( _is_slash_terminated($text) || ( $text eq "" ) ), "server", );
294 805         1078 return $url;
295             }
296              
297             sub _get_relative_url
298             {
299 402     402   556 my $from_text = shift;
300 402         607 my $to_text = shift(@_);
301 402         486 my $no_leading_dot = shift;
302              
303 402         581 my $from_url = _text_to_url_obj($from_text);
304 402         628 my $to_url = _text_to_url_obj($to_text);
305 402         683 my $ret =
306             $from_url->_get_relative_url( $to_url, _is_slash_terminated($from_text),
307             $no_leading_dot, );
308 402         1136 return $ret;
309             }
310              
311             sub _get_full_abs_url
312             {
313 43     43   73 my ( $self, $args ) = @_;
314              
315 43         62 my $host = $args->{host};
316 43         57 my $host_url = $args->{host_url};
317              
318 43         244 return ( $self->_hosts->{$host}->{base_url} . $host_url );
319             }
320              
321             sub get_cross_host_rel_url_ref
322             {
323 466     466 1 788 my ( $self, $args ) = @_;
324              
325 466         649 my $host = $args->{host};
326 466         597 my $host_url = $args->{host_url};
327 466         559 my $url_type = $args->{url_type};
328 466         550 my $url_is_abs = $args->{url_is_abs};
329              
330 466 100 100     2196 if ($url_is_abs)
    100          
    100          
    100          
331             {
332 15         57 return $host_url;
333             }
334             elsif ( ( $host ne $self->current_host() ) || ( $url_type eq "full_abs" ) )
335             {
336 43         93 return $self->_get_full_abs_url($args);
337             }
338             elsif ( $url_type eq "rel" )
339             {
340             # TODO : convert to a method.
341 401         1004 return _get_relative_url( $self->path_info(), $host_url,
342             $self->_no_leading_dot() );
343             }
344             elsif ( $url_type eq "site_abs" )
345             {
346 6         34 return ( $self->_hosts->{$host}->{trailing_url_base} . $host_url );
347             }
348             else
349             {
350 1         17 die "Unknown url_type \"$url_type\"!\n";
351             }
352             }
353              
354             sub get_cross_host_rel_url
355             {
356 13     13 1 1740 my $self = shift;
357              
358 13         40 return $self->get_cross_host_rel_url_ref( {@_} );
359             }
360              
361             sub _get_url_to_item
362             {
363 453     453   610 my $self = shift;
364 453         573 my $item = shift;
365              
366             return $self->get_cross_host_rel_url_ref(
367             {
368 453   100     1582 'host' => $item->_accum_state()->{'host'},
369             'host_url' => ( $item->_node->url() || "" ),
370             'url_type' => $item->get_url_type(),
371             'url_is_abs' => $item->_node->url_is_abs(),
372             }
373             );
374             }
375              
376             sub _gen_blank_nav_menu_tree_node
377             {
378 353     353   453 my $self = shift;
379              
380 353         641 return HTML::Widgets::NavMenu::Tree::Node->new();
381             }
382              
383             sub _create_predicate
384             {
385 38     38   69 my ( $self, $args ) = @_;
386              
387 38         127 return HTML::Widgets::NavMenu::Predicate->new( 'spec' => $args->{'spec'}, );
388             }
389              
390             sub _create_new_nav_menu_item
391             {
392 353     353   495 my ( $self, $args ) = @_;
393              
394 353         426 my $sub_contents = $args->{sub_contents};
395              
396 353         526 my $new_item = $self->_gen_blank_nav_menu_tree_node();
397              
398 353         758 $new_item->set_values_from_hash_ref($sub_contents);
399              
400 353 100       595 if ( exists( $sub_contents->{'expand'} ) )
401             {
402             my $expand_val = $self->_create_predicate(
403             {
404 38         103 'spec' => $sub_contents->{'expand'},
405             }
406             )->evaluate(
407             'path_info' => $self->path_info(),
408             'current_host' => $self->current_host(),
409             );
410 38 100       100 if ($expand_val)
411             {
412 18         46 $new_item->expand($expand_val);
413             }
414             }
415              
416 353         499 return $new_item;
417             }
418              
419             sub _render_tree_contents
420             {
421 353     353   418 my $self = shift;
422 353         403 my $sub_contents = shift;
423              
424 353         512 my $path_info = $self->path_info();
425              
426 353         682 my $new_item =
427             $self->_create_new_nav_menu_item( { sub_contents => $sub_contents }, );
428              
429 353 100       702 if ( exists( $sub_contents->{subs} ) )
430             {
431 127         162 foreach my $sub_contents_sub ( @{ $sub_contents->{subs} } )
  127         302  
432             {
433 301         554 $new_item->add_sub(
434             $self->_render_tree_contents( $sub_contents_sub, ) );
435             }
436             }
437 353         745 return $new_item;
438             }
439              
440             sub gen_site_map
441             {
442 6     6 1 20 my $self = shift;
443              
444 6         25 my $iterator = HTML::Widgets::NavMenu::Iterator::SiteMap->new(
445             {
446             'nav_menu' => $self,
447             }
448             );
449              
450 6         21 $iterator->traverse();
451              
452 6         14 return $iterator->get_results();
453             }
454              
455             sub _get_next_coords
456             {
457 52     52   76 my $self = shift;
458              
459 52 100       126 my @coords = @{ shift || $self->_get_current_coords };
  52         141  
460              
461 52         100 my @branches = ( $self->_get_traversed_tree() );
462              
463 52         87 my @dest_coords;
464              
465             my $i;
466              
467 52         158 for ( $i = 0 ; $i < scalar(@coords) ; ++$i )
468             {
469 43         115 $branches[ $i + 1 ] = $branches[$i]->get_nth_sub( $coords[$i] );
470             }
471              
472 52 100       164 if ( $branches[$i]->_num_subs() )
473             {
474 30         82 @dest_coords = ( @coords, 0 );
475             }
476             else
477             {
478 22         59 for ( --$i ; $i >= 0 ; --$i )
479             {
480 29 100       52 if ( $branches[$i]->_num_subs() > ( $coords[$i] + 1 ) )
481             {
482 19         61 @dest_coords = ( @coords[ 0 .. ( $i - 1 ) ], $coords[$i] + 1 );
483 19         30 last;
484             }
485             }
486 22 100       59 if ( $i == -1 )
487             {
488 3         8 return;
489             }
490             }
491              
492 49         137 return \@dest_coords;
493             }
494              
495             sub _get_prev_coords
496             {
497 49     49   81 my $self = shift;
498              
499 49 100       63 my @coords = @{ shift || $self->_get_current_coords() };
  49         130  
500              
501 49 100       159 if ( scalar(@coords) == 0 )
    100          
502             {
503 19         41 return;
504             }
505             elsif ( $coords[$#coords] > 0 )
506             {
507             # Get the previous leaf
508 23         79 my @previous_leaf =
509             ( @coords[ 0 .. ( $#coords - 1 ) ], $coords[$#coords] - 1 );
510              
511             # Continue in this leaf to the end.
512 23         74 my $new_coords = $self->_get_most_advanced_leaf( \@previous_leaf );
513              
514 23         66 return $new_coords;
515             }
516             else
517             {
518 7         25 return [ @coords[ 0 .. ( $#coords - 1 ) ] ];
519             }
520             }
521              
522             sub _get_up_coords
523             {
524 130     130   167 my $self = shift;
525              
526 130 100       162 my @coords = @{ shift || $self->_get_current_coords };
  130         329  
527              
528 130 100       267 if ( scalar(@coords) == 0 )
529             {
530 19         53 return;
531             }
532             else
533             {
534 111 100 100     370 if ( ( @coords == 1 ) && ( $coords[0] > 0 ) )
535             {
536 81         173 my $coords_stop = $self->coords_stop();
537 81         176 my $ret = [0];
538 81 50       162 if ($coords_stop)
539             {
540 0         0 $ret = [];
541             }
542 81         186 return $ret;
543             }
544 30         52 pop(@coords);
545 30         68 return \@coords;
546             }
547             }
548              
549             sub _get_top_coords
550             {
551 46     46   70 my $self = shift;
552              
553 46 100       63 my @coords = @{ shift || $self->_get_current_coords() };
  46         108  
554              
555 46 100 100     233 if ( ( !@coords ) || ( ( @coords == 1 ) && ( $coords[0] == 0 ) ) )
      100        
556             {
557 21         102 return;
558             }
559             else
560             {
561 25         119 return [0];
562             }
563             }
564              
565             sub _is_skip
566             {
567 97     97   141 my $self = shift;
568 97         120 my $coords = shift;
569              
570 97         176 my $iterator = $self->_get_nav_menu_traverser();
571              
572 97         279 my $ret = $iterator->find_node_by_coords($coords);
573              
574 97         156 my $item = $ret->{item};
575              
576 97         295 return $item->_node()->skip();
577             }
578              
579             sub _get_coords_while_skipping_skips
580             {
581 93     93   128 my $self = shift;
582              
583 93         109 my $callback = shift;
584 93         119 my $coords = shift(@_);
585 93 100       194 if ( !$coords )
586             {
587 92         176 $coords = $self->_get_current_coords();
588             }
589              
590 93         131 my $do_once = 1;
591              
592 93   100     253 while ( $do_once || $self->_is_skip($coords) )
593             {
594 97         196 $coords = $callback->( $self, $coords );
595             }
596             continue
597             {
598 97         282 $do_once = 0;
599             }
600              
601 93         304 return $coords;
602             }
603              
604             sub _get_most_advanced_leaf
605             {
606 23     23   33 my $self = shift;
607              
608             # We accept as a parameter the vector of coordinates
609 23         29 my $coords_ref = shift;
610              
611 23         31 my @coords = @{$coords_ref};
  23         42  
612              
613             # Get a reference to the contents HDS (= hierarchial data structure)
614 23         47 my $branch = $self->_get_traversed_tree();
615              
616             # Get to the current branch by advancing to the offset
617 23         49 foreach my $c (@coords)
618             {
619             # Advance to the next level which is at index $c
620 26         69 $branch = $branch->get_nth_sub($c);
621             }
622              
623             # As long as there is something deeper
624 23         57 while ( my $num_subs = $branch->_num_subs() )
625             {
626 1         5 my $index = $num_subs - 1;
627              
628             # We are going to return it, so store it
629 1         2 push @coords, $index;
630              
631             # Recurse into the sub-branch
632 1         3 $branch = $branch->get_nth_sub($index);
633             }
634              
635 23         45 return \@coords;
636             }
637              
638              
639             # The traversed_tree is the tree that is calculated from the tree given
640             # by the user and some other parameters such as the host and path_info.
641             # It is passed to the NavMenu::Iterator::* classes as argument.
642             sub _get_traversed_tree
643             {
644 648     648   784 my $self = shift;
645              
646 648 100       1319 if ( !$self->_traversed_tree() )
647             {
648 52         117 my $gen_retval = $self->_gen_traversed_tree();
649 52         187 $self->_traversed_tree( $gen_retval->{'tree'} );
650 52         123 $self->_current_coords( $gen_retval->{'current_coords'} );
651 52         132 $self->_leading_path_coords( $gen_retval->{'leading_path_coords'} );
652             }
653 648         1506 return $self->_traversed_tree();
654             }
655              
656             sub _gen_traversed_tree
657             {
658 52     52   91 my $self = shift;
659              
660 52         158 my $tree = $self->_render_tree_contents( $self->_tree_contents(), );
661              
662 52         267 my $find_coords_iterator =
663             HTML::Widgets::NavMenu::Iterator::GetCurrentlyActive->new(
664             {
665             'nav_menu' => $self,
666             'tree' => $tree,
667             }
668             );
669              
670 52         208 $find_coords_iterator->traverse();
671              
672 52   100     128 my $current_coords = $find_coords_iterator->get_final_coords() || [];
673 52   100     112 my $leading_path_coords =
674             $find_coords_iterator->_get_leading_path_coords() || [];
675              
676             # The root should always be expanded because:
677             # 1. If one of the leafs was marked as expanded so will its ancestors
678             # and eventually the root.
679             # 2. If nothing was marked as expanded, it should still be marked as
680             # expanded so it will expand.
681 52         158 $tree->expand();
682              
683             return {
684 52         291 'tree' => $tree,
685             'current_coords' => $current_coords,
686             'leading_path_coords' => $leading_path_coords,
687             };
688             }
689              
690             sub _get_leading_path_of_coords
691             {
692 154     154   199 my $self = shift;
693 154         203 my $coords = shift;
694              
695 154         237 my $coords_stop = $self->coords_stop();
696              
697 154 50       260 if ( !$coords_stop )
698             {
699 154 100       282 if ( !@$coords )
700             {
701 10         18 $coords = [0];
702             }
703             }
704 154         168 if (0) # ( $coords->[0] == 0 )
705             {
706             $coords = [ @$coords[ 1 .. $#$coords ] ];
707             }
708              
709 154         182 my @leading_path;
710 154         276 my $iterator = $self->_get_nav_menu_traverser();
711              
712             COORDS_LOOP:
713 154         268 while (1)
714             {
715 238         497 my $ret = $iterator->find_node_by_coords($coords);
716              
717 238         384 my $item = $ret->{item};
718              
719 238         340 my $node = $item->_node();
720              
721             # This is a workaround for the root link.
722 238 50       575 my $host_url = ( defined( $node->url() ) ? ( $node->url() ) : "" );
723 238         393 my $host = $item->_accum_state()->{'host'};
724              
725 238 100       646 my $url_type = (
726             $node->url_is_abs()
727             ? "full_abs"
728             : $item->get_url_type()
729             );
730              
731 238         752 push @leading_path,
732             HTML::Widgets::NavMenu::LeadingPath::Component->new(
733             {
734             'host' => $host,
735             'host_url' => $host_url,
736             'title' => $node->title(),
737             'label' => $node->text(),
738             'direct_url' => $self->_get_url_to_item($item),
739             'url_type' => $url_type,
740             }
741             );
742              
743 238 50 100     1331 if (
    100          
744             $coords_stop
745             ? ( scalar(@$coords) == 0 )
746             : ( ( scalar(@$coords) == 1 ) && ( $coords->[0] == 0 ) )
747             )
748             {
749 154         442 last COORDS_LOOP;
750             }
751             }
752             continue
753             {
754 84         191 $coords = $self->_get_up_coords($coords);
755             }
756              
757 154         281 my $p = [ reverse(@leading_path) ];
758 154 50       287 if ($coords_stop)
759             {
760 0   0     0 while ( ( @$p > 1 and $p->[0]->host_url eq $p->[1]->host_url ) )
761             {
762 0         0 shift @$p;
763             }
764             }
765 154         296 return $p;
766             }
767              
768             sub _get_leading_path
769             {
770 44     44   69 my $self = shift;
771 44         138 return $self->_get_leading_path_of_coords( $self->_leading_path_coords() );
772             }
773              
774             sub render
775             {
776 44     44 1 170 my $self = shift;
777 44         78 my %args = (@_);
778              
779 44         157 return $self->_render_generic(
780             { %args, _iter_method => '_get_nav_menu_traverser', } );
781             }
782              
783             sub _is_top_coords
784             {
785 44     44   85 my ( $self, $coords, $only_empty, ) = @_;
786              
787             return (
788 44 100       202 defined($coords)
    50          
    100          
    50          
789             ? (
790             ( @$coords == 0 ) ? 1
791             : $only_empty ? ''
792             : ( @$coords == 1 ) ? ( $coords->[0] == 0 )
793             : ''
794             )
795             : 1
796             );
797             }
798              
799             sub _render_generic
800             {
801 44     44   80 my $self = shift;
802 44         73 my $args = shift;
803              
804 44         83 my $method = $args->{_iter_method};
805              
806 44         119 my $iterator = $self->$method();
807 44         173 $iterator->traverse();
808 44         144 my $html = $iterator->get_results();
809              
810 44         84 my %nav_links;
811             my %nav_links_obj;
812              
813 44         190 my %links_proto = (
814             'prev' => scalar(
815             $self->_get_coords_while_skipping_skips( \&_get_prev_coords )
816             ),
817             'next' => scalar(
818             $self->_get_coords_while_skipping_skips( \&_get_next_coords )
819             ),
820             'up' => scalar( $self->_get_up_coords() ),
821             'top' => scalar( $self->_get_top_coords() ),
822             );
823 44         160 my $IS_TOP =
824             $self->_is_top_coords( $self->_current_coords(), $self->coords_stop(),
825             );
826              
827 44         198 while ( my ( $link_rel, $coords ) = each(%links_proto) )
828             {
829             # This is so we would avoid coordinates that point to the
830             # root ($coords == []).
831 176 100 100     584 if ( $IS_TOP
832             and ( $link_rel =~ /\A(?:prev|top|up)\z/ms )
833             ) # $self->_is_top_coords( $coords, 1 ) )
834             {
835 63         88 undef($coords);
836             }
837 176 100       385 if ( defined($coords) )
838             {
839 110         233 my $obj = $self->_get_leading_path_of_coords($coords)->[-1];
840              
841 110         214 $nav_links_obj{$link_rel} = $obj;
842 110         401 $nav_links{$link_rel} = $obj->direct_url();
843             }
844             }
845              
846 44         76 my $js_code = "";
847              
848             return {
849 44         130 'html' => $html,
850             'leading_path' => $self->_get_leading_path(),
851             'nav_links' => \%nav_links,
852             'nav_links_obj' => \%nav_links_obj,
853             };
854             }
855              
856             1;
857              
858             __END__