fomantic-ui-sass 2.6.4

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