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