1 | |
---|
2 | // Module QueryInput |
---|
3 | // provides a jQuery plugin with the same name. |
---|
4 | !function ($, console) { |
---|
5 | // could expose the defaults: $.fn.QueryInput.defaults = |
---|
6 | //{q:{label:"Query", widget:"text"}, submit:{value:"Search", widget:"submit"}} |
---|
7 | var defaults = { |
---|
8 | params: {}, |
---|
9 | input_prefix: "input-", |
---|
10 | slider_style: {width: "80px", display: "inline-block", "font-size": "70%", margin: "6px 12px 0 2px"}, |
---|
11 | onValueChanged: function () {}, |
---|
12 | fcs_source: "http://193.170.82.207:8680/exist/apps/sade/amc/fcs?operation=scan&x-format=json&scanClause=" |
---|
13 | }; |
---|
14 | |
---|
15 | var module = {}; |
---|
16 | |
---|
17 | /** |
---|
18 | * @class QueryInput |
---|
19 | * generate a customizable query_input UI, a input form with fields/widgets based on settings |
---|
20 | * options: multiple params/fields, |
---|
21 | * indexes, different widgets |
---|
22 | * |
---|
23 | * dependencies: jQuery, jquery-ui: slider, autocomplete |
---|
24 | |
---|
25 | * @author vronk, Andy Basch |
---|
26 | * @version 2013-01-17 |
---|
27 | */ |
---|
28 | /* we could make it a class (instead of jQuery plugin) |
---|
29 | function QueryInput(elem,s) */ |
---|
30 | module.QueryInput = function (options) |
---|
31 | { |
---|
32 | /** the dom-element to generate the query input in */ |
---|
33 | var elem=this; |
---|
34 | |
---|
35 | /** main variable holding all the settings for qi, especially also all params and their allowed values, and their current value |
---|
36 | * it is constructed here by merging the default and the user options passed as parameter to .QueryInput() |
---|
37 | */ |
---|
38 | var settings = $.extend(true, {}, defaults, options); |
---|
39 | |
---|
40 | /** gets the current value for a parameter |
---|
41 | * accepting settings as reliable source of current value |
---|
42 | * i.e. changes in input have to change the .value in settings. |
---|
43 | * This is assured by calling setParamValue upon input-change. |
---|
44 | * public by calling: $(elem).data("qi").getParamValue(param_key); |
---|
45 | * @public |
---|
46 | */ |
---|
47 | settings.getParamValue = function (key) { |
---|
48 | if (this.params[key]) { |
---|
49 | return this.params[key].value; |
---|
50 | } else { |
---|
51 | return ""; |
---|
52 | } |
---|
53 | }; |
---|
54 | |
---|
55 | /** allow to update the current value in settings from outside */ |
---|
56 | settings.setParamValue = function (key, value) { |
---|
57 | |
---|
58 | if (settings.params[key]) { |
---|
59 | settings.params[key].value = value; |
---|
60 | } |
---|
61 | // callback: |
---|
62 | settings.onValueChanged.call(settings, value); |
---|
63 | return value; |
---|
64 | }; |
---|
65 | |
---|
66 | blendInParams(); |
---|
67 | |
---|
68 | // makes the settings publicly available as .data("qi") |
---|
69 | elem.data("qi",settings); |
---|
70 | init(settings); |
---|
71 | |
---|
72 | function init(s) { |
---|
73 | //empty the target element - TODO:optional |
---|
74 | elem.html(''); |
---|
75 | generateWidgets(s.params, elem); |
---|
76 | } |
---|
77 | |
---|
78 | /** run through the params and generate the widget for every param */ |
---|
79 | function generateWidgets (params, trg_container) { |
---|
80 | |
---|
81 | $(trg_container).append("<form />"); |
---|
82 | var form = $(trg_container).find("form"); |
---|
83 | |
---|
84 | for ( var key in params ) { |
---|
85 | var param = params[key]; |
---|
86 | console.log("creating widget: " + param.widget + " for: " + key); |
---|
87 | // if input already exists - fill it with the default value |
---|
88 | if ($('#' + settings.input_prefix + key).length) { |
---|
89 | $('#' + settings.input_prefix + key).value = param.value; |
---|
90 | } else if (trg_container) { |
---|
91 | var label= param.label ? param.label : key; |
---|
92 | var new_input_label = param.label === '' ? $('') : $( |
---|
93 | "<label for='" + settings.input_prefix + key + "'>" + label+ "</label>" |
---|
94 | ); |
---|
95 | var new_input=null, new_widget=null; |
---|
96 | |
---|
97 | switch (param.widget) { |
---|
98 | case "text": |
---|
99 | new_input = genText(key, param); |
---|
100 | break; |
---|
101 | case "checkbox": |
---|
102 | new_input = genCheckBox(key, param); |
---|
103 | break; |
---|
104 | case "hidden": |
---|
105 | new_input = genHidden(key, param); |
---|
106 | break; |
---|
107 | case "submit": |
---|
108 | new_input = genSubmit (key, param); |
---|
109 | break; |
---|
110 | case "selectone": |
---|
111 | new_input = genCombo(key, param); |
---|
112 | break; |
---|
113 | case "multiselect": |
---|
114 | var elems = genMultiselect(key, param); |
---|
115 | new_input = elems[0]; |
---|
116 | new_widget = elems[1]; |
---|
117 | break; |
---|
118 | case "autocomplete": |
---|
119 | new_input = genAutocomplete (key, param); |
---|
120 | break; |
---|
121 | case "cql": |
---|
122 | var cql_elems = QueryInput_CQL.genCQLInput(key, param); |
---|
123 | new_input = cql_elems[0]; |
---|
124 | new_widget = cql_elems[1]; |
---|
125 | break; |
---|
126 | case "vkb-cql": |
---|
127 | var cql_elems = QueryInput_CQL.genCQLInput(key, param); |
---|
128 | new_input = genVKBCombo(key, param, cql_elems[0]); |
---|
129 | new_widget = cql_elems[1]; |
---|
130 | break; |
---|
131 | case "link": |
---|
132 | new_input = genLink (key, param); |
---|
133 | break; |
---|
134 | case "slider": |
---|
135 | var slider_elems = genSlider(key, param); |
---|
136 | new_input = slider_elems[0]; |
---|
137 | new_widget = slider_elems[1]; |
---|
138 | break; |
---|
139 | default: |
---|
140 | console.log("no such widget: " + param.widget + " for: " + key); |
---|
141 | } |
---|
142 | |
---|
143 | if (new_input) { |
---|
144 | var new_input = $(new_input); |
---|
145 | new_input.data("key", key) |
---|
146 | .addClass("type-" + param.widget + (param.additional_classes === undefined ? '' : ' ' + param.additional_classes)) |
---|
147 | .attr("id", settings.input_prefix + key) |
---|
148 | .data("param-object", param); |
---|
149 | |
---|
150 | if (param.data !== undefined) { |
---|
151 | for (var k in param.data) { |
---|
152 | new_input.attr("data-" + k, param.data[k]); |
---|
153 | } |
---|
154 | } |
---|
155 | |
---|
156 | if (param.widget !== "link") { |
---|
157 | // set initial valuelink |
---|
158 | $(new_input).val(param.value); |
---|
159 | |
---|
160 | /* update settings and widgets upon value-change */ |
---|
161 | new_input.change(function () { |
---|
162 | setParamValue(this); |
---|
163 | }); |
---|
164 | } |
---|
165 | |
---|
166 | if (new_input_label !== undefined) { |
---|
167 | new_input_label.attr('for', settings.input_prefix + key); |
---|
168 | if (param.additional_label_classes !== undefined) { |
---|
169 | new_input_label.addClass(param.additional_label_classes); |
---|
170 | } |
---|
171 | } |
---|
172 | if (settings.params[key].label_after_input === true) { |
---|
173 | $(form).append(new_input, new_input_label, new_widget); |
---|
174 | } else { |
---|
175 | $(form).append(new_input_label, new_input, new_widget); |
---|
176 | } |
---|
177 | } |
---|
178 | } |
---|
179 | } // end for |
---|
180 | |
---|
181 | |
---|
182 | } |
---|
183 | /* |
---|
184 | function formatForm(inputs) { |
---|
185 | for ( var key in inputs ) { |
---|
186 | |
---|
187 | } |
---|
188 | <table> |
---|
189 | </table> |
---|
190 | } |
---|
191 | */ |
---|
192 | function genText(key, param_settings) { |
---|
193 | |
---|
194 | var input = $("<input />"); |
---|
195 | $(input).attr("name",key); |
---|
196 | |
---|
197 | if (param_settings.size) |
---|
198 | $(input).attr("size", param_settings.size); |
---|
199 | |
---|
200 | return input; |
---|
201 | } |
---|
202 | |
---|
203 | function genCheckBox(key, param_settings) { |
---|
204 | |
---|
205 | var input = $("<input type='checkbox'/>"); |
---|
206 | $(input).attr("name", key); |
---|
207 | if (param_settings.checked !== undefined) |
---|
208 | $(input).attr("checked", param_settings.checked); |
---|
209 | |
---|
210 | return input; |
---|
211 | } |
---|
212 | |
---|
213 | function genVKBCombo(key, param_settings, preconfigured_input) { |
---|
214 | preconfigured_input.attr("data-context", param_settings.cql_config.settings.context); |
---|
215 | preconfigured_input.addClass("virtual-keyboard-input"); |
---|
216 | var input = $('<span class="virtual-keyboard-input-combo virtual-keyboard-input-above">' + |
---|
217 | $('<div>').append(preconfigured_input).html() + |
---|
218 | '<input type="checkbox" value="unused" class="virtual-keyboard-toggle" id="vkbt' + key + '"/>' + |
---|
219 | '<label for="vkbt' + key + '" class="virtual-keyboard-first-three">ÀöÌ</label>'); |
---|
220 | |
---|
221 | return input; |
---|
222 | } |
---|
223 | |
---|
224 | function genHidden(key, unused) { |
---|
225 | |
---|
226 | var input = $("<input type='hidden' />"); |
---|
227 | $(input).attr("name", key); |
---|
228 | |
---|
229 | return input; |
---|
230 | } |
---|
231 | |
---|
232 | function genLink(key, unused) { |
---|
233 | |
---|
234 | var a = $("<a>" + key + "</a>"); |
---|
235 | a.attr("href", generateLink()); |
---|
236 | |
---|
237 | $(a).mousedown(function(e) { |
---|
238 | $(this).attr("target", "_blank"); |
---|
239 | $(this).attr("href", generateLink()); |
---|
240 | }); |
---|
241 | return a; |
---|
242 | } |
---|
243 | |
---|
244 | function genSubmit(key, param_settings) { |
---|
245 | |
---|
246 | var input = $("<input type='submit'/>"); |
---|
247 | $(input).attr("name",key); |
---|
248 | $(input).attr("value",param_settings.label); |
---|
249 | return input; |
---|
250 | } |
---|
251 | |
---|
252 | /** generating our own comboboxes, because very annoying trying to use some of existing jquery plugins (easyui.combo, combobox, jquery-ui.autocomplete) */ |
---|
253 | function genCombo (key, param_settings) { |
---|
254 | |
---|
255 | var select = $("<select id='widget-" + key + "' />"); |
---|
256 | //select.attr("id", settings.input_prefix + key) |
---|
257 | |
---|
258 | if (param_settings.static_source) { |
---|
259 | //var scanURL = settings.fcs_source + param_settings.index |
---|
260 | var source_url = param_settings.static_source.replace(/&/g, '&'); |
---|
261 | // if static source - try to retrieve the data |
---|
262 | $.getJSON(source_url, function(data) { |
---|
263 | param_settings.values = data.terms; |
---|
264 | param_settings.values.forEach(function(v) { $(select).append("<option value='" + v.value + "' >" + v.label + "</option>") }); |
---|
265 | //console.log($(input).autocomplete().source); |
---|
266 | }); |
---|
267 | |
---|
268 | //param_settings.source = fcsScan; |
---|
269 | } else if (param_settings.values) { |
---|
270 | // $(input).autocomplete(param_settings); |
---|
271 | if (typeof param_settings.values[0] ==='object') {// accept format with value and label |
---|
272 | param_settings.values.forEach(function(v) { $(select).append("<option value='" + v.value +"' >" + v.label + "</option>") }); |
---|
273 | } else { |
---|
274 | param_settings.values.forEach(function(v) { $(select).append("<option value='" + v +"' >" + v + "</option>") }); |
---|
275 | } |
---|
276 | } else { /* if no values, rather make a textbox out of it? */ |
---|
277 | //select = |
---|
278 | } |
---|
279 | |
---|
280 | select.attr("id", settings.input_prefix + key) |
---|
281 | return select; |
---|
282 | } |
---|
283 | |
---|
284 | /** generate autocomplete */ |
---|
285 | function genAutocomplete (key, param_settings) { |
---|
286 | |
---|
287 | var input = $("<input />"); |
---|
288 | $(input).attr("name",key) |
---|
289 | // console.log(key, param_settings.static_source); |
---|
290 | if (param_settings.static_source) { |
---|
291 | //var scanURL = settings.fcs_source + param_settings.index |
---|
292 | var source_url = param_settings.static_source.replace(/&/g, '&'); |
---|
293 | // if static source - try to retrieve the data |
---|
294 | $.getJSON(source_url, function(data) { |
---|
295 | param_settings.source = data.terms |
---|
296 | $(input).autocomplete(param_settings); |
---|
297 | //console.log($(input).autocomplete().source); |
---|
298 | }); |
---|
299 | |
---|
300 | //param_settings.source = fcsScan; |
---|
301 | } else { |
---|
302 | $(input).autocomplete(param_settings); |
---|
303 | } |
---|
304 | |
---|
305 | return input; |
---|
306 | } |
---|
307 | |
---|
308 | /** generate a multiselect*/ |
---|
309 | function genMultiselect(key, param_settings) { |
---|
310 | |
---|
311 | var parent = $("<div/>"); |
---|
312 | var select = $("<select multiple='multiple' id='widget-" + key + "' />"); |
---|
313 | select.attr("name", key); |
---|
314 | //select.attr("id", settings.input_prefix + key) |
---|
315 | parent.append(select); |
---|
316 | |
---|
317 | if (param_settings.static_source) { |
---|
318 | //var scanURL = settings.fcs_source + param_settings.index |
---|
319 | var source_url = param_settings.static_source.replace(/&/g, '&'); |
---|
320 | // if static source - try to retrieve the data |
---|
321 | $.getJSON(source_url, function (data) { |
---|
322 | param_settings.values = data.terms |
---|
323 | param_settings.values.forEach(function (v) { |
---|
324 | $(select).append("<option value='" + v.value + "' >" + v.label + "</option>") |
---|
325 | }); |
---|
326 | //console.log($(input).autocomplete().source); |
---|
327 | }); |
---|
328 | |
---|
329 | //param_settings.source = fcsScan; |
---|
330 | } |
---|
331 | |
---|
332 | |
---|
333 | else if (param_settings.values) { |
---|
334 | // $(input).autocomplete(param_settings); |
---|
335 | param_settings.values.forEach(function (v) { |
---|
336 | $(select).append("<option value='" + v + "' >" + v + "</option>") |
---|
337 | }); |
---|
338 | } else { /* if no values, rather make a textbox out of it? */ |
---|
339 | //select = |
---|
340 | } |
---|
341 | |
---|
342 | select.attr("id", settings.input_prefix + key) |
---|
343 | select.chosen(param_settings); |
---|
344 | return [select, parent.find("#input_context_chosen")]; |
---|
345 | } |
---|
346 | |
---|
347 | |
---|
348 | function fcsScan(request, response) { |
---|
349 | response($.ui.autocomplete.filter( |
---|
350 | scan.terms, request.term)); |
---|
351 | // extractLast( request.term ) |
---|
352 | } |
---|
353 | |
---|
354 | /** generate a slider based on settings |
---|
355 | @returns an array of two elements: actual input-element with value and a div-container for the slider widget |
---|
356 | */ |
---|
357 | function genSlider (key, param_settings) { |
---|
358 | |
---|
359 | var new_input = $("<input />"); |
---|
360 | new_input.attr("id", settings.input_prefix + key) |
---|
361 | .val(param_settings.value) |
---|
362 | .attr("size", 3); |
---|
363 | |
---|
364 | var new_widget = $("<div class='widget-" + param_settings.widget + "'></div>"); |
---|
365 | new_widget.attr("id", "widget-" + key) |
---|
366 | .css(settings.slider_style) |
---|
367 | .slider( param_settings) |
---|
368 | |
---|
369 | // set both-ways references between the input-field and its slider - necessary for updating |
---|
370 | .data("related-input-field",new_input) |
---|
371 | .data("related-widget",new_widget); |
---|
372 | |
---|
373 | new_widget.bind("slidechange", function(event, ui) { |
---|
374 | $(this).data("related-input-field").val(ui.value); |
---|
375 | // update the settings-object, but with the (updated) value of the related input-field |
---|
376 | setParamValue($(this).data("related-input-field")); |
---|
377 | }); |
---|
378 | |
---|
379 | /* update the widget upon input value-change (updating the settings-value is handled in the general part */ |
---|
380 | new_input.bind("change", function () { |
---|
381 | var related_widget = $(this).data("related-widget"); |
---|
382 | if ($(related_widget).hasClass("widget-slider")) { |
---|
383 | $(related_widget).slider("option", "value", $(this).val()); } |
---|
384 | }); |
---|
385 | |
---|
386 | return [new_input,new_widget]; |
---|
387 | } |
---|
388 | |
---|
389 | |
---|
390 | /** update the current value in settings */ |
---|
391 | function setParamValue(input_object) { |
---|
392 | var param_object = $(input_object).data("param-object"); |
---|
393 | param_object.value= $(input_object).val(); |
---|
394 | var key = $(input_object).data("key"); |
---|
395 | var value = settings.params[key].value; |
---|
396 | |
---|
397 | // callback: |
---|
398 | settings.onValueChanged.call( input_object,value ); |
---|
399 | return value; |
---|
400 | } |
---|
401 | |
---|
402 | /** generate a query-link out of the current values of the params */ |
---|
403 | function generateLink() |
---|
404 | { |
---|
405 | var url = "?"; |
---|
406 | |
---|
407 | for ( var key in settings.params) { |
---|
408 | if (settings.params[key].value) { |
---|
409 | url += key + "=" + settings.params[key].value + "&"; |
---|
410 | } |
---|
411 | } |
---|
412 | |
---|
413 | return url; |
---|
414 | } |
---|
415 | |
---|
416 | /** overwrite settings with param-values from the URL-search string if available |
---|
417 | not using $.extend(), because we still want only known/defined params overriden, not adding new params that might be in the url (?) */ |
---|
418 | function blendInParams() { |
---|
419 | var params= getUrlParams(); |
---|
420 | for ( var key in settings.params ) { |
---|
421 | if (params[key]) {settings.params[key].value=params[key]; } |
---|
422 | } |
---|
423 | } |
---|
424 | |
---|
425 | /** get params from the uri */ |
---|
426 | function getUrlParams() { |
---|
427 | var currentURI = new URI(); |
---|
428 | var params = currentURI.search(true); |
---|
429 | return params; |
---|
430 | } |
---|
431 | |
---|
432 | |
---|
433 | |
---|
434 | }; // end $.fn.QueryInput |
---|
435 | |
---|
436 | |
---|
437 | /* TODO: add defaults for widgets, like: |
---|
438 | widgets: {slider: {style:{width:"80px", display:"inline-block", "font-size": "70%", margin: "6px 12px 0 2px"}}}, |
---|
439 | */ |
---|
440 | |
---|
441 | // publish; |
---|
442 | // this.QueryInput = module; |
---|
443 | $.fn.QueryInput = module.QueryInput; |
---|
444 | |
---|
445 | }(jQuery, console); |
---|
446 | |
---|