@ntlab/ntjs-assets 2.0.2 → 2.0.3

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