@materializecss/materialize 1.2.2 → 2.0.0-alpha
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.
- package/Gruntfile.js +68 -313
- package/README.md +2 -2
- package/dist/css/materialize.css +1009 -1822
- package/dist/css/materialize.min.css +2 -8
- package/dist/js/materialize.js +8402 -12300
- package/dist/js/materialize.min.js +3 -2
- package/dist/js/materialize.min.js.map +1 -0
- package/package.json +13 -9
- package/sass/components/_badges.scss +12 -2
- package/sass/components/_buttons.scss +16 -11
- package/sass/components/_cards.scss +14 -9
- package/sass/components/_carousel.scss +5 -2
- package/sass/components/_chips.scss +3 -3
- package/sass/components/_collapsible.scss +22 -8
- package/sass/components/_collection.scss +14 -6
- package/sass/components/_datepicker.scss +30 -11
- package/sass/components/_dropdown.scss +6 -4
- package/sass/components/_global.scss +132 -111
- package/sass/components/_grid.scss +119 -98
- package/sass/components/_modal.scss +3 -3
- package/sass/components/_navbar.scss +31 -17
- package/sass/components/_normalize.scss +26 -124
- package/sass/components/_sidenav.scss +21 -20
- package/sass/components/_slider.scss +27 -7
- package/sass/components/_table_of_contents.scss +12 -12
- package/sass/components/_tabs.scss +47 -16
- package/sass/components/_tapTarget.scss +6 -6
- package/sass/components/_timepicker.scss +54 -46
- package/sass/components/_toast.scss +3 -3
- package/sass/components/_tooltip.scss +4 -5
- package/sass/components/_typography.scss +1 -1
- package/sass/components/_variables.scss +185 -120
- package/sass/components/forms/_checkboxes.scss +9 -9
- package/sass/components/forms/_file-input.scss +9 -7
- package/sass/components/forms/_input-fields.scss +173 -234
- package/sass/components/forms/_radio-buttons.scss +1 -1
- package/sass/components/forms/_range.scss +11 -11
- package/sass/components/forms/_select.scss +29 -19
- package/sass/components/forms/_switches.scss +22 -18
- package/sass/materialize.scss +1 -1
- package/src/autocomplete.ts +459 -0
- package/src/bounding.ts +6 -0
- package/{js/buttons.js → src/buttons.ts} +103 -162
- package/src/cards.ts +54 -0
- package/{js/carousel.js → src/carousel.ts} +137 -262
- package/src/characterCounter.ts +88 -0
- package/src/chips.ts +350 -0
- package/src/collapsible.ts +184 -0
- package/{js/component.js → src/component.ts} +6 -19
- package/{js/datepicker.js → src/datepicker.ts} +213 -299
- package/{js/dropdown.js → src/dropdown.ts} +140 -254
- package/src/edges.ts +6 -0
- package/src/forms.ts +120 -0
- package/src/global.ts +385 -0
- package/src/materialbox.ts +348 -0
- package/src/modal.ts +256 -0
- package/{js/parallax.js → src/parallax.ts} +47 -60
- package/{js/pushpin.js → src/pushpin.ts} +19 -47
- package/{js/range.js → src/range.ts} +58 -139
- package/{js/scrollspy.js → src/scrollspy.ts} +81 -153
- package/src/select.ts +448 -0
- package/{js/sidenav.js → src/sidenav.ts} +96 -202
- package/src/slider.ts +415 -0
- package/src/tabs.ts +290 -0
- package/src/tapTarget.ts +240 -0
- package/{js/timepicker.js → src/timepicker.ts} +268 -272
- package/{js/toasts.js → src/toasts.ts} +75 -134
- package/{js/tooltip.js → src/tooltip.ts} +59 -96
- package/src/waves.ts +70 -0
- package/extras/noUiSlider/nouislider.css +0 -404
- package/extras/noUiSlider/nouislider.js +0 -2147
- package/extras/noUiSlider/nouislider.min.js +0 -1
- package/js/anime.min.js +0 -34
- package/js/autocomplete.js +0 -479
- package/js/cards.js +0 -40
- package/js/cash.js +0 -960
- package/js/characterCounter.js +0 -136
- package/js/chips.js +0 -486
- package/js/collapsible.js +0 -275
- package/js/forms.js +0 -285
- package/js/global.js +0 -428
- package/js/materialbox.js +0 -453
- package/js/modal.js +0 -382
- package/js/select.js +0 -391
- package/js/slider.js +0 -497
- package/js/tabs.js +0 -402
- package/js/tapTarget.js +0 -315
- package/js/waves.js +0 -615
- package/sass/components/_waves.scss +0 -187
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { Component } from "./component";
|
|
2
|
+
import { M } from "./global";
|
|
3
|
+
import anim from "animejs";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const _defaults = {
|
|
5
6
|
alignment: 'left',
|
|
6
7
|
autoFocus: true,
|
|
7
8
|
constrainWidth: true,
|
|
@@ -18,63 +19,44 @@
|
|
|
18
19
|
onItemClick: null
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
export class Dropdown extends Component {
|
|
23
|
+
el: HTMLElement;
|
|
24
|
+
static _dropdowns: Dropdown[] = [];
|
|
25
|
+
id: string;
|
|
26
|
+
dropdownEl: HTMLElement;
|
|
27
|
+
isOpen: boolean;
|
|
28
|
+
isScrollable: boolean;
|
|
29
|
+
isTouchMoving: boolean;
|
|
30
|
+
focusedIndex: number;
|
|
31
|
+
filterQuery: any[];
|
|
32
|
+
private _resetFilterQueryBound: any;
|
|
33
|
+
private _handleDocumentClickBound: any;
|
|
34
|
+
private _handleDocumentTouchmoveBound: any;
|
|
35
|
+
private _handleDropdownClickBound: any;
|
|
36
|
+
private _handleDropdownKeydownBound: any;
|
|
37
|
+
private _handleTriggerKeydownBound: any;
|
|
38
|
+
private _handleMouseEnterBound: any;
|
|
39
|
+
private _handleMouseLeaveBound: any;
|
|
40
|
+
_handleClickBound: any;
|
|
41
|
+
filterTimeout: NodeJS.Timeout;
|
|
42
|
+
|
|
25
43
|
constructor(el, options) {
|
|
26
44
|
super(Dropdown, el, options);
|
|
27
|
-
|
|
28
|
-
this.el.M_Dropdown = this;
|
|
45
|
+
(this.el as any).M_Dropdown = this;
|
|
29
46
|
Dropdown._dropdowns.push(this);
|
|
30
|
-
|
|
31
47
|
this.id = M.getIdFromTrigger(el);
|
|
32
48
|
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;
|
|
49
|
+
//this.$dropdownEl = $(this.dropdownEl);
|
|
50
|
+
this.options = {...Dropdown.defaults, ...options};
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
* Describes if dropdown content is scrollable
|
|
62
|
-
* @type {Boolean}
|
|
63
|
-
*/
|
|
52
|
+
this.isOpen = false;
|
|
64
53
|
this.isScrollable = false;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Describes if touch moving on dropdown content
|
|
68
|
-
* @type {Boolean}
|
|
69
|
-
*/
|
|
70
54
|
this.isTouchMoving = false;
|
|
71
|
-
|
|
72
55
|
this.focusedIndex = -1;
|
|
73
56
|
this.filterQuery = [];
|
|
74
57
|
|
|
75
58
|
// Move dropdown-content after dropdown-trigger
|
|
76
59
|
this._moveDropdown();
|
|
77
|
-
|
|
78
60
|
this._makeDropdownFocusable();
|
|
79
61
|
this._resetFilterQueryBound = this._resetFilterQuery.bind(this);
|
|
80
62
|
this._handleDocumentClickBound = this._handleDocumentClick.bind(this);
|
|
@@ -93,34 +75,23 @@
|
|
|
93
75
|
return super.init(this, els, options);
|
|
94
76
|
}
|
|
95
77
|
|
|
96
|
-
/**
|
|
97
|
-
* Get Instance
|
|
98
|
-
*/
|
|
99
78
|
static getInstance(el) {
|
|
100
|
-
|
|
79
|
+
const domElem = !!el.jquery ? el[0] : el;
|
|
101
80
|
return domElem.M_Dropdown;
|
|
102
81
|
}
|
|
103
82
|
|
|
104
|
-
/**
|
|
105
|
-
* Teardown component
|
|
106
|
-
*/
|
|
107
83
|
destroy() {
|
|
108
84
|
this._resetDropdownStyles();
|
|
109
85
|
this._removeEventHandlers();
|
|
110
86
|
Dropdown._dropdowns.splice(Dropdown._dropdowns.indexOf(this), 1);
|
|
111
|
-
this.el.M_Dropdown = undefined;
|
|
87
|
+
(this.el as any).M_Dropdown = undefined;
|
|
112
88
|
}
|
|
113
89
|
|
|
114
|
-
/**
|
|
115
|
-
* Setup Event Handlers
|
|
116
|
-
*/
|
|
117
90
|
_setupEventHandlers() {
|
|
118
91
|
// Trigger keydown handler
|
|
119
92
|
this.el.addEventListener('keydown', this._handleTriggerKeydownBound);
|
|
120
|
-
|
|
121
93
|
// Item click handler
|
|
122
|
-
this.dropdownEl
|
|
123
|
-
|
|
94
|
+
this.dropdownEl?.addEventListener('click', this._handleDropdownClickBound);
|
|
124
95
|
// Hover event handlers
|
|
125
96
|
if (this.options.hover) {
|
|
126
97
|
this._handleMouseEnterBound = this._handleMouseEnter.bind(this);
|
|
@@ -128,7 +99,6 @@
|
|
|
128
99
|
this._handleMouseLeaveBound = this._handleMouseLeave.bind(this);
|
|
129
100
|
this.el.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
|
130
101
|
this.dropdownEl.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
|
131
|
-
|
|
132
102
|
// Click event handlers
|
|
133
103
|
} else {
|
|
134
104
|
this._handleClickBound = this._handleClick.bind(this);
|
|
@@ -136,13 +106,9 @@
|
|
|
136
106
|
}
|
|
137
107
|
}
|
|
138
108
|
|
|
139
|
-
/**
|
|
140
|
-
* Remove Event Handlers
|
|
141
|
-
*/
|
|
142
109
|
_removeEventHandlers() {
|
|
143
110
|
this.el.removeEventListener('keydown', this._handleTriggerKeydownBound);
|
|
144
111
|
this.dropdownEl.removeEventListener('click', this._handleDropdownClickBound);
|
|
145
|
-
|
|
146
112
|
if (this.options.hover) {
|
|
147
113
|
this.el.removeEventListener('mouseenter', this._handleMouseEnterBound);
|
|
148
114
|
this.el.removeEventListener('mouseleave', this._handleMouseLeaveBound);
|
|
@@ -176,19 +142,17 @@
|
|
|
176
142
|
}
|
|
177
143
|
|
|
178
144
|
_handleMouseLeave(e) {
|
|
179
|
-
|
|
180
|
-
|
|
145
|
+
const toEl = e.toElement || e.relatedTarget;
|
|
146
|
+
const leaveToDropdownContent = !!toEl.closest('.dropdown-content');
|
|
181
147
|
let leaveToActiveDropdownTrigger = false;
|
|
182
|
-
|
|
183
|
-
let $closestTrigger = $(toEl).closest('.dropdown-trigger');
|
|
148
|
+
const closestTrigger = toEl.closest('.dropdown-trigger');
|
|
184
149
|
if (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
150
|
+
closestTrigger &&
|
|
151
|
+
!!(<any>closestTrigger).M_Dropdown &&
|
|
152
|
+
(<any>closestTrigger).M_Dropdown.isOpen
|
|
188
153
|
) {
|
|
189
154
|
leaveToActiveDropdownTrigger = true;
|
|
190
155
|
}
|
|
191
|
-
|
|
192
156
|
// Close hover dropdown if mouse did not leave to either active dropdown-trigger or dropdown-content
|
|
193
157
|
if (!leaveToActiveDropdownTrigger && !leaveToDropdownContent) {
|
|
194
158
|
this.close();
|
|
@@ -196,23 +160,24 @@
|
|
|
196
160
|
}
|
|
197
161
|
|
|
198
162
|
_handleDocumentClick(e) {
|
|
199
|
-
|
|
163
|
+
const target = <HTMLElement>e.target;
|
|
200
164
|
if (
|
|
201
165
|
this.options.closeOnClick &&
|
|
202
|
-
|
|
166
|
+
target.closest('.dropdown-content') &&
|
|
203
167
|
!this.isTouchMoving
|
|
204
168
|
) {
|
|
205
169
|
// isTouchMoving to check if scrolling on mobile.
|
|
206
|
-
setTimeout(() => {
|
|
207
|
-
|
|
208
|
-
}, 0);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
170
|
+
//setTimeout(() => {
|
|
171
|
+
this.close();
|
|
172
|
+
//}, 0);
|
|
173
|
+
}
|
|
174
|
+
else if (
|
|
175
|
+
target.closest('.dropdown-trigger') ||
|
|
176
|
+
!target.closest('.dropdown-content')
|
|
212
177
|
) {
|
|
213
|
-
setTimeout(() => {
|
|
214
|
-
|
|
215
|
-
}, 0);
|
|
178
|
+
//setTimeout(() => {
|
|
179
|
+
this.close();
|
|
180
|
+
//}, 0);
|
|
216
181
|
}
|
|
217
182
|
this.isTouchMoving = false;
|
|
218
183
|
}
|
|
@@ -225,157 +190,127 @@
|
|
|
225
190
|
}
|
|
226
191
|
}
|
|
227
192
|
|
|
228
|
-
/**
|
|
229
|
-
* Handle Document Touchmove
|
|
230
|
-
* @param {Event} e
|
|
231
|
-
*/
|
|
232
193
|
_handleDocumentTouchmove(e) {
|
|
233
|
-
|
|
234
|
-
if (
|
|
194
|
+
const target = <HTMLElement>e.target;
|
|
195
|
+
if (target.closest('.dropdown-content')) {
|
|
235
196
|
this.isTouchMoving = true;
|
|
236
197
|
}
|
|
237
198
|
}
|
|
238
199
|
|
|
239
|
-
/**
|
|
240
|
-
* Handle Dropdown Click
|
|
241
|
-
* @param {Event} e
|
|
242
|
-
*/
|
|
243
200
|
_handleDropdownClick(e) {
|
|
244
201
|
// onItemClick callback
|
|
245
202
|
if (typeof this.options.onItemClick === 'function') {
|
|
246
|
-
|
|
203
|
+
const itemEl = <HTMLElement>e.target.closest('li');
|
|
247
204
|
this.options.onItemClick.call(this, itemEl);
|
|
248
205
|
}
|
|
249
206
|
}
|
|
250
207
|
|
|
251
|
-
/**
|
|
252
|
-
* Handle Dropdown Keydown
|
|
253
|
-
* @param {Event} e
|
|
254
|
-
*/
|
|
255
208
|
_handleDropdownKeydown(e) {
|
|
256
209
|
if (e.which === M.keys.TAB) {
|
|
257
210
|
e.preventDefault();
|
|
258
211
|
this.close();
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
212
|
+
}
|
|
213
|
+
// Navigate down dropdown list
|
|
214
|
+
else if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) && this.isOpen) {
|
|
262
215
|
e.preventDefault();
|
|
263
|
-
|
|
216
|
+
const direction = e.which === M.keys.ARROW_DOWN ? 1 : -1;
|
|
264
217
|
let newFocusedIndex = this.focusedIndex;
|
|
265
|
-
let
|
|
218
|
+
let hasFoundNewIndex = false;
|
|
266
219
|
do {
|
|
267
220
|
newFocusedIndex = newFocusedIndex + direction;
|
|
268
|
-
|
|
269
221
|
if (
|
|
270
222
|
!!this.dropdownEl.children[newFocusedIndex] &&
|
|
271
|
-
this.dropdownEl.children[newFocusedIndex].tabIndex !== -1
|
|
223
|
+
(<any>this.dropdownEl.children[newFocusedIndex]).tabIndex !== -1
|
|
272
224
|
) {
|
|
273
|
-
|
|
225
|
+
hasFoundNewIndex = true;
|
|
274
226
|
break;
|
|
275
227
|
}
|
|
276
228
|
} while (newFocusedIndex < this.dropdownEl.children.length && newFocusedIndex >= 0);
|
|
277
229
|
|
|
278
|
-
if (
|
|
230
|
+
if (hasFoundNewIndex) {
|
|
279
231
|
// Remove active class from old element
|
|
280
232
|
if (this.focusedIndex >= 0)
|
|
281
233
|
this.dropdownEl.children[this.focusedIndex].classList.remove('active');
|
|
282
234
|
this.focusedIndex = newFocusedIndex;
|
|
283
235
|
this._focusFocusedItem();
|
|
284
236
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
237
|
+
}
|
|
238
|
+
// ENTER selects choice on focused item
|
|
239
|
+
else if (e.which === M.keys.ENTER && this.isOpen) {
|
|
288
240
|
// Search for <a> and <button>
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
.find('a, button')
|
|
292
|
-
.first();
|
|
293
|
-
|
|
241
|
+
const focusedElement = this.dropdownEl.children[this.focusedIndex];
|
|
242
|
+
const activatableElement = <HTMLElement>focusedElement.querySelector('a, button');
|
|
294
243
|
// Click a or button tag if exists, otherwise click li tag
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
} else if (!!focusedElement) {
|
|
298
|
-
focusedElement.click();
|
|
244
|
+
if (!!activatableElement) {
|
|
245
|
+
activatableElement.click();
|
|
299
246
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
247
|
+
else if (!!focusedElement) {
|
|
248
|
+
if (focusedElement instanceof HTMLElement) {
|
|
249
|
+
focusedElement.click();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Close dropdown on ESC
|
|
254
|
+
else if (e.which === M.keys.ESC && this.isOpen) {
|
|
303
255
|
e.preventDefault();
|
|
304
256
|
this.close();
|
|
305
257
|
}
|
|
306
258
|
|
|
307
259
|
// CASE WHEN USER TYPE LETTERS
|
|
308
|
-
|
|
309
|
-
|
|
260
|
+
const letter = String.fromCharCode(e.which).toLowerCase();
|
|
261
|
+
const nonLetters = [9, 13, 27, 38, 40];
|
|
310
262
|
if (letter && nonLetters.indexOf(e.which) === -1) {
|
|
311
263
|
this.filterQuery.push(letter);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
.find('li')
|
|
316
|
-
.filter((el) => {
|
|
317
|
-
return (
|
|
318
|
-
$(el)
|
|
319
|
-
.text()
|
|
320
|
-
.toLowerCase()
|
|
321
|
-
.indexOf(string) === 0
|
|
322
|
-
);
|
|
323
|
-
})[0];
|
|
324
|
-
|
|
264
|
+
const string = this.filterQuery.join('');
|
|
265
|
+
const newOptionEl = Array.from(this.dropdownEl.querySelectorAll('li'))
|
|
266
|
+
.find((el) => el.innerText.toLowerCase().indexOf(string) === 0);
|
|
325
267
|
if (newOptionEl) {
|
|
326
|
-
this.focusedIndex =
|
|
268
|
+
this.focusedIndex = [...newOptionEl.parentNode.children].indexOf(newOptionEl);
|
|
327
269
|
this._focusFocusedItem();
|
|
328
270
|
}
|
|
329
271
|
}
|
|
330
|
-
|
|
331
272
|
this.filterTimeout = setTimeout(this._resetFilterQueryBound, 1000);
|
|
332
273
|
}
|
|
333
274
|
|
|
334
|
-
/**
|
|
335
|
-
* Setup dropdown
|
|
336
|
-
*/
|
|
337
275
|
_resetFilterQuery() {
|
|
338
276
|
this.filterQuery = [];
|
|
339
277
|
}
|
|
340
278
|
|
|
341
279
|
_resetDropdownStyles() {
|
|
342
|
-
this
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
opacity: ''
|
|
351
|
-
});
|
|
280
|
+
this.dropdownEl.style.display = '';
|
|
281
|
+
this.dropdownEl.style.width = '';
|
|
282
|
+
this.dropdownEl.style.height = '';
|
|
283
|
+
this.dropdownEl.style.left = '';
|
|
284
|
+
this.dropdownEl.style.top = '';
|
|
285
|
+
this.dropdownEl.style.transformOrigin = '';
|
|
286
|
+
this.dropdownEl.style.transform = '';
|
|
287
|
+
this.dropdownEl.style.opacity = '';
|
|
352
288
|
}
|
|
353
289
|
|
|
354
290
|
// Move dropdown after container or trigger
|
|
355
|
-
_moveDropdown(containerEl) {
|
|
291
|
+
_moveDropdown(containerEl = null) {
|
|
356
292
|
if (!!this.options.container) {
|
|
357
|
-
|
|
358
|
-
}
|
|
293
|
+
this.options.container.append(this.dropdownEl);
|
|
294
|
+
}
|
|
295
|
+
else if (containerEl) {
|
|
359
296
|
if (!containerEl.contains(this.dropdownEl)) {
|
|
360
|
-
|
|
297
|
+
containerEl.append(this.dropdownEl);
|
|
361
298
|
}
|
|
362
|
-
}
|
|
363
|
-
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
this.el.after(this.dropdownEl);
|
|
364
302
|
}
|
|
365
303
|
}
|
|
366
304
|
|
|
367
305
|
_makeDropdownFocusable() {
|
|
306
|
+
if (!this.dropdownEl) return;
|
|
368
307
|
// Needed for arrow key navigation
|
|
369
308
|
this.dropdownEl.tabIndex = 0;
|
|
370
|
-
|
|
371
309
|
// Only set tabindex if it hasn't been set by user
|
|
372
|
-
|
|
373
|
-
.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
el.setAttribute('tabindex', 0);
|
|
377
|
-
}
|
|
378
|
-
});
|
|
310
|
+
Array.from(this.dropdownEl.children).forEach((el)=> {
|
|
311
|
+
if (!el.getAttribute('tabindex'))
|
|
312
|
+
el.setAttribute('tabindex', '0');
|
|
313
|
+
});
|
|
379
314
|
}
|
|
380
315
|
|
|
381
316
|
_focusFocusedItem() {
|
|
@@ -384,7 +319,7 @@
|
|
|
384
319
|
this.focusedIndex < this.dropdownEl.children.length &&
|
|
385
320
|
this.options.autoFocus
|
|
386
321
|
) {
|
|
387
|
-
this.dropdownEl.children[this.focusedIndex].focus({
|
|
322
|
+
(this.dropdownEl.children[this.focusedIndex] as HTMLElement).focus({
|
|
388
323
|
preventScroll: true
|
|
389
324
|
});
|
|
390
325
|
this.dropdownEl.children[this.focusedIndex].scrollIntoView({
|
|
@@ -396,23 +331,23 @@
|
|
|
396
331
|
}
|
|
397
332
|
|
|
398
333
|
_getDropdownPosition(closestOverflowParent) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
334
|
+
const offsetParentBRect = this.el.offsetParent.getBoundingClientRect();
|
|
335
|
+
const triggerBRect = this.el.getBoundingClientRect();
|
|
336
|
+
const dropdownBRect = this.dropdownEl.getBoundingClientRect();
|
|
402
337
|
|
|
403
338
|
let idealHeight = dropdownBRect.height;
|
|
404
339
|
let idealWidth = dropdownBRect.width;
|
|
405
340
|
let idealXPos = triggerBRect.left - dropdownBRect.left;
|
|
406
341
|
let idealYPos = triggerBRect.top - dropdownBRect.top;
|
|
407
342
|
|
|
408
|
-
|
|
343
|
+
const dropdownBounds = {
|
|
409
344
|
left: idealXPos,
|
|
410
345
|
top: idealYPos,
|
|
411
346
|
height: idealHeight,
|
|
412
347
|
width: idealWidth
|
|
413
348
|
};
|
|
414
349
|
|
|
415
|
-
|
|
350
|
+
const alignments = M.checkPossibleAlignments(
|
|
416
351
|
this.el,
|
|
417
352
|
closestOverflowParent,
|
|
418
353
|
dropdownBounds,
|
|
@@ -452,7 +387,7 @@
|
|
|
452
387
|
|
|
453
388
|
// If preferred horizontal alignment is possible
|
|
454
389
|
if (!alignments[horizontalAlignment]) {
|
|
455
|
-
|
|
390
|
+
const oppositeAlignment = horizontalAlignment === 'left' ? 'right' : 'left';
|
|
456
391
|
if (alignments[oppositeAlignment]) {
|
|
457
392
|
horizontalAlignment = oppositeAlignment;
|
|
458
393
|
} else {
|
|
@@ -485,9 +420,6 @@
|
|
|
485
420
|
};
|
|
486
421
|
}
|
|
487
422
|
|
|
488
|
-
/**
|
|
489
|
-
* Animate in dropdown
|
|
490
|
-
*/
|
|
491
423
|
_animateIn() {
|
|
492
424
|
anim.remove(this.dropdownEl);
|
|
493
425
|
anim({
|
|
@@ -501,10 +433,7 @@
|
|
|
501
433
|
duration: this.options.inDuration,
|
|
502
434
|
easing: 'easeOutQuint',
|
|
503
435
|
complete: (anim) => {
|
|
504
|
-
if (this.options.autoFocus)
|
|
505
|
-
this.dropdownEl.focus();
|
|
506
|
-
}
|
|
507
|
-
|
|
436
|
+
if (this.options.autoFocus) this.dropdownEl.focus();
|
|
508
437
|
// onOpenEnd callback
|
|
509
438
|
if (typeof this.options.onOpenEnd === 'function') {
|
|
510
439
|
this.options.onOpenEnd.call(this, this.el);
|
|
@@ -513,9 +442,6 @@
|
|
|
513
442
|
});
|
|
514
443
|
}
|
|
515
444
|
|
|
516
|
-
/**
|
|
517
|
-
* Animate out dropdown
|
|
518
|
-
*/
|
|
519
445
|
_animateOut() {
|
|
520
446
|
anim.remove(this.dropdownEl);
|
|
521
447
|
anim({
|
|
@@ -530,7 +456,6 @@
|
|
|
530
456
|
easing: 'easeOutQuint',
|
|
531
457
|
complete: (anim) => {
|
|
532
458
|
this._resetDropdownStyles();
|
|
533
|
-
|
|
534
459
|
// onCloseEnd callback
|
|
535
460
|
if (typeof this.options.onCloseEnd === 'function') {
|
|
536
461
|
this.options.onCloseEnd.call(this, this.el);
|
|
@@ -539,49 +464,41 @@
|
|
|
539
464
|
});
|
|
540
465
|
}
|
|
541
466
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
* Get closest ancestor that satisfies the condition
|
|
548
|
-
* @param {Element} el Element to find ancestors on
|
|
549
|
-
* @param {Function} condition Function that given an ancestor element returns true or false
|
|
550
|
-
* @returns {Element} Return closest ancestor or null if none satisfies the condition
|
|
551
|
-
*/
|
|
552
|
-
const getClosestAncestor = function(el, condition) {
|
|
553
|
-
let ancestor = el.parentNode;
|
|
554
|
-
while (ancestor !== null && !$(ancestor).is(document)) {
|
|
555
|
-
if (condition(ancestor)) {
|
|
556
|
-
return ancestor;
|
|
557
|
-
}
|
|
558
|
-
ancestor = ancestor.parentNode;
|
|
467
|
+
private _getClosestAncestor(el: Element, condition: Function): Element {
|
|
468
|
+
let ancestor = el.parentNode;
|
|
469
|
+
while (ancestor !== null && ancestor !== document) {
|
|
470
|
+
if (condition(ancestor)) {
|
|
471
|
+
return <Element>ancestor;
|
|
559
472
|
}
|
|
560
|
-
|
|
561
|
-
}
|
|
473
|
+
ancestor = ancestor.parentNode;
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
};
|
|
562
477
|
|
|
478
|
+
_placeDropdown() {
|
|
563
479
|
// Container here will be closest ancestor with overflow: hidden
|
|
564
|
-
let closestOverflowParent =
|
|
565
|
-
return
|
|
480
|
+
let closestOverflowParent: HTMLElement = <HTMLElement>this._getClosestAncestor(this.dropdownEl, (ancestor: HTMLElement) => {
|
|
481
|
+
return !['HTML','BODY'].includes(ancestor.tagName) && getComputedStyle(ancestor).overflow !== 'visible';
|
|
566
482
|
});
|
|
567
483
|
// Fallback
|
|
568
484
|
if (!closestOverflowParent) {
|
|
569
|
-
closestOverflowParent = !!this.dropdownEl.offsetParent
|
|
485
|
+
closestOverflowParent = <HTMLElement>(!!this.dropdownEl.offsetParent
|
|
570
486
|
? this.dropdownEl.offsetParent
|
|
571
|
-
: this.dropdownEl.parentNode;
|
|
487
|
+
: this.dropdownEl.parentNode);
|
|
572
488
|
}
|
|
573
|
-
|
|
574
|
-
|
|
489
|
+
|
|
490
|
+
if (getComputedStyle(closestOverflowParent).position === 'static')
|
|
491
|
+
closestOverflowParent.style.position = 'relative';
|
|
575
492
|
|
|
576
493
|
this._moveDropdown(closestOverflowParent);
|
|
577
494
|
|
|
578
495
|
// Set width before calculating positionInfo
|
|
579
|
-
|
|
496
|
+
const idealWidth = this.options.constrainWidth
|
|
580
497
|
? this.el.getBoundingClientRect().width
|
|
581
498
|
: this.dropdownEl.getBoundingClientRect().width;
|
|
582
499
|
this.dropdownEl.style.width = idealWidth + 'px';
|
|
583
500
|
|
|
584
|
-
|
|
501
|
+
const positionInfo = this._getDropdownPosition(closestOverflowParent);
|
|
585
502
|
this.dropdownEl.style.left = positionInfo.x + 'px';
|
|
586
503
|
this.dropdownEl.style.top = positionInfo.y + 'px';
|
|
587
504
|
this.dropdownEl.style.height = positionInfo.height + 'px';
|
|
@@ -591,79 +508,48 @@
|
|
|
591
508
|
} ${positionInfo.verticalAlignment === 'top' ? '0' : '100%'}`;
|
|
592
509
|
}
|
|
593
510
|
|
|
594
|
-
/**
|
|
595
|
-
* Open Dropdown
|
|
596
|
-
*/
|
|
597
511
|
open() {
|
|
598
|
-
if (this.isOpen)
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
512
|
+
if (this.isOpen) return;
|
|
601
513
|
this.isOpen = true;
|
|
602
|
-
|
|
603
514
|
// onOpenStart callback
|
|
604
515
|
if (typeof this.options.onOpenStart === 'function') {
|
|
605
516
|
this.options.onOpenStart.call(this, this.el);
|
|
606
517
|
}
|
|
607
|
-
|
|
608
518
|
// Reset styles
|
|
609
519
|
this._resetDropdownStyles();
|
|
610
520
|
this.dropdownEl.style.display = 'block';
|
|
611
|
-
|
|
612
521
|
this._placeDropdown();
|
|
613
522
|
this._animateIn();
|
|
614
523
|
this._setupTemporaryEventHandlers();
|
|
615
524
|
}
|
|
616
525
|
|
|
617
|
-
/**
|
|
618
|
-
* Close Dropdown
|
|
619
|
-
*/
|
|
620
526
|
close() {
|
|
621
|
-
if (!this.isOpen)
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
|
|
527
|
+
if (!this.isOpen) return;
|
|
625
528
|
this.isOpen = false;
|
|
626
529
|
this.focusedIndex = -1;
|
|
627
|
-
|
|
628
530
|
// onCloseStart callback
|
|
629
531
|
if (typeof this.options.onCloseStart === 'function') {
|
|
630
532
|
this.options.onCloseStart.call(this, this.el);
|
|
631
533
|
}
|
|
632
|
-
|
|
633
534
|
this._animateOut();
|
|
634
535
|
this._removeTemporaryEventHandlers();
|
|
635
|
-
|
|
636
536
|
if (this.options.autoFocus) {
|
|
637
537
|
this.el.focus();
|
|
638
538
|
}
|
|
639
539
|
}
|
|
640
540
|
|
|
641
|
-
/**
|
|
642
|
-
* Recalculate dimensions
|
|
643
|
-
*/
|
|
644
541
|
recalculateDimensions() {
|
|
645
542
|
if (this.isOpen) {
|
|
646
|
-
this
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
'transform-origin': ''
|
|
652
|
-
});
|
|
543
|
+
this.dropdownEl.style.width = '';
|
|
544
|
+
this.dropdownEl.style.height = '';
|
|
545
|
+
this.dropdownEl.style.left = '';
|
|
546
|
+
this.dropdownEl.style.top = '';
|
|
547
|
+
this.dropdownEl.style.transformOrigin = '';
|
|
653
548
|
this._placeDropdown();
|
|
654
549
|
}
|
|
655
550
|
}
|
|
656
|
-
}
|
|
657
551
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
*/
|
|
662
|
-
Dropdown._dropdowns = [];
|
|
663
|
-
|
|
664
|
-
M.Dropdown = Dropdown;
|
|
665
|
-
|
|
666
|
-
if (M.jQueryLoaded) {
|
|
667
|
-
M.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown');
|
|
552
|
+
static {
|
|
553
|
+
Dropdown._dropdowns = [];
|
|
554
|
+
}
|
|
668
555
|
}
|
|
669
|
-
})(cash, M.anime);
|
package/src/edges.ts
ADDED