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
    I quite like the idea , and I recommend adding a hard limit for the number of items per pages (max_entries_per_page) (Update: I didn't notice the flexibility that does this job, sorry for the noise).

    Regarding the name: I think the point is not that the number of entries per page is flexible (you can adjust that for other paging systems as well), but that it is automatically chosen.

    But I don't like Data::Page::Automatic very much (it doesn't give you a good idea what's going on), so maybe a fellow monk has a better idea.

      True, the name is difficult.

      The first name I had was Data::Page::Fuzzy, as the entries per page isn't known, but since there is no fuzzy math involved it doesn't explain what the module does very well.

      Perhaps Data::Page::Adjusted, since the entries per page gets adjusted to a more reasonable value. Or Data::Page::Reflow.

Re: RFC: Module for flexible data pagination
by Kimtaro (Acolyte) on Oct 25, 2007 at 19:16 UTC

    Ok, after having mulled over the name for a few days, I have come up with a better one that describes what the module actually does.

    Data::Page::Balanced

    Since the module balances the entries so that there are more or less an equal number of entries on all pages.

    Unless anyone has any objections to this I will go with it.

Re: RFC: Module for flexible data pagination
by Kimtaro (Acolyte) on Oct 28, 2007 at 00:36 UTC