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