@danielgindi/selectbox 1.0.147 → 2.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.
- package/css/droplist.css +1 -1
- package/css/droplist.css.map +1 -1
- package/dist/lib.cjs.js +853 -338
- package/dist/lib.cjs.js.map +1 -1
- package/dist/lib.cjs.min.js +2 -2
- package/dist/lib.cjs.min.js.map +1 -1
- package/dist/lib.es6.js +853 -338
- package/dist/lib.es6.js.map +1 -1
- package/dist/lib.es6.min.js +2 -2
- package/dist/lib.es6.min.js.map +1 -1
- package/dist/lib.umd.js +853 -338
- package/dist/lib.umd.js.map +1 -1
- package/dist/lib.umd.min.js +2 -2
- package/dist/lib.umd.min.js.map +1 -1
- package/lib/DropList.js +726 -104
- package/lib/SelectBox.js +80 -187
- package/package.json +19 -20
- package/scss/droplist.scss +141 -110
- package/vue/DropList.vue +93 -8
- package/vue/SelectBox.vue +13 -13
package/dist/lib.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @danielgindi/selectbox
|
|
2
|
+
* @danielgindi/selectbox 2.0.0
|
|
3
3
|
* git://github.com/danielgindi/selectbox.git
|
|
4
4
|
*/
|
|
5
5
|
'use strict';
|
|
@@ -14,9 +14,57 @@ var mitt = require('mitt');
|
|
|
14
14
|
|
|
15
15
|
var escapeRegex = (value) => value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
16
16
|
|
|
17
|
+
const throttle = (func, wait, options) => {
|
|
18
|
+
let timeout, context, args, result;
|
|
19
|
+
let previous = 0;
|
|
20
|
+
if (!options) options = {};
|
|
21
|
+
|
|
22
|
+
const later = () => {
|
|
23
|
+
previous = options.leading === false ? 0 : Date.now();
|
|
24
|
+
timeout = null;
|
|
25
|
+
result = func.apply(context, args);
|
|
26
|
+
if (!timeout) context = args = null;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const throttled = function () {
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
if (!previous && options.leading === false)
|
|
32
|
+
previous = now;
|
|
33
|
+
|
|
34
|
+
const remaining = wait - (now - previous);
|
|
35
|
+
context = this;
|
|
36
|
+
args = arguments;
|
|
37
|
+
if (remaining <= 0 || remaining > wait) {
|
|
38
|
+
if (timeout) {
|
|
39
|
+
clearTimeout(timeout);
|
|
40
|
+
timeout = null;
|
|
41
|
+
}
|
|
42
|
+
previous = now;
|
|
43
|
+
result = func.apply(context, args);
|
|
44
|
+
if (!timeout) context = args = null;
|
|
45
|
+
} else if (!timeout && options.trailing !== false) {
|
|
46
|
+
timeout = setTimeout(later, remaining);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
throttled.cancel = () => {
|
|
52
|
+
clearTimeout(timeout);
|
|
53
|
+
previous = 0;
|
|
54
|
+
timeout = context = args = null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
throttled.isScheduled = () => {
|
|
58
|
+
return !!timeout;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return throttled;
|
|
62
|
+
};
|
|
63
|
+
|
|
17
64
|
const ItemSymbol$1 = Symbol('item');
|
|
18
65
|
const DestroyedSymbol$1 = Symbol('destroyed');
|
|
19
66
|
const GhostSymbol = Symbol('ghost');
|
|
67
|
+
const NoResultsItemSymbol = Symbol('no_results_items');
|
|
20
68
|
|
|
21
69
|
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
22
70
|
|
|
@@ -42,7 +90,17 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
|
42
90
|
* @property {string} [valueProp='value']
|
|
43
91
|
* @property {function(item: DropList.ItemBase, itemEl: Element):(*|false)} [renderItem] Function to call when rendering an item element
|
|
44
92
|
* @property {function(item: DropList.ItemBase, itemEl: Element)} [unrenderItem] Function to call when rendering an item element
|
|
93
|
+
* @property {function(item: DropList.ItemBase, itemEl: Element):(*|false)} [renderNoResultsItem]
|
|
94
|
+
* @property {function(item: DropList.ItemBase, itemEl: Element)} [unrenderNoResultsItem]
|
|
45
95
|
* @property {function(name: string, data: *)} [on]
|
|
96
|
+
* @property {boolean} [searchable=false] include inline search box
|
|
97
|
+
* @property {string} [noResultsText='No matching results'] text for no results (empty for none)
|
|
98
|
+
* @property {number} [filterThrottleWindow=300] throttle time (milliseconds) for filtering
|
|
99
|
+
* @property {boolean} [filterOnEmptyTerm=false] call the filter function on empty search term too
|
|
100
|
+
* @property {boolean} [filterGroups=false] should groups be filtered?
|
|
101
|
+
* @property {boolean} [filterEmptyGroups=false] should empty groups be filtered out?
|
|
102
|
+
* @property {function(items: DropList.ItemBase[], term: string):(DropList.ItemBase[]|null)} [filterFn]
|
|
103
|
+
* @property {function(dropList: DropList):DropList.PositionOptions} [positionOptionsProvider]
|
|
46
104
|
* */
|
|
47
105
|
/** */
|
|
48
106
|
|
|
@@ -105,7 +163,14 @@ let defaultOptions$1 = {
|
|
|
105
163
|
labelProp: 'label',
|
|
106
164
|
valueProp: 'value',
|
|
107
165
|
|
|
108
|
-
on: null
|
|
166
|
+
on: null,
|
|
167
|
+
|
|
168
|
+
searchable: false,
|
|
169
|
+
noResultsText: 'No matching results',
|
|
170
|
+
filterThrottleWindow: 300,
|
|
171
|
+
filterOnEmptyTerm: false,
|
|
172
|
+
filterGroups: false,
|
|
173
|
+
filterEmptyGroups: false
|
|
109
174
|
};
|
|
110
175
|
|
|
111
176
|
/*
|
|
@@ -166,17 +231,35 @@ class DropList {
|
|
|
166
231
|
valueProp: o.valueProp,
|
|
167
232
|
renderItem: o.renderItem,
|
|
168
233
|
unrenderItem: o.unrenderItem,
|
|
234
|
+
renderNoResultsItem: o.renderNoResultsItem,
|
|
235
|
+
unrenderNoResultsItem: o.unrenderNoResultsItem,
|
|
169
236
|
on: o.on || null,
|
|
237
|
+
positionOptionsProvider: o.positionOptionsProvider ?? null,
|
|
238
|
+
|
|
239
|
+
searchable: o.searchable,
|
|
240
|
+
|
|
170
241
|
silenceEvents: true,
|
|
171
242
|
mitt: mitt(),
|
|
172
243
|
|
|
244
|
+
filterThrottleWindow: o.filterThrottleWindow,
|
|
245
|
+
filterOnEmptyTerm: o.filterOnEmptyTerm,
|
|
246
|
+
filterGroups: o.filterGroups,
|
|
247
|
+
filterEmptyGroups: o.filterEmptyGroups,
|
|
248
|
+
filterFn: o.filterFn,
|
|
249
|
+
filteredItems: null,
|
|
250
|
+
filterTerm: '',
|
|
251
|
+
needsRefilter: false,
|
|
252
|
+
throttledRefilterItems: null,
|
|
253
|
+
|
|
173
254
|
focusItemIndex: -1,
|
|
174
255
|
focusItemEl: null,
|
|
175
256
|
|
|
176
257
|
sink: new DomEventsSink()
|
|
177
258
|
};
|
|
178
259
|
|
|
179
|
-
|
|
260
|
+
const baseClass = p.baseClassName + '_wrapper';
|
|
261
|
+
|
|
262
|
+
let classes = [baseClass];
|
|
180
263
|
|
|
181
264
|
if (p.additionalClasses) {
|
|
182
265
|
classes = classes.concat((p.additionalClasses + '').split(' ').filter((x) => x));
|
|
@@ -187,31 +270,54 @@ class DropList {
|
|
|
187
270
|
top: '-9999px'
|
|
188
271
|
};
|
|
189
272
|
|
|
190
|
-
let
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Css.setCssProps(/**@type ElementCSSInlineStyle*/
|
|
273
|
+
let wrapperEl = o.el;
|
|
274
|
+
|
|
275
|
+
if (wrapperEl instanceof Element) {
|
|
276
|
+
p.elOriginalDisplay = wrapperEl.style.display || '';
|
|
277
|
+
wrapperEl.classList.add(...classes);
|
|
278
|
+
Css.setCssProps(/**@type ElementCSSInlineStyle*/wrapperEl, initialCss);
|
|
196
279
|
p.ownsEl = false;
|
|
197
280
|
} else {
|
|
198
|
-
|
|
281
|
+
wrapperEl = Dom.createElement('div', {
|
|
199
282
|
class: classes.join(' '),
|
|
200
|
-
role: 'menu',
|
|
201
283
|
css: initialCss
|
|
202
284
|
});
|
|
203
285
|
}
|
|
204
286
|
|
|
205
|
-
|
|
287
|
+
let menuEl = Dom.createElement('ul');
|
|
288
|
+
menuEl.role = 'menu';
|
|
206
289
|
|
|
207
|
-
|
|
290
|
+
if (o.searchable) {
|
|
291
|
+
p.headerEl = Dom.createElement('div', {
|
|
292
|
+
class: p.baseClassName + '_header'
|
|
293
|
+
});
|
|
208
294
|
|
|
209
|
-
|
|
295
|
+
p.searchInput = Dom.createElement('input', {
|
|
296
|
+
type: 'search',
|
|
297
|
+
role: 'searchbox',
|
|
298
|
+
tabindex: '0',
|
|
299
|
+
autocorrect: 'off',
|
|
300
|
+
autocomplete: 'off',
|
|
301
|
+
autocapitalize: 'off',
|
|
302
|
+
spellcheck: 'false',
|
|
303
|
+
'aria-autocomplete': 'list'
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
p.headerEl.appendChild(p.searchInput);
|
|
307
|
+
wrapperEl.appendChild(p.headerEl);
|
|
308
|
+
}
|
|
210
309
|
|
|
310
|
+
wrapperEl.appendChild(menuEl);
|
|
311
|
+
|
|
312
|
+
p.el = wrapperEl;
|
|
313
|
+
p.menuEl = menuEl;
|
|
314
|
+
|
|
315
|
+
p.items = [];
|
|
316
|
+
p.groupCount = 0; // This will keep state of how many `group` items we have
|
|
211
317
|
p.mouseHandled = false;
|
|
212
318
|
|
|
213
319
|
p.virtualListHelper = new VirtualListHelper({
|
|
214
|
-
list: p.
|
|
320
|
+
list: p.menuEl,
|
|
215
321
|
virtual: true,
|
|
216
322
|
buffer: 5,
|
|
217
323
|
estimatedItemHeight: o.estimatedItemHeight || 20,
|
|
@@ -238,7 +344,19 @@ class DropList {
|
|
|
238
344
|
};
|
|
239
345
|
itemEl.setAttribute('aria-hidden', 'true');
|
|
240
346
|
} else {
|
|
241
|
-
|
|
347
|
+
const items = p.filteredItems ?? p.items;
|
|
348
|
+
if (items.length === 0 && p.noResultsText) {
|
|
349
|
+
item = {
|
|
350
|
+
value: NoResultsItemSymbol,
|
|
351
|
+
label: p.noResultsText,
|
|
352
|
+
_nointeraction: true,
|
|
353
|
+
_nocheck: true,
|
|
354
|
+
|
|
355
|
+
[ItemSymbol$1]: NoResultsItemSymbol
|
|
356
|
+
};
|
|
357
|
+
} else {
|
|
358
|
+
item = items[index];
|
|
359
|
+
}
|
|
242
360
|
}
|
|
243
361
|
|
|
244
362
|
if (!item) {
|
|
@@ -284,36 +402,20 @@ class DropList {
|
|
|
284
402
|
}
|
|
285
403
|
});
|
|
286
404
|
|
|
287
|
-
|
|
288
|
-
const fn = p.unrenderItem;
|
|
289
|
-
p.virtualListHelper.setOnItemUnrender((el) => {
|
|
290
|
-
try {
|
|
291
|
-
fn(el[ItemSymbol$1][ItemSymbol$1], el);
|
|
292
|
-
} catch (err) {
|
|
293
|
-
console.error(err); // eslint-disable-line no-console
|
|
294
|
-
}
|
|
295
|
-
delete el[ItemSymbol$1];
|
|
296
|
-
|
|
297
|
-
if (p.focusItemEl === el)
|
|
298
|
-
p.focusItemEl = null;
|
|
299
|
-
});
|
|
300
|
-
} else {
|
|
301
|
-
p.virtualListHelper.setOnItemUnrender((el) => {
|
|
302
|
-
delete el[ItemSymbol$1];
|
|
303
|
-
|
|
304
|
-
if (p.focusItemEl === el)
|
|
305
|
-
p.focusItemEl = null;
|
|
306
|
-
});
|
|
307
|
-
}
|
|
405
|
+
this._setupUnrenderFunction();
|
|
308
406
|
|
|
309
407
|
if (p.capturesFocus) {
|
|
310
|
-
|
|
408
|
+
wrapperEl.tabIndex = 0;
|
|
311
409
|
}
|
|
312
410
|
|
|
411
|
+
this.setFilterThrottleWindow(o.filterThrottleWindow);
|
|
412
|
+
this.setNoResultsText(o.noResultsText);
|
|
413
|
+
|
|
313
414
|
this._hookMouseEvents();
|
|
314
415
|
this._hookTouchEvents();
|
|
315
416
|
this._hookFocusEvents();
|
|
316
417
|
this._hookKeyEvents();
|
|
418
|
+
this._hookSearchEvents();
|
|
317
419
|
|
|
318
420
|
this.silenceEvents = false;
|
|
319
421
|
}
|
|
@@ -331,7 +433,7 @@ class DropList {
|
|
|
331
433
|
p.sink.remove();
|
|
332
434
|
p.virtualListHelper.destroy();
|
|
333
435
|
|
|
334
|
-
if (p.el) {
|
|
436
|
+
if (p.el?.parentNode) {
|
|
335
437
|
DomCompat.remove(p.el);
|
|
336
438
|
}
|
|
337
439
|
|
|
@@ -340,13 +442,15 @@ class DropList {
|
|
|
340
442
|
p.currentSubDropList = null;
|
|
341
443
|
}
|
|
342
444
|
|
|
445
|
+
if (p.throttledRefilterItems)
|
|
446
|
+
p.throttledRefilterItems.cancel();
|
|
447
|
+
|
|
343
448
|
if (!p.ownsEl) {
|
|
344
449
|
for (let name of Array.from(p.el.classList)) {
|
|
345
450
|
if (name.startsWith(p.baseClassName)) {
|
|
346
451
|
p.el.classList.remove(name);
|
|
347
452
|
}
|
|
348
453
|
}
|
|
349
|
-
p.el.removeAttribute('role');
|
|
350
454
|
for (let key of ['position', 'left', 'top', 'right', 'bottom', 'z-index']) {
|
|
351
455
|
p.el.style[key] = '';
|
|
352
456
|
}
|
|
@@ -361,6 +465,8 @@ class DropList {
|
|
|
361
465
|
delete p.lastPositionTarget;
|
|
362
466
|
}
|
|
363
467
|
|
|
468
|
+
delete p.lastPositionOptions;
|
|
469
|
+
|
|
364
470
|
this._p = null;
|
|
365
471
|
}
|
|
366
472
|
|
|
@@ -444,16 +550,47 @@ class DropList {
|
|
|
444
550
|
*/
|
|
445
551
|
setUnrenderItem(fn) {
|
|
446
552
|
const p = this._p;
|
|
447
|
-
|
|
448
553
|
p.unrenderItem = fn;
|
|
554
|
+
this._setupUnrenderFunction();
|
|
555
|
+
return this;
|
|
556
|
+
}
|
|
449
557
|
|
|
450
|
-
|
|
558
|
+
/**
|
|
559
|
+
* @param {(function(item: DropList.ItemBase, itemEl: Element):(*|false))|null} render
|
|
560
|
+
* @param {(function(item: DropList.ItemBase, itemEl: Element))|null} unrender
|
|
561
|
+
* @returns {DropList}
|
|
562
|
+
*/
|
|
563
|
+
setRenderNoResultsItem(render, unrender) {
|
|
564
|
+
const p = this._p;
|
|
565
|
+
p.renderNoResultsItem = render;
|
|
566
|
+
p.unrenderNoResultsItem = unrender;
|
|
567
|
+
this._setupUnrenderFunction();
|
|
568
|
+
return this;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* @private
|
|
573
|
+
*/
|
|
574
|
+
_setupUnrenderFunction() {
|
|
575
|
+
const p = this._p;
|
|
576
|
+
|
|
577
|
+
if (typeof p.unrenderItem === 'function' || typeof p.unrenderNoResultsItem === 'function') {
|
|
451
578
|
const fn = p.unrenderItem;
|
|
579
|
+
const fnNoResults = p.unrenderNoResultsItem;
|
|
452
580
|
p.virtualListHelper.setOnItemUnrender((el) => {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
581
|
+
const item = el[ItemSymbol$1];
|
|
582
|
+
if (item === NoResultsItemSymbol) {
|
|
583
|
+
try {
|
|
584
|
+
fnNoResults(item, el);
|
|
585
|
+
} catch (err) {
|
|
586
|
+
console.error(err); // eslint-disable-line no-console
|
|
587
|
+
}
|
|
588
|
+
} else {
|
|
589
|
+
try {
|
|
590
|
+
fn(item[ItemSymbol$1], el);
|
|
591
|
+
} catch (err) {
|
|
592
|
+
console.error(err); // eslint-disable-line no-console
|
|
593
|
+
}
|
|
457
594
|
}
|
|
458
595
|
delete el[ItemSymbol$1];
|
|
459
596
|
|
|
@@ -488,7 +625,8 @@ class DropList {
|
|
|
488
625
|
if (!el)
|
|
489
626
|
return;
|
|
490
627
|
|
|
491
|
-
|
|
628
|
+
const baseClass = p.baseClassName + '_wrapper';
|
|
629
|
+
let classes = [baseClass];
|
|
492
630
|
|
|
493
631
|
if (p.direction === 'ltr' || p.direction === 'rtl')
|
|
494
632
|
classes.push(`${p.baseClassName}__` + p.direction);
|
|
@@ -515,7 +653,8 @@ class DropList {
|
|
|
515
653
|
p.focusItemEl = null;
|
|
516
654
|
}
|
|
517
655
|
|
|
518
|
-
const
|
|
656
|
+
const items = p.filteredItems ?? p.items;
|
|
657
|
+
const item = items[p.focusItemIndex];
|
|
519
658
|
p.focusItemIndex = -1;
|
|
520
659
|
|
|
521
660
|
if (!item) {
|
|
@@ -666,9 +805,24 @@ class DropList {
|
|
|
666
805
|
}
|
|
667
806
|
}
|
|
668
807
|
|
|
669
|
-
p.
|
|
670
|
-
|
|
671
|
-
|
|
808
|
+
if (!p.filteredItems) {
|
|
809
|
+
let hadNoResultItem = p.hasNoResultsItem;
|
|
810
|
+
p.hasNoResultsItem = p.items.length === 0 && !!p.noResultsText;
|
|
811
|
+
if (p.hasNoResultsItem) {
|
|
812
|
+
p.virtualListHelper.
|
|
813
|
+
setCount(1).
|
|
814
|
+
render();
|
|
815
|
+
} else {
|
|
816
|
+
if (hadNoResultItem)
|
|
817
|
+
p.virtualListHelper.removeItemsAt(1, 0);
|
|
818
|
+
|
|
819
|
+
p.virtualListHelper.
|
|
820
|
+
addItemsAt(itemsToAdd.length, atIndex === -1 ? atIndex : atIndex - itemsToAdd.length).
|
|
821
|
+
render();
|
|
822
|
+
}
|
|
823
|
+
} else {
|
|
824
|
+
p.needsRefilter = true;
|
|
825
|
+
}
|
|
672
826
|
|
|
673
827
|
return this;
|
|
674
828
|
}
|
|
@@ -682,9 +836,11 @@ class DropList {
|
|
|
682
836
|
const p = this._p;
|
|
683
837
|
|
|
684
838
|
p.items.length = 0;
|
|
839
|
+
p.filteredItems = null;
|
|
685
840
|
p.groupCount = 0;
|
|
686
841
|
|
|
687
|
-
p.
|
|
842
|
+
p.hasNoResultsItem = !!p.noResultsText;
|
|
843
|
+
p.virtualListHelper.setCount(p.hasNoResultsItem ? 1 : 0);
|
|
688
844
|
|
|
689
845
|
this.addItems(items);
|
|
690
846
|
this.updateSublist();
|
|
@@ -735,9 +891,18 @@ class DropList {
|
|
|
735
891
|
if (hasOwnProperty.call(newItem, '_child'))
|
|
736
892
|
item._child = !!newItem._child;
|
|
737
893
|
|
|
738
|
-
|
|
894
|
+
let virtualItemIndex = itemIndex;
|
|
895
|
+
if (p.filteredItems) {
|
|
896
|
+
virtualItemIndex = p.filteredItems.indexOf(item);
|
|
897
|
+
if (virtualItemIndex !== -1) {
|
|
898
|
+
p.filteredItems.splice(virtualItemIndex, 1);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (virtualItemIndex !== -1 &&
|
|
903
|
+
p.virtualListHelper.isItemRendered(virtualItemIndex)) {
|
|
739
904
|
p.virtualListHelper.
|
|
740
|
-
refreshItemAt(
|
|
905
|
+
refreshItemAt(virtualItemIndex).
|
|
741
906
|
render();
|
|
742
907
|
}
|
|
743
908
|
|
|
@@ -756,9 +921,27 @@ class DropList {
|
|
|
756
921
|
p.groupCount--;
|
|
757
922
|
}
|
|
758
923
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
924
|
+
let virtualItemIndex = itemIndex;
|
|
925
|
+
if (p.filteredItems) {
|
|
926
|
+
virtualItemIndex = p.filteredItems.indexOf(spliced[0]);
|
|
927
|
+
if (virtualItemIndex !== -1) {
|
|
928
|
+
p.filteredItems.splice(virtualItemIndex, 1);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
if (virtualItemIndex !== -1) {
|
|
933
|
+
p.hasNoResultsItem = (p.filteredItems ?? p.items).length === 0 && !!p.noResultsText;
|
|
934
|
+
|
|
935
|
+
if (p.hasNoResultsItem) {
|
|
936
|
+
p.virtualListHelper.
|
|
937
|
+
setCount(1).
|
|
938
|
+
render();
|
|
939
|
+
} else {
|
|
940
|
+
p.virtualListHelper.
|
|
941
|
+
removeItemsAt(virtualItemIndex, 1).
|
|
942
|
+
render();
|
|
943
|
+
}
|
|
944
|
+
}
|
|
762
945
|
|
|
763
946
|
return this;
|
|
764
947
|
}
|
|
@@ -767,10 +950,13 @@ class DropList {
|
|
|
767
950
|
const p = this._p;
|
|
768
951
|
|
|
769
952
|
p.items.length = 0;
|
|
953
|
+
p.filteredItems = null;
|
|
770
954
|
p.groupCount = 0;
|
|
771
955
|
|
|
956
|
+
p.hasNoResultsItem = !!p.noResultsText;
|
|
957
|
+
|
|
772
958
|
p.virtualListHelper.
|
|
773
|
-
setCount(0).
|
|
959
|
+
setCount(p.hasNoResultsItem ? 1 : 0).
|
|
774
960
|
render();
|
|
775
961
|
|
|
776
962
|
return this;
|
|
@@ -806,8 +992,23 @@ class DropList {
|
|
|
806
992
|
itemIndexByValue(value) {
|
|
807
993
|
const p = this._p;
|
|
808
994
|
|
|
809
|
-
|
|
810
|
-
|
|
995
|
+
const items = p.items;
|
|
996
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
997
|
+
let item = items[i];
|
|
998
|
+
if (item.value === value) {
|
|
999
|
+
return i;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
return -1;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
filteredItemIndexByValue(value) {
|
|
1007
|
+
const p = this._p;
|
|
1008
|
+
|
|
1009
|
+
const items = p.filteredItems ?? p.items;
|
|
1010
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1011
|
+
let item = items[i];
|
|
811
1012
|
if (item.value === value) {
|
|
812
1013
|
return i;
|
|
813
1014
|
}
|
|
@@ -819,8 +1020,23 @@ class DropList {
|
|
|
819
1020
|
itemIndexByValueOrLabel(value, label) {
|
|
820
1021
|
const p = this._p;
|
|
821
1022
|
|
|
822
|
-
|
|
823
|
-
|
|
1023
|
+
const items = p.items;
|
|
1024
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1025
|
+
let item = items[i];
|
|
1026
|
+
if (item.value === value || item.label === label) {
|
|
1027
|
+
return i;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
return -1;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
filteredItemIndexByValueOrLabel(value, label) {
|
|
1035
|
+
const p = this._p;
|
|
1036
|
+
|
|
1037
|
+
const items = p.filteredItems ?? p.items;
|
|
1038
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1039
|
+
let item = items[i];
|
|
824
1040
|
if (item.value === value || item.label === label) {
|
|
825
1041
|
return i;
|
|
826
1042
|
}
|
|
@@ -829,6 +1045,36 @@ class DropList {
|
|
|
829
1045
|
return -1;
|
|
830
1046
|
}
|
|
831
1047
|
|
|
1048
|
+
itemIndexByItem(item) {
|
|
1049
|
+
const p = this._p;
|
|
1050
|
+
|
|
1051
|
+
const items = p.items;
|
|
1052
|
+
|
|
1053
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1054
|
+
let it = items[i];
|
|
1055
|
+
if (it[ItemSymbol$1] === item) {
|
|
1056
|
+
return i;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
return -1;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
filteredItemIndexByItem(item) {
|
|
1064
|
+
const p = this._p;
|
|
1065
|
+
|
|
1066
|
+
const items = p.filteredItems ?? p.items;
|
|
1067
|
+
|
|
1068
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1069
|
+
let it = items[i];
|
|
1070
|
+
if (it[ItemSymbol$1] === item) {
|
|
1071
|
+
return i;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
return -1;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
832
1078
|
items() {
|
|
833
1079
|
return this._p.items.map((x) => x[ItemSymbol$1]);
|
|
834
1080
|
}
|
|
@@ -845,19 +1091,320 @@ class DropList {
|
|
|
845
1091
|
return this._p.items[index]?.[ItemSymbol$1];
|
|
846
1092
|
}
|
|
847
1093
|
|
|
1094
|
+
filteredItemAtIndex(index) {
|
|
1095
|
+
const p = this._p;
|
|
1096
|
+
const items = p.filteredItems ?? p.items;
|
|
1097
|
+
return items[index]?.[ItemSymbol$1];
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* @param {function(dropList: DropList):DropList.PositionOptions} fn
|
|
1102
|
+
* @returns {DropList}
|
|
1103
|
+
*/
|
|
1104
|
+
setPositionOptionsProvider(fn) {
|
|
1105
|
+
const p = this._p;
|
|
1106
|
+
if (p.positionOptionsProvider === fn)
|
|
1107
|
+
return this;
|
|
1108
|
+
p.positionOptionsProvider = fn ?? null;
|
|
1109
|
+
this.relayout();
|
|
1110
|
+
return this;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* @returns {function(dropList: DropList):DropList.PositionOptions|null}
|
|
1115
|
+
*/
|
|
1116
|
+
getPositionOptionsProvider() {
|
|
1117
|
+
const p = this._p;
|
|
1118
|
+
return p.positionOptionsProvider;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* @param {string} term
|
|
1123
|
+
* @param {boolean} [performSearch=false] should actually perform the search, or just set the input's text?
|
|
1124
|
+
* @returns {DropList}
|
|
1125
|
+
*/
|
|
1126
|
+
setSearchTerm(term) {let performSearch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1127
|
+
const p = this._p;
|
|
1128
|
+
|
|
1129
|
+
if (p.searchInput) {
|
|
1130
|
+
p.searchInput.value = term;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
if (performSearch) {
|
|
1134
|
+
p.filterTerm = term.trim();
|
|
1135
|
+
p.filteredItems = null;
|
|
1136
|
+
|
|
1137
|
+
this._trigger('search', { value: term });
|
|
1138
|
+
p.throttledRefilterItems();
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
return this;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
isFilterPending() {
|
|
1145
|
+
const p = this._p;
|
|
1146
|
+
|
|
1147
|
+
return !!(p.throttledRefilterItems.isScheduled() ||
|
|
1148
|
+
!p.filteredItems && (p.filterTerm || p.filterOnEmptyTerm && p.filterFn));
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/** @private */
|
|
1152
|
+
_refilterItems() {
|
|
1153
|
+
const p = this._p;
|
|
1154
|
+
|
|
1155
|
+
const term = p.filterTerm;
|
|
1156
|
+
const filterGroups = p.filterGroups;
|
|
1157
|
+
const filterEmptyGroups = p.filterEmptyGroups;
|
|
1158
|
+
|
|
1159
|
+
if (term || p.filterOnEmptyTerm && p.filterFn) {
|
|
1160
|
+
let fn = p.filterFn;
|
|
1161
|
+
|
|
1162
|
+
let filteredItems;
|
|
1163
|
+
|
|
1164
|
+
if (typeof fn === 'function') {
|
|
1165
|
+
filteredItems = p.filterFn(p.items, term);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// If there was no filter function, or it gave up on filtering.
|
|
1169
|
+
if (!Array.isArray(filteredItems)) {
|
|
1170
|
+
if (term) {
|
|
1171
|
+
const matcher = new RegExp(escapeRegex(term), 'i');
|
|
1172
|
+
const labelProp = p.labelProp;
|
|
1173
|
+
|
|
1174
|
+
filteredItems = p.items.filter((x) => {
|
|
1175
|
+
if (!filterGroups && x._group) return true;
|
|
1176
|
+
return matcher.test(x[labelProp]);
|
|
1177
|
+
});
|
|
1178
|
+
} else {
|
|
1179
|
+
filteredItems = null;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
p.filteredItems = filteredItems;
|
|
1184
|
+
|
|
1185
|
+
if (filteredItems && filterEmptyGroups) {
|
|
1186
|
+
// Clean up groups without children
|
|
1187
|
+
|
|
1188
|
+
let lastGroup = -1;
|
|
1189
|
+
let len = filteredItems.length;
|
|
1190
|
+
|
|
1191
|
+
for (let i = 0; i < len; i++) {
|
|
1192
|
+
let item = filteredItems[i];
|
|
1193
|
+
|
|
1194
|
+
if (item._group) {
|
|
1195
|
+
if (lastGroup !== -1 && lastGroup === i - 1) {
|
|
1196
|
+
// It was an empty group
|
|
1197
|
+
filteredItems.splice(lastGroup, 1);
|
|
1198
|
+
i--;
|
|
1199
|
+
len--;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
lastGroup = i;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
if (lastGroup !== -1) {
|
|
1207
|
+
if (lastGroup === len - 1) {
|
|
1208
|
+
// It was an empty group
|
|
1209
|
+
filteredItems.splice(lastGroup, 1);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
} else {
|
|
1214
|
+
p.filteredItems = null;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
this.needsRefilter = false;
|
|
1218
|
+
|
|
1219
|
+
const items = p.filteredItems ?? p.items;
|
|
1220
|
+
p.hasNoResultsItem = items.length === 0 && !!p.noResultsText;
|
|
1221
|
+
p.virtualListHelper.
|
|
1222
|
+
setCount(items.length + (p.hasNoResultsItem ? 1 : 0)).
|
|
1223
|
+
render();
|
|
1224
|
+
|
|
1225
|
+
this._trigger('itemschanged', { term: term, mutated: false, count: this.getFilteredItemCount() });
|
|
1226
|
+
this.relayout();
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
invokeRefilter() {
|
|
1230
|
+
const p = this._p;
|
|
1231
|
+
if (!p.filterTerm && !p.filterOnEmptyTerm && !p.filteredItems)
|
|
1232
|
+
return this;
|
|
1233
|
+
p.filteredItems = null;
|
|
1234
|
+
p.throttledRefilterItems();
|
|
1235
|
+
return this;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
getFilteredItemCount() {
|
|
1239
|
+
const p = this._p;
|
|
1240
|
+
|
|
1241
|
+
if (p.needsRefilter)
|
|
1242
|
+
this._refilterItems();
|
|
1243
|
+
|
|
1244
|
+
if (p.filteredItems)
|
|
1245
|
+
return p.filteredItems.length;
|
|
1246
|
+
|
|
1247
|
+
if (p.items)
|
|
1248
|
+
return p.items.length;
|
|
1249
|
+
|
|
1250
|
+
return 0;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
/**
|
|
1254
|
+
* @param {string} noResultsText
|
|
1255
|
+
* @returns {DropList}
|
|
1256
|
+
*/
|
|
1257
|
+
setNoResultsText(noResultsText) {
|
|
1258
|
+
this._p.noResultsText = noResultsText;
|
|
1259
|
+
return this;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* @returns {string}
|
|
1264
|
+
*/
|
|
1265
|
+
getNoResultsText() {
|
|
1266
|
+
return this._p.noResultsText;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* @param {number} window
|
|
1271
|
+
* @returns {DropList}
|
|
1272
|
+
*/
|
|
1273
|
+
setFilterThrottleWindow(window) {
|
|
1274
|
+
const p = this._p;
|
|
1275
|
+
p.filterThrottleWindow = window;
|
|
1276
|
+
|
|
1277
|
+
let isScheduled = p.throttledRefilterItems ? p.throttledRefilterItems.isScheduled() : false;
|
|
1278
|
+
|
|
1279
|
+
if (p.throttledRefilterItems)
|
|
1280
|
+
p.throttledRefilterItems.cancel();
|
|
1281
|
+
|
|
1282
|
+
p.throttledRefilterItems = throttle(() => this._refilterItems(), p.filterThrottleWindow, true);
|
|
1283
|
+
|
|
1284
|
+
if (isScheduled)
|
|
1285
|
+
p.throttledRefilterItems();
|
|
1286
|
+
|
|
1287
|
+
return this;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
/**
|
|
1291
|
+
* @returns {number}
|
|
1292
|
+
*/
|
|
1293
|
+
getFilterThrottleWindow() {
|
|
1294
|
+
return this._p.filterThrottleWindow;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
/**
|
|
1298
|
+
* @param {boolean} value
|
|
1299
|
+
* @returns {DropList}
|
|
1300
|
+
*/
|
|
1301
|
+
setFilterOnEmptyTerm(value) {
|
|
1302
|
+
const p = this._p;
|
|
1303
|
+
if (p.filterOnEmptyTerm === value)
|
|
1304
|
+
return this;
|
|
1305
|
+
p.filterOnEmptyTerm = value;
|
|
1306
|
+
p.throttledRefilterItems();
|
|
1307
|
+
return this;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* @returns {boolean}
|
|
1312
|
+
*/
|
|
1313
|
+
getFilterOnEmptyTerm() {
|
|
1314
|
+
return this._p.filterOnEmptyTerm;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* @param {boolean} value
|
|
1319
|
+
* @returns {DropList}
|
|
1320
|
+
*/
|
|
1321
|
+
setFilterGroups(value) {
|
|
1322
|
+
const p = this._p;
|
|
1323
|
+
if (p.filterGroups === value)
|
|
1324
|
+
return this;
|
|
1325
|
+
p.filterGroups = value;
|
|
1326
|
+
p.throttledRefilterItems();
|
|
1327
|
+
return this;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* @returns {boolean}
|
|
1332
|
+
*/
|
|
1333
|
+
getFilterGroups() {
|
|
1334
|
+
return this._p.filterGroups;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* @param {boolean} value
|
|
1339
|
+
* @returns {DropList}
|
|
1340
|
+
*/
|
|
1341
|
+
setFilterEmptyGroups(value) {
|
|
1342
|
+
const p = this._p;
|
|
1343
|
+
if (p.filterEmptyGroups === value)
|
|
1344
|
+
return this;
|
|
1345
|
+
p.filterEmptyGroups = value;
|
|
1346
|
+
p.throttledRefilterItems();
|
|
1347
|
+
return this;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
/**
|
|
1351
|
+
* @returns {boolean}
|
|
1352
|
+
*/
|
|
1353
|
+
getFilterEmptyGroups() {
|
|
1354
|
+
return this._p.filterEmptyGroups;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
/**
|
|
1358
|
+
* @param {function(items: DropList.ItemBase[], term: string):(DropList.ItemBase[]|null)} fn
|
|
1359
|
+
* @returns {DropList}
|
|
1360
|
+
*/
|
|
1361
|
+
setFilterFn(fn) {
|
|
1362
|
+
const p = this._p;
|
|
1363
|
+
if (p.filterFn === fn)
|
|
1364
|
+
return this;
|
|
1365
|
+
p.filterFn = fn;
|
|
1366
|
+
p.throttledRefilterItems();
|
|
1367
|
+
return this;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/**
|
|
1371
|
+
* @returns {function(items: DropList.ItemBase[], term: string):(DropList.ItemBase[]|null)}
|
|
1372
|
+
*/
|
|
1373
|
+
getFilterFn() {
|
|
1374
|
+
return this._p.filterFn;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
848
1377
|
/**
|
|
849
1378
|
*
|
|
850
|
-
* @param {DropList.PositionOptions} positionOptions
|
|
1379
|
+
* @param {DropList.PositionOptions} [positionOptions]
|
|
851
1380
|
* @returns {DropList}
|
|
852
1381
|
* @public
|
|
853
1382
|
*/
|
|
854
1383
|
relayout(positionOptions) {
|
|
855
|
-
const p = this._p,el = p.el;
|
|
1384
|
+
const p = this._p,el = p.el,menuEl = p.menuEl;
|
|
856
1385
|
|
|
857
1386
|
if (!this.isVisible()) return this;
|
|
858
1387
|
|
|
859
1388
|
let w = window;
|
|
860
1389
|
|
|
1390
|
+
if (!positionOptions)
|
|
1391
|
+
positionOptions = p.positionOptionsProvider?.() ?? p.lastPositionOptions;
|
|
1392
|
+
|
|
1393
|
+
// Supply some default for extreme cases, no crashing
|
|
1394
|
+
if (!positionOptions) {
|
|
1395
|
+
positionOptions = {
|
|
1396
|
+
targetOffset: {
|
|
1397
|
+
left: window.innerWidth / 2,
|
|
1398
|
+
top: window.innerHeight / 2
|
|
1399
|
+
},
|
|
1400
|
+
targetWidth: 0,
|
|
1401
|
+
targetHeight: 0,
|
|
1402
|
+
position: { x: 'center', y: 'center' },
|
|
1403
|
+
anchor: { x: 'center', y: 'center' },
|
|
1404
|
+
targetRtl: getComputedStyle(document.body).direction === 'rtl'
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
|
|
861
1408
|
let targetBox = {};
|
|
862
1409
|
|
|
863
1410
|
let offset = positionOptions.targetOffset || Css.getElementOffset(positionOptions.target);
|
|
@@ -920,18 +1467,25 @@ class DropList {
|
|
|
920
1467
|
let verticalBorderWidth = (parseFloat(elComputedStyle.borderTopWidth) || 0) + (
|
|
921
1468
|
parseFloat(elComputedStyle.borderBottomWidth) || 0);
|
|
922
1469
|
|
|
1470
|
+
let headerHeight = 0;
|
|
1471
|
+
if (p.headerEl) {
|
|
1472
|
+
headerHeight = Css.getElementHeight(p.headerEl, true, true);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
923
1475
|
if (p.virtualListHelper.isVirtual()) {
|
|
924
1476
|
maxViewHeight =
|
|
925
1477
|
p.virtualListHelper.estimateFullHeight() +
|
|
926
1478
|
verticalPadding +
|
|
927
|
-
verticalBorderWidth
|
|
1479
|
+
verticalBorderWidth +
|
|
1480
|
+
headerHeight;
|
|
928
1481
|
} else {
|
|
929
1482
|
// Another method to calculate height is measuring the whole thing at once.
|
|
930
1483
|
// This causes relayout of course.
|
|
931
1484
|
el.style.height = '';
|
|
1485
|
+
menuEl.style.height = '';
|
|
932
1486
|
el.style.top = '-9999px';
|
|
933
1487
|
|
|
934
|
-
maxViewHeight = Math.max(Css.getElementHeight(p.el),
|
|
1488
|
+
maxViewHeight = Math.max(Css.getElementHeight(p.el), menuEl.scrollHeight);
|
|
935
1489
|
maxViewHeight += verticalPadding + verticalBorderWidth;
|
|
936
1490
|
}
|
|
937
1491
|
|
|
@@ -1066,6 +1620,11 @@ class DropList {
|
|
|
1066
1620
|
Css.setCssProps(el, viewCss);
|
|
1067
1621
|
Css.setElementHeight(el, viewSize.height, true, true);
|
|
1068
1622
|
|
|
1623
|
+
if (menuEl !== el) {
|
|
1624
|
+
let menuHeight = viewSize.height - headerHeight - verticalBorderWidth - verticalPadding;
|
|
1625
|
+
Css.setElementHeight(menuEl, menuHeight, true, true);
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1069
1628
|
// Update the scroll position for virtual lists
|
|
1070
1629
|
p.virtualListHelper.render();
|
|
1071
1630
|
|
|
@@ -1203,7 +1762,7 @@ class DropList {
|
|
|
1203
1762
|
|
|
1204
1763
|
/**
|
|
1205
1764
|
*
|
|
1206
|
-
* @param {DropList.PositionOptions?} positionOptions
|
|
1765
|
+
* @param {DropList.PositionOptions?} [positionOptions]
|
|
1207
1766
|
* @returns {DropList}
|
|
1208
1767
|
* @public
|
|
1209
1768
|
*/
|
|
@@ -1230,6 +1789,10 @@ class DropList {
|
|
|
1230
1789
|
}
|
|
1231
1790
|
});
|
|
1232
1791
|
|
|
1792
|
+
if (p.needsRefilter) {
|
|
1793
|
+
this._refilterItems();
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1233
1796
|
const el = p.el;
|
|
1234
1797
|
el.style.position = 'absolute';
|
|
1235
1798
|
el.classList.remove(`${p.baseClassName}__is-hiding`);
|
|
@@ -1241,6 +1804,14 @@ class DropList {
|
|
|
1241
1804
|
if (getComputedStyle(p.el).display === 'none')
|
|
1242
1805
|
p.el.style.display = 'block';
|
|
1243
1806
|
|
|
1807
|
+
p.lastPositionOptions = null;
|
|
1808
|
+
|
|
1809
|
+
if (positionOptions === undefined) {
|
|
1810
|
+
positionOptions = p.positionOptionsProvider?.() ?? p.lastPositionOptions;
|
|
1811
|
+
} else {
|
|
1812
|
+
p.lastPositionOptions = positionOptions;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1244
1815
|
if (positionOptions) {
|
|
1245
1816
|
const elComputedStyle = getComputedStyle(el);
|
|
1246
1817
|
|
|
@@ -1287,6 +1858,11 @@ class DropList {
|
|
|
1287
1858
|
|
|
1288
1859
|
p.hiding = true;
|
|
1289
1860
|
|
|
1861
|
+
if (this.isFilterPending()) {
|
|
1862
|
+
p.throttledRefilterItems.cancel();
|
|
1863
|
+
p.needsRefilter = true;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1290
1866
|
if (el) {
|
|
1291
1867
|
|
|
1292
1868
|
el.classList.add(`${p.baseClassName}__is-hiding`);
|
|
@@ -1307,6 +1883,7 @@ class DropList {
|
|
|
1307
1883
|
}
|
|
1308
1884
|
});
|
|
1309
1885
|
} else {
|
|
1886
|
+
if (el.parentNode)
|
|
1310
1887
|
DomCompat.remove(el);
|
|
1311
1888
|
el.classList.remove(`${p.baseClassName}__is-hiding`);
|
|
1312
1889
|
}
|
|
@@ -1356,15 +1933,22 @@ class DropList {
|
|
|
1356
1933
|
setFocusedItemAtIndex(itemIndex) {
|
|
1357
1934
|
const p = this._p;
|
|
1358
1935
|
|
|
1936
|
+
if (p.filteredItems) {
|
|
1937
|
+
const item = p.items[itemIndex];
|
|
1938
|
+
itemIndex = p.items.indexOf(item);
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1359
1941
|
p.focusItemIndex = itemIndex;
|
|
1360
1942
|
|
|
1943
|
+
const items = p.filteredItems ?? p.items;
|
|
1944
|
+
|
|
1361
1945
|
let item = null;
|
|
1362
1946
|
if (itemIndex > -1)
|
|
1363
|
-
item =
|
|
1947
|
+
item = items[itemIndex];
|
|
1364
1948
|
if (item && item._nointeraction)
|
|
1365
1949
|
item = null;
|
|
1366
1950
|
if (itemIndex > -1) {
|
|
1367
|
-
this.
|
|
1951
|
+
this._scrollItemIndexIntoView(itemIndex);
|
|
1368
1952
|
}
|
|
1369
1953
|
let itemElement = item ? p.virtualListHelper.getItemElementAt(itemIndex) : null;
|
|
1370
1954
|
|
|
@@ -1418,7 +2002,8 @@ class DropList {
|
|
|
1418
2002
|
labelProp: p.labelProp,
|
|
1419
2003
|
valueProp: p.valueProp,
|
|
1420
2004
|
renderItem: p.renderItem,
|
|
1421
|
-
unrenderItem: p.unrenderItem
|
|
2005
|
+
unrenderItem: p.unrenderItem,
|
|
2006
|
+
positionOptionsProvider: () => p.currentSubDropList.showOptions
|
|
1422
2007
|
});
|
|
1423
2008
|
|
|
1424
2009
|
let onBlur = (event) => {
|
|
@@ -1466,7 +2051,7 @@ class DropList {
|
|
|
1466
2051
|
}
|
|
1467
2052
|
};
|
|
1468
2053
|
|
|
1469
|
-
droplist.show(
|
|
2054
|
+
droplist.show();
|
|
1470
2055
|
|
|
1471
2056
|
droplist.el.focus();
|
|
1472
2057
|
}
|
|
@@ -1520,7 +2105,7 @@ class DropList {
|
|
|
1520
2105
|
|
|
1521
2106
|
if (itemElement) {
|
|
1522
2107
|
p.currentSubDropList.showOptions.target = itemElement;
|
|
1523
|
-
p.currentSubDropList.droplist.relayout(
|
|
2108
|
+
p.currentSubDropList.droplist.relayout();
|
|
1524
2109
|
}
|
|
1525
2110
|
}
|
|
1526
2111
|
}
|
|
@@ -1531,7 +2116,8 @@ class DropList {
|
|
|
1531
2116
|
|
|
1532
2117
|
let itemIndex = item._nointeraction ? -1 : this._getItemIndex(item);
|
|
1533
2118
|
|
|
1534
|
-
|
|
2119
|
+
const items = p.items;
|
|
2120
|
+
if (itemIndex > -1 && items[itemIndex]._nointeraction)
|
|
1535
2121
|
itemIndex = -1;
|
|
1536
2122
|
|
|
1537
2123
|
return this.setFocusedItemAtIndex(itemIndex);
|
|
@@ -1547,7 +2133,14 @@ class DropList {
|
|
|
1547
2133
|
let itemEl = null;
|
|
1548
2134
|
|
|
1549
2135
|
if (itemIndex > -1 && !p.items[itemIndex]._nointeraction) {
|
|
1550
|
-
|
|
2136
|
+
if (p.filteredItems) {
|
|
2137
|
+
const item = p.items[itemIndex];
|
|
2138
|
+
itemIndex = p.filteredItems.indexOf(item);
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
if (itemIndex > -1) {
|
|
2142
|
+
itemEl = p.virtualListHelper.getItemElementAt(itemIndex);
|
|
2143
|
+
}
|
|
1551
2144
|
}
|
|
1552
2145
|
|
|
1553
2146
|
this._setSingleSelectedItemEl(itemEl);
|
|
@@ -1560,7 +2153,8 @@ class DropList {
|
|
|
1560
2153
|
|
|
1561
2154
|
let itemIndex = item._nointeraction ? -1 : this._getItemIndex(item);
|
|
1562
2155
|
|
|
1563
|
-
|
|
2156
|
+
const items = p.items;
|
|
2157
|
+
if (itemIndex > -1 && items[itemIndex]._nointeraction)
|
|
1564
2158
|
itemIndex = -1;
|
|
1565
2159
|
|
|
1566
2160
|
return this.setSingleSelectedItemAtIndex(itemIndex);
|
|
@@ -1580,24 +2174,42 @@ class DropList {
|
|
|
1580
2174
|
|
|
1581
2175
|
isFirstItem() {
|
|
1582
2176
|
const p = this._p;
|
|
1583
|
-
|
|
2177
|
+
const items = p.filteredItems ?? p.items;
|
|
2178
|
+
return p.focusItemIndex === 0 && p.focusItemIndex < items.length;
|
|
1584
2179
|
}
|
|
1585
2180
|
|
|
1586
2181
|
isLastItem() {
|
|
1587
2182
|
const p = this._p;
|
|
1588
|
-
|
|
2183
|
+
const items = p.filteredItems ?? p.items;
|
|
2184
|
+
return p.focusItemIndex > -1 && p.focusItemIndex === items.length - 1;
|
|
1589
2185
|
}
|
|
1590
2186
|
|
|
1591
2187
|
scrollItemIndexIntoView(itemIndex) {
|
|
1592
2188
|
const p = this._p;
|
|
1593
2189
|
|
|
2190
|
+
if (this._hasScroll()) {
|
|
2191
|
+
if (p.filteredItems) {
|
|
2192
|
+
const item = p.items[itemIndex];
|
|
2193
|
+
itemIndex = p.items.indexOf(item);
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
if (itemIndex !== -1) {
|
|
2197
|
+
this._scrollItemIndexIntoView(itemIndex);
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
return this;
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
_scrollItemIndexIntoView(itemIndex) {
|
|
2205
|
+
const p = this._p;
|
|
2206
|
+
|
|
1594
2207
|
if (this._hasScroll()) {
|
|
1595
2208
|
const el = p.el,scrollTop = el.scrollTop;
|
|
1596
2209
|
|
|
1597
2210
|
let itemPos,previousPos = -1;
|
|
1598
2211
|
let maxIterations = 30; // Some zoom/scroll issues can make it so that it takes almost forever
|
|
1599
2212
|
|
|
1600
|
-
|
|
1601
2213
|
while (maxIterations-- > 0) {
|
|
1602
2214
|
itemPos = p.virtualListHelper.getItemPosition(itemIndex);
|
|
1603
2215
|
|
|
@@ -1620,8 +2232,6 @@ class DropList {
|
|
|
1620
2232
|
p.virtualListHelper.render();
|
|
1621
2233
|
}
|
|
1622
2234
|
}
|
|
1623
|
-
|
|
1624
|
-
return this;
|
|
1625
2235
|
}
|
|
1626
2236
|
|
|
1627
2237
|
/**
|
|
@@ -1682,7 +2292,8 @@ class DropList {
|
|
|
1682
2292
|
let itemIndex = -1;
|
|
1683
2293
|
|
|
1684
2294
|
if (item) {
|
|
1685
|
-
|
|
2295
|
+
const items = p.filteredItems ?? p.items;
|
|
2296
|
+
itemIndex = items.indexOf(item);
|
|
1686
2297
|
if (itemIndex === -1) {
|
|
1687
2298
|
let value = item && item.value !== undefined ? item.value : item;
|
|
1688
2299
|
let label = item && item.label ? item.label : value;
|
|
@@ -1830,12 +2441,25 @@ class DropList {
|
|
|
1830
2441
|
|
|
1831
2442
|
p.sink.
|
|
1832
2443
|
add(p.el, 'focus', (event) => {
|
|
2444
|
+
if (event.target === this.el && p.searchable)
|
|
2445
|
+
p.searchInput.focus();
|
|
2446
|
+
|
|
2447
|
+
if (event.relatedTarget &&
|
|
2448
|
+
this.elContains(event.relatedTarget, true) &&
|
|
2449
|
+
this.elContains(event.target, true))
|
|
2450
|
+
return;
|
|
2451
|
+
|
|
1833
2452
|
let itemEl = p.focusItemEl || // focused item
|
|
1834
2453
|
p.el.firstChild; // or the first item
|
|
1835
2454
|
|
|
1836
2455
|
this._focus(event, itemEl, null, false);
|
|
1837
|
-
}).
|
|
2456
|
+
}, true).
|
|
1838
2457
|
add(p.el, 'blur', (event) => {
|
|
2458
|
+
if (event.relatedTarget &&
|
|
2459
|
+
this.elContains(event.relatedTarget, true) &&
|
|
2460
|
+
this.elContains(event.target, true))
|
|
2461
|
+
return;
|
|
2462
|
+
|
|
1839
2463
|
setTimeout(() => {
|
|
1840
2464
|
if (this[DestroyedSymbol$1]) return;
|
|
1841
2465
|
|
|
@@ -1846,7 +2470,7 @@ class DropList {
|
|
|
1846
2470
|
this._delayBlurItemOnBlur();
|
|
1847
2471
|
this._trigger('blur', event);
|
|
1848
2472
|
});
|
|
1849
|
-
});
|
|
2473
|
+
}, true);
|
|
1850
2474
|
}
|
|
1851
2475
|
|
|
1852
2476
|
_hookKeyEvents() {
|
|
@@ -1855,6 +2479,21 @@ class DropList {
|
|
|
1855
2479
|
p.sink.add(p.el, 'keydown', (evt) => this._keydown(evt));
|
|
1856
2480
|
}
|
|
1857
2481
|
|
|
2482
|
+
_hookSearchEvents() {
|
|
2483
|
+
const p = this._p;
|
|
2484
|
+
|
|
2485
|
+
if (!p.searchInput)
|
|
2486
|
+
return;
|
|
2487
|
+
|
|
2488
|
+
p.sink.add(p.searchInput, 'input', () => {
|
|
2489
|
+
p.filterTerm = p.searchInput.value.trim();
|
|
2490
|
+
p.filteredItems = null;
|
|
2491
|
+
|
|
2492
|
+
this._trigger('search', { value: p.searchInput.value });
|
|
2493
|
+
p.throttledRefilterItems();
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
|
|
1858
2497
|
_keydown(event) {
|
|
1859
2498
|
const p = this._p;
|
|
1860
2499
|
|
|
@@ -1899,7 +2538,8 @@ class DropList {
|
|
|
1899
2538
|
case keycodeJs.VALUE_RIGHT:
|
|
1900
2539
|
if (event.key === keycodeJs.VALUE_RIGHT && getComputedStyle(event.target).direction !== 'rtl' ||
|
|
1901
2540
|
event.key === keycodeJs.VALUE_LEFT && getComputedStyle(event.target).direction === 'rtl') {
|
|
1902
|
-
|
|
2541
|
+
const items = p.filteredItems ?? p.items;
|
|
2542
|
+
let item = items[p.focusItemIndex];
|
|
1903
2543
|
if (p.focusItemIndex > -1 && item._subitems)
|
|
1904
2544
|
this._showSublist(item, p.focusItemEl);
|
|
1905
2545
|
} else {
|
|
@@ -1929,7 +2569,11 @@ class DropList {
|
|
|
1929
2569
|
|
|
1930
2570
|
default:{
|
|
1931
2571
|
if (event.type === 'keydown') return;
|
|
2572
|
+
|
|
2573
|
+
// Inline search box not available, then support typing to focus by first letters
|
|
2574
|
+
if (!p.searchable)
|
|
1932
2575
|
this._keydownFreeType(event);
|
|
2576
|
+
|
|
1933
2577
|
preventDefault = false;
|
|
1934
2578
|
}
|
|
1935
2579
|
}
|
|
@@ -1954,12 +2598,14 @@ class DropList {
|
|
|
1954
2598
|
|
|
1955
2599
|
let focusItemIndex = p.focusItemIndex;
|
|
1956
2600
|
|
|
2601
|
+
const items = p.filteredItems ?? p.items;
|
|
2602
|
+
|
|
1957
2603
|
// These are all the possible matches for the text typed in so far
|
|
1958
|
-
for (let i = 0, count =
|
|
2604
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1959
2605
|
if (matchIndex !== -1 && i < focusItemIndex)
|
|
1960
2606
|
continue; // We are only interested in first match + match after the focused item
|
|
1961
2607
|
|
|
1962
|
-
item =
|
|
2608
|
+
item = items[i];
|
|
1963
2609
|
if (regex.test(item.label)) {
|
|
1964
2610
|
matchIndex = i;
|
|
1965
2611
|
if (focusItemIndex === -1 || i >= focusItemIndex)
|
|
@@ -1973,11 +2619,11 @@ class DropList {
|
|
|
1973
2619
|
keyword = character;
|
|
1974
2620
|
regex = new RegExp(`^${escapeRegex(keyword)}`, 'i');
|
|
1975
2621
|
|
|
1976
|
-
for (let i = 0, count =
|
|
2622
|
+
for (let i = 0, count = items.length; i < count; i++) {
|
|
1977
2623
|
if (matchIndex !== -1 && i < focusItemIndex)
|
|
1978
2624
|
continue; // We are only interested in first match + match after the focused item
|
|
1979
2625
|
|
|
1980
|
-
item =
|
|
2626
|
+
item = items[i];
|
|
1981
2627
|
if (regex.test(item.label)) {
|
|
1982
2628
|
matchIndex = i;
|
|
1983
2629
|
if (focusItemIndex === -1 || i >= focusItemIndex)
|
|
@@ -1991,7 +2637,7 @@ class DropList {
|
|
|
1991
2637
|
this._focus(evt, next || null, matchIndex, true);
|
|
1992
2638
|
|
|
1993
2639
|
if (!this.isVisible()) {
|
|
1994
|
-
this.triggerItemSelection(next ? null :
|
|
2640
|
+
this.triggerItemSelection(next ? null : items[matchIndex], evt);
|
|
1995
2641
|
}
|
|
1996
2642
|
|
|
1997
2643
|
// Record the last filter used
|
|
@@ -2018,6 +2664,10 @@ class DropList {
|
|
|
2018
2664
|
itemIndex = p.virtualListHelper.getItemIndexFromElement(itemEl);
|
|
2019
2665
|
}
|
|
2020
2666
|
|
|
2667
|
+
if (itemIndex > -1 && itemEl?.[ItemSymbol$1]?.[ItemSymbol$1] === NoResultsItemSymbol) {
|
|
2668
|
+
itemIndex = undefined;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2021
2671
|
if (itemIndex > -1) {
|
|
2022
2672
|
this.scrollItemIndexIntoView(itemIndex);
|
|
2023
2673
|
} else if (itemIndex === undefined) {
|
|
@@ -2043,7 +2693,8 @@ class DropList {
|
|
|
2043
2693
|
p.focusItemEl = focusItemEl;
|
|
2044
2694
|
p.focusItemIndex = itemIndex;
|
|
2045
2695
|
|
|
2046
|
-
const
|
|
2696
|
+
const items = p.filteredItems ?? p.items;
|
|
2697
|
+
const item = items[itemIndex];
|
|
2047
2698
|
this._trigger('itemfocus', {
|
|
2048
2699
|
value: item.value,
|
|
2049
2700
|
item: item[ItemSymbol$1] ?? item,
|
|
@@ -2078,12 +2729,13 @@ class DropList {
|
|
|
2078
2729
|
const p = this._p;
|
|
2079
2730
|
|
|
2080
2731
|
let next,nextIndex,directionUp = false;
|
|
2732
|
+
const items = p.filteredItems ?? p.items;
|
|
2081
2733
|
|
|
2082
2734
|
if (direction === 'first') {
|
|
2083
2735
|
nextIndex = 0;
|
|
2084
2736
|
directionUp = false;
|
|
2085
2737
|
} else if (direction === 'last') {
|
|
2086
|
-
nextIndex =
|
|
2738
|
+
nextIndex = items.length - 1;
|
|
2087
2739
|
directionUp = true;
|
|
2088
2740
|
} else if (direction === 'prev') {
|
|
2089
2741
|
if (!this.hasFocusedItem())
|
|
@@ -2091,7 +2743,7 @@ class DropList {
|
|
|
2091
2743
|
|
|
2092
2744
|
nextIndex = p.focusItemIndex - 1;
|
|
2093
2745
|
if (nextIndex === -1) {
|
|
2094
|
-
nextIndex =
|
|
2746
|
+
nextIndex = items.length - 1;
|
|
2095
2747
|
}
|
|
2096
2748
|
|
|
2097
2749
|
directionUp = true;
|
|
@@ -2100,7 +2752,7 @@ class DropList {
|
|
|
2100
2752
|
return this._move('first', event);
|
|
2101
2753
|
|
|
2102
2754
|
nextIndex = p.focusItemIndex + 1;
|
|
2103
|
-
if (nextIndex ===
|
|
2755
|
+
if (nextIndex === items.length) {
|
|
2104
2756
|
nextIndex = 0;
|
|
2105
2757
|
}
|
|
2106
2758
|
|
|
@@ -2129,8 +2781,8 @@ class DropList {
|
|
|
2129
2781
|
|
|
2130
2782
|
if (nextIndex < 0) {
|
|
2131
2783
|
nextIndex = 0;
|
|
2132
|
-
} else if (nextIndex >=
|
|
2133
|
-
nextIndex =
|
|
2784
|
+
} else if (nextIndex >= items.length) {
|
|
2785
|
+
nextIndex = items.length;
|
|
2134
2786
|
}
|
|
2135
2787
|
} else if (p.focusItemEl) {
|
|
2136
2788
|
let base = Css.getElementOffset(p.focusItemEl).top;
|
|
@@ -2167,13 +2819,13 @@ class DropList {
|
|
|
2167
2819
|
return;
|
|
2168
2820
|
}
|
|
2169
2821
|
|
|
2170
|
-
let itemCount =
|
|
2822
|
+
let itemCount = items.length;
|
|
2171
2823
|
|
|
2172
2824
|
if (nextIndex >= itemCount) {
|
|
2173
2825
|
return;
|
|
2174
2826
|
}
|
|
2175
2827
|
|
|
2176
|
-
let item =
|
|
2828
|
+
let item = items[nextIndex];
|
|
2177
2829
|
// noinspection UnnecessaryLocalVariableJS
|
|
2178
2830
|
let startedAtIndex = nextIndex;
|
|
2179
2831
|
|
|
@@ -2190,7 +2842,7 @@ class DropList {
|
|
|
2190
2842
|
}
|
|
2191
2843
|
}
|
|
2192
2844
|
|
|
2193
|
-
item =
|
|
2845
|
+
item = items[nextIndex];
|
|
2194
2846
|
|
|
2195
2847
|
if (nextIndex === startedAtIndex) {
|
|
2196
2848
|
break;
|
|
@@ -2206,7 +2858,9 @@ class DropList {
|
|
|
2206
2858
|
}
|
|
2207
2859
|
|
|
2208
2860
|
_hasScroll() {
|
|
2209
|
-
|
|
2861
|
+
const p = this._p;
|
|
2862
|
+
const menuEl = p.menuEl;
|
|
2863
|
+
return menuEl.clientHeight < menuEl.scrollHeight;
|
|
2210
2864
|
}
|
|
2211
2865
|
|
|
2212
2866
|
_updateGroupStateForItem(item) {
|
|
@@ -2221,7 +2875,7 @@ class DropList {
|
|
|
2221
2875
|
let affectedItems = 0;
|
|
2222
2876
|
|
|
2223
2877
|
if (p.autoCheckGroupChildren) {
|
|
2224
|
-
let items = p.items;
|
|
2878
|
+
let items = p.filteredItems ?? p.items;
|
|
2225
2879
|
let groupIndex = items.indexOf(item);
|
|
2226
2880
|
|
|
2227
2881
|
for (let i = groupIndex + 1, len = items.length; i < len; i++) {
|
|
@@ -2264,7 +2918,7 @@ class DropList {
|
|
|
2264
2918
|
affectedItems: affectedItems
|
|
2265
2919
|
});
|
|
2266
2920
|
} else if (p.groupCount > 0 && p.autoCheckGroupChildren) {
|
|
2267
|
-
let items = p.items;
|
|
2921
|
+
let items = p.filteredItems ?? p.items;
|
|
2268
2922
|
let itemIndex = items.indexOf(item);
|
|
2269
2923
|
let groupIndex = -1;
|
|
2270
2924
|
|
|
@@ -2290,7 +2944,7 @@ class DropList {
|
|
|
2290
2944
|
if (!(p.multi && p.autoCheckGroupChildren && groupIndex > -1))
|
|
2291
2945
|
return this;
|
|
2292
2946
|
|
|
2293
|
-
let items = p.items;
|
|
2947
|
+
let items = p.filteredItems ?? p.items;
|
|
2294
2948
|
let groupItem = items[groupIndex];
|
|
2295
2949
|
|
|
2296
2950
|
if (!groupItem || !groupItem._group) return this;
|
|
@@ -2416,7 +3070,7 @@ class DropList {
|
|
|
2416
3070
|
_determineVirtualMode(targetItemCount) {
|
|
2417
3071
|
const p = this._p;
|
|
2418
3072
|
|
|
2419
|
-
let items = p.items;
|
|
3073
|
+
let items = p.filteredItems ?? p.items;
|
|
2420
3074
|
if (targetItemCount === undefined) {
|
|
2421
3075
|
targetItemCount = items.length;
|
|
2422
3076
|
}
|
|
@@ -2436,7 +3090,21 @@ class DropList {
|
|
|
2436
3090
|
// NOTE: a "measure" item will not have full data of original item.
|
|
2437
3091
|
// so for a custom renderer - we try to send original item, and fallback to our private list item.
|
|
2438
3092
|
|
|
2439
|
-
|
|
3093
|
+
const originalItem = item[ItemSymbol$1];
|
|
3094
|
+
|
|
3095
|
+
if (originalItem === NoResultsItemSymbol) {
|
|
3096
|
+
if (p.renderNoResultsItem && p.renderNoResultsItem(item, itemEl) !== false) {
|
|
3097
|
+
return true;
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
itemEl.appendChild(Dom.createElement('div', {
|
|
3101
|
+
class: 'droplist-no-results-content',
|
|
3102
|
+
textContent: p.noResultsText
|
|
3103
|
+
}));
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
if (!p.renderItem || p.renderItem(originalItem || item, itemEl) === false) {
|
|
2440
3108
|
itemEl.appendChild(Dom.createElement('span', {
|
|
2441
3109
|
class: `${p.baseClassName}__item_label`,
|
|
2442
3110
|
textContent: item.label
|
|
@@ -2478,7 +3146,7 @@ class DropList {
|
|
|
2478
3146
|
}
|
|
2479
3147
|
|
|
2480
3148
|
let autoWidth = 0;
|
|
2481
|
-
if (!p.useExactTargetWidth) {
|
|
3149
|
+
if (!p.useExactTargetWidth || !targetWidth) {
|
|
2482
3150
|
if (p.estimateWidth || p.virtualListHelper.isVirtual()) {
|
|
2483
3151
|
autoWidth = p.lastMeasureItemWidth;
|
|
2484
3152
|
} else {
|
|
@@ -2505,56 +3173,8 @@ class DropList {
|
|
|
2505
3173
|
}
|
|
2506
3174
|
}
|
|
2507
3175
|
|
|
2508
|
-
const throttle = (func, wait, options) => {
|
|
2509
|
-
let timeout, context, args, result;
|
|
2510
|
-
let previous = 0;
|
|
2511
|
-
if (!options) options = {};
|
|
2512
|
-
|
|
2513
|
-
const later = () => {
|
|
2514
|
-
previous = options.leading === false ? 0 : Date.now();
|
|
2515
|
-
timeout = null;
|
|
2516
|
-
result = func.apply(context, args);
|
|
2517
|
-
if (!timeout) context = args = null;
|
|
2518
|
-
};
|
|
2519
|
-
|
|
2520
|
-
const throttled = function () {
|
|
2521
|
-
const now = Date.now();
|
|
2522
|
-
if (!previous && options.leading === false)
|
|
2523
|
-
previous = now;
|
|
2524
|
-
|
|
2525
|
-
const remaining = wait - (now - previous);
|
|
2526
|
-
context = this;
|
|
2527
|
-
args = arguments;
|
|
2528
|
-
if (remaining <= 0 || remaining > wait) {
|
|
2529
|
-
if (timeout) {
|
|
2530
|
-
clearTimeout(timeout);
|
|
2531
|
-
timeout = null;
|
|
2532
|
-
}
|
|
2533
|
-
previous = now;
|
|
2534
|
-
result = func.apply(context, args);
|
|
2535
|
-
if (!timeout) context = args = null;
|
|
2536
|
-
} else if (!timeout && options.trailing !== false) {
|
|
2537
|
-
timeout = setTimeout(later, remaining);
|
|
2538
|
-
}
|
|
2539
|
-
return result;
|
|
2540
|
-
};
|
|
2541
|
-
|
|
2542
|
-
throttled.cancel = () => {
|
|
2543
|
-
clearTimeout(timeout);
|
|
2544
|
-
previous = 0;
|
|
2545
|
-
timeout = context = args = null;
|
|
2546
|
-
};
|
|
2547
|
-
|
|
2548
|
-
throttled.isScheduled = () => {
|
|
2549
|
-
return !!timeout;
|
|
2550
|
-
};
|
|
2551
|
-
|
|
2552
|
-
return throttled;
|
|
2553
|
-
};
|
|
2554
|
-
|
|
2555
3176
|
const ItemSymbol = Symbol('item');
|
|
2556
3177
|
const DestroyedSymbol = Symbol('destroyed');
|
|
2557
|
-
const NoResultsItemSymbol = Symbol('no_results_items');
|
|
2558
3178
|
const RestMultiItemsSymbol = Symbol('rest_multi_items');
|
|
2559
3179
|
|
|
2560
3180
|
const hasTouchCapability = !!('ontouchstart' in window ||
|
|
@@ -2612,10 +3232,6 @@ const inputBackbufferCssProps = [
|
|
|
2612
3232
|
* @property {boolean} [showSelection=true] show selection? if false, the placeholder will take effect
|
|
2613
3233
|
* @property {boolean} [showPlaceholderInTooltip=false] show placeholder in title attribute
|
|
2614
3234
|
* @property {function(items: DropList.ItemBase[]):string} [multiPlaceholderFormatter] formatter for placeholder for multi items mode
|
|
2615
|
-
* @property {boolean} [searchable=false] is it searchable?
|
|
2616
|
-
* @property {string} [noResultsText='No matching results'] text for no results (empty for none)
|
|
2617
|
-
* @property {number} [filterThrottleWindow=300] throttle time (milliseconds) for filtering
|
|
2618
|
-
* @property {boolean} [filterOnEmptyTerm=false] call the filter function on empty search term too
|
|
2619
3235
|
* @property {string} [labelProp='label']
|
|
2620
3236
|
* @property {string} [valueProp='value']
|
|
2621
3237
|
* @property {string} [multiItemLabelProp='short_label']
|
|
@@ -2632,6 +3248,10 @@ const inputBackbufferCssProps = [
|
|
|
2632
3248
|
* @property {function(item: DropList.ItemBase, itemEl: Element)} [unrenderRestMultiItem]
|
|
2633
3249
|
* @property {function(item: DropList.ItemBase, itemEl: Element):(*|false)} [renderNoResultsItem]
|
|
2634
3250
|
* @property {function(item: DropList.ItemBase, itemEl: Element)} [unrenderNoResultsItem]
|
|
3251
|
+
* @property {boolean} [searchable=false] is it searchable?
|
|
3252
|
+
* @property {string} [noResultsText='No matching results'] text for no results (empty for none)
|
|
3253
|
+
* @property {number} [filterThrottleWindow=300] throttle time (milliseconds) for filtering
|
|
3254
|
+
* @property {boolean} [filterOnEmptyTerm=false] call the filter function on empty search term too
|
|
2635
3255
|
* @property {function(items: DropList.ItemBase[], term: string):(DropList.ItemBase[]|null)} [filterFn]
|
|
2636
3256
|
* @property {function(name: string, ...args)} [on]
|
|
2637
3257
|
* @property {boolean} [isLoadingMode]
|
|
@@ -2750,8 +3370,6 @@ class SelectBox {
|
|
|
2750
3370
|
multiPlaceholderFormatter: o.multiPlaceholderFormatter,
|
|
2751
3371
|
searchable: o.searchable,
|
|
2752
3372
|
noResultsText: o.noResultsText,
|
|
2753
|
-
filterThrottleWindow: o.filterThrottleWindow,
|
|
2754
|
-
filterOnEmptyTerm: o.filterOnEmptyTerm,
|
|
2755
3373
|
|
|
2756
3374
|
labelProp: o.labelProp,
|
|
2757
3375
|
valueProp: o.valueProp,
|
|
@@ -2768,7 +3386,6 @@ class SelectBox {
|
|
|
2768
3386
|
unrenderRestMultiItem: o.unrenderRestMultiItem,
|
|
2769
3387
|
renderNoResultsItem: o.renderNoResultsItem,
|
|
2770
3388
|
unrenderNoResultsItem: o.unrenderNoResultsItem,
|
|
2771
|
-
filterFn: o.filterFn,
|
|
2772
3389
|
on: o.on || null,
|
|
2773
3390
|
silenceEvents: true,
|
|
2774
3391
|
mitt: mitt(),
|
|
@@ -2776,8 +3393,6 @@ class SelectBox {
|
|
|
2776
3393
|
isLoadingMode: !!o.isLoadingMode,
|
|
2777
3394
|
|
|
2778
3395
|
items: [],
|
|
2779
|
-
filteredItems: null,
|
|
2780
|
-
currentItemsView: [], // contains the final version of items sent to DropList
|
|
2781
3396
|
itemsChanged: true,
|
|
2782
3397
|
|
|
2783
3398
|
sink: new DomEventsSink(),
|
|
@@ -2790,10 +3405,9 @@ class SelectBox {
|
|
|
2790
3405
|
selectionChanged: true,
|
|
2791
3406
|
resortBySelectionNeeded: false,
|
|
2792
3407
|
|
|
2793
|
-
|
|
2794
|
-
o.
|
|
2795
|
-
|
|
2796
|
-
|
|
3408
|
+
filterThrottleWindow: o.filterThrottleWindow,
|
|
3409
|
+
filterOnEmptyTerm: o.filterOnEmptyTerm,
|
|
3410
|
+
filterFn: null,
|
|
2797
3411
|
filterTerm: ''
|
|
2798
3412
|
};
|
|
2799
3413
|
|
|
@@ -2905,6 +3519,9 @@ class SelectBox {
|
|
|
2905
3519
|
p.resizeObserver.observe(p.el);
|
|
2906
3520
|
}
|
|
2907
3521
|
|
|
3522
|
+
if (o.filterFn)
|
|
3523
|
+
this.setFilterFn(o.filterFn);
|
|
3524
|
+
|
|
2908
3525
|
this.setItems(o.items);
|
|
2909
3526
|
delete o.items; // we do not need this in memory anymore
|
|
2910
3527
|
|
|
@@ -2938,9 +3555,6 @@ class SelectBox {
|
|
|
2938
3555
|
p.sink.remove();
|
|
2939
3556
|
p.dropList && p.dropList.destroy();
|
|
2940
3557
|
|
|
2941
|
-
if (p.throttledUpdateListItems)
|
|
2942
|
-
p.throttledUpdateListItems.cancel();
|
|
2943
|
-
|
|
2944
3558
|
this._cleanupSingleWrapper();
|
|
2945
3559
|
|
|
2946
3560
|
if (p.unrenderMultiItem || p.unrenderRestMultiItem) {
|
|
@@ -3069,7 +3683,6 @@ class SelectBox {
|
|
|
3069
3683
|
items = [];
|
|
3070
3684
|
|
|
3071
3685
|
p.items = items.slice(0);
|
|
3072
|
-
p.filteredItems = null;
|
|
3073
3686
|
p.itemsChanged = true;
|
|
3074
3687
|
|
|
3075
3688
|
this._updateItemByValueMap();
|
|
@@ -3086,8 +3699,8 @@ class SelectBox {
|
|
|
3086
3699
|
getFilteredItemCount() {
|
|
3087
3700
|
const p = this._p;
|
|
3088
3701
|
|
|
3089
|
-
if (p.
|
|
3090
|
-
return p.
|
|
3702
|
+
if (p.dropList)
|
|
3703
|
+
return p.dropList.getFilteredItemCount();
|
|
3091
3704
|
|
|
3092
3705
|
if (p.items)
|
|
3093
3706
|
return p.items.length;
|
|
@@ -3097,9 +3710,7 @@ class SelectBox {
|
|
|
3097
3710
|
|
|
3098
3711
|
isFilterPending() {
|
|
3099
3712
|
const p = this._p;
|
|
3100
|
-
|
|
3101
|
-
return !!(p.throttledUpdateListItems.isScheduled() ||
|
|
3102
|
-
!p.filteredItems && (p.filterTerm || p.filterOnEmptyTerm && p.filterFn));
|
|
3713
|
+
return p.dropList?.isFilterPending() === true;
|
|
3103
3714
|
}
|
|
3104
3715
|
|
|
3105
3716
|
updateItemByValue(value, newItem) {
|
|
@@ -3199,11 +3810,7 @@ class SelectBox {
|
|
|
3199
3810
|
|
|
3200
3811
|
if (performSearch) {
|
|
3201
3812
|
p.filterTerm = p.input.value.trim();
|
|
3202
|
-
p.
|
|
3203
|
-
p.itemsChanged = true;
|
|
3204
|
-
|
|
3205
|
-
this._trigger('search', { value: p.input.value });
|
|
3206
|
-
p.throttledUpdateListItems();
|
|
3813
|
+
p.dropList?.setSearchTerm(p.filterTerm, performSearch);
|
|
3207
3814
|
}
|
|
3208
3815
|
|
|
3209
3816
|
return this;
|
|
@@ -3221,11 +3828,7 @@ class SelectBox {
|
|
|
3221
3828
|
|
|
3222
3829
|
invokeRefilter() {
|
|
3223
3830
|
const p = this._p;
|
|
3224
|
-
|
|
3225
|
-
return this;
|
|
3226
|
-
p.filteredItems = null;
|
|
3227
|
-
p.itemsChanged = true;
|
|
3228
|
-
p.throttledUpdateListItems();
|
|
3831
|
+
p.dropList?.invokeRefilter();
|
|
3229
3832
|
return this;
|
|
3230
3833
|
}
|
|
3231
3834
|
|
|
@@ -3262,7 +3865,6 @@ class SelectBox {
|
|
|
3262
3865
|
return this;
|
|
3263
3866
|
|
|
3264
3867
|
p.sortListItems = sortListItems;
|
|
3265
|
-
p.filteredItems = null;
|
|
3266
3868
|
p.itemsChanged = true;
|
|
3267
3869
|
this._scheduleSync('render_list');
|
|
3268
3870
|
return this;
|
|
@@ -3351,6 +3953,8 @@ class SelectBox {
|
|
|
3351
3953
|
return this;
|
|
3352
3954
|
|
|
3353
3955
|
p.treatGroupSelectionAsItems = treatGroupSelectionAsItems;
|
|
3956
|
+
p.dropList?.setFilterGroups(treatGroupSelectionAsItems);
|
|
3957
|
+
p.dropList?.setFilterEmptyGroups(!treatGroupSelectionAsItems);
|
|
3354
3958
|
p.itemsChanged = true;
|
|
3355
3959
|
this._scheduleSync('render_list');
|
|
3356
3960
|
return this;
|
|
@@ -3530,8 +4134,7 @@ class SelectBox {
|
|
|
3530
4134
|
* @returns {SelectBox}
|
|
3531
4135
|
*/
|
|
3532
4136
|
setNoResultsText(noResultsText) {
|
|
3533
|
-
this._p.noResultsText
|
|
3534
|
-
this._scheduleSync('render_list');
|
|
4137
|
+
this._p.dropList?.setNoResultsText(noResultsText);
|
|
3535
4138
|
return this;
|
|
3536
4139
|
}
|
|
3537
4140
|
|
|
@@ -3549,17 +4152,7 @@ class SelectBox {
|
|
|
3549
4152
|
setFilterThrottleWindow(window) {
|
|
3550
4153
|
const p = this._p;
|
|
3551
4154
|
p.filterThrottleWindow = window;
|
|
3552
|
-
|
|
3553
|
-
let isScheduled = p.throttledUpdateListItems ? p.throttledUpdateListItems.isScheduled() : false;
|
|
3554
|
-
|
|
3555
|
-
if (p.throttledUpdateListItems)
|
|
3556
|
-
p.throttledUpdateListItems.cancel();
|
|
3557
|
-
|
|
3558
|
-
p.throttledUpdateListItems = throttle(() => this._updateListItems(), p.filterThrottleWindow, true);
|
|
3559
|
-
|
|
3560
|
-
if (isScheduled)
|
|
3561
|
-
p.throttledUpdateListItems();
|
|
3562
|
-
|
|
4155
|
+
p.dropList?.setFilterThrottleWindow(window);
|
|
3563
4156
|
return this;
|
|
3564
4157
|
}
|
|
3565
4158
|
|
|
@@ -3578,8 +4171,7 @@ class SelectBox {
|
|
|
3578
4171
|
const p = this._p;
|
|
3579
4172
|
if (p.filterOnEmptyTerm === value)
|
|
3580
4173
|
return this;
|
|
3581
|
-
p.
|
|
3582
|
-
p.throttledUpdateListItems();
|
|
4174
|
+
p.dropList?.setFilterOnEmptyTerm(value);
|
|
3583
4175
|
return this;
|
|
3584
4176
|
}
|
|
3585
4177
|
|
|
@@ -3721,8 +4313,21 @@ class SelectBox {
|
|
|
3721
4313
|
const p = this._p;
|
|
3722
4314
|
if (p.filterFn === fn)
|
|
3723
4315
|
return this;
|
|
4316
|
+
if (!fn) {
|
|
4317
|
+
// Add search by multi-item label
|
|
4318
|
+
fn = (items, term) => {
|
|
4319
|
+
const matcher = new RegExp(escapeRegex(term), 'i');
|
|
4320
|
+
const labelProp = p.labelProp,
|
|
4321
|
+
multiItemLabelProp = p.multiItemLabelProp;
|
|
4322
|
+
|
|
4323
|
+
return p.items.filter((x) => {
|
|
4324
|
+
if (!p.treatGroupSelectionAsItems && x._group) return true;
|
|
4325
|
+
return matcher.test(x[labelProp] || x[multiItemLabelProp]);
|
|
4326
|
+
});
|
|
4327
|
+
};
|
|
4328
|
+
}
|
|
3724
4329
|
p.filterFn = fn;
|
|
3725
|
-
p.
|
|
4330
|
+
p.dropList?.setFilterFn(fn);
|
|
3726
4331
|
return this;
|
|
3727
4332
|
}
|
|
3728
4333
|
|
|
@@ -3902,7 +4507,7 @@ class SelectBox {
|
|
|
3902
4507
|
// Propagate direction to droplist
|
|
3903
4508
|
p.dropList.setDirection(getComputedStyle(p.el).direction);
|
|
3904
4509
|
|
|
3905
|
-
p.dropList.show(
|
|
4510
|
+
p.dropList.show();
|
|
3906
4511
|
this._repositionDropList();
|
|
3907
4512
|
|
|
3908
4513
|
// Another one in case the droplist position messed with screen layout.
|
|
@@ -4295,31 +4900,14 @@ class SelectBox {
|
|
|
4295
4900
|
const customUnrenderItem = (p.listOptions || {}).unrenderItem;
|
|
4296
4901
|
|
|
4297
4902
|
const renderItem = renderNoResultsItem || customRenderItem ? (item, itemEl) => {
|
|
4298
|
-
if (
|
|
4299
|
-
|
|
4300
|
-
return true;
|
|
4301
|
-
}
|
|
4302
|
-
|
|
4303
|
-
itemEl.appendChild(Dom.createElement('div', {
|
|
4304
|
-
class: 'droplist-no-results-content',
|
|
4305
|
-
textContent: p.noResultsText
|
|
4306
|
-
}));
|
|
4307
|
-
return true;
|
|
4308
|
-
} else {
|
|
4309
|
-
if (customRenderItem)
|
|
4310
|
-
return customRenderItem(item, itemEl);
|
|
4311
|
-
}
|
|
4903
|
+
if (customRenderItem)
|
|
4904
|
+
return customRenderItem(item, itemEl);
|
|
4312
4905
|
return false;
|
|
4313
4906
|
} : null;
|
|
4314
4907
|
|
|
4315
4908
|
const unrenderItem = unrenderNoResultsItem || customRenderItem ? (item, itemEl) => {
|
|
4316
|
-
if (
|
|
4317
|
-
|
|
4318
|
-
return unrenderNoResultsItem(item, itemEl);
|
|
4319
|
-
} else {
|
|
4320
|
-
if (customUnrenderItem)
|
|
4321
|
-
return customUnrenderItem(item, itemEl);
|
|
4322
|
-
}
|
|
4909
|
+
if (customUnrenderItem)
|
|
4910
|
+
return customUnrenderItem(item, itemEl);
|
|
4323
4911
|
return false;
|
|
4324
4912
|
} : null;
|
|
4325
4913
|
|
|
@@ -4337,6 +4925,16 @@ class SelectBox {
|
|
|
4337
4925
|
labelProp: p.labelProp,
|
|
4338
4926
|
valueProp: p.valueProp,
|
|
4339
4927
|
|
|
4928
|
+
searchable: false,
|
|
4929
|
+
noResultsText: p.noResultsText,
|
|
4930
|
+
filterThrottleWindow: p.filterThrottleWindow,
|
|
4931
|
+
filterOnEmptyTerm: p.filterOnEmptyTerm,
|
|
4932
|
+
filterGroups: p.treatGroupSelectionAsItems,
|
|
4933
|
+
filterEmptyGroups: p.treatGroupSelectionAsItems,
|
|
4934
|
+
filterFn: p.filterFn,
|
|
4935
|
+
|
|
4936
|
+
positionOptionsProvider: () => this._getDropListPositionOptions(),
|
|
4937
|
+
|
|
4340
4938
|
on: (name, event) => {
|
|
4341
4939
|
switch (name) {
|
|
4342
4940
|
case 'show:before':{
|
|
@@ -4491,6 +5089,15 @@ class SelectBox {
|
|
|
4491
5089
|
|
|
4492
5090
|
case 'blur':
|
|
4493
5091
|
this._handleOnBlur();
|
|
5092
|
+
break;
|
|
5093
|
+
|
|
5094
|
+
case 'search':
|
|
5095
|
+
this._trigger('search', event);
|
|
5096
|
+
break;
|
|
5097
|
+
|
|
5098
|
+
case 'itemschanged':
|
|
5099
|
+
this._trigger('itemschanged', event);
|
|
5100
|
+
break;
|
|
4494
5101
|
}
|
|
4495
5102
|
}
|
|
4496
5103
|
});
|
|
@@ -4521,8 +5128,7 @@ class SelectBox {
|
|
|
4521
5128
|
p.dropList && this.droplistElContains(document.activeElement, true))) {
|
|
4522
5129
|
return;
|
|
4523
5130
|
}
|
|
4524
|
-
|
|
4525
|
-
p.throttledUpdateListItems.cancel();
|
|
5131
|
+
|
|
4526
5132
|
this.closeList();
|
|
4527
5133
|
});
|
|
4528
5134
|
}
|
|
@@ -4669,12 +5275,9 @@ class SelectBox {
|
|
|
4669
5275
|
if (p.disabled) return;
|
|
4670
5276
|
|
|
4671
5277
|
p.filterTerm = p.input.value.trim();
|
|
4672
|
-
p.
|
|
4673
|
-
p.itemsChanged = true;
|
|
5278
|
+
p.dropList?.setSearchTerm(p.filterTerm, true);
|
|
4674
5279
|
|
|
4675
5280
|
this._trigger('search', { value: p.input.value });
|
|
4676
|
-
|
|
4677
|
-
p.throttledUpdateListItems();
|
|
4678
5281
|
}).
|
|
4679
5282
|
add(p.input, 'click.dropdown', () => {
|
|
4680
5283
|
if (p.disabled) return;
|
|
@@ -4779,15 +5382,16 @@ class SelectBox {
|
|
|
4779
5382
|
if (this.isMultiEnabled()) return;
|
|
4780
5383
|
|
|
4781
5384
|
let selectedItems = this.getSelectedItems();
|
|
4782
|
-
let
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
5385
|
+
let finalItemCount = p.dropList.getFilteredItemCount();
|
|
5386
|
+
|
|
5387
|
+
if (finalItemCount + (p.clearable ? 1 : 0) > 1) {
|
|
5388
|
+
let nextIndex = selectedItems.length > 0 ?
|
|
5389
|
+
p.dropList.filteredItemIndexByItem(selectedItems[0]) - 1 :
|
|
5390
|
+
finalItemCount - 1;
|
|
4787
5391
|
if (nextIndex === -1 && !p.clearable)
|
|
4788
|
-
nextIndex =
|
|
5392
|
+
nextIndex = finalItemCount - 1;
|
|
4789
5393
|
|
|
4790
|
-
let item = nextIndex === -1 ? null :
|
|
5394
|
+
let item = nextIndex === -1 ? null : p.dropList.filteredItemAtIndex(nextIndex);
|
|
4791
5395
|
if (item) {
|
|
4792
5396
|
this._performSelectWithEvent(item, item[p.valueProp]);
|
|
4793
5397
|
} else {
|
|
@@ -4802,15 +5406,16 @@ class SelectBox {
|
|
|
4802
5406
|
if (this.isMultiEnabled()) return;
|
|
4803
5407
|
|
|
4804
5408
|
let selectedItems = this.getSelectedItems();
|
|
4805
|
-
let
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
5409
|
+
let finalItemCount = p.dropList.getFilteredItemCount();
|
|
5410
|
+
|
|
5411
|
+
if (finalItemCount + (p.clearable ? 1 : 0) > 1) {
|
|
5412
|
+
let nextIndex = selectedItems.length > 0 ?
|
|
5413
|
+
p.dropList.filteredItemIndexByItem(selectedItems[0]) + 1 :
|
|
5414
|
+
0;
|
|
5415
|
+
if (nextIndex === finalItemCount)
|
|
4811
5416
|
nextIndex = p.clearable ? -1 : 0;
|
|
4812
5417
|
|
|
4813
|
-
let item = nextIndex === -1 ? null :
|
|
5418
|
+
let item = nextIndex === -1 ? null : p.dropList.filteredItemAtIndex(nextIndex);
|
|
4814
5419
|
if (item) {
|
|
4815
5420
|
this._performSelectWithEvent(item, item[p.valueProp]);
|
|
4816
5421
|
} else {
|
|
@@ -4827,37 +5432,19 @@ class SelectBox {
|
|
|
4827
5432
|
if (!dropList || !p.dropListVisible)
|
|
4828
5433
|
return;
|
|
4829
5434
|
|
|
4830
|
-
// For every search change, filteredItems is cleared.
|
|
4831
|
-
// If it's non-null here, then it means we have an extra call to _updateListItems, and not need to refilter.
|
|
4832
|
-
if (!p.filteredItems && (p.filterTerm || p.filterOnEmptyTerm && p.filterFn)) {
|
|
4833
|
-
this._refilterItems();
|
|
4834
|
-
}
|
|
4835
|
-
|
|
4836
5435
|
if (p.itemsChanged || p.selectionChanged) {
|
|
4837
5436
|
p.dropList._lastSerializedBox = null;
|
|
4838
5437
|
}
|
|
4839
5438
|
|
|
4840
5439
|
if (p.itemsChanged) {
|
|
4841
|
-
let items = p.
|
|
5440
|
+
let items = p.items;
|
|
4842
5441
|
if (p.sortListItems || p.sortListCheckedFirst && p.multi) {
|
|
4843
5442
|
items = this._sortItems(items,
|
|
4844
5443
|
p.sortListItems,
|
|
4845
5444
|
p.sortListCheckedFirst && p.multi,
|
|
4846
5445
|
p.splitListCheckedGroups);
|
|
4847
5446
|
}
|
|
4848
|
-
dropList.
|
|
4849
|
-
|
|
4850
|
-
if (items.length === 0 && p.noResultsText) {
|
|
4851
|
-
items = [{
|
|
4852
|
-
[p.labelProp]: p.noResultsText,
|
|
4853
|
-
[p.valueProp]: NoResultsItemSymbol,
|
|
4854
|
-
_nointeraction: true,
|
|
4855
|
-
_nocheck: true
|
|
4856
|
-
}];
|
|
4857
|
-
}
|
|
4858
|
-
|
|
4859
|
-
dropList.addItems(items);
|
|
4860
|
-
p.currentItemsView = items;
|
|
5447
|
+
dropList.setItems(items);
|
|
4861
5448
|
p.itemsChanged = false;
|
|
4862
5449
|
p.selectionChanged = true;
|
|
4863
5450
|
p.resortBySelectionNeeded = false;
|
|
@@ -4887,77 +5474,6 @@ class SelectBox {
|
|
|
4887
5474
|
}
|
|
4888
5475
|
}
|
|
4889
5476
|
|
|
4890
|
-
/** @private */
|
|
4891
|
-
_refilterItems() {
|
|
4892
|
-
const p = this._p;
|
|
4893
|
-
|
|
4894
|
-
const term = p.filterTerm;
|
|
4895
|
-
const treatGroupSelectionAsItems = p.treatGroupSelectionAsItems;
|
|
4896
|
-
|
|
4897
|
-
if (term || p.filterOnEmptyTerm && p.filterFn) {
|
|
4898
|
-
let fn = p.filterFn;
|
|
4899
|
-
|
|
4900
|
-
let filteredItems;
|
|
4901
|
-
|
|
4902
|
-
if (typeof fn === 'function') {
|
|
4903
|
-
filteredItems = p.filterFn(p.items, term);
|
|
4904
|
-
}
|
|
4905
|
-
|
|
4906
|
-
// If there was no filter function, or it gave up on filtering.
|
|
4907
|
-
if (!Array.isArray(filteredItems)) {
|
|
4908
|
-
if (term) {
|
|
4909
|
-
const matcher = new RegExp(escapeRegex(term), 'i');
|
|
4910
|
-
const labelProp = p.labelProp,
|
|
4911
|
-
multiItemLabelProp = p.multiItemLabelProp;
|
|
4912
|
-
|
|
4913
|
-
filteredItems = p.items.filter((x) => {
|
|
4914
|
-
if (!treatGroupSelectionAsItems && x._group) return true;
|
|
4915
|
-
return matcher.test(x[labelProp] || x[multiItemLabelProp]);
|
|
4916
|
-
});
|
|
4917
|
-
} else {
|
|
4918
|
-
filteredItems = null;
|
|
4919
|
-
}
|
|
4920
|
-
}
|
|
4921
|
-
|
|
4922
|
-
p.filteredItems = filteredItems;
|
|
4923
|
-
|
|
4924
|
-
if (filteredItems && !treatGroupSelectionAsItems) {
|
|
4925
|
-
// Clean up groups without children
|
|
4926
|
-
|
|
4927
|
-
let lastGroup = -1;
|
|
4928
|
-
let len = filteredItems.length;
|
|
4929
|
-
|
|
4930
|
-
for (let i = 0; i < len; i++) {
|
|
4931
|
-
let item = filteredItems[i];
|
|
4932
|
-
|
|
4933
|
-
if (item._group) {
|
|
4934
|
-
if (lastGroup !== -1 && lastGroup === i - 1) {
|
|
4935
|
-
// It was an empty group
|
|
4936
|
-
filteredItems.splice(lastGroup, 1);
|
|
4937
|
-
i--;
|
|
4938
|
-
len--;
|
|
4939
|
-
}
|
|
4940
|
-
|
|
4941
|
-
lastGroup = i;
|
|
4942
|
-
}
|
|
4943
|
-
}
|
|
4944
|
-
|
|
4945
|
-
if (lastGroup !== -1) {
|
|
4946
|
-
if (lastGroup === len - 1) {
|
|
4947
|
-
// It was an empty group
|
|
4948
|
-
filteredItems.splice(lastGroup, 1);
|
|
4949
|
-
}
|
|
4950
|
-
}
|
|
4951
|
-
}
|
|
4952
|
-
} else {
|
|
4953
|
-
p.filteredItems = null;
|
|
4954
|
-
}
|
|
4955
|
-
|
|
4956
|
-
this._trigger('itemschanged', { term: term, mutated: false, count: this.getFilteredItemCount() });
|
|
4957
|
-
|
|
4958
|
-
p.itemsChanged = true;
|
|
4959
|
-
}
|
|
4960
|
-
|
|
4961
5477
|
/** @private */
|
|
4962
5478
|
_setSelectedItems(items) {
|
|
4963
5479
|
const p = this._p,valueProp = p.valueProp;
|
|
@@ -5596,8 +6112,7 @@ class SelectBox {
|
|
|
5596
6112
|
p.input.value = value == null ? '' : String(value);
|
|
5597
6113
|
|
|
5598
6114
|
p.filterTerm = '';
|
|
5599
|
-
p.
|
|
5600
|
-
p.itemsChanged = true;
|
|
6115
|
+
p.dropList?.setSearchTerm('', true);
|
|
5601
6116
|
}
|
|
5602
6117
|
|
|
5603
6118
|
/**
|
|
@@ -5718,7 +6233,7 @@ class SelectBox {
|
|
|
5718
6233
|
const serialized = box.left + ',' + box.top + ',' + box.right + ',' + box.bottom;
|
|
5719
6234
|
|
|
5720
6235
|
if (p.dropList._lastSerializedBox !== serialized) {
|
|
5721
|
-
p.dropList.relayout(
|
|
6236
|
+
p.dropList.relayout();
|
|
5722
6237
|
p.dropList._lastSerializedBox = serialized;
|
|
5723
6238
|
}
|
|
5724
6239
|
|