@materializecss/materialize 1.2.0 → 1.2.2

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 (82) hide show
  1. package/Gruntfile.js +722 -712
  2. package/LICENSE +21 -21
  3. package/README.md +91 -91
  4. package/dist/css/materialize.css +78 -137
  5. package/dist/css/materialize.min.css +12 -12
  6. package/dist/js/materialize.js +1502 -1378
  7. package/dist/js/materialize.min.js +6 -6
  8. package/extras/noUiSlider/nouislider.css +403 -403
  9. package/extras/noUiSlider/nouislider.js +2147 -2147
  10. package/js/anime.min.js +34 -34
  11. package/js/autocomplete.js +479 -479
  12. package/js/buttons.js +354 -354
  13. package/js/cards.js +40 -40
  14. package/js/carousel.js +732 -732
  15. package/js/cash.js +960 -960
  16. package/js/characterCounter.js +136 -136
  17. package/js/chips.js +486 -486
  18. package/js/collapsible.js +275 -275
  19. package/js/component.js +44 -44
  20. package/js/datepicker.js +983 -983
  21. package/js/dropdown.js +669 -669
  22. package/js/forms.js +285 -285
  23. package/js/global.js +428 -428
  24. package/js/materialbox.js +453 -453
  25. package/js/modal.js +382 -382
  26. package/js/parallax.js +138 -138
  27. package/js/pushpin.js +148 -148
  28. package/js/range.js +263 -263
  29. package/js/scrollspy.js +295 -295
  30. package/js/select.js +391 -391
  31. package/js/sidenav.js +583 -583
  32. package/js/slider.js +497 -359
  33. package/js/tabs.js +402 -402
  34. package/js/tapTarget.js +315 -315
  35. package/js/timepicker.js +712 -712
  36. package/js/toasts.js +325 -325
  37. package/js/tooltip.js +320 -320
  38. package/js/waves.js +614 -614
  39. package/package.json +87 -84
  40. package/sass/components/_badges.scss +55 -55
  41. package/sass/components/_buttons.scss +322 -322
  42. package/sass/components/_cards.scss +195 -195
  43. package/sass/components/_carousel.scss +90 -90
  44. package/sass/components/_chips.scss +96 -96
  45. package/sass/components/_collapsible.scss +91 -91
  46. package/sass/components/_collection.scss +106 -106
  47. package/sass/components/_color-classes.scss +32 -32
  48. package/sass/components/_color-variables.scss +370 -370
  49. package/sass/components/_datepicker.scss +191 -191
  50. package/sass/components/_dropdown.scss +84 -84
  51. package/sass/components/_global.scss +646 -646
  52. package/sass/components/_grid.scss +158 -158
  53. package/sass/components/_icons-material-design.scss +5 -5
  54. package/sass/components/_materialbox.scss +42 -42
  55. package/sass/components/_modal.scss +97 -97
  56. package/sass/components/_navbar.scss +208 -208
  57. package/sass/components/_normalize.scss +447 -447
  58. package/sass/components/_preloader.scss +334 -334
  59. package/sass/components/_pulse.scss +34 -34
  60. package/sass/components/_sidenav.scss +214 -214
  61. package/sass/components/_slider.scss +100 -91
  62. package/sass/components/_table_of_contents.scss +33 -33
  63. package/sass/components/_tabs.scss +99 -99
  64. package/sass/components/_tapTarget.scss +103 -103
  65. package/sass/components/_timepicker.scss +199 -199
  66. package/sass/components/_toast.scss +58 -58
  67. package/sass/components/_tooltip.scss +32 -32
  68. package/sass/components/_transitions.scss +12 -12
  69. package/sass/components/_typography.scss +62 -62
  70. package/sass/components/_variables.scss +352 -352
  71. package/sass/components/_waves.scss +187 -187
  72. package/sass/components/forms/_checkboxes.scss +200 -200
  73. package/sass/components/forms/_file-input.scss +44 -44
  74. package/sass/components/forms/_forms.scss +22 -22
  75. package/sass/components/forms/_input-fields.scss +388 -388
  76. package/sass/components/forms/_radio-buttons.scss +115 -115
  77. package/sass/components/forms/_range.scss +161 -161
  78. package/sass/components/forms/_select.scss +199 -199
  79. package/sass/components/forms/_switches.scss +91 -91
  80. package/sass/materialize.scss +42 -42
  81. package/sass/_style.scss +0 -929
  82. package/sass/ghpages-materialize.scss +0 -7
@@ -1,479 +1,479 @@
1
- (function($) {
2
- 'use strict';
3
-
4
- let _defaults = {
5
- data: {}, // Autocomplete data set
6
- limit: Infinity, // Limit of results the autocomplete shows
7
- onAutocomplete: null, // Callback for when autocompleted
8
- dropdownOptions: {
9
- // Default dropdown options
10
- autoFocus: false,
11
- closeOnClick: false,
12
- coverTrigger: false
13
- },
14
- minLength: 1, // Min characters before autocomplete starts
15
- sortFunction: function(a, b, inputString) {
16
- // Sort function for sorting autocomplete results
17
- return a.indexOf(inputString) - b.indexOf(inputString);
18
- },
19
- allowUnsafeHTML: false
20
- };
21
-
22
- /**
23
- * @class
24
- *
25
- */
26
- class Autocomplete extends Component {
27
- /**
28
- * Construct Autocomplete instance
29
- * @constructor
30
- * @param {Element} el
31
- * @param {Object} options
32
- */
33
- constructor(el, options) {
34
- super(Autocomplete, el, options);
35
-
36
- this.el.M_Autocomplete = this;
37
-
38
- /**
39
- * Options for the autocomplete
40
- * @member Autocomplete#options
41
- * @prop {Number} duration
42
- * @prop {Number} dist
43
- * @prop {number} shift
44
- * @prop {number} padding
45
- * @prop {Boolean} fullWidth
46
- * @prop {Boolean} indicators
47
- * @prop {Boolean} noWrap
48
- * @prop {Function} onCycleTo
49
- */
50
- this.options = $.extend({}, Autocomplete.defaults, options);
51
-
52
- // Setup
53
- this.isOpen = false;
54
- this.count = 0;
55
- this.activeIndex = -1;
56
- this.oldVal;
57
- this.$inputField = this.$el.closest('.input-field');
58
- this.$active = $();
59
- this._mousedown = false;
60
- this._setupDropdown();
61
-
62
- this._setupEventHandlers();
63
- }
64
-
65
- static get defaults() {
66
- return _defaults;
67
- }
68
-
69
- static init(els, options) {
70
- return super.init(this, els, options);
71
- }
72
-
73
- /**
74
- * Get Instance
75
- */
76
- static getInstance(el) {
77
- let domElem = !!el.jquery ? el[0] : el;
78
- return domElem.M_Autocomplete;
79
- }
80
-
81
- /**
82
- * Teardown component
83
- */
84
- destroy() {
85
- this._removeEventHandlers();
86
- this._removeDropdown();
87
- this.el.M_Autocomplete = undefined;
88
- }
89
-
90
- /**
91
- * Setup Event Handlers
92
- */
93
- _setupEventHandlers() {
94
- this._handleInputBlurBound = this._handleInputBlur.bind(this);
95
- this._handleInputKeyupAndFocusBound = this._handleInputKeyupAndFocus.bind(this);
96
- this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
97
- this._handleInputClickBound = this._handleInputClick.bind(this);
98
- this._handleContainerMousedownAndTouchstartBound = this._handleContainerMousedownAndTouchstart.bind(
99
- this
100
- );
101
- this._handleContainerMouseupAndTouchendBound = this._handleContainerMouseupAndTouchend.bind(
102
- this
103
- );
104
-
105
- this.el.addEventListener('blur', this._handleInputBlurBound);
106
- this.el.addEventListener('keyup', this._handleInputKeyupAndFocusBound);
107
- this.el.addEventListener('focus', this._handleInputKeyupAndFocusBound);
108
- this.el.addEventListener('keydown', this._handleInputKeydownBound);
109
- this.el.addEventListener('click', this._handleInputClickBound);
110
- this.container.addEventListener(
111
- 'mousedown',
112
- this._handleContainerMousedownAndTouchstartBound
113
- );
114
- this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
115
-
116
- if (typeof window.ontouchstart !== 'undefined') {
117
- this.container.addEventListener(
118
- 'touchstart',
119
- this._handleContainerMousedownAndTouchstartBound
120
- );
121
- this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchendBound);
122
- }
123
- }
124
-
125
- /**
126
- * Remove Event Handlers
127
- */
128
- _removeEventHandlers() {
129
- this.el.removeEventListener('blur', this._handleInputBlurBound);
130
- this.el.removeEventListener('keyup', this._handleInputKeyupAndFocusBound);
131
- this.el.removeEventListener('focus', this._handleInputKeyupAndFocusBound);
132
- this.el.removeEventListener('keydown', this._handleInputKeydownBound);
133
- this.el.removeEventListener('click', this._handleInputClickBound);
134
- this.container.removeEventListener(
135
- 'mousedown',
136
- this._handleContainerMousedownAndTouchstartBound
137
- );
138
- this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
139
-
140
- if (typeof window.ontouchstart !== 'undefined') {
141
- this.container.removeEventListener(
142
- 'touchstart',
143
- this._handleContainerMousedownAndTouchstartBound
144
- );
145
- this.container.removeEventListener(
146
- 'touchend',
147
- this._handleContainerMouseupAndTouchendBound
148
- );
149
- }
150
- }
151
-
152
- /**
153
- * Setup dropdown
154
- */
155
- _setupDropdown() {
156
- this.container = document.createElement('ul');
157
- this.container.id = `autocomplete-options-${M.guid()}`;
158
- $(this.container).addClass('autocomplete-content dropdown-content');
159
- this.$inputField.append(this.container);
160
- this.el.setAttribute('data-target', this.container.id);
161
-
162
- // Initialize dropdown
163
- let dropdownOptions = $.extend(
164
- {},
165
- Autocomplete.defaults.dropdownOptions,
166
- this.options.dropdownOptions
167
- );
168
- let userOnItemClick = dropdownOptions.onItemClick;
169
-
170
- // Ensuring the selectOption call when user passes custom onItemClick function to dropdown
171
- dropdownOptions.onItemClick = (el) => {
172
- this.selectOption($(el));
173
-
174
- // Handle user declared onItemClick if needed
175
- if (userOnItemClick && typeof userOnItemClick === 'function') {
176
- userOnItemClick.call(this.dropdown, this.el);
177
- }
178
- };
179
-
180
- this.dropdown = M.Dropdown.init(this.el, dropdownOptions);
181
-
182
- // Sketchy removal of dropdown click handler
183
- this.el.removeEventListener('click', this.dropdown._handleClickBound);
184
- }
185
-
186
- /**
187
- * Remove dropdown
188
- */
189
- _removeDropdown() {
190
- this.container.parentNode.removeChild(this.container);
191
- }
192
-
193
- /**
194
- * Handle Input Blur
195
- */
196
- _handleInputBlur() {
197
- if (!this._mousedown) {
198
- this.close();
199
- this._resetAutocomplete();
200
- }
201
- }
202
-
203
- /**
204
- * Handle Input Keyup and Focus
205
- * @param {Event} e
206
- */
207
- _handleInputKeyupAndFocus(e) {
208
- if (e.type === 'keyup') {
209
- Autocomplete._keydown = false;
210
- }
211
-
212
- this.count = 0;
213
- let val = this.el.value.toLowerCase();
214
-
215
- // Don't capture enter or arrow key usage.
216
- if (e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40) {
217
- return;
218
- }
219
-
220
- // Check if the input isn't empty
221
- // Check if focus triggered by tab
222
- if (this.oldVal !== val && (M.tabPressed || e.type !== 'focus')) {
223
- this.open();
224
- }
225
-
226
- // Update oldVal
227
- this.oldVal = val;
228
- }
229
-
230
- /**
231
- * Handle Input Keydown
232
- * @param {Event} e
233
- */
234
- _handleInputKeydown(e) {
235
- Autocomplete._keydown = true;
236
-
237
- // Arrow keys and enter key usage
238
- let keyCode = e.keyCode,
239
- liElement,
240
- numItems = $(this.container).children('li').length;
241
-
242
- // select element on Enter
243
- if (keyCode === M.keys.ENTER && this.activeIndex >= 0) {
244
- liElement = $(this.container)
245
- .children('li')
246
- .eq(this.activeIndex);
247
- if (liElement.length) {
248
- this.selectOption(liElement);
249
- e.preventDefault();
250
- }
251
- return;
252
- }
253
-
254
- // Capture up and down key
255
- if (keyCode === M.keys.ARROW_UP || keyCode === M.keys.ARROW_DOWN) {
256
- e.preventDefault();
257
-
258
- if (keyCode === M.keys.ARROW_UP && this.activeIndex > 0) {
259
- this.activeIndex--;
260
- }
261
-
262
- if (keyCode === M.keys.ARROW_DOWN && this.activeIndex < numItems - 1) {
263
- this.activeIndex++;
264
- }
265
-
266
- this.$active.removeClass('active');
267
- if (this.activeIndex >= 0) {
268
- this.$active = $(this.container)
269
- .children('li')
270
- .eq(this.activeIndex);
271
- this.$active.addClass('active');
272
-
273
- // Focus selected
274
- this.container.children[this.activeIndex].scrollIntoView({
275
- behavior: 'smooth',
276
- block: 'nearest',
277
- inline: 'nearest'
278
- });
279
- }
280
- }
281
- }
282
-
283
- /**
284
- * Handle Input Click
285
- * @param {Event} e
286
- */
287
- _handleInputClick(e) {
288
- this.open();
289
- }
290
-
291
- /**
292
- * Handle Container Mousedown and Touchstart
293
- * @param {Event} e
294
- */
295
- _handleContainerMousedownAndTouchstart(e) {
296
- this._mousedown = true;
297
- }
298
-
299
- /**
300
- * Handle Container Mouseup and Touchend
301
- * @param {Event} e
302
- */
303
- _handleContainerMouseupAndTouchend(e) {
304
- this._mousedown = false;
305
- }
306
-
307
- /**
308
- * Highlight partial match
309
- */
310
- _highlight(input, label) {
311
- const start = label.toLowerCase().indexOf('' + input.toLowerCase() + '');
312
- const end = start + input.length - 1;
313
- //custom filters may return results where the string does not match any part
314
- if (start == -1 || end == -1) {
315
- return [label, '', ''];
316
- }
317
- return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];
318
- }
319
-
320
- /**
321
- * Reset current element position
322
- */
323
- _resetCurrentElement() {
324
- this.activeIndex = -1;
325
- this.$active.removeClass('active');
326
- }
327
-
328
- /**
329
- * Reset autocomplete elements
330
- */
331
- _resetAutocomplete() {
332
- $(this.container).empty();
333
- this._resetCurrentElement();
334
- this.oldVal = null;
335
- this.isOpen = false;
336
- this._mousedown = false;
337
- }
338
-
339
- /**
340
- * Select autocomplete option
341
- * @param {Element} el Autocomplete option list item element
342
- */
343
- selectOption(el) {
344
- let text = el.text().trim();
345
- this.el.value = text;
346
- this.$el.trigger('change');
347
- this._resetAutocomplete();
348
- this.close();
349
-
350
- // Handle onAutocomplete callback.
351
- if (typeof this.options.onAutocomplete === 'function') {
352
- this.options.onAutocomplete.call(this, text);
353
- }
354
- }
355
-
356
- /**
357
- * Render dropdown content
358
- * @param {Object} data data set
359
- * @param {String} val current input value
360
- */
361
- _renderDropdown(data, val) {
362
- this._resetAutocomplete();
363
-
364
- let matchingData = [];
365
-
366
- // Gather all matching data
367
- for (let key in data) {
368
- if (data.hasOwnProperty(key) && key.toLowerCase().indexOf(val) !== -1) {
369
- let entry = {
370
- data: data[key],
371
- key: key
372
- };
373
- matchingData.push(entry);
374
-
375
- this.count++;
376
- }
377
- }
378
-
379
- // Sort
380
- if (this.options.sortFunction) {
381
- let sortFunctionBound = (a, b) => {
382
- return this.options.sortFunction(
383
- a.key.toLowerCase(),
384
- b.key.toLowerCase(),
385
- val.toLowerCase()
386
- );
387
- };
388
- matchingData.sort(sortFunctionBound);
389
- }
390
-
391
- // Limit
392
- matchingData = matchingData.slice(0, this.options.limit);
393
-
394
- // Render
395
- for (let i = 0; i < matchingData.length; i++) {
396
- const entry = matchingData[i];
397
- const item = document.createElement('li');
398
- if (!!entry.data) {
399
- const img = document.createElement('img');
400
- img.classList.add('right', 'circle');
401
- img.src = entry.data;
402
- item.appendChild(img);
403
- }
404
-
405
- const parts = this._highlight(val, entry.key);
406
- const s = document.createElement('span');
407
- if (this.options.allowUnsafeHTML) {
408
- s.innerHTML = parts[0] + '<span class="highlight">' + parts[1] + '</span>' + parts[2];
409
- } else {
410
- s.appendChild(document.createTextNode(parts[0]));
411
- if (!!parts[1]) {
412
- const highlight = document.createElement('span');
413
- highlight.textContent = parts[1];
414
- highlight.classList.add('highlight');
415
- s.appendChild(highlight);
416
- s.appendChild(document.createTextNode(parts[2]));
417
- }
418
- }
419
- item.appendChild(s);
420
-
421
- $(this.container).append(item);
422
- }
423
- }
424
-
425
- /**
426
- * Open Autocomplete Dropdown
427
- */
428
- open() {
429
- let val = this.el.value.toLowerCase();
430
-
431
- this._resetAutocomplete();
432
-
433
- if (val.length >= this.options.minLength) {
434
- this.isOpen = true;
435
- this._renderDropdown(this.options.data, val);
436
- }
437
-
438
- // Open dropdown
439
- if (!this.dropdown.isOpen) {
440
- this.dropdown.open();
441
- } else {
442
- // Recalculate dropdown when its already open
443
- this.dropdown.recalculateDimensions();
444
- }
445
- }
446
-
447
- /**
448
- * Close Autocomplete Dropdown
449
- */
450
- close() {
451
- this.dropdown.close();
452
- }
453
-
454
- /**
455
- * Update Data
456
- * @param {Object} data
457
- */
458
- updateData(data) {
459
- let val = this.el.value.toLowerCase();
460
- this.options.data = data;
461
-
462
- if (this.isOpen) {
463
- this._renderDropdown(data, val);
464
- }
465
- }
466
- }
467
-
468
- /**
469
- * @static
470
- * @memberof Autocomplete
471
- */
472
- Autocomplete._keydown = false;
473
-
474
- M.Autocomplete = Autocomplete;
475
-
476
- if (M.jQueryLoaded) {
477
- M.initializeJqueryWrapper(Autocomplete, 'autocomplete', 'M_Autocomplete');
478
- }
479
- })(cash);
1
+ (function($) {
2
+ 'use strict';
3
+
4
+ let _defaults = {
5
+ data: {}, // Autocomplete data set
6
+ limit: Infinity, // Limit of results the autocomplete shows
7
+ onAutocomplete: null, // Callback for when autocompleted
8
+ dropdownOptions: {
9
+ // Default dropdown options
10
+ autoFocus: false,
11
+ closeOnClick: false,
12
+ coverTrigger: false
13
+ },
14
+ minLength: 1, // Min characters before autocomplete starts
15
+ sortFunction: function(a, b, inputString) {
16
+ // Sort function for sorting autocomplete results
17
+ return a.indexOf(inputString) - b.indexOf(inputString);
18
+ },
19
+ allowUnsafeHTML: false
20
+ };
21
+
22
+ /**
23
+ * @class
24
+ *
25
+ */
26
+ class Autocomplete extends Component {
27
+ /**
28
+ * Construct Autocomplete instance
29
+ * @constructor
30
+ * @param {Element} el
31
+ * @param {Object} options
32
+ */
33
+ constructor(el, options) {
34
+ super(Autocomplete, el, options);
35
+
36
+ this.el.M_Autocomplete = this;
37
+
38
+ /**
39
+ * Options for the autocomplete
40
+ * @member Autocomplete#options
41
+ * @prop {Number} duration
42
+ * @prop {Number} dist
43
+ * @prop {number} shift
44
+ * @prop {number} padding
45
+ * @prop {Boolean} fullWidth
46
+ * @prop {Boolean} indicators
47
+ * @prop {Boolean} noWrap
48
+ * @prop {Function} onCycleTo
49
+ */
50
+ this.options = $.extend({}, Autocomplete.defaults, options);
51
+
52
+ // Setup
53
+ this.isOpen = false;
54
+ this.count = 0;
55
+ this.activeIndex = -1;
56
+ this.oldVal;
57
+ this.$inputField = this.$el.closest('.input-field');
58
+ this.$active = $();
59
+ this._mousedown = false;
60
+ this._setupDropdown();
61
+
62
+ this._setupEventHandlers();
63
+ }
64
+
65
+ static get defaults() {
66
+ return _defaults;
67
+ }
68
+
69
+ static init(els, options) {
70
+ return super.init(this, els, options);
71
+ }
72
+
73
+ /**
74
+ * Get Instance
75
+ */
76
+ static getInstance(el) {
77
+ let domElem = !!el.jquery ? el[0] : el;
78
+ return domElem.M_Autocomplete;
79
+ }
80
+
81
+ /**
82
+ * Teardown component
83
+ */
84
+ destroy() {
85
+ this._removeEventHandlers();
86
+ this._removeDropdown();
87
+ this.el.M_Autocomplete = undefined;
88
+ }
89
+
90
+ /**
91
+ * Setup Event Handlers
92
+ */
93
+ _setupEventHandlers() {
94
+ this._handleInputBlurBound = this._handleInputBlur.bind(this);
95
+ this._handleInputKeyupAndFocusBound = this._handleInputKeyupAndFocus.bind(this);
96
+ this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
97
+ this._handleInputClickBound = this._handleInputClick.bind(this);
98
+ this._handleContainerMousedownAndTouchstartBound = this._handleContainerMousedownAndTouchstart.bind(
99
+ this
100
+ );
101
+ this._handleContainerMouseupAndTouchendBound = this._handleContainerMouseupAndTouchend.bind(
102
+ this
103
+ );
104
+
105
+ this.el.addEventListener('blur', this._handleInputBlurBound);
106
+ this.el.addEventListener('keyup', this._handleInputKeyupAndFocusBound);
107
+ this.el.addEventListener('focus', this._handleInputKeyupAndFocusBound);
108
+ this.el.addEventListener('keydown', this._handleInputKeydownBound);
109
+ this.el.addEventListener('click', this._handleInputClickBound);
110
+ this.container.addEventListener(
111
+ 'mousedown',
112
+ this._handleContainerMousedownAndTouchstartBound
113
+ );
114
+ this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
115
+
116
+ if (typeof window.ontouchstart !== 'undefined') {
117
+ this.container.addEventListener(
118
+ 'touchstart',
119
+ this._handleContainerMousedownAndTouchstartBound
120
+ );
121
+ this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchendBound);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Remove Event Handlers
127
+ */
128
+ _removeEventHandlers() {
129
+ this.el.removeEventListener('blur', this._handleInputBlurBound);
130
+ this.el.removeEventListener('keyup', this._handleInputKeyupAndFocusBound);
131
+ this.el.removeEventListener('focus', this._handleInputKeyupAndFocusBound);
132
+ this.el.removeEventListener('keydown', this._handleInputKeydownBound);
133
+ this.el.removeEventListener('click', this._handleInputClickBound);
134
+ this.container.removeEventListener(
135
+ 'mousedown',
136
+ this._handleContainerMousedownAndTouchstartBound
137
+ );
138
+ this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
139
+
140
+ if (typeof window.ontouchstart !== 'undefined') {
141
+ this.container.removeEventListener(
142
+ 'touchstart',
143
+ this._handleContainerMousedownAndTouchstartBound
144
+ );
145
+ this.container.removeEventListener(
146
+ 'touchend',
147
+ this._handleContainerMouseupAndTouchendBound
148
+ );
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Setup dropdown
154
+ */
155
+ _setupDropdown() {
156
+ this.container = document.createElement('ul');
157
+ this.container.id = `autocomplete-options-${M.guid()}`;
158
+ $(this.container).addClass('autocomplete-content dropdown-content');
159
+ this.$inputField.append(this.container);
160
+ this.el.setAttribute('data-target', this.container.id);
161
+
162
+ // Initialize dropdown
163
+ let dropdownOptions = $.extend(
164
+ {},
165
+ Autocomplete.defaults.dropdownOptions,
166
+ this.options.dropdownOptions
167
+ );
168
+ let userOnItemClick = dropdownOptions.onItemClick;
169
+
170
+ // Ensuring the selectOption call when user passes custom onItemClick function to dropdown
171
+ dropdownOptions.onItemClick = (el) => {
172
+ this.selectOption($(el));
173
+
174
+ // Handle user declared onItemClick if needed
175
+ if (userOnItemClick && typeof userOnItemClick === 'function') {
176
+ userOnItemClick.call(this.dropdown, this.el);
177
+ }
178
+ };
179
+
180
+ this.dropdown = M.Dropdown.init(this.el, dropdownOptions);
181
+
182
+ // Sketchy removal of dropdown click handler
183
+ this.el.removeEventListener('click', this.dropdown._handleClickBound);
184
+ }
185
+
186
+ /**
187
+ * Remove dropdown
188
+ */
189
+ _removeDropdown() {
190
+ this.container.parentNode.removeChild(this.container);
191
+ }
192
+
193
+ /**
194
+ * Handle Input Blur
195
+ */
196
+ _handleInputBlur() {
197
+ if (!this._mousedown) {
198
+ this.close();
199
+ this._resetAutocomplete();
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Handle Input Keyup and Focus
205
+ * @param {Event} e
206
+ */
207
+ _handleInputKeyupAndFocus(e) {
208
+ if (e.type === 'keyup') {
209
+ Autocomplete._keydown = false;
210
+ }
211
+
212
+ this.count = 0;
213
+ let val = this.el.value.toLowerCase();
214
+
215
+ // Don't capture enter or arrow key usage.
216
+ if (e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40) {
217
+ return;
218
+ }
219
+
220
+ // Check if the input isn't empty
221
+ // Check if focus triggered by tab
222
+ if (this.oldVal !== val && (M.tabPressed || e.type !== 'focus')) {
223
+ this.open();
224
+ }
225
+
226
+ // Update oldVal
227
+ this.oldVal = val;
228
+ }
229
+
230
+ /**
231
+ * Handle Input Keydown
232
+ * @param {Event} e
233
+ */
234
+ _handleInputKeydown(e) {
235
+ Autocomplete._keydown = true;
236
+
237
+ // Arrow keys and enter key usage
238
+ let keyCode = e.keyCode,
239
+ liElement,
240
+ numItems = $(this.container).children('li').length;
241
+
242
+ // select element on Enter
243
+ if (keyCode === M.keys.ENTER && this.activeIndex >= 0) {
244
+ liElement = $(this.container)
245
+ .children('li')
246
+ .eq(this.activeIndex);
247
+ if (liElement.length) {
248
+ this.selectOption(liElement);
249
+ e.preventDefault();
250
+ }
251
+ return;
252
+ }
253
+
254
+ // Capture up and down key
255
+ if (keyCode === M.keys.ARROW_UP || keyCode === M.keys.ARROW_DOWN) {
256
+ e.preventDefault();
257
+
258
+ if (keyCode === M.keys.ARROW_UP && this.activeIndex > 0) {
259
+ this.activeIndex--;
260
+ }
261
+
262
+ if (keyCode === M.keys.ARROW_DOWN && this.activeIndex < numItems - 1) {
263
+ this.activeIndex++;
264
+ }
265
+
266
+ this.$active.removeClass('active');
267
+ if (this.activeIndex >= 0) {
268
+ this.$active = $(this.container)
269
+ .children('li')
270
+ .eq(this.activeIndex);
271
+ this.$active.addClass('active');
272
+
273
+ // Focus selected
274
+ this.container.children[this.activeIndex].scrollIntoView({
275
+ behavior: 'smooth',
276
+ block: 'nearest',
277
+ inline: 'nearest'
278
+ });
279
+ }
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Handle Input Click
285
+ * @param {Event} e
286
+ */
287
+ _handleInputClick(e) {
288
+ this.open();
289
+ }
290
+
291
+ /**
292
+ * Handle Container Mousedown and Touchstart
293
+ * @param {Event} e
294
+ */
295
+ _handleContainerMousedownAndTouchstart(e) {
296
+ this._mousedown = true;
297
+ }
298
+
299
+ /**
300
+ * Handle Container Mouseup and Touchend
301
+ * @param {Event} e
302
+ */
303
+ _handleContainerMouseupAndTouchend(e) {
304
+ this._mousedown = false;
305
+ }
306
+
307
+ /**
308
+ * Highlight partial match
309
+ */
310
+ _highlight(input, label) {
311
+ const start = label.toLowerCase().indexOf('' + input.toLowerCase() + '');
312
+ const end = start + input.length - 1;
313
+ //custom filters may return results where the string does not match any part
314
+ if (start == -1 || end == -1) {
315
+ return [label, '', ''];
316
+ }
317
+ return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];
318
+ }
319
+
320
+ /**
321
+ * Reset current element position
322
+ */
323
+ _resetCurrentElement() {
324
+ this.activeIndex = -1;
325
+ this.$active.removeClass('active');
326
+ }
327
+
328
+ /**
329
+ * Reset autocomplete elements
330
+ */
331
+ _resetAutocomplete() {
332
+ $(this.container).empty();
333
+ this._resetCurrentElement();
334
+ this.oldVal = null;
335
+ this.isOpen = false;
336
+ this._mousedown = false;
337
+ }
338
+
339
+ /**
340
+ * Select autocomplete option
341
+ * @param {Element} el Autocomplete option list item element
342
+ */
343
+ selectOption(el) {
344
+ let text = el.text().trim();
345
+ this.el.value = text;
346
+ this.$el.trigger('change');
347
+ this._resetAutocomplete();
348
+ this.close();
349
+
350
+ // Handle onAutocomplete callback.
351
+ if (typeof this.options.onAutocomplete === 'function') {
352
+ this.options.onAutocomplete.call(this, text);
353
+ }
354
+ }
355
+
356
+ /**
357
+ * Render dropdown content
358
+ * @param {Object} data data set
359
+ * @param {String} val current input value
360
+ */
361
+ _renderDropdown(data, val) {
362
+ this._resetAutocomplete();
363
+
364
+ let matchingData = [];
365
+
366
+ // Gather all matching data
367
+ for (let key in data) {
368
+ if (data.hasOwnProperty(key) && key.toLowerCase().indexOf(val) !== -1) {
369
+ let entry = {
370
+ data: data[key],
371
+ key: key
372
+ };
373
+ matchingData.push(entry);
374
+
375
+ this.count++;
376
+ }
377
+ }
378
+
379
+ // Sort
380
+ if (this.options.sortFunction) {
381
+ let sortFunctionBound = (a, b) => {
382
+ return this.options.sortFunction(
383
+ a.key.toLowerCase(),
384
+ b.key.toLowerCase(),
385
+ val.toLowerCase()
386
+ );
387
+ };
388
+ matchingData.sort(sortFunctionBound);
389
+ }
390
+
391
+ // Limit
392
+ matchingData = matchingData.slice(0, this.options.limit);
393
+
394
+ // Render
395
+ for (let i = 0; i < matchingData.length; i++) {
396
+ const entry = matchingData[i];
397
+ const item = document.createElement('li');
398
+ if (!!entry.data) {
399
+ const img = document.createElement('img');
400
+ img.classList.add('right', 'circle');
401
+ img.src = entry.data;
402
+ item.appendChild(img);
403
+ }
404
+
405
+ const parts = this._highlight(val, entry.key);
406
+ const s = document.createElement('span');
407
+ if (this.options.allowUnsafeHTML) {
408
+ s.innerHTML = parts[0] + '<span class="highlight">' + parts[1] + '</span>' + parts[2];
409
+ } else {
410
+ s.appendChild(document.createTextNode(parts[0]));
411
+ if (!!parts[1]) {
412
+ const highlight = document.createElement('span');
413
+ highlight.textContent = parts[1];
414
+ highlight.classList.add('highlight');
415
+ s.appendChild(highlight);
416
+ s.appendChild(document.createTextNode(parts[2]));
417
+ }
418
+ }
419
+ item.appendChild(s);
420
+
421
+ $(this.container).append(item);
422
+ }
423
+ }
424
+
425
+ /**
426
+ * Open Autocomplete Dropdown
427
+ */
428
+ open() {
429
+ let val = this.el.value.toLowerCase();
430
+
431
+ this._resetAutocomplete();
432
+
433
+ if (val.length >= this.options.minLength) {
434
+ this.isOpen = true;
435
+ this._renderDropdown(this.options.data, val);
436
+ }
437
+
438
+ // Open dropdown
439
+ if (!this.dropdown.isOpen) {
440
+ this.dropdown.open();
441
+ } else {
442
+ // Recalculate dropdown when its already open
443
+ this.dropdown.recalculateDimensions();
444
+ }
445
+ }
446
+
447
+ /**
448
+ * Close Autocomplete Dropdown
449
+ */
450
+ close() {
451
+ this.dropdown.close();
452
+ }
453
+
454
+ /**
455
+ * Update Data
456
+ * @param {Object} data
457
+ */
458
+ updateData(data) {
459
+ let val = this.el.value.toLowerCase();
460
+ this.options.data = data;
461
+
462
+ if (this.isOpen) {
463
+ this._renderDropdown(data, val);
464
+ }
465
+ }
466
+ }
467
+
468
+ /**
469
+ * @static
470
+ * @memberof Autocomplete
471
+ */
472
+ Autocomplete._keydown = false;
473
+
474
+ M.Autocomplete = Autocomplete;
475
+
476
+ if (M.jQueryLoaded) {
477
+ M.initializeJqueryWrapper(Autocomplete, 'autocomplete', 'M_Autocomplete');
478
+ }
479
+ })(cash);