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.internal.util;
21
22 import org.apache.myfaces.tobago.component.Attributes;
23 import org.apache.myfaces.tobago.component.RendererTypes;
24 import org.apache.myfaces.tobago.component.Tags;
25 import org.apache.myfaces.tobago.component.Visual;
26 import org.apache.myfaces.tobago.context.Markup;
27 import org.apache.myfaces.tobago.internal.component.AbstractUIStyle;
28 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
29 import org.apache.myfaces.tobago.renderkit.css.Icons;
30 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
31 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
32 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
33 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
34 import org.apache.myfaces.tobago.util.ComponentUtils;
35 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import javax.el.ELContext;
40 import javax.el.ValueExpression;
41 import javax.faces.component.UIComponent;
42 import javax.faces.component.UIInput;
43 import javax.faces.context.FacesContext;
44 import javax.faces.model.SelectItem;
45 import javax.faces.model.SelectItemGroup;
46 import java.io.IOException;
47 import java.lang.invoke.MethodHandles;
48 import java.util.Arrays;
49 import java.util.Locale;
50 import java.util.Map;
51
52 public final class HtmlRendererUtils {
53
54 private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
55
56 private HtmlRendererUtils() {
57
58 }
59
60 public static String getRendererName(final FacesContext facesContext, final UIComponent component) {
61 final String rendererType = component.getRendererType();
62 return rendererType.substring(0, 1).toLowerCase(Locale.ENGLISH) + rendererType.substring(1);
63 }
64
65 public static void writeLabelWithAccessKey(final TobagoResponseWriter writer, final LabelWithAccessKey label)
66 throws IOException {
67 final int pos = label.getPos();
68 final String text = label.getLabel();
69 if (text != null) {
70 if (pos == -1) {
71 writer.writeText(text);
72 } else {
73 writer.writeText(text.substring(0, pos));
74 writer.startElement(HtmlElements.U);
75 writer.writeText(Character.toString(text.charAt(pos)));
76 writer.endElement(HtmlElements.U);
77 writer.writeText(text.substring(pos + 1));
78 }
79 }
80 }
81
82 public static void encodeIconOrImage(final TobagoResponseWriter writer, final String image) throws IOException {
83 if (image != null) {
84 if (image.startsWith("fa-")) {
85 writer.startElement(HtmlElements.I);
86 writer.writeClassAttribute(Icons.FA, Icons.custom(image));
87 writer.endElement(HtmlElements.I);
88 } else {
89 writer.startElement(HtmlElements.IMG);
90 writer.writeAttribute(HtmlAttributes.SRC, image, true);
91 writer.writeAttribute(HtmlAttributes.ALT, "", false);
92 writer.endElement(HtmlElements.IMG);
93 }
94 }
95 }
96
97 public static String getTitleFromTipAndMessages(final FacesContext facesContext, final UIComponent component) {
98 final String messages = ComponentUtils.getFacesMessageAsString(facesContext, component);
99 return HtmlRendererUtils.addTip(messages, ComponentUtils.getAttribute(component, Attributes.tip));
100 }
101
102 public static String addTip(final String title, final Object tip) {
103 String result = title;
104 if (tip != null) {
105 if (result != null && result.length() > 0) {
106 result += " :: ";
107 } else {
108 result = "";
109 }
110 result += tip;
111 }
112 return result;
113 }
114
115 public static void renderSelectItems(final UIInput component, final TobagoClass optionClass,
116 final Iterable<SelectItem> items, final Object[] values, final String[] submittedValues,
117 final TobagoResponseWriter writer, final FacesContext facesContext) throws IOException {
118 renderSelectItems(component, optionClass, items, values, submittedValues, null, writer, facesContext);
119 }
120
121 public static void renderSelectItems(final UIInput component, final TobagoClass optionClass,
122 final Iterable<SelectItem> items, final Object value, final String submittedValue,
123 final TobagoResponseWriter writer, final FacesContext facesContext) throws IOException {
124 renderSelectItems(component, optionClass, items, value != null ? new Object[]{value} : null,
125 submittedValue != null ? new String[]{submittedValue} : null, null, writer, facesContext);
126 }
127
128 public static void renderSelectItems(final UIInput component, final TobagoClass optionClass,
129 final Iterable<SelectItem> items, final Object[] values, final String[] submittedValues,
130 final Boolean onlySelected, final TobagoResponseWriter writer, final FacesContext facesContext)
131 throws IOException {
132
133 if (LOG.isDebugEnabled()) {
134 LOG.debug("component id = '{}'", component.getId());
135 LOG.debug("values = '{}'", Arrays.toString(values));
136 LOG.debug("submittedValues = '{}'", Arrays.toString(submittedValues));
137 }
138 for (final SelectItem item : items) {
139 if (item instanceof SelectItemGroup) {
140 writer.startElement(HtmlElements.OPTGROUP);
141 writer.writeAttribute(HtmlAttributes.LABEL, item.getLabel(), true);
142 if (item.isDisabled()) {
143 writer.writeAttribute(HtmlAttributes.DISABLED, true);
144 }
145 final SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems();
146 renderSelectItems(component, optionClass, Arrays.asList(selectItems), values, submittedValues,
147 onlySelected, writer, facesContext);
148 writer.endElement(HtmlElements.OPTGROUP);
149 } else {
150
151 Object itemValue = item.getValue();
152
153 if (itemValue instanceof String && values != null && values.length > 0 && !(values[0] instanceof String)) {
154 itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
155 }
156 final String formattedValue = ComponentUtils.getFormattedValue(facesContext, component, itemValue);
157 final boolean contains;
158 if (submittedValues == null) {
159 contains = ArrayUtils.contains(values, itemValue);
160 } else {
161 contains = ArrayUtils.contains(submittedValues, formattedValue);
162 }
163 if (onlySelected != null) {
164 if (onlySelected) {
165 if (!contains) {
166 continue;
167 }
168 } else {
169 if (contains) {
170 continue;
171 }
172 }
173 }
174 writer.startElement(HtmlElements.OPTION);
175 writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
176 if (item instanceof org.apache.myfaces.tobago.model.SelectItem) {
177 final String image = ((org.apache.myfaces.tobago.model.SelectItem) item).getImage();
178 if (image != null) {
179 final AbstractUIStyle style = (AbstractUIStyle) facesContext.getApplication()
180 .createComponent(facesContext, Tags.style.componentType(), RendererTypes.Style.name());
181 style.setTransient(true);
182 style.setBackgroundImage(image);
183 style.setSelector(
184 StyleRenderUtils.encodeIdSelector(component.getClientId(facesContext))
185 + " option[value=" + formattedValue + "]");
186
187 component.getChildren().add(style);
188 }
189 }
190 Markup markup = item instanceof Visual ? ((Visual) item).getMarkup() : Markup.NULL;
191 if (onlySelected == null && contains) {
192 writer.writeAttribute(HtmlAttributes.SELECTED, true);
193 markup = Markup.SELECTED.add(markup);
194 }
195 if (item.isDisabled()) {
196 writer.writeAttribute(HtmlAttributes.DISABLED, true);
197 markup = Markup.DISABLED.add(markup);
198 }
199 writer.writeClassAttribute(optionClass, optionClass.createMarkup(markup));
200
201 writer.writeText(item.getLabel());
202 writer.endElement(HtmlElements.OPTION);
203 }
204 }
205 }
206
207 public static void writeDataAttributes(
208 final FacesContext context, final TobagoResponseWriter writer, final UIComponent component)
209 throws IOException {
210
211 final Map<Object, Object> dataAttributes = ComponentUtils.getDataAttributes(component);
212 if (dataAttributes == null) {
213 return;
214 }
215
216 final ELContext elContext = context.getELContext();
217
218 for (final Map.Entry<Object, Object> entry : dataAttributes.entrySet()) {
219 final Object mapKey = entry.getKey();
220 final String name = mapKey instanceof ValueExpression
221 ? ((ValueExpression) mapKey).getValue(elContext).toString() : mapKey.toString();
222 final Object mapValue = entry.getValue();
223 final String value = mapValue instanceof ValueExpression
224 ? ((ValueExpression) mapValue).getValue(elContext).toString() : mapValue.toString();
225 writer.writeAttribute(DataAttributes.dynamic(name), value, true);
226 }
227 }
228 }