activeadmin_materialize_theme 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +26 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/config/activeadmin_materialize_theme_manifest.js +1 -0
  6. data/app/assets/javascripts/activeadmin_materialize_theme.js +65 -0
  7. data/app/assets/javascripts/materialize/anime.min.js +34 -0
  8. data/app/assets/javascripts/materialize/autocomplete.js +450 -0
  9. data/app/assets/javascripts/materialize/bin/materialize.js +12374 -0
  10. data/app/assets/javascripts/materialize/bin/materialize.min.js +6 -0
  11. data/app/assets/javascripts/materialize/buttons.js +354 -0
  12. data/app/assets/javascripts/materialize/cards.js +40 -0
  13. data/app/assets/javascripts/materialize/carousel.js +717 -0
  14. data/app/assets/javascripts/materialize/cash.js +960 -0
  15. data/app/assets/javascripts/materialize/characterCounter.js +136 -0
  16. data/app/assets/javascripts/materialize/chips.js +481 -0
  17. data/app/assets/javascripts/materialize/collapsible.js +275 -0
  18. data/app/assets/javascripts/materialize/component.js +44 -0
  19. data/app/assets/javascripts/materialize/datepicker.js +975 -0
  20. data/app/assets/javascripts/materialize/dropdown.js +617 -0
  21. data/app/assets/javascripts/materialize/forms.js +275 -0
  22. data/app/assets/javascripts/materialize/global.js +427 -0
  23. data/app/assets/javascripts/materialize/materialbox.js +453 -0
  24. data/app/assets/javascripts/materialize/modal.js +382 -0
  25. data/app/assets/javascripts/materialize/parallax.js +138 -0
  26. data/app/assets/javascripts/materialize/pushpin.js +145 -0
  27. data/app/assets/javascripts/materialize/range.js +263 -0
  28. data/app/assets/javascripts/materialize/scrollspy.js +295 -0
  29. data/app/assets/javascripts/materialize/select.js +432 -0
  30. data/app/assets/javascripts/materialize/sidenav.js +580 -0
  31. data/app/assets/javascripts/materialize/slider.js +359 -0
  32. data/app/assets/javascripts/materialize/tabs.js +402 -0
  33. data/app/assets/javascripts/materialize/tapTarget.js +314 -0
  34. data/app/assets/javascripts/materialize/timepicker.js +647 -0
  35. data/app/assets/javascripts/materialize/toasts.js +310 -0
  36. data/app/assets/javascripts/materialize/tooltip.js +303 -0
  37. data/app/assets/javascripts/materialize/waves.js +335 -0
  38. data/app/assets/stylesheets/activeadmin_materialize_theme/base.scss +107 -0
  39. data/app/assets/stylesheets/activeadmin_materialize_theme/components/footer.scss +18 -0
  40. data/app/assets/stylesheets/activeadmin_materialize_theme/components/form.scss +140 -0
  41. data/app/assets/stylesheets/activeadmin_materialize_theme/components/header.scss +61 -0
  42. data/app/assets/stylesheets/activeadmin_materialize_theme/components/layout_index.scss +83 -0
  43. data/app/assets/stylesheets/activeadmin_materialize_theme/components/layout_show.scss +56 -0
  44. data/app/assets/stylesheets/activeadmin_materialize_theme/components/sidebar.scss +37 -0
  45. data/app/assets/stylesheets/activeadmin_materialize_theme/components/title_bar.scss +43 -0
  46. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/LICENSE +21 -0
  47. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/README.md +91 -0
  48. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_badges.scss +55 -0
  49. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_buttons.scss +322 -0
  50. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_cards.scss +195 -0
  51. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_carousel.scss +90 -0
  52. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_chips.scss +90 -0
  53. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_collapsible.scss +91 -0
  54. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_color-classes.scss +32 -0
  55. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_color-variables.scss +370 -0
  56. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_datepicker.scss +191 -0
  57. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_dropdown.scss +85 -0
  58. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_global.scss +769 -0
  59. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_grid.scss +156 -0
  60. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_icons-material-design.scss +5 -0
  61. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_materialbox.scss +43 -0
  62. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_modal.scss +94 -0
  63. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_navbar.scss +208 -0
  64. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_normalize.scss +447 -0
  65. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_preloader.scss +334 -0
  66. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_pulse.scss +34 -0
  67. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_sidenav.scss +216 -0
  68. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_slider.scss +92 -0
  69. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_table_of_contents.scss +33 -0
  70. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tabs.scss +99 -0
  71. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tapTarget.scss +103 -0
  72. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_timepicker.scss +183 -0
  73. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_toast.scss +58 -0
  74. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tooltip.scss +32 -0
  75. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_transitions.scss +13 -0
  76. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_typography.scss +60 -0
  77. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_variables.scss +349 -0
  78. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_waves.scss +114 -0
  79. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_checkboxes.scss +200 -0
  80. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_file-input.scss +44 -0
  81. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_forms.scss +22 -0
  82. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_input-fields.scss +354 -0
  83. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_radio-buttons.scss +115 -0
  84. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_range.scss +161 -0
  85. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_select.scss +180 -0
  86. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_switches.scss +89 -0
  87. data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/materialize.scss +41 -0
  88. data/app/assets/stylesheets/activeadmin_materialize_theme/normalize.css +349 -0
  89. data/app/assets/stylesheets/activeadmin_materialize_theme/theme.scss +13 -0
  90. data/app/assets/stylesheets/activeadmin_materialize_theme/variables.scss +14 -0
  91. data/lib/activeadmin_materialize_theme.rb +6 -0
  92. data/lib/activeadmin_materialize_theme/engine.rb +7 -0
  93. data/lib/activeadmin_materialize_theme/version.rb +5 -0
  94. metadata +149 -0
@@ -0,0 +1,136 @@
1
+ (function($) {
2
+ 'use strict';
3
+
4
+ let _defaults = {};
5
+
6
+ /**
7
+ * @class
8
+ *
9
+ */
10
+ class CharacterCounter extends Component {
11
+ /**
12
+ * Construct CharacterCounter instance
13
+ * @constructor
14
+ * @param {Element} el
15
+ * @param {Object} options
16
+ */
17
+ constructor(el, options) {
18
+ super(CharacterCounter, el, options);
19
+
20
+ this.el.M_CharacterCounter = this;
21
+
22
+ /**
23
+ * Options for the character counter
24
+ */
25
+ this.options = $.extend({}, CharacterCounter.defaults, options);
26
+
27
+ this.isInvalid = false;
28
+ this.isValidLength = false;
29
+ this._setupCounter();
30
+ this._setupEventHandlers();
31
+ }
32
+
33
+ static get defaults() {
34
+ return _defaults;
35
+ }
36
+
37
+ static init(els, options) {
38
+ return super.init(this, els, options);
39
+ }
40
+
41
+ /**
42
+ * Get Instance
43
+ */
44
+ static getInstance(el) {
45
+ let domElem = !!el.jquery ? el[0] : el;
46
+ return domElem.M_CharacterCounter;
47
+ }
48
+
49
+ /**
50
+ * Teardown component
51
+ */
52
+ destroy() {
53
+ this._removeEventHandlers();
54
+ this.el.CharacterCounter = undefined;
55
+ this._removeCounter();
56
+ }
57
+
58
+ /**
59
+ * Setup Event Handlers
60
+ */
61
+ _setupEventHandlers() {
62
+ this._handleUpdateCounterBound = this.updateCounter.bind(this);
63
+
64
+ this.el.addEventListener('focus', this._handleUpdateCounterBound, true);
65
+ this.el.addEventListener('input', this._handleUpdateCounterBound, true);
66
+ }
67
+
68
+ /**
69
+ * Remove Event Handlers
70
+ */
71
+ _removeEventHandlers() {
72
+ this.el.removeEventListener('focus', this._handleUpdateCounterBound, true);
73
+ this.el.removeEventListener('input', this._handleUpdateCounterBound, true);
74
+ }
75
+
76
+ /**
77
+ * Setup counter element
78
+ */
79
+ _setupCounter() {
80
+ this.counterEl = document.createElement('span');
81
+ $(this.counterEl)
82
+ .addClass('character-counter')
83
+ .css({
84
+ float: 'right',
85
+ 'font-size': '12px',
86
+ height: 1
87
+ });
88
+
89
+ this.$el.parent().append(this.counterEl);
90
+ }
91
+
92
+ /**
93
+ * Remove counter element
94
+ */
95
+ _removeCounter() {
96
+ $(this.counterEl).remove();
97
+ }
98
+
99
+ /**
100
+ * Update counter
101
+ */
102
+ updateCounter() {
103
+ let maxLength = +this.$el.attr('data-length'),
104
+ actualLength = this.el.value.length;
105
+ this.isValidLength = actualLength <= maxLength;
106
+ let counterString = actualLength;
107
+
108
+ if (maxLength) {
109
+ counterString += '/' + maxLength;
110
+ this._validateInput();
111
+ }
112
+
113
+ $(this.counterEl).html(counterString);
114
+ }
115
+
116
+ /**
117
+ * Add validation classes
118
+ */
119
+ _validateInput() {
120
+ if (this.isValidLength && this.isInvalid) {
121
+ this.isInvalid = false;
122
+ this.$el.removeClass('invalid');
123
+ } else if (!this.isValidLength && !this.isInvalid) {
124
+ this.isInvalid = true;
125
+ this.$el.removeClass('valid');
126
+ this.$el.addClass('invalid');
127
+ }
128
+ }
129
+ }
130
+
131
+ M.CharacterCounter = CharacterCounter;
132
+
133
+ if (M.jQueryLoaded) {
134
+ M.initializeJqueryWrapper(CharacterCounter, 'characterCounter', 'M_CharacterCounter');
135
+ }
136
+ })(cash);
@@ -0,0 +1,481 @@
1
+ (function($) {
2
+ 'use strict';
3
+
4
+ let _defaults = {
5
+ data: [],
6
+ placeholder: '',
7
+ secondaryPlaceholder: '',
8
+ autocompleteOptions: {},
9
+ limit: Infinity,
10
+ onChipAdd: null,
11
+ onChipSelect: null,
12
+ onChipDelete: null
13
+ };
14
+
15
+ /**
16
+ * @typedef {Object} chip
17
+ * @property {String} tag chip tag string
18
+ * @property {String} [image] chip avatar image string
19
+ */
20
+
21
+ /**
22
+ * @class
23
+ *
24
+ */
25
+ class Chips extends Component {
26
+ /**
27
+ * Construct Chips instance and set up overlay
28
+ * @constructor
29
+ * @param {Element} el
30
+ * @param {Object} options
31
+ */
32
+ constructor(el, options) {
33
+ super(Chips, el, options);
34
+
35
+ this.el.M_Chips = this;
36
+
37
+ /**
38
+ * Options for the modal
39
+ * @member Chips#options
40
+ * @prop {Array} data
41
+ * @prop {String} placeholder
42
+ * @prop {String} secondaryPlaceholder
43
+ * @prop {Object} autocompleteOptions
44
+ */
45
+ this.options = $.extend({}, Chips.defaults, options);
46
+
47
+ this.$el.addClass('chips input-field');
48
+ this.chipsData = [];
49
+ this.$chips = $();
50
+ this._setupInput();
51
+ this.hasAutocomplete = Object.keys(this.options.autocompleteOptions).length > 0;
52
+
53
+ // Set input id
54
+ if (!this.$input.attr('id')) {
55
+ this.$input.attr('id', M.guid());
56
+ }
57
+
58
+ // Render initial chips
59
+ if (this.options.data.length) {
60
+ this.chipsData = this.options.data;
61
+ this._renderChips(this.chipsData);
62
+ }
63
+
64
+ // Setup autocomplete if needed
65
+ if (this.hasAutocomplete) {
66
+ this._setupAutocomplete();
67
+ }
68
+
69
+ this._setPlaceholder();
70
+ this._setupLabel();
71
+ this._setupEventHandlers();
72
+ }
73
+
74
+ static get defaults() {
75
+ return _defaults;
76
+ }
77
+
78
+ static init(els, options) {
79
+ return super.init(this, els, options);
80
+ }
81
+
82
+ /**
83
+ * Get Instance
84
+ */
85
+ static getInstance(el) {
86
+ let domElem = !!el.jquery ? el[0] : el;
87
+ return domElem.M_Chips;
88
+ }
89
+
90
+ /**
91
+ * Get Chips Data
92
+ */
93
+ getData() {
94
+ return this.chipsData;
95
+ }
96
+
97
+ /**
98
+ * Teardown component
99
+ */
100
+ destroy() {
101
+ this._removeEventHandlers();
102
+ this.$chips.remove();
103
+ this.el.M_Chips = undefined;
104
+ }
105
+
106
+ /**
107
+ * Setup Event Handlers
108
+ */
109
+ _setupEventHandlers() {
110
+ this._handleChipClickBound = this._handleChipClick.bind(this);
111
+ this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
112
+ this._handleInputFocusBound = this._handleInputFocus.bind(this);
113
+ this._handleInputBlurBound = this._handleInputBlur.bind(this);
114
+
115
+ this.el.addEventListener('click', this._handleChipClickBound);
116
+ document.addEventListener('keydown', Chips._handleChipsKeydown);
117
+ document.addEventListener('keyup', Chips._handleChipsKeyup);
118
+ this.el.addEventListener('blur', Chips._handleChipsBlur, true);
119
+ this.$input[0].addEventListener('focus', this._handleInputFocusBound);
120
+ this.$input[0].addEventListener('blur', this._handleInputBlurBound);
121
+ this.$input[0].addEventListener('keydown', this._handleInputKeydownBound);
122
+ }
123
+
124
+ /**
125
+ * Remove Event Handlers
126
+ */
127
+ _removeEventHandlers() {
128
+ this.el.removeEventListener('click', this._handleChipClickBound);
129
+ document.removeEventListener('keydown', Chips._handleChipsKeydown);
130
+ document.removeEventListener('keyup', Chips._handleChipsKeyup);
131
+ this.el.removeEventListener('blur', Chips._handleChipsBlur, true);
132
+ this.$input[0].removeEventListener('focus', this._handleInputFocusBound);
133
+ this.$input[0].removeEventListener('blur', this._handleInputBlurBound);
134
+ this.$input[0].removeEventListener('keydown', this._handleInputKeydownBound);
135
+ }
136
+
137
+ /**
138
+ * Handle Chip Click
139
+ * @param {Event} e
140
+ */
141
+ _handleChipClick(e) {
142
+ let $chip = $(e.target).closest('.chip');
143
+ let clickedClose = $(e.target).is('.close');
144
+ if ($chip.length) {
145
+ let index = $chip.index();
146
+ if (clickedClose) {
147
+ // delete chip
148
+ this.deleteChip(index);
149
+ this.$input[0].focus();
150
+ } else {
151
+ // select chip
152
+ this.selectChip(index);
153
+ }
154
+
155
+ // Default handle click to focus on input
156
+ } else {
157
+ this.$input[0].focus();
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Handle Chips Keydown
163
+ * @param {Event} e
164
+ */
165
+ static _handleChipsKeydown(e) {
166
+ Chips._keydown = true;
167
+
168
+ let $chips = $(e.target).closest('.chips');
169
+ let chipsKeydown = e.target && $chips.length;
170
+
171
+ // Don't handle keydown inputs on input and textarea
172
+ if ($(e.target).is('input, textarea') || !chipsKeydown) {
173
+ return;
174
+ }
175
+
176
+ let currChips = $chips[0].M_Chips;
177
+
178
+ // backspace and delete
179
+ if (e.keyCode === 8 || e.keyCode === 46) {
180
+ e.preventDefault();
181
+
182
+ let selectIndex = currChips.chipsData.length;
183
+ if (currChips._selectedChip) {
184
+ let index = currChips._selectedChip.index();
185
+ currChips.deleteChip(index);
186
+ currChips._selectedChip = null;
187
+
188
+ // Make sure selectIndex doesn't go negative
189
+ selectIndex = Math.max(index - 1, 0);
190
+ }
191
+
192
+ if (currChips.chipsData.length) {
193
+ currChips.selectChip(selectIndex);
194
+ }
195
+
196
+ // left arrow key
197
+ } else if (e.keyCode === 37) {
198
+ if (currChips._selectedChip) {
199
+ let selectIndex = currChips._selectedChip.index() - 1;
200
+ if (selectIndex < 0) {
201
+ return;
202
+ }
203
+ currChips.selectChip(selectIndex);
204
+ }
205
+
206
+ // right arrow key
207
+ } else if (e.keyCode === 39) {
208
+ if (currChips._selectedChip) {
209
+ let selectIndex = currChips._selectedChip.index() + 1;
210
+
211
+ if (selectIndex >= currChips.chipsData.length) {
212
+ currChips.$input[0].focus();
213
+ } else {
214
+ currChips.selectChip(selectIndex);
215
+ }
216
+ }
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Handle Chips Keyup
222
+ * @param {Event} e
223
+ */
224
+ static _handleChipsKeyup(e) {
225
+ Chips._keydown = false;
226
+ }
227
+
228
+ /**
229
+ * Handle Chips Blur
230
+ * @param {Event} e
231
+ */
232
+ static _handleChipsBlur(e) {
233
+ if (!Chips._keydown) {
234
+ let $chips = $(e.target).closest('.chips');
235
+ let currChips = $chips[0].M_Chips;
236
+
237
+ currChips._selectedChip = null;
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Handle Input Focus
243
+ */
244
+ _handleInputFocus() {
245
+ this.$el.addClass('focus');
246
+ }
247
+
248
+ /**
249
+ * Handle Input Blur
250
+ */
251
+ _handleInputBlur() {
252
+ this.$el.removeClass('focus');
253
+ }
254
+
255
+ /**
256
+ * Handle Input Keydown
257
+ * @param {Event} e
258
+ */
259
+ _handleInputKeydown(e) {
260
+ Chips._keydown = true;
261
+
262
+ // enter
263
+ if (e.keyCode === 13) {
264
+ // Override enter if autocompleting.
265
+ if (this.hasAutocomplete && this.autocomplete && this.autocomplete.isOpen) {
266
+ return;
267
+ }
268
+
269
+ e.preventDefault();
270
+ this.addChip({
271
+ tag: this.$input[0].value
272
+ });
273
+ this.$input[0].value = '';
274
+
275
+ // delete or left
276
+ } else if (
277
+ (e.keyCode === 8 || e.keyCode === 37) &&
278
+ this.$input[0].value === '' &&
279
+ this.chipsData.length
280
+ ) {
281
+ e.preventDefault();
282
+ this.selectChip(this.chipsData.length - 1);
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Render Chip
288
+ * @param {chip} chip
289
+ * @return {Element}
290
+ */
291
+ _renderChip(chip) {
292
+ if (!chip.tag) {
293
+ return;
294
+ }
295
+
296
+ let renderedChip = document.createElement('div');
297
+ let closeIcon = document.createElement('i');
298
+ renderedChip.classList.add('chip');
299
+ renderedChip.textContent = chip.tag;
300
+ renderedChip.setAttribute('tabindex', 0);
301
+ $(closeIcon).addClass('material-icons close');
302
+ closeIcon.textContent = 'close';
303
+
304
+ // attach image if needed
305
+ if (chip.image) {
306
+ let img = document.createElement('img');
307
+ img.setAttribute('src', chip.image);
308
+ renderedChip.insertBefore(img, renderedChip.firstChild);
309
+ }
310
+
311
+ renderedChip.appendChild(closeIcon);
312
+ return renderedChip;
313
+ }
314
+
315
+ /**
316
+ * Render Chips
317
+ */
318
+ _renderChips() {
319
+ this.$chips.remove();
320
+ for (let i = 0; i < this.chipsData.length; i++) {
321
+ let chipEl = this._renderChip(this.chipsData[i]);
322
+ this.$el.append(chipEl);
323
+ this.$chips.add(chipEl);
324
+ }
325
+
326
+ // move input to end
327
+ this.$el.append(this.$input[0]);
328
+ }
329
+
330
+ /**
331
+ * Setup Autocomplete
332
+ */
333
+ _setupAutocomplete() {
334
+ this.options.autocompleteOptions.onAutocomplete = (val) => {
335
+ this.addChip({
336
+ tag: val
337
+ });
338
+ this.$input[0].value = '';
339
+ this.$input[0].focus();
340
+ };
341
+
342
+ this.autocomplete = M.Autocomplete.init(this.$input[0], this.options.autocompleteOptions);
343
+ }
344
+
345
+ /**
346
+ * Setup Input
347
+ */
348
+ _setupInput() {
349
+ this.$input = this.$el.find('input');
350
+ if (!this.$input.length) {
351
+ this.$input = $('<input></input>');
352
+ this.$el.append(this.$input);
353
+ }
354
+
355
+ this.$input.addClass('input');
356
+ }
357
+
358
+ /**
359
+ * Setup Label
360
+ */
361
+ _setupLabel() {
362
+ this.$label = this.$el.find('label');
363
+ if (this.$label.length) {
364
+ this.$label.setAttribute('for', this.$input.attr('id'));
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Set placeholder
370
+ */
371
+ _setPlaceholder() {
372
+ if (this.chipsData !== undefined && !this.chipsData.length && this.options.placeholder) {
373
+ $(this.$input).prop('placeholder', this.options.placeholder);
374
+ } else if (
375
+ (this.chipsData === undefined || !!this.chipsData.length) &&
376
+ this.options.secondaryPlaceholder
377
+ ) {
378
+ $(this.$input).prop('placeholder', this.options.secondaryPlaceholder);
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Check if chip is valid
384
+ * @param {chip} chip
385
+ */
386
+ _isValid(chip) {
387
+ if (chip.hasOwnProperty('tag') && chip.tag !== '') {
388
+ let exists = false;
389
+ for (let i = 0; i < this.chipsData.length; i++) {
390
+ if (this.chipsData[i].tag === chip.tag) {
391
+ exists = true;
392
+ break;
393
+ }
394
+ }
395
+ return !exists;
396
+ }
397
+
398
+ return false;
399
+ }
400
+
401
+ /**
402
+ * Add chip
403
+ * @param {chip} chip
404
+ */
405
+ addChip(chip) {
406
+ if (!this._isValid(chip) || this.chipsData.length >= this.options.limit) {
407
+ return;
408
+ }
409
+
410
+ let renderedChip = this._renderChip(chip);
411
+ this.$chips.add(renderedChip);
412
+ this.chipsData.push(chip);
413
+ $(this.$input).before(renderedChip);
414
+ this._setPlaceholder();
415
+
416
+ // fire chipAdd callback
417
+ if (typeof this.options.onChipAdd === 'function') {
418
+ this.options.onChipAdd.call(this, this.$el, renderedChip);
419
+ }
420
+ }
421
+
422
+ /**
423
+ * Delete chip
424
+ * @param {Number} chip
425
+ */
426
+ deleteChip(chipIndex) {
427
+ let $chip = this.$chips.eq(chipIndex);
428
+ this.$chips.eq(chipIndex).remove();
429
+ this.$chips = this.$chips.filter(function(el) {
430
+ return $(el).index() >= 0;
431
+ });
432
+ this.chipsData.splice(chipIndex, 1);
433
+ this._setPlaceholder();
434
+
435
+ // fire chipDelete callback
436
+ if (typeof this.options.onChipDelete === 'function') {
437
+ this.options.onChipDelete.call(this, this.$el, $chip[0]);
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Select chip
443
+ * @param {Number} chip
444
+ */
445
+ selectChip(chipIndex) {
446
+ let $chip = this.$chips.eq(chipIndex);
447
+ this._selectedChip = $chip;
448
+ $chip[0].focus();
449
+
450
+ // fire chipSelect callback
451
+ if (typeof this.options.onChipSelect === 'function') {
452
+ this.options.onChipSelect.call(this, this.$el, $chip[0]);
453
+ }
454
+ }
455
+ }
456
+
457
+ /**
458
+ * @static
459
+ * @memberof Chips
460
+ */
461
+ Chips._keydown = false;
462
+
463
+ M.Chips = Chips;
464
+
465
+ if (M.jQueryLoaded) {
466
+ M.initializeJqueryWrapper(Chips, 'chips', 'M_Chips');
467
+ }
468
+
469
+ $(document).ready(function() {
470
+ // Handle removal of static chips.
471
+ $(document.body).on('click', '.chip .close', function() {
472
+ let $chips = $(this).closest('.chips');
473
+ if ($chips.length && $chips[0].M_Chips) {
474
+ return;
475
+ }
476
+ $(this)
477
+ .closest('.chip')
478
+ .remove();
479
+ });
480
+ });
481
+ })(cash);