@materializecss/materialize 2.0.3-beta → 2.0.4
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/LICENSE +1 -1
- package/README.md +16 -18
- package/dist/css/materialize.css +73 -26
- package/dist/css/materialize.min.css +3 -3
- package/dist/js/materialize.js +560 -2015
- package/dist/js/materialize.min.js +3 -3
- package/dist/js/materialize.min.js.map +1 -1
- package/dist/src/buttons.d.ts.map +1 -1
- package/dist/src/cards.d.ts.map +1 -1
- package/dist/src/collapsible.d.ts +1 -0
- package/dist/src/collapsible.d.ts.map +1 -1
- package/dist/src/dropdown.d.ts +1 -0
- package/dist/src/dropdown.d.ts.map +1 -1
- package/dist/src/global.d.ts.map +1 -1
- package/dist/src/materialbox.d.ts +14 -10
- package/dist/src/materialbox.d.ts.map +1 -1
- package/dist/src/modal.d.ts.map +1 -1
- package/dist/src/range.d.ts.map +1 -1
- package/dist/src/scrollspy.d.ts.map +1 -1
- package/dist/src/sidenav.d.ts +25 -25
- package/dist/src/sidenav.d.ts.map +1 -1
- package/dist/src/slider.d.ts +12 -12
- package/dist/src/slider.d.ts.map +1 -1
- package/dist/src/tabs.d.ts +1 -1
- package/dist/src/tabs.d.ts.map +1 -1
- package/dist/src/toasts.d.ts +7 -2
- package/dist/src/toasts.d.ts.map +1 -1
- package/dist/src/tooltip.d.ts.map +1 -1
- package/package.json +29 -44
- package/sass/components/_collapsible.scss +14 -2
- package/sass/components/_materialbox.scss +2 -2
- package/sass/components/_modal.scss +0 -1
- package/sass/components/_tooltip.scss +18 -8
- package/sass/components/_variables.scss +2 -2
- package/Gruntfile.js +0 -385
- package/src/autocomplete.ts +0 -553
- package/src/bounding.ts +0 -6
- package/src/buttons.ts +0 -260
- package/src/cards.ts +0 -53
- package/src/carousel.ts +0 -676
- package/src/characterCounter.ts +0 -117
- package/src/chips.ts +0 -439
- package/src/collapsible.ts +0 -249
- package/src/component.ts +0 -120
- package/src/datepicker.ts +0 -1076
- package/src/dropdown.ts +0 -644
- package/src/edges.ts +0 -6
- package/src/forms.ts +0 -132
- package/src/global.ts +0 -114
- package/src/index.ts +0 -26
- package/src/materialbox.ts +0 -404
- package/src/modal.ts +0 -341
- package/src/parallax.ts +0 -149
- package/src/pushpin.ts +0 -165
- package/src/range.ts +0 -198
- package/src/scrollspy.ts +0 -263
- package/src/select.ts +0 -484
- package/src/sidenav.ts +0 -543
- package/src/slider.ts +0 -474
- package/src/tabs.ts +0 -347
- package/src/tapTarget.ts +0 -273
- package/src/timepicker.ts +0 -832
- package/src/toasts.ts +0 -290
- package/src/tooltip.ts +0 -366
- package/src/utils.ts +0 -271
- package/src/waves.ts +0 -70
package/src/select.ts
DELETED
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
import { Utils } from "./utils";
|
|
2
|
-
import { Dropdown, DropdownOptions } from "./dropdown";
|
|
3
|
-
import { Component, BaseOptions, InitElements, MElement } from "./component";
|
|
4
|
-
|
|
5
|
-
export interface FormSelectOptions extends BaseOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Classes to be added to the select wrapper element.
|
|
8
|
-
* @default ""
|
|
9
|
-
*/
|
|
10
|
-
classes: string;
|
|
11
|
-
/**
|
|
12
|
-
* Pass options object to select dropdown initialization.
|
|
13
|
-
* @default {}
|
|
14
|
-
*/
|
|
15
|
-
dropdownOptions: Partial<DropdownOptions>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let _defaults: FormSelectOptions = {
|
|
19
|
-
classes: '',
|
|
20
|
-
dropdownOptions: {}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
type ValueStruct = {
|
|
24
|
-
el: HTMLOptionElement,
|
|
25
|
-
optionEl: HTMLElement,
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class FormSelect extends Component<FormSelectOptions> {
|
|
29
|
-
declare el: HTMLSelectElement;
|
|
30
|
-
/** If this is a multiple select. */
|
|
31
|
-
isMultiple: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Label associated with the current select element.
|
|
34
|
-
* Is "null", if not detected.
|
|
35
|
-
*/
|
|
36
|
-
labelEl: HTMLLabelElement;
|
|
37
|
-
/** Dropdown UL element. */
|
|
38
|
-
dropdownOptions: HTMLUListElement;
|
|
39
|
-
/** Text input that shows current selected option. */
|
|
40
|
-
input: HTMLInputElement;
|
|
41
|
-
/** Instance of the dropdown plugin for this select. */
|
|
42
|
-
dropdown: Dropdown;
|
|
43
|
-
/** The select wrapper element. */
|
|
44
|
-
wrapper: HTMLDivElement;
|
|
45
|
-
selectOptions: (HTMLOptionElement|HTMLOptGroupElement)[];
|
|
46
|
-
private _values: ValueStruct[];
|
|
47
|
-
|
|
48
|
-
constructor(el: HTMLSelectElement, options: FormSelectOptions) {
|
|
49
|
-
super(el, options, FormSelect);
|
|
50
|
-
if (this.el.classList.contains('browser-default')) return;
|
|
51
|
-
(this.el as any).M_FormSelect = this;
|
|
52
|
-
|
|
53
|
-
this.options = {
|
|
54
|
-
...FormSelect.defaults,
|
|
55
|
-
...options
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
this.isMultiple = this.el.multiple;
|
|
59
|
-
this.el.tabIndex = -1;
|
|
60
|
-
this._values = [];
|
|
61
|
-
//this.labelEl = null;
|
|
62
|
-
//this._labelFor = false;
|
|
63
|
-
this._setupDropdown();
|
|
64
|
-
this._setupEventHandlers();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static get defaults(): FormSelectOptions {
|
|
68
|
-
return _defaults;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Initializes instance of FormSelect.
|
|
73
|
-
* @param el HTML element.
|
|
74
|
-
* @param options Component options.
|
|
75
|
-
*/
|
|
76
|
-
static init(el: HTMLSelectElement, options?: Partial<FormSelectOptions>): FormSelect;
|
|
77
|
-
/**
|
|
78
|
-
* Initializes instances of FormSelect.
|
|
79
|
-
* @param els HTML elements.
|
|
80
|
-
* @param options Component options.
|
|
81
|
-
*/
|
|
82
|
-
static init(els: InitElements<HTMLSelectElement | MElement>, options?: Partial<FormSelectOptions>): FormSelect[];
|
|
83
|
-
/**
|
|
84
|
-
* Initializes instances of FormSelect.
|
|
85
|
-
* @param els HTML elements.
|
|
86
|
-
* @param options Component options.
|
|
87
|
-
*/
|
|
88
|
-
static init(els: HTMLSelectElement | InitElements<HTMLSelectElement | MElement>, options: Partial<FormSelectOptions> = {}): FormSelect | FormSelect[] {
|
|
89
|
-
return super.init(els, options, FormSelect);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
static getInstance(el: HTMLElement): FormSelect {
|
|
93
|
-
return (el as any).M_FormSelect;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
destroy() {
|
|
97
|
-
// Returns label to its original owner
|
|
98
|
-
//if (this._labelFor) this.labelEl.setAttribute("for", this.el.id);
|
|
99
|
-
this._removeEventHandlers();
|
|
100
|
-
this._removeDropdown();
|
|
101
|
-
(this.el as any).M_FormSelect = undefined;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
_setupEventHandlers() {
|
|
105
|
-
this.dropdownOptions.querySelectorAll('li:not(.optgroup)').forEach((el) => {
|
|
106
|
-
el.addEventListener('click', this._handleOptionClick);
|
|
107
|
-
el.addEventListener('keydown', (e: KeyboardEvent) => {
|
|
108
|
-
if (e.key === " " || e.key === "Enter") this._handleOptionClick(e);
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
this.el.addEventListener('change', this._handleSelectChange);
|
|
112
|
-
this.input.addEventListener('click', this._handleInputClick);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
_removeEventHandlers() {
|
|
116
|
-
this.dropdownOptions.querySelectorAll('li:not(.optgroup)').forEach((el) => {
|
|
117
|
-
el.removeEventListener('click', this._handleOptionClick);
|
|
118
|
-
});
|
|
119
|
-
this.el.removeEventListener('change', this._handleSelectChange);
|
|
120
|
-
this.input.removeEventListener('click', this._handleInputClick);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
_handleSelectChange = () => {
|
|
124
|
-
this._setValueToInput();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
_handleOptionClick = (e: MouseEvent | KeyboardEvent) => {
|
|
128
|
-
e.preventDefault();
|
|
129
|
-
const virtualOption = (e.target as HTMLLIElement).closest('li');
|
|
130
|
-
this._selectOptionElement(virtualOption);
|
|
131
|
-
e.stopPropagation();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
_arraysEqual<T, E>(a: T[], b: (E|T)[]) {
|
|
135
|
-
if (a === b) return true;
|
|
136
|
-
if (a == null || b == null) return false;
|
|
137
|
-
if (a.length !== b.length) return false;
|
|
138
|
-
for (let i = 0; i < a.length; ++i) if (a[i] !== b[i]) return false;
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
_selectOptionElement(virtualOption: HTMLElement) {
|
|
143
|
-
if (!virtualOption.classList.contains('disabled') && !virtualOption.classList.contains('optgroup')) {
|
|
144
|
-
const value = this._values.find((value) => value.optionEl === virtualOption);
|
|
145
|
-
const previousSelectedValues = this.getSelectedValues();
|
|
146
|
-
if (this.isMultiple) {
|
|
147
|
-
// Multi-Select
|
|
148
|
-
this._toggleEntryFromArray(value);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
// Single-Select
|
|
152
|
-
this._deselectAll();
|
|
153
|
-
this._selectValue(value);
|
|
154
|
-
}
|
|
155
|
-
// Refresh Input-Text
|
|
156
|
-
this._setValueToInput();
|
|
157
|
-
// Trigger Change-Event only when data is different
|
|
158
|
-
const actualSelectedValues = this.getSelectedValues();
|
|
159
|
-
const selectionHasChanged = !this._arraysEqual(
|
|
160
|
-
previousSelectedValues,
|
|
161
|
-
actualSelectedValues
|
|
162
|
-
);
|
|
163
|
-
if (selectionHasChanged) this.el.dispatchEvent(new Event('change',{bubbles:true, cancelable:true, composed:true})); // trigger('change');
|
|
164
|
-
}
|
|
165
|
-
if (!this.isMultiple) this.dropdown.close();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
_handleInputClick = () => {
|
|
169
|
-
if (this.dropdown && this.dropdown.isOpen) {
|
|
170
|
-
this._setValueToInput();
|
|
171
|
-
this._setSelectedStates();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
_setupDropdown() {
|
|
176
|
-
// Get Label
|
|
177
|
-
this.labelEl = this.el.parentElement.querySelector('label');
|
|
178
|
-
|
|
179
|
-
// Create Wrapper
|
|
180
|
-
this.wrapper = document.createElement('div');
|
|
181
|
-
this.wrapper.classList.add('select-wrapper', 'input-field');
|
|
182
|
-
if (this.options.classes.length > 0) {
|
|
183
|
-
this.wrapper.classList.add(...this.options.classes.split(' '));
|
|
184
|
-
}
|
|
185
|
-
this.el.before(this.wrapper);
|
|
186
|
-
|
|
187
|
-
// Move actual select element into overflow hidden wrapper
|
|
188
|
-
const hideSelect = document.createElement('div');
|
|
189
|
-
hideSelect.classList.add('hide-select');
|
|
190
|
-
this.wrapper.append(hideSelect);
|
|
191
|
-
hideSelect.appendChild(this.el);
|
|
192
|
-
|
|
193
|
-
if (this.el.disabled) this.wrapper.classList.add('disabled');
|
|
194
|
-
|
|
195
|
-
this.selectOptions = <(HTMLOptGroupElement|HTMLOptionElement)[]>Array.from(this.el.children).filter(el => ['OPTION','OPTGROUP'].includes(el.tagName));
|
|
196
|
-
|
|
197
|
-
// Create dropdown
|
|
198
|
-
this.dropdownOptions = document.createElement('ul');
|
|
199
|
-
this.dropdownOptions.id = `select-options-${Utils.guid()}`;
|
|
200
|
-
this.dropdownOptions.classList.add('dropdown-content', 'select-dropdown');
|
|
201
|
-
this.dropdownOptions.setAttribute('role', 'listbox');
|
|
202
|
-
this.dropdownOptions.ariaMultiSelectable = this.isMultiple.toString();
|
|
203
|
-
if (this.isMultiple) this.dropdownOptions.classList.add('multiple-select-dropdown');
|
|
204
|
-
|
|
205
|
-
// Create dropdown structure
|
|
206
|
-
if (this.selectOptions.length > 0) {
|
|
207
|
-
this.selectOptions.forEach((realOption) => {
|
|
208
|
-
if (realOption.tagName === 'OPTION') {
|
|
209
|
-
// Option
|
|
210
|
-
const virtualOption = this._createAndAppendOptionWithIcon(realOption, this.isMultiple ? 'multiple' : undefined);
|
|
211
|
-
this._addOptionToValues(realOption as HTMLOptionElement, virtualOption);
|
|
212
|
-
}
|
|
213
|
-
else if (realOption.tagName === 'OPTGROUP') {
|
|
214
|
-
// Optgroup
|
|
215
|
-
const groupId = "opt-group-"+Utils.guid();
|
|
216
|
-
const groupParent = document.createElement('li');
|
|
217
|
-
groupParent.classList.add('optgroup');
|
|
218
|
-
groupParent.tabIndex = -1;
|
|
219
|
-
groupParent.setAttribute('role', 'group');
|
|
220
|
-
groupParent.setAttribute('aria-labelledby', groupId);
|
|
221
|
-
groupParent.innerHTML = `<span id="${groupId}" role="presentation">${realOption.getAttribute('label')}</span>`;
|
|
222
|
-
this.dropdownOptions.append(groupParent);
|
|
223
|
-
|
|
224
|
-
const groupChildren = [];
|
|
225
|
-
const selectOptions = <HTMLOptionElement[]>Array.from(realOption.children).filter(el => el.tagName === 'OPTION');
|
|
226
|
-
selectOptions.forEach(realOption => {
|
|
227
|
-
const virtualOption = this._createAndAppendOptionWithIcon(realOption, 'optgroup-option');
|
|
228
|
-
const childId = "opt-child-"+Utils.guid();
|
|
229
|
-
virtualOption.id = childId;
|
|
230
|
-
groupChildren.push(childId);
|
|
231
|
-
this._addOptionToValues(realOption, virtualOption);
|
|
232
|
-
});
|
|
233
|
-
groupParent.setAttribute("aria-owns", groupChildren.join(" "));
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
this.wrapper.append(this.dropdownOptions);
|
|
238
|
-
|
|
239
|
-
// Add input dropdown
|
|
240
|
-
this.input = document.createElement('input');
|
|
241
|
-
this.input.id = "m_select-input-" + Utils.guid();
|
|
242
|
-
this.input.classList.add('select-dropdown', 'dropdown-trigger');
|
|
243
|
-
this.input.type = 'text';
|
|
244
|
-
this.input.readOnly = true;
|
|
245
|
-
this.input.setAttribute('data-target', this.dropdownOptions.id);
|
|
246
|
-
this.input.ariaReadOnly = 'true';
|
|
247
|
-
this.input.ariaRequired = this.el.hasAttribute("required").toString(); //setAttribute("aria-required", this.el.hasAttribute("required"));
|
|
248
|
-
if (this.el.disabled) this.input.disabled = true; // 'true');
|
|
249
|
-
|
|
250
|
-
// Place Label after input
|
|
251
|
-
if (this.labelEl) {
|
|
252
|
-
this.input.after(this.labelEl);
|
|
253
|
-
this.labelEl.setAttribute('for', this.input.id);
|
|
254
|
-
this.labelEl.id = "m_select-label-" + Utils.guid();
|
|
255
|
-
this.dropdownOptions.setAttribute("aria-labelledby", this.labelEl.id);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Makes new element to assume HTML's select label and aria-attributes, if exists
|
|
259
|
-
/*
|
|
260
|
-
if (this.el.hasAttribute("aria-labelledby")){
|
|
261
|
-
console.log(1);
|
|
262
|
-
this.labelEl = <HTMLLabelElement>document.getElementById(this.el.getAttribute("aria-labelledby"));
|
|
263
|
-
}
|
|
264
|
-
else if (this.el.id != ""){
|
|
265
|
-
console.log(2);
|
|
266
|
-
const label = document.createElement('label');
|
|
267
|
-
label.setAttribute('for', this.el.id);
|
|
268
|
-
if (label){
|
|
269
|
-
this.labelEl = label;
|
|
270
|
-
this.labelEl.removeAttribute("for");
|
|
271
|
-
this._labelFor = true;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
*/
|
|
275
|
-
// Tries to find a valid label in parent element
|
|
276
|
-
// if (!this.labelEl) {
|
|
277
|
-
// this.labelEl = this.el.parentElement.querySelector('label');
|
|
278
|
-
// }
|
|
279
|
-
// if (this.labelEl && this.labelEl.id == "") {
|
|
280
|
-
// this.labelEl.id = "m_select-label-" + Utils.guid();
|
|
281
|
-
// }
|
|
282
|
-
// if (this.labelEl) {
|
|
283
|
-
// this.labelEl.setAttribute("for", this.input.id);
|
|
284
|
-
// this.dropdownOptions.setAttribute("aria-labelledby", this.labelEl.id);
|
|
285
|
-
// }
|
|
286
|
-
// else
|
|
287
|
-
// this.dropdownOptions.ariaLabel = '';
|
|
288
|
-
|
|
289
|
-
const attrs = this.el.attributes;
|
|
290
|
-
for (let i = 0; i < attrs.length; ++i){
|
|
291
|
-
const attr = attrs[i];
|
|
292
|
-
if (attr.name.startsWith("aria-"))
|
|
293
|
-
this.input.setAttribute(attr.name, attr.value);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Adds aria-attributes to input element
|
|
297
|
-
this.input.setAttribute('role', 'combobox');
|
|
298
|
-
this.input.ariaExpanded = 'false';
|
|
299
|
-
this.input.setAttribute("aria-owns", this.dropdownOptions.id);
|
|
300
|
-
this.input.setAttribute("aria-controls", this.dropdownOptions.id);
|
|
301
|
-
this.input.placeholder = " ";
|
|
302
|
-
|
|
303
|
-
this.wrapper.prepend(this.input);
|
|
304
|
-
this._setValueToInput();
|
|
305
|
-
|
|
306
|
-
// Add caret
|
|
307
|
-
const dropdownIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); //document.createElement('svg')
|
|
308
|
-
dropdownIcon.classList.add('caret');
|
|
309
|
-
dropdownIcon.setAttribute('height', '24');
|
|
310
|
-
dropdownIcon.setAttribute('width', '24');
|
|
311
|
-
dropdownIcon.setAttribute('viewBox', '0 0 24 24');
|
|
312
|
-
dropdownIcon.ariaHidden = 'true';
|
|
313
|
-
dropdownIcon.innerHTML = `<path d="M7 10l5 5 5-5z"/><path d="M0 0h24v24H0z" fill="none"/>`;
|
|
314
|
-
this.wrapper.prepend(dropdownIcon);
|
|
315
|
-
|
|
316
|
-
// Initialize dropdown
|
|
317
|
-
if (!this.el.disabled) {
|
|
318
|
-
const dropdownOptions = {...this.options.dropdownOptions}; // TODO:
|
|
319
|
-
dropdownOptions.coverTrigger = false;
|
|
320
|
-
const userOnOpenEnd = dropdownOptions.onOpenEnd;
|
|
321
|
-
const userOnCloseEnd = dropdownOptions.onCloseEnd;
|
|
322
|
-
// Add callback for centering selected option when dropdown content is scrollable
|
|
323
|
-
dropdownOptions.onOpenEnd = (el) => {
|
|
324
|
-
const selectedOption = this.dropdownOptions.querySelector('.selected');
|
|
325
|
-
if (selectedOption) {
|
|
326
|
-
// Focus selected option in dropdown
|
|
327
|
-
Utils.keyDown = true;
|
|
328
|
-
this.dropdown.focusedIndex = [...selectedOption.parentNode.children].indexOf(selectedOption);
|
|
329
|
-
this.dropdown._focusFocusedItem();
|
|
330
|
-
Utils.keyDown = false;
|
|
331
|
-
// Handle scrolling to selected option
|
|
332
|
-
if (this.dropdown.isScrollable) {
|
|
333
|
-
let scrollOffset =
|
|
334
|
-
selectedOption.getBoundingClientRect().top -
|
|
335
|
-
(this.dropdownOptions as HTMLElement).getBoundingClientRect().top; // scroll to selected option
|
|
336
|
-
scrollOffset -= this.dropdownOptions.clientHeight / 2; // center in dropdown
|
|
337
|
-
this.dropdownOptions.scrollTop = scrollOffset;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
this.input.ariaExpanded = 'true';
|
|
341
|
-
// Handle user declared onOpenEnd if needed
|
|
342
|
-
if (userOnOpenEnd && typeof userOnOpenEnd === 'function')
|
|
343
|
-
userOnOpenEnd.call(this.dropdown, this.el);
|
|
344
|
-
};
|
|
345
|
-
// Add callback for reseting "expanded" state
|
|
346
|
-
dropdownOptions.onCloseEnd = (el) => {
|
|
347
|
-
this.input.ariaExpanded = 'false';
|
|
348
|
-
// Handle user declared onOpenEnd if needed
|
|
349
|
-
if (userOnCloseEnd && typeof userOnCloseEnd === 'function')
|
|
350
|
-
userOnCloseEnd.call(this.dropdown, this.el);
|
|
351
|
-
};
|
|
352
|
-
// Prevent dropdown from closing too early
|
|
353
|
-
dropdownOptions.closeOnClick = false;
|
|
354
|
-
this.dropdown = Dropdown.init(this.input, dropdownOptions);
|
|
355
|
-
}
|
|
356
|
-
// Add initial selections
|
|
357
|
-
this._setSelectedStates();
|
|
358
|
-
|
|
359
|
-
// ! Workaround for Label: move label up again
|
|
360
|
-
if (this.labelEl) this.input.after(this.labelEl);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
_addOptionToValues(realOption: HTMLOptionElement, virtualOption: HTMLElement) {
|
|
364
|
-
this._values.push({ el: realOption, optionEl: virtualOption });
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
_removeDropdown() {
|
|
368
|
-
this.wrapper.querySelector('.caret').remove();
|
|
369
|
-
this.input.remove();
|
|
370
|
-
this.dropdownOptions.remove();
|
|
371
|
-
this.wrapper.before(this.el);
|
|
372
|
-
this.wrapper.remove();
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
_createAndAppendOptionWithIcon(realOption, type: string) {
|
|
376
|
-
const li = document.createElement('li');
|
|
377
|
-
li.setAttribute('role', 'option');
|
|
378
|
-
if (realOption.disabled){
|
|
379
|
-
li.classList.add('disabled');
|
|
380
|
-
li.ariaDisabled = 'true';
|
|
381
|
-
}
|
|
382
|
-
if (type === 'optgroup-option') li.classList.add(type);
|
|
383
|
-
// Text / Checkbox
|
|
384
|
-
const span = document.createElement('span');
|
|
385
|
-
if (this.isMultiple)
|
|
386
|
-
span.innerHTML = `<label><input type="checkbox"${
|
|
387
|
-
realOption.disabled ? ' disabled="disabled"' : ''
|
|
388
|
-
}><span>${realOption.innerHTML}</span></label>`;
|
|
389
|
-
else
|
|
390
|
-
span.innerHTML = realOption.innerHTML;
|
|
391
|
-
li.appendChild(span);
|
|
392
|
-
// add Icon
|
|
393
|
-
const iconUrl = realOption.getAttribute('data-icon');
|
|
394
|
-
const classes = realOption.getAttribute('class')?.split();
|
|
395
|
-
if (iconUrl) {
|
|
396
|
-
const img = document.createElement('img');
|
|
397
|
-
if (classes) img.classList.add(classes);
|
|
398
|
-
img.src = iconUrl;
|
|
399
|
-
img.ariaHidden = 'true';
|
|
400
|
-
li.prepend(img);
|
|
401
|
-
}
|
|
402
|
-
// Check for multiple type
|
|
403
|
-
this.dropdownOptions.append(li);
|
|
404
|
-
return li;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
_selectValue(value: ValueStruct) {
|
|
408
|
-
value.el.selected = true;
|
|
409
|
-
value.optionEl.classList.add('selected');
|
|
410
|
-
value.optionEl.ariaSelected = 'true'; // setAttribute("aria-selected", true);
|
|
411
|
-
const checkbox = <HTMLInputElement>value.optionEl.querySelector('input[type="checkbox"]');
|
|
412
|
-
if (checkbox) checkbox.checked = true;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
_deselectValue(value: ValueStruct) {
|
|
416
|
-
value.el.selected = false;
|
|
417
|
-
value.optionEl.classList.remove('selected');
|
|
418
|
-
value.optionEl.ariaSelected = 'false'; //setAttribute("aria-selected", false);
|
|
419
|
-
const checkbox = <HTMLInputElement>value.optionEl.querySelector('input[type="checkbox"]');
|
|
420
|
-
if (checkbox) checkbox.checked = false;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
_deselectAll() {
|
|
424
|
-
this._values.forEach(value => this._deselectValue(value));
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
_isValueSelected(value: ValueStruct) {
|
|
428
|
-
const realValues = this.getSelectedValues();
|
|
429
|
-
return realValues.some((realValue) => realValue === value.el.value);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
_toggleEntryFromArray(value: ValueStruct) {
|
|
433
|
-
if (this._isValueSelected(value))
|
|
434
|
-
this._deselectValue(value);
|
|
435
|
-
else
|
|
436
|
-
this._selectValue(value);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
_getSelectedOptions(): HTMLOptionElement[] {
|
|
440
|
-
// remove null, false, ... values
|
|
441
|
-
return Array.prototype.filter.call(this.el.selectedOptions, (realOption: HTMLOptionElement) => realOption);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
_setValueToInput() {
|
|
445
|
-
const realOptions = this._getSelectedOptions();
|
|
446
|
-
const values = this._values.filter((value) => realOptions.indexOf(value.el) >= 0);
|
|
447
|
-
const texts = values.map((value) => value.optionEl.querySelector('span').innerText.trim());
|
|
448
|
-
// Set input-text to first Option with empty value which indicates a description like "choose your option"
|
|
449
|
-
if (texts.length === 0) {
|
|
450
|
-
const firstDisabledOption = <HTMLOptionElement>this.el.querySelector('option:disabled');
|
|
451
|
-
if (firstDisabledOption && firstDisabledOption.value === '') {
|
|
452
|
-
this.input.value = firstDisabledOption.innerText;
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
this.input.value = texts.join(', ');
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
_setSelectedStates() {
|
|
460
|
-
this._values.forEach((value) => {
|
|
461
|
-
const optionIsSelected = value.el.selected;
|
|
462
|
-
const cb = <HTMLInputElement>value.optionEl.querySelector('input[type="checkbox"]');
|
|
463
|
-
if (cb) cb.checked = optionIsSelected;
|
|
464
|
-
if (optionIsSelected) {
|
|
465
|
-
this._activateOption(this.dropdownOptions, value.optionEl);
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
value.optionEl.classList.remove('selected');
|
|
469
|
-
value.optionEl.ariaSelected = 'false'; // attr("aria-selected", 'false');
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
_activateOption(ul: HTMLElement, li: HTMLElement) {
|
|
475
|
-
if (!li) return;
|
|
476
|
-
if (!this.isMultiple) ul.querySelectorAll('li.selected').forEach(li => li.classList.remove('selected'));
|
|
477
|
-
li.classList.add('selected');
|
|
478
|
-
li.ariaSelected = 'true';
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
getSelectedValues() {
|
|
482
|
-
return this._getSelectedOptions().map((realOption) => realOption.value);
|
|
483
|
-
}
|
|
484
|
-
}
|