1 | |
---|
2 | // jQuery closure |
---|
3 | (function($) { |
---|
4 | |
---|
5 | /** |
---|
6 | * @class QueryInput |
---|
7 | * generate a customizable query_input UI, a input form with fields/widgets based on settings |
---|
8 | * options: multiple params/fields, |
---|
9 | * indexes, different widgets |
---|
10 | * |
---|
11 | * dependencies: jQuery, jquery-ui: slider, autocomplete |
---|
12 | |
---|
13 | * @author vronk, Andy Basch |
---|
14 | * @version 2013-01-17 |
---|
15 | */ |
---|
16 | /* we could make it a class (instead of jQuery plugin) |
---|
17 | function QueryInput(elem,s) */ |
---|
18 | $.fn.QueryInput = function (options) |
---|
19 | { |
---|
20 | /** the dom-element to generate the query input in */ |
---|
21 | var elem=this; |
---|
22 | |
---|
23 | /** main variable holding all the settings for qi, especially also all params and their allowed values, and their current value |
---|
24 | * it is constructed here by merging the default and the user options passed as parameter to .QueryInput() |
---|
25 | */ |
---|
26 | var settings = $.extend(true, {}, defaults, options); |
---|
27 | blendInParams(settings.params, getUrlParams(location.search)) |
---|
28 | |
---|
29 | // makes the settings publicly available as .data("qi") |
---|
30 | elem.data("qi",settings); |
---|
31 | init(settings); |
---|
32 | |
---|
33 | function init(s) { |
---|
34 | //empty the target element - TODO:optional |
---|
35 | elem.html(''); |
---|
36 | generateWidgets(s.params, elem); |
---|
37 | } |
---|
38 | |
---|
39 | /** run through the params and generate the widget for every param */ |
---|
40 | function generateWidgets (params, trg_container) { |
---|
41 | |
---|
42 | $(trg_container).append("<form />"); |
---|
43 | var form = $(trg_container).find("form"); |
---|
44 | |
---|
45 | for ( var key in params ) { |
---|
46 | var param = params[key]; |
---|
47 | // if input already exists - fill it with the default value |
---|
48 | if ($('#' + settings.input_prefix + key).length) { |
---|
49 | $('#' + settings.input_prefix + key).value = param.value; |
---|
50 | } else if (trg_container) { |
---|
51 | var label= param.label ? param.label : key; |
---|
52 | var new_input_label = param.label=='' ? '' : "<label>" + label+ "</label>"; |
---|
53 | var new_input=null, new_widget=null; |
---|
54 | |
---|
55 | switch (param.widget) { |
---|
56 | case "text": |
---|
57 | new_input = genText(key, param); |
---|
58 | break; |
---|
59 | case "submit": |
---|
60 | new_input = genSubmit (key, param); |
---|
61 | break; |
---|
62 | case "selectone": |
---|
63 | new_input = genCombo(key, param); |
---|
64 | break; |
---|
65 | case "autocomplete": |
---|
66 | new_input = genAutocomplete (key, param); |
---|
67 | break; |
---|
68 | case "cql": |
---|
69 | var cql_elems = genCQLInput(key, param); |
---|
70 | new_input = cql_elems[0]; |
---|
71 | new_widget = cql_elems[1]; |
---|
72 | break; |
---|
73 | case "link": |
---|
74 | new_input = genLink (key, param); |
---|
75 | break; |
---|
76 | case "slider": |
---|
77 | var slider_elems = genSlider(key, param); |
---|
78 | new_input = slider_elems[0]; |
---|
79 | new_widget = slider_elems[1]; |
---|
80 | break; |
---|
81 | default: |
---|
82 | console.log("no such widget: " + param.widget); |
---|
83 | } |
---|
84 | |
---|
85 | if (new_input) { |
---|
86 | $(new_input).data("key", key) |
---|
87 | .addClass("type-" + param.widget) |
---|
88 | .attr("id", settings.input_prefix + key) |
---|
89 | .data("param-object", param); |
---|
90 | |
---|
91 | if (param.widget!="link") { |
---|
92 | // set initial valuelink |
---|
93 | $(new_input).val(param.value); |
---|
94 | |
---|
95 | /* update settings and widgets upon value-change */ |
---|
96 | new_input.change(function () { |
---|
97 | setParamValue(this); |
---|
98 | }); |
---|
99 | } |
---|
100 | |
---|
101 | $(form).append(new_input_label, new_input, new_widget); |
---|
102 | // inputs.push(key, new_input_label, new_input, new_widget]); |
---|
103 | } |
---|
104 | } |
---|
105 | } // end for |
---|
106 | |
---|
107 | |
---|
108 | } |
---|
109 | /* |
---|
110 | function formatForm(inputs) { |
---|
111 | for ( var key in inputs ) { |
---|
112 | |
---|
113 | } |
---|
114 | <table> |
---|
115 | </table> |
---|
116 | } |
---|
117 | */ |
---|
118 | function genText(key, param_settings) { |
---|
119 | |
---|
120 | var input = $("<input />"); |
---|
121 | $(input).attr("name",key); |
---|
122 | |
---|
123 | return input; |
---|
124 | } |
---|
125 | |
---|
126 | function genLink(key, param_settings) { |
---|
127 | |
---|
128 | var a = $("<a>" + key + "</a>"); |
---|
129 | a.attr("href", generateLink()); |
---|
130 | |
---|
131 | $(a).mousedown(function(e) { |
---|
132 | $(this).attr("target", "_blank"); |
---|
133 | $(this).attr("href", generateLink()); |
---|
134 | }); |
---|
135 | return a; |
---|
136 | } |
---|
137 | |
---|
138 | function genSubmit(key, param_settings) { |
---|
139 | |
---|
140 | var input = $("<input type='submit'/>"); |
---|
141 | $(input).attr("name",key); |
---|
142 | $(input).attr("value",param_settings.label); |
---|
143 | return input; |
---|
144 | } |
---|
145 | |
---|
146 | /** generating our own comboboxes, because very annoying trying to use some of existing jquery plugins (easyui.combo, combobox, jquery-ui.autocomplete) */ |
---|
147 | function genCombo (key, param_settings) { |
---|
148 | |
---|
149 | var select = $("<select id='widget-" + key + "' />"); |
---|
150 | //select.attr("id", settings.input_prefix + key) |
---|
151 | |
---|
152 | if (param_settings.static_source) { |
---|
153 | //var scanURL = settings.fcs_source + param_settings.index |
---|
154 | var source_url = param_settings.static_source.replace(/&/g,'&'); |
---|
155 | // if static source - try to retrieve the data |
---|
156 | $.getJSON(source_url, function(data) { |
---|
157 | param_settings.values = data.terms |
---|
158 | param_settings.values.forEach(function(v) { $(select).append("<option value='" + v.value +"' >" + v.label + "</option>") }); |
---|
159 | //console.log($(input).autocomplete().source); |
---|
160 | }); |
---|
161 | |
---|
162 | //param_settings.source = fcsScan; |
---|
163 | } else if (param_settings.values) { |
---|
164 | // $(input).autocomplete(param_settings); |
---|
165 | if (typeof param_settings.values[0] ==='object') {// accept format with value and label |
---|
166 | param_settings.values.forEach(function(v) { $(select).append("<option value='" + v.value +"' >" + v.label + "</option>") }); |
---|
167 | } else { |
---|
168 | param_settings.values.forEach(function(v) { $(select).append("<option value='" + v +"' >" + v + "</option>") }); |
---|
169 | } |
---|
170 | } else { /* if no values, rather make a textbox out of it? */ |
---|
171 | //select = |
---|
172 | } |
---|
173 | |
---|
174 | select.attr("id", settings.input_prefix + key) |
---|
175 | return select; |
---|
176 | } |
---|
177 | |
---|
178 | /** generate autocomplete */ |
---|
179 | function genAutocomplete (key, param_settings) { |
---|
180 | |
---|
181 | var input = $("<input />"); |
---|
182 | $(input).attr("name",key) |
---|
183 | // console.log(key, param_settings.static_source); |
---|
184 | if (param_settings.static_source) { |
---|
185 | //var scanURL = settings.fcs_source + param_settings.index |
---|
186 | var source_url = param_settings.static_source.replace(/&/g,'&'); |
---|
187 | // if static source - try to retrieve the data |
---|
188 | $.getJSON(source_url, function(data) { |
---|
189 | param_settings.source = data.terms |
---|
190 | $(input).autocomplete(param_settings); |
---|
191 | //console.log($(input).autocomplete().source); |
---|
192 | }); |
---|
193 | |
---|
194 | //param_settings.source = fcsScan; |
---|
195 | } else { |
---|
196 | $(input).autocomplete(param_settings); |
---|
197 | } |
---|
198 | |
---|
199 | return input; |
---|
200 | } |
---|
201 | |
---|
202 | |
---|
203 | function fcsScan(request, response) { |
---|
204 | response( $.ui.autocomplete.filter( |
---|
205 | scan.terms, request.term ) ); |
---|
206 | // extractLast( request.term ) |
---|
207 | } |
---|
208 | |
---|
209 | /** generate a slider based on settings |
---|
210 | @returns an array of two elements: actual input-element with value and a div-container for the slider widget |
---|
211 | */ |
---|
212 | function genSlider (key, param_settings) { |
---|
213 | |
---|
214 | var new_input = $("<input />"); |
---|
215 | new_input.attr("id", settings.input_prefix + key) |
---|
216 | .val(param_settings.value) |
---|
217 | .attr("size", 3); |
---|
218 | |
---|
219 | var new_widget = $("<div class='widget-" + param_settings.widget + "'></div>"); |
---|
220 | new_widget.attr("id", "widget-" + key) |
---|
221 | .css(settings.slider_style) |
---|
222 | .slider( param_settings) |
---|
223 | |
---|
224 | // set both-ways references between the input-field and its slider - necessary for updating |
---|
225 | .data("related-input-field",new_input) |
---|
226 | .data("related-widget",new_widget); |
---|
227 | |
---|
228 | new_widget.bind( "slidechange", function(event, ui) { |
---|
229 | $(this).data("related-input-field").val(ui.value); |
---|
230 | // update the settings-object, but with the (updated) value of the related input-field |
---|
231 | setParamValue($(this).data("related-input-field")); |
---|
232 | }); |
---|
233 | |
---|
234 | /* update the widget upon input value-change (updating the settings-value is handled in the general part */ |
---|
235 | new_input.bind("change", function () { |
---|
236 | var related_widget = $(this).data("related-widget"); |
---|
237 | if ( $(related_widget).hasClass("widget-slider")) {$(related_widget).slider("option", "value", $(this).val()); } |
---|
238 | }); |
---|
239 | |
---|
240 | return [new_input,new_widget]; |
---|
241 | } |
---|
242 | |
---|
243 | |
---|
244 | /** gets the current value for a parameter |
---|
245 | accepting settings as reliable source of current value |
---|
246 | i.e. changes in input have to change the .value in settings. |
---|
247 | This is assured by calling setParamValue upon input-change. |
---|
248 | public by calling: $(elem).data("qi").getParamValue(param_key); |
---|
249 | @public |
---|
250 | */ |
---|
251 | settings.getParamValue = function(key) { |
---|
252 | if (this.params[key]) { |
---|
253 | return this.params[key].value |
---|
254 | } else { |
---|
255 | return "" |
---|
256 | } |
---|
257 | } |
---|
258 | |
---|
259 | /** allow to update the current value in settings from outside */ |
---|
260 | settings.setParamValue = function(key, value) { |
---|
261 | |
---|
262 | if (settings.params[key]) { |
---|
263 | settings.params[key].value = value |
---|
264 | } |
---|
265 | // callback: |
---|
266 | settings.onValueChanged.call( settings,value ); |
---|
267 | return value |
---|
268 | } |
---|
269 | |
---|
270 | /** update the current value in settings */ |
---|
271 | function setParamValue(input_object) { |
---|
272 | var param_object = $(input_object).data("param-object"); |
---|
273 | param_object.value= $(input_object).val(); |
---|
274 | var key = $(input_object).data("key"); |
---|
275 | var value = settings.params[key].value; |
---|
276 | |
---|
277 | // callback: |
---|
278 | settings.onValueChanged.call( input_object,value ); |
---|
279 | return value |
---|
280 | } |
---|
281 | |
---|
282 | |
---|
283 | /** get params from the uri */ |
---|
284 | function getUrlParams(url) |
---|
285 | { |
---|
286 | var urlParams = {}; |
---|
287 | if (url != undefined) |
---|
288 | { |
---|
289 | var match; |
---|
290 | var pl = /\+/g; // Regex for replacing addition symbol with a space |
---|
291 | var search = /([^&=]+)=?([^&]*)/g; |
---|
292 | var decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }; |
---|
293 | |
---|
294 | var query = ""; |
---|
295 | var qmPos = url.indexOf('?'); |
---|
296 | if (qmPos != -1) |
---|
297 | query = url.substr(qmPos + 1); |
---|
298 | else |
---|
299 | query = url; |
---|
300 | |
---|
301 | while (match = search.exec(query)) |
---|
302 | urlParams[decode(match[1])] = decode(match[2]); |
---|
303 | } |
---|
304 | |
---|
305 | return urlParams; |
---|
306 | } |
---|
307 | |
---|
308 | function blendInParams(settings_params, params) { |
---|
309 | |
---|
310 | for ( var key in settings_params ) { |
---|
311 | if (params[key]) {settings_params[key].value=params[key]; } |
---|
312 | } |
---|
313 | } |
---|
314 | |
---|
315 | /** generate a query-link out of the current values of the params */ |
---|
316 | function generateLink() |
---|
317 | { |
---|
318 | var url="?"; |
---|
319 | |
---|
320 | for ( var key in settings.params) { |
---|
321 | if (settings.params[key].value) { |
---|
322 | url += key + "=" + settings.params[key].value + "&"; |
---|
323 | } |
---|
324 | } |
---|
325 | |
---|
326 | return url; |
---|
327 | } |
---|
328 | |
---|
329 | |
---|
330 | // } |
---|
331 | |
---|
332 | } // end $.fn.QueryInput |
---|
333 | |
---|
334 | |
---|
335 | // could expose the defaults: $.fn.QueryInput.defaults = |
---|
336 | //{q:{label:"Query", widget:"text"}, submit:{value:"Search", widget:"submit"}} |
---|
337 | var defaults = {params: {}, |
---|
338 | input_prefix:"input-", |
---|
339 | slider_style:{width:"80px", display:"inline-block", "font-size": "70%", margin: "6px 12px 0 2px"}, |
---|
340 | onValueChanged : function() {}, |
---|
341 | fcs_source: "http://193.170.82.207:8680/exist/apps/sade/amc/fcs?operation=scan&x-format=json&scanClause=" |
---|
342 | }; |
---|
343 | |
---|
344 | /* TODO: add defaults for widgets, like: |
---|
345 | widgets: {slider: {style:{width:"80px", display:"inline-block", "font-size": "70%", margin: "6px 12px 0 2px"}}}, |
---|
346 | */ |
---|
347 | |
---|
348 | })(jQuery, this); |
---|
349 | |
---|