001: /*
002: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
003: *
004: * "The contents of this file are subject to the Mozilla Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
011: * License for the specific language governing rights and limitations under
012: * the License.
013: *
014: * The Original Code is ICEfaces 1.5 open source software code, released
015: * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
016: * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
017: * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
018: *
019: * Contributor(s): _____________________.
020: *
021: * Alternatively, the contents of this file may be used under the terms of
022: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
023: * License), in which case the provisions of the LGPL License are
024: * applicable instead of those above. If you wish to allow use of your
025: * version of this file only under the terms of the LGPL License and not to
026: * allow others to use your version of this file under the MPL, indicate
027: * your decision by deleting the provisions above and replace them with
028: * the notice and other provisions required by the LGPL License. If you do
029: * not delete the provisions above, a recipient may use your version of
030: * this file under either the MPL or the LGPL License."
031: *
032: */
033:
034: package com.icesoft.faces.renderkit.dom_html_basic;
035:
036: import com.icesoft.faces.component.UIXhtmlComponent;
037: import com.icesoft.faces.context.DOMContext;
038: import com.icesoft.faces.util.DOMUtils;
039: import org.w3c.dom.Element;
040: import org.w3c.dom.Node;
041: import org.w3c.dom.Text;
042:
043: import javax.faces.component.UIComponent;
044: import javax.faces.component.UIInput;
045: import javax.faces.component.UIOutput;
046: import javax.faces.context.FacesContext;
047: import java.io.IOException;
048: import java.util.HashSet;
049: import java.util.Map;
050:
051: public class TextRenderer extends DomBasicInputRenderer {
052:
053: public void encodeChildren(FacesContext facesContext,
054: UIComponent uiComponent) {
055: validateParameters(facesContext, uiComponent, null);
056: }
057:
058: protected void renderEnd(FacesContext facesContext,
059: UIComponent uiComponent, String currentValue)
060: throws IOException {
061: validateParameters(facesContext, uiComponent, null);
062: if (uiComponent instanceof UIInput) {
063: renderUIInput(facesContext, uiComponent, currentValue);
064: } else if (uiComponent instanceof UIOutput) {
065: renderUIOutput(facesContext, uiComponent, currentValue);
066: }
067: }
068:
069: /**
070: * @param facesContext
071: * @param uiComponent
072: * @param currentValue
073: * @throws IOException
074: */
075: private void renderUIOutput(FacesContext facesContext,
076: UIComponent uiComponent, String currentValue)
077: throws IOException {
078:
079: DOMContext domContext = DOMContext.attachDOMContext(
080: facesContext, uiComponent);
081:
082: boolean requiresContainingSpan = requiresContainingSpan(uiComponent);
083:
084: if (requiresContainingSpan) {
085: renderContainingSpan(facesContext, uiComponent, domContext);
086: } else {
087: renderTextNode(domContext);
088: }
089:
090: if (currentValue == null) {
091: // We need to set the data in the text node to the empty string.
092: // The text node can be either the root node or it can be
093: // the first child of the root node in the case where we
094: // rendered a containing span
095: Text textNode = null;
096: if (requiresContainingSpan) {
097: textNode = (Text) domContext.getRootNode()
098: .getFirstChild();
099: } else {
100: textNode = ((Text) domContext.getRootNode());
101: }
102: if (textNode != null) {
103: textNode.setData("");
104: }
105: } else {
106: renderCurrentValue(uiComponent, currentValue, domContext,
107: requiresContainingSpan);
108: }
109: domContext.streamWrite(facesContext, uiComponent);
110: }
111:
112: /**
113: * @param domContext
114: */
115: private void renderTextNode(DOMContext domContext) {
116: if (!domContext.isInitialized()) {
117: Node root = domContext.getDocument().createTextNode("");
118: domContext.setRootNode(root);
119: } else if (!(domContext.getRootNode() instanceof Text)) {
120: // Need to switch from a root span to a root text node.
121: // This type of change can occur when the binding attribute is defined
122: // and the model has altered one of the attributes requiring a span
123: // from non-null to null.
124: domContext.getRootNode().getParentNode().removeChild(
125: domContext.getRootNode());
126: domContext.setRootNode(domContext.getDocument()
127: .createTextNode(""));
128: }
129: }
130:
131: /**
132: * @param facesContext
133: * @param uiComponent
134: * @param domContext
135: */
136: private void renderContainingSpan(FacesContext facesContext,
137: UIComponent uiComponent, DOMContext domContext) {
138: if (!domContext.isInitialized()) {
139: Node root = domContext.createElement(HTML.SPAN_ELEM);
140: domContext.setRootNode(root);
141: } else if (!(domContext.getRootNode() instanceof Element)) {
142: // if we require a span but the existing root node is not a span then we
143: // need to switch from a text node at the root to a span at the root
144: // This type of change can occur when the binding attribute is defined
145: // and the model has altered one of the attributes requiring a span
146: // from null to some non-null value
147: domContext.getRootNode().getParentNode().removeChild(
148: domContext.getRootNode());
149: domContext.setRootNode(domContext
150: .createElement(HTML.SPAN_ELEM));
151: }
152: Element rootSpan = (Element) domContext.getRootNode();
153: setRootElementId(facesContext, rootSpan, uiComponent);
154: // render styleClass as the value of the class attribute;
155: // leave the style to be passed through
156: String styleClass = (String) uiComponent.getAttributes().get(
157: "styleClass");
158: if (styleClass != null) {
159: ((Element) rootSpan).setAttribute("class", styleClass);
160: }
161: PassThruAttributeRenderer.renderAttributes(facesContext,
162: uiComponent, null);
163: }
164:
165: /**
166: * @param uiComponent
167: * @param currentValue
168: * @param domContext
169: * @param requiresContainingSpan
170: */
171: private void renderCurrentValue(UIComponent uiComponent,
172: String currentValue, DOMContext domContext,
173: boolean requiresContainingSpan) {
174:
175: // escape
176: boolean valueTextRequiresEscape = DOMUtils
177: .escapeIsRequired(uiComponent);
178: if (valueTextRequiresEscape) {
179: currentValue = DOMUtils.escapeAnsi(currentValue);
180: }
181:
182: // Avoid severing and recreating the node
183: Node rootNode = domContext.getRootNode();
184: if (requiresContainingSpan) {
185: domContext.setCursorParent(rootNode);
186: if (rootNode.getFirstChild() != null
187: && rootNode.getFirstChild() instanceof Text) {
188: ((Text) rootNode.getFirstChild()).setData(currentValue);
189: } else {
190: Text text = domContext.getDocument().createTextNode(
191: currentValue);
192: rootNode.appendChild(text);
193: }
194: } else {
195: ((Text) rootNode).setData(currentValue);
196: }
197: }
198:
199: /**
200: * @param facesContext
201: * @param uiComponent
202: * @param currentValue
203: * @throws IOException
204: */
205: private void renderUIInput(FacesContext facesContext,
206: UIComponent uiComponent, String currentValue)
207: throws IOException {
208:
209: DOMContext domContext = DOMContext.attachDOMContext(
210: facesContext, uiComponent);
211:
212: if (!domContext.isInitialized()) {
213: Element root = domContext.createElement("input");
214: domContext.setRootNode(root);
215: setRootElementId(facesContext, root, uiComponent);
216: root.setAttribute("type", "text");
217: root.setAttribute("name", uiComponent
218: .getClientId(facesContext));
219: }
220: Element root = (Element) domContext.getRootNode();
221:
222: String bidi = (String) uiComponent.getAttributes().get("dir");
223: if (bidi != null) {
224: root.setAttribute("dir", bidi);
225: }
226:
227: if (currentValue != null) {
228: root.setAttribute("value", currentValue);
229: } else {
230: root.removeAttribute("value");
231: }
232:
233: String styleClass = (String) uiComponent.getAttributes().get(
234: "styleClass");
235: if (styleClass != null) {
236: root.setAttribute("class", styleClass);
237: }
238:
239: HashSet excludes = new HashSet();
240: addJavaScript(facesContext, uiComponent, root, currentValue,
241: excludes);
242: PassThruAttributeRenderer.renderAttributes(facesContext,
243: uiComponent, getExcludesArray(excludes));
244: domContext.streamWrite(facesContext, uiComponent);
245:
246: }
247:
248: /**
249: * We require a containing span if either styleClass or style attributes are
250: * present, or there is an id to accommodate.
251: *
252: * @param uiComponent
253: * @return boolean
254: */
255: private boolean requiresContainingSpan(UIComponent uiComponent) {
256:
257: // special case for title element
258: UIComponent parent = uiComponent.getParent();
259: if (parent != null && parent instanceof UIXhtmlComponent) {
260: String tag = ((UIXhtmlComponent) parent).getTag();
261: if (tag != null && tag.equalsIgnoreCase("title")) {
262: return false;
263: }
264: }
265:
266: String style = (String) uiComponent.getAttributes()
267: .get("style");
268: String styleClass = (String) uiComponent.getAttributes().get(
269: "styleClass");
270: String title = (String) uiComponent.getAttributes()
271: .get("title");
272: if (styleClass != null || style != null || title != null) {
273: return true;
274: }
275: Map attributes = uiComponent.getAttributes();
276: if (attributes.size() != 0) {
277: if (PassThruAttributeRenderer
278: .passThruAttributeExists(uiComponent)) {
279: return true;
280: }
281: }
282: if (idNotNull(uiComponent)
283: && !uiComponent.getId().startsWith("_")) {
284: return true;
285: }
286: return false;
287: }
288:
289: protected void addJavaScript(FacesContext facesContext,
290: UIComponent uiComponent, Element root, String currentValue,
291: HashSet excludes) {
292:
293: }
294: }
|