| Data-Page-FlickrLike documentation | Contained in the Data-Page-FlickrLike distribution. |
Data::Page::FlickrLike - Generates flickr-like navigation links
use Data::Page;
use Data::Page::FlickrLike;
my $page = Data::Page->new();
$page->total_entries($total_entries);
$page->entries_per_page($entries_per_page);
$page->current_page($current_page);
print join (" ",
map { $_ == 0
? q{<span>...</span>}
: qq{<a href="/page/$_">$_</a>}
} $page->navigations);
# 1*2 3 4 5 6 7 ... 76 77
# 1 2 ... 10 11 12 13*14 15 16 ... 76 77
# 1 2 ... 71 72 73 74 75 76 77*
# Note: * means the current page
Data::Page::FlickrLike is an extension to Data::Page to generate flickr-like navigation links.
This method returns an array reference consisting of the the pages to display.
$nav = $page->navigations
It calculates: how many pages should be displayed after the first and before the last page, whether or not there's a big enough gap between the first page and the current page to put an ellipsis and more. As the name of this modules says, the array ref should make it easy to generate a "Flickr-Like" navigation.
This methods uses "0" to represent an ellipsis between two sets of page numbers. For example, if you have enough pages, navigations() returns like this:
[ 1, 2, 3, 4, 5, 6, 7, 0, 76, 77 ]
So, to display an ellipsis(...) you would write:
for my $num ($page->navigations) {
if ($num == 0 ) {
print "...";
} else {
print qq{<a href="/page/$_">$_</a>};
}
}
By default, navigation() generates an array reference to create the same pagination than Flickr.com. But if you do not like this behavior, you can tweak the following configuration variables:
Customises the minimum number of pages before and after the current page.
Customises the number of pages at the start and end of the pager.
If current page is adjacent to an edge, the number of pages returned around current page will be extended to meet c<$Data::Page::FlickrLike::MinLength>
Customises the glue capability of the page. "Gluing" means that if the set containing the current page is isolated of an edge, we merge the two sets together by adding the interleaved pages to form a bigger set. This variable defines the maximum distance between two sets required to glue them together.
For example, these "3g" and "4g" are displayed because of the glue length (= 2).
1 2 3 4 5 6* 7 8 9 ... 21 22 1 2 3g 4 5 6 7* 8 9 10 ... 21 22 1 2 3g 4g 5 6 7 8* 9 10 11 ... 21 22 1 2 ... 5 6 7 8 9* 10 11 12 ... 21 22 (* represents the current page)
Masayoshi Sekimura <sekimura@cpan.org> Yann Kerherve <yannk@cpan.org>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Data::Page, Data::Page::Navigation, http://flickr.com/
| Data-Page-FlickrLike documentation | Contained in the Data-Page-FlickrLike distribution. |
package Data::Page::FlickrLike; use warnings; use strict; use 5.008_001; use Exporter::Lite; use Data::Page; our $VERSION = '2.00'; our @EXPORT = qw( navigations ); our $InnerWindow = 3; our $OuterWindow = 2; our $MinLength = 7; our $GlueLength = 2; sub _get_min_fill { my ($page, $first_page, $last_page, $min) = @_; my $length = $last_page - $first_page + 1 < $min ? $last_page - $first_page + 1 : $min; my $current_length = scalar @$page; return $length - $current_length; } sub Data::Page::navigations { my ($self, $args) = @_; my $nav; my $prev_skip = 1; my $next_skip = 1; my $inner = exists $args->{inner_window} ? $args->{inner_window} : $Data::Page::FlickrLike::InnerWindow; my $outer = exists $args->{outer_window} ? $args->{outer_window} : $Data::Page::FlickrLike::OuterWindow; my $min = exists $args->{min_length} ? $args->{min_length} : $Data::Page::FlickrLike::MinLength; my $glue_length = exists $args->{glue_length} ? $args->{glue_length} : $Data::Page::FlickrLike::GlueLength; my $current_page = $self->current_page; my $last_page = $self->last_page; my $first_page = $self->first_page; ## build the pages around current_page to begin with for (my $i = $current_page - $inner; $i <= $current_page + $inner ; $i++) { push @$nav, $i if $i >= $first_page && $i <= $last_page; } ## shortcut if we already take all the room if ($nav->[0] == $first_page && $nav->[-1] == $last_page) { return wantarray ? @$nav : $nav; } ## NOTE: there are some extra operations in there just in case $first_page != 1 ## but, this shouldn't really be necessary... if ($nav->[0] == $first_page && $nav->[-1] != $last_page) { ## we're stuck at the beginning, check for $min_lengh my $min_fill = _get_min_fill($nav, $first_page, $last_page, $min); my $last = $nav->[-1]; push @$nav, map { $last + $_ } (1 .. $min_fill); } ## stuck at the end: fill the beginning using $min_length elsif ($nav->[0] != $first_page && $nav->[-1] == $last_page) { my $min_fill = _get_min_fill($nav, $first_page, $last_page, $min); my $first = $nav->[0]; unshift @$nav, reverse map { $first - $_ } (1 .. $min_fill); } ## now, care about extremities specifically my (@begin, @end); for (0 .. ($outer - 1)) { push @begin, $first_page + $_; push @end, $last_page - $_; } @end = reverse @end; ## we might need some glue if ($begin[-1] < $nav->[0] - 1) { my $to_glue = $nav->[0] - $begin[-1] - 1; if ($to_glue <= $glue_length) { ## we can glue! my $last = $begin[-1]; push @begin, map { $last + $_ } (1 .. $to_glue); } else { push @begin, 0; } } if ($end[0] > $nav->[-1] + 1) { my $to_glue = $end[0] - $nav->[-1] - 1; if ($to_glue <= $glue_length) { ## we can glue! my $first = $end[0]; unshift @end, reverse map { $first - $_ } (1 .. $to_glue); } else { unshift @end, 0; } } ## trim redundant items if they exist while (@begin && $begin[-1] >= $nav->[0]) { pop @begin; }; while (@end && $end[0] && $end[0] <= $nav->[-1]) { shift @end; }; $nav = [ @begin, @$nav, @end ]; return wantarray ? @$nav : $nav; } 1; # Magic true value required at end of module __END__