1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.renderkit.html.util;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.myfaces.tobago.component.Attributes;
24 import org.apache.myfaces.tobago.component.SupportsMarkup;
25 import org.apache.myfaces.tobago.component.SupportsRenderedPartially;
26 import org.apache.myfaces.tobago.component.UIColumnEvent;
27 import org.apache.myfaces.tobago.component.UICommand;
28 import org.apache.myfaces.tobago.component.UIForm;
29 import org.apache.myfaces.tobago.component.UIPage;
30 import org.apache.myfaces.tobago.component.UISheet;
31 import org.apache.myfaces.tobago.context.Markup;
32 import org.apache.myfaces.tobago.context.ResourceManagerUtils;
33 import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
34 import org.apache.myfaces.tobago.internal.util.Deprecation;
35 import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
36 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterWrapper;
37 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
38 import org.apache.myfaces.tobago.renderkit.css.Classes;
39 import org.apache.myfaces.tobago.renderkit.html.Command;
40 import org.apache.myfaces.tobago.renderkit.html.CommandMap;
41 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
42 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
43 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
44 import org.apache.myfaces.tobago.renderkit.html.JsonUtils;
45 import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
46 import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
47 import org.apache.myfaces.tobago.util.ComponentUtils;
48 import org.apache.myfaces.tobago.util.FacetUtils;
49 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 import javax.el.ELContext;
54 import javax.el.ValueExpression;
55 import javax.faces.component.NamingContainer;
56 import javax.faces.component.UIComponent;
57 import javax.faces.component.UIInput;
58 import javax.faces.context.FacesContext;
59 import javax.faces.context.ResponseWriter;
60 import javax.faces.model.SelectItem;
61 import javax.faces.model.SelectItemGroup;
62 import java.io.IOException;
63 import java.util.ArrayList;
64 import java.util.Arrays;
65 import java.util.List;
66 import java.util.Locale;
67 import java.util.Map;
68
69 public final class HtmlRendererUtils {
70
71 private static final Logger LOG = LoggerFactory.getLogger(HtmlRendererUtils.class);
72 private static final String ERROR_FOCUS_KEY = HtmlRendererUtils.class.getName() + ".ErrorFocusId";
73 private static final String FOCUS_KEY = HtmlRendererUtils.class.getName() + ".FocusId";
74
75 private HtmlRendererUtils() {
76
77 }
78
79 private static boolean renderErrorFocusId(final FacesContext facesContext, final UIInput input) throws IOException {
80 if (ComponentUtils.isError(input)) {
81 if (!FacesContext.getCurrentInstance().getExternalContext().getRequestMap().containsKey(ERROR_FOCUS_KEY)) {
82 FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(ERROR_FOCUS_KEY, Boolean.TRUE);
83 TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
84 String id = input.getClientId(facesContext);
85 writer.writeJavascript("Tobago.errorFocusId = '" + id + "';");
86 return true;
87 } else {
88 return true;
89 }
90 }
91 return FacesContext.getCurrentInstance().getExternalContext().getRequestMap().containsKey(ERROR_FOCUS_KEY);
92 }
93
94 public static void renderFocus(String clientId, boolean focus, boolean error, FacesContext facesContext,
95 TobagoResponseWriter writer) throws IOException {
96 final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
97 if (!requestMap.containsKey(FOCUS_KEY)
98 && (clientId.equals(FacesContextUtils.getFocusId(facesContext)) || focus || error)) {
99 requestMap.put(FOCUS_KEY, Boolean.TRUE);
100 writer.writeAttribute(HtmlAttributes.AUTOFOCUS, true);
101 }
102 }
103
104 public static void renderFocusId(final FacesContext facesContext, final UIComponent component)
105 throws IOException {
106 if (component instanceof UIInput) {
107 renderFocusId(facesContext, (UIInput) component);
108 }
109 }
110
111 public static void renderFocusId(final FacesContext facesContext, final UIInput component)
112 throws IOException {
113 if (renderErrorFocusId(facesContext, component)) {
114 return;
115 }
116 if (ComponentUtils.getBooleanAttribute(component, Attributes.FOCUS)) {
117 UIPage page = (UIPage) ComponentUtils.findPage(facesContext, component);
118 String id = component.getClientId(facesContext);
119 if (!StringUtils.isBlank(page.getFocusId()) && !page.getFocusId().equals(id)) {
120 LOG.warn("page focusId = \"" + page.getFocusId() + "\" ignoring new value \""
121 + id + "\"");
122 } else {
123 TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
124 writer.writeJavascript("Tobago.focusId = '" + id + "';");
125 }
126 }
127 }
128
129 public static void createCssClass(FacesContext facesContext, UIComponent component) {
130 String rendererName = getRendererName(facesContext, component);
131 if (rendererName != null) {
132 StyleClasses classes = StyleClasses.ensureStyleClasses(component);
133 classes.updateClassAttributeAndMarkup(component, rendererName);
134 }
135 }
136
137 public static String getRendererName(FacesContext facesContext, UIComponent component) {
138 String rendererType = component.getRendererType();
139 return rendererType.substring(0, 1).toLowerCase(Locale.ENGLISH) + rendererType.substring(1);
140 }
141
142 public static void writeLabelWithAccessKey(TobagoResponseWriter writer, LabelWithAccessKey label)
143 throws IOException {
144 int pos = label.getPos();
145 String text = label.getText();
146 if (pos == -1) {
147 writer.writeText(text);
148 } else {
149 writer.writeText(text.substring(0, pos));
150 writer.startElement(HtmlElements.U, null);
151 writer.writeText(Character.toString(text.charAt(pos)));
152 writer.endElement(HtmlElements.U);
153 writer.writeText(text.substring(pos + 1));
154 }
155 }
156
157
158 @Deprecated
159 public static void setDefaultTransition(FacesContext facesContext, boolean transition)
160 throws IOException {
161 writeScriptLoader(facesContext, null, new String[]{"Tobago.transition = " + transition + ";"});
162 }
163
164 public static void addClickAcceleratorKey(
165 FacesContext facesContext, String clientId, char key)
166 throws IOException {
167
168 }
169
170 public static void addClickAcceleratorKey(
171 FacesContext facesContext, String clientId, char key, String modifier)
172 throws IOException {
173
174
175
176 }
177
178 public static void addAcceleratorKey(
179 FacesContext facesContext, String func, char key) throws IOException {
180
181 }
182
183 public static void addAcceleratorKey(
184 FacesContext facesContext, String func, char key, String modifier)
185 throws IOException {
186 String str = createAcceleratorKeyJsStatement(func, key, modifier);
187 writeScriptLoader(facesContext, null, new String[]{str});
188 }
189
190 public static String createOnclickAcceleratorKeyJsStatement(
191 String clientId, char key, String modifier) {
192 String func = "Tobago.clickOnElement('" + clientId + "');";
193 return createAcceleratorKeyJsStatement(func, key, modifier);
194 }
195
196 public static String createAcceleratorKeyJsStatement(
197 String func, char key, String modifier) {
198 StringBuilder buffer = new StringBuilder("new Tobago.AcceleratorKey(function() {");
199 buffer.append(func);
200 if (!func.endsWith(";")) {
201 buffer.append(';');
202 }
203 buffer.append("}, \"");
204 buffer.append(key);
205 if (modifier != null) {
206 buffer.append("\", \"");
207 buffer.append(modifier);
208 }
209 buffer.append("\");");
210 return buffer.toString();
211 }
212
213
214
215
216 @Deprecated
217 public static void removeStyleAttribute(UIComponent component, String name) {
218 Deprecation.LOG.error("HtmlRendererUtils.removeStyleAttribute() no longer supported. Use setter.");
219 }
220
221 @Deprecated
222 public static void createHeaderAndBodyStyles(FacesContext facesContext, UIComponent component) {
223 Deprecation.LOG.error("HtmlRendererUtils.createHeaderAndBodyStyles() no longer supported");
224 }
225
226 @Deprecated
227 public static void createHeaderAndBodyStyles(FacesContext facesContext, UIComponent component, boolean width) {
228 Deprecation.LOG.error("HtmlRendererUtils.createHeaderAndBodyStyles() no longer supported");
229 }
230
231 public static String createSrc(String src, String ext) {
232 int dot = src.lastIndexOf('.');
233 if (dot == -1) {
234 LOG.warn("Image src without extension: '" + src + "'");
235 return src;
236 } else {
237 return src.substring(0, dot) + ext + src.substring(dot);
238 }
239 }
240
241 public static TobagoResponseWriter getTobagoResponseWriter(FacesContext facesContext) {
242
243 ResponseWriter writer = facesContext.getResponseWriter();
244 if (writer instanceof TobagoResponseWriter) {
245 return (TobagoResponseWriter) writer;
246 } else {
247 return new TobagoResponseWriterWrapper(writer);
248 }
249 }
250
251 public static void writeScriptLoader(FacesContext facesContext, String script)
252 throws IOException {
253 writeScriptLoader(facesContext, new String[]{script}, null);
254 }
255
256 public static void writeScriptLoader(FacesContext facesContext, String[] scripts, String[] afterLoadCmds)
257 throws IOException {
258 TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
259 if (scripts != null) {
260 LOG.error("Scripts argument for writeScriptLoader not supported anymore!");
261 }
262 String allScripts = "[]";
263 if (scripts != null) {
264 allScripts = ResourceManagerUtils.getScriptsAsJSArray(facesContext, scripts);
265 }
266 boolean ajax = FacesContextUtils.isAjax(facesContext);
267 writer.startJavascript();
268
269 if (ajax || scripts != null) {
270 writer.write("new Tobago.ScriptLoader(");
271 if (!ajax) {
272 writer.write("\n ");
273 }
274 writer.write(allScripts);
275
276 if (afterLoadCmds != null && afterLoadCmds.length > 0) {
277 writer.write(", ");
278 if (!ajax) {
279 writer.write("\n");
280 }
281 boolean first = true;
282 for (String afterLoadCmd : afterLoadCmds) {
283 String[] splittedStrings = StringUtils.split(afterLoadCmd, '\n');
284 for (String splitted : splittedStrings) {
285 writer.write(first ? " " : " + ");
286 writer.write("\"");
287 String cmd = StringUtils.replace(splitted, "\\", "\\\\");
288 cmd = StringUtils.replace(cmd, "\"", "\\\"");
289 writer.write(cmd);
290 writer.write("\"");
291 if (!ajax) {
292 writer.write("\n");
293 }
294 first = false;
295 }
296 }
297 }
298 writer.write(");");
299 } else {
300 for (String afterLoadCmd : afterLoadCmds) {
301 writer.write(afterLoadCmd);
302 }
303 }
304 writer.endJavascript();
305 }
306
307 public static void writeStyleLoader(
308 FacesContext facesContext, String[] styles) throws IOException {
309 TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
310
311 writer.startJavascript();
312 writer.write("Tobago.ensureStyleFiles(");
313 writer.write(ResourceManagerUtils.getStylesAsJSArray(facesContext, styles));
314 writer.write(");");
315 writer.endJavascript();
316 }
317
318 public static String getTitleFromTipAndMessages(FacesContext facesContext, UIComponent component) {
319 String messages = ComponentUtils.getFacesMessageAsString(facesContext, component);
320 return HtmlRendererUtils.addTip(messages, component.getAttributes().get(Attributes.TIP));
321 }
322
323 public static String addTip(String title, Object tip) {
324 if (tip != null) {
325 if (title != null && title.length() > 0) {
326 title += " :: ";
327 } else {
328 title = "";
329 }
330 title += tip;
331 }
332 return title;
333 }
334
335 public static void renderSelectItems(UIInput component, List<SelectItem> items, Object[] values,
336 TobagoResponseWriter writer, FacesContext facesContext) throws IOException {
337 renderSelectItems(component, items, values, null, writer, facesContext);
338
339 }
340
341 public static void renderSelectItems(UIInput component, List<SelectItem> items, Object[] values, Boolean onlySelected,
342 TobagoResponseWriter writer, FacesContext facesContext) throws IOException {
343
344 if (LOG.isDebugEnabled()) {
345 LOG.debug("value = '" + Arrays.toString(values) + "'");
346 }
347 for (SelectItem item : items) {
348 if (item instanceof SelectItemGroup) {
349 writer.startElement(HtmlElements.OPTGROUP, null);
350 writer.writeAttribute(HtmlAttributes.LABEL, item.getLabel(), true);
351 if (item.isDisabled()) {
352 writer.writeAttribute(HtmlAttributes.DISABLED, true);
353 }
354 SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems();
355 renderSelectItems(component, Arrays.asList(selectItems), values, onlySelected, writer, facesContext);
356 writer.endElement(HtmlElements.OPTGROUP);
357 } else {
358
359 Object itemValue = item.getValue();
360
361 if (itemValue instanceof String && values != null && values.length > 0 && !(values[0] instanceof String)) {
362 itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
363 }
364 boolean contains = RenderUtils.contains(values, itemValue);
365 if (onlySelected != null) {
366 if (onlySelected) {
367 if (!contains) {
368 continue;
369 }
370 } else {
371 if (contains) {
372 continue;
373 }
374 }
375 }
376 writer.startElement(HtmlElements.OPTION, null);
377 String formattedValue = RenderUtils.getFormattedValue(facesContext, component, itemValue);
378 writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
379 if (item instanceof org.apache.myfaces.tobago.model.SelectItem) {
380 String image = ((org.apache.myfaces.tobago.model.SelectItem) item).getImage();
381 if (image != null) {
382 String imagePath = ResourceManagerUtils.getImageWithPath(facesContext, image);
383 writer.writeStyleAttribute("background-image: url('" + imagePath + "')");
384 }
385 }
386 Markup markup = item instanceof SupportsMarkup ? ((SupportsMarkup) item).getMarkup() : Markup.NULL;
387 if (onlySelected == null && contains) {
388 writer.writeAttribute(HtmlAttributes.SELECTED, true);
389 markup = Markup.SELECTED.add(markup);
390 }
391 if (item.isDisabled()) {
392 writer.writeAttribute(HtmlAttributes.DISABLED, true);
393 markup = Markup.DISABLED.add(markup);
394 }
395 writer.writeClassAttribute(Classes.create(component, "option", markup));
396
397 writer.writeText(item.getLabel());
398 writer.endElement(HtmlElements.OPTION);
399 }
400 }
401 }
402
403 public static String getComponentIds(FacesContext context, UIComponent component, String[] componentId) {
404 StringBuilder sb = new StringBuilder();
405 for (String id : componentId) {
406 if (!StringUtils.isBlank(id)) {
407 if (sb.length() > 0) {
408 sb.append(",");
409 }
410 String clientId = getComponentId(context, component, id);
411 if (clientId != null) {
412 sb.append(clientId);
413 }
414 }
415 }
416 return sb.toString();
417 }
418
419 public static String[] getComponentIdsAsList(
420 FacesContext context, UIComponent component, String[] componentId) {
421 List<String> result = new ArrayList<String>(componentId.length);
422 for (String id : componentId) {
423 if (!StringUtils.isBlank(id)) {
424 String clientId = getComponentId(context, component, id);
425 if (clientId != null) {
426 result.add(clientId);
427 }
428 }
429 }
430 return (String[]) result.toArray(new String[result.size()]);
431 }
432
433 public static String getComponentId(FacesContext context, UIComponent component, String componentId) {
434 UIComponent partiallyComponent = ComponentUtils.findComponent(component, componentId);
435 if (partiallyComponent != null) {
436 String clientId = partiallyComponent.getClientId(context);
437 if (partiallyComponent instanceof UISheet) {
438 int rowIndex = ((UISheet) partiallyComponent).getRowIndex();
439 if (rowIndex >= 0 && clientId.endsWith(Integer.toString(rowIndex))) {
440 return clientId.substring(0, clientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR));
441 }
442 }
443 return clientId;
444 }
445 LOG.error("No Component found for id " + componentId + " search base component " + component.getClientId(context));
446 return null;
447 }
448
449
450
451
452 @Deprecated
453 public static String toStyleString(String key, Integer value) {
454 StringBuilder buf = new StringBuilder();
455 buf.append(key);
456 buf.append(":");
457 buf.append(value);
458 buf.append("px; ");
459 return buf.toString();
460 }
461
462
463
464
465 @Deprecated
466 public static String toStyleString(String key, String value) {
467 StringBuilder buf = new StringBuilder();
468 buf.append(key);
469 buf.append(":");
470 buf.append(value);
471 buf.append("; ");
472 return buf.toString();
473 }
474
475
476
477
478 @Deprecated
479 public static void renderTip(UIComponent component, TobagoResponseWriter writer) throws IOException {
480 Object objTip = component.getAttributes().get(Attributes.TIP);
481 if (objTip != null) {
482 String tip = String.valueOf(objTip);
483 writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
484 }
485 }
486
487
488
489
490 public static void renderImageTip(UIComponent component, TobagoResponseWriter writer) throws IOException {
491 Object objTip = component.getAttributes().get(Attributes.TIP);
492 if (objTip != null) {
493 String tip = String.valueOf(objTip);
494 writer.writeAttribute(HtmlAttributes.ALT, tip, true);
495 } else {
496 writer.writeAttribute(HtmlAttributes.ALT, "", false);
497 }
498 }
499
500 public static String getJavascriptString(String str) {
501 if (str != null) {
502 return "\"" + str + "\"";
503 }
504 return null;
505 }
506
507 public static String getRenderedPartiallyJavascriptArray(FacesContext facesContext, UICommand command) {
508 if (command == null) {
509 return null;
510 }
511 return getRenderedPartiallyJavascriptArray(facesContext, command, command);
512 }
513
514 public static String getRenderedPartiallyJavascriptArray(FacesContext facesContext, UIComponent searchBase,
515 SupportsRenderedPartially supportsRenderedPartially) {
516 String[] list = supportsRenderedPartially.getRenderedPartially();
517 if (list == null || list.length == 0) {
518 return null;
519 }
520 StringBuilder strBuilder = new StringBuilder();
521 strBuilder.append("[");
522 for (int i = 0; i < list.length; i++) {
523 if (i != 0) {
524 strBuilder.append(",");
525 }
526 strBuilder.append("\"");
527 strBuilder.append(HtmlRendererUtils.getComponentId(facesContext, searchBase, list[i]));
528 strBuilder.append("\"");
529 }
530 strBuilder.append("]");
531 return strBuilder.toString();
532 }
533
534 public static String getJavascriptArray(String[] list) {
535 StringBuilder strBuilder = new StringBuilder();
536 strBuilder.append("[");
537 for (int i = 0; i < list.length; i++) {
538 if (i != 0) {
539 strBuilder.append(",");
540 }
541 strBuilder.append("\"");
542 strBuilder.append(list[i]);
543 strBuilder.append("\"");
544 }
545 strBuilder.append("]");
546 return strBuilder.toString();
547 }
548
549 public static void renderDojoDndSource(FacesContext context, UIComponent component)
550 throws IOException {
551 Object objDojoType = component.getAttributes().get("dojoType");
552 if (null != objDojoType && (objDojoType.equals("dojo.dnd.Source") || objDojoType.equals("dojo.dnd.Target"))) {
553 FacesContextUtils.addOnloadScript(context, createDojoDndType(component,
554 component.getClientId(context), String.valueOf(objDojoType)));
555 }
556 }
557
558 public static void renderDojoDndItem(UIComponent component, TobagoResponseWriter writer, boolean addStyle)
559 throws IOException {
560 Object objDndType = component.getAttributes().get("dndType");
561 if (objDndType != null) {
562 writer.writeAttribute("dndType", String.valueOf(objDndType), false);
563 }
564 Object objDndData = component.getAttributes().get("dndData");
565 if (objDndData != null) {
566 writer.writeAttribute("dndData", String.valueOf(objDndData), false);
567 }
568 if (addStyle && (null != objDndType || null != objDndData)) {
569 StyleClasses styles = StyleClasses.ensureStyleClasses(component);
570 styles.addFullQualifiedClass("dojoDndItem");
571 }
572 }
573
574 private static String createDojoDndType(UIComponent component, String clientId, String dojoType) {
575 StringBuilder strBuilder = new StringBuilder();
576 strBuilder.append("new ").append(dojoType).append("('").append(clientId).append("'");
577 StringBuilder parameter = new StringBuilder();
578
579 Object objHorizontal = component.getAttributes().get("horizontal");
580 if (objHorizontal != null) {
581 parameter.append("horizontal: ").append(String.valueOf(objHorizontal)).append(",");
582 }
583 Object objCopyOnly = component.getAttributes().get("copyOnly");
584 if (objCopyOnly != null) {
585 parameter.append("copyOnly: ").append(String.valueOf(objCopyOnly)).append(",");
586 }
587 Object objSkipForm = component.getAttributes().get("skipForm");
588 if (objSkipForm != null) {
589 parameter.append("skipForm: ").append(String.valueOf(objSkipForm)).append(",");
590 }
591 Object objWithHandles = component.getAttributes().get("withHandles");
592 if (objWithHandles != null) {
593 parameter.append("withHandles: ").append(String.valueOf(objWithHandles)).append(",");
594 }
595 Object objAccept = component.getAttributes().get("accept");
596 if (objAccept != null) {
597 String accept = null;
598 if (objAccept instanceof String[]) {
599 String[] allowed = (String[]) objAccept;
600 if (allowed.length > 1) {
601
602 accept = "'" + allowed[0] + "'";
603 for (int i = 1; i < allowed.length; i++) {
604 accept += ",'" + allowed[i] + "'";
605 }
606 }
607 } else {
608 accept = (String) objAccept;
609 }
610 parameter.append("accept: [").append(accept).append("],");
611 }
612 Object objSingular = component.getAttributes().get("singular");
613 if (objSingular != null) {
614 parameter.append("singular: ").append(String.valueOf(objSingular)).append(",");
615 }
616 Object objCreator = component.getAttributes().get("creator");
617 if (objCreator != null) {
618 parameter.append("creator: ").append(String.valueOf(objCreator)).append(",");
619 }
620 if (parameter.length() > 0) {
621 parameter.deleteCharAt(parameter.lastIndexOf(","));
622 strBuilder.append(",{").append(parameter).append("}");
623 }
624 strBuilder.append(");");
625 return strBuilder.toString();
626 }
627
628
629 public static void renderCommandFacet(UIComponent component, FacesContext facesContext,
630 TobagoResponseWriter writer) throws IOException {
631 renderCommandFacet(component, component.getClientId(facesContext), facesContext, writer);
632 }
633
634 public static void renderCommandFacet(
635 UIComponent component, String id, FacesContext facesContext, TobagoResponseWriter writer) throws IOException {
636 if (ComponentUtils.getBooleanAttribute(component, Attributes.READONLY)
637 || ComponentUtils.getBooleanAttribute(component, Attributes.DISABLED)) {
638 return;
639 }
640 CommandMap commandMap = null;
641 Map<String, UIComponent> facets = component.getFacets();
642 for (Map.Entry<String, UIComponent> entry : facets.entrySet()) {
643 UIComponent facetComponent = entry.getValue();
644 if (facetComponent.isRendered()
645 && (facetComponent instanceof AbstractUICommand || facetComponent instanceof UIForm)) {
646 if (commandMap == null) {
647 commandMap = new CommandMap();
648 }
649 String key = entry.getKey();
650 commandMap.addCommand(key, new Command(facesContext, entry.getValue(), id));
651 }
652 }
653 if (commandMap != null) {
654 writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(commandMap), true);
655 }
656 }
657
658 public static boolean renderSheetCommands(UISheet sheet, FacesContext facesContext,
659 TobagoResponseWriter writer) throws IOException {
660 CommandMap commandMap = null;
661 for (UIComponent child : sheet.getChildren()) {
662 if (child instanceof UIColumnEvent) {
663 UIColumnEvent columnEvent = (UIColumnEvent) child;
664 if (columnEvent.isRendered()) {
665 UIComponent selectionChild = child.getChildren().get(0);
666 if (selectionChild != null && selectionChild instanceof AbstractUICommand && selectionChild.isRendered()) {
667 UICommand action = (UICommand) selectionChild;
668 if (commandMap == null) {
669 commandMap = new CommandMap();
670 }
671 commandMap.addCommand(columnEvent.getEvent(), new Command(facesContext, action, null));
672 }
673 }
674 }
675 }
676 if (commandMap != null) {
677 writer.writeAttribute(DataAttributes.ROWACTION, JsonUtils.encode(commandMap), true);
678 return true;
679 }
680 return false;
681 }
682
683
684 public static void checkForCommandFacet(UIComponent component, FacesContext facesContext, TobagoResponseWriter writer)
685 throws IOException {
686 checkForCommandFacet(component, Arrays.asList(component.getClientId(facesContext)), facesContext, writer);
687 }
688
689 public static void checkForCommandFacet(UIComponent component, List<String> clientIds, FacesContext facesContext,
690 TobagoResponseWriter writer) throws IOException {
691 if (ComponentUtils.getBooleanAttribute(component, Attributes.READONLY)
692 || ComponentUtils.getBooleanAttribute(component, Attributes.DISABLED)) {
693 return;
694 }
695 Map<String, UIComponent> facets = component.getFacets();
696 for (Map.Entry<String, UIComponent> entry : facets.entrySet()) {
697 if (entry.getValue() instanceof UICommand) {
698 addCommandFacet(clientIds, entry, facesContext, writer);
699 }
700 }
701 }
702
703 private static void addCommandFacet(
704 List<String> clientIds, Map.Entry<String, UIComponent> facetEntry,
705 FacesContext facesContext, TobagoResponseWriter writer)
706 throws IOException {
707 for (String clientId : clientIds) {
708 writeScriptForClientId(clientId, facetEntry, facesContext, writer);
709 }
710 }
711
712
713
714
715 @Deprecated
716 private static void writeScriptForClientId(
717 String clientId, Map.Entry<String, UIComponent> facetEntry,
718 FacesContext facesContext, TobagoResponseWriter writer) throws IOException {
719 if (facetEntry.getValue() instanceof UICommand
720 && ((UICommand) facetEntry.getValue()).getRenderedPartially().length > 0) {
721 writer.startJavascript();
722 writer.write("var element = Tobago.element(\"");
723 writer.write(clientId);
724 writer.write("\");\n");
725 writer.write("if (element) {\n");
726 writer.write(" Tobago.addEventListener(element, \"");
727 writer.write(facetEntry.getKey());
728 writer.write("\", function(){Tobago.reloadComponent(this, '");
729 writer.write(HtmlRendererUtils.getComponentIds(facesContext, facetEntry.getValue(),
730 ((UICommand) facetEntry.getValue()).getRenderedPartially()));
731 writer.write("','");
732 writer.write(facetEntry.getValue().getClientId(facesContext));
733 writer.write("', {})});\n");
734 writer.write("};");
735 writer.endJavascript();
736 } else {
737 UIComponent facetComponent = facetEntry.getValue();
738
739 writer.startJavascript();
740 writer.write("var element = Tobago.element(\"");
741 writer.write(clientId + "\");\n");
742 writer.write("if (element) {\n");
743 writer.write(" Tobago.addEventListener(element, \"");
744 writer.write(facetEntry.getKey());
745 writer.write("\", function(){");
746 String facetAction = (String) facetComponent.getAttributes().get(Attributes.ONCLICK);
747 if (facetAction != null) {
748
749 facetAction = StringUtils.replace(facetAction, "@autoId", facetComponent.getClientId(facesContext));
750 writer.write(facetAction);
751 } else {
752 writer.write(createSubmitAction(
753 facetComponent.getClientId(facesContext),
754 ComponentUtils.getBooleanAttribute(facetComponent, Attributes.TRANSITION),
755 null,
756 clientId));
757 }
758 writer.write("});\n};");
759 writer.endJavascript();
760 }
761 }
762
763
764
765
766 @Deprecated
767 public static String createSubmitAction(String clientId, boolean transition, String target, String focus) {
768 StringBuilder builder = new StringBuilder();
769 builder.append("Tobago.submitAction(this,'");
770 builder.append(clientId);
771 builder.append("',{");
772 if (!transition) {
773 builder.append("transition:false");
774 if (target != null || focus != null) {
775 builder.append(',');
776 }
777 }
778 if (target != null) {
779 builder.append("target:'");
780 builder.append(target);
781 builder.append('\'');
782 if (focus != null) {
783 builder.append(',');
784 }
785 }
786 if (focus != null) {
787 builder.append("focus:'");
788 builder.append(focus);
789 builder.append('\'');
790 }
791 builder.append("});");
792 return builder.toString();
793 }
794
795
796
797
798 @Deprecated
799 public static void removeStyleClasses(UIComponent cell) {
800 Object obj = cell.getAttributes().get(Attributes.STYLE_CLASS);
801 if (obj != null && obj instanceof StyleClasses && cell.getRendererType() != null) {
802 StyleClasses styleClasses = (StyleClasses) obj;
803 if (!styleClasses.isEmpty()) {
804 String rendererName = cell.getRendererType().substring(0, 1).toLowerCase(Locale.ENGLISH)
805 + cell.getRendererType().substring(1);
806 styleClasses.removeTobagoClasses(rendererName);
807 }
808 if (styleClasses.isEmpty()) {
809 cell.getAttributes().remove(Attributes.STYLE_CLASS);
810 }
811 }
812 }
813
814 public static void encodeContextMenu(FacesContext facesContext, TobagoResponseWriter writer, UIComponent parent)
815 throws IOException {
816 final UIComponent contextMenu = FacetUtils.getContextMenu(parent);
817 if (contextMenu != null) {
818 writer.startElement(HtmlElements.OL, contextMenu);
819 writer.writeClassAttribute("tobago-menuBar tobago-menu-contextMenu");
820 RenderUtils.encode(facesContext, contextMenu);
821 writer.endElement(HtmlElements.OL);
822 }
823 }
824
825 public static void addAcceleratorKey(FacesContext facesContext, UIComponent component, Character accessKey) {
826 String clientId = component.getClientId(facesContext);
827 String jsStatement = createOnclickAcceleratorKeyJsStatement(clientId, accessKey, null);
828 FacesContextUtils.addMenuAcceleratorScript(facesContext, jsStatement);
829 }
830
831 public static void writeDataAttributes(
832 FacesContext context, TobagoResponseWriter writer, UIComponent component)
833 throws IOException {
834
835 final Map<Object, Object> dataAttributes = ComponentUtils.getDataAttributes(component);
836 if (dataAttributes == null) {
837 return;
838 }
839
840 final ELContext elContext = context.getELContext();
841
842 for (Map.Entry<Object, Object> entry : dataAttributes.entrySet()) {
843 final Object mapKey = entry.getKey();
844 final String name = mapKey instanceof ValueExpression
845 ? ((ValueExpression) mapKey).getValue(elContext).toString() : mapKey.toString();
846 final Object mapValue = entry.getValue();
847 final String value = mapValue instanceof ValueExpression
848 ? ((ValueExpression) mapValue).getValue(elContext).toString() : mapValue.toString();
849 writer.writeAttribute("data-" + name, value, true);
850 }
851 }
852 }