Hi all,
I have written a small module for doing flexible data pagination, and since this is my first public module, I would appreciate any comments before I release it on CPAN as Data::Page::Flexible. The main thing left to do is to write some more tests for it.
It allows the number of entries per page to be flexible, so situations where you have two pages with only one or a few entries on the last page can be avoided.
The relevant POD is below and the code is after the jump.
Thanks!
NAME Data::Page::Flexible - A data pager that allows a flexible number of entries per page. VERSION This document describes Data::Page::Flexible version 0.0.1 SYNOPSIS use Data::Page::Flexible; my $pager = Data::Page::Flexible->new({ total_entries => 67, entries_per_page => 25 }); print $pager->last_page() # 2 print $pager->entries_per_page() # 34 DESCRIPTION This module behaves like Data::Page except that it allows the number of entries per page to be flexible. If, for example, you have 26 entries and want 25 entries per page, a normal pager would give you two pages with 25 entries on the first and 1 on the last. Data::Page::Flexible will instead give you one page with 26 entries. The benefit of a flexible number of entries per page is greater when the number of pages is small, with the ideal case being when there are two pages with only one entry on the last. This saves the user from having to navigate to a page with only one entry, making it easier for him or her to see all the entries at once. The default flexibility is "floor(entries_per_page/2)", which means that in the example with 25 entries per page, the calculated entries per page can go up to 37 (25 + 12). The flexibility can be changed both at initialization and later on. INTERFACE new my $pager = Data::Page::Flexible->new({ total_entries => 67, entries_per_page => 25 }); This constructs a new pager object. The "total_entries" and "entries_per_page" arguments are mandatory, since they are used to calculate the actual number of entries per page. You can optionally also specify the "current_page" and "flexibility" arguments. All arguments are given as name-value pairs in an anonymous hash. total_entries $pager->total_entries(100); # Sets the total entries to 100 $pager->total_entries(); # Returns the current total entries This will get or set the total entries. *Changing this will re-calculate the number of entries per page.* entries_per_page $pager->entries_per_page(23); # Sets the entries per page to 2 +3 $pager->entries_per_page(); # Returns the current entries pe +r page This will get or set the entries per page. *Since changing this will re-calculate the number of entries per page according to the flexibility, in most cases what you set is not what you later will get.* flexibility $pager->flexibility(12); # Sets the flexibility to 12 $pager->flexibility(); # Returns the current flexibility This will get or set the flexibility value. *Changing this will re-calculate the number of entries per page.*
package Data::Page::Flexible; use warnings; use strict; use Carp; use POSIX qw(ceil floor); use base qw(Class::Accessor::Chained::Fast Data::Page); use version; our $VERSION = qv('0.0.1'); __PACKAGE__->mk_accessors(qw(flexibility)); sub new { my ($class, $arg_ref) = @_; my $self = {}; croak("total_entries and entries_per_page must be supplied") unless defined $arg_ref->{'total_entries'} && defined $arg_ref->{'entries_per_page'}; bless($self, $class); # flexibility can be 0, which is false, so can't use ||-assignment my $flexibility = exists $arg_ref->{flexibility} ? $arg_ref->{flex +ibility} : floor($arg_ref->{entries_per_page} / 2); $self->_flexibility_accessor( $flexibility + ); $self->_total_entries_accessor( $arg_ref->{total_entries} + ); $self->_current_page_accessor( $arg_ref->{current_page} || +1 ); $self->_entries_per_page_accessor( $arg_ref->{entries_per_page} + ); $self->_entries_per_page_accessor( $self->_get_flexible_epp() + ); return $self; } # Calculate the entries_per_page (expected_epp) within the limits of t +he flexibility sub _get_flexible_epp { my ($self) = @_; my $flexibility = $self->flexibility(); my $total_entries = $self->total_entries(); my $entries_per_page = $self->entries_per_page(); return $entries_per_page if $flexibility == 0 || $total_entries == 0; return $entries_per_page if $total_entries < $entries_per_page; my $pages = ceil($total_entries / $entries_per_page +); my $expected_epp = $total_entries / $pages; ENTRIES: while ( $expected_epp < $entries_per_page ) { $pages--; $pages = 1 if $pages < 1; $expected_epp = $total_entries / $pages; if ( $expected_epp > $entries_per_page + $flexibility ) { $expected_epp = $entries_per_page; last ENTRIES; } } return ceil($expected_epp); } sub total_entries { my $self = shift; if ( @_ ) { my $accessor = $self->_total_entries_accessor(@_); $self->_entries_per_page_accessor( $self->_get_flexible_epp() +); return $accessor; } return $self->_total_entries_accessor(); } sub entries_per_page { my $self = shift; my $entries_per_page = $_[0]; if ( @_ ) { croak(sprintf('There must be at least one entry per page. %d i +s too small.', $entries_per_page)) if $entries_per_page < 1; $self->_entries_per_page_accessor(@_); return $self->_entries_per_page_accessor( $self->_get_flexible +_epp() ); } return $self->_entries_per_page_accessor(); } sub flexibility { my $self = shift; if ( @_ ) { my $accessor = $self->_flexibility_accessor(@_); $self->_entries_per_page_accessor( $self->_get_flexible_epp() +); return $accessor; } return $self->_flexibility_accessor(); } 1;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: RFC: Module for flexible data pagination
by moritz (Cardinal) on Oct 22, 2007 at 08:24 UTC | |
by Kimtaro (Acolyte) on Oct 22, 2007 at 15:04 UTC | |
|
Re: RFC: Module for flexible data pagination
by Kimtaro (Acolyte) on Oct 25, 2007 at 19:16 UTC | |
|
Re: RFC: Module for flexible data pagination
by Kimtaro (Acolyte) on Oct 28, 2007 at 00:36 UTC |