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