1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.myfaces.shared.component.DisplayValueOnlyCapable;
24 import org.apache.myfaces.shared.component.EscapeCapable;
25 import org.apache.myfaces.shared.config.MyfacesConfig;
26 import org.apache.myfaces.shared.renderkit.JSFAttr;
27 import org.apache.myfaces.shared.renderkit.RendererUtils;
28 import org.apache.myfaces.shared.renderkit.html.util.FormInfo;
29 import org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder;
30 import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;
31
32 import javax.faces.FacesException;
33 import javax.faces.component.*;
34 import javax.faces.component.html.HtmlDataTable;
35 import javax.faces.component.html.HtmlPanelGrid;
36 import javax.faces.context.ExternalContext;
37 import javax.faces.context.FacesContext;
38 import javax.faces.context.ResponseWriter;
39 import javax.faces.convert.Converter;
40 import javax.faces.model.SelectItem;
41 import javax.faces.model.SelectItemGroup;
42 import java.io.IOException;
43 import java.util.*;
44
45 /***
46 * @author Manfred Geiler (latest modification by $Author: lu4242 $)
47 * @version $Revision: 960240 $ $Date: 2010-07-03 12:30:42 -0500 (Sat, 03 Jul 2010) $
48 */
49 public final class HtmlRendererUtils {
50 private static final Log log = LogFactory.getLog(HtmlRendererUtils.class);
51
52
53 private static final String LINE_SEPARATOR = System.getProperty(
54 "line.separator", "\r\n");
55 private static final char TABULATOR = '\t';
56
57 public static final String HIDDEN_COMMANDLINK_FIELD_NAME = "_idcl";
58 public static final String HIDDEN_COMMANDLINK_FIELD_NAME_MYFACES_OLD = "_link_hidden_";
59 public static final String HIDDEN_COMMANDLINK_FIELD_NAME_TRINIDAD = "source";
60
61 public static final String CLEAR_HIDDEN_FIELD_FN_NAME =
62 "clearFormHiddenParams";
63 public static final String SUBMIT_FORM_FN_NAME = "oamSubmitForm";
64 public static final String ALLOW_CDATA_SECTION_ON = "org.apache.myfaces.ResponseWriter.CdataSectionOn";
65
66 private static final String SET_HIDDEN_INPUT_FN_NAME = "oamSetHiddenInput";
67 private static final String CLEAR_HIDDEN_INPUT_FN_NAME = "oamClearHiddenInput";
68
69 private static final String AUTO_SCROLL_PARAM = "autoScroll";
70 private static final String AUTO_SCROLL_FUNCTION = "getScrolling";
71
72 private static final String FIRST_SUBMIT_SCRIPT_ON_PAGE = "org.apache.MyFaces.FIRST_SUBMIT_SCRIPT_ON_PAGE";
73
74 public static final String NON_SUBMITTED_VALUE_WARNING
75 = "There should always be a submitted value for an input if it is rendered,"
76 + " its form is submitted, and it was not originally rendered disabled or read-only."
77 + " You cannot submit a form after disabling an input element via javascript."
78 + " Consider setting read-only to true instead"
79 + " or resetting the disabled value back to false prior to form submission.";
80
81
82 private HtmlRendererUtils() {
83
84 }
85
86 /***
87 * Utility to set the submitted value of the provided component from the
88 * data in the current request object.
89 * <p>
90 * Param component is required to be an EditableValueHolder. On return
91 * from this method, the component's submittedValue property will be
92 * set if the submitted form contained that component.
93 */
94 public static void decodeUIInput(FacesContext facesContext,
95 UIComponent component) {
96 if (!(component instanceof EditableValueHolder)) {
97 throw new IllegalArgumentException("Component "
98 + component.getClientId(facesContext)
99 + " is not an EditableValueHolder");
100 }
101 Map paramMap = facesContext.getExternalContext()
102 .getRequestParameterMap();
103 String clientId = component.getClientId(facesContext);
104
105 if(isDisabledOrReadOnly(component))
106 return;
107
108 if(paramMap.containsKey(clientId))
109 {
110 ((EditableValueHolder) component).setSubmittedValue(paramMap
111 .get(clientId));
112 }
113 else {
114 log.warn(NON_SUBMITTED_VALUE_WARNING +
115 " Component : " +
116 RendererUtils.getPathToComponent(component));
117 }
118 }
119
120 /***
121 * X-CHECKED: tlddoc h:selectBooleanCheckbox
122 *
123 * @param facesContext
124 * @param component
125 */
126 public static void decodeUISelectBoolean(FacesContext facesContext,
127 UIComponent component) {
128 if (!(component instanceof EditableValueHolder)) {
129 throw new IllegalArgumentException("Component "
130 + component.getClientId(facesContext)
131 + " is not an EditableValueHolder");
132 }
133
134 if(isDisabledOrReadOnly(component))
135 return;
136
137 Map paramMap = facesContext.getExternalContext()
138 .getRequestParameterMap();
139 String clientId = component.getClientId(facesContext);
140 if (paramMap.containsKey(clientId)) {
141 String reqValue = (String) paramMap.get(clientId);
142 if ((reqValue.equalsIgnoreCase("on")
143 || reqValue.equalsIgnoreCase("yes") || reqValue
144 .equalsIgnoreCase("true"))) {
145 ((EditableValueHolder) component)
146 .setSubmittedValue(Boolean.TRUE);
147 } else {
148 ((EditableValueHolder) component)
149 .setSubmittedValue(Boolean.FALSE);
150 }
151 } else {
152 ((EditableValueHolder) component)
153 .setSubmittedValue(Boolean.FALSE);
154 }
155 }
156
157 public static boolean isDisabledOrReadOnly(UIComponent component)
158 {
159 return isDisplayValueOnly(component) ||
160 isDisabled(component) ||
161 isReadOnly(component);
162 }
163
164 public static boolean isDisabled(UIComponent component)
165 {
166 return isTrue(component.getAttributes().get("disabled"));
167 }
168
169 public static boolean isReadOnly(UIComponent component)
170 {
171 return isTrue(component.getAttributes().get("readonly"));
172 }
173
174 private static boolean isTrue(Object obj)
175 {
176 if(!(obj instanceof Boolean))
177 return false;
178
179 return ((Boolean) obj).booleanValue();
180 }
181
182 /***
183 * X-CHECKED: tlddoc h:selectManyListbox
184 *
185 * @param facesContext
186 * @param component
187 */
188 public static void decodeUISelectMany(FacesContext facesContext,
189 UIComponent component) {
190 if (!(component instanceof EditableValueHolder)) {
191 throw new IllegalArgumentException("Component "
192 + component.getClientId(facesContext)
193 + " is not an EditableValueHolder");
194 }
195 Map paramValuesMap = facesContext.getExternalContext()
196 .getRequestParameterValuesMap();
197 String clientId = component.getClientId(facesContext);
198
199 if(isDisabledOrReadOnly(component))
200 return;
201
202 if (paramValuesMap.containsKey(clientId)) {
203 String[] reqValues = (String[]) paramValuesMap.get(clientId);
204 ((EditableValueHolder) component).setSubmittedValue(reqValues);
205 } else {
206
207
208
209
210
211
212 ((EditableValueHolder) component).setSubmittedValue( new String[]{});
213 }
214 }
215
216 /***
217 * X-CHECKED: tlddoc h:selectManyListbox
218 *
219 * @param facesContext
220 * @param component
221 */
222 public static void decodeUISelectOne(FacesContext facesContext,
223 UIComponent component) {
224 if (!(component instanceof EditableValueHolder)) {
225 throw new IllegalArgumentException("Component "
226 + component.getClientId(facesContext)
227 + " is not an EditableValueHolder");
228 }
229
230 if(isDisabledOrReadOnly(component))
231 return;
232
233 Map paramMap = facesContext.getExternalContext()
234 .getRequestParameterMap();
235 String clientId = component.getClientId(facesContext);
236 if (paramMap.containsKey(clientId)) {
237
238 ((EditableValueHolder) component).setSubmittedValue(paramMap
239 .get(clientId));
240 } else {
241
242 ((EditableValueHolder) component).setSubmittedValue( RendererUtils.NOTHING );
243 }
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 public static void renderListbox(FacesContext facesContext,
275 UISelectOne selectOne, boolean disabled, int size)
276 throws IOException {
277 internalRenderSelect(facesContext, selectOne, disabled, size, false);
278 }
279
280 public static void renderListbox(FacesContext facesContext,
281 UISelectMany selectMany, boolean disabled, int size)
282 throws IOException {
283 internalRenderSelect(facesContext, selectMany, disabled, size, true);
284 }
285
286 public static void renderMenu(FacesContext facesContext,
287 UISelectOne selectOne, boolean disabled) throws IOException {
288 internalRenderSelect(facesContext, selectOne, disabled, 1, false);
289 }
290
291 public static void renderMenu(FacesContext facesContext,
292 UISelectMany selectMany, boolean disabled) throws IOException {
293 internalRenderSelect(facesContext, selectMany, disabled, 1, true);
294 }
295
296 private static void internalRenderSelect(FacesContext facesContext,
297 UIComponent uiComponent, boolean disabled, int size,
298 boolean selectMany) throws IOException {
299 ResponseWriter writer = facesContext.getResponseWriter();
300
301 writer.startElement(HTML.SELECT_ELEM, uiComponent);
302 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
303 writer.writeAttribute(HTML.NAME_ATTR, uiComponent
304 .getClientId(facesContext), null);
305
306 List selectItemList;
307 Converter converter;
308 if (selectMany) {
309 writer.writeAttribute(HTML.MULTIPLE_ATTR, HTML.MULTIPLE_ATTR, null);
310 selectItemList = org.apache.myfaces.shared.renderkit.RendererUtils
311 .getSelectItemList((UISelectMany) uiComponent);
312 converter = findUISelectManyConverterFailsafe(facesContext, uiComponent);
313 } else {
314 selectItemList = RendererUtils
315 .getSelectItemList((UISelectOne) uiComponent);
316 converter = findUIOutputConverterFailSafe(facesContext, uiComponent);
317 }
318
319 if (size == Integer.MIN_VALUE) {
320
321 writer.writeAttribute(HTML.SIZE_ATTR, Integer
322 .toString(selectItemList.size()), null);
323 } else {
324 writer.writeAttribute(HTML.SIZE_ATTR, Integer.toString(size), null);
325 }
326 renderHTMLAttributes(writer, uiComponent,
327 HTML.SELECT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
328 if (disabled) {
329 writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
330 }
331
332 if (isReadOnly(uiComponent))
333 {
334 writer.writeAttribute(HTML.READONLY_ATTR, HTML.READONLY_ATTR, null);
335 }
336
337 Set lookupSet = getSubmittedOrSelectedValuesAsSet(selectMany, uiComponent, facesContext, converter);
338
339 renderSelectOptions(facesContext, uiComponent, converter, lookupSet,
340 selectItemList);
341
342 writer.writeText("", null);
343 writer.endElement(HTML.SELECT_ELEM);
344 }
345
346 public static Set getSubmittedOrSelectedValuesAsSet(boolean selectMany, UIComponent uiComponent, FacesContext facesContext, Converter converter) {
347 Set lookupSet;
348
349 if (selectMany) {
350 UISelectMany uiSelectMany = (UISelectMany) uiComponent;
351 lookupSet = RendererUtils.getSubmittedValuesAsSet(facesContext, uiComponent, converter, uiSelectMany);
352 if (lookupSet == null)
353 {
354 lookupSet = RendererUtils.getSelectedValuesAsSet(facesContext, uiComponent, converter, uiSelectMany);
355 }
356 } else {
357 UISelectOne uiSelectOne = (UISelectOne) uiComponent;
358 Object lookup = uiSelectOne.getSubmittedValue();
359 if (lookup == null)
360 {
361 lookup = uiSelectOne.getValue();
362 String lookupString = RendererUtils.getConvertedStringValue(facesContext, uiComponent, converter, lookup);
363 lookupSet = Collections.singleton(lookupString);
364 }
365 else if(org.apache.myfaces.shared.renderkit.RendererUtils.NOTHING.equals(lookup))
366 {
367 lookupSet = Collections.EMPTY_SET;
368 }
369 else
370 {
371 lookupSet = Collections.singleton(lookup);
372 }
373 }
374 return lookupSet;
375 }
376
377 public static Converter findUISelectManyConverterFailsafe(FacesContext facesContext, UIComponent uiComponent) {
378 Converter converter;
379 try {
380 converter = RendererUtils.findUISelectManyConverter(
381 facesContext, (UISelectMany) uiComponent);
382 } catch (FacesException e) {
383 log.error("Error finding Converter for component with id "
384 + uiComponent.getClientId(facesContext), e);
385 converter = null;
386 }
387 return converter;
388 }
389
390 public static Converter findUIOutputConverterFailSafe(FacesContext facesContext, UIComponent uiComponent) {
391 Converter converter;
392 try {
393 converter = RendererUtils.findUIOutputConverter(facesContext,
394 (UIOutput) uiComponent);
395 } catch (FacesException e) {
396 log.error("Error finding Converter for component with id "
397 + uiComponent.getClientId(facesContext), e);
398 converter = null;
399 }
400 return converter;
401 }
402
403 /***
404 * Renders the select options for a <code>UIComponent</code> that is
405 * rendered as an HTML select element.
406 *
407 * @param context
408 * the current <code>FacesContext</code>.
409 * @param component
410 * the <code>UIComponent</code> whose options need to be
411 * rendered.
412 * @param converter
413 * <code>component</code>'s converter
414 * @param lookupSet
415 * the <code>Set</code> to use to look up selected options
416 * @param selectItemList
417 * the <code>List</code> of <code>SelectItem</code> s to be
418 * rendered as HTML option elements.
419 * @throws IOException
420 */
421 public static void renderSelectOptions(FacesContext context,
422 UIComponent component, Converter converter, Set lookupSet,
423 List selectItemList) throws IOException {
424 ResponseWriter writer = context.getResponseWriter();
425
426 for (Iterator it = selectItemList.iterator(); it.hasNext();) {
427 SelectItem selectItem = (SelectItem) it.next();
428
429 if (selectItem instanceof SelectItemGroup) {
430 writer.startElement(HTML.OPTGROUP_ELEM, component);
431 writer.writeAttribute(HTML.LABEL_ATTR, selectItem.getLabel(),
432 null);
433 SelectItem[] selectItems = ((SelectItemGroup) selectItem)
434 .getSelectItems();
435 renderSelectOptions(context, component, converter, lookupSet,
436 Arrays.asList(selectItems));
437 writer.endElement(HTML.OPTGROUP_ELEM);
438 } else {
439 String itemStrValue = org.apache.myfaces.shared.renderkit.RendererUtils.getConvertedStringValue(context, component,
440 converter, selectItem);
441
442 writer.write(TABULATOR);
443 writer.startElement(HTML.OPTION_ELEM, component);
444 if (itemStrValue != null) {
445 writer.writeAttribute(HTML.VALUE_ATTR, itemStrValue, null);
446 }
447
448 if (lookupSet.contains(itemStrValue)) {
449 writer.writeAttribute(HTML.SELECTED_ATTR,
450 HTML.SELECTED_ATTR, null);
451 }
452
453 boolean disabled = selectItem.isDisabled();
454 if (disabled) {
455 writer.writeAttribute(HTML.DISABLED_ATTR,
456 HTML.DISABLED_ATTR, null);
457 }
458
459 String labelClass = null;
460 boolean componentDisabled = isTrue(component.getAttributes().get("disabled"));
461
462 if (componentDisabled || disabled) {
463 labelClass = (String) component.getAttributes().get(JSFAttr.DISABLED_CLASS_ATTR);
464 } else {
465 labelClass = (String) component.getAttributes().get(JSFAttr.ENABLED_CLASS_ATTR);
466 }
467 if (labelClass != null) {
468 writer.writeAttribute("class", labelClass, "labelClass");
469 }
470
471 boolean escape;
472 if (component instanceof EscapeCapable)
473 {
474 escape = ((EscapeCapable)component).isEscape();
475
476
477
478
479
480
481 if (escape && selectItem.isEscape())
482 {
483 writer.writeText(selectItem.getLabel(), null);
484 } else
485 {
486 writer.write(selectItem.getLabel());
487 }
488 }
489 else
490 {
491 escape = RendererUtils.getBooleanAttribute(component, JSFAttr.ESCAPE_ATTR,
492 false);
493
494
495
496
497
498
499
500 if (escape || selectItem.isEscape())
501 {
502 writer.writeText(selectItem.getLabel(), null);
503 } else
504 {
505 writer.write(selectItem.getLabel());
506 }
507 }
508
509 writer.endElement(HTML.OPTION_ELEM);
510 }
511 }
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 public static void writePrettyLineSeparator(FacesContext facesContext)
543 throws IOException {
544 if (org.apache.myfaces.shared.config.MyfacesConfig.getCurrentInstance(facesContext.getExternalContext())
545 .isPrettyHtml()) {
546 facesContext.getResponseWriter().write(LINE_SEPARATOR);
547 }
548 }
549
550 public static void writePrettyIndent(FacesContext facesContext)
551 throws IOException {
552 if (org.apache.myfaces.shared.config.MyfacesConfig.getCurrentInstance(facesContext.getExternalContext())
553 .isPrettyHtml()) {
554 facesContext.getResponseWriter().write('\t');
555 }
556 }
557
558 /***
559 * @return true, if the attribute was written
560 * @throws java.io.IOException
561 */
562 public static boolean renderHTMLAttribute(ResponseWriter writer,
563 String componentProperty, String attrName, Object value)
564 throws IOException {
565 if (!RendererUtils.isDefaultAttributeValue(value)) {
566
567 String htmlAttrName =
568 attrName.equals(HTML.STYLE_CLASS_ATTR) ?
569 HTML.CLASS_ATTR : attrName;
570 writer.writeAttribute(htmlAttrName, value, componentProperty);
571 return true;
572 }
573
574 return false;
575 }
576
577 /***
578 * @return true, if the attribute was written
579 * @throws java.io.IOException
580 */
581 public static boolean renderHTMLAttribute(ResponseWriter writer,
582 UIComponent component, String componentProperty, String htmlAttrName)
583 throws IOException {
584 Object value = component.getAttributes().get(componentProperty);
585 return renderHTMLAttribute(writer, componentProperty, htmlAttrName,
586 value);
587 }
588
589 /***
590 * @return true, if an attribute was written
591 * @throws java.io.IOException
592 */
593 public static boolean renderHTMLAttributes(ResponseWriter writer,
594 UIComponent component, String[] attributes) throws IOException {
595 boolean somethingDone = false;
596 for (int i = 0, len = attributes.length; i < len; i++) {
597 String attrName = attributes[i];
598 if (renderHTMLAttribute(writer, component, attrName, attrName)) {
599 somethingDone = true;
600 }
601 }
602 return somethingDone;
603 }
604
605 public static boolean renderHTMLAttributeWithOptionalStartElement(
606 ResponseWriter writer, UIComponent component, String elementName,
607 String attrName, Object value, boolean startElementWritten)
608 throws IOException {
609 if (!org.apache.myfaces.shared.renderkit.RendererUtils.isDefaultAttributeValue(value)) {
610 if (!startElementWritten) {
611 writer.startElement(elementName, component);
612 startElementWritten = true;
613 }
614 renderHTMLAttribute(writer, attrName, attrName, value);
615 }
616 return startElementWritten;
617 }
618
619 public static boolean renderHTMLAttributesWithOptionalStartElement(
620 ResponseWriter writer, UIComponent component, String elementName,
621 String[] attributes) throws IOException {
622 boolean startElementWritten = false;
623 for (int i = 0, len = attributes.length; i < len; i++) {
624 String attrName = attributes[i];
625 Object value = component.getAttributes().get(attrName);
626 if (!RendererUtils.isDefaultAttributeValue(value)) {
627 if (!startElementWritten) {
628 writer.startElement(elementName, component);
629 startElementWritten = true;
630 }
631 renderHTMLAttribute(writer, attrName, attrName, value);
632 }
633 }
634 return startElementWritten;
635 }
636
637 public static boolean renderOptionalEndElement(ResponseWriter writer,
638 UIComponent component, String elementName, String[] attributes)
639 throws IOException {
640 boolean endElementNeeded = false;
641 for (int i = 0, len = attributes.length; i < len; i++) {
642 String attrName = attributes[i];
643 Object value = component.getAttributes().get(attrName);
644 if (!RendererUtils.isDefaultAttributeValue(value)) {
645 endElementNeeded = true;
646 break;
647 }
648 }
649 if (endElementNeeded) {
650 writer.endElement(elementName);
651 return true;
652 }
653
654 return false;
655 }
656
657 public static void writeIdIfNecessary(ResponseWriter writer, UIComponent component,
658 FacesContext facesContext)
659 throws IOException
660 {
661 if(component.getId()!=null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
662 {
663 writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext),null);
664 }
665 }
666
667 public static void writeIdAndNameIfNecessary(ResponseWriter writer, UIComponent component,
668 FacesContext facesContext)
669 throws IOException
670 {
671 if(component.getId()!=null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
672 {
673 String clientId = component.getClientId(facesContext);
674 writer.writeAttribute(HTML.ID_ATTR, clientId, null);
675 writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
676 }
677 }
678
679 public static void renderDisplayValueOnlyForSelects(FacesContext facesContext, UIComponent
680 uiComponent)
681 throws IOException
682 {
683 ResponseWriter writer = facesContext.getResponseWriter();
684
685 List selectItemList=null;
686 Converter converter=null;
687 boolean isSelectOne=false;
688
689 if(uiComponent instanceof UISelectBoolean)
690 {
691 converter = findUIOutputConverterFailSafe(facesContext, uiComponent);
692
693 writer.startElement(HTML.SPAN_ELEM, uiComponent);
694 writeIdIfNecessary(writer, uiComponent, facesContext);
695 renderDisplayValueOnlyAttributes(uiComponent, writer);
696 writer.writeText(RendererUtils.getConvertedStringValue(facesContext,uiComponent,
697 converter,((UISelectBoolean) uiComponent).getValue()),JSFAttr.VALUE_ATTR);
698 writer.endElement(HTML.SPAN_ELEM);
699
700 }
701 else
702 {
703 if (uiComponent instanceof UISelectMany) {
704 isSelectOne = false;
705 selectItemList = RendererUtils
706 .getSelectItemList((UISelectMany) uiComponent);
707 converter = findUISelectManyConverterFailsafe(facesContext, uiComponent);
708 } else if(uiComponent instanceof UISelectOne){
709 isSelectOne = true;
710 selectItemList = RendererUtils
711 .getSelectItemList((UISelectOne) uiComponent);
712 converter = findUIOutputConverterFailSafe(facesContext, uiComponent);
713 }
714
715 writer.startElement(isSelectOne ? HTML.SPAN_ELEM : HTML.UL_ELEM, uiComponent);
716 writeIdIfNecessary(writer, uiComponent, facesContext);
717
718 renderDisplayValueOnlyAttributes(uiComponent, writer);
719
720 Set lookupSet = getSubmittedOrSelectedValuesAsSet(
721 uiComponent instanceof UISelectMany,
722 uiComponent, facesContext, converter);
723
724 renderSelectOptionsAsText(facesContext, uiComponent, converter, lookupSet,
725 selectItemList, isSelectOne);
726
727
728 writer.writeText("", null);
729 writer.endElement(isSelectOne ? HTML.SPAN_ELEM : HTML.UL_ELEM);
730 }
731
732 }
733
734 public static void renderDisplayValueOnlyAttributes(UIComponent uiComponent, ResponseWriter writer) throws IOException {
735 if(!(uiComponent instanceof org.apache.myfaces.shared.component.DisplayValueOnlyCapable))
736 {
737 log.error("Wrong type of uiComponent. needs DisplayValueOnlyCapable.");
738 renderHTMLAttributes(writer, uiComponent,
739 HTML.COMMON_PASSTROUGH_ATTRIBUTES);
740
741 return;
742 }
743
744 if(getDisplayValueOnlyStyle(uiComponent) != null || getDisplayValueOnlyStyleClass(uiComponent)!=null)
745 {
746 if(getDisplayValueOnlyStyle(uiComponent) != null )
747 {
748 writer.writeAttribute(HTML.STYLE_ATTR, getDisplayValueOnlyStyle(uiComponent), null);
749 }
750 else if(uiComponent.getAttributes().get("style")!=null)
751 {
752 writer.writeAttribute(HTML.STYLE_ATTR, uiComponent.getAttributes().get("style"), null);
753 }
754
755 if(getDisplayValueOnlyStyleClass(uiComponent) != null )
756 {
757 writer.writeAttribute(HTML.CLASS_ATTR, getDisplayValueOnlyStyleClass(uiComponent), null);
758 }
759 else if(uiComponent.getAttributes().get("styleClass")!=null)
760 {
761 writer.writeAttribute(HTML.CLASS_ATTR, uiComponent.getAttributes().get("styleClass"), null);
762 }
763
764 renderHTMLAttributes(writer, uiComponent,
765 HTML.COMMON_PASSTROUGH_ATTRIBUTES_WITHOUT_STYLE);
766 }
767 else
768 {
769 renderHTMLAttributes(writer, uiComponent,
770 HTML.COMMON_PASSTROUGH_ATTRIBUTES);
771 }
772 }
773
774 private static void renderSelectOptionsAsText(FacesContext context,
775 UIComponent component, Converter converter, Set lookupSet,
776 List selectItemList, boolean isSelectOne) throws IOException {
777 ResponseWriter writer = context.getResponseWriter();
778
779 for (Iterator it = selectItemList.iterator(); it.hasNext();) {
780 SelectItem selectItem = (SelectItem) it.next();
781
782 if (selectItem instanceof SelectItemGroup) {
783 SelectItem[] selectItems = ((SelectItemGroup) selectItem)
784 .getSelectItems();
785 renderSelectOptionsAsText(context, component, converter, lookupSet,
786 Arrays.asList(selectItems), isSelectOne);
787 } else {
788 String itemStrValue = RendererUtils.getConvertedStringValue(context, component,
789 converter, selectItem);
790
791 if (lookupSet.contains(itemStrValue)) {
792
793 if( ! isSelectOne )
794 writer.startElement(HTML.LI_ELEM, component);
795 writer.writeText(selectItem.getLabel(), null);
796 if( ! isSelectOne )
797 writer.endElement(HTML.LI_ELEM);
798
799 if( isSelectOne )
800 {
801
802 return;
803 }
804 }
805 }
806 }
807 }
808
809 public static void renderTableCaption(FacesContext context,
810 ResponseWriter writer,
811 UIComponent component)
812 throws IOException
813 {
814 UIComponent captionFacet = component.getFacet("caption");
815 if (captionFacet == null) return;
816
817 String captionClass;
818 String captionStyle;
819
820 if (component instanceof HtmlPanelGrid)
821 {
822 HtmlPanelGrid panelGrid = (HtmlPanelGrid) component;
823 captionClass = panelGrid.getCaptionClass();
824 captionStyle = panelGrid.getCaptionStyle();
825 }
826 else if (component instanceof HtmlDataTable)
827 {
828 HtmlDataTable dataTable = (HtmlDataTable) component;
829 captionClass = dataTable.getCaptionClass();
830 captionStyle = dataTable.getCaptionStyle();
831 }
832 else
833 {
834 captionClass = (String)component.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.CAPTION_CLASS_ATTR);
835 captionStyle = (String)component.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.CAPTION_STYLE_ATTR);
836 }
837
838 HtmlRendererUtils.writePrettyLineSeparator(context);
839 writer.startElement(HTML.CAPTION_ELEM, component);
840
841 if (captionClass != null)
842 {
843 writer.writeAttribute(HTML.CLASS_ATTR, captionClass, null);
844 }
845
846 if (captionStyle != null)
847 {
848 writer.writeAttribute(HTML.STYLE_ATTR, captionStyle, null);
849 }
850
851 RendererUtils.renderChild(context, captionFacet);
852
853 writer.endElement(HTML.CAPTION_ELEM);
854 }
855
856 public static String getDisplayValueOnlyStyleClass(UIComponent component) {
857
858 if(component instanceof org.apache.myfaces.shared.component.DisplayValueOnlyCapable)
859 {
860 if(((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) component).getDisplayValueOnlyStyleClass()!=null)
861 return ((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) component).getDisplayValueOnlyStyleClass();
862
863 UIComponent parent=component;
864
865 while((parent = parent.getParent())!=null)
866 {
867 if(parent instanceof org.apache.myfaces.shared.component.DisplayValueOnlyCapable &&
868 ((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) parent).getDisplayValueOnlyStyleClass()!=null)
869 {
870 return ((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) parent).getDisplayValueOnlyStyleClass();
871 }
872 }
873 }
874
875 return null;
876 }
877
878 public static String getDisplayValueOnlyStyle(UIComponent component) {
879
880 if(component instanceof DisplayValueOnlyCapable)
881 {
882 if(((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) component).getDisplayValueOnlyStyle()!=null)
883 return ((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) component).getDisplayValueOnlyStyle();
884
885 UIComponent parent=component;
886
887 while((parent = parent.getParent())!=null)
888 {
889 if(parent instanceof org.apache.myfaces.shared.component.DisplayValueOnlyCapable &&
890 ((DisplayValueOnlyCapable) parent).getDisplayValueOnlyStyle()!=null)
891 {
892 return ((DisplayValueOnlyCapable) parent).getDisplayValueOnlyStyle();
893 }
894 }
895 }
896
897 return null;
898 }
899
900 public static boolean isDisplayValueOnly(UIComponent component) {
901
902 if(component instanceof DisplayValueOnlyCapable)
903 {
904 if(((DisplayValueOnlyCapable) component).isSetDisplayValueOnly())
905 return ((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) component).isDisplayValueOnly();
906
907 UIComponent parent=component;
908
909 while((parent = parent.getParent())!=null)
910 {
911 if(parent instanceof DisplayValueOnlyCapable &&
912 ((DisplayValueOnlyCapable) parent).isSetDisplayValueOnly())
913 {
914 return ((org.apache.myfaces.shared.component.DisplayValueOnlyCapable) parent).isDisplayValueOnly();
915 }
916 }
917 }
918
919 return false;
920 }
921
922 public static void renderDisplayValueOnly(FacesContext facesContext, UIInput input) throws IOException {
923 ResponseWriter writer = facesContext.getResponseWriter();
924 writer.startElement(org.apache.myfaces.shared.renderkit.html.HTML.SPAN_ELEM, input);
925
926 writeIdIfNecessary(writer, input, facesContext);
927
928 renderDisplayValueOnlyAttributes(input, writer);
929
930 String strValue = RendererUtils.getStringValue(facesContext, input);
931 writer.write( HTMLEncoder.encode(strValue, true, true) );
932
933 writer.endElement(HTML.SPAN_ELEM);
934 }
935
936 public static void appendClearHiddenCommandFormParamsFunctionCall(StringBuffer buf, String formName) {
937 appendClearHiddenCommandFormParamsFunctionCall(new ScriptContext(buf,false), formName);
938 }
939
940 private static void appendClearHiddenCommandFormParamsFunctionCall(ScriptContext context, String formName) {
941
942 String functionName = HtmlRendererUtils.getClearHiddenCommandFormParamsFunctionName(formName);
943
944 if(formName == null)
945 {
946 context.prettyLine();
947 context.append("var clearFn = ");
948 context.append(functionName);
949 context.append(";");
950 context.prettyLine();
951 context.append("if(typeof window[clearFn] =='function')");
952 context.append("{");
953 context.append("window[clearFn](formName);");
954 context.append("}");
955 }
956 else
957 {
958 context.prettyLine();
959 context.append("if(typeof window.");
960 context.append(functionName);
961 context.append("=='function')");
962 context.append("{");
963 context.append(functionName).append("('").append(formName).append("');");
964 context.append("}");
965 }
966 }
967
968
969 public static void renderFormSubmitScript(FacesContext facesContext)
970 throws IOException
971 {
972
973 Map map = facesContext.getExternalContext().getRequestMap();
974 Boolean firstScript = (Boolean) map.get(FIRST_SUBMIT_SCRIPT_ON_PAGE);
975
976 if (firstScript == null || firstScript.equals(Boolean.TRUE)) {
977 map.put(FIRST_SUBMIT_SCRIPT_ON_PAGE, Boolean.FALSE);
978 HtmlRendererUtils.renderFormSubmitScriptIfNecessary(facesContext);
979
980 }
981 }
982
983 private static void renderFormSubmitScriptIfNecessary(FacesContext facesContext) throws IOException {
984 ResponseWriter writer = facesContext.getResponseWriter();
985
986 writer.startElement(HTML.SCRIPT_ELEM, null);
987 writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
988
989 final ExternalContext externalContext = facesContext.getExternalContext();
990 final MyfacesConfig currentInstance = MyfacesConfig.getCurrentInstance(externalContext);
991 boolean autoScroll = currentInstance.isAutoScroll();
992
993 ScriptContext context = new ScriptContext(currentInstance
994 .isPrettyHtml());
995 context.prettyLine();
996 context.increaseIndent();
997
998 prepareScript(context, autoScroll);
999
1000 writer.writeText(context.toString(),null);
1001
1002 writer.endElement(HTML.SCRIPT_ELEM);
1003 }
1004
1005 private static void prepareScript(ScriptContext context, boolean autoScroll)
1006 {
1007
1008 context.prettyLine();
1009
1010
1011 context.append("function ");
1012 context.append(SET_HIDDEN_INPUT_FN_NAME).append("(formname, name, value)");
1013 context.append("{");
1014 context.append("var form = document.forms[formname];");
1015 context.prettyLine();
1016 context.append("if (typeof form == 'undefined')");
1017 context.append("{");
1018 context.append("form = document.getElementById(formname);");
1019 context.append("}");
1020 context.prettyLine();
1021 context.append("if(typeof form.elements[name]!='undefined' && (form.elements[name].nodeName=='INPUT' || form.elements[name].nodeName=='input'))");
1022 context.append("{");
1023 context.append("form.elements[name].value=value;");
1024 context.append("}");
1025 context.append("else");
1026 context.append("{");
1027 context.append("var newInput = document.createElement('input');");
1028 context.prettyLine();
1029 context.append("newInput.setAttribute('type','hidden');");
1030 context.prettyLine();
1031 context.append("newInput.setAttribute('id',name);");
1032 context.prettyLine();
1033 context.append("newInput.setAttribute('name',name);");
1034 context.prettyLine();
1035 context.append("newInput.setAttribute('value',value);");
1036 context.prettyLine();
1037 context.append("form.appendChild(newInput);");
1038 context.append("}");
1039
1040 context.append("}");
1041
1042 context.prettyLine();
1043
1044 context.prettyLine();
1045
1046
1047 context.append("function ");
1048 context.append(CLEAR_HIDDEN_INPUT_FN_NAME).append("(formname, name, value)");
1049 context.append("{");
1050 context.append("var form = document.forms[formname];");
1051 context.prettyLine();
1052 context.append("if (typeof form == 'undefined')");
1053 context.append("{");
1054 context.append("form = document.getElementById(formname);");
1055 context.append("}");
1056 context.prettyLine();
1057 context.append("var hInput = form.elements[name];");
1058 context.prettyLine();
1059 context.append("if(typeof hInput !='undefined')");
1060 context.append("{");
1061
1062 context.append("form.removeChild(hInput);");
1063 context.append("}");
1064
1065 context.append("}");
1066
1067 context.prettyLine();
1068
1069 context.append("function ");
1070 context.append(SUBMIT_FORM_FN_NAME).append("(formName, linkId, target, params)");
1071 context.append("{");
1072
1073
1074
1075
1076 HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(context, null);
1077
1078 if (autoScroll)
1079 {
1080 appendAutoScrollAssignment(context, null);
1081 }
1082
1083 context.prettyLine();
1084
1085 context.append("var form = document.forms[formName];");
1086 context.prettyLine();
1087 context.append("if (typeof form == 'undefined')");
1088 context.append("{");
1089 context.append("form = document.getElementById(formName);");
1090 context.append("}");
1091 context.prettyLine();
1092
1093 if (JavascriptUtils.isSaveFormSubmitLinkIE(FacesContext.getCurrentInstance().getExternalContext())){
1094 context.append("var agentString = navigator.userAgent.toLowerCase();");
1095 context.prettyLine();
1096
1097 context.prettyLine();
1098 context.append("if (agentString.indexOf('msie') != -1)");
1099
1100 context.append("{");
1101 context.append("if (!(agentString.indexOf('ppc') != -1 && agentString.indexOf('windows ce') != -1 && version >= 4.0))");
1102 context.append("{");
1103 context.append("window.external.AutoCompleteSaveForm(form);");
1104
1105 context.append("}");
1106
1107
1108
1109
1110
1111
1112 context.append("}");
1113
1114 context.prettyLine();
1115 }
1116
1117
1118 context.append("var oldTarget = form.target;");
1119 context.prettyLine();
1120 context.append("if(target != null)");
1121 context.append("{");
1122 context.prettyLine();
1123 context.append("form.target=target;");
1124 context.append("}");
1125
1126
1127
1128 context.append("if((typeof params!='undefined') && params != null)");
1129 context.append("{");
1130 context.prettyLine();
1131 context.append("for(var i=0, param; (param = params[i]); i++)");
1132 context.append("{");
1133 context.append(SET_HIDDEN_INPUT_FN_NAME).append("(formName,param[0], param[1]);");
1134 context.append("}");
1135 context.append("}");
1136
1137 context.prettyLine();
1138
1139 context.append(SET_HIDDEN_INPUT_FN_NAME);
1140 context.append("(formName,formName +'"+NamingContainer.SEPARATOR_CHAR+
1141 "'+'"+HtmlRendererUtils.HIDDEN_COMMANDLINK_FIELD_NAME+"',linkId);");
1142
1143 context.prettyLine();
1144 context.prettyLine();
1145
1146
1147
1148 context.append("if(form.onsubmit)");
1149 context.append("{");
1150 context.append("var result=form.onsubmit();");
1151 context.prettyLine();
1152 context.append("if((typeof result=='undefined')||result)");
1153 context.append("{");
1154 context.append("try");
1155 context.append("{");
1156 context.append("form.submit();");
1157 context.append("}");
1158 context.append("catch(e){}");
1159 context.append("}");
1160 context.append("}");
1161 context.append("else ");
1162 context.append("{");
1163 context.append("try");
1164 context.append("{");
1165 context.append("form.submit();");
1166 context.append("}");
1167 context.append("catch(e){}");
1168 context.append("}");
1169
1170
1171 context.prettyLine();
1172
1173 context.append("form.target=oldTarget;");
1174 context.prettyLine();
1175
1176
1177
1178
1179 context.append("if((typeof params!='undefined') && params != null)");
1180 context.append("{");
1181 context.prettyLine();
1182 context.append("for(var i=0, param; (param = params[i]); i++)");
1183 context.append("{");
1184 context.append(CLEAR_HIDDEN_INPUT_FN_NAME).append("(formName,param[0], param[1]);");
1185 context.append("}");
1186 context.append("}");
1187
1188 context.prettyLine();
1189
1190 context.append(CLEAR_HIDDEN_INPUT_FN_NAME);
1191 context.append("(formName,formName +'"+NamingContainer.SEPARATOR_CHAR+
1192 "'+'"+HtmlRendererUtils.HIDDEN_COMMANDLINK_FIELD_NAME+"',linkId);");
1193
1194
1195
1196 context.append("return false;");
1197 context.append("}");
1198
1199 context.prettyLineDecreaseIndent();
1200 }
1201
1202 /***
1203 * Adds the hidden form input value assignment that is necessary for the autoscroll
1204 * feature to an html link or button onclick attribute.
1205 */
1206 public static void appendAutoScrollAssignment(StringBuffer onClickValue, String formName)
1207 {
1208 appendAutoScrollAssignment(new ScriptContext(onClickValue,false),formName);
1209 }
1210
1211 private static void appendAutoScrollAssignment(ScriptContext scriptContext, String formName)
1212 {
1213 String formNameStr = formName == null? "formName" : (new StringBuffer("'").append(formName).append("'").toString());
1214 String paramName = new StringBuffer().append("'").
1215 append(AUTO_SCROLL_PARAM).append("'").toString();
1216 String value = new StringBuffer().append(AUTO_SCROLL_FUNCTION).append("()").toString();
1217
1218 scriptContext.prettyLine();
1219 scriptContext.append("if(typeof window."+AUTO_SCROLL_FUNCTION+"!='undefined')");
1220 scriptContext.append("{");
1221 scriptContext.append(SET_HIDDEN_INPUT_FN_NAME);
1222 scriptContext.append("(").append(formNameStr).append(",").append(paramName).append(",").append(value).append(");");
1223 scriptContext.append("}");
1224
1225 }
1226
1227 /***
1228 * Renders the hidden form input that is necessary for the autoscroll feature.
1229 */
1230 public static void renderAutoScrollHiddenInput(FacesContext facesContext, ResponseWriter writer) throws IOException
1231 {
1232 writePrettyLineSeparator(facesContext);
1233 writer.startElement(HTML.INPUT_ELEM, null);
1234 writer.writeAttribute(HTML.TYPE_ATTR, "hidden", null);
1235 writer.writeAttribute(HTML.NAME_ATTR, AUTO_SCROLL_PARAM, null);
1236 writer.endElement(HTML.INPUT_ELEM);
1237 writePrettyLineSeparator(facesContext);
1238 }
1239
1240 /***
1241 * Renders the autoscroll javascript function.
1242 */
1243 public static void renderAutoScrollFunction(FacesContext facesContext,
1244 ResponseWriter writer) throws IOException
1245 {
1246 writePrettyLineSeparator(facesContext);
1247 writer.startElement(HTML.SCRIPT_ELEM,null);
1248 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT,null);
1249
1250 ScriptContext script = new ScriptContext(
1251 MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isPrettyHtml());
1252
1253 script.prettyLineIncreaseIndent();
1254
1255 script.append("function ");
1256 script.append(AUTO_SCROLL_FUNCTION);
1257 script.append("()");
1258 script.append("{");
1259 script.append("var x = 0; var y = 0;");
1260 script.append( "if (self.pageXOffset || self.pageYOffset)");
1261 script.append("{");
1262 script.append("x = self.pageXOffset;");
1263 script.prettyLine();
1264 script.append("y = self.pageYOffset;");
1265 script.append("}");
1266 script.append(" else if ((document.documentElement && document.documentElement.scrollLeft)||(document.documentElement && document.documentElement.scrollTop))");
1267 script.append("{");
1268 script.append("x = document.documentElement.scrollLeft;");
1269 script.prettyLine();
1270 script.append("y = document.documentElement.scrollTop;");
1271 script.append("}");
1272 script.append(" else if (document.body) ");
1273 script.append("{");
1274 script.append("x = document.body.scrollLeft;");
1275 script.prettyLine();
1276 script.append("y = document.body.scrollTop;");
1277 script.append("}");
1278 script.append("return x + \",\" + y;");
1279 script.append("}");
1280
1281 ExternalContext externalContext = facesContext.getExternalContext();
1282 String oldViewId = JavascriptUtils.getOldViewId(externalContext);
1283 if (oldViewId != null && oldViewId.equals(facesContext.getViewRoot().getViewId()))
1284 {
1285
1286 String scrolling = (String)externalContext.getRequestParameterMap().get(AUTO_SCROLL_PARAM);
1287 if (scrolling != null && scrolling.length() > 0)
1288 {
1289 int x = 0;
1290 int y = 0;
1291 int comma = scrolling.indexOf(',');
1292 if (comma == -1)
1293 {
1294 log.warn("Illegal autoscroll request parameter: " + scrolling);
1295 }
1296 else
1297 {
1298 try {
1299
1300 x = Integer.parseInt(scrolling.substring(0, comma));
1301 } catch (NumberFormatException e) {
1302 log.warn("Error getting x offset for autoscroll feature. Bad param value: " + scrolling);
1303 x = 0;
1304 }
1305
1306 try {
1307
1308 y = Integer.parseInt(scrolling.substring(comma + 1));
1309 } catch (NumberFormatException e) {
1310 log.warn("Error getting y offset for autoscroll feature. Bad param value: " + scrolling);
1311 y = 0;
1312 }
1313 }
1314 script.append("window.scrollTo(").append(x).append(",").append(y).append(");\n");
1315 }
1316 }
1317
1318 writer.writeText(script.toString(),null);
1319
1320 writer.endElement(HTML.SCRIPT_ELEM);
1321 writePrettyLineSeparator(facesContext);
1322 }
1323
1324 public static boolean isAllowedCdataSection(FacesContext fc) {
1325 Boolean value = null;
1326
1327 if (fc != null) {
1328 value = (Boolean) fc.getExternalContext().getRequestMap().get(ALLOW_CDATA_SECTION_ON);
1329 }
1330
1331 return value != null && ((Boolean) value).booleanValue();
1332 }
1333
1334 public static void allowCdataSection(FacesContext fc, boolean cdataSectionAllowed)
1335 {
1336 fc.getExternalContext().getRequestMap().put(ALLOW_CDATA_SECTION_ON,Boolean.valueOf(cdataSectionAllowed));
1337 }
1338
1339 public static class LinkParameter {
1340 private String _name;
1341
1342 private Object _value;
1343
1344 public String getName() {
1345 return _name;
1346 }
1347
1348 public void setName(String name) {
1349 _name = name;
1350 }
1351
1352 public Object getValue() {
1353 return _value;
1354 }
1355
1356 public void setValue(Object value) {
1357 _value = value;
1358 }
1359
1360 }
1361
1362 public static void renderHiddenCommandFormParams(ResponseWriter writer,
1363 Set dummyFormParams) throws IOException {
1364 for (Iterator it = dummyFormParams.iterator(); it.hasNext();) {
1365 Object name = it.next();
1366 renderHiddenInputField(writer, name, null);
1367 }
1368 }
1369
1370 public static void renderHiddenInputField(ResponseWriter writer, Object name, Object value)
1371 throws IOException
1372 {
1373 writer.startElement(HTML.INPUT_ELEM, null);
1374 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
1375 writer.writeAttribute(HTML.NAME_ATTR, name, null);
1376 if(value!=null)
1377 {
1378 writer.writeAttribute(HTML.VALUE_ATTR,value,null);
1379 }
1380 writer.endElement(HTML.INPUT_ELEM);
1381 }
1382
1383 /***
1384 * @deprecated Replaced by
1385 * renderLabel(ResponseWriter writer,
1386 UIComponent component,
1387 String forClientId,
1388 SelectItem item,
1389 boolean disabled).
1390 * Renders a label HTML element
1391 */
1392 @Deprecated
1393 public static void renderLabel(ResponseWriter writer,
1394 UIComponent component,
1395 String forClientId,
1396 String labelValue,
1397 boolean disabled) throws IOException
1398 {
1399 writer.startElement(HTML.LABEL_ELEM, component);
1400 writer.writeAttribute(HTML.FOR_ATTR, forClientId, null);
1401
1402 String labelClass = null;
1403
1404 if (disabled)
1405 {
1406 labelClass = (String) component.getAttributes().get(JSFAttr.DISABLED_CLASS_ATTR);
1407 }
1408 else
1409 {
1410 labelClass = (String) component.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.ENABLED_CLASS_ATTR);
1411 }
1412 if (labelClass != null)
1413 {
1414 writer.writeAttribute("class", labelClass, "labelClass");
1415 }
1416
1417 if ((labelValue != null) && (labelValue.length() > 0))
1418 {
1419 writer.write(HTML.NBSP_ENTITY);
1420 writer.writeText(labelValue, null);
1421 }
1422
1423 writer.endElement(HTML.LABEL_ELEM);
1424 }
1425
1426 /***
1427 * Renders a label HTML element
1428 */
1429 public static void renderLabel(ResponseWriter writer,
1430 UIComponent component,
1431 String forClientId,
1432 SelectItem item,
1433 boolean disabled) throws IOException
1434 {
1435 writer.startElement(HTML.LABEL_ELEM, component);
1436 writer.writeAttribute(HTML.FOR_ATTR, forClientId, null);
1437
1438 String labelClass = null;
1439
1440 if (disabled)
1441 {
1442 labelClass = (String) component.getAttributes().get(JSFAttr.DISABLED_CLASS_ATTR);
1443 }
1444 else
1445 {
1446 labelClass = (String) component.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.ENABLED_CLASS_ATTR);
1447 }
1448 if (labelClass != null)
1449 {
1450 writer.writeAttribute("class", labelClass, "labelClass");
1451 }
1452
1453 if ((item.getLabel() != null) && (item.getLabel().length() > 0))
1454 {
1455 writer.write(HTML.NBSP_ENTITY);
1456 if(item.isEscape())
1457 {
1458 writer.writeText(item.getLabel(), null);
1459 }
1460 else
1461 {
1462 writer.write(item.getLabel());
1463 }
1464 }
1465
1466 writer.endElement(HTML.LABEL_ELEM);
1467 }
1468
1469 /***
1470 * Render the javascript function that is called on a click on a commandLink
1471 * to clear the hidden inputs. This is necessary because on a browser back,
1472 * each hidden input still has it's old value (browser cache!) and therefore
1473 * a new submit would cause the according action once more!
1474 *
1475 * @param writer
1476 * @param formName
1477 * @param dummyFormParams
1478 * @param formTarget
1479 * @throws IOException
1480 */
1481 public static void renderClearHiddenCommandFormParamsFunction(
1482 ResponseWriter writer, String formName, Set dummyFormParams,
1483 String formTarget) throws IOException {
1484
1485 String functionName = getClearHiddenCommandFormParamsFunctionName(formName);
1486 writer.startElement(HTML.SCRIPT_ELEM, null);
1487 writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
1488
1489
1490 StringBuffer script = new StringBuffer();
1491 script.append("function ");
1492 script.append(functionName);
1493 script.append("() {");
1494 if (dummyFormParams != null) {
1495 script.append("\n var f = document.forms['");
1496 script.append(formName);
1497 script.append("'];");
1498 int i=0;
1499 for (Iterator it = dummyFormParams.iterator(); it.hasNext();) {
1500 String elemVarName = "elem"+i;
1501 script.append("\n var ").append(elemVarName).append(" = ");
1502 script.append("f.elements['").append((String) it.next()).append("'];");
1503 script.append("\n if(typeof ").append(elemVarName).append(" !='undefined' && ");
1504 script.append(elemVarName).append(".nodeName=='INPUT'){");
1505 script.append("\n if (").append(elemVarName).append(".value != '') {");
1506 script.append("\n "+elemVarName+".value='';");
1507 script.append("\n }");
1508 script.append("\n }");
1509 i++;
1510 }
1511 }
1512
1513 script.append("\n f.target=");
1514 if (formTarget == null || formTarget.length() == 0) {
1515
1516
1517
1518 script.append("'';");
1519 } else {
1520 script.append("'");
1521 script.append(formTarget);
1522 script.append("';");
1523 }
1524 script.append("\n}");
1525
1526
1527
1528
1529 script.append("\n");
1530 script.append(functionName);
1531 script.append("();");
1532
1533 writer.writeText(script.toString(),null);
1534 writer.endElement(HTML.SCRIPT_ELEM);
1535 }
1536
1537 /***
1538 * Prefixes the given String with "clear_" and removes special characters
1539 *
1540 * @param formName
1541 * @return String
1542 */
1543 public static String getClearHiddenCommandFormParamsFunctionName(
1544 String formName)
1545 {
1546 if (formName == null)
1547 {
1548 return "'" + CLEAR_HIDDEN_FIELD_FN_NAME
1549 + "_'+formName.replace(/-/g, '//$" + NamingContainer.SEPARATOR_CHAR + "').replace(/" + NamingContainer.SEPARATOR_CHAR + "/g,'_')";
1550 }
1551
1552 return JavascriptUtils.getValidJavascriptNameAsInRI(CLEAR_HIDDEN_FIELD_FN_NAME
1553 + "_"
1554 + formName
1555 .replace(NamingContainer.SEPARATOR_CHAR, '_'));
1556 }
1557
1558 public static String getClearHiddenCommandFormParamsFunctionNameMyfacesLegacy(
1559 String formName)
1560 {
1561 return "clear_"
1562 + JavascriptUtils.getValidJavascriptName(formName, false);
1563 }
1564
1565
1566 /***
1567 * Get the name of the request parameter that holds the id of the
1568 * link-type component that caused the form to be submitted.
1569 * <p/>
1570 * Within each page there may be multiple "link" type components that
1571 * cause page submission. On the server it is necessary to know which
1572 * of these actually caused the submit, in order to invoke the correct
1573 * listeners. Such components therefore store their id into the
1574 * "hidden command link field" in their associated form before
1575 * submitting it.
1576 * <p/>
1577 * The field is always a direct child of each form, and has the same
1578 * <i>name</i> in each form. The id of the form component is therefore
1579 * both necessary and sufficient to determine the full name of the
1580 * field.
1581 */
1582 public static String getHiddenCommandLinkFieldName(FormInfo formInfo) {
1583 if (RendererUtils.isAdfOrTrinidadForm(formInfo.getForm())) {
1584 return HIDDEN_COMMANDLINK_FIELD_NAME_TRINIDAD;
1585 }
1586 return formInfo.getFormName() + NamingContainer.SEPARATOR_CHAR
1587 + HIDDEN_COMMANDLINK_FIELD_NAME;
1588 }
1589
1590 /***
1591 *
1592 * @param formInfo
1593 * @deprecated Use getHiddenCommandLinkFieldNameMyfaces(FormInfo) instead
1594 * @return
1595 */
1596 public static String getHiddenCommandLinkFieldNameMyfacesOld(FormInfo formInfo) {
1597 return formInfo.getFormName() + NamingContainer.SEPARATOR_CHAR
1598 + HIDDEN_COMMANDLINK_FIELD_NAME_MYFACES_OLD;
1599 }
1600
1601
1602 private static String HTML_CONTENT_TYPE = "text/html";
1603 private static String TEXT_ANY_CONTENT_TYPE = "text/*";
1604 private static String ANY_CONTENT_TYPE = "*/*";
1605
1606 public static String DEFAULT_CHAR_ENCODING = "ISO-8859-1";
1607 private static String XHTML_CONTENT_TYPE = "application/xhtml+xml";
1608 private static String APPLICATION_XML_CONTENT_TYPE = "application/xml";
1609 private static String TEXT_XML_CONTENT_TYPE = "text/xml";
1610
1611
1612 private static final String [] SUPPORTED_CONTENT_TYPES = {
1613 HTML_CONTENT_TYPE,
1614 XHTML_CONTENT_TYPE,
1615 APPLICATION_XML_CONTENT_TYPE,
1616 TEXT_XML_CONTENT_TYPE,
1617 TEXT_ANY_CONTENT_TYPE,
1618 ANY_CONTENT_TYPE
1619 };
1620
1621 public static String selectContentType(String contentTypeListString)
1622 {
1623 if (contentTypeListString == null)
1624 {
1625 FacesContext context = FacesContext.getCurrentInstance();
1626 if(context != null)
1627 {
1628 contentTypeListString = (String)
1629 context.getExternalContext().getRequestHeaderMap().get("Accept");
1630
1631
1632
1633
1634
1635
1636 if (contentTypeListString != null &&
1637 contentTypeListString.startsWith("application/vnd.wap.mms-message;*/*"))
1638 {
1639 contentTypeListString = "*/*";
1640 }
1641 }
1642
1643 if(contentTypeListString == null)
1644 {
1645 if (log.isDebugEnabled())
1646 log.debug("No content type list given, creating HtmlResponseWriterImpl with default content type.");
1647
1648 contentTypeListString = HTML_CONTENT_TYPE;
1649 }
1650 }
1651
1652 List contentTypeList = splitContentTypeListString(contentTypeListString);
1653 String[] supportedContentTypeArray = getSupportedContentTypes();
1654
1655 String selectedContentType = null;
1656
1657 for (int i = 0; i < supportedContentTypeArray.length; i++)
1658 {
1659 String supportedContentType = supportedContentTypeArray[i].trim();
1660
1661 for (int j = 0; j < contentTypeList.size(); j++)
1662 {
1663 String contentType = (String) contentTypeList.get(j);
1664
1665 if (contentType.indexOf(supportedContentType) != -1)
1666 {
1667 if (isHTMLContentType(contentType)) {
1668 selectedContentType = HTML_CONTENT_TYPE;
1669 }
1670
1671 else if (isXHTMLContentType(contentType)) {
1672 selectedContentType = XHTML_CONTENT_TYPE;
1673 }
1674 break;
1675 }
1676 }
1677 if (selectedContentType!=null)
1678 {
1679 break;
1680 }
1681 }
1682
1683 if(selectedContentType==null)
1684 {
1685 throw new IllegalArgumentException("ContentTypeList does not contain a supported content type: " +
1686 contentTypeListString);
1687 }
1688 return selectedContentType;
1689 }
1690
1691 public static String[] getSupportedContentTypes()
1692 {
1693
1694
1695 return SUPPORTED_CONTENT_TYPES;
1696 }
1697
1698 private static boolean isHTMLContentType(String contentType)
1699 {
1700 return contentType.indexOf(HTML_CONTENT_TYPE) != -1 ||
1701 contentType.indexOf(ANY_CONTENT_TYPE) != -1 ||
1702 contentType.indexOf(TEXT_ANY_CONTENT_TYPE) != -1 ;
1703 }
1704
1705 public static boolean isXHTMLContentType(String contentType)
1706 {
1707 return contentType.indexOf(XHTML_CONTENT_TYPE) != -1 ||
1708 contentType.indexOf(APPLICATION_XML_CONTENT_TYPE) != -1 ||
1709 contentType.indexOf(TEXT_XML_CONTENT_TYPE) != -1;
1710 }
1711
1712 private static List splitContentTypeListString(String contentTypeListString)
1713 {
1714 List contentTypeList = new ArrayList();
1715
1716 StringTokenizer st = new StringTokenizer(contentTypeListString, ",");
1717 while (st.hasMoreTokens())
1718 {
1719 String contentType = st.nextToken().trim();
1720
1721 int semicolonIndex = contentType.indexOf(";");
1722
1723 if (semicolonIndex!=-1)
1724 {
1725 contentType = contentType.substring(0,semicolonIndex);
1726 }
1727
1728 contentTypeList.add(contentType);
1729 }
1730
1731 return contentTypeList;
1732 }
1733
1734 public static String getJavascriptLocation(UIComponent component)
1735 {
1736 if(component==null)
1737 return null;
1738
1739 return (String)component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
1740 }
1741
1742 public static String getImageLocation(UIComponent component)
1743 {
1744 if(component==null)
1745 return null;
1746
1747 return (String)component.getAttributes().get(JSFAttr.IMAGE_LOCATION);
1748 }
1749
1750 public static String getStyleLocation(UIComponent component)
1751 {
1752 if(component==null)
1753 return null;
1754
1755 return (String)component.getAttributes().get(JSFAttr.STYLE_LOCATION);
1756 }
1757
1758 public static void renderViewStateJavascript(FacesContext facesContext, String hiddenId, String serializedState) throws IOException {
1759 ResponseWriter writer = facesContext.getResponseWriter();
1760
1761 writer.startElement(HTML.SCRIPT_ELEM, null);
1762 writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
1763
1764 final ExternalContext externalContext = facesContext.getExternalContext();
1765 final MyfacesConfig currentInstance = MyfacesConfig.getCurrentInstance(externalContext);
1766
1767 ScriptContext context = new ScriptContext(currentInstance.isPrettyHtml());
1768 context.prettyLine();
1769 context.increaseIndent();
1770
1771 context.append("function setViewState() {\n");
1772 context.append("\tvar state = '");
1773 context.append(serializedState);
1774 context.append("';\n");
1775 context.append("\tfor (var i = 0; i < document.forms.length; i++) {\n");
1776 context.append("\t\tdocument.forms[i]['" + hiddenId + "'].value = state;\n");
1777 context.append("\t}\n");
1778 context.append("}\n");
1779 context.append("setViewState();\n");
1780
1781 context.decreaseIndent();
1782
1783 writer.writeText(context.toString(), null);
1784
1785 writer.endElement(HTML.SCRIPT_ELEM);
1786 }
1787 /***
1788 * The ScriptContext offers methods and fields
1789 * to help with rendering out a script and keeping a
1790 * proper formatting.
1791 */
1792 public static class ScriptContext
1793 {
1794 private long currentIndentationLevel;
1795 private StringBuffer buffer = new StringBuffer();
1796 private boolean prettyPrint = false;
1797 /***
1798 * automatic formatting will render
1799 * new-lines and indents if blocks are opened
1800 * and closed - attention: you need to append
1801 * opening and closing brackets of blocks separately in this case!
1802 */
1803 private boolean automaticFormatting = true;
1804
1805 public ScriptContext()
1806 {
1807
1808 }
1809
1810 public ScriptContext(boolean prettyPrint)
1811 {
1812 this.prettyPrint = prettyPrint;
1813 }
1814
1815 public ScriptContext(StringBuffer buf, boolean prettyPrint)
1816 {
1817 this.prettyPrint = prettyPrint;
1818 this.buffer = buf;
1819 }
1820
1821 public void increaseIndent()
1822 {
1823 currentIndentationLevel++;
1824 }
1825
1826 public void decreaseIndent()
1827 {
1828 currentIndentationLevel--;
1829
1830 if(currentIndentationLevel<0)
1831 currentIndentationLevel=0;
1832 }
1833
1834 public void prettyLine()
1835 {
1836 if(prettyPrint)
1837 {
1838 append(LINE_SEPARATOR);
1839
1840 for(int i=0; i<getCurrentIndentationLevel(); i++)
1841 append(TABULATOR);
1842 }
1843 }
1844
1845 public void prettyLineIncreaseIndent()
1846 {
1847 increaseIndent();
1848 prettyLine();
1849 }
1850
1851 public void prettyLineDecreaseIndent()
1852 {
1853 decreaseIndent();
1854 prettyLine();
1855 }
1856
1857 public long getCurrentIndentationLevel()
1858 {
1859 return currentIndentationLevel;
1860 }
1861
1862 public void setCurrentIndentationLevel(long currentIndentationLevel)
1863 {
1864 this.currentIndentationLevel = currentIndentationLevel;
1865 }
1866
1867 public ScriptContext append(String str)
1868 {
1869
1870 if(automaticFormatting && str.length()==1)
1871 {
1872 boolean openBlock = str.equals("{");
1873 boolean closeBlock = str.equals("}");
1874
1875 if(openBlock)
1876 {
1877 prettyLine();
1878 }
1879 else if(closeBlock)
1880 {
1881 prettyLineDecreaseIndent();
1882 }
1883
1884 buffer.append(str);
1885
1886 if(openBlock)
1887 {
1888 prettyLineIncreaseIndent();
1889 }
1890 else if(closeBlock)
1891 {
1892 prettyLine();
1893 }
1894 }
1895 else
1896 {
1897 buffer.append(str);
1898 }
1899 return this;
1900 }
1901
1902 public ScriptContext append(char c)
1903 {
1904 buffer.append(c);
1905 return this;
1906 }
1907
1908 public ScriptContext append(int i) {
1909 buffer.append(i);
1910 return this;
1911 }
1912
1913 public String toString()
1914 {
1915 return buffer.toString();
1916 }
1917 }
1918 }