/*
* � Copyright IBM Corp. 2010, 2011
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.xsp.extlib.renderkit.html_extended.data;
import java.io.IOException;
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.component.FacesDataIterator;
import com.ibm.xsp.context.FacesContextEx;
import com.ibm.xsp.event.PagerEvent;
import com.ibm.xsp.extlib.component.data.AbstractPager;
import com.ibm.xsp.extlib.event.ExtlibPagerEvent;
import com.ibm.xsp.extlib.renderkit.html_extended.FacesRendererEx;
import com.ibm.xsp.extlib.util.ExtLibUtil;
import com.ibm.xsp.util.AjaxUtilEx;
import com.ibm.xsp.util.FacesUtil;
import com.ibm.xsp.util.HtmlUtil;
import com.ibm.xsp.util.JavaScriptUtil;
public abstract class AbstractPagerRenderer extends FacesRendererEx {
protected static final int PROP_PAGERTAG = 1;
protected static final int PROP_PAGERSTYLE = 2;
protected static final int PROP_PAGERCLASS = 3;
protected static final int PROP_PAGERROLE = 4;
protected static final int PROP_FORCEID = 5;
@Override
protected Object getProperty(int prop) {
switch(prop) {
case PROP_PAGERTAG: return "span"; // $NON-NLS-1$
case PROP_PAGERROLE: return "navigation"; // $NON-NLS-1$
// these controls don't have a dojoType so id not forced
case PROP_FORCEID: return false;
}
return super.getProperty(prop);
}
@Override
public void decode(FacesContext context, UIComponent component) {
super.decode(context, component);
// check that this component cause the submit
String currentClientId = component.getClientId(context);
String hiddenValue = FacesUtil.getHiddenFieldValue(context);
if(StringUtil.isNotEmpty(hiddenValue) && hiddenValue.startsWith(currentClientId)) {
int pos = hiddenValue.lastIndexOf('_');
if (pos==currentClientId.length()) {
String idSuffix = hiddenValue.substring(pos+1);
try {
ExtlibPagerEvent pagerEvent = new ExtlibPagerEvent(component);
//>tmg:a11y
pagerEvent.setClientId(hiddenValue);
//<tmg:a11y
if(initPagerEvent(context, component, pagerEvent, idSuffix)) {
component.queueEvent(pagerEvent);
}
} catch(Exception ex) {}
}
}
}
protected abstract boolean initPagerEvent(FacesContext context, UIComponent component, PagerEvent pagerEvent, String idSuffix);
@Override
public void encodeBegin(FacesContext context, UIComponent component)
throws IOException {
ResponseWriter w = context.getResponseWriter();
if(!component.isRendered()) {
return;
}
AbstractPager pager = (AbstractPager)component;
FacesDataIterator dataIterator = pager.findDataIterator();
if(dataIterator!=null) {
writeMain(context, w, pager, dataIterator);
}
//>tmg:a11y
String _pagerClientId = (String)HtmlUtil.readEncodeParameter(context, pager, AbstractPager.PAGER_CLIENT_ID, /*remove*/ true);
if(null != _pagerClientId){
StringBuilder js = new StringBuilder();
js.append("XSP.setFocus("); //$NON-NLS-1$
JavaScriptUtil.addString(js, _pagerClientId); // $NON-NLS-1$
js.append(");\n"); //$NON-NLS-1$
JavaScriptUtil.addScriptOnLoad(js.toString());
}
//<tmg:a11y
}
protected void writeMain(FacesContext context, ResponseWriter w, AbstractPager pager, FacesDataIterator dataIterator) throws IOException {
String tag = (String)getProperty(PROP_PAGERTAG);
if(StringUtil.isNotEmpty(tag)) {
w.startElement(tag, null);
boolean shouldWriteId = false;
String componentId = pager.getId();
if( HtmlUtil.isUserId(componentId) ){
// user set an ID in the XPage source
shouldWriteId = true;
}
boolean forceId = (Boolean) getProperty(PROP_FORCEID);
if( forceId ){
// this control needs to write out an ID attribute to the HTML source,
// usually needed when a dojoType attribute is always written.
shouldWriteId = true;
}
if( shouldWriteId ){
String clientId = pager.getClientId(context);
w.writeAttribute("id", clientId, null); // $NON-NLS-1$
}
String role = (String)getProperty(PROP_PAGERROLE);
if(StringUtil.isNotEmpty(role)) {
w.writeAttribute("role", role,null); // $NON-NLS-1$
}
String ariaLabel = pager.getAriaLabel();
if(StringUtil.isNotEmpty(ariaLabel)) {
w.writeAttribute("aria-label", ariaLabel, null); // $NON-NLS-1$
}
String title = pager.getTitle();
if(StringUtil.isNotEmpty(title)) {
w.writeAttribute("title", title, null); // $NON-NLS-1$
}
String style = ExtLibUtil.concatStyles(pager.getStyle(), (String)getProperty(PROP_PAGERSTYLE));
if(StringUtil.isNotEmpty(style)) {
w.writeAttribute("style", style, null); // $NON-NLS-1$
}
String clazz = ExtLibUtil.concatStyleClasses(pager.getStyleClass(),(String)getProperty(PROP_PAGERCLASS));
if(StringUtil.isNotEmpty(clazz)) {
w.writeAttribute("class", clazz,null); // $NON-NLS-1$
}
}
writePagerContent(context, w, pager, dataIterator);
if(StringUtil.isNotEmpty(tag)) {
w.endElement(tag);
}
}
protected abstract void writePagerContent(FacesContext context, ResponseWriter w, AbstractPager pager, FacesDataIterator dataIterator) throws IOException;
protected void setupSubmitOnClick(FacesContext context, ResponseWriter w,
AbstractPager pager, FacesDataIterator dataIterator, String clientId, String sourceId) throws IOException {
boolean immediate = false;
UIComponent subTree = ((FacesContextEx)context).getSubTreeComponent();
boolean partialExec = pager.isPartialExecute();
String execId = null;
if (partialExec) {
execId = pager.getClientId(context);
immediate = true;
} else {
if(subTree!=null) {
partialExec = true;
execId = subTree.getClientId(context);
immediate = true;
}
}
boolean partialRefresh = pager.isPartialRefresh();
String refreshId = null;
if(partialRefresh) {
UIComponent refreshComponent = pager.findSharedDataPagerParent();
if (null == refreshComponent) {
refreshComponent = (UIComponent) pager.findDataIterator();
}
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, sourceId,
sourceId, execId, event,
/* clientSideScriptName */null,
immediate ? JavaScriptUtil.VALIDATION_NONE
: JavaScriptUtil.VALIDATION_FULL,
/* refreshId */refreshId,
/* onstart */getOnStart(pager),
/* oncomplete */getOnComplete(pager),
/* onerror */getOnError(pager));
} else {
JavaScriptUtil.appendAttachEvent(buff, sourceId, 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(AbstractPager component) {
return (String)component.getAttributes().get("onStart"); // $NON-NLS-1$
}
protected String getOnComplete(AbstractPager component) {
return (String)component.getAttributes().get("onComplete"); // $NON-NLS-1$
}
protected String getOnError(AbstractPager component) {
return (String)component.getAttributes().get("onError"); // $NON-NLS-1$
}
}