ページナビゲーション.

ページナビゲーションを実装するにあたっての脳内整理的メモ.Perl っぽい表記になってますので,頭の中で適当に置き換えてください.

$N 個 (インデックスは 0, 1, …, $N-1) のオブジェクト (例えば写真とか) を,$n 個ずつ表示させる場合のページナビゲーションについて考えます.

この場合の全ページ数 $P は

$P = int( $N / $n ) + 1;

となります.

$p ページ目 (1 ≤ $p ≤ $P) におけるページナビゲーションな HTML 文字列を返すサブルーチン pagenavi を次のように定義できます.

# $pagenavi = pagenavi( $N, $n, $p ); な感じで
sub pagenavi {
  my ( $N, $n, $p ) = @_;
  my $html = '';
  my $P = int( $N / $n ) + 1;
  for( my $i = 1; $i < = $P; $i++ ) {
    if( $i == $p ) {
      # 現在のページの処理:リンクを張らないとか,文字を大きくするとか
      $html .= qq{<span class="currentpage">$i</a>};
    }
    else {
      # 他のページの処理:リンクを張るとか
      $html .= qq{<a href="?page=$i">$i</a>};
    }
  }
  return $html;
}

余談ですが,$p ページ目に表示させるべきオブジェクトのうち,最初のインデックス $i0は

$i0 = ( $p - 1 ) * $n;

で得られます.したがって,

for( my $i = $i0; $i < $i0 + $n; $i++ ) {
  my $obj = $objlist[$i];
  ...
}

のようにすることで,オブジェクトリストのうちの該当部分のみを処理することができます.また,SQL でデータベースからデータを取り出す場合には,

SELECT ...
  FROM ...
  WHERE 1
  LIMIT $i0, $n;

などとすればいいでしょう.

さて,先の pagenavi では,オブジェクトの数 $N の増加に伴ってページ数 $P も増加するため,扱いづらいとかスペースを取るとかの不都合が出てきます.

ページ数が増え,いろいろ不都合なページナビゲーション.


そこで,現在のページの周辺のページのみ表示して他は省略する,という方法が考えられます.というか,たいていのサイトはそうなっているかと.

現在のページとその前後 $r ページのみ表示する場合,

$p - $r ≤ $p0 ≤ $p + $r

を満たすような $p0 に対してのみを処理の対象とします.言い換えれば,

$p0 ≤ $p - $r または $p + $r ≤ $p0

を満たす $p0 に対しては処理を行わない,です.(当然ながら,1 ≤ $p0 ≤ $P です.)

この条件を加えると,先のサブルーチン pagenavi は次のように書き換えられます.

# $pagenavi = pagenavi( $N, $n, $p, $r );
sub pagenavi {
  my ( $N, $n, $p, $r ) = @_;
  my $html = '';
  my $P = int( $N / $n ) + 1;
  for( my $i = 1; $i < = $P; $i++ ) {
    if( $i < $p - $r ||  $p + $r < $i ) { next; }
    if( $i == $p ) {
      # 現在のページの処理:リンクを張らないとか,文字を大きくするとか
      $html .= qq{<span class="currentpage">$i</a>};
    }
    else {
      # 他のページの処理:リンクを張るとか
      $html .= qq{<a href="?page=$i">$i</a>};
    }
  }
  return $html;
}

あとは,最初・最後のページへのリンクや相対的な前後ページへのリンク,ページ表示の省略を表す記号なんかを加えていくと,それっぽくなります.

# $pagenavi = pagenavi( $N, $n, $p, $r );
sub pagenavi {
  my ( $N, $n, $p, $r ) = @_;
  my $html = '';
  my $P = int( $N / $n ) + 1;
  # 最初のページへのリンクを張るとか
  $html .= qq{<a href="?page=1">最初</a>};
  if( $p > 1 ) {
    # 前のページへのリンクを張るとか
    $html .= sprintf( qq{<a href="?page=%d">前</a>}, $p - 1 );
  }
  if( $p - $r > 1 ) {
    # 省略記号を付加するとか
    $html .= '...';
  }
  for( my $i = 1; $i < = $P; $i++ ) {
    if( $i < $p - $r ||  $p + $r < $i ) { next; }
    if( $i == $p ) {
      # 現在のページの処理:リンクを張らないとか,文字を大きくするとか
      $html .= qq{<span class="currentpage">$i</a>};
    }
    else {
      # 他のページの処理:リンクを張るとか
      $html .= qq{<a href="?page=$i">$i</a>};
    }
  }
  if( $p + $r < $P ) {
    # 省略記号を付加するとか
    $html .= '...';
  }
  if( $p < $P ) {
    # 次のページへのリンクを張るとか
    $html .= sprintf( qq{<a href="?page=%d">次</a>}, $p + 1 );
  }
  # 最後ページへのリンクを張るとか
  $html .= qq{<a href="?page=$P">最後</a>};
  return $html;
}

本日の一語: 余談

本筋をはずれた話。ほかの話。
よだん 0 【余談】 – goo 辞書

元に戻れる程度に外れましょう.

こちらもあわせてどうぞ

Leave a Reply

直近のつぶやきを読み込みちゅう...