StatelessPage 上で、PageNavigator が必要になり、
Stateless な PageNavigator が必要になって、作ってみたので、結果を記載します。
参考サイト
-
SEO - Search Engine Optimization - Apache Wicket - Apache Software Foundation
検索エンジン最適化についてのページ。jessionid
を除去する方法、sitemap.xml
の作成する方法等とともに、
Stateless な PageNavigator の作成方法についての記載があります。 -
Wicket で Bookmarkable な PagingNavigator - より良い環境を求めて
Bookmarkable な PagingNavigator へのリンクがあります。 -
household/StatelessPagingNavigator.java at master · asvanberg/household
ずばりそのものなStatelessPagingNavigator.java
です。
こちらの実装を参考に、Bootstrap の css を適用するために修正しました。 -
Pagination · Bootstrap
Bootstrap の Pagination の説明ページです。
StatelessPagingNavigator.html
Navigator の HTML は以下の通り実装しました。
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:panel>
<nav aria-label="Page navigation" class="text-center">
<ul class="pagination">
<li class="page-item" wicket:id="firstWrap"><a wicket:id="first" class="page-link first"><<</a></li>
<li class="page-item" wicket:id="prevWrap"><a wicket:id="prev" rel="prev" class="page-link prev"><</a>
</li>
<li class="page-item" wicket:id="navigation">
<a class="page-link" wicket:id="pageLink" href="#">
<span wicket:id="pageNumber">5</span>
</a>
</li>
<li class="page-item" wicket:id="nextWrap"><a wicket:id="next" rel="next" class="page-link next">></a>
</li>
<li class="page-item" wicket:id="lastWrap"><a wicket:id="last" class="page-link last">>></a></li>
</ul>
</nav>
</wicket:panel>
</body>
</html>
StatelessPagingNavigator.java
以下の通り、StatelessPagingNavigator.java
を作成しました。
PagingNavigator
で保持している markup 部を変更する必要があったため、
Panel
を直接継承するようにして、実装しました。
PagingNavigator
と元々の StatelessPagingNavigator.java
を
マージしたような状態になっています。
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.LoopItem;
import org.apache.wicket.markup.html.navigation.paging.IPageable;
import org.apache.wicket.markup.html.navigation.paging.IPagingLabelProvider;
import org.apache.wicket.markup.html.navigation.paging.PagingNavigation;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.collections.MicroMap;
/**
* StatelessPagingNavigator
*/
public class StatelessPagingNavigator extends Panel {
private static final long serialVersionUID = 8219151328688000388L;
public static final String PAGING_PAGE_PARAMETER = "page";
private final IPageable pageable;
private final IPagingLabelProvider labelProvider;
private PageParameters parameters;
private PagingNavigation pagingNavigation;
/**
* Construct.
* @param id
* @param parameters
* @param pageable
*/
public StatelessPagingNavigator(String id, PageParameters parameters, IPageable pageable) {
this(id, pageable);
this.parameters = new PageParameters(parameters);
pageable.setCurrentPage(this.parameters.get(PAGING_PAGE_PARAMETER).toLong(0));
}
/**
* Construct.
* @param id
* @param pageable
*/
public StatelessPagingNavigator(String id, IPageable pageable) {
this(id, pageable, (IPagingLabelProvider) null);
}
/**
* Construct.
*
* @param id
* @param pageable
* @param labelProvider
*/
public StatelessPagingNavigator(String id, IPageable pageable, IPagingLabelProvider labelProvider) {
super(id);
this.pageable = pageable;
this.labelProvider = labelProvider;
setRenderBodyOnly(true);
}
protected AbstractLink newPagingNavigationIncrementLink(String id, IPageable pageable, int increment) {
long pageNumber = pageable.getCurrentPage() + increment;
return newPageLink(id, pageNumber);
}
protected AbstractLink newPagingNavigationLink(String id, IPageable pageable, int pageNumber) {
// The base PagingNavigator uses -1 to refer to the last page
if (pageNumber < 0) {
pageNumber += pageable.getPageCount();
}
return newPageLink(id, pageNumber);
}
protected PagingNavigation newNavigation(final String id, final IPageable pageable, final IPagingLabelProvider labelProvider) {
return new PagingNavigation(id, pageable, labelProvider) {
@Override
protected AbstractLink newPagingNavigationLink(String id, IPageable pageable, long pageNumber) {
return newPageLink(id, pageNumber);
}
protected void populateItem(LoopItem loopItem) {
long pageIndex = this.getStartIndex() + (long) loopItem.getIndex();
AbstractLink link = this.newPagingNavigationLink("pageLink", this.pageable, pageIndex);
link.add(new Behavior[]{new PagingNavigationTitleAppender(pageIndex, this)});
loopItem.add(new Component[]{link});
String label = "";
if (this.labelProvider != null) {
label = this.labelProvider.getPageLabel(pageIndex);
} else {
label = String.valueOf(pageIndex + 1L).intern();
}
Component components = new Label("pageNumber", label);
link.add(components);
// ---------------------------------------
// 現在表示しているページには、class activeを付与する
// --------------
if (pageable.getCurrentPage() == pageIndex) {
loopItem.add(AttributeModifier.append("class", "active"));
}
}
};
}
@Override
protected boolean getStatelessHint() {
return true;
}
private AbstractLink newPageLink(String id, long pageNumber) {
PageParameters withPaging = new PageParameters(parameters);
withPaging.set(PAGING_PAGE_PARAMETER, pageNumber);
return new BookmarkablePageLink<>(id, getPage().getPageClass(), withPaging);
}
public final IPageable getPageable() {
return this.pageable;
}
protected void onInitialize() {
super.onInitialize();
this.pagingNavigation = this.newNavigation("navigation", this.pageable, this.labelProvider);
this.add(new Component[]{this.pagingNavigation});
MarkupContainer firstWrap = new WebMarkupContainer("firstWrap");
firstWrap.add(new Component[]{this.newPagingNavigationLink("first", this.pageable, 0).add(new Behavior[]{new PagingNavigatorTitleAppender("PagingNavigator.first")})});
// 1ページ目を選択時は、非活性化する
if (getPageable().getCurrentPage() == 0) {
firstWrap.add(AttributeModifier.append("class", "disabled"));
firstWrap.setEnabled(false);
}
this.add(firstWrap);
MarkupContainer prevWrap = new WebMarkupContainer("prevWrap");
prevWrap.add(new Component[]{this.newPagingNavigationIncrementLink("prev", this.pageable, -1).add(new Behavior[]{new PagingNavigatorTitleAppender("PagingNavigator.previous")})});
// 1ページ目を選択時は、非活性化する
if (getPageable().getCurrentPage() == 0) {
prevWrap.add(AttributeModifier.append("class", "disabled"));
prevWrap.setEnabled(false);
}
this.add(prevWrap);
MarkupContainer nextWrap = new WebMarkupContainer("nextWrap");
nextWrap.add(new Component[]{this.newPagingNavigationIncrementLink("next", this.pageable, 1).add(new Behavior[]{new PagingNavigatorTitleAppender("PagingNavigator.next")})});
// 最終ページを選択時は、非活性化する
if (getPageable().getPageCount() - 1 == getPageable().getCurrentPage()) {
nextWrap.add(AttributeModifier.append("class", "disabled"));
nextWrap.setEnabled(false);
}
this.add(nextWrap);
MarkupContainer lastWrap = new WebMarkupContainer("lastWrap");
lastWrap.add(new Component[]{this.newPagingNavigationLink("last", this.pageable, -1).add(new Behavior[]{new PagingNavigatorTitleAppender("PagingNavigator.last")})});
// 最終ページを選択時は、非活性化する
if (getPageable().getPageCount() - 1 == getPageable().getCurrentPage()) {
lastWrap.add(AttributeModifier.append("class", "disabled"));
lastWrap.setEnabled(false);
}
this.add(lastWrap);
}
public final PagingNavigation getPagingNavigation() {
return this.pagingNavigation;
}
// PagingNavigatorTitleAppender
private final class PagingNavigatorTitleAppender extends Behavior {
private static final long serialVersionUID = 1L;
private final String resourceKey;
public PagingNavigatorTitleAppender(String resourceKey) {
this.resourceKey = resourceKey;
}
public void onComponentTag(Component component, ComponentTag tag) {
tag.put("title", StatelessPagingNavigator.this.getString(this.resourceKey));
}
}
// PagingNavigationTitleAppender
private final class PagingNavigationTitleAppender extends Behavior {
private static final long serialVersionUID = 1L;
private static final String RES = "PagingNavigation.page";
private PagingNavigation pagingNavigation;
private final long page;
public PagingNavigationTitleAppender(long page, PagingNavigation pagingNavigation) {
this.page = page;
this.pagingNavigation = pagingNavigation;
}
public void onComponentTag(Component component, ComponentTag tag) {
String pageIndex = String.valueOf(this.page + 1L).intern();
MicroMap vars = new MicroMap("page", pageIndex);
tag.put("title", this.pagingNavigation.getString(RES, Model.ofMap(vars)));
}
}
}
-
説明1
if (getPageable().getCurrentPage() == 0)
で 1ページ目かどうか判定できます。 -
説明2
if (getPageable().getPageCount() - 1 == getPageable().getCurrentPage())
で 最終ページかどうか判定できます。 -
説明3
StatelessPagingNavigator#newNavigation()
で生成するPagingNavigation
のpopulateItem
メソッドで、
if (pageable.getCurrentPage() == pageIndex)
で 現在表示ページがどれかを判断できます。
HTML
上以下の部分に該当する処理になります。
<li class="page-item" wicket:id="navigation">
<a class="page-link" wicket:id="pageLink" href="#">
<span wicket:id="pageNumber">5</span>
</a>
</li>
StatelessPagingNavigator.java の使用箇所
使用箇所は、以下のような実装になります。
- Java
// Add FestivalListView
PageableListView<Festival> festivals = newFestivalListView(parameters.get(PAGING_PAGE_PARAMETER).toLong(0));
add(new StatelessPagingNavigator("navigator", parameters, festivals));
add(festivals);
- HTML
<!-- StatelessPagingNavigator の Markup -->
<div class="col-md-12">
<div wicket:id="navigator"></div>
</div>
<!-- ListView の Markup -->
<div class="col-md-12">
<div class="isotope-container row">
<div class="col-sm-6 col-md-3 isotope-item" wicket:id="festivals">
<div class="image-box">
<div class="overlay-container">
<img class="fit" wicket:id="festvalImage" alt="Festibal image"
style="width:100%; height:auto;">
<a class="overlay">
<i class="fa fa-search-plus"></i>
<span wicket:id="siteUrl">Festival URL</span>
</a>
</div>
<a class="btn btn-default btn-block" wicket:id="festivalLink">
<span wicket:id="festivalName">Festival Name</span>
</a>
</div>
</div>
</div>
</div>
- 画面表示
使用箇所は以下のように表示されます。
以上です。
コメント