[Moscow.pm] Постраничный вывод (Pagination)

oleg alexeenkov proler на gmail.com
Пн Апр 23 09:11:11 PDT 2012


Alessandro Gorohovski <angel на domashka.kiev.ua> писал(а) в своём письме  
Mon, 23 Apr 2012 19:58:41 +0400:

> Andrew Shitov <andy на shitov.ru> писал(а) в своём письме Mon, 23 Apr 2012  
> 18:49:39 +0300:
>
>> http://search.cpan.org/search?query=pagination&mode=all
>> ?
>
> Спасибо.
> Согласен, выбор не просто большой --- огромный.
>
> А реально кто чем и
> главное как пользуется?

[вброс] давным давно наковырял такую штуку, работает с миллиардами страниц  
8) причем скорее всего путь перехода со страницы X на страницу Y будет  
наименьшим среди аналогов (особенно если подкрутить параметры)

sub gotopage {
   my ($fparam) = @_;
   my (%ret);
   #$fparam->{'total'} : total results, usually COUNT(*) as total
   #-----------size -- : size of one page in rows (LIMIT x,size)
   #current : current page number
   #actual : usually $DBI::rows, if total unknown
   #last : last page number (auto calculated from total/size if 0)
   #total_max = 1000 : maximum db results
   #printlog('dmp', 'gotopage start:', Dumper($fparam));
   $fparam->{'size'} = 100 unless defined $fparam->{'size'};
   return {} unless $fparam->{'size'};
   $fparam->{'actual'} = $fparam->{'size'} unless defined  
$fparam->{'actual'};
   $fparam->{'current'} ||= 1;
   $fparam->{'last'} ||=
     $fparam->{'size'} < 1
     ? undef
     : ( int( $fparam->{'total'} / ( $fparam->{'size'} || 1 ) ) + (  
$fparam->{'total'} % ( $fparam->{'size'} || 1 ) ? 1 : 0 ) );
   $fparam->{'buttonsb'} ||= $config{'gotopage_bb'} || 5;    #before
   $fparam->{'buttonsa'} ||= $config{'gotopage_ba'} || 5;    #after
   $fparam->{'align'}   = 1 unless defined $fparam->{'align'};
   $fparam->{'jumpten'} = 1 unless defined $fparam->{'jumpten'};
   $fparam->{'power'}   = 2 unless defined $fparam->{'power'};
   my $fromto = sub {
     my ($n) = @_;
     return (
       ( ( ( $n - 1 ) * $fparam->{'size'} ) + 1 ) . '-'
         . (
         ( $fparam->{'total'} and ( $fparam->{'total'} < $n *  
$fparam->{'size'} ) ) ? $fparam->{'total'} : $n * $fparam->{'size'}
         )
     );
   };
   my $align = sub {
     my $a = int(shift);
     my $len = shift || $fparam->{'align'};
     substr( $a, $len, length($a) - $len ) = '0' x ( length($a) - $len ) if  
$len > 0 and length($a) > $len;
     return $a;
   };
   #printlog('dmp', 'gotopage calc:'," <br\n/>" .Dumper($fparam) .  
"<br\n/>");
   my $next = $fparam->{'actual'} >= $fparam->{'size'};
   if ( ( !$fparam->{'total'} and $fparam->{'actual'} > 0 )
     or $fparam->{'total'} >= $fparam->{'size'}
     or $fparam->{'current'} > 1 )
   {
     $ret{'prev'}{ $fparam->{'current'} - 1 } = $fromto->(  
$fparam->{'current'} - 1 ) if $fparam->{'current'} > 1;
     for my $n ( ( $fparam->{'current'} > $fparam->{'buttonsb'} ?  
$fparam->{'current'} - $fparam->{'buttonsb'} : 2 )
       .. $fparam->{'current'} + ( $next ? $fparam->{'buttonsa'} : 0 ) )
     {
       last if $fparam->{'total'} and $n > $fparam->{'last'};
       last if $fparam->{'total_max'} and $n * $fparam->{'size'} >  
$fparam->{'total_max'};
       ( ( !$fparam->{'total'} and $n > $fparam->{'current'} + 1 ) ? ( \%{  
$ret{'small'} } ) : ( \%{ $ret{'big'} } ) )->{$n} =
         $fromto->($n);
     }
     if ( $fparam->{'jumpten'} ) {
       $fparam->{'jumpfrom'} ||= '1' . ( 0 x ( length( $fparam->{'current'}  
- $fparam->{'buttonsb'} ) - 1 ) );
       $fparam->{'jumpto'} ||= '1' . ( 0 x length( $fparam->{'current'} +  
$fparam->{'buttonsa'} ) );
       $ret{'big'}{$_} = $fromto->($_)
         for grep { !$fparam->{'last'} or $_ <= $fparam->{'last'} }
         map { '1' . ( 0 x $_ ) } 1 .. length( $fparam->{'current'} ) - 1;
       if ($next) {
         $ret{'big'}{$_} = $fromto->($_)
           for map { '1' . ( 0 x $_ ) } length( $fparam->{'current'} ) ..  
length( $fparam->{'last'} ) - 1;
       }
     }
     $fparam->{'jumpfrom'} ||= 1;
     $fparam->{'jumpto'}   ||= $fparam->{'last'};
     #$fparam->{'jumpto'} = psmisc::min( $fparam->{'jumpto'},  
$fparam->{'last'} );
     $fparam->{'jumpto'} = $fparam->{'last'} if $fparam->{'last'} <  
$fparam->{'jumpto'};
     if ( $fparam->{'power'} > 1 ) {
       my ($n);
       $n = $fparam->{'current'} - $fparam->{'buttonsb'} *  
$fparam->{'power'};
       for (
         $_ = $fparam->{'buttonsb'} ;
         $fparam->{'jumpfrom'} >= 1 and $n > $fparam->{'jumpfrom'} and $n <  
$fparam->{'last'} ;
         $n -= ( $_ *= $fparam->{'power'} )
         )
       {
         $ret{'big'}{ $align->($n) } = $fromto->( $align->($n) );
       }
       $n = $fparam->{'current'} + $fparam->{'buttonsa'} *  
$fparam->{'power'};
       for ( $_ = $fparam->{'buttonsa'} ; $next and $n <  
$fparam->{'jumpto'} ; $n += ( $_ *= $fparam->{'power'} ) ) {
         $ret{'big'}{ $align->($n) } = $fromto->( $align->($n) );
       }
     }
     $ret{'big'}{ $fparam->{'last'} } = $fromto->( $fparam->{'last'} ) if  
$fparam->{'last'} > 1 and $next;
     $ret{'big'}{1} ||= $fromto->(1)
       if ( $fparam->{'last'} > 1 or !$fparam->{'total'} )
       and $fparam->{'actual'} >= $fparam->{'size'};
     $ret{'next'}{ $fparam->{'current'} + 1 } = $fromto->(  
$fparam->{'current'} + 1 )
       if $next and !$fparam->{'last'}
         or $fparam->{'current'} < $fparam->{'last'};
   }
   #printlog('dmp', 'gotopage ret:', Dumper(\%ret));
   return wantarray ? ( sort { $a <=> $b } keys %{ $ret{'big'} }, keys %{  
$ret{'small'} } ) : \%ret;
}







>
>
>> 2012/4/23 Alessandro Gorohovski <angel на domashka.kiev.ua>:
>>> Уважаемое сообщество,
>>> Доброго времени суток!
>>>
>>> Подскажите, может есть где готовое решение в виде модуля
>>> (чтобы не изобретать велосипед)
>>> генерации списка страниц, с разбивкой списка страниц на страницы
>>> по типу
>>>
>>> prev · 1 2 3 ... 388 389 390 [391] 392 393 394 ... 398 399 400 · next
>>>
>>>
>>> Спасибо.
>>>
>>> --
>>> ANG
>>> --
>>> Moscow.pm mailing list
>>> moscow-pm на pm.org | http://moscow.pm.org
>>
>>
>>
>


Подробная информация о списке рассылки Moscow-pm