simp-select 1.0.0

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.
@@ -0,0 +1,152 @@
1
+ import { ISimpleSelectOptions, ISimpleSelectProps } from './types/simpleSelect.types';
2
+ import { selectorType } from './types/item.types';
3
+
4
+ import { nameMark, nameSelect, simpleSelectionOptions } from './const/simpleSelection.const';
5
+ import { createDataAttr, toCamelCase } from './utils/simpleSelection.utils';
6
+ import { SimpleSelectItem } from './simpleSelectItem';
7
+ import './style.css';
8
+
9
+ export default class SimpleSelect {
10
+ callCount = Date.now();
11
+
12
+ countInit = 0;
13
+
14
+ // $selects: HTMLSelectElement[] = [];
15
+ $selects: SimpleSelectItem[] = [];
16
+
17
+ options!: ISimpleSelectOptions;
18
+
19
+ nameMarkTransform = toCamelCase(nameMark);
20
+
21
+ dataNameMark = createDataAttr(nameMark);
22
+
23
+ isNative!: boolean;
24
+
25
+ constructor(selector: selectorType, options?: ISimpleSelectProps) {
26
+ if (!selector) {
27
+ selector = 'select';
28
+ }
29
+ // this.$selects = Array.from(document.querySelectorAll(selector));
30
+
31
+ this.options = {
32
+ ...simpleSelectionOptions,
33
+ ...options,
34
+ };
35
+
36
+ if (typeof selector === 'string') {
37
+ this.init(Array.from(document.querySelectorAll(selector)));
38
+ } else if (selector instanceof HTMLSelectElement) {
39
+ this.init([selector]);
40
+ } else if (selector instanceof NodeList) {
41
+ this.init(Array.from(selector));
42
+ } else if (Array.isArray(selector)) {
43
+ this.init(selector);
44
+ } else {
45
+ console.warn('Wrong selector: ', selector);
46
+ }
47
+ }
48
+
49
+ detectMobile() {
50
+ if (this.options.detectNative) {
51
+ this.isNative = this.options.detectNative();
52
+ return;
53
+ }
54
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
55
+ // @ts-ignore
56
+ const ua = navigator.userAgent || navigator.vendor || window.opera;
57
+
58
+ let res = false;
59
+ // Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices
60
+ for (let i = 0; i < this.options.nativeOnDevice.length; i++) {
61
+ if (ua.toString().toLowerCase().indexOf(this.options.nativeOnDevice[i].toLowerCase()) > 0) {
62
+ if (this.options.nativeOnDevice[i]) {
63
+ res = true;
64
+ }
65
+ }
66
+ }
67
+ this.isNative = res;
68
+ }
69
+
70
+ private init(selects: HTMLSelectElement[]) {
71
+ this.detectMobile();
72
+ selects.forEach(($select) => {
73
+ this.build($select);
74
+ });
75
+ }
76
+
77
+ createMethods(select: SimpleSelectItem) {
78
+ const self = this;
79
+ return {
80
+ getInstance: () => select.getSelect(),
81
+ reload() {
82
+ self.rebuild(select);
83
+ },
84
+ update() {
85
+ select.updateHTML();
86
+ },
87
+ detach() {
88
+ self.detach(select);
89
+ },
90
+ };
91
+ }
92
+
93
+ setMethods(select: SimpleSelectItem) {
94
+ // @ts-ignore
95
+ select.$select[nameSelect] = this.createMethods(select);
96
+ }
97
+
98
+ setMethodsClear(select: SimpleSelectItem) {
99
+ // @ts-ignore
100
+ delete select.$select[nameSelect];
101
+ }
102
+
103
+ private build(select: HTMLSelectElement) {
104
+ const isProcessed = this.nameMarkTransform in select.dataset;
105
+ if (isProcessed) {
106
+ console.warn('This element has already been initialized', select);
107
+ return;
108
+ }
109
+
110
+ this.countInit += 1;
111
+ const id = `${this.callCount}-${this.countInit}`;
112
+ select.setAttribute(this.dataNameMark, id);
113
+ // this.$selects.push(select);
114
+
115
+ const newSelect = new SimpleSelectItem(select, this.options, {
116
+ id, isNative: this.isNative,
117
+ });
118
+ this.$selects.push(newSelect);
119
+ this.setMethods(newSelect);
120
+ }
121
+
122
+ private detach(itemSelect: SimpleSelectItem) {
123
+ itemSelect.detachItem();
124
+
125
+ itemSelect.$select.removeAttribute(this.dataNameMark);
126
+ this.setMethodsClear(itemSelect);
127
+ this.$selects = this.$selects.filter((item) => item !== itemSelect);
128
+ }
129
+
130
+ public rebuild(selectsItems: SimpleSelectItem) {
131
+ const select = selectsItems.$select;
132
+ this.detach(selectsItems);
133
+ this.build(select);
134
+ }
135
+
136
+ public getSelects() {
137
+ return this.$selects;
138
+ }
139
+
140
+ public getSelectFirst() {
141
+ // return this.$selects[0];
142
+ return this.createMethods(this.$selects[0]);
143
+ }
144
+
145
+ public getSelectById(id:string) {
146
+ const search = this.$selects.filter((item) => item.id === id)[0];
147
+ if (!search) {
148
+ return null;
149
+ }
150
+ return this.createMethods(search);
151
+ }
152
+ }
@@ -0,0 +1,535 @@
1
+ import { IItemLocalOptions, ISimpleSelectOptions } from './types/simpleSelect.types';
2
+ import { IOptionItems } from './types/item.types';
3
+ import {
4
+ cloneObj,
5
+ compareObj,
6
+ getCreateListItem,
7
+ toCamelCase,
8
+ triggerInputEvent,
9
+ } from './utils/simpleSelection.utils';
10
+ import { SimpleSelectItemDOM } from './simpleSelectItemDOM';
11
+
12
+ export class SimpleSelectItem extends SimpleSelectItemDOM {
13
+ closeOutsideHandler!: (e:MouseEvent) => void; // not native
14
+
15
+ closeEscHandler!: (e:KeyboardEvent) => void; // not native
16
+
17
+ changeListener!: (e:Event) => void; // not native
18
+
19
+ searchHandler!: (e:Event) => void; // not native
20
+
21
+ clickToggleOpen!: (e:MouseEvent | KeyboardEvent) => void; // not native
22
+
23
+ triggerSetup!: (e: MouseEvent) => void; // not native
24
+
25
+ confirmOkHandler!: (e: MouseEvent) => void; // not native
26
+
27
+ confirmNoHandler!: (e: MouseEvent) => void; // not native
28
+
29
+ selectAllHandler!: (e: MouseEvent) => void; // not native
30
+
31
+ resetAllHandler!: (e: MouseEvent) => void; // not native
32
+
33
+ closeHandler!: (e: MouseEvent) => void; // not native
34
+
35
+ handleResize!: (e: MediaQueryList | null) => void; // not native
36
+
37
+ mql: MediaQueryList | null = null;
38
+
39
+ countOpen = 0;
40
+
41
+ multiDebounceTime = 0;
42
+
43
+ timeoutDebounceId: NodeJS.Timeout | null = null;
44
+
45
+ constructor(select: HTMLSelectElement, options: ISimpleSelectOptions, localOptions: IItemLocalOptions) {
46
+ super(select, options, localOptions);
47
+
48
+ if (!select) {
49
+ throw Error('Select is required');
50
+ }
51
+ this.init();
52
+ super.initDom();
53
+ this.initAfterDom();
54
+ }
55
+
56
+ init() {
57
+ this.changeListener = this.changeListenerInit.bind(this);
58
+ this.$select.addEventListener('change', this.changeListener);
59
+
60
+ this.searchHandler = this.searchHandlerInit.bind(this);
61
+ this.closeOutsideHandler = this.closeOutsideHandlerInit.bind(this);
62
+ this.closeEscHandler = this.closeEscHandlerInit.bind(this);
63
+ this.clickToggleOpen = this.clickToggleOpenInit.bind(this);
64
+
65
+ this.triggerSetup = this.triggerSetupInit.bind(this);
66
+
67
+ this.confirmOkHandler = this.confirmOkHandlerInit.bind(this);
68
+ this.confirmNoHandler = this.confirmNoHandlerInit.bind(this);
69
+
70
+ this.selectAllHandler = this.selectAllHandlerInit.bind(this);
71
+ this.resetAllHandler = this.resetAllHandlerInit.bind(this);
72
+
73
+ this.closeHandler = this.closeHandlerInit.bind(this);
74
+
75
+ this.handleResize = this.handleResizeInit.bind(this);
76
+
77
+ if (this.options.callbackInitialization) {
78
+ this.options.callbackInitialization(this);
79
+ }
80
+
81
+ if (!this.isNative && this.options.floatWidth) {
82
+ this.mql = window.matchMedia(`(max-width: ${this.options.floatWidth}px)`);
83
+ if (this.mql) {
84
+ // @ts-ignore
85
+ this.mql.onchange = this.handleResize;
86
+ this.handleResizeInit(this.mql);
87
+ }
88
+ }
89
+
90
+ this.state.subscribe('isOpen', (val: IOptionItems[]) => {
91
+ this.toggleOpenHandler();
92
+ if (!val && this.options.isConfirmInMulti) {
93
+ this.createList();
94
+ }
95
+ if (val) {
96
+ if (this.elemInputSearch) {
97
+ this.elemInputSearch.value = '';
98
+ }
99
+ }
100
+ // if (!val) {
101
+ // if (this.options.isConfirmInMulti) {
102
+ // this.triggerInit();
103
+ // }
104
+ // }
105
+ });
106
+
107
+ this.state.subscribe('filterStr', (val: string) => {
108
+ this.filterList(val);
109
+ });
110
+
111
+ if (!this.isNative) {
112
+ this.elemTopBody.addEventListener('click', this.clickToggleOpen);
113
+ this.elemTopBody.addEventListener('keyup', this.clickToggleOpen);
114
+ }
115
+ }
116
+
117
+ private handleResizeInit(e: MediaQueryList | null) {
118
+ if (!e) {
119
+ return;
120
+ }
121
+
122
+ if (e.matches) {
123
+ this.state.setState('isFloat', true);
124
+ } else {
125
+ this.state.setState('isFloat', false);
126
+ }
127
+ }
128
+
129
+ private initAfterDom() {
130
+ if (this.confirmOk) {
131
+ this.confirmOk.addEventListener('click', this.confirmOkHandler);
132
+ }
133
+ if (this.confirmNo) {
134
+ this.confirmNo.addEventListener('click', this.confirmNoHandler);
135
+ }
136
+
137
+ if (this.options.callbackInitialized) {
138
+ this.options.callbackInitialized(this);
139
+ }
140
+
141
+ if (this.isMulti && !this.options.isConfirmInMulti) {
142
+ if (toCamelCase('simple-debounce-time') in this.$select.dataset) {
143
+ this.multiDebounceTime = Number(this.$select.dataset[toCamelCase('simple-debounce-time')]);
144
+ } else if (this.options.debounceTime || this.options.debounceTime === 0) {
145
+ this.multiDebounceTime = this.options.debounceTime;
146
+ }
147
+ }
148
+
149
+ if (this.multiDebounceTime) {
150
+ this.multiDebounceChange = this.debounce(this.multiDebounceChange.bind(this), this.multiDebounceTime);
151
+ }
152
+
153
+ if (this.elemSelectAll) {
154
+ this.elemSelectAll.addEventListener('click', this.selectAllHandler);
155
+ }
156
+ if (this.elemResetAll) {
157
+ this.elemResetAll.addEventListener('click', this.resetAllHandler);
158
+ }
159
+ if (this.elemDropDownClose) {
160
+ this.elemDropDownClose.addEventListener('click', this.closeHandler);
161
+ }
162
+ }
163
+
164
+ debounce<T extends (
165
+ ...args: never[]) => void>(
166
+ func: T,
167
+ delay: number,
168
+ ): (...args: Parameters<T>) => void {
169
+ return (...args: Parameters<T>): void => {
170
+ if (this.timeoutDebounceId) {
171
+ clearTimeout(this.timeoutDebounceId);
172
+ }
173
+
174
+ this.timeoutDebounceId = setTimeout(() => {
175
+ func(...args);
176
+ this.timeoutDebounceId = null;
177
+ }, delay);
178
+ };
179
+ }
180
+
181
+ confirmOkHandlerInit(e:MouseEvent) {
182
+ e.preventDefault();
183
+
184
+ this.confirmOkBuild();
185
+ }
186
+
187
+ confirmOkBuild() {
188
+ const { options } = this.$select;
189
+ if (!this.elemListBody) {
190
+ return;
191
+ }
192
+ const liItems: NodeListOf<HTMLLIElement> = this.elemListBody.querySelectorAll('[data-sel-position]');
193
+ liItems.forEach((item:HTMLLIElement) => {
194
+ const pos = parseInt(item.dataset[toCamelCase('sel-position')]!, 10);
195
+ if (!pos && pos !== 0) {
196
+ return;
197
+ }
198
+ const option = options[pos];
199
+ if (!option || option.disabled) {
200
+ return;
201
+ }
202
+ option.selected = item.dataset[toCamelCase('sel-opt-checked')] === 'true';
203
+ });
204
+ this.state.setState('isOpen', false);
205
+ this.triggerInit();
206
+ }
207
+
208
+ confirmNoHandlerInit(e:MouseEvent) {
209
+ e.preventDefault();
210
+ this.state.setState('isOpen', false);
211
+ }
212
+
213
+ closeHandlerInit(e:MouseEvent) {
214
+ e.preventDefault();
215
+ this.state.setState('isOpen', false);
216
+ }
217
+
218
+ selectAllHandlerInit(e:MouseEvent) {
219
+ e.preventDefault();
220
+ Array.from(this.$select.options).forEach((option) => {
221
+ if (option.disabled) {
222
+ return;
223
+ }
224
+ option.selected = true;
225
+ });
226
+ this.createList();
227
+ if (this.options.selectAllAfterClose) {
228
+ this.state.setState('isOpen', false);
229
+ }
230
+ this.triggerInit();
231
+ }
232
+
233
+ resetAllHandlerInit(e:MouseEvent) {
234
+ e.preventDefault();
235
+ Array.from(this.$select.options).forEach((option) => {
236
+ if (option.disabled) {
237
+ return;
238
+ }
239
+ option.selected = false;
240
+ });
241
+ this.createList();
242
+ if (this.options.selectAllAfterClose) {
243
+ this.state.setState('isOpen', false);
244
+ }
245
+ this.triggerInit();
246
+ }
247
+
248
+ // click for LI
249
+ triggerSetupInit(e:MouseEvent) {
250
+ if (e.button !== 0) return;
251
+ const target = e.target as HTMLElement;
252
+ const targetLi = target.closest('li');
253
+ if (targetLi) {
254
+ this.changeClickItem(targetLi);
255
+ }
256
+ }
257
+
258
+ changeClickItem(item: HTMLLIElement) {
259
+ if (item) {
260
+ const pos = Number(item.dataset[toCamelCase('sel-position')]) || 0;
261
+ const option = this.$select.options[pos];
262
+ if (option && !option.disabled) {
263
+ if (this.isMulti) {
264
+ if (this.options.isConfirmInMulti || this.isFloatWidth) {
265
+ if (item.dataset[toCamelCase('sel-opt-checked')] === 'true') {
266
+ item.dataset[toCamelCase('sel-opt-checked')] = 'false';
267
+ item.classList.remove('SimpleSel__list_item--checked');
268
+ } else {
269
+ item.dataset[toCamelCase('sel-opt-checked')] = 'true';
270
+ item.classList.add('SimpleSel__list_item--checked');
271
+ }
272
+ } else {
273
+ option.selected = !option.selected;
274
+ this.createList();
275
+ this.multiDebounceChange();
276
+ }
277
+ } else {
278
+ option.selected = !option.selected;
279
+ this.createList();
280
+ this.state.setState('isOpen', false);
281
+ this.triggerInit();
282
+ }
283
+ }
284
+ }
285
+ }
286
+
287
+ multiDebounceChange() {
288
+ // can be overridden for multiselect - debounce
289
+ this.triggerInit();
290
+ }
291
+
292
+ triggerInit() {
293
+ triggerInputEvent(this.$select);
294
+ }
295
+
296
+ clickToggleOpenInit(e:MouseEvent | KeyboardEvent) {
297
+ e.preventDefault();
298
+ if (this.isDisabled) {
299
+ return;
300
+ }
301
+ if (e.type === 'click') {
302
+ this.state.setState('isOpen', !this.state.getState('isOpen'));
303
+ return;
304
+ }
305
+ if (e instanceof KeyboardEvent) {
306
+ if (e.key === 'Enter') {
307
+ this.state.setState('isOpen', !this.state.getState('isOpen'));
308
+ }
309
+ }
310
+ }
311
+
312
+ closeOutsideHandlerInit(e: MouseEvent) {
313
+ const target: HTMLElement = e.target as HTMLElement;
314
+ if (!target) {
315
+ return;
316
+ }
317
+ if (!this.elemWrap.contains(target)) {
318
+ if (this.options.isConfirmInMulti && this.options.isConfirmInMultiOkClickOutside) {
319
+ this.confirmOkBuild();
320
+ }
321
+
322
+ this.state.setState('isOpen', false);
323
+ }
324
+ }
325
+
326
+ closeEscHandlerInit(e: KeyboardEvent) {
327
+ if (e.code === 'Escape') {
328
+ e.preventDefault();
329
+ e.stopPropagation();
330
+ this.state.setState('isOpen', false);
331
+ }
332
+ if (e.code === 'Tab') {
333
+ e.preventDefault();
334
+ e.stopPropagation();
335
+
336
+ if (!this.elemWrap.contains(e.target as HTMLElement)) {
337
+ this.state.setState('isOpen', false);
338
+ }
339
+ }
340
+ if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
341
+ e.preventDefault();
342
+ e.stopPropagation();
343
+ this.keyBoardChangeChecked(e.key === 'ArrowDown');
344
+ }
345
+ if (e.key === 'Enter') {
346
+ const target = e.target as HTMLLIElement;
347
+ if (target && toCamelCase('sel-opt-item') in target.dataset) {
348
+ e.preventDefault();
349
+ e.stopPropagation();
350
+ this.changeClickItem(target);
351
+ }
352
+ }
353
+ }
354
+
355
+ keyBoardChangeChecked(isDown: boolean) {
356
+ // eslint-disable-next-line max-len
357
+ const liItems: NodeListOf<HTMLLIElement> = this.elemListBody!.querySelectorAll('[data-sel-position]:not([data-sel-opt-disabled="true"])');
358
+ if (!liItems.length) {
359
+ return;
360
+ }
361
+
362
+ let indCurrent = 0;
363
+ let firstOption!: HTMLLIElement;
364
+ liItems.forEach((el, i) => {
365
+ if (document.activeElement === el) {
366
+ indCurrent = i;
367
+ firstOption = el;
368
+ }
369
+ el.removeAttribute('tabindex');
370
+ });
371
+
372
+ if (!firstOption) {
373
+ firstOption = isDown ? liItems[0] : liItems[liItems.length - 1];
374
+ } else if (isDown) {
375
+ firstOption = liItems[indCurrent + 1] || liItems[0];
376
+ } else {
377
+ firstOption = liItems[indCurrent - 1] || liItems[liItems.length - 1];
378
+ }
379
+
380
+ firstOption.tabIndex = 0;
381
+ firstOption.focus();
382
+ }
383
+
384
+ searchHandlerInit(e: Event) {
385
+ const target = e.target as HTMLInputElement;
386
+ if (!target) {
387
+ return;
388
+ }
389
+ const { value } = target;
390
+ this.state.setState('filterStr', value);
391
+ }
392
+
393
+ toggleOpenHandler() {
394
+ const isOpen = this.state.getState('isOpen');
395
+
396
+ if (isOpen) {
397
+ this.elemWrap.classList.add('SimpleSel--open');
398
+ document.addEventListener('click', this.closeOutsideHandler);
399
+ document.addEventListener('keyup', this.closeEscHandler);
400
+
401
+ if (this.elemInputSearch) {
402
+ this.elemInputSearch.focus();
403
+ // this.elemInputSearch.tabIndex = 0;
404
+ }
405
+
406
+ if (this.options.callbackOpen) {
407
+ this.options.callbackOpen(this);
408
+ }
409
+ this.countOpen++;
410
+ } else {
411
+ this.state.setState('filterList', '');
412
+ this.elemWrap.classList.remove('SimpleSel--open');
413
+ document.removeEventListener('click', this.closeOutsideHandler);
414
+ document.removeEventListener('keyup', this.closeEscHandler);
415
+
416
+ if (this.timeoutDebounceId) {
417
+ clearTimeout(this.timeoutDebounceId);
418
+ this.triggerInit();
419
+ }
420
+
421
+ if (this.options.callbackClose && this.countOpen > 0) {
422
+ this.options.callbackClose(this);
423
+ }
424
+ }
425
+ // this.bodyElement.classList.toggle('SimpleSel--open', this.state.getState('isOpen'))
426
+ }
427
+
428
+ private changeListenerInit(e: Event) {
429
+ if (this.options.callbackChangeSelect) {
430
+ this.options.callbackChangeSelect(e, this);
431
+ }
432
+
433
+ this.createList(true);
434
+ // alert(e.target.value);
435
+ }
436
+
437
+ public getSelect() {
438
+ return this.$select;
439
+ }
440
+
441
+ protected handlerChangeChecked() {
442
+ if (this.elemListBody) {
443
+ this.elemListBody.addEventListener('mouseup', this.triggerSetup);
444
+ // this.elemListBody.addEventListener('mouseup', (e) => {})
445
+ }
446
+ }
447
+
448
+ protected createList(isCompare = false) {
449
+ const newItems:IOptionItems[] = [];
450
+ const group = this.$select.querySelectorAll('optgroup');
451
+ if (group && group.length) {
452
+ group.forEach((item, ind) => {
453
+ newItems.push(getCreateListItem(item, (ind + 1).toString(), true));
454
+ });
455
+ } else {
456
+ newItems.push(getCreateListItem(this.$select, '1', false));
457
+ }
458
+
459
+ if (isCompare) {
460
+ const old = this.state.getState('items');
461
+ if (!compareObj(old, newItems)) {
462
+ this.state.setState('items', newItems);
463
+ }
464
+ } else {
465
+ this.state.setState('items', newItems);
466
+ }
467
+ }
468
+
469
+ private filterList(val: string) {
470
+ val = val.toLowerCase();
471
+ const items:IOptionItems[] = cloneObj(this.state.getState('items'));
472
+
473
+ items.forEach((group) => {
474
+ let isShowGroup = false;
475
+ group.items.forEach((item) => {
476
+ if (item.title.toLowerCase().includes(val)) {
477
+ isShowGroup = true;
478
+ item.isShowFilter = true;
479
+ } else {
480
+ item.isShowFilter = false;
481
+ }
482
+ });
483
+ group.isShowFilter = isShowGroup;
484
+ });
485
+ this.state.setState('items', items);
486
+ }
487
+
488
+ inputSearchHandler() {
489
+ if (!this.elemInputSearch) {
490
+ return;
491
+ }
492
+ this.elemInputSearch.addEventListener('input', this.searchHandler);
493
+ }
494
+
495
+ public detachItem() {
496
+ if (this.options.callbackDestroyInit) {
497
+ this.options.callbackDestroyInit(this);
498
+ }
499
+ const parentElement = this.elemWrap.parentNode;
500
+ this.$select.removeEventListener('change', this.changeListener);
501
+
502
+ if (this.elemInputSearch) {
503
+ this.elemInputSearch.removeEventListener('input', this.searchHandler);
504
+ }
505
+
506
+ if (this.confirmOk) {
507
+ this.confirmOk.removeEventListener('click', this.confirmOkHandler);
508
+ }
509
+ if (this.confirmNo) {
510
+ this.confirmNo.removeEventListener('click', this.confirmNoHandler);
511
+ }
512
+
513
+ parentElement!.replaceChild(this.$select, this.elemWrap);
514
+ this.$select.classList.remove(this.classSelectInit);
515
+
516
+ if (this.elemSelectAll) {
517
+ this.elemSelectAll.removeEventListener('click', this.selectAllHandler);
518
+ }
519
+ if (this.elemResetAll) {
520
+ this.elemResetAll.removeEventListener('click', this.resetAllHandler);
521
+ }
522
+
523
+ if (this.options.callbackDestroy) {
524
+ this.options.callbackDestroy(this);
525
+ }
526
+
527
+ if (this.elemDropDownClose) {
528
+ this.elemDropDownClose.removeEventListener('click', this.closeHandler);
529
+ }
530
+ if (this.mql) {
531
+ this.mql.onchange = null;
532
+ this.mql = null;
533
+ }
534
+ }
535
+ }