activeadmin_materialize_theme 0.1.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 (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,617 @@
1
+ (function($, anim) {
2
+ 'use strict';
3
+
4
+ let _defaults = {
5
+ alignment: 'left',
6
+ autoFocus: true,
7
+ constrainWidth: true,
8
+ container: null,
9
+ coverTrigger: true,
10
+ closeOnClick: true,
11
+ hover: false,
12
+ inDuration: 150,
13
+ outDuration: 250,
14
+ onOpenStart: null,
15
+ onOpenEnd: null,
16
+ onCloseStart: null,
17
+ onCloseEnd: null,
18
+ onItemClick: null
19
+ };
20
+
21
+ /**
22
+ * @class
23
+ */
24
+ class Dropdown extends Component {
25
+ constructor(el, options) {
26
+ super(Dropdown, el, options);
27
+
28
+ this.el.M_Dropdown = this;
29
+ Dropdown._dropdowns.push(this);
30
+
31
+ this.id = M.getIdFromTrigger(el);
32
+ this.dropdownEl = document.getElementById(this.id);
33
+ this.$dropdownEl = $(this.dropdownEl);
34
+
35
+ /**
36
+ * Options for the dropdown
37
+ * @member Dropdown#options
38
+ * @prop {String} [alignment='left'] - Edge which the dropdown is aligned to
39
+ * @prop {Boolean} [autoFocus=true] - Automatically focus dropdown el for keyboard
40
+ * @prop {Boolean} [constrainWidth=true] - Constrain width to width of the button
41
+ * @prop {Element} container - Container element to attach dropdown to (optional)
42
+ * @prop {Boolean} [coverTrigger=true] - Place dropdown over trigger
43
+ * @prop {Boolean} [closeOnClick=true] - Close on click of dropdown item
44
+ * @prop {Boolean} [hover=false] - Open dropdown on hover
45
+ * @prop {Number} [inDuration=150] - Duration of open animation in ms
46
+ * @prop {Number} [outDuration=250] - Duration of close animation in ms
47
+ * @prop {Function} onOpenStart - Function called when dropdown starts opening
48
+ * @prop {Function} onOpenEnd - Function called when dropdown finishes opening
49
+ * @prop {Function} onCloseStart - Function called when dropdown starts closing
50
+ * @prop {Function} onCloseEnd - Function called when dropdown finishes closing
51
+ */
52
+ this.options = $.extend({}, Dropdown.defaults, options);
53
+
54
+ /**
55
+ * Describes open/close state of dropdown
56
+ * @type {Boolean}
57
+ */
58
+ this.isOpen = false;
59
+
60
+ /**
61
+ * Describes if dropdown content is scrollable
62
+ * @type {Boolean}
63
+ */
64
+ this.isScrollable = false;
65
+
66
+ /**
67
+ * Describes if touch moving on dropdown content
68
+ * @type {Boolean}
69
+ */
70
+ this.isTouchMoving = false;
71
+
72
+ this.focusedIndex = -1;
73
+ this.filterQuery = [];
74
+
75
+ // Move dropdown-content after dropdown-trigger
76
+ if (!!this.options.container) {
77
+ $(this.options.container).append(this.dropdownEl);
78
+ } else {
79
+ this.$el.after(this.dropdownEl);
80
+ }
81
+
82
+ this._makeDropdownFocusable();
83
+ this._resetFilterQueryBound = this._resetFilterQuery.bind(this);
84
+ this._handleDocumentClickBound = this._handleDocumentClick.bind(this);
85
+ this._handleDocumentTouchmoveBound = this._handleDocumentTouchmove.bind(this);
86
+ this._handleDropdownClickBound = this._handleDropdownClick.bind(this);
87
+ this._handleDropdownKeydownBound = this._handleDropdownKeydown.bind(this);
88
+ this._handleTriggerKeydownBound = this._handleTriggerKeydown.bind(this);
89
+ this._setupEventHandlers();
90
+ }
91
+
92
+ static get defaults() {
93
+ return _defaults;
94
+ }
95
+
96
+ static init(els, options) {
97
+ return super.init(this, els, options);
98
+ }
99
+
100
+ /**
101
+ * Get Instance
102
+ */
103
+ static getInstance(el) {
104
+ let domElem = !!el.jquery ? el[0] : el;
105
+ return domElem.M_Dropdown;
106
+ }
107
+
108
+ /**
109
+ * Teardown component
110
+ */
111
+ destroy() {
112
+ this._resetDropdownStyles();
113
+ this._removeEventHandlers();
114
+ Dropdown._dropdowns.splice(Dropdown._dropdowns.indexOf(this), 1);
115
+ this.el.M_Dropdown = undefined;
116
+ }
117
+
118
+ /**
119
+ * Setup Event Handlers
120
+ */
121
+ _setupEventHandlers() {
122
+ // Trigger keydown handler
123
+ this.el.addEventListener('keydown', this._handleTriggerKeydownBound);
124
+
125
+ // Item click handler
126
+ this.dropdownEl.addEventListener('click', this._handleDropdownClickBound);
127
+
128
+ // Hover event handlers
129
+ if (this.options.hover) {
130
+ this._handleMouseEnterBound = this._handleMouseEnter.bind(this);
131
+ this.el.addEventListener('mouseenter', this._handleMouseEnterBound);
132
+ this._handleMouseLeaveBound = this._handleMouseLeave.bind(this);
133
+ this.el.addEventListener('mouseleave', this._handleMouseLeaveBound);
134
+ this.dropdownEl.addEventListener('mouseleave', this._handleMouseLeaveBound);
135
+
136
+ // Click event handlers
137
+ } else {
138
+ this._handleClickBound = this._handleClick.bind(this);
139
+ this.el.addEventListener('click', this._handleClickBound);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Remove Event Handlers
145
+ */
146
+ _removeEventHandlers() {
147
+ this.el.removeEventListener('keydown', this._handleTriggerKeydownBound);
148
+ this.dropdownEl.removeEventListener('click', this._handleDropdownClickBound);
149
+
150
+ if (this.options.hover) {
151
+ this.el.removeEventListener('mouseenter', this._handleMouseEnterBound);
152
+ this.el.removeEventListener('mouseleave', this._handleMouseLeaveBound);
153
+ this.dropdownEl.removeEventListener('mouseleave', this._handleMouseLeaveBound);
154
+ } else {
155
+ this.el.removeEventListener('click', this._handleClickBound);
156
+ }
157
+ }
158
+
159
+ _setupTemporaryEventHandlers() {
160
+ // Use capture phase event handler to prevent click
161
+ document.body.addEventListener('click', this._handleDocumentClickBound, true);
162
+ document.body.addEventListener('touchend', this._handleDocumentClickBound);
163
+ document.body.addEventListener('touchmove', this._handleDocumentTouchmoveBound);
164
+ this.dropdownEl.addEventListener('keydown', this._handleDropdownKeydownBound);
165
+ }
166
+
167
+ _removeTemporaryEventHandlers() {
168
+ // Use capture phase event handler to prevent click
169
+ document.body.removeEventListener('click', this._handleDocumentClickBound, true);
170
+ document.body.removeEventListener('touchend', this._handleDocumentClickBound);
171
+ document.body.removeEventListener('touchmove', this._handleDocumentTouchmoveBound);
172
+ this.dropdownEl.removeEventListener('keydown', this._handleDropdownKeydownBound);
173
+ }
174
+
175
+ _handleClick(e) {
176
+ e.preventDefault();
177
+ this.open();
178
+ }
179
+
180
+ _handleMouseEnter() {
181
+ this.open();
182
+ }
183
+
184
+ _handleMouseLeave(e) {
185
+ let toEl = e.toElement || e.relatedTarget;
186
+ let leaveToDropdownContent = !!$(toEl).closest('.dropdown-content').length;
187
+ let leaveToActiveDropdownTrigger = false;
188
+
189
+ let $closestTrigger = $(toEl).closest('.dropdown-trigger');
190
+ if (
191
+ $closestTrigger.length &&
192
+ !!$closestTrigger[0].M_Dropdown &&
193
+ $closestTrigger[0].M_Dropdown.isOpen
194
+ ) {
195
+ leaveToActiveDropdownTrigger = true;
196
+ }
197
+
198
+ // Close hover dropdown if mouse did not leave to either active dropdown-trigger or dropdown-content
199
+ if (!leaveToActiveDropdownTrigger && !leaveToDropdownContent) {
200
+ this.close();
201
+ }
202
+ }
203
+
204
+ _handleDocumentClick(e) {
205
+ let $target = $(e.target);
206
+ if (
207
+ this.options.closeOnClick &&
208
+ $target.closest('.dropdown-content').length &&
209
+ !this.isTouchMoving
210
+ ) {
211
+ // isTouchMoving to check if scrolling on mobile.
212
+ setTimeout(() => {
213
+ this.close();
214
+ }, 0);
215
+ } else if (
216
+ $target.closest('.dropdown-trigger').length ||
217
+ !$target.closest('.dropdown-content').length
218
+ ) {
219
+ setTimeout(() => {
220
+ this.close();
221
+ }, 0);
222
+ }
223
+ this.isTouchMoving = false;
224
+ }
225
+
226
+ _handleTriggerKeydown(e) {
227
+ // ARROW DOWN OR ENTER WHEN SELECT IS CLOSED - open Dropdown
228
+ if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ENTER) && !this.isOpen) {
229
+ e.preventDefault();
230
+ this.open();
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Handle Document Touchmove
236
+ * @param {Event} e
237
+ */
238
+ _handleDocumentTouchmove(e) {
239
+ let $target = $(e.target);
240
+ if ($target.closest('.dropdown-content').length) {
241
+ this.isTouchMoving = true;
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Handle Dropdown Click
247
+ * @param {Event} e
248
+ */
249
+ _handleDropdownClick(e) {
250
+ // onItemClick callback
251
+ if (typeof this.options.onItemClick === 'function') {
252
+ let itemEl = $(e.target).closest('li')[0];
253
+ this.options.onItemClick.call(this, itemEl);
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Handle Dropdown Keydown
259
+ * @param {Event} e
260
+ */
261
+ _handleDropdownKeydown(e) {
262
+ if (e.which === M.keys.TAB) {
263
+ e.preventDefault();
264
+ this.close();
265
+
266
+ // Navigate down dropdown list
267
+ } else if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) && this.isOpen) {
268
+ e.preventDefault();
269
+ let direction = e.which === M.keys.ARROW_DOWN ? 1 : -1;
270
+ let newFocusedIndex = this.focusedIndex;
271
+ let foundNewIndex = false;
272
+ do {
273
+ newFocusedIndex = newFocusedIndex + direction;
274
+
275
+ if (
276
+ !!this.dropdownEl.children[newFocusedIndex] &&
277
+ this.dropdownEl.children[newFocusedIndex].tabIndex !== -1
278
+ ) {
279
+ foundNewIndex = true;
280
+ break;
281
+ }
282
+ } while (newFocusedIndex < this.dropdownEl.children.length && newFocusedIndex >= 0);
283
+
284
+ if (foundNewIndex) {
285
+ this.focusedIndex = newFocusedIndex;
286
+ this._focusFocusedItem();
287
+ }
288
+
289
+ // ENTER selects choice on focused item
290
+ } else if (e.which === M.keys.ENTER && this.isOpen) {
291
+ // Search for <a> and <button>
292
+ let focusedElement = this.dropdownEl.children[this.focusedIndex];
293
+ let $activatableElement = $(focusedElement)
294
+ .find('a, button')
295
+ .first();
296
+
297
+ // Click a or button tag if exists, otherwise click li tag
298
+ if (!!$activatableElement.length) {
299
+ $activatableElement[0].click();
300
+ } else if (!!focusedElement) {
301
+ focusedElement.click();
302
+ }
303
+
304
+ // Close dropdown on ESC
305
+ } else if (e.which === M.keys.ESC && this.isOpen) {
306
+ e.preventDefault();
307
+ this.close();
308
+ }
309
+
310
+ // CASE WHEN USER TYPE LETTERS
311
+ let letter = String.fromCharCode(e.which).toLowerCase(),
312
+ nonLetters = [9, 13, 27, 38, 40];
313
+ if (letter && nonLetters.indexOf(e.which) === -1) {
314
+ this.filterQuery.push(letter);
315
+
316
+ let string = this.filterQuery.join(''),
317
+ newOptionEl = $(this.dropdownEl)
318
+ .find('li')
319
+ .filter((el) => {
320
+ return (
321
+ $(el)
322
+ .text()
323
+ .toLowerCase()
324
+ .indexOf(string) === 0
325
+ );
326
+ })[0];
327
+
328
+ if (newOptionEl) {
329
+ this.focusedIndex = $(newOptionEl).index();
330
+ this._focusFocusedItem();
331
+ }
332
+ }
333
+
334
+ this.filterTimeout = setTimeout(this._resetFilterQueryBound, 1000);
335
+ }
336
+
337
+ /**
338
+ * Setup dropdown
339
+ */
340
+ _resetFilterQuery() {
341
+ this.filterQuery = [];
342
+ }
343
+
344
+ _resetDropdownStyles() {
345
+ this.$dropdownEl.css({
346
+ display: '',
347
+ width: '',
348
+ height: '',
349
+ left: '',
350
+ top: '',
351
+ 'transform-origin': '',
352
+ transform: '',
353
+ opacity: ''
354
+ });
355
+ }
356
+
357
+ _makeDropdownFocusable() {
358
+ // Needed for arrow key navigation
359
+ this.dropdownEl.tabIndex = 0;
360
+
361
+ // Only set tabindex if it hasn't been set by user
362
+ $(this.dropdownEl)
363
+ .children()
364
+ .each(function(el) {
365
+ if (!el.getAttribute('tabindex')) {
366
+ el.setAttribute('tabindex', 0);
367
+ }
368
+ });
369
+ }
370
+
371
+ _focusFocusedItem() {
372
+ if (
373
+ this.focusedIndex >= 0 &&
374
+ this.focusedIndex < this.dropdownEl.children.length &&
375
+ this.options.autoFocus
376
+ ) {
377
+ this.dropdownEl.children[this.focusedIndex].focus();
378
+ }
379
+ }
380
+
381
+ _getDropdownPosition() {
382
+ let offsetParentBRect = this.el.offsetParent.getBoundingClientRect();
383
+ let triggerBRect = this.el.getBoundingClientRect();
384
+ let dropdownBRect = this.dropdownEl.getBoundingClientRect();
385
+
386
+ let idealHeight = dropdownBRect.height;
387
+ let idealWidth = dropdownBRect.width;
388
+ let idealXPos = triggerBRect.left - dropdownBRect.left;
389
+ let idealYPos = triggerBRect.top - dropdownBRect.top;
390
+
391
+ let dropdownBounds = {
392
+ left: idealXPos,
393
+ top: idealYPos,
394
+ height: idealHeight,
395
+ width: idealWidth
396
+ };
397
+
398
+ // Countainer here will be closest ancestor with overflow: hidden
399
+ let closestOverflowParent = !!this.dropdownEl.offsetParent
400
+ ? this.dropdownEl.offsetParent
401
+ : this.dropdownEl.parentNode;
402
+
403
+ let alignments = M.checkPossibleAlignments(
404
+ this.el,
405
+ closestOverflowParent,
406
+ dropdownBounds,
407
+ this.options.coverTrigger ? 0 : triggerBRect.height
408
+ );
409
+
410
+ let verticalAlignment = 'top';
411
+ let horizontalAlignment = this.options.alignment;
412
+ idealYPos += this.options.coverTrigger ? 0 : triggerBRect.height;
413
+
414
+ // Reset isScrollable
415
+ this.isScrollable = false;
416
+
417
+ if (!alignments.top) {
418
+ if (alignments.bottom) {
419
+ verticalAlignment = 'bottom';
420
+ } else {
421
+ this.isScrollable = true;
422
+
423
+ // Determine which side has most space and cutoff at correct height
424
+ if (alignments.spaceOnTop > alignments.spaceOnBottom) {
425
+ verticalAlignment = 'bottom';
426
+ idealHeight += alignments.spaceOnTop;
427
+ idealYPos -= alignments.spaceOnTop;
428
+ } else {
429
+ idealHeight += alignments.spaceOnBottom;
430
+ }
431
+ }
432
+ }
433
+
434
+ // If preferred horizontal alignment is possible
435
+ if (!alignments[horizontalAlignment]) {
436
+ let oppositeAlignment = horizontalAlignment === 'left' ? 'right' : 'left';
437
+ if (alignments[oppositeAlignment]) {
438
+ horizontalAlignment = oppositeAlignment;
439
+ } else {
440
+ // Determine which side has most space and cutoff at correct height
441
+ if (alignments.spaceOnLeft > alignments.spaceOnRight) {
442
+ horizontalAlignment = 'right';
443
+ idealWidth += alignments.spaceOnLeft;
444
+ idealXPos -= alignments.spaceOnLeft;
445
+ } else {
446
+ horizontalAlignment = 'left';
447
+ idealWidth += alignments.spaceOnRight;
448
+ }
449
+ }
450
+ }
451
+
452
+ if (verticalAlignment === 'bottom') {
453
+ idealYPos =
454
+ idealYPos - dropdownBRect.height + (this.options.coverTrigger ? triggerBRect.height : 0);
455
+ }
456
+ if (horizontalAlignment === 'right') {
457
+ idealXPos = idealXPos - dropdownBRect.width + triggerBRect.width;
458
+ }
459
+ return {
460
+ x: idealXPos,
461
+ y: idealYPos,
462
+ verticalAlignment: verticalAlignment,
463
+ horizontalAlignment: horizontalAlignment,
464
+ height: idealHeight,
465
+ width: idealWidth
466
+ };
467
+ }
468
+
469
+ /**
470
+ * Animate in dropdown
471
+ */
472
+ _animateIn() {
473
+ anim.remove(this.dropdownEl);
474
+ anim({
475
+ targets: this.dropdownEl,
476
+ opacity: {
477
+ value: [0, 1],
478
+ easing: 'easeOutQuad'
479
+ },
480
+ scaleX: [0.3, 1],
481
+ scaleY: [0.3, 1],
482
+ duration: this.options.inDuration,
483
+ easing: 'easeOutQuint',
484
+ complete: (anim) => {
485
+ if (this.options.autoFocus) {
486
+ this.dropdownEl.focus();
487
+ }
488
+
489
+ // onOpenEnd callback
490
+ if (typeof this.options.onOpenEnd === 'function') {
491
+ this.options.onOpenEnd.call(this, this.el);
492
+ }
493
+ }
494
+ });
495
+ }
496
+
497
+ /**
498
+ * Animate out dropdown
499
+ */
500
+ _animateOut() {
501
+ anim.remove(this.dropdownEl);
502
+ anim({
503
+ targets: this.dropdownEl,
504
+ opacity: {
505
+ value: 0,
506
+ easing: 'easeOutQuint'
507
+ },
508
+ scaleX: 0.3,
509
+ scaleY: 0.3,
510
+ duration: this.options.outDuration,
511
+ easing: 'easeOutQuint',
512
+ complete: (anim) => {
513
+ this._resetDropdownStyles();
514
+
515
+ // onCloseEnd callback
516
+ if (typeof this.options.onCloseEnd === 'function') {
517
+ this.options.onCloseEnd.call(this, this.el);
518
+ }
519
+ }
520
+ });
521
+ }
522
+
523
+ /**
524
+ * Place dropdown
525
+ */
526
+ _placeDropdown() {
527
+ // Set width before calculating positionInfo
528
+ let idealWidth = this.options.constrainWidth
529
+ ? this.el.getBoundingClientRect().width
530
+ : this.dropdownEl.getBoundingClientRect().width;
531
+ this.dropdownEl.style.width = idealWidth + 'px';
532
+
533
+ let positionInfo = this._getDropdownPosition();
534
+ this.dropdownEl.style.left = positionInfo.x + 'px';
535
+ this.dropdownEl.style.top = positionInfo.y + 'px';
536
+ this.dropdownEl.style.height = positionInfo.height + 'px';
537
+ this.dropdownEl.style.width = positionInfo.width + 'px';
538
+ this.dropdownEl.style.transformOrigin = `${
539
+ positionInfo.horizontalAlignment === 'left' ? '0' : '100%'
540
+ } ${positionInfo.verticalAlignment === 'top' ? '0' : '100%'}`;
541
+ }
542
+
543
+ /**
544
+ * Open Dropdown
545
+ */
546
+ open() {
547
+ if (this.isOpen) {
548
+ return;
549
+ }
550
+ this.isOpen = true;
551
+
552
+ // onOpenStart callback
553
+ if (typeof this.options.onOpenStart === 'function') {
554
+ this.options.onOpenStart.call(this, this.el);
555
+ }
556
+
557
+ // Reset styles
558
+ this._resetDropdownStyles();
559
+ this.dropdownEl.style.display = 'block';
560
+
561
+ this._placeDropdown();
562
+ this._animateIn();
563
+ this._setupTemporaryEventHandlers();
564
+ }
565
+
566
+ /**
567
+ * Close Dropdown
568
+ */
569
+ close() {
570
+ if (!this.isOpen) {
571
+ return;
572
+ }
573
+ this.isOpen = false;
574
+ this.focusedIndex = -1;
575
+
576
+ // onCloseStart callback
577
+ if (typeof this.options.onCloseStart === 'function') {
578
+ this.options.onCloseStart.call(this, this.el);
579
+ }
580
+
581
+ this._animateOut();
582
+ this._removeTemporaryEventHandlers();
583
+
584
+ if (this.options.autoFocus) {
585
+ this.el.focus();
586
+ }
587
+ }
588
+
589
+ /**
590
+ * Recalculate dimensions
591
+ */
592
+ recalculateDimensions() {
593
+ if (this.isOpen) {
594
+ this.$dropdownEl.css({
595
+ width: '',
596
+ height: '',
597
+ left: '',
598
+ top: '',
599
+ 'transform-origin': ''
600
+ });
601
+ this._placeDropdown();
602
+ }
603
+ }
604
+ }
605
+
606
+ /**
607
+ * @static
608
+ * @memberof Dropdown
609
+ */
610
+ Dropdown._dropdowns = [];
611
+
612
+ M.Dropdown = Dropdown;
613
+
614
+ if (M.jQueryLoaded) {
615
+ M.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown');
616
+ }
617
+ })(cash, M.anime);