1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.picklist;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import javax.faces.component.EditableValueHolder;
30 import javax.faces.component.UIComponent;
31 import javax.faces.component.UISelectMany;
32 import javax.faces.context.FacesContext;
33 import javax.faces.context.ResponseWriter;
34 import javax.faces.convert.Converter;
35 import javax.faces.model.SelectItem;
36
37 import org.apache.commons.collections.CollectionUtils;
38 import org.apache.myfaces.renderkit.html.util.AddResource;
39 import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
40 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
41 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
42 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
43 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
44 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlListboxRendererBase;
45
46
47
48
49
50
51
52
53
54
55
56 public class HtmlPicklistRenderer extends HtmlListboxRendererBase
57 {
58
59 private static final String FUNCTION_ADD_TO_SELECTED = "myfaces_picklist_addToSelected";
60 private static final String FUNCTION_ADD_ALL_TO_SELECTED = "myfaces_picklist_addAllToSelected";
61 private static final String FUNCTION_REMOVE_FROM_SELECTED = "myfaces_picklist_removeFromSelected";
62 private static final String FUNCTION_REMOVE_ALL_FROM_SELECTED = "myfaces_picklist_removeAllFromSelected";
63
64 private static final String AVAILABLE_SUFFIX = "_AVAILABLE";
65 private static final String SELECTED_SUFFIX = "_SELECTED";
66 private static final String HIDDEN_SUFFIX = "_HIDDEN";
67
68 public void decode(FacesContext facesContext, UIComponent uiComponent)
69 {
70 RendererUtils.checkParamValidity(facesContext, uiComponent, null);
71
72 if (!(uiComponent instanceof EditableValueHolder))
73 {
74 throw new IllegalArgumentException("Component "
75 + uiComponent.getClientId(facesContext)
76 + " is not an EditableValueHolder");
77 }
78
79 String hiddenClientId = uiComponent.getClientId(facesContext)
80 + HIDDEN_SUFFIX;
81
82 Map paramValuesMap = facesContext.getExternalContext()
83 .getRequestParameterValuesMap();
84
85 if (HtmlRendererUtils.isDisabledOrReadOnly(uiComponent))
86 return;
87
88 if (paramValuesMap.containsKey(hiddenClientId))
89 {
90 String[] valuesInline = (String[]) paramValuesMap
91 .get(hiddenClientId);
92
93 if (valuesInline[0].trim().equals(""))
94 {
95 ((EditableValueHolder) uiComponent)
96 .setSubmittedValue(new String[] {});
97 }
98 else
99 {
100 String[] reqValues = valuesInline[0].split(",");
101 ((EditableValueHolder) uiComponent)
102 .setSubmittedValue(reqValues);
103 }
104 }
105 else
106 {
107
108
109
110
111
112
113 ((EditableValueHolder) uiComponent)
114 .setSubmittedValue(new String[] {});
115 }
116 }
117
118 public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
119 throws IOException
120 {
121 RendererUtils.checkParamValidity(facesContext, uiComponent,
122 HtmlSelectManyPicklist.class);
123
124
125 if(HtmlRendererUtils.isDisplayValueOnly(uiComponent))
126 {
127 HtmlRendererUtils.renderDisplayValueOnlyForSelects(facesContext, uiComponent);
128 return;
129 }
130
131 HtmlSelectManyPicklist picklist = (HtmlSelectManyPicklist) uiComponent;
132
133 String addButtonText = picklist.getAddButtonText();
134 String addAllButtonText = picklist.getAddAllButtonText();
135 String removeButtonText = picklist.getRemoveButtonText();
136 String removeAllButtonText = picklist.getRemoveAllButtonText();
137 String addButtonStyle = picklist.getAddButtonStyle();
138 String addAllButtonStyle = picklist.getAddAllButtonStyle();
139 String removeButtonStyle = picklist.getRemoveButtonStyle();
140 String removeAllButtonStyle = picklist.getRemoveAllButtonStyle();
141 String addButtonStyleClass = picklist.getAddButtonStyleClass();
142 String addAllButtonStyleClass = picklist.getAddAllButtonStyleClass();
143 String removeButtonStyleClass = picklist.getRemoveButtonStyleClass();
144 String removeAllButtonStyleClass = picklist.getRemoveAllButtonStyleClass();
145
146
147 if(addButtonText == null || addButtonText.length() == 0)
148 addButtonText = ">";
149
150 if(addAllButtonText == null || addAllButtonText.length() == 0)
151 addAllButtonText = ">>";
152
153 if(removeButtonText == null || removeButtonText.length() == 0)
154 removeButtonText = "<";
155
156 if(removeAllButtonText == null || removeAllButtonText.length() == 0)
157 removeAllButtonText = "<<";
158
159 encodeJavascript(facesContext, uiComponent);
160
161 String availableListClientId = uiComponent.getClientId(facesContext)
162 + AVAILABLE_SUFFIX;
163 String selectedListClientId = uiComponent.getClientId(facesContext)
164 + SELECTED_SUFFIX;
165 String hiddenFieldCliendId = uiComponent.getClientId(facesContext)
166 + HIDDEN_SUFFIX;
167
168 List selectItemList = RendererUtils
169 .getSelectItemList((UISelectMany) uiComponent);
170 Converter converter = HtmlRendererUtils
171 .findUISelectManyConverterFailsafe(facesContext, uiComponent);
172
173 Set lookupSet = HtmlRendererUtils.getSubmittedOrSelectedValuesAsSet(
174 true, uiComponent, facesContext, converter);
175
176 List selectItemsForSelectedValues = selectItemsForSelectedList(
177 facesContext, uiComponent, selectItemList, converter, lookupSet);
178 List selectItemsForAvailableList = selectItemsForAvailableList(
179 facesContext, uiComponent, selectItemList,
180 selectItemsForSelectedValues, converter);
181
182 ResponseWriter writer = facesContext.getResponseWriter();
183
184 writer.startElement(HTML.TABLE_ELEM, uiComponent);
185 HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
186 writer.startElement(HTML.TR_ELEM, uiComponent);
187 writer.startElement(HTML.TD_ELEM, uiComponent);
188
189 encodeSelect(facesContext, picklist, availableListClientId, isDisabled(
190 facesContext, uiComponent), picklist.getSize(),
191 selectItemsForAvailableList, converter);
192
193 writer.endElement(HTML.TD_ELEM);
194
195
196 writer.startElement(HTML.TD_ELEM, uiComponent);
197
198 String javascriptAddToSelected = FUNCTION_ADD_TO_SELECTED + "('"
199 + availableListClientId + "','" + selectedListClientId + "','"
200 + hiddenFieldCliendId + "')";
201
202 String javascriptAddAllToSelected = FUNCTION_ADD_ALL_TO_SELECTED + "('"
203 + availableListClientId + "','" + selectedListClientId + "','"
204 + hiddenFieldCliendId + "')";
205
206 String javascriptRemoveFromSelected = FUNCTION_REMOVE_FROM_SELECTED
207 + "('" + availableListClientId + "','" + selectedListClientId
208 + "','" + hiddenFieldCliendId + "')";
209
210 String javascriptRemoveAllFromSelected = FUNCTION_REMOVE_ALL_FROM_SELECTED
211 + "('" + availableListClientId + "','" + selectedListClientId
212 + "','" + hiddenFieldCliendId + "')";
213
214
215 encodeSwapButton(facesContext, uiComponent, javascriptAddToSelected,
216 addButtonText, addButtonStyle, addButtonStyleClass);
217
218 writer.startElement(HTML.BR_ELEM, uiComponent);
219 writer.endElement(HTML.BR_ELEM);
220
221
222 encodeSwapButton(facesContext, uiComponent, javascriptAddAllToSelected,
223 addAllButtonText, addAllButtonStyle, addAllButtonStyleClass);
224
225 writer.startElement(HTML.BR_ELEM, uiComponent);
226 writer.endElement(HTML.BR_ELEM);
227
228
229 encodeSwapButton(facesContext, uiComponent, javascriptRemoveFromSelected,
230 removeButtonText, removeButtonStyle, removeButtonStyleClass);
231
232 writer.startElement(HTML.BR_ELEM, uiComponent);
233 writer.endElement(HTML.BR_ELEM);
234
235
236 encodeSwapButton(facesContext, uiComponent, javascriptRemoveAllFromSelected,
237 removeAllButtonText, removeAllButtonStyle, removeAllButtonStyleClass);
238
239 writer.endElement(HTML.TD_ELEM);
240
241
242 writer.startElement(HTML.TD_ELEM, uiComponent);
243
244 encodeSelect(facesContext, picklist, selectedListClientId, isDisabled(
245 facesContext, uiComponent), picklist.getSize(),
246 selectItemsForSelectedValues, converter);
247
248
249 encodeHiddenField(facesContext, uiComponent, hiddenFieldCliendId,
250 lookupSet);
251
252 writer.endElement(HTML.TD_ELEM);
253 writer.endElement(HTML.TR_ELEM);
254 writer.endElement(HTML.TABLE_ELEM);
255 }
256
257 private void encodeJavascript(FacesContext facesContext,
258 UIComponent uiComponent)
259 {
260
261 AddResource addResource = AddResourceFactory.getInstance(facesContext);
262 addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN,
263 HtmlPicklistRenderer.class, "picklist.js");
264 }
265
266 private void encodeSwapButton(FacesContext facesContext,
267 UIComponent uiComponent, String javaScriptFunction,
268 String text, String style, String styleClass)
269 throws IOException
270 {
271 ResponseWriter writer = facesContext.getResponseWriter();
272
273 writer.startElement(HTML.INPUT_ELEM, uiComponent);
274 writer.writeAttribute(HTML.STYLE_ATTR, style, null);
275 writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
276 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_BUTTON,
277 JSFAttr.TYPE_ATTR);
278 writer.writeAttribute(HTML.ONCLICK_ATTR, javaScriptFunction, null);
279 writer.writeAttribute(HTML.VALUE_ATTR, text, null);
280 writer.endElement(HTML.INPUT_ELEM);
281 }
282
283 private void encodeSelect(FacesContext facesContext,
284 UIComponent uiComponent, String clientId, boolean disabled,
285 int size, List selectItemsToDisplay, Converter converter)
286 throws IOException
287 {
288 ResponseWriter writer = facesContext.getResponseWriter();
289
290 writer.startElement(HTML.SELECT_ELEM, uiComponent);
291 writer.writeAttribute(HTML.ID_ATTR, clientId, JSFAttr.ID_ATTR);
292 writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
293
294 writer.writeAttribute(HTML.MULTIPLE_ATTR, "true", null);
295
296 if (size == 0)
297 {
298
299 writer.writeAttribute(HTML.SIZE_ATTR, Integer
300 .toString(selectItemsToDisplay.size()), null);
301 }
302 else
303 {
304 writer.writeAttribute(HTML.SIZE_ATTR, Integer.toString(size), null);
305 }
306 HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
307 HTML.SELECT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
308 if (disabled)
309 {
310 writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
311 }
312
313 HtmlRendererUtils.renderSelectOptions(facesContext, uiComponent,
314 converter, Collections.EMPTY_SET, selectItemsToDisplay);
315
316
317 writer.writeText("", null);
318 writer.endElement(HTML.SELECT_ELEM);
319 }
320
321 private void encodeHiddenField(FacesContext facesContext,
322 UIComponent uiComponent, String hiddenFieldCliendId, Set lookupSet)
323 throws IOException
324 {
325 ResponseWriter writer = facesContext.getResponseWriter();
326
327 writer.startElement(HTML.INPUT_ELEM, uiComponent);
328 writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN,
329 JSFAttr.TYPE_ATTR);
330 writer.writeAttribute(HTML.ID_ATTR, hiddenFieldCliendId,
331 JSFAttr.ID_ATTR);
332 writer.writeAttribute(HTML.NAME_ATTR, hiddenFieldCliendId, null);
333
334 StringBuffer sb = new StringBuffer();
335 int n = 0;
336 for (Iterator i = lookupSet.iterator(); i.hasNext();)
337 {
338 if (n > 0)
339 {
340 sb.append(",");
341 }
342 String value = (String) i.next();
343 sb.append(value);
344 n++;
345 }
346
347 writer.writeAttribute(HTML.VALUE_ATTR, sb.toString(), null);
348 writer.endElement(HTML.INPUT_ELEM);
349
350 }
351
352 private List selectItemsForSelectedList(FacesContext facesContext,
353 UIComponent uiComponent, List selectItemList, Converter converter,
354 Set lookupSet)
355 {
356 List selectItemForSelectedValues = new ArrayList(lookupSet.size());
357
358 for (Iterator i = selectItemList.iterator(); i.hasNext();)
359 {
360 SelectItem selectItem = (SelectItem) i.next();
361 String itemStrValue = RendererUtils.getConvertedStringValue(facesContext, uiComponent,
362 converter, selectItem);
363
364
365 for (Iterator i2 = lookupSet.iterator(); i2.hasNext();)
366 {
367 Object value = i2.next();
368 if (value.equals(itemStrValue))
369 {
370 selectItemForSelectedValues.add(selectItem);
371 }
372 }
373 }
374
375 return selectItemForSelectedValues;
376 }
377
378 private List selectItemsForAvailableList(FacesContext facesContext,
379 UIComponent uiComponent, List selectItemList,
380 List selectItemsForSelectedList, Converter converter)
381 {
382
383 return new ArrayList(CollectionUtils.subtract(selectItemList,
384 selectItemsForSelectedList));
385 }
386
387 }