PowerCMS Xでは、新着情報一覧ページなど静的に生成されたオブジェクトの一覧ページに所定のパラメータを付与することで、動的ページネーションを実装できます。動的ページネーションの基本的な仕組みについてはPowerCMS Xドキュメント(ページネーション)を読むと良いでしょう。
今回は分割するページ数が多くページネーションの一部を…と省略表示したい場合の実装例を紹介します。
事前準備
動的ページネーションを動作させるためには、パラメータ付きリクエストをダイナミック・パブリッシングの対象にする必要があります。PowerCMS Xドキュメント(ページネーション)を参考に設定してください。
インクルード・モジュール「ページネーション」を作成
ビューに以下のインクルード・モジュールを作成します。コメントで簡単に説明を入れていますので、変数及びページネーションのHTMLは適宜調整してください。
<mt:Var name="pagination_max_pages" value="3" note="ページネーションに表示する最大ページ数。奇数指定を推奨" />
<mt:Math eq="floor(x / 2)" x="$pagination_max_pages" setvar="pagination_half_number" />
<mt:Math eq="ceil(x / y)" x="$object_count" y="$pagination_limit" setvar="pagination_total_pages" />
<mt:SetVarBlock name="is_omit"><mt:If name="pagination_total_pages" gt="$pagination_max_pages">1</mt:If></mt:SetVarBlock>
<mt:SetVarTemplate name="create_pager_link" note="ページネーションのリンク生成">
<mt:Var name="current_archive_url" />?limit=<mt:Var name="pagination_limit" />
<mt:If name="pager_offset">&offset=<mt:Var name="pager_offset" /></mt:If>
&_filter=<mt:Var name="pagination_filter_model" />
</mt:SetVarTemplate>
<mt:Var name="regex_pattern" value="/[\r|\n|\t|\s| | ]/g" note="create_pager_linkの不要な改行とスペース置換" />
<mt:If name="is_omit" note="pagination_max_pagesよりページが多ければ省略表示">
<mt:Var name="current_page" decrement="$pagination_half_number" setvar="pagination_start_page" />
<mt:Var name="current_page" increment="$pagination_half_number" setvar="pagination_end_page" />
<mt:If name="pagination_start_page" lt="1">
<mt:Var name="pagination_start_page" value="1" />
<mt:Var name="pagination_end_page" value="$pagination_max_pages" />
<mt:ElseIf name="pagination_end_page" gt="$pagination_total_pages">
<mt:Math eq="x - (y - 1)" x="$pagination_total_pages" y="$pagination_max_pages" setvar="pagination_start_page" />
<mt:Var name="pagination_end_page" value="$pagination_total_pages" />
</mt:If>
<mt:Else note="pagination_max_pagesよりページが少なければ全て表示">
<mt:Var name="pagination_start_page" value="1" />
<mt:Var name="pagination_end_page" value="$pagination_max_pages" />
<mt:If name="pagination_total_pages" lt="$pagination_max_pages">
<mt:Var name="pagination_end_page" value="$pagination_total_pages" />
</mt:If>
</mt:If>
<mt:If name="pagination_total_pages" gt="1" note="2ページ以上あればページネーションを生成">
<mt:For from="$pagination_start_page" to="$pagination_end_page" step="1">
<mt:If name="__first__">
<div class="pagination">
<mt:SetVarBlock name="has_prev"><mt:If name="current_page" gt="1">1</mt:If></mt:SetVarBlock>
<mt:If name="has_prev" note="現在のページが2ページ目以降なら前ページへのリンクを生成">
<div class="pagination__prev">
<mt:SetVarBlock name="pager_offset"><mt:If name="prev_offset"><mt:Var name="prev_offset" /></mt:If></mt:SetVarBlock>
<a href="<mt:Var name="create_pager_link" regex_replace="'$regex_pattern',''" />">前へ</a>
</div><!-- /.pagination__prev -->
</mt:If>
<div class="pagination__page">
<mt:If name="is_omit" note="省略表示する場合">
<mt:If name="__value__" ne="1" note="最初のページへのリンクがない場合、リンクを生成">
<mt:Var name="pager_offset" value="" />
<a href="<mt:Var name="create_pager_link" regex_replace="'$regex_pattern',''" />"<mt:If name="__value__" eq="$current_page"> class="-is-current"</mt:If>>1</a>
<mt:If name="__value__" gt="2" note="pagination_start_pageが3以上なら...を挿入">
<span class="pagination__omission">...</span>
</mt:If>
</mt:If>
</mt:If>
</mt:If>
<mt:SetVarBlock name="pager_offset"><mt:Math eq="(x - 1) * y" x="$__value__" y="$pagination_limit" /></mt:SetVarBlock>
<a href="<mt:Var name="create_pager_link" regex_replace="'$regex_pattern',''" />"<mt:If name="__value__" eq="$current_page"> class="-is-current"</mt:If>><mt:Var name="__value__" /></a>
<mt:If name="__last__">
<mt:If name="is_omit" note="省略表示する場合">
<mt:If name="__value__" ne="$pagination_total_pages" note="最後のページへのリンクがない場合、リンクを生成">
<mt:SetVarBlock name="end_prev_page"><mt:Var name="pagination_total_pages" decrement="1" /></mt:SetVarBlock>
<mt:If name="__value__" ne="$end_prev_page" note="pagination_end_pageが最後のページより2以上小さければ...を挿入">
<span class="pagination__omission">...</span>
</mt:If>
<mt:SetVarBlock name="pager_offset"><mt:Math eq="(x - 1) * y" x="$pagination_total_pages" y="$pagination_limit" /></mt:SetVarBlock>
<a href="<mt:Var name="create_pager_link" regex_replace="'$regex_pattern',''" />"<mt:If name="__value__" eq="$current_page"> class="-is-current"</mt:If>><mt:Var name="pagination_total_pages" /></a>
</mt:If>
</mt:If>
</div><!-- /.pagination__page -->
<mt:SetVarBlock name="has_next"><mt:If name="current_page" lt="$pagination_total_pages">1</mt:If></mt:SetVarBlock>
<mt:If name="has_next" note="現在のページが最後のページ以外なら次ページへのリンクを生成">
<div class="pagination__next">
<mt:SetVarBlock name="pager_offset"><mt:If name="next_offset"><mt:Var name="next_offset" /><mt:Else><mt:Var name="pagination_limit" /></mt:If></mt:SetVarBlock>
<a href="<mt:Var name="create_pager_link" regex_replace="'$regex_pattern',''" />">次へ</a>
</div><!-- /.pagination__next -->
</mt:If>
</div><!-- / .pagination -->
</mt:If>
</mt:For>
</mt:If>
モデル「ページ」一覧のページネーションの例
この例では、PowerCMS Xドキュメント(ページネーション)同様に1ページ目については静的生成、2ページ目以降は動的生成を想定していますが、1ページ目が動的生成でも動作します。
<mt:Var name="pagination_limit" value="10" note="ページ送り件数" />
<mt:Var name="pagination_filter_model" value="page" note="オブジェクト一覧の対象モデル" />
<mt:Pages sort_by="published_on" sort_order="ascend" limit="$pagination_limit">
<mt:If name="__first__">
<ul>
</mt:If>
// 中略
<mt:If name="__last__">
</ul>
<mt:Include module="ページネーション">
</mt:If>
</mt:Pages>
まとめ
PowerCMS Xでは柔軟にページネーションを実装できます。公開サーバーでダイナミック・パブリッシングが利用できない場合、今回ご紹介した方法では実現できませんので、静的ページ分割を実現する有償プラグイン(SplitPage)の導入を検討すると良いでしょう。