fomantic-ui-sass 2.9.0 → 2.9.1

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