sub paginate_list { my( $class, $session, $basename, $list, %opts ) = @_; my $n_results = $list->count(); my $offset = defined $opts{offset} ? $opts{offset} : ($session->param( $basename."_offset" ) || 0); $offset += 0; my $pagesize = defined $opts{page_size} ? $opts{page_size} : ($session->param( $basename."page_size" ) || 10); # TODO: get default from somewhere? $pagesize += 0; my @results = $list->get_records( $offset , $pagesize ); my $plast = $offset + $pagesize; $plast = $n_results if $n_results< $plast; # Add params to action urls my $url = URI->new( $session->get_uri ); my @param_list; #push @param_list, "_cache=" . $list->get_cache_id; # if cached #my $escexp = $list->{encoded}; # serialised search expression #$escexp =~ s/ /+/g; # not great way... #push @param_list, "_exp=$escexp"; if( defined $opts{params} ) { my $params = $opts{params}; foreach my $key ( keys %$params ) { my $value = $params->{$key}; push @param_list, $key => $value if defined $value; } } $url->query_form( @param_list ); my $paginate_data = { url => $url, basename => $basename, from => $offset + 1, to => $plast, n_results => $n_results, page_size => $opts{page_size}, }; my $results_info = { n_results => $n_results, rows_before => $opts{rows_before}, rows => [], rows_after => $opts{rows_after}, }; if( scalar $n_results > 0 ) { if( !$opts{page_size} ) { if( defined $session->param( "${basename}page_size" ) ) { $url->query_form( @param_list, $basename."page_size" => $pagesize ); } } } my @controls; # page controls if( defined $opts{controls_before} ) { foreach my $control ( @{ $opts{controls_before} } ) { push @controls, { url => $control->{url}, label => $control->{label}, type => 'before' }; } } # Previous page link if( $offset > 0 ) { my $bk = $offset-$pagesize; my $prevurl = "$url&$basename\_offset=".($bk<0?0:$bk); push @controls, { url => $prevurl, type => 'previous' }; } # Page jumps my $pages_to_show = $opts{pagejumps} || 10; # TODO: get default from somewhere? my $cur_page = $offset / $pagesize; my $num_pages = int( $n_results / $pagesize ); $num_pages++ if $n_results % $pagesize; $num_pages--; # zero based my $start_page = $cur_page - ( $pages_to_show / 2 ); my $end_page = $cur_page + ( $pages_to_show / 2 ); if( $start_page < 0 ) { $end_page += -$start_page; # end page takes up slack } if( $end_page > $num_pages ) { $start_page -= $end_page - $num_pages; # start page takes up slack } $start_page = 0 if $start_page < 0; # normalise $end_page = $num_pages if $end_page > $num_pages; # normalise unless( $start_page == $end_page ) # only one page, don't need jumps { for my $page_n ( $start_page..$end_page ) { my $jumpurl = "$url&$basename\_offset=" . $page_n * $pagesize; push @controls, { url => $jumpurl, label => $page_n + 1, type => $page_n != $cur_page ? "jump" : "current" }; } } # Next page link if( $offset + $pagesize < $n_results ) { my $nexturl="$url&$basename\_offset=".($offset+$pagesize); push @controls, { url => $nexturl, type => 'next' }; } my $has_main_controls = scalar @controls > 0; my $type; if( !defined $opts{container} ) { $type = $session->get_citation_type( $list->get_dataset ); } my $n = $offset; foreach my $result ( @results ) { $n += 1; my $row_info = { index => $n, as_div => 0, }; # Render individual results if( defined $opts{render_result} ) { # Custom rendering routine specified $row_info->{render} = &{ $opts{render_result} }( $session, $result, $opts{render_result_params}, $n ); } elsif( $type eq "table_row" ) { $row_info->{render} = $result->render_citation_link(); } else { $row_info->{as_div} = 1; $row_info->{render} = $result->render_citation_link(); } push @{ $results_info->{rows} }, $row_info; } # If we have no results, we can use a custom renderer to # put a descriptive phrase in place of the result list. if( $n_results == 0 ) { if( defined $opts{render_no_results} ) { my $params = $opts{render_result_params}; $results_info->{no_results_message} = &{ $opts{render_no_results} }( $session, $params, $session->html_phrase( "lib/paginate:no_items" ) ); } } my %pins; $pins{above_results} = $opts{above_results}; if( !defined $pins{above_results} ) { $pins{above_results} = $session->make_doc_fragment; } $pins{below_results} = $opts{below_results}; if( !defined $pins{below_results} ) { $pins{below_results} = $session->make_doc_fragment; } $results_info->{container} = $opts{container}; $results_info->{citation_type} = $type; $pins{results} = $session->template_phrase( "view:EPrints/Paginate:paginate_list/results_container", { item => $results_info } ); $paginate_data->{control_links} = \@controls; $paginate_data->{controls_after} = $opts{controls_after}; $paginate_data->{has_main_controls} = $has_main_controls; if( $has_main_controls || $opts{controls_after} ) { $pins{controls} = $session->template_phrase( "view:EPrints/Paginate:paginate_list/controls", { item => $paginate_data } ); } # Apply custom pins. my $custom_pins = $opts{pins}; for( keys %$custom_pins ) { $pins{$_} = $custom_pins->{$_} if defined $custom_pins->{$_}; } $paginate_data->{above_results} = $pins{above_results}; $paginate_data->{below_results} = $pins{below_results}; $paginate_data->{results} = $pins{results}; $paginate_data->{controls} = $pins{controls}; return $session->template_phrase( "view:EPrints/Paginate:paginate_list", { item => $paginate_data } ); }