1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
package org.apache.tapestry.dojo.form; |
15 | |
|
16 | |
import org.apache.tapestry.*; |
17 | |
import org.apache.tapestry.engine.DirectServiceParameter; |
18 | |
import org.apache.tapestry.engine.IEngineService; |
19 | |
import org.apache.tapestry.engine.ILink; |
20 | |
import org.apache.tapestry.form.ValidatableField; |
21 | |
import org.apache.tapestry.form.ValidatableFieldSupport; |
22 | |
import org.apache.tapestry.json.IJSONWriter; |
23 | |
import org.apache.tapestry.json.JSONObject; |
24 | |
import org.apache.tapestry.services.DataSqueezer; |
25 | |
import org.apache.tapestry.valid.ValidatorException; |
26 | |
|
27 | |
import java.util.ArrayList; |
28 | |
import java.util.HashMap; |
29 | |
import java.util.List; |
30 | |
import java.util.Map; |
31 | |
|
32 | |
|
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | 0 | public abstract class Autocompleter extends AbstractFormWidget implements ValidatableField, IJSONRender, IDirect |
42 | |
{ |
43 | |
|
44 | |
private static final String MODE_REMOTE = "remote"; |
45 | |
private static final String MODE_LOCAL = "local"; |
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | |
|
51 | |
protected void renderFormWidget(IMarkupWriter writer, IRequestCycle cycle) |
52 | |
{ |
53 | 0 | IAutocompleteModel model = getModel(); |
54 | 0 | if (model == null) |
55 | 0 | throw Tapestry.createRequiredParameterException(this, "model"); |
56 | |
|
57 | 0 | Object value = getValue(); |
58 | 0 | Object key = value != null && !"".equals(value.toString()) ? model.getPrimaryKey(value) : null; |
59 | |
|
60 | 0 | renderDelegatePrefix(writer, cycle); |
61 | |
|
62 | 0 | writer.begin("select"); |
63 | 0 | writer.attribute("name", getName()); |
64 | 0 | writer.attribute("autocomplete", "off"); |
65 | |
|
66 | 0 | if (isDisabled()) |
67 | 0 | writer.attribute("disabled", "disabled"); |
68 | |
|
69 | 0 | renderIdAttribute(writer, cycle); |
70 | |
|
71 | 0 | renderDelegateAttributes(writer, cycle); |
72 | |
|
73 | 0 | getValidatableFieldSupport().renderContributions(this, writer, cycle); |
74 | |
|
75 | |
|
76 | 0 | renderInformalParameters(writer, cycle); |
77 | |
|
78 | 0 | writer.print(" "); |
79 | |
|
80 | 0 | if (isLocal()) |
81 | |
{ |
82 | 0 | List list = model.getValues(""); |
83 | 0 | for (int i=0; i<list.size(); i++) |
84 | |
{ |
85 | 0 | Object optionKey = model.getPrimaryKey(list.get(i)); |
86 | |
|
87 | 0 | writer.begin("option"); |
88 | 0 | writer.attribute("value", getDataSqueezer().squeeze(optionKey)); |
89 | |
|
90 | 0 | if (optionKey!=null && optionKey.equals(key)) |
91 | 0 | writer.attribute("selected", "selected"); |
92 | |
|
93 | 0 | writer.print(model.getLabelFor(list.get(i))); |
94 | 0 | writer.end(); |
95 | |
} |
96 | |
} |
97 | |
|
98 | 0 | writer.end(); |
99 | 0 | renderDelegateSuffix(writer, cycle); |
100 | |
|
101 | 0 | Map parms = new HashMap(); |
102 | 0 | parms.put("id", getClientId()); |
103 | |
|
104 | 0 | JSONObject json = new JSONObject(); |
105 | 0 | if (!isLocal()) |
106 | |
{ |
107 | 0 | ILink link = getDirectService().getLink(true, new DirectServiceParameter(this)); |
108 | 0 | json.put("dataUrl", link.getURL() + "&filter=%{searchString}"); |
109 | |
} |
110 | |
|
111 | 0 | json.put("mode", isLocal() ? MODE_LOCAL : MODE_REMOTE); |
112 | 0 | json.put("widgetId", getName()); |
113 | 0 | json.put("name", getName()); |
114 | 0 | json.put("searchDelay", getSearchDelay()); |
115 | 0 | json.put("fadeTime", getFadeTime()); |
116 | 0 | json.put("maxListLength", getMaxListLength()); |
117 | 0 | json.put("forceValidOption", isForceValidOption()); |
118 | 0 | json.put("disabled", isDisabled()); |
119 | 0 | json.put("autoComplete", getAutoCompleteField()); |
120 | |
|
121 | 0 | json.put("value", key != null ? getDataSqueezer().squeeze(key) : ""); |
122 | 0 | json.put("label", value != null ? model.getLabelFor(value) : ""); |
123 | |
|
124 | 0 | parms.put("props", json.toString()); |
125 | 0 | parms.put("form", getForm().getName()); |
126 | 0 | parms.put("widget", this); |
127 | |
|
128 | 0 | PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, this); |
129 | 0 | getScript().execute(this, cycle, prs, parms); |
130 | 0 | } |
131 | |
|
132 | |
|
133 | |
|
134 | |
|
135 | |
public void renderComponent(IJSONWriter writer, IRequestCycle cycle) |
136 | |
{ |
137 | 0 | IAutocompleteModel model = getModel(); |
138 | |
|
139 | 0 | if (model == null) |
140 | 0 | throw Tapestry.createRequiredParameterException(this, "model"); |
141 | |
|
142 | 0 | List filteredValues = model.getValues(getFilter()); |
143 | |
|
144 | 0 | if (filteredValues == null) |
145 | 0 | return; |
146 | |
|
147 | 0 | Object key = null; |
148 | 0 | String label = null; |
149 | |
|
150 | 0 | JSONObject json = writer.object(); |
151 | |
|
152 | 0 | for (int i=0; i < filteredValues.size(); i++) { |
153 | 0 | Object value = filteredValues.get(i); |
154 | |
|
155 | 0 | key = model.getPrimaryKey(value); |
156 | 0 | label = model.getLabelFor(value); |
157 | |
|
158 | 0 | json.put(getDataSqueezer().squeeze(key), label ); |
159 | |
} |
160 | |
|
161 | 0 | } |
162 | |
|
163 | |
|
164 | |
|
165 | |
|
166 | |
protected void rewindFormWidget(IMarkupWriter writer, IRequestCycle cycle) |
167 | |
{ |
168 | 0 | String value = cycle.getParameter(getName()); |
169 | |
|
170 | 0 | Object object = null; |
171 | |
|
172 | |
try |
173 | |
{ |
174 | 0 | if (value != null && value.length() > 0) |
175 | 0 | object = getModel().getValue(getDataSqueezer().unsqueeze(value)); |
176 | |
|
177 | 0 | getValidatableFieldSupport().validate(this, writer, cycle, object); |
178 | |
|
179 | 0 | setValue(object); |
180 | |
} |
181 | 0 | catch (ValidatorException e) |
182 | |
{ |
183 | 0 | getForm().getDelegate().record(e); |
184 | 0 | } |
185 | 0 | } |
186 | |
|
187 | |
|
188 | |
|
189 | |
|
190 | |
public boolean isStateful() |
191 | |
{ |
192 | 0 | return true; |
193 | |
} |
194 | |
|
195 | |
|
196 | |
|
197 | |
|
198 | |
|
199 | |
|
200 | |
public void trigger(IRequestCycle cycle) |
201 | |
{ |
202 | 0 | setFilter(cycle.getParameter("filter")); |
203 | 0 | } |
204 | |
|
205 | |
public abstract IAutocompleteModel getModel(); |
206 | |
|
207 | |
|
208 | |
public abstract int getSearchDelay(); |
209 | |
|
210 | |
|
211 | |
public abstract int getFadeTime(); |
212 | |
|
213 | |
|
214 | |
public abstract int getMaxListLength(); |
215 | |
|
216 | |
|
217 | |
public abstract boolean isForceValidOption(); |
218 | |
|
219 | |
|
220 | |
public abstract boolean isLocal(); |
221 | |
|
222 | |
|
223 | |
public abstract Object getValue(); |
224 | |
|
225 | |
|
226 | |
public abstract void setValue(Object value); |
227 | |
|
228 | |
|
229 | |
public abstract void setFilter(String value); |
230 | |
|
231 | |
|
232 | |
public abstract String getFilter(); |
233 | |
|
234 | |
|
235 | |
public abstract boolean getAutoCompleteField(); |
236 | |
|
237 | |
|
238 | |
public abstract DataSqueezer getDataSqueezer(); |
239 | |
|
240 | |
|
241 | |
|
242 | |
|
243 | |
public abstract ValidatableFieldSupport getValidatableFieldSupport(); |
244 | |
|
245 | |
|
246 | |
|
247 | |
|
248 | |
public abstract IEngineService getDirectService(); |
249 | |
|
250 | |
|
251 | |
|
252 | |
|
253 | |
public abstract IScript getScript(); |
254 | |
|
255 | |
|
256 | |
|
257 | |
|
258 | |
public boolean isRequired() |
259 | |
{ |
260 | 0 | return getValidatableFieldSupport().isRequired(this); |
261 | |
} |
262 | |
|
263 | |
|
264 | |
|
265 | |
|
266 | |
public List getUpdateComponents() |
267 | |
{ |
268 | 0 | List comps = new ArrayList(); |
269 | 0 | comps.add(getClientId()); |
270 | |
|
271 | 0 | return comps; |
272 | |
} |
273 | |
|
274 | |
|
275 | |
|
276 | |
|
277 | |
public boolean isAsync() |
278 | |
{ |
279 | 0 | return true; |
280 | |
} |
281 | |
|
282 | |
|
283 | |
|
284 | |
|
285 | |
public boolean isJson() |
286 | |
{ |
287 | 0 | return true; |
288 | |
} |
289 | |
} |