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

Alessandro Gorohovski angel на domashka.kiev.ua
Пн Апр 23 09:26:54 PDT 2012


oleg alexeenkov <proler на gmail.com> писал(а) в своём письме Mon, 23 Apr  
2012 19:11:11 +0300:

> 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;
> }


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