/*
* � Copyright IBM Corp. 2010, 2013
*
* 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.picker;
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.commons.util.io.json.JsonJavaObject;
import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.component.UIInputEx;
import com.ibm.xsp.component.UIViewRootEx;
import com.ibm.xsp.extlib.component.picker.AbstractPicker;
import com.ibm.xsp.extlib.component.picker.data.IPickerData;
import com.ibm.xsp.extlib.controls.ExtlibControlsLogger;
import com.ibm.xsp.extlib.renderkit.dojo.DojoRendererUtil;
import com.ibm.xsp.extlib.resources.ExtLibResources;
import com.ibm.xsp.renderkit.FacesRenderer;
import com.ibm.xsp.renderkit.html_basic.HtmlRendererUtil;
import com.ibm.xsp.util.FacesUtil;
import com.ibm.xsp.util.JSUtil;
/**
* Abstract Picker renderer.
*/
public abstract class AbstractPickerRenderer extends FacesRenderer {
@Override
public void decode(FacesContext context, UIComponent component) {
// Nothing to decode here...
}
@Override
public boolean getRendersChildren() {
return true;
}
@Override
public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
}
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
}
@Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
ResponseWriter w = context.getResponseWriter();
AbstractPicker picker = (AbstractPicker)component;
IPickerData data = picker.getDataProvider();
String dojoType = picker.getDojoType();
if(StringUtil.isEmpty(dojoType)) {
dojoType = getDefaultDojoType(); //"extlib.dijit.ValuePickerList";
}
dojoType = encodeDojoType(dojoType);
// Encode the necessary resources
UIViewRootEx rootEx = (UIViewRootEx) context.getViewRoot();
rootEx.setDojoTheme(true);
rootEx.setDojoParseOnLoad(true);
ExtLibResources.addEncodeResource(rootEx, ExtLibResources.extlibPicker);
encodeExtraResources(context, picker, data, rootEx, dojoType);
writeLink(context, w, picker, data, dojoType);
}
protected void writeLink(FacesContext context, ResponseWriter w, AbstractPicker picker, IPickerData data, String dojoType) throws IOException {
UIComponent _for = getFor(context,picker);
boolean readOnly = _for!=null ? FacesUtil.isComponentReadOnly(context, _for) : false;
if(!readOnly) {
Boolean _disabled_ = _for!=null ? (Boolean)_for.getAttributes().get("disabled") : null; // $NON-NLS-1$
boolean disabled = _disabled_!=null ? _disabled_:false; // $NON-NLS-1$
if(disabled) {
w.startElement("span", null); // $NON-NLS-1$
} else {
w.startElement("a", null);
w.writeAttribute("class", "xspPickerLink", null); // $NON-NLS-1$ $NON-NLS-2$
w.writeAttribute("href", "javascript:;", null); // $NON-NLS-1$ $NON-NLS-2$
if(data!=null) {
//PHAN8YWEJZ fix IE namepicker beforeunload event occurring
StringBuilder onclick = new StringBuilder();
onclick.append("return XSP.selectValue("); // $NON-NLS-1$
JSUtil.addSingleQuoteString(onclick, dojoType);
onclick.append(","); // $NON-NLS-1$
onclick.append(createParametersAsJson(context, picker, _for, data, dojoType));
onclick.append(")"); // $NON-NLS-1$
w.writeAttribute("onclick", onclick.toString(), null); // $NON-NLS-1$
StringBuilder onkeydown = new StringBuilder();
onkeydown.append("javascript:var kc=event.keyCode?event.keyCode:event.which;if(kc==32){ return XSP.selectValue("); // $NON-NLS-1$
JSUtil.addSingleQuoteString(onkeydown, dojoType);
onkeydown.append(","); // $NON-NLS-1$
// TODO this onkeydown="javascript: something" contains JSON with double-quotes, breaking the XML attribute
onkeydown.append(createParametersAsJson(context, picker, _for,data, dojoType));
onkeydown.append(")}"); // $NON-NLS-1$
w.writeAttribute("onkeydown", onkeydown.toString(), null); // $NON-NLS-1$ $NON-NLS-2$
}
//LHEY97QME8 adding the role= button
w.writeAttribute("role", "button", null); // $NON-NLS-1$ $NON-NLS-2$
}
// Get the text/icon
String text = picker.getPickerText();
String icon = picker.getPickerIcon();
boolean custom = StringUtil.isNotEmpty(text) || StringUtil.isNotEmpty(icon);
if(!custom) {
icon = getImageLink();
}
if(StringUtil.isNotEmpty(icon)) {
w.startElement("img", null); // $NON-NLS-1$
w.writeAttribute("src", HtmlRendererUtil.getImageURL(context,icon), null); // $NON-NLS-1$
String iconAlt = "Open Picker"; // $NLS-AbstractPickerRenderer.OpenPicker-1$
w.writeAttribute("alt", iconAlt, null); // $NON-NLS-1$
w.endElement("img"); // $NON-NLS-1$
}
if(StringUtil.isNotEmpty(text)) {
w.writeText(text, null);
}
if(disabled) {
w.endElement("span"); // $NON-NLS-1$
} else {
w.endElement("a");
}
}
}
protected UIComponent getFor(FacesContext context, AbstractPicker picker) {
// Associated control
String control = picker.getFor();
if(StringUtil.isNotEmpty(control)) {
UIComponent c = FacesUtil.getComponentFor(picker, control);
return c;
}
return null;
}
protected abstract String getDefaultDojoType();
protected abstract String getDialogTitleSingleSelect();
protected abstract String getDialogTitleMultipleSelect();
protected abstract String getImageLink();
protected String encodeDojoType(String dojoType) {
return dojoType;
}
protected void encodeExtraResources(FacesContext context, AbstractPicker picker, IPickerData data, UIViewRootEx rootEx, String dojoType) {
// if the grid is to be used, load the grid CSS
if(StringUtil.equals(dojoType, "extlib.dijit.ValuePickerGrid")) { // $NON-NLS-1$
ExtLibResources.addEncodeResources(rootEx, ExtLibResources.GRID_EXTRA_RESOURCES);
}
}
protected String createParametersAsJson(FacesContext context, AbstractPicker picker, UIComponent _for, IPickerData data, String dojoType) {
try {
JsonJavaObject json = new JsonJavaObject();
DojoRendererUtil.getDojoAttributeMap(picker,json);
initDojoAttributes(context, picker, _for, data, dojoType, json);
// And generate them
return DojoRendererUtil.getDojoAttributesAsJson(context,picker,json);
} catch(Exception e) {
throw new FacesExceptionEx(e);
}
}
protected void initDojoAttributes(FacesContext context, AbstractPicker picker, UIComponent _for, IPickerData data, String dojoType, JsonJavaObject json) throws IOException {
// Associated control
boolean allowMultiple = false;
if(_for!=null) {
json.putString("control",_for.getClientId(context)); // $NON-NLS-1$
if(_for instanceof UIInputEx) {
UIInputEx iex = (UIInputEx)_for;
// Check for a multiple separator
String ch = iex.getMultipleSeparator();
if(StringUtil.isNotEmpty(ch)) {
boolean trim = iex.isMultipleTrim();
json.putString("msep",ch); // $NON-NLS-1$
//Defect 198787 - a11y fix to set aria-multiselectable property
json.putBoolean("allowMultiple",true); // $NON-NLS-1$
json.putBoolean("trim",trim); // $NON-NLS-1$
allowMultiple = true;
}
}
}
// Dialog title
String title = picker.getDialogTitle();
if(StringUtil.isEmpty(title)) {
if( allowMultiple ){
title = getDialogTitleMultipleSelect();
}else{
title = getDialogTitleSingleSelect();
}
}
json.putString("dlgTitle",title); // $NON-NLS-1$
// Dialog sizes
String lw = picker.getListWidth();
if(StringUtil.isNotEmpty(lw)) {
json.putString("listWidth",lw); // $NON-NLS-1$
}
String lh = picker.getListHeight();
if(StringUtil.isNotEmpty(lh)) {
json.putString("listHeight",lh); // $NON-NLS-1$
}
// The rest service URL
String url = picker.getUrl(context, null);
json.putString("url",url); // $NON-NLS-1$
// Generate the source list, if applicable
boolean hasMultipleSource = data.hasCapability(IPickerData.CAPABILITY_MULTIPLESOURCES);
if(hasMultipleSource) {
String[] labels = data.getSourceLabels();
if(labels!=null && labels.length>=2) {
json.putObject("sources",labels); // $NON-NLS-1$
}
}
}
}