package Data::Pagination; use 5.005; use strict; our $VERSION = '0.37'; # {{{ constructor # Making all calculations and storing results at class properties sub new { my $self = bless {}, shift; # statistics: $self->{total_entries} = shift; $self->{entries_per_page} = shift; $self->{pages_per_set} = shift; # pages control: # total number of pages $self->{total_pages} = int(($self->{total_entries} - 1) / $self->{entries_per_page}) + 1; # current page $self->{current_page} = shift; if ($self->{current_page} < 1) { $self->{current_page} = 1; } elsif ($self->{current_page} > $self->{total_pages}) { $self->{current_page} = $self->{total_pages}; } # previous number of page # undefine, if haven't place to be $self->{prev_page} = $self->{current_page} - 1; if ($self->{prev_page} < 1) { $self->{prev_page} = undef; } # next number of page # undefine, if haven't place to be $self->{next_page} = $self->{current_page} + 1; if ($self->{next_page} > $self->{total_pages}) { $self->{next_page} = undef; } # pages set control: # start position of current set $self->{start_of_set} = int(($self->{current_page} - 1) / $self->{pages_per_set}) * $self->{pages_per_set} + 1; # end position of current set $self->{end_of_set} = $self->{start_of_set} + $self->{pages_per_set} - 1; if ($self->{end_of_set} > $self->{total_pages}) { $self->{end_of_set} = $self->{total_pages}; } # nearest page number in previous set # undefine, if haven't place to be $self->{page_of_prev_set} = $self->{start_of_set} - 1; if ($self->{page_of_prev_set} < 1) { $self->{page_of_prev_set} = undef; } # nearest page number in next set # undefine, if haven't place to be $self->{page_of_next_set} = $self->{end_of_set} + 1; if ($self->{page_of_next_set} > $self->{total_pages}) { $self->{page_of_next_set} = undef; } # slice params: # start position of the slice $self->{start_of_slice} = ($self->{current_page} - 1) * $self->{entries_per_page}; # end position of the slice $self->{end_of_slice} = $self->{start_of_slice} + $self->{entries_per_page} - 1; if ($self->{end_of_slice} > $self->{total_entries} - 1) { $self->{end_of_slice} = $self->{total_entries} - 1; } # length of the slice $self->{length_of_slice} = $self->{end_of_slice} - $self->{start_of_slice} + 1; return $self; } # }}} 1; __END__ =head1 NAME Data::Pagination - Paginal navigation on some data =head1 SYNOPSIS use Data::Pagination; # previously needs to check total number of entries. it can be # count of SQL records or length of array or something other. # # example: SELECT count(*) ... # # note: if no records exists, then no needs to continue processing. # enough to tell the user about that. my $pg = Data::Pagination->new( $total_entries, # - total number of entries (>= 1) # $entries_per_page, # - how much records (>= 1) maximum you want # to see on one page. # $pages_per_set, # - how much pages you want to see in pages # set. if you don't want to use this # feature, then don't use, but some number # (>= 1) must be presented here. # $current_page # - user specified number of page from # request. must contain some integer # number (don't forget to check this). ); # now, for getting slice of data, use properties from # "slice params" group. # # example: SELECT ... # LIMIT $pg->{start_of_slice}, $pg->{length_of_slice} # all properties from "statistics" group are copied from arguments, # and with some properties from other groups can be used for # shown some statistic information to user. # # example: # # $pg->{total_pages} # / $pg->{total_entries} # Total pages: 20 / # Total records: 200 # Shown from 61 to 70 records # \ \ # \ $pg->{start_of_slice} + 1 # $pg->{end_of_slice} + 1 # # properties from "pages control" and "pages set control" intended # for construction paginal navigation panel. # # example (simple): # # <-- previous page | next page --> # / \ # $pg->{prev_page} $pg->{next_page} # # example (advanced): # # $pg->{current_page} # | # $pg->{prev_page} | $pg->{next_page} # \ | / # << < 6 [7] 8 9 10 > >> # / / \ \ # $pg->{page_of_prev_set} / \ $pg->{page_of_next_set} # / \ # $pg->{start_of_set} $pg->{end_of_set} # # =head1 DESCRIPTION This class intended for organization of paginal navigation on some data. Basically intended for construction of paginal navigation panels on web sites. =head1 METHODS =over 4 =item B<$pg = Data::Pagination-Enew($total_entries, $entries_per_page, $pages_per_set, $current_page)> Making all calculations and storing results at class properties. Arguments: =over 4 =item * B<$total_entries> - total number of entries (>= 1) =item * B<$entries_per_page> - number of entries per page (>= 1) =item * B<$pages_per_set> - number of pages per set (>= 1) =item * B<$current_page> - current number of page =back Note: all arguments are required and must contains only integer numbers. =back =head1 PROPERTIES Slice params: =over 4 =item * B<$pg-E{start_of_slice}> - start position of the slice (>= 0) =item * B<$pg-E{end_of_slice}> - end position of the slice (>= 0) =item * B<$pg-E{length_of_slice}> - length of the slice (>= 1) =back Statistics: =over 4 =item * B<$pg-E{total_entries}> - total number of entries (>= 1) (copied from arguments) =item * B<$pg-E{entries_per_page}> - number of entries per page (>= 1) (copied from arguments) =item * B<$pg-E{pages_per_set}> - number of pages per set (>= 1) (copied from arguments) =back Pages control: =over 4 =item * B<$pg-E{total_pages}> - total number of pages (>= 1) =item * B<$pg-E{current_page}> - current number of page (>= 1) (corrected) =item * B<$pg-E{prev_page}> - previous number of page (>= 1) or undefined, if haven't place to be =item * B<$pg-E{next_page}> - next number of page (>= 1) or undefined, if haven't place to be =back Pages set control: =over 4 =item * B<$pg-E{start_of_set}> - start position of current set (>= 1) =item * B<$pg-E{end_of_set}> - end position of current set (>= 1) =item * B<$pg-E{page_of_prev_set}> - nearest page number of the previous set (>= 1) or undefined, if haven't place to be =item * B<$pg-E{page_of_next_set}> - nearest page number of the next set (>= 1) or undefined, if haven't place to be =back =head1 NOTES =over 4 =item * Most simple way to check, needs to show navigation panel or not, is checking $pg-E{total_pages} property. Needs only, if this property more then 1. =item * $pg-E{prev_page}, $pg-E{next_page}, $pg-E{page_of_prev_set} and $pg-E{page_of_next_set} properties must be checked for undefined value before using. =item * All results are in numbers, and you can construct paginal navigation panels with any design and can use templates processors (as TT and others). For that you only needs to transfer class object to template processor params. =back =head1 SEE ALSO L L L L L =head1 AUTHOR Andrian Zubko Eondr@cpan.orgE =cut