File Coverage

blib/lib/HTML/Widgets/NavMenu.pm
Criterion Covered Total %
statement 309 312 99.0
branch 83 88 94.3
condition 38 43 88.3
subroutine 54 54 100.0
pod 4 4 100.0
total 488 501 97.4


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