Total Complexity | 276 |
Complexity/F | 2.58 |
Lines of Code | 1441 |
Function Count | 107 |
Duplicated Lines | 1441 |
Ratio | 100 % |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like public/lib/semantic/components/search.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | /*! |
||
11 | View Code Duplication | ;(function ($, window, document, undefined) { |
|
|
|||
12 | |||
13 | "use strict"; |
||
14 | |||
15 | window = (typeof window != 'undefined' && window.Math == Math) |
||
16 | ? window |
||
17 | : (typeof self != 'undefined' && self.Math == Math) |
||
18 | ? self |
||
19 | : Function('return this')() |
||
20 | ; |
||
21 | |||
22 | $.fn.search = function(parameters) { |
||
23 | var |
||
24 | $allModules = $(this), |
||
25 | moduleSelector = $allModules.selector || '', |
||
26 | |||
27 | time = new Date().getTime(), |
||
28 | performance = [], |
||
29 | |||
30 | query = arguments[0], |
||
31 | methodInvoked = (typeof query == 'string'), |
||
32 | queryArguments = [].slice.call(arguments, 1), |
||
33 | returnedValue |
||
34 | ; |
||
35 | $(this) |
||
36 | .each(function() { |
||
37 | var |
||
38 | settings = ( $.isPlainObject(parameters) ) |
||
39 | ? $.extend(true, {}, $.fn.search.settings, parameters) |
||
40 | : $.extend({}, $.fn.search.settings), |
||
41 | |||
42 | className = settings.className, |
||
43 | metadata = settings.metadata, |
||
44 | regExp = settings.regExp, |
||
45 | fields = settings.fields, |
||
46 | selector = settings.selector, |
||
47 | error = settings.error, |
||
48 | namespace = settings.namespace, |
||
49 | |||
50 | eventNamespace = '.' + namespace, |
||
51 | moduleNamespace = namespace + '-module', |
||
52 | |||
53 | $module = $(this), |
||
54 | $prompt = $module.find(selector.prompt), |
||
55 | $searchButton = $module.find(selector.searchButton), |
||
56 | $results = $module.find(selector.results), |
||
57 | $result = $module.find(selector.result), |
||
58 | $category = $module.find(selector.category), |
||
59 | |||
60 | element = this, |
||
61 | instance = $module.data(moduleNamespace), |
||
62 | |||
63 | disabledBubbled = false, |
||
64 | resultsDismissed = false, |
||
65 | |||
66 | module |
||
67 | ; |
||
68 | |||
69 | module = { |
||
70 | |||
71 | initialize: function() { |
||
72 | module.verbose('Initializing module'); |
||
73 | module.determine.searchFields(); |
||
74 | module.bind.events(); |
||
75 | module.set.type(); |
||
76 | module.create.results(); |
||
77 | module.instantiate(); |
||
78 | }, |
||
79 | instantiate: function() { |
||
80 | module.verbose('Storing instance of module', module); |
||
81 | instance = module; |
||
82 | $module |
||
83 | .data(moduleNamespace, module) |
||
84 | ; |
||
85 | }, |
||
86 | destroy: function() { |
||
87 | module.verbose('Destroying instance'); |
||
88 | $module |
||
89 | .off(eventNamespace) |
||
90 | .removeData(moduleNamespace) |
||
91 | ; |
||
92 | }, |
||
93 | |||
94 | refresh: function() { |
||
95 | module.debug('Refreshing selector cache'); |
||
96 | $prompt = $module.find(selector.prompt); |
||
97 | $searchButton = $module.find(selector.searchButton); |
||
98 | $category = $module.find(selector.category); |
||
99 | $results = $module.find(selector.results); |
||
100 | $result = $module.find(selector.result); |
||
101 | }, |
||
102 | |||
103 | refreshResults: function() { |
||
104 | $results = $module.find(selector.results); |
||
105 | $result = $module.find(selector.result); |
||
106 | }, |
||
107 | |||
108 | bind: { |
||
109 | events: function() { |
||
110 | module.verbose('Binding events to search'); |
||
111 | if(settings.automatic) { |
||
112 | $module |
||
113 | .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input) |
||
114 | ; |
||
115 | $prompt |
||
116 | .attr('autocomplete', 'off') |
||
117 | ; |
||
118 | } |
||
119 | $module |
||
120 | // prompt |
||
121 | .on('focus' + eventNamespace, selector.prompt, module.event.focus) |
||
122 | .on('blur' + eventNamespace, selector.prompt, module.event.blur) |
||
123 | .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard) |
||
124 | // search button |
||
125 | .on('click' + eventNamespace, selector.searchButton, module.query) |
||
126 | // results |
||
127 | .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown) |
||
128 | .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup) |
||
129 | .on('click' + eventNamespace, selector.result, module.event.result.click) |
||
130 | ; |
||
131 | } |
||
132 | }, |
||
133 | |||
134 | determine: { |
||
135 | searchFields: function() { |
||
136 | // this makes sure $.extend does not add specified search fields to default fields |
||
137 | // this is the only setting which should not extend defaults |
||
138 | if(parameters && parameters.searchFields !== undefined) { |
||
139 | settings.searchFields = parameters.searchFields; |
||
140 | } |
||
141 | } |
||
142 | }, |
||
143 | |||
144 | event: { |
||
145 | input: function() { |
||
146 | if(settings.searchDelay) { |
||
147 | clearTimeout(module.timer); |
||
148 | module.timer = setTimeout(function() { |
||
149 | if(module.is.focused()) { |
||
150 | module.query(); |
||
151 | } |
||
152 | }, settings.searchDelay); |
||
153 | } |
||
154 | else { |
||
155 | module.query(); |
||
156 | } |
||
157 | }, |
||
158 | focus: function() { |
||
159 | module.set.focus(); |
||
160 | if(settings.searchOnFocus && module.has.minimumCharacters() ) { |
||
161 | module.query(function() { |
||
162 | if(module.can.show() ) { |
||
163 | module.showResults(); |
||
164 | } |
||
165 | }); |
||
166 | } |
||
167 | }, |
||
168 | blur: function(event) { |
||
169 | var |
||
170 | pageLostFocus = (document.activeElement === this), |
||
171 | callback = function() { |
||
172 | module.cancel.query(); |
||
173 | module.remove.focus(); |
||
174 | module.timer = setTimeout(module.hideResults, settings.hideDelay); |
||
175 | } |
||
176 | ; |
||
177 | if(pageLostFocus) { |
||
178 | return; |
||
179 | } |
||
180 | resultsDismissed = false; |
||
181 | if(module.resultsClicked) { |
||
182 | module.debug('Determining if user action caused search to close'); |
||
183 | $module |
||
184 | .one('click.close' + eventNamespace, selector.results, function(event) { |
||
185 | if(module.is.inMessage(event) || disabledBubbled) { |
||
186 | $prompt.focus(); |
||
187 | return; |
||
188 | } |
||
189 | disabledBubbled = false; |
||
190 | if( !module.is.animating() && !module.is.hidden()) { |
||
191 | callback(); |
||
192 | } |
||
193 | }) |
||
194 | ; |
||
195 | } |
||
196 | else { |
||
197 | module.debug('Input blurred without user action, closing results'); |
||
198 | callback(); |
||
199 | } |
||
200 | }, |
||
201 | result: { |
||
202 | mousedown: function() { |
||
203 | module.resultsClicked = true; |
||
204 | }, |
||
205 | mouseup: function() { |
||
206 | module.resultsClicked = false; |
||
207 | }, |
||
208 | click: function(event) { |
||
209 | module.debug('Search result selected'); |
||
210 | var |
||
211 | $result = $(this), |
||
212 | $title = $result.find(selector.title).eq(0), |
||
213 | $link = $result.is('a[href]') |
||
214 | ? $result |
||
215 | : $result.find('a[href]').eq(0), |
||
216 | href = $link.attr('href') || false, |
||
217 | target = $link.attr('target') || false, |
||
218 | title = $title.html(), |
||
219 | // title is used for result lookup |
||
220 | value = ($title.length > 0) |
||
221 | ? $title.text() |
||
222 | : false, |
||
223 | results = module.get.results(), |
||
224 | result = $result.data(metadata.result) || module.get.result(value, results), |
||
225 | returnedValue |
||
226 | ; |
||
227 | if( $.isFunction(settings.onSelect) ) { |
||
228 | if(settings.onSelect.call(element, result, results) === false) { |
||
229 | module.debug('Custom onSelect callback cancelled default select action'); |
||
230 | disabledBubbled = true; |
||
231 | return; |
||
232 | } |
||
233 | } |
||
234 | module.hideResults(); |
||
235 | if(value) { |
||
236 | module.set.value(value); |
||
237 | } |
||
238 | if(href) { |
||
239 | module.verbose('Opening search link found in result', $link); |
||
240 | if(target == '_blank' || event.ctrlKey) { |
||
241 | window.open(href); |
||
242 | } |
||
243 | else { |
||
244 | window.location.href = (href); |
||
245 | } |
||
246 | } |
||
247 | } |
||
248 | } |
||
249 | }, |
||
250 | handleKeyboard: function(event) { |
||
251 | var |
||
252 | // force selector refresh |
||
253 | $result = $module.find(selector.result), |
||
254 | $category = $module.find(selector.category), |
||
255 | $activeResult = $result.filter('.' + className.active), |
||
256 | currentIndex = $result.index( $activeResult ), |
||
257 | resultSize = $result.length, |
||
258 | hasActiveResult = $activeResult.length > 0, |
||
259 | |||
260 | keyCode = event.which, |
||
261 | keys = { |
||
262 | backspace : 8, |
||
263 | enter : 13, |
||
264 | escape : 27, |
||
265 | upArrow : 38, |
||
266 | downArrow : 40 |
||
267 | }, |
||
268 | newIndex |
||
269 | ; |
||
270 | // search shortcuts |
||
271 | if(keyCode == keys.escape) { |
||
272 | module.verbose('Escape key pressed, blurring search field'); |
||
273 | module.hideResults(); |
||
274 | resultsDismissed = true; |
||
275 | } |
||
276 | if( module.is.visible() ) { |
||
277 | if(keyCode == keys.enter) { |
||
278 | module.verbose('Enter key pressed, selecting active result'); |
||
279 | if( $result.filter('.' + className.active).length > 0 ) { |
||
280 | module.event.result.click.call($result.filter('.' + className.active), event); |
||
281 | event.preventDefault(); |
||
282 | return false; |
||
283 | } |
||
284 | } |
||
285 | else if(keyCode == keys.upArrow && hasActiveResult) { |
||
286 | module.verbose('Up key pressed, changing active result'); |
||
287 | newIndex = (currentIndex - 1 < 0) |
||
288 | ? currentIndex |
||
289 | : currentIndex - 1 |
||
290 | ; |
||
291 | $category |
||
292 | .removeClass(className.active) |
||
293 | ; |
||
294 | $result |
||
295 | .removeClass(className.active) |
||
296 | .eq(newIndex) |
||
297 | .addClass(className.active) |
||
298 | .closest($category) |
||
299 | .addClass(className.active) |
||
300 | ; |
||
301 | event.preventDefault(); |
||
302 | } |
||
303 | else if(keyCode == keys.downArrow) { |
||
304 | module.verbose('Down key pressed, changing active result'); |
||
305 | newIndex = (currentIndex + 1 >= resultSize) |
||
306 | ? currentIndex |
||
307 | : currentIndex + 1 |
||
308 | ; |
||
309 | $category |
||
310 | .removeClass(className.active) |
||
311 | ; |
||
312 | $result |
||
313 | .removeClass(className.active) |
||
314 | .eq(newIndex) |
||
315 | .addClass(className.active) |
||
316 | .closest($category) |
||
317 | .addClass(className.active) |
||
318 | ; |
||
319 | event.preventDefault(); |
||
320 | } |
||
321 | } |
||
322 | else { |
||
323 | // query shortcuts |
||
324 | if(keyCode == keys.enter) { |
||
325 | module.verbose('Enter key pressed, executing query'); |
||
326 | module.query(); |
||
327 | module.set.buttonPressed(); |
||
328 | $prompt.one('keyup', module.remove.buttonFocus); |
||
329 | } |
||
330 | } |
||
331 | }, |
||
332 | |||
333 | setup: { |
||
334 | api: function(searchTerm, callback) { |
||
335 | var |
||
336 | apiSettings = { |
||
337 | debug : settings.debug, |
||
338 | on : false, |
||
339 | cache : true, |
||
340 | action : 'search', |
||
341 | urlData : { |
||
342 | query : searchTerm |
||
343 | }, |
||
344 | onSuccess : function(response) { |
||
345 | module.parse.response.call(element, response, searchTerm); |
||
346 | callback(); |
||
347 | }, |
||
348 | onFailure : function() { |
||
349 | module.displayMessage(error.serverError); |
||
350 | callback(); |
||
351 | }, |
||
352 | onAbort : function(response) { |
||
353 | }, |
||
354 | onError : module.error |
||
355 | }, |
||
356 | searchHTML |
||
357 | ; |
||
358 | $.extend(true, apiSettings, settings.apiSettings); |
||
359 | module.verbose('Setting up API request', apiSettings); |
||
360 | $module.api(apiSettings); |
||
361 | } |
||
362 | }, |
||
363 | |||
364 | can: { |
||
365 | useAPI: function() { |
||
366 | return $.fn.api !== undefined; |
||
367 | }, |
||
368 | show: function() { |
||
369 | return module.is.focused() && !module.is.visible() && !module.is.empty(); |
||
370 | }, |
||
371 | transition: function() { |
||
372 | return settings.transition && $.fn.transition !== undefined && $module.transition('is supported'); |
||
373 | } |
||
374 | }, |
||
375 | |||
376 | is: { |
||
377 | animating: function() { |
||
378 | return $results.hasClass(className.animating); |
||
379 | }, |
||
380 | hidden: function() { |
||
381 | return $results.hasClass(className.hidden); |
||
382 | }, |
||
383 | inMessage: function(event) { |
||
384 | if(!event.target) { |
||
385 | return; |
||
386 | } |
||
387 | var |
||
388 | $target = $(event.target), |
||
389 | isInDOM = $.contains(document.documentElement, event.target) |
||
390 | ; |
||
391 | return (isInDOM && $target.closest(selector.message).length > 0); |
||
392 | }, |
||
393 | empty: function() { |
||
394 | return ($results.html() === ''); |
||
395 | }, |
||
396 | visible: function() { |
||
397 | return ($results.filter(':visible').length > 0); |
||
398 | }, |
||
399 | focused: function() { |
||
400 | return ($prompt.filter(':focus').length > 0); |
||
401 | } |
||
402 | }, |
||
403 | |||
404 | get: { |
||
405 | inputEvent: function() { |
||
406 | var |
||
407 | prompt = $prompt[0], |
||
408 | inputEvent = (prompt !== undefined && prompt.oninput !== undefined) |
||
409 | ? 'input' |
||
410 | : (prompt !== undefined && prompt.onpropertychange !== undefined) |
||
411 | ? 'propertychange' |
||
412 | : 'keyup' |
||
413 | ; |
||
414 | return inputEvent; |
||
415 | }, |
||
416 | value: function() { |
||
417 | return $prompt.val(); |
||
418 | }, |
||
419 | results: function() { |
||
420 | var |
||
421 | results = $module.data(metadata.results) |
||
422 | ; |
||
423 | return results; |
||
424 | }, |
||
425 | result: function(value, results) { |
||
426 | var |
||
427 | lookupFields = ['title', 'id'], |
||
428 | result = false |
||
429 | ; |
||
430 | value = (value !== undefined) |
||
431 | ? value |
||
432 | : module.get.value() |
||
433 | ; |
||
434 | results = (results !== undefined) |
||
435 | ? results |
||
436 | : module.get.results() |
||
437 | ; |
||
438 | if(settings.type === 'category') { |
||
439 | module.debug('Finding result that matches', value); |
||
440 | $.each(results, function(index, category) { |
||
441 | if($.isArray(category.results)) { |
||
442 | result = module.search.object(value, category.results, lookupFields)[0]; |
||
443 | // don't continue searching if a result is found |
||
444 | if(result) { |
||
445 | return false; |
||
446 | } |
||
447 | } |
||
448 | }); |
||
449 | } |
||
450 | else { |
||
451 | module.debug('Finding result in results object', value); |
||
452 | result = module.search.object(value, results, lookupFields)[0]; |
||
453 | } |
||
454 | return result || false; |
||
455 | }, |
||
456 | }, |
||
457 | |||
458 | select: { |
||
459 | firstResult: function() { |
||
460 | module.verbose('Selecting first result'); |
||
461 | $result.first().addClass(className.active); |
||
462 | } |
||
463 | }, |
||
464 | |||
465 | set: { |
||
466 | focus: function() { |
||
467 | $module.addClass(className.focus); |
||
468 | }, |
||
469 | loading: function() { |
||
470 | $module.addClass(className.loading); |
||
471 | }, |
||
472 | value: function(value) { |
||
473 | module.verbose('Setting search input value', value); |
||
474 | $prompt |
||
475 | .val(value) |
||
476 | ; |
||
477 | }, |
||
478 | type: function(type) { |
||
479 | type = type || settings.type; |
||
480 | if(settings.type == 'category') { |
||
481 | $module.addClass(settings.type); |
||
482 | } |
||
483 | }, |
||
484 | buttonPressed: function() { |
||
485 | $searchButton.addClass(className.pressed); |
||
486 | } |
||
487 | }, |
||
488 | |||
489 | remove: { |
||
490 | loading: function() { |
||
491 | $module.removeClass(className.loading); |
||
492 | }, |
||
493 | focus: function() { |
||
494 | $module.removeClass(className.focus); |
||
495 | }, |
||
496 | buttonPressed: function() { |
||
497 | $searchButton.removeClass(className.pressed); |
||
498 | } |
||
499 | }, |
||
500 | |||
501 | query: function(callback) { |
||
502 | callback = $.isFunction(callback) |
||
503 | ? callback |
||
504 | : function(){} |
||
505 | ; |
||
506 | var |
||
507 | searchTerm = module.get.value(), |
||
508 | cache = module.read.cache(searchTerm) |
||
509 | ; |
||
510 | callback = callback || function() {}; |
||
511 | if( module.has.minimumCharacters() ) { |
||
512 | if(cache) { |
||
513 | module.debug('Reading result from cache', searchTerm); |
||
514 | module.save.results(cache.results); |
||
515 | module.addResults(cache.html); |
||
516 | module.inject.id(cache.results); |
||
517 | callback(); |
||
518 | } |
||
519 | else { |
||
520 | module.debug('Querying for', searchTerm); |
||
521 | if($.isPlainObject(settings.source) || $.isArray(settings.source)) { |
||
522 | module.search.local(searchTerm); |
||
523 | callback(); |
||
524 | } |
||
525 | else if( module.can.useAPI() ) { |
||
526 | module.search.remote(searchTerm, callback); |
||
527 | } |
||
528 | else { |
||
529 | module.error(error.source); |
||
530 | callback(); |
||
531 | } |
||
532 | } |
||
533 | settings.onSearchQuery.call(element, searchTerm); |
||
534 | } |
||
535 | else { |
||
536 | module.hideResults(); |
||
537 | } |
||
538 | }, |
||
539 | |||
540 | search: { |
||
541 | local: function(searchTerm) { |
||
542 | var |
||
543 | results = module.search.object(searchTerm, settings.content), |
||
544 | searchHTML |
||
545 | ; |
||
546 | module.set.loading(); |
||
547 | module.save.results(results); |
||
548 | module.debug('Returned local search results', results); |
||
549 | |||
550 | searchHTML = module.generateResults({ |
||
551 | results: results |
||
552 | }); |
||
553 | module.remove.loading(); |
||
554 | module.addResults(searchHTML); |
||
555 | module.inject.id(results); |
||
556 | module.write.cache(searchTerm, { |
||
557 | html : searchHTML, |
||
558 | results : results |
||
559 | }); |
||
560 | }, |
||
561 | remote: function(searchTerm, callback) { |
||
562 | callback = $.isFunction(callback) |
||
563 | ? callback |
||
564 | : function(){} |
||
565 | ; |
||
566 | if($module.api('is loading')) { |
||
567 | $module.api('abort'); |
||
568 | } |
||
569 | module.setup.api(searchTerm, callback); |
||
570 | $module |
||
571 | .api('query') |
||
572 | ; |
||
573 | }, |
||
574 | object: function(searchTerm, source, searchFields) { |
||
575 | var |
||
576 | results = [], |
||
577 | fuzzyResults = [], |
||
578 | searchExp = searchTerm.toString().replace(regExp.escape, '\\$&'), |
||
579 | matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'), |
||
580 | |||
581 | // avoid duplicates when pushing results |
||
582 | addResult = function(array, result) { |
||
583 | var |
||
584 | notResult = ($.inArray(result, results) == -1), |
||
585 | notFuzzyResult = ($.inArray(result, fuzzyResults) == -1) |
||
586 | ; |
||
587 | if(notResult && notFuzzyResult) { |
||
588 | array.push(result); |
||
589 | } |
||
590 | } |
||
591 | ; |
||
592 | source = source || settings.source; |
||
593 | searchFields = (searchFields !== undefined) |
||
594 | ? searchFields |
||
595 | : settings.searchFields |
||
596 | ; |
||
597 | |||
598 | // search fields should be array to loop correctly |
||
599 | if(!$.isArray(searchFields)) { |
||
600 | searchFields = [searchFields]; |
||
601 | } |
||
602 | |||
603 | // exit conditions if no source |
||
604 | if(source === undefined || source === false) { |
||
605 | module.error(error.source); |
||
606 | return []; |
||
607 | } |
||
608 | |||
609 | // iterate through search fields looking for matches |
||
610 | $.each(searchFields, function(index, field) { |
||
611 | $.each(source, function(label, content) { |
||
612 | var |
||
613 | fieldExists = (typeof content[field] == 'string') |
||
614 | ; |
||
615 | if(fieldExists) { |
||
616 | if( content[field].search(matchRegExp) !== -1) { |
||
617 | // content starts with value (first in results) |
||
618 | addResult(results, content); |
||
619 | } |
||
620 | else if(settings.searchFullText && module.fuzzySearch(searchTerm, content[field]) ) { |
||
621 | // content fuzzy matches (last in results) |
||
622 | addResult(fuzzyResults, content); |
||
623 | } |
||
624 | } |
||
625 | }); |
||
626 | }); |
||
627 | return $.merge(results, fuzzyResults); |
||
628 | } |
||
629 | }, |
||
630 | |||
631 | fuzzySearch: function(query, term) { |
||
632 | var |
||
633 | termLength = term.length, |
||
634 | queryLength = query.length |
||
635 | ; |
||
636 | if(typeof query !== 'string') { |
||
637 | return false; |
||
638 | } |
||
639 | query = query.toLowerCase(); |
||
640 | term = term.toLowerCase(); |
||
641 | if(queryLength > termLength) { |
||
642 | return false; |
||
643 | } |
||
644 | if(queryLength === termLength) { |
||
645 | return (query === term); |
||
646 | } |
||
647 | search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) { |
||
648 | var |
||
649 | queryCharacter = query.charCodeAt(characterIndex) |
||
650 | ; |
||
651 | while(nextCharacterIndex < termLength) { |
||
652 | if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) { |
||
653 | continue search; |
||
654 | } |
||
655 | } |
||
656 | return false; |
||
657 | } |
||
658 | return true; |
||
659 | }, |
||
660 | |||
661 | parse: { |
||
662 | response: function(response, searchTerm) { |
||
663 | var |
||
664 | searchHTML = module.generateResults(response) |
||
665 | ; |
||
666 | module.verbose('Parsing server response', response); |
||
667 | if(response !== undefined) { |
||
668 | if(searchTerm !== undefined && response[fields.results] !== undefined) { |
||
669 | module.addResults(searchHTML); |
||
670 | module.inject.id(response[fields.results]); |
||
671 | module.write.cache(searchTerm, { |
||
672 | html : searchHTML, |
||
673 | results : response[fields.results] |
||
674 | }); |
||
675 | module.save.results(response[fields.results]); |
||
676 | } |
||
677 | } |
||
678 | } |
||
679 | }, |
||
680 | |||
681 | cancel: { |
||
682 | query: function() { |
||
683 | if( module.can.useAPI() ) { |
||
684 | $module.api('abort'); |
||
685 | } |
||
686 | } |
||
687 | }, |
||
688 | |||
689 | has: { |
||
690 | minimumCharacters: function() { |
||
691 | var |
||
692 | searchTerm = module.get.value(), |
||
693 | numCharacters = searchTerm.length |
||
694 | ; |
||
695 | return (numCharacters >= settings.minCharacters); |
||
696 | }, |
||
697 | results: function() { |
||
698 | if($results.length === 0) { |
||
699 | return false; |
||
700 | } |
||
701 | var |
||
702 | html = $results.html() |
||
703 | ; |
||
704 | return html != ''; |
||
705 | } |
||
706 | }, |
||
707 | |||
708 | clear: { |
||
709 | cache: function(value) { |
||
710 | var |
||
711 | cache = $module.data(metadata.cache) |
||
712 | ; |
||
713 | if(!value) { |
||
714 | module.debug('Clearing cache', value); |
||
715 | $module.removeData(metadata.cache); |
||
716 | } |
||
717 | else if(value && cache && cache[value]) { |
||
718 | module.debug('Removing value from cache', value); |
||
719 | delete cache[value]; |
||
720 | $module.data(metadata.cache, cache); |
||
721 | } |
||
722 | } |
||
723 | }, |
||
724 | |||
725 | read: { |
||
726 | cache: function(name) { |
||
727 | var |
||
728 | cache = $module.data(metadata.cache) |
||
729 | ; |
||
730 | if(settings.cache) { |
||
731 | module.verbose('Checking cache for generated html for query', name); |
||
732 | return (typeof cache == 'object') && (cache[name] !== undefined) |
||
733 | ? cache[name] |
||
734 | : false |
||
735 | ; |
||
736 | } |
||
737 | return false; |
||
738 | } |
||
739 | }, |
||
740 | |||
741 | create: { |
||
742 | id: function(resultIndex, categoryIndex) { |
||
743 | var |
||
744 | resultID = (resultIndex + 1), // not zero indexed |
||
745 | categoryID = (categoryIndex + 1), |
||
746 | firstCharCode, |
||
747 | letterID, |
||
748 | id |
||
749 | ; |
||
750 | if(categoryIndex !== undefined) { |
||
751 | // start char code for "A" |
||
752 | letterID = String.fromCharCode(97 + categoryIndex); |
||
753 | id = letterID + resultID; |
||
754 | module.verbose('Creating category result id', id); |
||
755 | } |
||
756 | else { |
||
757 | id = resultID; |
||
758 | module.verbose('Creating result id', id); |
||
759 | } |
||
760 | return id; |
||
761 | }, |
||
762 | results: function() { |
||
763 | if($results.length === 0) { |
||
764 | $results = $('<div />') |
||
765 | .addClass(className.results) |
||
766 | .appendTo($module) |
||
767 | ; |
||
768 | } |
||
769 | } |
||
770 | }, |
||
771 | |||
772 | inject: { |
||
773 | result: function(result, resultIndex, categoryIndex) { |
||
774 | module.verbose('Injecting result into results'); |
||
775 | var |
||
776 | $selectedResult = (categoryIndex !== undefined) |
||
777 | ? $results |
||
778 | .children().eq(categoryIndex) |
||
779 | .children(selector.result).eq(resultIndex) |
||
780 | : $results |
||
781 | .children(selector.result).eq(resultIndex) |
||
782 | ; |
||
783 | module.verbose('Injecting results metadata', $selectedResult); |
||
784 | $selectedResult |
||
785 | .data(metadata.result, result) |
||
786 | ; |
||
787 | }, |
||
788 | id: function(results) { |
||
789 | module.debug('Injecting unique ids into results'); |
||
790 | var |
||
791 | // since results may be object, we must use counters |
||
792 | categoryIndex = 0, |
||
793 | resultIndex = 0 |
||
794 | ; |
||
795 | if(settings.type === 'category') { |
||
796 | // iterate through each category result |
||
797 | $.each(results, function(index, category) { |
||
798 | resultIndex = 0; |
||
799 | $.each(category.results, function(index, value) { |
||
800 | var |
||
801 | result = category.results[index] |
||
802 | ; |
||
803 | if(result.id === undefined) { |
||
804 | result.id = module.create.id(resultIndex, categoryIndex); |
||
805 | } |
||
806 | module.inject.result(result, resultIndex, categoryIndex); |
||
807 | resultIndex++; |
||
808 | }); |
||
809 | categoryIndex++; |
||
810 | }); |
||
811 | } |
||
812 | else { |
||
813 | // top level |
||
814 | $.each(results, function(index, value) { |
||
815 | var |
||
816 | result = results[index] |
||
817 | ; |
||
818 | if(result.id === undefined) { |
||
819 | result.id = module.create.id(resultIndex); |
||
820 | } |
||
821 | module.inject.result(result, resultIndex); |
||
822 | resultIndex++; |
||
823 | }); |
||
824 | } |
||
825 | return results; |
||
826 | } |
||
827 | }, |
||
828 | |||
829 | save: { |
||
830 | results: function(results) { |
||
831 | module.verbose('Saving current search results to metadata', results); |
||
832 | $module.data(metadata.results, results); |
||
833 | } |
||
834 | }, |
||
835 | |||
836 | write: { |
||
837 | cache: function(name, value) { |
||
838 | var |
||
839 | cache = ($module.data(metadata.cache) !== undefined) |
||
840 | ? $module.data(metadata.cache) |
||
841 | : {} |
||
842 | ; |
||
843 | if(settings.cache) { |
||
844 | module.verbose('Writing generated html to cache', name, value); |
||
845 | cache[name] = value; |
||
846 | $module |
||
847 | .data(metadata.cache, cache) |
||
848 | ; |
||
849 | } |
||
850 | } |
||
851 | }, |
||
852 | |||
853 | addResults: function(html) { |
||
854 | if( $.isFunction(settings.onResultsAdd) ) { |
||
855 | if( settings.onResultsAdd.call($results, html) === false ) { |
||
856 | module.debug('onResultsAdd callback cancelled default action'); |
||
857 | return false; |
||
858 | } |
||
859 | } |
||
860 | if(html) { |
||
861 | $results |
||
862 | .html(html) |
||
863 | ; |
||
864 | module.refreshResults(); |
||
865 | if(settings.selectFirstResult) { |
||
866 | module.select.firstResult(); |
||
867 | } |
||
868 | module.showResults(); |
||
869 | } |
||
870 | else { |
||
871 | module.hideResults(function() { |
||
872 | $results.empty(); |
||
873 | }); |
||
874 | } |
||
875 | }, |
||
876 | |||
877 | showResults: function(callback) { |
||
878 | callback = $.isFunction(callback) |
||
879 | ? callback |
||
880 | : function(){} |
||
881 | ; |
||
882 | if(resultsDismissed) { |
||
883 | return; |
||
884 | } |
||
885 | if(!module.is.visible() && module.has.results()) { |
||
886 | if( module.can.transition() ) { |
||
887 | module.debug('Showing results with css animations'); |
||
888 | $results |
||
889 | .transition({ |
||
890 | animation : settings.transition + ' in', |
||
891 | debug : settings.debug, |
||
892 | verbose : settings.verbose, |
||
893 | duration : settings.duration, |
||
894 | onComplete : function() { |
||
895 | callback(); |
||
896 | }, |
||
897 | queue : true |
||
898 | }) |
||
899 | ; |
||
900 | } |
||
901 | else { |
||
902 | module.debug('Showing results with javascript'); |
||
903 | $results |
||
904 | .stop() |
||
905 | .fadeIn(settings.duration, settings.easing) |
||
906 | ; |
||
907 | } |
||
908 | settings.onResultsOpen.call($results); |
||
909 | } |
||
910 | }, |
||
911 | hideResults: function(callback) { |
||
912 | callback = $.isFunction(callback) |
||
913 | ? callback |
||
914 | : function(){} |
||
915 | ; |
||
916 | if( module.is.visible() ) { |
||
917 | if( module.can.transition() ) { |
||
918 | module.debug('Hiding results with css animations'); |
||
919 | $results |
||
920 | .transition({ |
||
921 | animation : settings.transition + ' out', |
||
922 | debug : settings.debug, |
||
923 | verbose : settings.verbose, |
||
924 | duration : settings.duration, |
||
925 | onComplete : function() { |
||
926 | callback(); |
||
927 | }, |
||
928 | queue : true |
||
929 | }) |
||
930 | ; |
||
931 | } |
||
932 | else { |
||
933 | module.debug('Hiding results with javascript'); |
||
934 | $results |
||
935 | .stop() |
||
936 | .fadeOut(settings.duration, settings.easing) |
||
937 | ; |
||
938 | } |
||
939 | settings.onResultsClose.call($results); |
||
940 | } |
||
941 | }, |
||
942 | |||
943 | generateResults: function(response) { |
||
944 | module.debug('Generating html from response', response); |
||
945 | var |
||
946 | template = settings.templates[settings.type], |
||
947 | isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])), |
||
948 | isProperArray = ($.isArray(response[fields.results]) && response[fields.results].length > 0), |
||
949 | html = '' |
||
950 | ; |
||
951 | if(isProperObject || isProperArray ) { |
||
952 | if(settings.maxResults > 0) { |
||
953 | if(isProperObject) { |
||
954 | if(settings.type == 'standard') { |
||
955 | module.error(error.maxResults); |
||
956 | } |
||
957 | } |
||
958 | else { |
||
959 | response[fields.results] = response[fields.results].slice(0, settings.maxResults); |
||
960 | } |
||
961 | } |
||
962 | if($.isFunction(template)) { |
||
963 | html = template(response, fields); |
||
964 | } |
||
965 | else { |
||
966 | module.error(error.noTemplate, false); |
||
967 | } |
||
968 | } |
||
969 | else if(settings.showNoResults) { |
||
970 | html = module.displayMessage(error.noResults, 'empty'); |
||
971 | } |
||
972 | settings.onResults.call(element, response); |
||
973 | return html; |
||
974 | }, |
||
975 | |||
976 | displayMessage: function(text, type) { |
||
977 | type = type || 'standard'; |
||
978 | module.debug('Displaying message', text, type); |
||
979 | module.addResults( settings.templates.message(text, type) ); |
||
980 | return settings.templates.message(text, type); |
||
981 | }, |
||
982 | |||
983 | setting: function(name, value) { |
||
984 | if( $.isPlainObject(name) ) { |
||
985 | $.extend(true, settings, name); |
||
986 | } |
||
987 | else if(value !== undefined) { |
||
988 | settings[name] = value; |
||
989 | } |
||
990 | else { |
||
991 | return settings[name]; |
||
992 | } |
||
993 | }, |
||
994 | internal: function(name, value) { |
||
995 | if( $.isPlainObject(name) ) { |
||
996 | $.extend(true, module, name); |
||
997 | } |
||
998 | else if(value !== undefined) { |
||
999 | module[name] = value; |
||
1000 | } |
||
1001 | else { |
||
1002 | return module[name]; |
||
1003 | } |
||
1004 | }, |
||
1005 | debug: function() { |
||
1006 | if(!settings.silent && settings.debug) { |
||
1007 | if(settings.performance) { |
||
1008 | module.performance.log(arguments); |
||
1009 | } |
||
1010 | else { |
||
1011 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
||
1012 | module.debug.apply(console, arguments); |
||
1013 | } |
||
1014 | } |
||
1015 | }, |
||
1016 | verbose: function() { |
||
1017 | if(!settings.silent && settings.verbose && settings.debug) { |
||
1018 | if(settings.performance) { |
||
1019 | module.performance.log(arguments); |
||
1020 | } |
||
1021 | else { |
||
1022 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
||
1023 | module.verbose.apply(console, arguments); |
||
1024 | } |
||
1025 | } |
||
1026 | }, |
||
1027 | error: function() { |
||
1028 | if(!settings.silent) { |
||
1029 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
||
1030 | module.error.apply(console, arguments); |
||
1031 | } |
||
1032 | }, |
||
1033 | performance: { |
||
1034 | log: function(message) { |
||
1035 | var |
||
1036 | currentTime, |
||
1037 | executionTime, |
||
1038 | previousTime |
||
1039 | ; |
||
1040 | if(settings.performance) { |
||
1041 | currentTime = new Date().getTime(); |
||
1042 | previousTime = time || currentTime; |
||
1043 | executionTime = currentTime - previousTime; |
||
1044 | time = currentTime; |
||
1045 | performance.push({ |
||
1046 | 'Name' : message[0], |
||
1047 | 'Arguments' : [].slice.call(message, 1) || '', |
||
1048 | 'Element' : element, |
||
1049 | 'Execution Time' : executionTime |
||
1050 | }); |
||
1051 | } |
||
1052 | clearTimeout(module.performance.timer); |
||
1053 | module.performance.timer = setTimeout(module.performance.display, 500); |
||
1054 | }, |
||
1055 | display: function() { |
||
1056 | var |
||
1057 | title = settings.name + ':', |
||
1058 | totalTime = 0 |
||
1059 | ; |
||
1060 | time = false; |
||
1061 | clearTimeout(module.performance.timer); |
||
1062 | $.each(performance, function(index, data) { |
||
1063 | totalTime += data['Execution Time']; |
||
1064 | }); |
||
1065 | title += ' ' + totalTime + 'ms'; |
||
1066 | if(moduleSelector) { |
||
1067 | title += ' \'' + moduleSelector + '\''; |
||
1068 | } |
||
1069 | if($allModules.length > 1) { |
||
1070 | title += ' ' + '(' + $allModules.length + ')'; |
||
1071 | } |
||
1072 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
||
1073 | console.groupCollapsed(title); |
||
1074 | if(console.table) { |
||
1075 | console.table(performance); |
||
1076 | } |
||
1077 | else { |
||
1078 | $.each(performance, function(index, data) { |
||
1079 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
||
1080 | }); |
||
1081 | } |
||
1082 | console.groupEnd(); |
||
1083 | } |
||
1084 | performance = []; |
||
1085 | } |
||
1086 | }, |
||
1087 | invoke: function(query, passedArguments, context) { |
||
1088 | var |
||
1089 | object = instance, |
||
1090 | maxDepth, |
||
1091 | found, |
||
1092 | response |
||
1093 | ; |
||
1094 | passedArguments = passedArguments || queryArguments; |
||
1095 | context = element || context; |
||
1096 | if(typeof query == 'string' && object !== undefined) { |
||
1097 | query = query.split(/[\. ]/); |
||
1098 | maxDepth = query.length - 1; |
||
1099 | $.each(query, function(depth, value) { |
||
1100 | var camelCaseValue = (depth != maxDepth) |
||
1101 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
||
1102 | : query |
||
1103 | ; |
||
1104 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
||
1105 | object = object[camelCaseValue]; |
||
1106 | } |
||
1107 | else if( object[camelCaseValue] !== undefined ) { |
||
1108 | found = object[camelCaseValue]; |
||
1109 | return false; |
||
1110 | } |
||
1111 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
||
1112 | object = object[value]; |
||
1113 | } |
||
1114 | else if( object[value] !== undefined ) { |
||
1115 | found = object[value]; |
||
1116 | return false; |
||
1117 | } |
||
1118 | else { |
||
1119 | return false; |
||
1120 | } |
||
1121 | }); |
||
1122 | } |
||
1123 | if( $.isFunction( found ) ) { |
||
1124 | response = found.apply(context, passedArguments); |
||
1125 | } |
||
1126 | else if(found !== undefined) { |
||
1127 | response = found; |
||
1128 | } |
||
1129 | if($.isArray(returnedValue)) { |
||
1130 | returnedValue.push(response); |
||
1131 | } |
||
1132 | else if(returnedValue !== undefined) { |
||
1133 | returnedValue = [returnedValue, response]; |
||
1134 | } |
||
1135 | else if(response !== undefined) { |
||
1136 | returnedValue = response; |
||
1137 | } |
||
1138 | return found; |
||
1139 | } |
||
1140 | }; |
||
1141 | if(methodInvoked) { |
||
1142 | if(instance === undefined) { |
||
1143 | module.initialize(); |
||
1144 | } |
||
1145 | module.invoke(query); |
||
1146 | } |
||
1147 | else { |
||
1148 | if(instance !== undefined) { |
||
1149 | instance.invoke('destroy'); |
||
1150 | } |
||
1151 | module.initialize(); |
||
1152 | } |
||
1153 | |||
1154 | }) |
||
1155 | ; |
||
1156 | |||
1157 | return (returnedValue !== undefined) |
||
1158 | ? returnedValue |
||
1159 | : this |
||
1160 | ; |
||
1161 | }; |
||
1162 | |||
1163 | $.fn.search.settings = { |
||
1164 | |||
1165 | name : 'Search', |
||
1166 | namespace : 'search', |
||
1167 | |||
1168 | silent : false, |
||
1169 | debug : false, |
||
1170 | verbose : false, |
||
1171 | performance : true, |
||
1172 | |||
1173 | // template to use (specified in settings.templates) |
||
1174 | type : 'standard', |
||
1175 | |||
1176 | // minimum characters required to search |
||
1177 | minCharacters : 1, |
||
1178 | |||
1179 | // whether to select first result after searching automatically |
||
1180 | selectFirstResult : false, |
||
1181 | |||
1182 | // API config |
||
1183 | apiSettings : false, |
||
1184 | |||
1185 | // object to search |
||
1186 | source : false, |
||
1187 | |||
1188 | // Whether search should query current term on focus |
||
1189 | searchOnFocus : true, |
||
1190 | |||
1191 | // fields to search |
||
1192 | searchFields : [ |
||
1193 | 'title', |
||
1194 | 'description' |
||
1195 | ], |
||
1196 | |||
1197 | // field to display in standard results template |
||
1198 | displayField : '', |
||
1199 | |||
1200 | // whether to include fuzzy results in local search |
||
1201 | searchFullText : true, |
||
1202 | |||
1203 | // whether to add events to prompt automatically |
||
1204 | automatic : true, |
||
1205 | |||
1206 | // delay before hiding menu after blur |
||
1207 | hideDelay : 0, |
||
1208 | |||
1209 | // delay before searching |
||
1210 | searchDelay : 200, |
||
1211 | |||
1212 | // maximum results returned from local |
||
1213 | maxResults : 7, |
||
1214 | |||
1215 | // whether to store lookups in local cache |
||
1216 | cache : true, |
||
1217 | |||
1218 | // whether no results errors should be shown |
||
1219 | showNoResults : true, |
||
1220 | |||
1221 | // transition settings |
||
1222 | transition : 'scale', |
||
1223 | duration : 200, |
||
1224 | easing : 'easeOutExpo', |
||
1225 | |||
1226 | // callbacks |
||
1227 | onSelect : false, |
||
1228 | onResultsAdd : false, |
||
1229 | |||
1230 | onSearchQuery : function(query){}, |
||
1231 | onResults : function(response){}, |
||
1232 | |||
1233 | onResultsOpen : function(){}, |
||
1234 | onResultsClose : function(){}, |
||
1235 | |||
1236 | className: { |
||
1237 | animating : 'animating', |
||
1238 | active : 'active', |
||
1239 | empty : 'empty', |
||
1240 | focus : 'focus', |
||
1241 | hidden : 'hidden', |
||
1242 | loading : 'loading', |
||
1243 | results : 'results', |
||
1244 | pressed : 'down' |
||
1245 | }, |
||
1246 | |||
1247 | error : { |
||
1248 | source : 'Cannot search. No source used, and Semantic API module was not included', |
||
1249 | noResults : 'Your search returned no results', |
||
1250 | logging : 'Error in debug logging, exiting.', |
||
1251 | noEndpoint : 'No search endpoint was specified', |
||
1252 | noTemplate : 'A valid template name was not specified.', |
||
1253 | serverError : 'There was an issue querying the server.', |
||
1254 | maxResults : 'Results must be an array to use maxResults setting', |
||
1255 | method : 'The method you called is not defined.' |
||
1256 | }, |
||
1257 | |||
1258 | metadata: { |
||
1259 | cache : 'cache', |
||
1260 | results : 'results', |
||
1261 | result : 'result' |
||
1262 | }, |
||
1263 | |||
1264 | regExp: { |
||
1265 | escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, |
||
1266 | beginsWith : '(?:\s|^)' |
||
1267 | }, |
||
1268 | |||
1269 | // maps api response attributes to internal representation |
||
1270 | fields: { |
||
1271 | categories : 'results', // array of categories (category view) |
||
1272 | categoryName : 'name', // name of category (category view) |
||
1273 | categoryResults : 'results', // array of results (category view) |
||
1274 | description : 'description', // result description |
||
1275 | image : 'image', // result image |
||
1276 | price : 'price', // result price |
||
1277 | results : 'results', // array of results (standard) |
||
1278 | title : 'title', // result title |
||
1279 | url : 'url', // result url |
||
1280 | action : 'action', // "view more" object name |
||
1281 | actionText : 'text', // "view more" text |
||
1282 | actionURL : 'url' // "view more" url |
||
1283 | }, |
||
1284 | |||
1285 | selector : { |
||
1286 | prompt : '.prompt', |
||
1287 | searchButton : '.search.button', |
||
1288 | results : '.results', |
||
1289 | message : '.results > .message', |
||
1290 | category : '.category', |
||
1291 | result : '.result', |
||
1292 | title : '.title, .name' |
||
1293 | }, |
||
1294 | |||
1295 | templates: { |
||
1296 | escape: function(string) { |
||
1297 | var |
||
1298 | badChars = /[&<>"'`]/g, |
||
1299 | shouldEscape = /[&<>"'`]/, |
||
1300 | escape = { |
||
1301 | "&": "&", |
||
1302 | "<": "<", |
||
1303 | ">": ">", |
||
1304 | '"': """, |
||
1305 | "'": "'", |
||
1306 | "`": "`" |
||
1307 | }, |
||
1308 | escapedChar = function(chr) { |
||
1309 | return escape[chr]; |
||
1310 | } |
||
1311 | ; |
||
1312 | if(shouldEscape.test(string)) { |
||
1313 | return string.replace(badChars, escapedChar); |
||
1314 | } |
||
1315 | return string; |
||
1316 | }, |
||
1317 | message: function(message, type) { |
||
1318 | var |
||
1319 | html = '' |
||
1320 | ; |
||
1321 | if(message !== undefined && type !== undefined) { |
||
1322 | html += '' |
||
1323 | + '<div class="message ' + type + '">' |
||
1324 | ; |
||
1325 | // message type |
||
1326 | if(type == 'empty') { |
||
1327 | html += '' |
||
1328 | + '<div class="header">No Results</div class="header">' |
||
1329 | + '<div class="description">' + message + '</div class="description">' |
||
1330 | ; |
||
1331 | } |
||
1332 | else { |
||
1333 | html += ' <div class="description">' + message + '</div>'; |
||
1334 | } |
||
1335 | html += '</div>'; |
||
1336 | } |
||
1337 | return html; |
||
1338 | }, |
||
1339 | category: function(response, fields) { |
||
1340 | var |
||
1341 | html = '', |
||
1342 | escape = $.fn.search.settings.templates.escape |
||
1343 | ; |
||
1344 | if(response[fields.categoryResults] !== undefined) { |
||
1345 | |||
1346 | // each category |
||
1347 | $.each(response[fields.categoryResults], function(index, category) { |
||
1348 | if(category[fields.results] !== undefined && category.results.length > 0) { |
||
1349 | |||
1350 | html += '<div class="category">'; |
||
1351 | |||
1352 | if(category[fields.categoryName] !== undefined) { |
||
1353 | html += '<div class="name">' + category[fields.categoryName] + '</div>'; |
||
1354 | } |
||
1355 | |||
1356 | // each item inside category |
||
1357 | $.each(category.results, function(index, result) { |
||
1358 | if(result[fields.url]) { |
||
1359 | html += '<a class="result" href="' + result[fields.url] + '">'; |
||
1360 | } |
||
1361 | else { |
||
1362 | html += '<a class="result">'; |
||
1363 | } |
||
1364 | if(result[fields.image] !== undefined) { |
||
1365 | html += '' |
||
1366 | + '<div class="image">' |
||
1367 | + ' <img src="' + result[fields.image] + '">' |
||
1368 | + '</div>' |
||
1369 | ; |
||
1370 | } |
||
1371 | html += '<div class="content">'; |
||
1372 | if(result[fields.price] !== undefined) { |
||
1373 | html += '<div class="price">' + result[fields.price] + '</div>'; |
||
1374 | } |
||
1375 | if(result[fields.title] !== undefined) { |
||
1376 | html += '<div class="title">' + result[fields.title] + '</div>'; |
||
1377 | } |
||
1378 | if(result[fields.description] !== undefined) { |
||
1379 | html += '<div class="description">' + result[fields.description] + '</div>'; |
||
1380 | } |
||
1381 | html += '' |
||
1382 | + '</div>' |
||
1383 | ; |
||
1384 | html += '</a>'; |
||
1385 | }); |
||
1386 | html += '' |
||
1387 | + '</div>' |
||
1388 | ; |
||
1389 | } |
||
1390 | }); |
||
1391 | if(response[fields.action]) { |
||
1392 | html += '' |
||
1393 | + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">' |
||
1394 | + response[fields.action][fields.actionText] |
||
1395 | + '</a>'; |
||
1396 | } |
||
1397 | return html; |
||
1398 | } |
||
1399 | return false; |
||
1400 | }, |
||
1401 | standard: function(response, fields) { |
||
1402 | var |
||
1403 | html = '' |
||
1404 | ; |
||
1405 | if(response[fields.results] !== undefined) { |
||
1406 | |||
1407 | // each result |
||
1408 | $.each(response[fields.results], function(index, result) { |
||
1409 | if(result[fields.url]) { |
||
1410 | html += '<a class="result" href="' + result[fields.url] + '">'; |
||
1411 | } |
||
1412 | else { |
||
1413 | html += '<a class="result">'; |
||
1414 | } |
||
1415 | if(result[fields.image] !== undefined) { |
||
1416 | html += '' |
||
1417 | + '<div class="image">' |
||
1418 | + ' <img src="' + result[fields.image] + '">' |
||
1419 | + '</div>' |
||
1420 | ; |
||
1421 | } |
||
1422 | html += '<div class="content">'; |
||
1423 | if(result[fields.price] !== undefined) { |
||
1424 | html += '<div class="price">' + result[fields.price] + '</div>'; |
||
1425 | } |
||
1426 | if(result[fields.title] !== undefined) { |
||
1427 | html += '<div class="title">' + result[fields.title] + '</div>'; |
||
1428 | } |
||
1429 | if(result[fields.description] !== undefined) { |
||
1430 | html += '<div class="description">' + result[fields.description] + '</div>'; |
||
1431 | } |
||
1432 | html += '' |
||
1433 | + '</div>' |
||
1434 | ; |
||
1435 | html += '</a>'; |
||
1436 | }); |
||
1437 | |||
1438 | if(response[fields.action]) { |
||
1439 | html += '' |
||
1440 | + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">' |
||
1441 | + response[fields.action][fields.actionText] |
||
1442 | + '</a>'; |
||
1443 | } |
||
1444 | return html; |
||
1445 | } |
||
1446 | return false; |
||
1447 | } |
||
1448 | } |
||
1449 | }; |
||
1450 | |||
1451 | })( jQuery, window, document ); |
||
1452 |