Considéré comme le raison pour laquelle vous avez donné le commentaire à votre question, je vous suggère d'implémenter votre propre moteur de rendu personnalisé pour le pager.
Dans le faces-config.xml
Déclarons ce qui suit:
<render-kit>
<renderer>
<component-family>com.ibm.xsp.Pager
</component-family>
<renderer-type>com.ibm.xsp.XPager
</renderer-type>
<renderer-class>com.irc.xsp.renderer.UIPagerRenderer
</renderer-class>
</renderer>
</render-kit>
Où com.irc.xsp.renderer.UIPagerRenderer
est la classe de rendu. Évidemment, vous pouvez le nommer comme vous voulez. Utilisez simplement le même nom aux deux endroits.
Le moteur de rendu pourrait ressembler à ceci:
package com.irc.xsp.renderer;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import com.ibm.commons.util.StringUtil;
import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.component.UIPager;
import com.ibm.xsp.component.UIPagerControl;
import com.ibm.xsp.component.xp.XspPager;
import com.ibm.xsp.component.xp.XspPagerControl;
import com.ibm.xsp.context.FacesContextEx;
import com.ibm.xsp.event.PagerEvent;
import com.ibm.xsp.extsn.ResourceHandler;
import com.ibm.xsp.renderkit.html_extended.XPagerRenderer;
import com.ibm.xsp.util.AjaxUtilEx;
import com.ibm.xsp.util.FacesUtil;
import com.ibm.xsp.util.JavaScriptUtil;
import com.ibm.xsp.util.TypedUtil;
public class UIPagerRenderer extends XPagerRenderer {
public static final String VAR_PAGE = "page"; //$NON-NLS-1$
private enum Property {
LIST_ITEM_CLASS, PAGER_LINK_CLASS, ACTIVE_CLASS("active"), DISABLED_CLASS("disabled");
String className;
Property() {
}
Property(String s) {
this.className = s;
}
String getClassName() {
return className;
}
}
@Override
public void decode(FacesContext context, UIComponent component) {
super.decode(context, component);
// check that this component cause the submit
if (decodeCausedSubmit(context, component)) {
PagerEvent pagerEvent = new PagerEvent(component);
String hiddenValue = FacesUtil.getHiddenFieldValue(context);
if (StringUtil.isNotEmpty(hiddenValue)) {
int pos = hiddenValue.lastIndexOf('_');
if (pos > -1) {
hiddenValue = hiddenValue.substring(pos + 1);
if (isFirst(hiddenValue)) {
pagerEvent.setAction(PagerEvent.ACTION_FIRST);
} else if (isLast(hiddenValue)) {
pagerEvent.setAction(PagerEvent.ACTION_LAST);
} else if (isNext(hiddenValue)) {
pagerEvent.setAction(PagerEvent.ACTION_NEXT);
} else if (isPrevious(hiddenValue)) {
pagerEvent.setAction(PagerEvent.ACTION_PREVIOUS);
} else {
try {
int value = Integer.parseInt(hiddenValue);
pagerEvent.setAction(PagerEvent.ACTION_GOTOPAGE);
pagerEvent.setPage(value);
} catch (NumberFormatException nfe) {
return; // just don't queue the event
}
}
} else {
return;
}
}
((UIPager) component).queueEvent(pagerEvent);
}
}
private boolean decodeCausedSubmit(FacesContext context, UIComponent component) {
String currentClientId = component.getClientId(context);
String hiddenValue = FacesUtil.getHiddenFieldValue(context);
if (currentClientId != null && hiddenValue != null) {
return StringUtil.indexOfIgnoreCase(hiddenValue, currentClientId) > -1;
}
return false;
}
@Override
public boolean getRendersChildren() {
return true;
}
@Override
public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
if (context == null || component == null) {
throw new IOException();
}
List<?> controls = component.getChildren();
if (controls.isEmpty()) {
return;
}
XspPager pager = (XspPager) component;
UIPager.PagerState pagerState = ((UIPager) component).createPagerState();
if (pagerState == null) {
throw new FacesExceptionEx(ResourceHandler.getString("PagerRenderer.Pagerisnotassociatedwithanydataco"));
}
encodePagerContent(context, context.getResponseWriter(), pager, pagerState, controls, false);
}
protected void encodePagerContent(FacesContext context, ResponseWriter writer, XspPager pager,
UIPager.PagerState pagerState, List<?> controls, boolean rtl) throws IOException {
// Compute the pages that should be displayed
int pageCount = pagerState.getPageCount();
int startCount = getStartCount(pagerState, pageCount);
int endCount = getEndCount(pagerState, pageCount, startCount);
String pagerId = pager.getClientId(context);
String pagerRole = pager.getRole();
String pagerTitle = pager.getTitle();
String pagerOuterClass = pager.getOuterStyleClass();
String pagerAriaLabel = pager.getAriaLabel();
boolean closeOuterTag = false;
if (isAnyAssigned(pagerRole, pagerTitle, pagerOuterClass, pagerAriaLabel)) {
writer.startElement("div", null); // $NON-NLS-1$
writeNonNullAttributeOnly(writer, "role", pagerRole);
writeNonNullAttributeOnly(writer, "title", pagerTitle);
writeNonNullAttributeOnly(writer, "class", pagerOuterClass);
writeNonNullAttributeOnly(writer, "aria-label", pagerAriaLabel);
closeOuterTag = true;
}
writer.startElement("ul", null);
writeNonNullAttributeOnly(writer, "class", pager.getStyleClass());
writeNonNullAttributeOnly(writer, "id", pagerId);
Iterator<?> it = controls.iterator();
while (it.hasNext()) {
Object obj = it.next();
if (obj instanceof XspPagerControl) {
XspPagerControl control = (XspPagerControl) obj;
String type = control.getType();
if (StringUtil.isNotEmpty(type)) {
if (isFirst(type) || isNext(type) || isPrevious(type)
|| (isLast(type) && pager.isAlwaysCalculateLast())) {
encodeAction(context, writer, pager, pagerState, pagerId, control, type, startCount, endCount,
rtl);
continue;
} else if (isLast(type) && !pager.isAlwaysCalculateLast()) {
if (!pagerState.hasMoreRows()) {
encodeAction(context, writer, pager, pagerState, pagerId, control, type, startCount,
endCount, rtl);
} else {
writer.startElement("li", null);
writeNonNullAttributeOnly(writer, "class", com.irc.util.StringUtil.concat(Property.LIST_ITEM_CLASS
.getClassName(), Property.DISABLED_CLASS.getClassName()));
writer.startElement("a", null);
writeNonNullAttributeOnly(writer, "class", Property.PAGER_LINK_CLASS.getClassName());
writer.writeText(getMayBeMorePages(), null);
writer.endElement("a");
writer.endElement("li");
}
continue;
} else if (type.equalsIgnoreCase(UIPagerControl.TYPE_GROUP)) {
encodeGroup(context, writer, pager, pagerState, pagerId, control, startCount, endCount);
continue;
} else if (type.equalsIgnoreCase(UIPagerControl.TYPE_STATUS)) {
encodeStatus(context, writer, pager, pagerState, control, startCount, endCount);
continue;
} else if (isSeparator(type)) {
encodeSeparator(context, writer, control, type);
continue;
} else if (type.equalsIgnoreCase(UIPagerControl.TYPE_GOTO)) {
encodeGoto();
continue;
}
}
// "Unknown control type {0}"
String msg = com.ibm.xsp.extsn.ResourceHandler.getString("PagerRenderer.Unknowncontroltype0"); //$NON-NLS-1$
msg = StringUtil.format(msg, type);
throw new FacesExceptionEx(msg);
}
}
writer.endElement("ul");
if (closeOuterTag) {
writer.endElement("div");
}
}
protected void encodeAction(FacesContext context, ResponseWriter writer, XspPager pager,
UIPager.PagerState pagerState, String pagerId, XspPagerControl control, String type, int startCount,
int endCount, boolean rtl) throws IOException {
String controlId = pagerId + "__" + type;
String defaultText = "";
String ariaLabel = "";
boolean renderLink = true;
//TODO need to handle BIDI here for the unicode symbols
if (isFirst(type)) {
renderLink = pagerState.getCurrentPage() > startCount;
// "\u00AB" FirstSymbol
defaultText = "\u00AB"; //$NON-NLS-1$
// "First page"
ariaLabel = ResourceHandler.getString("PagerRenderer.First"); //$NON-NLS-1$
} else if (isPrevious(type)) {
renderLink = pagerState.getCurrentPage() > startCount;
// "\u2039" PreviousSymbol
defaultText = "\u2039"; //$NON-NLS-1$
// "Previous page"
ariaLabel = ResourceHandler.getString("PagerRenderer.Previous"); //$NON-NLS-1$
} else if (isNext(type)) {
renderLink = pagerState.getCurrentPage() < endCount - 1;
// "\u203A" NextSymbol
defaultText = "\u203A"; //$NON-NLS-1$;
// "Next page"
ariaLabel = ResourceHandler.getString("PagerRenderer.Next"); //$NON-NLS-1$
} else if (isLast(type)) {
renderLink = pagerState.getCurrentPage() < endCount - 1;
// "\u00BB" LastSymbol
defaultText = "\u00BB"; //$NON-NLS-1$
// "Last page"
ariaLabel = ResourceHandler.getString("PagerRenderer.Last"); //$NON-NLS-1$
}
writer.startElement("li", null);
String listItemClass = Property.LIST_ITEM_CLASS.getClassName();
if (!renderLink) {
//If current page is the first, disable first/previous pagers
//and if current page is the last, disable last/next pagers
listItemClass = com.irc.util.StringUtil.concat(listItemClass, Property.DISABLED_CLASS.getClassName());
}
writeNonNullAttributeOnly(writer, "class", listItemClass);
// Generate the image link
String val = (String) control.getValue();
if (StringUtil.isEmpty(val)) {
val = defaultText;
}
// Generate the text link
if (StringUtil.isNotEmpty(val)) {
writer.startElement("a", null); // $NON-NLS-1$
if (renderLink) {
writer.writeAttribute("aria-disabled", "false", null); // $NON-NLS-1$ $NON-NLS-2$
writer.writeAttribute("href", "#", null); // $NON-NLS-1$ $NON-NLS-2$
} else {
//add a11y attributes
writer.writeAttribute("aria-disabled", "true", null); // $NON-NLS-1$ $NON-NLS-2$
}
writeNonNullAttributeOnly(writer, "class", Property.PAGER_LINK_CLASS.getClassName());
writer.writeAttribute("id", controlId + "__lnk", null); // $NON-NLS-1$ $NON-NLS-2$
writer.writeAttribute("role", "button", null); // $NON-NLS-1$ $NON-NLS-2$
writer.writeAttribute("aria-label", ariaLabel, null); // $NON-NLS-1$
writer.writeText(val, null);
writer.endElement("a"); // $NON-NLS-1$
if (renderLink) {
setupSubmitOnClick(context, pager, pagerState, controlId, controlId + "__lnk"); // $NON-NLS-1$
}
}
writer.endElement("li"); // $NON-NLS-1$
}
protected void encodeGroup(FacesContext context, ResponseWriter writer, XspPager pager,
UIPager.PagerState pagerState, String pagerId, XspPagerControl control, int startCount, int endCount)
throws IOException {
// Save the old page value
Map<String, Object> requestMap = TypedUtil.getRequestMap(context.getExternalContext());
Object oldPage = requestMap.get(VAR_PAGE);
String controlId = pagerId + "__" + control.getType();//$NON-NLS-1$
// Encode the pages
for (int i = startCount; i < endCount; i++) {
// Push the page number
requestMap.put(VAR_PAGE, i + 1);
boolean renderLink = (i != pagerState.getCurrentPage());
writer.startElement("li", null); // $NON-NLS-1$
String listItemClass = Property.LIST_ITEM_CLASS.getClassName();
if (!renderLink) {
listItemClass = com.irc.util.StringUtil.concat(listItemClass, Property.ACTIVE_CLASS.getClassName());
}
writeNonNullAttributeOnly(writer, "class", listItemClass);
// Generate the image link
String val = (String) control.getValue();
if (StringUtil.isEmpty(val)) {
val = Integer.toString(i + 1);
}
// Generate the text link
if (StringUtil.isNotEmpty(val)) { // Generate the text link
writer.startElement("a", control); //$NON-NLS-1$
writer.writeAttribute("id", controlId + "__lnk__" + i, null); // $NON-NLS-1$ $NON-NLS-2$
// "Page {0}"
String ariaLabel = ResourceHandler.getString("PagerRenderer.Gotopage0"); //$NON-NLS-1$
ariaLabel = StringUtil.format(ariaLabel, val);
writer.writeAttribute("aria-label", ariaLabel, null); // $NON-NLS-1$
writer.writeAttribute("role", "button", null); // $NON-NLS-1$ $NON-NLS-2$
writeNonNullAttributeOnly(writer, "class", Property.PAGER_LINK_CLASS.getClassName());
if (renderLink) { //make sure the a is tab-able
writer.writeAttribute("tabindex", "0", null); // $NON-NLS-1$ $NON-NLS-2$
writer.writeAttribute("aria-pressed", "false", null); // $NON-NLS-1$ $NON-NLS-2$
} else {
writer.writeAttribute("aria-pressed", "true", null); // $NON-NLS-1$ $NON-NLS-2$
}
writer.writeText(val, null);
writer.endElement("a"); // $NON-NLS-1$
if (renderLink) {
setupSubmitOnClick(context, pager, pagerState, controlId + "__lnk__" + i, controlId + "__lnk__" + i); // $NON-NLS-1$ $NON-NLS-2$
}
}
writer.endElement("li"); // $NON-NLS-1$
}
// Encode after the pages
if (!pager.isAlwaysCalculateLast()) {
if (endCount < pagerState.getLastPage() || pagerState.hasMoreRows()) {
writer.startElement("li", null); // $NON-NLS-1$
writeNonNullAttributeOnly(writer, "class", com.irc.util.StringUtil.concat(Property.LIST_ITEM_CLASS.getClassName(),
Property.DISABLED_CLASS.getClassName()));
writer.startElement("a", control); //$NON-NLS-1$
writeNonNullAttributeOnly(writer, "class", Property.PAGER_LINK_CLASS.getClassName());
writer.writeText(getMayBeMorePages(), null);
writer.endElement("a"); // $NON-NLS-1$
writer.endElement("li"); // $NON-NLS-1$
}
}
// Restore the old page value
if (oldPage != null) {
requestMap.put(VAR_PAGE, oldPage);
} else {
requestMap.remove(VAR_PAGE);
}
}
protected void setupSubmitOnClick(FacesContext context, XspPager component, UIPager.PagerState st, String clientId,
String sourceId) {
boolean immediate = false;
UIComponent subTree = ((FacesContextEx) context).getSubTreeComponent();
boolean partialExec = component.isPartialExecute();
String execId = null;
if (partialExec) {
execId = component.getClientId(context);
immediate = true;
} else {
if (subTree != null) {
partialExec = true;
execId = subTree.getClientId(context);
immediate = true;
}
}
boolean partialRefresh = component.isPartialRefresh();
String refreshId = null;
if (partialRefresh) {
UIComponent refreshComponent = component.findSharedDataPagerParent();
if (null == refreshComponent) {
refreshComponent = (UIComponent) st.getDataIterator();
}
refreshId = AjaxUtilEx.getRefreshId(context, refreshComponent);
} else {
if (subTree != null) {
partialRefresh = true;
refreshId = subTree.getClientId(context);
}
}
// call some JavaScript in xspClient.js
final String event = "onclick"; // $NON-NLS-1$
// Note, the onClick event is also triggered if the user tabs to the
// image\link and presses enter (Not just when clicked with a
// mouse).
// When the source is clicked, put its id in the hidden field and
// submit the form.
StringBuilder buff = new StringBuilder();
if (partialRefresh) {
JavaScriptUtil.appendAttachPartialRefreshEvent(buff, clientId, sourceId, execId, event,
/* clientSideScriptName */null, immediate ? JavaScriptUtil.VALIDATION_NONE
: JavaScriptUtil.VALIDATION_FULL,
/* refreshId */refreshId,
/* onstart */getOnStart(component),
/* oncomplete */getOnComplete(component),
/* onerror */getOnError(component));
} else {
JavaScriptUtil.appendAttachEvent(buff, clientId, sourceId, execId, event,
/* clientSideScriptName */null,
/* submit */true, immediate ? JavaScriptUtil.VALIDATION_NONE : JavaScriptUtil.VALIDATION_FULL);
}
String script = buff.toString();
// Add the script block we just generated.
JavaScriptUtil.addScriptOnLoad(script);
}
protected String getOnStart(XspPager component) {
return (String) component.getAttributes().get("onStart"); // $NON-NLS-1$
}
protected String getOnComplete(XspPager component) {
return (String) component.getAttributes().get("onComplete"); // $NON-NLS-1$
}
protected String getOnError(XspPager component) {
return (String) component.getAttributes().get("onError"); // $NON-NLS-1$
}
protected void encodeStatus(FacesContext context, ResponseWriter writer, XspPager pager,
UIPager.PagerState pagerState, XspPagerControl control, int startCount, int endCount) throws IOException {
writer.startElement("li", null); // $NON-NLS-1$
writeNonNullAttributeOnly(writer, "class", com.irc.util.StringUtil.concat(Property.LIST_ITEM_CLASS.getClassName(),
Property.DISABLED_CLASS.getClassName()));
String val = (String) control.getValue();
if (StringUtil.isEmpty(val)) {
val = "{0}"; // $NON-NLS-1$
}
if (pagerState.getLastPage() > 0) {
writer.startElement("a", null); // $NON-NLS-1$
writeNonNullAttributeOnly(writer, "class", Property.PAGER_LINK_CLASS.getClassName());
writer.writeAttribute("role", "button", null); // $NON-NLS-2$ $NON-NLS-1$
val = StringUtil.format(val, pagerState.getCurrentPage() + 1, pagerState.getLastPage(), startCount,
endCount);
writer.writeText(val, null);
writer.endElement("a"); // $NON-NLS-1$
}
writer.endElement("li"); // $NON-NLS-1$
}
protected void encodeSeparator(FacesContext context, ResponseWriter writer, XspPagerControl control, String type)
throws IOException {
String val = (String) control.getValue();
writer.startElement("li", null); // $NON-NLS-1$
if (StringUtil.isEmpty(val)) {
String defaultSeparator = "|"; // $NON-NLS-1$
if (type.equalsIgnoreCase(UIPagerControl.TYPE_SEPARATORPAGE)) {
// "Page"
defaultSeparator = com.ibm.xsp.extsn.ResourceHandler.getString("PagerRenderer.Page"); //$NON-NLS-1$
}
val = defaultSeparator;
}
writeNonNullAttributeOnly(writer, "class", com.irc.util.StringUtil.concat(Property.LIST_ITEM_CLASS.getClassName(),
Property.DISABLED_CLASS.getClassName()));
// Generate the text link
if (StringUtil.isNotEmpty(val)) {
writer.startElement("a", null); // $NON-NLS-1$
writeNonNullAttributeOnly(writer, "class", Property.PAGER_LINK_CLASS.getClassName());
writer.writeText(val, null);
writer.endElement("a"); // $NON-NLS-1$
}
writer.endElement("li"); // $NON-NLS-1$
}
protected void encodeGoto() {
// Do not exists in core XPages yet..
}
protected int getStartCount(UIPager.PagerState st, int pageCount) {
int start = (st.getFirst()/st.getRows()) - pageCount/2;
start = Math.min(Math.max(0, st.getLastPage() - pageCount), Math.max(0, start));
return start;
}
protected int getEndCount(UIPager.PagerState st, int pageCount, int start) {
int sizeOfPageRange = Math.min(start + pageCount, st.getLastPage()) - start;
int end = start + sizeOfPageRange;
return end;
}
protected boolean isFirst(String type) {
return (type.equalsIgnoreCase(UIPagerControl.TYPE_FIRST)
|| type.equalsIgnoreCase(UIPagerControl.TYPE_FIRSTARROW) || type
.equalsIgnoreCase(UIPagerControl.TYPE_FIRSTIMAGE));
}
protected boolean isNext(String type) {
return (type.equalsIgnoreCase(UIPagerControl.TYPE_NEXT) || type.equalsIgnoreCase(UIPagerControl.TYPE_NEXTARROW) || type
.equalsIgnoreCase(UIPagerControl.TYPE_NEXTIMAGE));
}
protected boolean isLast(String type) {
return (type.equalsIgnoreCase(UIPagerControl.TYPE_LAST) || type.equalsIgnoreCase(UIPagerControl.TYPE_LASTARROW) || type
.equalsIgnoreCase(UIPagerControl.TYPE_LASTIMAGE));
}
protected boolean isPrevious(String type) {
return (type.equalsIgnoreCase(UIPagerControl.TYPE_PREVIOUS)
|| type.equalsIgnoreCase(UIPagerControl.TYPE_PREVIOUSARROW) || type
.equalsIgnoreCase(UIPagerControl.TYPE_PREVIOUSIMAGE));
}
protected boolean isSeparator(String type) {
return (type.equalsIgnoreCase(UIPagerControl.TYPE_SEPARATOR) || type
.equalsIgnoreCase(UIPagerControl.TYPE_SEPARATORPAGE));
}
protected String getMayBeMorePages() {
return "..."; // $NON-NLS-1$
}
private void writeNonNullAttributeOnly(ResponseWriter writer, String attributeName, String attributeValue)
throws IOException {
if (attributeValue != null && !attributeValue.isEmpty()) {
writer.writeAttribute(attributeName, attributeValue, null);
}
}
private boolean isAnyAssigned(String... objs) {
for (String s : objs) {
if (s != null && !s.isEmpty())
return true;
}
return false;
}
}
C'est une classe que je me sers dans mon dernier projet. Fondamentalement, il réimplémente tout ce que le pager fait pour avoir le contrôle de l'aspect et de la convivialité du composant - c'est ce qu'on appelle le rendu. Vous pourriez essayer de le modifier ici et là pour voir comment les différentes choses fonctionnent sur la page. C'est un processus d'apprentissage.
Et la raison pour laquelle vous ne voulez pas utiliser le '' est? –
shillem
Parce que le (comme de nombreux éléments xp:) ne peut pas être adapté pour ressembler à la pagination dans le modèle que j'ai reçu –
Ce n'est pas vrai: vous pouvez utiliser une combinaison d'instructions de thème et de moteurs de rendu personnalisés. – shillem