1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit.html.ext;
20
21 import java.io.IOException;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26
27 import javax.faces.component.UIComponent;
28 import javax.faces.component.UIInput;
29 import javax.faces.component.UIOutput;
30 import javax.faces.component.UIViewRoot;
31 import javax.faces.component.behavior.ClientBehavior;
32 import javax.faces.component.behavior.ClientBehaviorHolder;
33 import javax.faces.component.html.HtmlOutputText;
34 import javax.faces.context.FacesContext;
35 import javax.faces.context.ResponseWriter;
36
37 import org.apache.myfaces.component.UserRoleUtils;
38 import org.apache.myfaces.component.html.ext.HtmlInputText;
39 import org.apache.myfaces.shared_tomahawk.component.EscapeCapable;
40 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
41 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
42 import org.apache.myfaces.shared_tomahawk.renderkit.html.CommonEventUtils;
43 import org.apache.myfaces.shared_tomahawk.renderkit.html.CommonPropertyConstants;
44 import org.apache.myfaces.shared_tomahawk.renderkit.html.CommonPropertyUtils;
45 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
46 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
47 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTextRendererBase;
48 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class HtmlTextRenderer
66 extends HtmlTextRendererBase
67 {
68 private static final String ONCHANGE_PREFIX = "onChange_";
69 private static final String HIDDEN_SUFFIX = "_hidden";
70
71
72 private static final Logger log = Logger.getLogger(HtmlTextRenderer.class.getName());
73
74 @Override
75 protected boolean isCommonPropertiesOptimizationEnabled(FacesContext facesContext)
76 {
77 return true;
78 }
79
80 @Override
81 protected boolean isCommonEventsOptimizationEnabled(FacesContext facesContext)
82 {
83 return true;
84 }
85
86 protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
87 {
88 if (!UserRoleUtils.isEnabledOnUserRole(uiComponent))
89 {
90 return true;
91 }
92 else
93 {
94 return super.isDisabled(facesContext, uiComponent);
95 }
96 }
97
98
99
100 protected boolean isDisabledOnClientSide(FacesContext facesContext, UIComponent component)
101 {
102 if (component instanceof HtmlInputText)
103 {
104 return ((HtmlInputText)component).isDisabledOnClientSide();
105 }
106
107 return false;
108 }
109
110 public void encodeEnd(FacesContext facesContext, UIComponent component)
111 throws IOException
112 {
113 if (HtmlRendererUtils.isDisplayValueOnly(component))
114 {
115 renderInputValueOnly(facesContext, component);
116 }
117 else
118 {
119 renderNormal(facesContext, component);
120 }
121 }
122
123 @Override
124 protected void renderOutput(FacesContext facesContext, UIComponent component)
125 throws IOException
126 {
127 String text = org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils.getStringValue(facesContext, component);
128 if (log.isLoggable(Level.FINE)) log.fine("renderOutput '" + text + "'");
129 boolean escape;
130 if (component instanceof HtmlOutputText || component instanceof EscapeCapable)
131 {
132 escape = ((HtmlOutputText)component).isEscape();
133 }
134 else
135 {
136 escape = RendererUtils.getBooleanAttribute(component, org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr.ESCAPE_ATTR,
137 true);
138 }
139
140 if (text != null)
141 {
142 ResponseWriter writer = facesContext.getResponseWriter();
143 boolean span = false;
144
145 Map<String, List<ClientBehavior>> behaviors = null;
146 if (component instanceof ClientBehaviorHolder)
147 {
148 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
149 }
150
151 if (behaviors != null && !behaviors.isEmpty())
152 {
153 span = true;
154 writer.startElement(HTML.SPAN_ELEM, component);
155 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext),null);
156 if (isCommonPropertiesOptimizationEnabled(facesContext))
157 {
158 long commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
159
160 CommonPropertyUtils.renderUniversalProperties(writer, commonPropertiesMarked, component);
161 CommonPropertyUtils.renderStyleProperties(writer, commonPropertiesMarked, component);
162
163 if (isCommonEventsOptimizationEnabled(facesContext))
164 {
165 Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(component);
166 CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer,
167 commonPropertiesMarked, commonEventsMarked, component, behaviors);
168 }
169 else
170 {
171 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, behaviors);
172 }
173 }
174 else
175 {
176 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.UNIVERSAL_ATTRIBUTES);
177 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, behaviors);
178 }
179 }
180 else
181 {
182 if (isCommonPropertiesOptimizationEnabled(facesContext))
183 {
184 long commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
185 if ( (commonPropertiesMarked & ~(CommonPropertyConstants.ESCAPE_PROP)) > 0)
186 {
187 span = true;
188 writer.startElement(HTML.SPAN_ELEM, component);
189 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
190 }
191 else if (CommonPropertyUtils.isIdRenderingNecessary(component))
192 {
193 span = true;
194 writer.startElement(HTML.SPAN_ELEM, component);
195 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext), null);
196 }
197
198 CommonPropertyUtils.renderUniversalProperties(writer, commonPropertiesMarked, component);
199 CommonPropertyUtils.renderStyleProperties(writer, commonPropertiesMarked, component);
200
201 if (isRenderOutputEventAttributes())
202 {
203 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.EVENT_HANDLER_ATTRIBUTES);
204 }
205 }
206 else
207 {
208 if(component.getId()!=null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
209 {
210 span = true;
211
212 writer.startElement(HTML.SPAN_ELEM, component);
213
214 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
215
216 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.COMMON_PASSTROUGH_ATTRIBUTES);
217
218 }
219 else
220 {
221 span = HtmlRendererUtils.renderHTMLAttributesWithOptionalStartElement(writer,component,
222 HTML.SPAN_ELEM,HTML.COMMON_PASSTROUGH_ATTRIBUTES);
223 }
224 }
225 }
226
227 if (escape)
228 {
229 Logger log = Logger.getLogger(HtmlTextRendererBase.class.getName());
230 if (log.isLoggable(Level.FINE)) log.fine("renderOutputText writing '" + text + "'");
231 writer.writeText(text, org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr.VALUE_ATTR);
232 }
233 else
234 {
235 writer.write(text);
236 }
237
238 if(span)
239 {
240 writer.endElement(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SPAN_ELEM);
241 }
242 }
243 }
244
245 @Override
246 protected void renderInput(FacesContext facesContext, UIComponent component) throws IOException
247 {
248 if (!isDisabledOnClientSide(facesContext, component) || isDisabled(facesContext, component))
249 {
250 super.renderInput(facesContext, component);
251 return;
252 }
253
254
255 ResponseWriter writer = facesContext.getResponseWriter();
256
257 String clientId = component.getClientId(facesContext);
258 String value = RendererUtils.getStringValue(facesContext, component);
259
260 writer.startElement(HTML.INPUT_ELEM, component);
261 writer.writeAttribute(HTML.ID_ATTR, clientId, null);
262 writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
263 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_TEXT, null);
264 if (value != null)
265 {
266 writer.writeAttribute(HTML.VALUE_ATTR, value, JSFAttr.VALUE_ATTR);
267 }
268
269 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
270
271 writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
272
273 writer.writeAttribute(HTML.ONCHANGE_ATTR, getOnChangeFunctionName(clientId)+"();", null);
274
275 writer.endElement(HTML.INPUT_ELEM);
276
277
278 renderHiddenInput(facesContext, (UIInput)component);
279 }
280
281
282
283 protected void renderHiddenInput(FacesContext facesContext, UIComponent component) throws IOException
284 {
285 ResponseWriter writer = facesContext.getResponseWriter();
286
287 String disabledInputClientId = component.getClientId(facesContext);
288
289 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
290
291 writer.startElement(HTML.SCRIPT_ELEM, null);
292 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
293 writer.writeText(createOnChangeListenerJS(disabledInputClientId), null);
294 writer.endElement(HTML.SCRIPT_ELEM);
295
296 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
297
298 writer.startElement(HTML.INPUT_ELEM, null);
299 writer.writeAttribute(HTML.ID_ATTR, disabledInputClientId + HIDDEN_SUFFIX, null);
300 writer.writeAttribute(HTML.NAME_ATTR, disabledInputClientId + HIDDEN_SUFFIX, null);
301 writer.writeAttribute(HTML.VALUE_ATTR, RendererUtils.getStringValue(facesContext, component), null);
302 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
303 writer.endElement(HTML.INPUT_ELEM);
304
305 HtmlRendererUtils.writePrettyLineSeparator(facesContext);
306 }
307
308 protected void renderInputValueOnly(FacesContext facesContext, UIComponent component)
309 throws IOException
310 {
311 HtmlRendererUtils.renderDisplayValueOnly(facesContext,
312 (UIInput) component);
313 }
314
315 protected void renderNormal(FacesContext facesContext, UIComponent component)
316 throws IOException
317 {
318 super.encodeEnd(facesContext, component);
319 }
320
321
322
323
324 protected String getOnChangeFunctionName(String inputDisabledClientId)
325 {
326 StringBuffer buf = new StringBuffer();
327 buf.append(ONCHANGE_PREFIX);
328 buf.append(JavascriptUtils.getValidJavascriptName(inputDisabledClientId, true));
329
330 return buf.toString();
331 }
332
333
334
335 protected String createOnChangeListenerJS(String inputDisabledClientId)
336 {
337 StringBuffer script = new StringBuffer();
338 script.append("function ");
339 script.append(getOnChangeFunctionName(inputDisabledClientId));
340 script.append("() {\n");
341 script.append("var hiddenInput = document.getElementById(\"").append(inputDisabledClientId + HIDDEN_SUFFIX).append("\");\n");
342 script.append("var disabledInput = document.getElementById(\"").append(inputDisabledClientId).append("\");\n");
343 script.append("hiddenInput.value=disabledInput.value;\n");
344 script.append("}\n");
345
346 return script.toString();
347 }
348
349 public void decode(FacesContext facesContext, UIComponent component)
350 {
351 if (isDisabledOnClientSide(facesContext, component) && !isDisabled(facesContext, component))
352 {
353
354
355 Map paramValuesMap = facesContext.getExternalContext().getRequestParameterMap();
356 Object reqValue = paramValuesMap.get(component.getClientId(facesContext) + HIDDEN_SUFFIX);
357
358 ((UIInput)component).setSubmittedValue(reqValue);
359 return;
360 }
361
362 if (!(component instanceof UIInput) && (component instanceof UIOutput))
363 {
364 HtmlRendererUtils.decodeClientBehaviors(facesContext, component);
365 }
366 super.decode(facesContext, component);
367 }
368 }