ボタンの位置と表示には多くのバリエーションがありますが、私は個人的に次の解決策に行きましたが、それは私の意見では最も視覚的で便利です。 5ページと5000の両方に適しています。
HTMLサンプルコード
私は茂みに勝ちません、すぐにhtmlスクリプトによって生成されたコードの例を添付します:
<div class="navigation"> <a href="/playlist/1.html?page=6"></a> <a href="/playlist/1.html">1</a> <i>...</i> <a href="/playlist/1.html?page=4">4</a> <a href="/playlist/1.html?page=5">5</a> <a href="/playlist/1.html?page=6">6</a> <span class="link_active">7</span> <a href="/playlist/1.html?page=8">8</a> <a href="/playlist/1.html?page=9">9</a> <a href="/playlist/1.html?page=10">10</a> <i>...</i> <a href="/playlist/1.html?page=17">17</a> <a href="/playlist/1.html?page=8"></a> </div>
構築ロジック
パラメーターの設定に従って、コードが取り込まれた後、少し後で停止します。次に、数値自体の形成のロジックについて説明します。
「戻る」ボタンと「進む」ボタンを使用すると、すべてオフにできるだけでなく、すべてに明確であると思うので、それらに集中しません。
最初と最後のページ番号、つまり「開始」ボタンと「終了」ボタンが常に表示されます。
中間は、単純なアルゴリズムによってすでに形成されています。 表示しているページが表示され、各ページにNページが表示されます。 この例では、N = 3ページが表示されます。 原則として、すべてがシンプルで明確ですが、端に近づくときは特別なトリックが使用されます。 例で説明します。
ページ1-3 (3 = N)
1 2 3 4 5 6 ... 17最初のN * 2ページと最後のページが表示されます。
4ページ
1 2 3 4 5 6 7 ... 17最初の、さらに形成された行は、4-3 = 1から4 + 3 = 7まで表示されます。 最初のページは予約されているため、2〜7の数字が形成されます。
5ページ
1 2 3 4 5 6 7 8 ... 175-3 = 2から5 + 3 = 8まで。
6ページ
1 2 3 4 5 6 7 8 9 ... 17おそらく、私が見たすべてのナビゲーション(Habrを含む)で、パスはパスで形成されます。 1 ... 3 4 5 6 7 8 9 ... 17
ただし、単一の数字ではなく省略記号を表示することは論理的ではありません。 2番目の省略記号を作成するときに、同様のチェックが実行されます。
7ページ
1 ... 4 5 6 7 8 9 10 ... 17中間はすでに標準です。
終わりの形成は始まりに似ています
12ページ
1 ... 9 10 11 12 13 14 15 16 17
13ページ
1 ... 10 11 12 13 14 15 16 17
14ページ
1 ... 11 12 13 14 15 16 17
15-17ページ
1 ... 12 13 14 15 16 17
リダイレクト
さらに2点強調したい機能に加えて、これはページの存在を確認し、「正しい」アドレスにリダイレクトします。 すなわち たとえば、ハブ上で、最初のページに2mのアドレスですぐにアクセスできます。
habrahabr.ru/sandbox/page1
habrahabr.ru/sandbox
スクリプトは、ページ/ 1 /へのアクセスを許可せず、「クリーンな」アドレスにリダイレクトします
また、ページ番号が大きすぎる場合、最後の既存のページ番号へのリダイレクトが実行されます。 たとえば、資料が削除されたり、ページあたりのエントリ数が変更されたりしました。 CEOの観点から有用であるかどうかは確かに言えませんが、ユーザーにとってはより便利だと思われます。
PHPコードとその使用
PHPコード
class PaginateNavigationBuilder { /** * URL * , {page} * : * /some_url{page}.html * : * /some_url.html * /some_url/page_2.html * {page} , * * @var string */ private $baseUrl = '/'; /** * * * @var string */ public $tpl = 'page/{page}/'; /** * * * @var string */ public $wrap = "<div class=\"navigation\">{pages}</div>"; /** * * : * $spread = 2 * 9 5 * 1 ... 3 4 5 6 7 ... 9 * * @var integer */ public $spread = 5; /** * * * @var string */ public $separator = "<i>...</i>"; /** * * * @var string */ public $activeClass = 'link_active'; /** * * * @var integer */ private $currentPage = 0; /** * "" "" * * @var bool */ public $nextPrev = true; /** * "" * * @var string */ public $prevTitle = ''; /** * "" * * @var string */ public $nextTitle = ''; /** * * * @param string $baseUrl URL */ public function __construct($baseUrl = '/') { $this->baseUrl = $baseUrl; } /** * * * @param integer $limit 1 * @param integer $count_all * @param integer $currentPage * @return mixed */ public function build($limit, $count_all, $currentPage = 1) { if( $limit < 1 OR $count_all <= $limit ) return; $count_pages = ceil( $count_all / $limit ); if( $currentPage > $count_pages ) { header( "HTTP/1.0 301 Moved Permanently" ); header( "Location: " . $this->getUrl( $count_pages ) ); die( "Redirect" ); } if( $currentPage == 1 AND $_SERVER['REQUEST_URI'] != $this->getUrl( $currentPage ) ) { header( "HTTP/1.0 301 Moved Permanently" ); header( "Location: " . $this->getUrl( $currentPage ) ); die( "Redirect" ); } $this->currentPage = intval( $currentPage ); if( $this->currentPage < 1 ) $this->currentPage = 1; $shift_start = max( $this->currentPage - $this->spread, 2 ); $shift_end = min( $this->currentPage + $this->spread, $count_pages-1 ); if( $shift_end < $this->spread*2 ) { $shift_end = min( $this->spread*2, $count_pages-1 ); } if( $shift_end == $count_pages - 1 AND $shift_start > 3 ) { $shift_start = max( 3, min( $count_pages - $this->spread*2 + 1, $shift_start ) ); } $list = $this->getItem( 1 ); if ($shift_start == 3) { $list .= $this->getItem( 2 ); } elseif ( $shift_start > 3 ) { $list .= $this->separator; } for( $i = $shift_start; $i <= $shift_end; $i++ ) { $list .= $this->getItem( $i ); } $last_page = $count_pages - 1; if( $shift_end == $last_page-1 ){ $list .= $this->getItem( $last_page ); } elseif( $shift_end < $last_page ) { $list .= $this->separator; } $list .= $this->getItem( $count_pages ); if( $this->nextPrev ) { $list = $this->getItem( $this->currentPage > 1 ? $this->currentPage - 1 : 1, $this->prevTitle, true ) . $list . $this->getItem( $this->currentPage < $count_pages ? $this->currentPage + 1 : $count_pages, $this->nextTitle, true ); } return str_replace( "{pages}", $list, $this->wrap ); } /** * * @param int $page_num * @return string */ private function getUrl( $page_num = 0 ) { $page = $page_num > 1 ? str_replace( '{page}', $page_num, $this->tpl ) : ''; if( stripos( $this->baseUrl, '{page}' ) !== false ){ return str_replace( '{page}', $page, $this->baseUrl ); } else { return $this->baseUrl . $page; } } /** * / * @param int $page_num * @param string $page_name , * @param bool $noclass * @return - span . */ private function getItem( $page_num, $page_name = '', $noclass = false ) { $page_name = $page_name ?: $page_num; $className = $noclass ? '' : $this->activeClass; if( $this->currentPage == $page_num ) { return "<span class=\"{$className}\">{$page_name}</span>"; } else { return "<a href=\"{$this->getUrl($page_num)}\">{$page_name}</a>"; } } }
わかりやすくするために、サンドボックスナビゲーションの構築例を示します。
habrahabr.ru/sandbox/page12
$navi = new PaginateNavigationBuilder( "/sandbox/" ); $navi->tpl = "page{page}/"; $navi->spread = 4; $template = $navi->build( $limit, $count_all, $page_num );
または、ページ番号がURL内に記述されている場合:
example.com/some_url/1.html-最初のページ
example.com/some_url/1-page2.html-2ページ目
$navi = new PaginateNavigationBuilder( "/some_url/1{page}.html" ); $navi->tpl = "-page{page}"; $template = $navi->build( $limit, $count_all, $page_num );
どこで
$ limit-ページあたりのエントリ数
$ count_all-エントリの総数
$ page_num-ユーザーがいるページ番号
おそらくそれだけです。 私は建設的な批判に喜んでいるでしょう。
PS。 すべての非購読者、特にscる(そして正しいことをする)人に感謝します。
すべてを熟知し、考慮し、改善することを約束します。