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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +26 -0
- data/Rakefile +34 -0
- data/app/assets/config/activeadmin_materialize_theme_manifest.js +1 -0
- data/app/assets/javascripts/activeadmin_materialize_theme.js +65 -0
- data/app/assets/javascripts/materialize/anime.min.js +34 -0
- data/app/assets/javascripts/materialize/autocomplete.js +450 -0
- data/app/assets/javascripts/materialize/bin/materialize.js +12374 -0
- data/app/assets/javascripts/materialize/bin/materialize.min.js +6 -0
- data/app/assets/javascripts/materialize/buttons.js +354 -0
- data/app/assets/javascripts/materialize/cards.js +40 -0
- data/app/assets/javascripts/materialize/carousel.js +717 -0
- data/app/assets/javascripts/materialize/cash.js +960 -0
- data/app/assets/javascripts/materialize/characterCounter.js +136 -0
- data/app/assets/javascripts/materialize/chips.js +481 -0
- data/app/assets/javascripts/materialize/collapsible.js +275 -0
- data/app/assets/javascripts/materialize/component.js +44 -0
- data/app/assets/javascripts/materialize/datepicker.js +975 -0
- data/app/assets/javascripts/materialize/dropdown.js +617 -0
- data/app/assets/javascripts/materialize/forms.js +275 -0
- data/app/assets/javascripts/materialize/global.js +427 -0
- data/app/assets/javascripts/materialize/materialbox.js +453 -0
- data/app/assets/javascripts/materialize/modal.js +382 -0
- data/app/assets/javascripts/materialize/parallax.js +138 -0
- data/app/assets/javascripts/materialize/pushpin.js +145 -0
- data/app/assets/javascripts/materialize/range.js +263 -0
- data/app/assets/javascripts/materialize/scrollspy.js +295 -0
- data/app/assets/javascripts/materialize/select.js +432 -0
- data/app/assets/javascripts/materialize/sidenav.js +580 -0
- data/app/assets/javascripts/materialize/slider.js +359 -0
- data/app/assets/javascripts/materialize/tabs.js +402 -0
- data/app/assets/javascripts/materialize/tapTarget.js +314 -0
- data/app/assets/javascripts/materialize/timepicker.js +647 -0
- data/app/assets/javascripts/materialize/toasts.js +310 -0
- data/app/assets/javascripts/materialize/tooltip.js +303 -0
- data/app/assets/javascripts/materialize/waves.js +335 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/base.scss +107 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/footer.scss +18 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/form.scss +140 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/header.scss +61 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/layout_index.scss +83 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/layout_show.scss +56 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/sidebar.scss +37 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/components/title_bar.scss +43 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/LICENSE +21 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/README.md +91 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_badges.scss +55 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_buttons.scss +322 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_cards.scss +195 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_carousel.scss +90 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_chips.scss +90 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_collapsible.scss +91 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_color-classes.scss +32 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_color-variables.scss +370 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_datepicker.scss +191 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_dropdown.scss +85 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_global.scss +769 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_grid.scss +156 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_icons-material-design.scss +5 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_materialbox.scss +43 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_modal.scss +94 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_navbar.scss +208 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_normalize.scss +447 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_preloader.scss +334 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_pulse.scss +34 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_sidenav.scss +216 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_slider.scss +92 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_table_of_contents.scss +33 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tabs.scss +99 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tapTarget.scss +103 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_timepicker.scss +183 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_toast.scss +58 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_tooltip.scss +32 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_transitions.scss +13 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_typography.scss +60 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_variables.scss +349 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/_waves.scss +114 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_checkboxes.scss +200 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_file-input.scss +44 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_forms.scss +22 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_input-fields.scss +354 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_radio-buttons.scss +115 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_range.scss +161 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_select.scss +180 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/components/forms/_switches.scss +89 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/materialize/materialize.scss +41 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/normalize.css +349 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/theme.scss +13 -0
- data/app/assets/stylesheets/activeadmin_materialize_theme/variables.scss +14 -0
- data/lib/activeadmin_materialize_theme.rb +6 -0
- data/lib/activeadmin_materialize_theme/engine.rb +7 -0
- data/lib/activeadmin_materialize_theme/version.rb +5 -0
- 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);
|