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.scarborough.standard.tag;
21
22 import org.apache.myfaces.tobago.component.Attributes;
23 import org.apache.myfaces.tobago.component.Facets;
24 import org.apache.myfaces.tobago.component.RendererTypes;
25 import org.apache.myfaces.tobago.component.UIMenuCommand;
26 import org.apache.myfaces.tobago.component.UISelectBooleanCheckbox;
27 import org.apache.myfaces.tobago.context.Markup;
28 import org.apache.myfaces.tobago.context.ResourceManagerUtils;
29 import org.apache.myfaces.tobago.internal.util.AccessKeyMap;
30 import org.apache.myfaces.tobago.layout.Measure;
31 import org.apache.myfaces.tobago.renderkit.CommandRendererBase;
32 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
33 import org.apache.myfaces.tobago.renderkit.css.Classes;
34 import org.apache.myfaces.tobago.renderkit.css.Style;
35 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
36 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
37 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
38 import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
39 import org.apache.myfaces.tobago.renderkit.html.util.CommandRendererHelper;
40 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
41 import org.apache.myfaces.tobago.renderkit.util.JQueryUtils;
42 import org.apache.myfaces.tobago.renderkit.util.RenderUtils;
43 import org.apache.myfaces.tobago.util.ComponentUtils;
44 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import javax.faces.component.UIComponent;
49 import javax.faces.component.UISelectOne;
50 import javax.faces.context.FacesContext;
51 import javax.faces.model.SelectItem;
52 import java.io.IOException;
53 import java.util.List;
54
55
56
57
58
59
60 public class MenuCommandRenderer extends CommandRendererBase {
61
62 private static final Logger LOG = LoggerFactory.getLogger(MenuCommandRenderer.class);
63
64 @Override
65 public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
66 UIMenuCommand menu = (UIMenuCommand) component;
67 TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
68
69 boolean disabled = menu.isDisabled();
70 boolean firstLevel = RendererTypes.MENU_BAR.equals(menu.getParent().getRendererType());
71 LabelWithAccessKey label = new LabelWithAccessKey(menu);
72 String clientId = menu.getClientId(facesContext);
73 String submit = HtmlRendererUtils.createSubmitAction(clientId, true, null, null);
74
75 if (menu.getFacet(Facets.CHECKBOX) != null) {
76
77 UISelectBooleanCheckbox checkbox = (UISelectBooleanCheckbox) menu.getFacet(Facets.CHECKBOX);
78 boolean checked = ComponentUtils.getBooleanAttribute(checkbox, Attributes.VALUE);
79 String image = checked ? "image/MenuCheckmark.gif" : null;
80 String hiddenId = checkbox.getClientId(facesContext);
81
82 String setValue = JQueryUtils.selectId(hiddenId)
83 + ".each(function(){jQuery(this).val(jQuery(this).val() == 'true' ? 'false' : 'true')}); ";
84 encodeItem(facesContext, writer, menu, label, setValue + submit, disabled, firstLevel, image);
85 encodeHidden(writer, hiddenId, checked);
86 } else if (menu.getFacet(Facets.RADIO) != null) {
87
88 UISelectOne radio = (UISelectOne) menu.getFacet(Facets.RADIO);
89 List<SelectItem> items = RenderUtils.getSelectItems(radio);
90 String hiddenId = radio.getClientId(facesContext);
91 for (SelectItem item : items) {
92 boolean checked = item.getValue().equals(radio.getValue());
93 String image = checked ? "image/MenuRadioChecked.gif" : null;
94 final String labelText = item.getLabel();
95 label.reset();
96 if (labelText != null) {
97 if (labelText.indexOf(LabelWithAccessKey.INDICATOR) > -1) {
98 label.setup(labelText);
99 } else {
100 label.setText(labelText);
101 }
102 } else {
103 LOG.warn("Menu item has label=null where clientId=" + clientId);
104 }
105 String formattedValue = RenderUtils.getFormattedValue(facesContext, radio, item.getValue());
106 String setValue = JQueryUtils.selectId(hiddenId) + ".val('" + JQueryUtils.escapeValue(formattedValue) + "'); ";
107 encodeItem(facesContext, writer, null, label, setValue + submit, disabled, firstLevel, image);
108 }
109 encodeHidden(writer, hiddenId, getCurrentValue(facesContext, radio));
110 } else {
111
112 CommandRendererHelper helper = new CommandRendererHelper(facesContext, menu);
113 String onclick = helper.getOnclick();
114 String image = menu.getImage();
115 encodeItem(facesContext, writer, menu, label, onclick != null ? onclick : submit, disabled, firstLevel, image);
116 }
117 }
118
119 private void encodeHidden(TobagoResponseWriter writer, String hiddenId, Object value) throws IOException {
120 writer.startElement(HtmlElements.INPUT, null);
121 writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN, false);
122 writer.writeIdAttribute(hiddenId);
123 writer.writeNameAttribute(hiddenId);
124 if (value != null) {
125 writer.writeAttribute(HtmlAttributes.VALUE, value.toString(), true);
126 }
127 writer.endElement(HtmlElements.INPUT);
128 }
129
130 private void encodeItem(
131 FacesContext facesContext, TobagoResponseWriter writer, UIMenuCommand component, LabelWithAccessKey label,
132 String onclick, boolean disabled, boolean firstLevel, String image) throws IOException {
133
134 writer.startElement(HtmlElements.LI, null);
135 if (component != null) {
136 writer.writeIdAttribute(component.getClientId(facesContext));
137 }
138 Markup markup = null;
139 if (component != null) {
140 markup = component.getCurrentMarkup();
141 if (firstLevel) {
142 markup = Markup.TOP.add(markup);
143 }
144 }
145 writer.writeClassAttribute(Classes.createWorkaround("menu", markup));
146 writer.writeAttribute(HtmlAttributes.ONCLICK, onclick, true);
147 if (component != null) {
148 HtmlRendererUtils.writeDataAttributes(facesContext, writer, component);
149 }
150
151 if (image != null) {
152 if (firstLevel) {
153 Style iconStyle = new Style();
154 iconStyle.setLeft(Measure.valueOf(0));
155 iconStyle.setTop(Measure.valueOf(0));
156 iconStyle.setHeight(Measure.valueOf(16));
157 iconStyle.setWidth(Measure.valueOf(16));
158
159 writer.startElement(HtmlElements.IMG, null);
160 String imageWithPath = ResourceManagerUtils.getImageWithPath(facesContext, image, true);
161 writer.writeAttribute(HtmlAttributes.SRC, imageWithPath, false);
162 String imageHover
163 = ResourceManagerUtils.getImageWithPath(facesContext, HtmlRendererUtils.createSrc(image, "Hover"), true);
164 if (imageHover != null) {
165 writer.writeAttribute(DataAttributes.SRCDEFAULT, imageWithPath, false);
166 writer.writeAttribute(DataAttributes.SRCHOVER, imageHover, false);
167 }
168
169 writer.writeAttribute(HtmlAttributes.ALT, label.getText(), true);
170 writer.writeStyleAttribute(iconStyle);
171 writer.endElement(HtmlElements.IMG);
172 } else {
173 Style style = new Style();
174 style.setBackgroundImage("url("
175 + ResourceManagerUtils.getImageWithPath(facesContext, image)
176 + ")");
177 writer.writeStyleAttribute(style);
178 }
179 }
180
181 writer.startElement(HtmlElements.A, null);
182 writer.writeAttribute(HtmlAttributes.HREF, "#", false);
183 if (image != null && firstLevel) {
184 writer.writeStyleAttribute("vertical-align:top");
185 }
186
187
188 if (label.getText() != null) {
189 if (label.getAccessKey() != null) {
190 if (LOG.isInfoEnabled()
191 && !AccessKeyMap.addAccessKey(facesContext, label.getAccessKey())) {
192 LOG.info("duplicated accessKey : " + label.getAccessKey());
193 }
194 if (!disabled && component != null && label.getAccessKey() != null) {
195 writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
196 }
197 }
198 HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
199 }
200 writer.endElement(HtmlElements.A);
201 writer.endElement(HtmlElements.LI);
202 }
203
204 public void encodeChildren(FacesContext facesContext, UIComponent component)
205 throws IOException {
206 }
207
208 public boolean getRendersChildren() {
209 return true;
210 }
211
212
213 }