1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.custom.suggestajax.inputsuggestajax;
21
22 import org.apache.commons.collections.map.HashedMap;
23 import org.apache.myfaces.custom.ajax.api.AjaxRenderer;
24 import org.apache.myfaces.custom.dojo.DojoConfig;
25 import org.apache.myfaces.custom.dojo.DojoUtils;
26 import org.apache.myfaces.custom.suggestajax.SuggestAjaxRenderer;
27 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
28 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
29 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
30
31 import javax.faces.component.UIComponent;
32 import javax.faces.context.FacesContext;
33 import javax.faces.context.ResponseWriter;
34 import javax.faces.convert.Converter;
35 import javax.faces.el.MethodBinding;
36 import javax.servlet.ServletResponse;
37 import java.io.IOException;
38 import java.util.Collection;
39 import java.util.Iterator;
40 import java.util.Map;
41
42
43
44
45
46
47
48
49
50
51
52
53 public class InputSuggestAjaxRenderer extends SuggestAjaxRenderer implements AjaxRenderer
54 {
55
56
57
58
59
60
61
62
63
64 private void encodeJavascript(FacesContext context, UIComponent component)
65 throws IOException
66 {
67 String javascriptLocation = (String)component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
68
69 DojoUtils.addMainInclude(context, component, javascriptLocation, new DojoConfig());
70 DojoUtils.addRequire(context, component, "extensions.FacesIO");
71 DojoUtils.addRequire(context, component, "extensions.widget.InputSuggestAjax");
72 DojoUtils.addRequire(context, component, "dojo.event.*");
73 }
74
75 public void encodeEnd(FacesContext context, UIComponent component) throws IOException
76 {
77 RendererUtils.checkParamValidity(context, component, InputSuggestAjax.class);
78
79 InputSuggestAjax inputSuggestAjax = (InputSuggestAjax) component;
80
81 encodeJavascript(context,component);
82
83 String clientId = component.getClientId(context);
84 String actionURL = getActionUrl(context);
85
86 String charset = (inputSuggestAjax.getCharset() != null ? inputSuggestAjax.getCharset() : "");
87
88 String ajaxUrl = context.getExternalContext().encodeActionURL(addQueryString(actionURL, "affectedAjaxComponent=" + clientId +
89 "&charset=" + charset + "&" + clientId + "=%{searchString}"));
90
91 ResponseWriter out = context.getResponseWriter();
92
93 String label = null;
94 String hiddenInputValue = null;
95 boolean hasLabelMethod = false;
96
97 String mainComponentRenderedValue = null;
98
99
100 if (inputSuggestAjax.getItemLabelMethod() == null)
101 {
102 mainComponentRenderedValue = RendererUtils.getStringValue(context, inputSuggestAjax);
103 }
104 else
105 {
106 MethodBinding labelMethod = inputSuggestAjax.getItemLabelMethod();
107
108 if (labelMethod != null)
109 {
110 hasLabelMethod = true;
111
112 Object valueObject = inputSuggestAjax.getValue();
113
114 Converter converter = getRequiredConverter(context, inputSuggestAjax);
115
116 label = (String) labelMethod.invoke(context, new Object[]{valueObject});
117
118 hiddenInputValue = converter.getAsString(context, inputSuggestAjax, valueObject);
119 mainComponentRenderedValue = hiddenInputValue;
120 }
121 }
122
123 String placeHolderId = context.getViewRoot().createUniqueId();
124 out.startElement(HTML.DIV_ELEM, component);
125 out.writeAttribute(HTML.ID_ATTR, placeHolderId , null);
126 if(inputSuggestAjax.getStyle() != null)
127 {
128 out.writeAttribute(HTML.STYLE_ATTR, inputSuggestAjax.getStyle(), null);
129 }
130 if(inputSuggestAjax.getStyleClass() != null)
131 {
132 out.writeAttribute(HTML.CLASS_ATTR, inputSuggestAjax.getStyleClass(), null);
133 }
134 out.endElement(HTML.DIV_ELEM);
135
136 String textInputId = inputSuggestAjax.getClientId(context);
137 if (label != null)
138 {
139
140
141
142 String oriId = inputSuggestAjax.getId();
143 try
144 {
145
146 inputSuggestAjax.setId(oriId + "_fake");
147
148 textInputId = inputSuggestAjax.getClientId(context);
149
150
151 inputSuggestAjax.setSubmittedValue(label);
152
153 super.encodeEnd(context, inputSuggestAjax);
154 }
155 finally
156 {
157 inputSuggestAjax.setSubmittedValue(null);
158 inputSuggestAjax.setId(oriId);
159 }
160 }
161 else
162 {
163 super.encodeEnd(context, inputSuggestAjax);
164 }
165
166 String inputSuggestComponentVar = DojoUtils.calculateWidgetVarName(placeHolderId);
167
168 Map attributes = new HashedMap();
169
170 attributes.put("dataUrl", ajaxUrl);
171 attributes.put("mode", "remote");
172 attributes.put("textInputId", textInputId);
173
174 String autoComplete = inputSuggestAjax.getAutoComplete().booleanValue()?"true":"false";
175 attributes.put("autoComplete", autoComplete);
176
177 if (label != null)
178 {
179 mainComponentRenderedValue = label;
180 }
181 else if (mainComponentRenderedValue != null)
182 {
183 mainComponentRenderedValue = escapeQuotes(mainComponentRenderedValue);
184 }
185
186 DojoUtils.renderWidgetInitializationCode(context.getResponseWriter(), component, "extensions:InputSuggestAjax", attributes, placeHolderId.toString(), true);
187
188 out.startElement(HTML.SCRIPT_ELEM, null);
189 out.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
190
191 StringBuffer buffer = new StringBuffer();
192
193 buffer.append("dojo.addOnLoad(function() {\n")
194 .append(inputSuggestComponentVar).append(".comboBoxValue.value = \"").append(mainComponentRenderedValue).append("\";\n")
195 .append(inputSuggestComponentVar).append(".onResize();\n")
196 .append("});\n");
197
198 out.write(buffer.toString());
199
200 out.endElement(HTML.SCRIPT_ELEM);
201
202 if (hasLabelMethod)
203 {
204 out.startElement(HTML.INPUT_ELEM, inputSuggestAjax);
205 out.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
206 out.writeAttribute(HTML.ID_ATTR, clientId, null);
207 out.writeAttribute(HTML.NAME_ATTR, clientId, null);
208 out.writeAttribute(HTML.VALUE_ATTR, hiddenInputValue!=null?hiddenInputValue:"", null);
209 out.endElement(HTML.INPUT_ELEM);
210
211 out.startElement(HTML.SCRIPT_ELEM, null);
212 out.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
213
214 StringBuffer script = new StringBuffer();
215
216 script.append("dojo.event.connect("+inputSuggestComponentVar+", \"_selectOption\", function(evt) { \n"
217 + "dojo.byId('"+ clientId +"').value = ").append(inputSuggestComponentVar).append(".comboBoxSelectionValue.value; });\n");
218
219 out.write(script.toString());
220
221 out.endElement(HTML.SCRIPT_ELEM);
222 }
223 }
224
225 protected Converter getRequiredConverter(FacesContext context, InputSuggestAjax inputSuggestAjax)
226 {
227 Converter converter = inputSuggestAjax.getConverter();
228 if (converter != null)
229 {
230 return converter;
231 }
232
233 Class type = inputSuggestAjax.getValueBinding("value").getType(context);
234 if (type != null)
235 {
236 converter = context.getApplication().createConverter(type);
237 if (converter != null)
238 {
239 return converter;
240 }
241 }
242
243 throw new IllegalStateException("There must be a converter if " +
244 "attribute \"labelMethod\" is used");
245 }
246
247 public void encodeAjax(FacesContext context, UIComponent uiComponent)
248 throws IOException
249 {
250
251
252 ServletResponse response = (ServletResponse) context.getExternalContext().getResponse();
253 response.setContentType("text/plain");
254
255 InputSuggestAjax inputSuggestAjax = (InputSuggestAjax) uiComponent;
256
257 Collection suggesteds = getSuggestedItems(context, uiComponent);
258
259 MethodBinding labelMethod = inputSuggestAjax.getItemLabelMethod();
260
261 StringBuffer buf = new StringBuffer();
262
263 buf.append("[");
264
265 if (labelMethod != null)
266 {
267 Converter converter = getRequiredConverter(context, inputSuggestAjax);
268
269 for (Iterator iterator = suggesteds.iterator(); iterator.hasNext();)
270 {
271 Object suggestedItemObject = iterator.next();
272
273 String label = (String) labelMethod.invoke(context, new Object[]{suggestedItemObject});
274 String value = converter.getAsString(context, inputSuggestAjax, suggestedItemObject);
275
276 buf.append("[\"").append(label).append("\",\"").append(value).append("\"],");
277 }
278 }
279 else
280 {
281
282 for (Iterator suggestedItem = suggesteds.iterator(); suggestedItem.hasNext() ;)
283 {
284 Object item = suggestedItem.next();
285
286 String prefix = escapeQuotes(encodeSuggestString(item.toString()).substring(0, 1)).toUpperCase();
287
288 buf.append("[\"").append(encodeSuggestString(escapeQuotes(item.toString()))).append("\",\"")
289 .append(prefix).append("\"],");
290 }
291 }
292
293 buf.append("]");
294
295 context.getResponseWriter().write(buf.toString());
296 }
297
298 protected String encodeSuggestString(String str)
299 {
300
301 return str;
302 }
303
304 public void decode(FacesContext facesContext, UIComponent component)
305 {
306 super.decode(facesContext, component);
307 }
308
309 private String escapeQuotes(String input)
310 {
311 return input != null ? input.replaceAll("\"", "\\\\\"") : "";
312 }
313
314 }