Data::Pageとページナビゲーション
検索などで多くのページがヒットしたときの、ページナビゲーション
<< 3 4 5 6 *7 8 9 10 11 12 >>
の部分をうまく扱って、100ページ分とかあっても、前後のページのみ表示するモジュールを探していたんだけど、良いのが見つからない。
Data::Pagesetというのがあるんだけど、思ったのと違う。
トータルエントリーが30、1ページ5つのエントリーとして、ナビゲーションのリンクは4つとした場合に、Data::Pagesetでは、
ページ1の場合 *1, 2, 3, 4 ページ2の場合 1, *2, 3, 4 ページ3の場合 1, 2, *3, 4 ページ4の場合 1, 2, 3, *4 ページ5の場合 *5, 6 ページ6の場合 5, *6
となってしまいます。*がついているところは現在のページを表してます。
希望としては、
ページ1の場合 *1, 2, 3, 4 ページ2の場合 1, *2, 3, 4 ページ3の場合 2, *3, 4, 5 ページ4の場合 3, *4, 5, 6 ページ5の場合 3, 4, *5, 6 ページ6の場合 3, 4, 5, *6
こうなってほしいのです。
Data::Pagesetの場合のソースは↓
foreach my $current_page (1..6){ my $pageset = Data::Pageset->new({ total_entries=>$total_entries, entries_per_page=>$entries_per_page, current_page=>$current_page, pages_per_set=>$pages_per_set, }); print join ",", "p$current_page",map {sprintf("% 3s",($_ == $current_page) ? "*$_" : $_)} @{$pageset->pages_in_set}; print "\n"; }
Data::Page::Pagesetというのもあるけど、ちょっと違う。
んで、思った通りのモジュールが見当たらないので、ちょっとひどい実装だけど自分で組んでみた。
Data::Pageを継承して、pages_in_setメソッドを追加しています。モジュール名も適当。
package DataPageSet; use strict; use warnings; use base qw(Data::Page); __PACKAGE__->mk_accessors(qw(pages_per_set)); sub new { my $class = shift; my $self = {}; bless($self, $class); my ($total_entries, $entries_per_page, $current_page, $pages_per_set) = @_; $self->total_entries($total_entries || 0); $self->entries_per_page($entries_per_page || 10); $self->current_page($current_page || 1); $self->pages_per_set($pages_per_set || 10); return $self; } sub pages_in_set(){ my $self = shift; my $pages_per_set = shift; $pages_per_set ||= $self->pages_per_set || 10; return ($self->first_page..$self->last_page) if $pages_per_set >= $self->last_page; my $prev = $self->current_page - 1; my $next = $self->current_page + 1; my @ret = ($self->current_page); my $i=0; while(@ret < $pages_per_set){ if($i%2){ unshift(@ret,$prev) if $self->first_page <= $prev; --$prev; }else{ push(@ret,$next) if $self->last_page >= $next; $next++; } $i++; } return @ret; } 1;
全くヒドい実装だが、とりあえず動く。
使い方は、Data::Pageと同じ形で四つ目の引数に1ページのナビゲーションのリンクの数を書く。
初期値は10で、pages_per_setでも変更ができる。
foreach my $current_page (1..6){ my $pageset = DataPageSet->new( $total_entries, $entries_per_page, $current_page, $pages_per_set ); print join ",", "p$current_page",map {sprintf("% 3s",($_ == $current_page) ? "*$_" : $_)} $pageset->pages_in_set; print "\n"; }
これの結果は
p1, *1, 2, 3, 4 p2, 1, *2, 3, 4 p3, 2, *3, 4, 5 p4, 3, *4, 5, 6 p5, 3, 4, *5, 6 p6, 3, 4, 5, *6
となって思った通り動いてくれました。
もうすこしましな実装と、Time::Piece::MySQLのようにプラグイン的な使い方ができたらいいかなぁと思う。