com.icesoft.faces.component.selectinputtext.SelectInputTextRenderer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icefaces-compat Show documentation
Show all versions of icefaces-compat Show documentation
${icefaces.product.name} Compat Component Library
The newest version!
/*
* Copyright 2004-2013 ICEsoft Technologies Canada Corp.
*
* 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.icesoft.faces.component.selectinputtext;
import com.icesoft.faces.component.ext.KeyEvent;
import com.icesoft.faces.context.DOMContext;
import com.icesoft.faces.context.effects.JavascriptContext;
import com.icesoft.faces.renderkit.dom_html_basic.DomBasicInputRenderer;
import com.icesoft.faces.renderkit.dom_html_basic.HTML;
import com.icesoft.faces.renderkit.dom_html_basic.PassThruAttributeRenderer;
import com.icesoft.util.pooling.ClientIdPool;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.icefaces.impl.util.DOMUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class SelectInputTextRenderer extends DomBasicInputRenderer {
private Map domUpdateMap = new HashMap();
private static final String AUTOCOMPLETE_DIV = "_div";
static final String AUTOCOMPLETE_INDEX = "_idx";
private static final Log log =
LogFactory.getLog(SelectInputTextRenderer.class);
//private static final String[] passThruAttributes = ExtendedAttributeConstants.getAttributes(ExtendedAttributeConstants.ICE_SELECTINPUTTEXT);
//handle HTML.ONKEYDOWN_ATTR, HTML.ONKEYUP_ATTR, HTML.ONFOCUS_ATTR, HTML.ONBLUR_ATTR
private static final String[] passThruAttributes = new String[]{HTML.ACCESSKEY_ATTR, HTML.ALT_ATTR, HTML.DIR_ATTR, HTML.LANG_ATTR, HTML.MAXLENGTH_ATTR, HTML.ONCHANGE_ATTR, HTML.ONCLICK_ATTR, HTML.ONDBLCLICK_ATTR, HTML.ONKEYPRESS_ATTR, HTML.ONMOUSEDOWN_ATTR, HTML.ONMOUSEMOVE_ATTR, HTML.ONMOUSEOUT_ATTR, HTML.ONMOUSEOVER_ATTR, HTML.ONMOUSEUP_ATTR, HTML.ONSELECT_ATTR, HTML.ROWS_ATTR, HTML.SIZE_ATTR, HTML.STYLE_ATTR, HTML.TITLE_ATTR, HTML.WIDTH_ATTR};
public boolean getRendersChildren() {
return true;
}
public void encodeBegin(FacesContext facesContext, UIComponent uiComponent)
throws IOException {
domUpdateMap.clear();
validateParameters(facesContext, uiComponent, null);
if (log.isTraceEnabled()) {
log.trace("encodeBegin");
}
SelectInputText component = (SelectInputText) uiComponent;
DOMContext domContext =
DOMContext.attachDOMContext(facesContext, uiComponent);
String clientId = uiComponent.getClientId(facesContext);
String divId = ClientIdPool.get(clientId + AUTOCOMPLETE_DIV);
if (!domContext.isInitialized()) {
Element root = domContext.createRootElement(HTML.DIV_ELEM);
Element input = domContext.createElement(HTML.INPUT_ELEM);
input.setAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_TEXT);
setRootElementId(facesContext, input, uiComponent);
root.appendChild(input);
input.setAttribute(HTML.NAME_ATTR, clientId);
input.setAttribute(HTML.CLASS_ATTR, component.getInputTextClass());
String mousedownScript = (String) uiComponent.getAttributes().get(HTML.ONMOUSEDOWN_ATTR);
input.setAttribute(HTML.ONMOUSEDOWN_ATTR, combinedPassThru(mousedownScript, "this.focus();"));
String inputStyle = component.getWidthAsStyle();
if (inputStyle != null && inputStyle.length() > 0)
input.setAttribute(HTML.STYLE_ATTR, inputStyle);
else
input.removeAttribute(HTML.STYLE_ATTR);
input.setAttribute("autocomplete", "off");
Element div = domContext.createElement(HTML.DIV_ELEM);
String listClass = component.getListClass();
div.setAttribute(HTML.ID_ATTR, divId);
if (listClass == null) {
div.setAttribute(HTML.STYLE_ATTR,
"display:none;border:1px solid black;background-color:white;z-index:500;");
} else {
div.setAttribute(HTML.CLASS_ATTR, listClass);
}
root.appendChild(div);
Element index = domContext.createElement(HTML.INPUT_ELEM);
index.setAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN);
String indexId = ClientIdPool.get(clientId + AUTOCOMPLETE_INDEX);
index.setAttribute(HTML.NAME_ATTR, indexId);
root.appendChild(index);
String rootStyle = component.getStyle();
if (rootStyle != null && rootStyle.length() > 0)
root.setAttribute(HTML.STYLE_ATTR, rootStyle);
else
root.removeAttribute(HTML.STYLE_ATTR);
root.setAttribute(HTML.CLASS_ATTR, component.getStyleClass());
// Element script = domContext.createElement(HTML.SCRIPT_ELEM);
// script.setAttribute(HTML.SCRIPT_LANGUAGE_ATTR,
// HTML.SCRIPT_LANGUAGE_JAVASCRIPT);
// String scriptCode = "window.onLoad(function(){" + call + "});";
// Node node = domContext.createTextNode(scriptCode);
// script.appendChild(node);
// root.appendChild(script);
if (log.isDebugEnabled()) {
log.debug(
"SelectInputText:encodeBegin():component created with the following id : " +
clientId);
}
PassThruAttributeRenderer.renderHtmlAttributes(facesContext, uiComponent, input, null, passThruAttributes);
PassThruAttributeRenderer.renderHtmlAttributes(facesContext, uiComponent, input, null, new String[]{HTML.TABINDEX_ATTR});
PassThruAttributeRenderer.renderBooleanAttributes(facesContext,
uiComponent, input, PassThruAttributeRenderer.EMPTY_STRING_ARRAY);
Element scriptEle = domContext.createElement(HTML.SCRIPT_ELEM);
scriptEle.setAttribute(HTML.ID_ATTR, ClientIdPool.get(clientId + "script"));
scriptEle.setAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT);
boolean partialSubmit = component.getPartialSubmit();
if (!component.isDisabled() && !component.isReadonly()) {
Node node = domContext.createTextNodeUnescaped("new Ice.Autocompleter('" + clientId + "','" + divId +
"', " + component.getOptions() + " ,'" + component.getRowClass() + "','" +
component.getSelectedRowClass() + "'," + partialSubmit + ");");
scriptEle.appendChild(node);
}
root.appendChild(scriptEle);
domUpdateMap.put("rows", component.getRows());
Element span = domContext.createElement(HTML.SPAN_ELEM);
span.setAttribute("data-hashcode", String.valueOf(domUpdateMap.hashCode()));
span.setAttribute("style", "display: none;");
root.appendChild(span);
}
}
public void encodeChildren(FacesContext facesContext,
UIComponent uiComponent)
throws IOException {
DOMContext domContext =
DOMContext.getDOMContext(facesContext, uiComponent);
SelectInputText component = (SelectInputText) uiComponent;
Element input = (Element) domContext.getRootNode().getFirstChild();
String combinedValue = "setFocus(this.id);";
Object appValue = uiComponent.getAttributes().get("onfocus");
if (appValue != null)
combinedValue += appValue.toString();
input.setAttribute("onfocus", combinedValue);
combinedValue = "setFocus('');";
appValue = uiComponent.getAttributes().get("onblur");
if (appValue != null)
combinedValue += appValue.toString();
input.setAttribute("onblur", combinedValue);
appValue = uiComponent.getAttributes().get("onchange");
if (appValue != null)
input.setAttribute("onchange", appValue.toString());
// this would prevent, when first valueChangeListener fires with null value
//System.out.println("SelectInputTextRenderer.encodeChildren() clientId: " + uiComponent.getClientId(facesContext));
String value = getValue(facesContext, uiComponent);
//System.out.println("SelectInputTextRenderer.encodeChildren() value: " + value);
if (value != null) {
input.setAttribute(HTML.VALUE_ATTR, value);
//System.out.println("SelectInputTextRenderer.encodeChildren() changed: " + component.hasChanged());
if (component.hasChanged()) {
if (log.isDebugEnabled()) {
log.debug(
"SelectInputText:encodeChildren(): component's value have been changed, start populating list : ");
}
Map requestParemeterMap = facesContext.getExternalContext().getRequestParameterMap();
KeyEvent keyEvent = new KeyEvent(component, requestParemeterMap);
if (keyEvent.getKeyCode() != KeyEvent.CARRIAGE_RETURN) {
populateList(facesContext, component);
}
component.setChangedComponentId(null);
}
}
// renderAttribute(uiComponent, input, HTML.DISABLED_ATTR,
// HTML.DISABLED_ATTR);
// renderAttribute(uiComponent, input, HTML.READONLY_ATTR,
// HTML.READONLY_ATTR);
domContext.stepOver();
}
public void populateList(FacesContext facesContext, SelectInputText component)
throws IOException {
if (log.isTraceEnabled()) {
log.trace("populateList");
}
component.populateItemList();
Iterator matches = component.getItemList();
int rows = component.getRows();
if (rows == 0) rows = Integer.MAX_VALUE;
int rowCounter = 0;
if (component.getSelectFacet() != null) {
if (log.isDebugEnabled()) {
log.debug(
"SelectInputText:populateList(): \"selectInputText\" facet found, generate generic html for list");
}
UIComponent facet = component.getSelectFacet();
DOMContext domContext =
DOMContext.getDOMContext(facesContext, component);
Element listDiv = domContext.createElement(HTML.DIV_ELEM);
Map requestMap =
facesContext.getExternalContext().getRequestMap();
//set index to 0, so child components can get client id from autoComplete component
component.setIndex(0);
while (matches.hasNext() && rowCounter++ < rows) {
Element div = domContext.createElement(HTML.DIV_ELEM);
SelectItem item = (SelectItem) matches.next();
requestMap.put(component.getListVar(), item.getValue());
listDiv.appendChild(div);
// When HTML is display we still need a selected value. Hidding the value in a hidden span
// accomplishes this.
Element spanToDisplay =
domContext.createElement(HTML.SPAN_ELEM);
spanToDisplay.setAttribute(HTML.CLASS_ATTR, "informal");
div.appendChild(spanToDisplay);
domContext.setCursorParent(spanToDisplay);
encodeParentAndChildren(facesContext, facet);
Element spanToSelect =
domContext.createElement(HTML.SPAN_ELEM);
spanToSelect.setAttribute(HTML.STYLE_ATTR,
"visibility:hidden;display:none;");
String itemLabel = item.getLabel();
if (itemLabel == null) {
itemLabel = converterGetAsString(
facesContext, component, item.getValue());
}
Text label = domContext.createTextNode((itemLabel));
spanToSelect.appendChild(label);
div.appendChild(spanToSelect);
component.resetId(facet);
}
component.setIndex(-1);
String nodeValue =
DOMUtils.nodeToString(listDiv).replaceAll("\n", "");
String call = "Ice.Scriptaculous.Autocompleter.Finder.find('" +
component.getClientId(facesContext) +
"').updateNOW('" + escapeSingleQuote(nodeValue) + "');";
JavascriptContext.addJavascriptCall(facesContext, call);
} else {
if (log.isDebugEnabled()) {
log.debug(
"SelectInputText:populateList(): \"selectItem(s)\" found, generate plain-text for list");
}
if (matches.hasNext()) {
StringBuffer sb = new StringBuffer("");
SelectItem item = null;
while (matches.hasNext() && rowCounter++ < rows) {
item = (SelectItem) matches.next();
String itemLabel = item.getLabel();
if (itemLabel == null) {
itemLabel = converterGetAsString(
facesContext, component, item.getValue());
}
sb.append("").append(DOMUtils.escapeAnsi(itemLabel))
.append("");
}
sb.append("");
String call = "Ice.Scriptaculous.Autocompleter.Finder.find('" +
component.getClientId(facesContext) +
"').updateNOW('" + escapeSingleQuote(sb.toString()) + "');";
JavascriptContext.addJavascriptCall(facesContext, call);
}
}
}
private static String escapeSingleQuote(String text) {
if (null == text) {
return "";
}
char[] chars = text.toCharArray();
StringBuilder buffer = new StringBuilder(chars.length);
for (int index = 0; index < chars.length; index++) {
char ch = chars[index];
if (ch == '\'') {
buffer.append("'");
} else {
buffer.append(ch);
}
}
return buffer.toString();
}
}