volt-semantic-ui 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -0
  3. data/Gemfile +0 -0
  4. data/LICENSE.txt +0 -0
  5. data/README.md +0 -0
  6. data/Rakefile +0 -0
  7. data/app/semanticui/assets/css/semantic.min.css +3 -3
  8. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.eot +0 -0
  9. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.svg +0 -0
  10. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.ttf +0 -0
  11. data/app/semanticui/assets/css/themes/basic/assets/fonts/icons.woff +0 -0
  12. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.eot +0 -0
  13. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.otf +0 -0
  14. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.svg +526 -465
  15. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.ttf +0 -0
  16. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.woff +0 -0
  17. data/app/semanticui/assets/css/themes/default/assets/fonts/icons.woff2 +0 -0
  18. data/app/semanticui/assets/css/themes/default/assets/images/flags.png +0 -0
  19. data/app/semanticui/assets/js/components/accordion.css +256 -0
  20. data/app/semanticui/assets/js/components/accordion.js +578 -0
  21. data/app/semanticui/assets/js/components/accordion.min.css +10 -0
  22. data/app/semanticui/assets/js/components/accordion.min.js +11 -0
  23. data/app/semanticui/assets/js/components/ad.css +276 -0
  24. data/app/semanticui/assets/js/components/ad.min.css +10 -0
  25. data/app/semanticui/assets/js/components/api.js +871 -0
  26. data/app/semanticui/assets/js/components/api.min.js +11 -0
  27. data/app/semanticui/assets/js/components/breadcrumb.css +124 -0
  28. data/app/semanticui/assets/js/components/breadcrumb.min.css +10 -0
  29. data/app/semanticui/assets/js/components/button.css +2391 -0
  30. data/app/semanticui/assets/js/components/button.min.css +10 -0
  31. data/app/semanticui/assets/js/components/card.css +909 -0
  32. data/app/semanticui/assets/js/components/card.min.css +10 -0
  33. data/app/semanticui/assets/js/components/checkbox.css +513 -0
  34. data/app/semanticui/assets/js/components/checkbox.js +509 -0
  35. data/app/semanticui/assets/js/components/checkbox.min.css +10 -0
  36. data/app/semanticui/assets/js/components/checkbox.min.js +11 -0
  37. data/app/semanticui/assets/js/components/comment.css +259 -0
  38. data/app/semanticui/assets/js/components/comment.min.css +10 -0
  39. data/app/semanticui/assets/js/components/dimmer.css +186 -0
  40. data/app/semanticui/assets/js/components/dimmer.js +669 -0
  41. data/app/semanticui/assets/js/components/dimmer.min.css +10 -0
  42. data/app/semanticui/assets/js/components/dimmer.min.js +11 -0
  43. data/app/semanticui/assets/js/components/divider.css +241 -0
  44. data/app/semanticui/assets/js/components/divider.min.css +10 -0
  45. data/app/semanticui/assets/js/components/dropdown.css +1103 -0
  46. data/app/semanticui/assets/js/components/dropdown.js +1795 -0
  47. data/app/semanticui/assets/js/components/dropdown.min.css +10 -0
  48. data/app/semanticui/assets/js/components/dropdown.min.js +11 -0
  49. data/app/semanticui/assets/js/components/feed.css +276 -0
  50. data/app/semanticui/assets/js/components/feed.min.css +10 -0
  51. data/app/semanticui/assets/js/components/flag.css +1024 -0
  52. data/app/semanticui/assets/js/components/flag.min.css +10 -0
  53. data/app/semanticui/assets/js/components/form.css +891 -0
  54. data/app/semanticui/assets/js/components/form.js +1118 -0
  55. data/app/semanticui/assets/js/components/form.min.css +10 -0
  56. data/app/semanticui/assets/js/components/form.min.js +11 -0
  57. data/app/semanticui/assets/js/components/grid.css +1871 -0
  58. data/app/semanticui/assets/js/components/grid.min.css +10 -0
  59. data/app/semanticui/assets/js/components/header.css +596 -0
  60. data/app/semanticui/assets/js/components/header.min.css +10 -0
  61. data/app/semanticui/assets/js/components/icon.css +2467 -0
  62. data/app/semanticui/assets/js/components/icon.min.css +10 -0
  63. data/app/semanticui/assets/js/components/image.css +288 -0
  64. data/app/semanticui/assets/js/components/image.min.css +10 -0
  65. data/app/semanticui/assets/js/components/input.css +439 -0
  66. data/app/semanticui/assets/js/components/input.min.css +10 -0
  67. data/app/semanticui/assets/js/components/item.css +456 -0
  68. data/app/semanticui/assets/js/components/item.min.css +10 -0
  69. data/app/semanticui/assets/js/components/label.css +963 -0
  70. data/app/semanticui/assets/js/components/label.min.css +10 -0
  71. data/app/semanticui/assets/js/components/list.css +878 -0
  72. data/app/semanticui/assets/js/components/list.min.css +10 -0
  73. data/app/semanticui/assets/js/components/loader.css +284 -0
  74. data/app/semanticui/assets/js/components/loader.min.css +10 -0
  75. data/app/semanticui/assets/js/components/menu.css +1608 -0
  76. data/app/semanticui/assets/js/components/menu.min.css +10 -0
  77. data/app/semanticui/assets/js/components/message.css +421 -0
  78. data/app/semanticui/assets/js/components/message.min.css +10 -0
  79. data/app/semanticui/assets/js/components/modal.css +432 -0
  80. data/app/semanticui/assets/js/components/modal.js +860 -0
  81. data/app/semanticui/assets/js/components/modal.min.css +10 -0
  82. data/app/semanticui/assets/js/components/modal.min.js +11 -0
  83. data/app/semanticui/assets/js/components/nag.css +148 -0
  84. data/app/semanticui/assets/js/components/nag.js +477 -0
  85. data/app/semanticui/assets/js/components/nag.min.css +10 -0
  86. data/app/semanticui/assets/js/components/nag.min.js +11 -0
  87. data/app/semanticui/assets/js/components/popup.css +293 -0
  88. data/app/semanticui/assets/js/components/popup.js +1224 -0
  89. data/app/semanticui/assets/js/components/popup.min.css +10 -0
  90. data/app/semanticui/assets/js/components/popup.min.js +11 -0
  91. data/app/semanticui/assets/js/components/progress.css +461 -0
  92. data/app/semanticui/assets/js/components/progress.js +785 -0
  93. data/app/semanticui/assets/js/components/progress.min.css +10 -0
  94. data/app/semanticui/assets/js/components/progress.min.js +11 -0
  95. data/app/semanticui/assets/js/components/rail.css +124 -0
  96. data/app/semanticui/assets/js/components/rail.min.css +10 -0
  97. data/app/semanticui/assets/js/components/rating.css +251 -0
  98. data/app/semanticui/assets/js/components/rating.js +451 -0
  99. data/app/semanticui/assets/js/components/rating.min.css +10 -0
  100. data/app/semanticui/assets/js/components/rating.min.js +11 -0
  101. data/app/semanticui/assets/js/components/reset.css +429 -0
  102. data/app/semanticui/assets/js/components/reset.min.css +10 -0
  103. data/app/semanticui/assets/js/components/reveal.css +293 -0
  104. data/app/semanticui/assets/js/components/reveal.min.css +10 -0
  105. data/app/semanticui/assets/js/components/search.css +329 -0
  106. data/app/semanticui/assets/js/components/search.js +1096 -0
  107. data/app/semanticui/assets/js/components/search.min.css +10 -0
  108. data/app/semanticui/assets/js/components/search.min.js +11 -0
  109. data/app/semanticui/assets/js/components/segment.css +635 -0
  110. data/app/semanticui/assets/js/components/segment.min.css +10 -0
  111. data/app/semanticui/assets/js/components/shape.css +154 -0
  112. data/app/semanticui/assets/js/components/shape.js +830 -0
  113. data/app/semanticui/assets/js/components/shape.min.css +10 -0
  114. data/app/semanticui/assets/js/components/shape.min.js +11 -0
  115. data/app/semanticui/assets/js/components/sidebar.css +625 -0
  116. data/app/semanticui/assets/js/components/sidebar.js +1089 -0
  117. data/app/semanticui/assets/js/components/sidebar.min.css +10 -0
  118. data/app/semanticui/assets/js/components/sidebar.min.js +11 -0
  119. data/app/semanticui/assets/js/components/site.css +160 -0
  120. data/app/semanticui/assets/js/components/site.js +487 -0
  121. data/app/semanticui/assets/js/components/site.min.css +10 -0
  122. data/app/semanticui/assets/js/components/site.min.js +11 -0
  123. data/app/semanticui/assets/js/components/state.js +695 -0
  124. data/app/semanticui/assets/js/components/state.min.js +11 -0
  125. data/app/semanticui/assets/js/components/statistic.css +409 -0
  126. data/app/semanticui/assets/js/components/statistic.min.css +10 -0
  127. data/app/semanticui/assets/js/components/step.css +432 -0
  128. data/app/semanticui/assets/js/components/step.min.css +10 -0
  129. data/app/semanticui/assets/js/components/sticky.css +79 -0
  130. data/app/semanticui/assets/js/components/sticky.js +792 -0
  131. data/app/semanticui/assets/js/components/sticky.min.css +10 -0
  132. data/app/semanticui/assets/js/components/sticky.min.js +11 -0
  133. data/app/semanticui/assets/js/components/tab.css +92 -0
  134. data/app/semanticui/assets/js/components/tab.js +802 -0
  135. data/app/semanticui/assets/js/components/tab.min.css +10 -0
  136. data/app/semanticui/assets/js/components/tab.min.js +11 -0
  137. data/app/semanticui/assets/js/components/table.css +1000 -0
  138. data/app/semanticui/assets/js/components/table.min.css +10 -0
  139. data/app/semanticui/assets/js/components/transition.css +1990 -0
  140. data/app/semanticui/assets/js/components/transition.js +1038 -0
  141. data/app/semanticui/assets/js/components/transition.min.css +10 -0
  142. data/app/semanticui/assets/js/components/transition.min.js +11 -0
  143. data/app/semanticui/assets/js/components/video.css +125 -0
  144. data/app/semanticui/assets/js/components/video.js +540 -0
  145. data/app/semanticui/assets/js/components/video.min.css +10 -0
  146. data/app/semanticui/assets/js/components/video.min.js +11 -0
  147. data/app/semanticui/assets/js/components/visibility.js +1032 -0
  148. data/app/semanticui/assets/js/components/visibility.min.js +11 -0
  149. data/app/semanticui/assets/js/semantic.min.js +9 -9
  150. data/lib/volt/semanticui.rb +0 -0
  151. data/lib/volt/semanticui/version.rb +1 -1
  152. data/volt-semantic-ui-0.0.1.gem +0 -0
  153. data/volt-semanticui-0.0.1.gem +0 -0
  154. data/volt-semanticui.gemspec +0 -0
  155. metadata +141 -10
@@ -0,0 +1,1096 @@
1
+ /*!
2
+ * # Semantic UI 1.11.4 - Search
3
+ * http://github.com/semantic-org/semantic-ui/
4
+ *
5
+ *
6
+ * Copyright 2014 Contributors
7
+ * Released under the MIT license
8
+ * http://opensource.org/licenses/MIT
9
+ *
10
+ */
11
+
12
+ ;(function ($, window, document, undefined) {
13
+
14
+ "use strict";
15
+
16
+ $.fn.search = function(parameters) {
17
+ var
18
+ $allModules = $(this),
19
+ moduleSelector = $allModules.selector || '',
20
+
21
+ time = new Date().getTime(),
22
+ performance = [],
23
+
24
+ query = arguments[0],
25
+ methodInvoked = (typeof query == 'string'),
26
+ queryArguments = [].slice.call(arguments, 1),
27
+ returnedValue
28
+ ;
29
+ $(this)
30
+ .each(function() {
31
+ var
32
+ settings = $.extend(true, {}, $.fn.search.settings, parameters),
33
+
34
+ className = settings.className,
35
+ metadata = settings.metadata,
36
+ regExp = settings.regExp,
37
+ selector = settings.selector,
38
+ error = settings.error,
39
+ namespace = settings.namespace,
40
+
41
+ eventNamespace = '.' + namespace,
42
+ moduleNamespace = namespace + '-module',
43
+
44
+ $module = $(this),
45
+ $prompt = $module.find(selector.prompt),
46
+ $searchButton = $module.find(selector.searchButton),
47
+ $results = $module.find(selector.results),
48
+ $result = $module.find(selector.result),
49
+ $category = $module.find(selector.category),
50
+
51
+ element = this,
52
+ instance = $module.data(moduleNamespace),
53
+
54
+ module
55
+ ;
56
+ module = {
57
+
58
+ initialize: function() {
59
+ module.verbose('Initializing module');
60
+ var
61
+ prompt = $prompt[0],
62
+ inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
63
+ ? 'input'
64
+ : (prompt !== undefined && prompt.onpropertychange !== undefined)
65
+ ? 'propertychange'
66
+ : 'keyup'
67
+ ;
68
+ if(settings.automatic) {
69
+ $prompt
70
+ .on(inputEvent + eventNamespace, module.throttle)
71
+ .attr('autocomplete', 'off')
72
+ ;
73
+ }
74
+ $prompt
75
+ .on('focus' + eventNamespace, module.event.focus)
76
+ .on('blur' + eventNamespace, module.event.blur)
77
+ .on('keydown' + eventNamespace, module.handleKeyboard)
78
+ ;
79
+ $searchButton
80
+ .on('click' + eventNamespace, module.query)
81
+ ;
82
+ $results
83
+ .on('mousedown' + eventNamespace, module.event.result.mousedown)
84
+ .on('mouseup' + eventNamespace, module.event.result.mouseup)
85
+ .on('click' + eventNamespace, selector.result, module.event.result.click)
86
+ ;
87
+ module.instantiate();
88
+ },
89
+ instantiate: function() {
90
+ module.verbose('Storing instance of module', module);
91
+ instance = module;
92
+ $module
93
+ .data(moduleNamespace, module)
94
+ ;
95
+ },
96
+ destroy: function() {
97
+ module.verbose('Destroying instance');
98
+ $module
99
+ .removeData(moduleNamespace)
100
+ ;
101
+ $prompt
102
+ .off(eventNamespace)
103
+ ;
104
+ $searchButton
105
+ .off(eventNamespace)
106
+ ;
107
+ $results
108
+ .off(eventNamespace)
109
+ ;
110
+ },
111
+ event: {
112
+ focus: function() {
113
+ module.set.focus();
114
+ clearTimeout(module.timer);
115
+ module.throttle();
116
+ if( module.has.minimumCharacters() ) {
117
+ module.showResults();
118
+ }
119
+ },
120
+ blur: function(event) {
121
+ var
122
+ pageLostFocus = (document.activeElement === this)
123
+ ;
124
+ if(!pageLostFocus && !module.resultsClicked) {
125
+ module.cancel.query();
126
+ module.remove.focus();
127
+ module.timer = setTimeout(module.hideResults, settings.hideDelay);
128
+ }
129
+ },
130
+ result: {
131
+ mousedown: function() {
132
+ module.resultsClicked = true;
133
+ },
134
+ mouseup: function() {
135
+ module.resultsClicked = false;
136
+ },
137
+ click: function(event) {
138
+ module.debug('Search result selected');
139
+ var
140
+ $result = $(this),
141
+ $title = $result.find(selector.title).eq(0),
142
+ $link = $result.find('a[href]').eq(0),
143
+ href = $link.attr('href') || false,
144
+ target = $link.attr('target') || false,
145
+ title = $title.html(),
146
+ name = ($title.length > 0)
147
+ ? $title.text()
148
+ : false,
149
+ results = module.get.results(),
150
+ result = module.get.result(name, results),
151
+ returnedValue
152
+ ;
153
+ if( $.isFunction(settings.onSelect) ) {
154
+ if(settings.onSelect.call(element, result, results) === false) {
155
+ module.debug('Custom onSelect callback cancelled default select action');
156
+ return;
157
+ }
158
+ }
159
+ module.hideResults();
160
+ if(name) {
161
+ module.set.value(name);
162
+ }
163
+ if(href) {
164
+ module.verbose('Opening search link found in result', $link);
165
+ if(target == '_blank' || event.ctrlKey) {
166
+ window.open(href);
167
+ }
168
+ else {
169
+ window.location.href = (href);
170
+ }
171
+ }
172
+ }
173
+ }
174
+ },
175
+ handleKeyboard: function(event) {
176
+ var
177
+ // force selector refresh
178
+ $result = $module.find(selector.result),
179
+ $category = $module.find(selector.category),
180
+ currentIndex = $result.index( $result.filter('.' + className.active) ),
181
+ resultSize = $result.length,
182
+
183
+ keyCode = event.which,
184
+ keys = {
185
+ backspace : 8,
186
+ enter : 13,
187
+ escape : 27,
188
+ upArrow : 38,
189
+ downArrow : 40
190
+ },
191
+ newIndex
192
+ ;
193
+ // search shortcuts
194
+ if(keyCode == keys.escape) {
195
+ module.verbose('Escape key pressed, blurring search field');
196
+ $prompt
197
+ .trigger('blur')
198
+ ;
199
+ }
200
+ if( module.is.visible() ) {
201
+ if(keyCode == keys.enter) {
202
+ module.verbose('Enter key pressed, selecting active result');
203
+ if( $result.filter('.' + className.active).length > 0 ) {
204
+ module.event.result.click.call($result.filter('.' + className.active), event);
205
+ event.preventDefault();
206
+ return false;
207
+ }
208
+ }
209
+ else if(keyCode == keys.upArrow) {
210
+ module.verbose('Up key pressed, changing active result');
211
+ newIndex = (currentIndex - 1 < 0)
212
+ ? currentIndex
213
+ : currentIndex - 1
214
+ ;
215
+ $category
216
+ .removeClass(className.active)
217
+ ;
218
+ $result
219
+ .removeClass(className.active)
220
+ .eq(newIndex)
221
+ .addClass(className.active)
222
+ .closest($category)
223
+ .addClass(className.active)
224
+ ;
225
+ event.preventDefault();
226
+ }
227
+ else if(keyCode == keys.downArrow) {
228
+ module.verbose('Down key pressed, changing active result');
229
+ newIndex = (currentIndex + 1 >= resultSize)
230
+ ? currentIndex
231
+ : currentIndex + 1
232
+ ;
233
+ $category
234
+ .removeClass(className.active)
235
+ ;
236
+ $result
237
+ .removeClass(className.active)
238
+ .eq(newIndex)
239
+ .addClass(className.active)
240
+ .closest($category)
241
+ .addClass(className.active)
242
+ ;
243
+ event.preventDefault();
244
+ }
245
+ }
246
+ else {
247
+ // query shortcuts
248
+ if(keyCode == keys.enter) {
249
+ module.verbose('Enter key pressed, executing query');
250
+ module.query();
251
+ module.set.buttonPressed();
252
+ $prompt.one('keyup', module.remove.buttonFocus);
253
+ }
254
+ }
255
+ },
256
+
257
+ setup: {
258
+ api: function() {
259
+ var
260
+ apiSettings = {
261
+ on : false,
262
+ action : 'search',
263
+ onFailure : module.error
264
+ },
265
+ searchHTML
266
+ ;
267
+ module.verbose('First request, initializing API');
268
+ $module.api(apiSettings);
269
+ }
270
+ },
271
+
272
+ can: {
273
+ useAPI: function() {
274
+ return $.fn.api !== undefined;
275
+ },
276
+ transition: function() {
277
+ return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
278
+ }
279
+ },
280
+
281
+ is: {
282
+ empty: function() {
283
+ return ($results.html() === '');
284
+ },
285
+ visible: function() {
286
+ return ($results.filter(':visible').length > 0);
287
+ },
288
+ focused: function() {
289
+ return ($prompt.filter(':focus').length > 0);
290
+ }
291
+ },
292
+
293
+ get: {
294
+ value: function() {
295
+ return $prompt.val();
296
+ },
297
+ results: function() {
298
+ var
299
+ results = $module.data(metadata.results)
300
+ ;
301
+ return results;
302
+ },
303
+ result: function(value, results) {
304
+ var
305
+ result = false
306
+ ;
307
+ value = value || module.get.value();
308
+ results = results || module.get.results();
309
+ if(settings.type === 'category') {
310
+ module.debug('Finding result that matches', value);
311
+ $.each(results, function(index, category) {
312
+ if($.isArray(category.results)) {
313
+ result = module.search.object(value, category.results)[0];
314
+ if(result && result.length > 0) {
315
+ return true;
316
+ }
317
+ }
318
+ });
319
+ }
320
+ else {
321
+ module.debug('Finding result in results object', value);
322
+ result = module.search.object(value, results)[0];
323
+ }
324
+ return result;
325
+ },
326
+ },
327
+
328
+ set: {
329
+ focus: function() {
330
+ $module.addClass(className.focus);
331
+ },
332
+ loading: function() {
333
+ $module.addClass(className.loading);
334
+ },
335
+ value: function(value) {
336
+ module.verbose('Setting search input value', value);
337
+ $prompt.val(value);
338
+ module.query();
339
+ },
340
+ buttonPressed: function() {
341
+ $searchButton.addClass(className.pressed);
342
+ }
343
+ },
344
+
345
+ remove: {
346
+ loading: function() {
347
+ $module.removeClass(className.loading);
348
+ },
349
+ focus: function() {
350
+ $module.removeClass(className.focus);
351
+ },
352
+ buttonPressed: function() {
353
+ $searchButton.removeClass(className.pressed);
354
+ }
355
+ },
356
+
357
+ query: function() {
358
+ var
359
+ searchTerm = module.get.value(),
360
+ cache = module.read.cache(searchTerm)
361
+ ;
362
+ if(cache) {
363
+ module.debug('Reading result for ' + searchTerm + ' from cache');
364
+ module.save.results(cache.results);
365
+ module.addResults(cache.html);
366
+ }
367
+ else {
368
+ module.debug('Querying for ' + searchTerm);
369
+ if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
370
+ module.search.local(searchTerm);
371
+ }
372
+ else if( module.can.useAPI() ) {
373
+ if(settings.apiSettings) {
374
+ module.debug('Searching with specified API settings', settings.apiSettings);
375
+ module.search.remote(searchTerm);
376
+ }
377
+ else if($.api.settings.api.search !== undefined) {
378
+ module.debug('Searching with default search API endpoint');
379
+ module.search.remote(searchTerm);
380
+ }
381
+ else {
382
+ module.error(error.noEndpoint);
383
+ }
384
+ }
385
+ else {
386
+ module.error(error.source);
387
+ }
388
+ settings.onSearchQuery.call(element, searchTerm);
389
+ }
390
+ },
391
+
392
+ search: {
393
+ local: function(searchTerm) {
394
+ var
395
+ searchResults = module.search.object(searchTerm, settings.content),
396
+ searchHTML
397
+ ;
398
+ module.set.loading();
399
+ module.save.results(searchResults);
400
+ module.debug('Returned local search results', searchResults);
401
+
402
+ searchHTML = module.generateResults({
403
+ results: searchResults
404
+ });
405
+ module.remove.loading();
406
+ module.write.cache(searchTerm, {
407
+ html : searchHTML,
408
+ results : searchResults
409
+ });
410
+ module.addResults(searchHTML);
411
+ },
412
+ remote: function(searchTerm) {
413
+ var
414
+ apiSettings = {
415
+ onSuccess : function(response) {
416
+ module.parse.response.call(element, response, searchTerm);
417
+ },
418
+ urlData: {
419
+ query: searchTerm
420
+ }
421
+ }
422
+ ;
423
+ if( !$module.api('get request') ) {
424
+ module.setup.api();
425
+ }
426
+ $.extend(true, apiSettings, settings.apiSettings);
427
+ module.debug('Executing search', apiSettings);
428
+ module.cancel.query();
429
+ $module
430
+ .api('setting', apiSettings)
431
+ .api('query')
432
+ ;
433
+ },
434
+ object: function(searchTerm, source) {
435
+ var
436
+ results = [],
437
+ fullTextResults = [],
438
+ searchFields = $.isArray(settings.searchFields)
439
+ ? settings.searchFields
440
+ : [settings.searchFields],
441
+ searchExp = searchTerm.replace(regExp.escape, '\\$&'),
442
+ searchRegExp = new RegExp(regExp.exact + searchExp, 'i')
443
+ ;
444
+
445
+ source = source || settings.source;
446
+
447
+ // exit conditions on no source
448
+ if(source === undefined) {
449
+ module.error(error.source);
450
+ return [];
451
+ }
452
+
453
+ // iterate through search fields in array order
454
+ $.each(searchFields, function(index, field) {
455
+ $.each(source, function(label, content) {
456
+ var
457
+ fieldExists = (typeof content[field] == 'string'),
458
+ notAlreadyResult = ($.inArray(content, results) == -1 && $.inArray(content, fullTextResults) == -1)
459
+ ;
460
+ if(fieldExists && notAlreadyResult) {
461
+ if( content[field].match(searchRegExp) ) {
462
+ results.push(content);
463
+ }
464
+ else if(settings.searchFullText && module.fuzzySearch(searchTerm, content[field]) ) {
465
+ fullTextResults.push(content);
466
+ }
467
+ }
468
+ });
469
+ });
470
+ return $.merge(results, fullTextResults);
471
+ }
472
+ },
473
+
474
+ fuzzySearch: function(query, term) {
475
+ var
476
+ termLength = term.length,
477
+ queryLength = query.length
478
+ ;
479
+ query = query.toLowerCase();
480
+ term = term.toLowerCase();
481
+ if(queryLength > termLength) {
482
+ return false;
483
+ }
484
+ if(queryLength === termLength) {
485
+ return (query === term);
486
+ }
487
+ search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
488
+ var
489
+ queryCharacter = query.charCodeAt(characterIndex)
490
+ ;
491
+ while(nextCharacterIndex < termLength) {
492
+ if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
493
+ continue search;
494
+ }
495
+ }
496
+ return false;
497
+ }
498
+ return true;
499
+ },
500
+
501
+ parse: {
502
+ response: function(response, searchTerm) {
503
+ var
504
+ searchHTML = module.generateResults(response)
505
+ ;
506
+ module.verbose('Parsing server response', response);
507
+ if(response !== undefined) {
508
+ if(searchTerm !== undefined && response.results !== undefined) {
509
+ module.write.cache(searchTerm, {
510
+ html : searchHTML,
511
+ results : response.results
512
+ });
513
+ module.save.results(response.results);
514
+ module.addResults(searchHTML);
515
+ }
516
+ }
517
+ }
518
+ },
519
+
520
+ throttle: function() {
521
+ clearTimeout(module.timer);
522
+ if(module.has.minimumCharacters()) {
523
+ module.timer = setTimeout(module.query, settings.searchDelay);
524
+ }
525
+ else {
526
+ module.hideResults();
527
+ }
528
+ },
529
+
530
+ cancel: {
531
+ query: function() {
532
+ if( module.can.useAPI() ) {
533
+ $module.api('abort');
534
+ }
535
+ }
536
+ },
537
+
538
+ has: {
539
+ minimumCharacters: function() {
540
+ var
541
+ searchTerm = module.get.value(),
542
+ numCharacters = searchTerm.length
543
+ ;
544
+ return (numCharacters >= settings.minCharacters);
545
+ }
546
+ },
547
+
548
+ read: {
549
+ cache: function(name) {
550
+ var
551
+ cache = $module.data(metadata.cache)
552
+ ;
553
+ if(settings.cache) {
554
+ module.verbose('Checking cache for generated html for query', name);
555
+ return (typeof cache == 'object') && (cache[name] !== undefined)
556
+ ? cache[name]
557
+ : false
558
+ ;
559
+ }
560
+ return false;
561
+ }
562
+ },
563
+
564
+ save: {
565
+ results: function(results) {
566
+ module.verbose('Saving current search results to metadata', results);
567
+ $module.data(metadata.results, results);
568
+ }
569
+ },
570
+
571
+ write: {
572
+ cache: function(name, value) {
573
+ var
574
+ cache = ($module.data(metadata.cache) !== undefined)
575
+ ? $module.data(metadata.cache)
576
+ : {}
577
+ ;
578
+ if(settings.cache) {
579
+ module.verbose('Writing generated html to cache', name, value);
580
+ cache[name] = value;
581
+ $module
582
+ .data(metadata.cache, cache)
583
+ ;
584
+ }
585
+ }
586
+ },
587
+
588
+ addResults: function(html) {
589
+ if( $.isFunction(settings.onResultsAdd) ) {
590
+ if( settings.onResultsAdd.call($results, html) === false ) {
591
+ module.debug('onResultsAdd callback cancelled default action');
592
+ return false;
593
+ }
594
+ }
595
+ $results
596
+ .html(html)
597
+ ;
598
+ module.showResults();
599
+ },
600
+
601
+ showResults: function() {
602
+ if( !module.is.visible() && module.is.focused() && !module.is.empty() ) {
603
+ if( module.can.transition() ) {
604
+ module.debug('Showing results with css animations');
605
+ $results
606
+ .transition({
607
+ animation : settings.transition + ' in',
608
+ duration : settings.duration,
609
+ queue : true
610
+ })
611
+ ;
612
+ }
613
+ else {
614
+ module.debug('Showing results with javascript');
615
+ $results
616
+ .stop()
617
+ .fadeIn(settings.duration, settings.easing)
618
+ ;
619
+ }
620
+ settings.onResultsOpen.call($results);
621
+ }
622
+ },
623
+ hideResults: function() {
624
+ if( module.is.visible() ) {
625
+ if( module.can.transition() ) {
626
+ module.debug('Hiding results with css animations');
627
+ $results
628
+ .transition({
629
+ animation : settings.transition + ' out',
630
+ duration : settings.duration,
631
+ queue : true
632
+ })
633
+ ;
634
+ }
635
+ else {
636
+ module.debug('Hiding results with javascript');
637
+ $results
638
+ .stop()
639
+ .fadeOut(settings.duration, settings.easing)
640
+ ;
641
+ }
642
+ settings.onResultsClose.call($results);
643
+ }
644
+ },
645
+
646
+ generateResults: function(response) {
647
+ module.debug('Generating html from response', response);
648
+ var
649
+ template = settings.templates[settings.type],
650
+ isProperObject = ($.isPlainObject(response.results) && !$.isEmptyObject(response.results)),
651
+ isProperArray = ($.isArray(response.results) && response.results.length > 0),
652
+ html = ''
653
+ ;
654
+ if(isProperObject || isProperArray ) {
655
+ if(settings.maxResults > 0) {
656
+ if(isProperObject) {
657
+ if(settings.type == 'standard') {
658
+ module.error(error.maxResults);
659
+ }
660
+ }
661
+ else {
662
+ response.results = response.results.slice(0, settings.maxResults);
663
+ }
664
+ }
665
+ if($.isFunction(template)) {
666
+ html = template(response);
667
+ }
668
+ else {
669
+ module.error(error.noTemplate, false);
670
+ }
671
+ }
672
+ else {
673
+ html = module.displayMessage(error.noResults, 'empty');
674
+ }
675
+ settings.onResults.call(element, response);
676
+ return html;
677
+ },
678
+
679
+ displayMessage: function(text, type) {
680
+ type = type || 'standard';
681
+ module.debug('Displaying message', text, type);
682
+ module.addResults( settings.templates.message(text, type) );
683
+ return settings.templates.message(text, type);
684
+ },
685
+
686
+ setting: function(name, value) {
687
+ if( $.isPlainObject(name) ) {
688
+ $.extend(true, settings, name);
689
+ }
690
+ else if(value !== undefined) {
691
+ settings[name] = value;
692
+ }
693
+ else {
694
+ return settings[name];
695
+ }
696
+ },
697
+ internal: function(name, value) {
698
+ if( $.isPlainObject(name) ) {
699
+ $.extend(true, module, name);
700
+ }
701
+ else if(value !== undefined) {
702
+ module[name] = value;
703
+ }
704
+ else {
705
+ return module[name];
706
+ }
707
+ },
708
+ debug: function() {
709
+ if(settings.debug) {
710
+ if(settings.performance) {
711
+ module.performance.log(arguments);
712
+ }
713
+ else {
714
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
715
+ module.debug.apply(console, arguments);
716
+ }
717
+ }
718
+ },
719
+ verbose: function() {
720
+ if(settings.verbose && settings.debug) {
721
+ if(settings.performance) {
722
+ module.performance.log(arguments);
723
+ }
724
+ else {
725
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
726
+ module.verbose.apply(console, arguments);
727
+ }
728
+ }
729
+ },
730
+ error: function() {
731
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
732
+ module.error.apply(console, arguments);
733
+ },
734
+ performance: {
735
+ log: function(message) {
736
+ var
737
+ currentTime,
738
+ executionTime,
739
+ previousTime
740
+ ;
741
+ if(settings.performance) {
742
+ currentTime = new Date().getTime();
743
+ previousTime = time || currentTime;
744
+ executionTime = currentTime - previousTime;
745
+ time = currentTime;
746
+ performance.push({
747
+ 'Name' : message[0],
748
+ 'Arguments' : [].slice.call(message, 1) || '',
749
+ 'Element' : element,
750
+ 'Execution Time' : executionTime
751
+ });
752
+ }
753
+ clearTimeout(module.performance.timer);
754
+ module.performance.timer = setTimeout(module.performance.display, 100);
755
+ },
756
+ display: function() {
757
+ var
758
+ title = settings.name + ':',
759
+ totalTime = 0
760
+ ;
761
+ time = false;
762
+ clearTimeout(module.performance.timer);
763
+ $.each(performance, function(index, data) {
764
+ totalTime += data['Execution Time'];
765
+ });
766
+ title += ' ' + totalTime + 'ms';
767
+ if(moduleSelector) {
768
+ title += ' \'' + moduleSelector + '\'';
769
+ }
770
+ if($allModules.length > 1) {
771
+ title += ' ' + '(' + $allModules.length + ')';
772
+ }
773
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
774
+ console.groupCollapsed(title);
775
+ if(console.table) {
776
+ console.table(performance);
777
+ }
778
+ else {
779
+ $.each(performance, function(index, data) {
780
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
781
+ });
782
+ }
783
+ console.groupEnd();
784
+ }
785
+ performance = [];
786
+ }
787
+ },
788
+ invoke: function(query, passedArguments, context) {
789
+ var
790
+ object = instance,
791
+ maxDepth,
792
+ found,
793
+ response
794
+ ;
795
+ passedArguments = passedArguments || queryArguments;
796
+ context = element || context;
797
+ if(typeof query == 'string' && object !== undefined) {
798
+ query = query.split(/[\. ]/);
799
+ maxDepth = query.length - 1;
800
+ $.each(query, function(depth, value) {
801
+ var camelCaseValue = (depth != maxDepth)
802
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
803
+ : query
804
+ ;
805
+ if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
806
+ object = object[camelCaseValue];
807
+ }
808
+ else if( object[camelCaseValue] !== undefined ) {
809
+ found = object[camelCaseValue];
810
+ return false;
811
+ }
812
+ else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
813
+ object = object[value];
814
+ }
815
+ else if( object[value] !== undefined ) {
816
+ found = object[value];
817
+ return false;
818
+ }
819
+ else {
820
+ return false;
821
+ }
822
+ });
823
+ }
824
+ if( $.isFunction( found ) ) {
825
+ response = found.apply(context, passedArguments);
826
+ }
827
+ else if(found !== undefined) {
828
+ response = found;
829
+ }
830
+ if($.isArray(returnedValue)) {
831
+ returnedValue.push(response);
832
+ }
833
+ else if(returnedValue !== undefined) {
834
+ returnedValue = [returnedValue, response];
835
+ }
836
+ else if(response !== undefined) {
837
+ returnedValue = response;
838
+ }
839
+ return found;
840
+ }
841
+ };
842
+ if(methodInvoked) {
843
+ if(instance === undefined) {
844
+ module.initialize();
845
+ }
846
+ module.invoke(query);
847
+ }
848
+ else {
849
+ if(instance !== undefined) {
850
+ instance.invoke('destroy');
851
+ }
852
+ module.initialize();
853
+ }
854
+
855
+ })
856
+ ;
857
+
858
+ return (returnedValue !== undefined)
859
+ ? returnedValue
860
+ : this
861
+ ;
862
+ };
863
+
864
+ $.fn.search.settings = {
865
+
866
+ name : 'Search Module',
867
+ namespace : 'search',
868
+
869
+ debug : false,
870
+ verbose : true,
871
+ performance : true,
872
+
873
+ type : 'standard',
874
+ minCharacters : 1,
875
+
876
+ // api config
877
+ apiSettings : false,
878
+
879
+ source : false,
880
+ searchFields : [
881
+ 'title',
882
+ 'description'
883
+ ],
884
+ searchFullText : true,
885
+
886
+ automatic : 'true',
887
+ hideDelay : 0,
888
+ searchDelay : 100,
889
+ maxResults : 7,
890
+ cache : true,
891
+
892
+ transition : 'scale',
893
+ duration : 300,
894
+ easing : 'easeOutExpo',
895
+
896
+ onSelect : false,
897
+ onResultsAdd : false,
898
+
899
+ onSearchQuery : function(){},
900
+ onResults : function(response){},
901
+
902
+ onResultsOpen : function(){},
903
+ onResultsClose : function(){},
904
+
905
+ className: {
906
+ active : 'active',
907
+ empty : 'empty',
908
+ focus : 'focus',
909
+ loading : 'loading',
910
+ pressed : 'down'
911
+ },
912
+
913
+ error : {
914
+ source : 'Cannot search. No source used, and Semantic API module was not included',
915
+ noResults : 'Your search returned no results',
916
+ logging : 'Error in debug logging, exiting.',
917
+ noEndpoint : 'No search endpoint was specified',
918
+ noTemplate : 'A valid template name was not specified.',
919
+ serverError : 'There was an issue with querying the server.',
920
+ maxResults : 'Results must be an array to use maxResults setting',
921
+ method : 'The method you called is not defined.'
922
+ },
923
+
924
+ metadata: {
925
+ cache : 'cache',
926
+ results : 'results'
927
+ },
928
+
929
+ regExp: {
930
+ escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
931
+ exact : '(?:\s|^)'
932
+ },
933
+
934
+ selector : {
935
+ prompt : '.prompt',
936
+ searchButton : '.search.button',
937
+ results : '.results',
938
+ category : '.category',
939
+ result : '.result',
940
+ title : '.title, .name'
941
+ },
942
+
943
+ templates: {
944
+ escape: function(string) {
945
+ var
946
+ badChars = /[&<>"'`]/g,
947
+ shouldEscape = /[&<>"'`]/,
948
+ escape = {
949
+ "&": "&amp;",
950
+ "<": "&lt;",
951
+ ">": "&gt;",
952
+ '"': "&quot;",
953
+ "'": "&#x27;",
954
+ "`": "&#x60;"
955
+ },
956
+ escapedChar = function(chr) {
957
+ return escape[chr];
958
+ }
959
+ ;
960
+ if(shouldEscape.test(string)) {
961
+ return string.replace(badChars, escapedChar);
962
+ }
963
+ return string;
964
+ },
965
+ message: function(message, type) {
966
+ var
967
+ html = ''
968
+ ;
969
+ if(message !== undefined && type !== undefined) {
970
+ html += ''
971
+ + '<div class="message ' + type + '">'
972
+ ;
973
+ // message type
974
+ if(type == 'empty') {
975
+ html += ''
976
+ + '<div class="header">No Results</div class="header">'
977
+ + '<div class="description">' + message + '</div class="description">'
978
+ ;
979
+ }
980
+ else {
981
+ html += ' <div class="description">' + message + '</div>';
982
+ }
983
+ html += '</div>';
984
+ }
985
+ return html;
986
+ },
987
+ category: function(response) {
988
+ var
989
+ html = '',
990
+ escape = $.fn.search.settings.templates.escape
991
+ ;
992
+ if(response.results !== undefined) {
993
+ // each category
994
+ $.each(response.results, function(index, category) {
995
+ if(category.results !== undefined && category.results.length > 0) {
996
+ html += ''
997
+ + '<div class="category">'
998
+ + '<div class="name">' + category.name + '</div>'
999
+ ;
1000
+ // each item inside category
1001
+ $.each(category.results, function(index, result) {
1002
+ html += '<div class="result">';
1003
+ if(result.url) {
1004
+ html += '<a href="' + result.url + '"></a>';
1005
+ }
1006
+ if(result.image !== undefined) {
1007
+ result.image = escape(result.image);
1008
+ html += ''
1009
+ + '<div class="image">'
1010
+ + ' <img src="' + result.image + '" alt="">'
1011
+ + '</div>'
1012
+ ;
1013
+ }
1014
+ html += '<div class="content">';
1015
+ if(result.price !== undefined) {
1016
+ result.price = escape(result.price);
1017
+ html += '<div class="price">' + result.price + '</div>';
1018
+ }
1019
+ if(result.title !== undefined) {
1020
+ result.title = escape(result.title);
1021
+ html += '<div class="title">' + result.title + '</div>';
1022
+ }
1023
+ if(result.description !== undefined) {
1024
+ html += '<div class="description">' + result.description + '</div>';
1025
+ }
1026
+ html += ''
1027
+ + '</div>'
1028
+ + '</div>'
1029
+ ;
1030
+ });
1031
+ html += ''
1032
+ + '</div>'
1033
+ ;
1034
+ }
1035
+ });
1036
+ if(response.action) {
1037
+ html += ''
1038
+ + '<a href="' + response.action.url + '" class="action">'
1039
+ + response.action.text
1040
+ + '</a>';
1041
+ }
1042
+ return html;
1043
+ }
1044
+ return false;
1045
+ },
1046
+ standard: function(response) {
1047
+ var
1048
+ html = ''
1049
+ ;
1050
+ if(response.results !== undefined) {
1051
+
1052
+ // each result
1053
+ $.each(response.results, function(index, result) {
1054
+ if(result.url) {
1055
+ html += '<a class="result" href="' + result.url + '">';
1056
+ }
1057
+ else {
1058
+ html += '<a class="result">';
1059
+ }
1060
+ if(result.image !== undefined) {
1061
+ html += ''
1062
+ + '<div class="image">'
1063
+ + ' <img src="' + result.image + '">'
1064
+ + '</div>'
1065
+ ;
1066
+ }
1067
+ html += '<div class="content">';
1068
+ if(result.price !== undefined) {
1069
+ html += '<div class="price">' + result.price + '</div>';
1070
+ }
1071
+ if(result.title !== undefined) {
1072
+ html += '<div class="title">' + result.title + '</div>';
1073
+ }
1074
+ if(result.description !== undefined) {
1075
+ html += '<div class="description">' + result.description + '</div>';
1076
+ }
1077
+ html += ''
1078
+ + '</div>'
1079
+ ;
1080
+ html += '</a>';
1081
+ });
1082
+
1083
+ if(response.action) {
1084
+ html += ''
1085
+ + '<a href="' + response.action.url + '" class="action">'
1086
+ + response.action.text
1087
+ + '</a>';
1088
+ }
1089
+ return html;
1090
+ }
1091
+ return false;
1092
+ }
1093
+ }
1094
+ };
1095
+
1096
+ })( jQuery, window , document );