selective-ui 1.4.0 → 1.4.1
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/dist/selective-ui.css +0 -6
- package/dist/selective-ui.css.map +1 -1
- package/dist/selective-ui.esm.js +252 -553
- package/dist/selective-ui.esm.js.map +1 -1
- package/dist/selective-ui.esm.min.js +2 -2
- package/dist/selective-ui.esm.min.js.br +0 -0
- package/dist/selective-ui.min.css +1 -1
- package/dist/selective-ui.min.css.br +0 -0
- package/dist/selective-ui.min.js +2 -2
- package/dist/selective-ui.min.js.br +0 -0
- package/dist/selective-ui.umd.js +254 -555
- package/dist/selective-ui.umd.js.map +1 -1
- package/package.json +12 -12
- package/src/ts/adapter/mixed-adapter.ts +147 -68
- package/src/ts/components/accessorybox.ts +14 -11
- package/src/ts/components/directive.ts +1 -1
- package/src/ts/components/option-handle.ts +12 -9
- package/src/ts/components/placeholder.ts +5 -5
- package/src/ts/components/popup/empty-state.ts +5 -5
- package/src/ts/components/popup/loading-state.ts +5 -5
- package/src/ts/components/popup/popup.ts +138 -76
- package/src/ts/components/searchbox.ts +17 -13
- package/src/ts/components/selectbox.ts +242 -81
- package/src/ts/core/base/adapter.ts +39 -14
- package/src/ts/core/base/fenwick.ts +3 -2
- package/src/ts/core/base/lifecycle.ts +14 -4
- package/src/ts/core/base/model.ts +17 -15
- package/src/ts/core/base/recyclerview.ts +7 -5
- package/src/ts/core/base/view.ts +10 -5
- package/src/ts/core/base/virtual-recyclerview.ts +89 -37
- package/src/ts/core/model-manager.ts +48 -21
- package/src/ts/core/search-controller.ts +174 -56
- package/src/ts/global.ts +5 -8
- package/src/ts/index.ts +2 -2
- package/src/ts/models/group-model.ts +33 -8
- package/src/ts/models/option-model.ts +60 -19
- package/src/ts/services/dataset-observer.ts +6 -3
- package/src/ts/services/ea-observer.ts +1 -1
- package/src/ts/services/effector.ts +22 -12
- package/src/ts/services/refresher.ts +7 -3
- package/src/ts/services/resize-observer.ts +24 -11
- package/src/ts/services/select-observer.ts +2 -2
- package/src/ts/types/components/popup.type.ts +18 -1
- package/src/ts/types/components/searchbox.type.ts +43 -30
- package/src/ts/types/components/state.box.type.ts +1 -1
- package/src/ts/types/core/base/adapter.type.ts +13 -5
- package/src/ts/types/core/base/lifecycle.type.ts +1 -2
- package/src/ts/types/core/base/model.type.ts +3 -3
- package/src/ts/types/core/base/recyclerview.type.ts +7 -5
- package/src/ts/types/core/base/view.type.ts +6 -6
- package/src/ts/types/core/base/virtual-recyclerview.type.ts +45 -46
- package/src/ts/types/core/search-controller.type.ts +18 -2
- package/src/ts/types/css.d.ts +1 -0
- package/src/ts/types/plugins/plugin.type.ts +2 -2
- package/src/ts/types/services/effector.type.ts +25 -25
- package/src/ts/types/services/resize-observer.type.ts +23 -12
- package/src/ts/types/utils/callback-scheduler.type.ts +2 -2
- package/src/ts/types/utils/ievents.type.ts +1 -1
- package/src/ts/types/utils/istorage.type.ts +62 -60
- package/src/ts/types/utils/libs.type.ts +19 -17
- package/src/ts/types/utils/selective.type.ts +6 -3
- package/src/ts/types/views/view.group.type.ts +9 -5
- package/src/ts/types/views/view.option.type.ts +39 -17
- package/src/ts/utils/callback-scheduler.ts +12 -7
- package/src/ts/utils/ievents.ts +12 -5
- package/src/ts/utils/istorage.ts +5 -3
- package/src/ts/utils/libs.ts +122 -43
- package/src/ts/utils/selective.ts +15 -8
- package/src/ts/views/group-view.ts +11 -9
- package/src/ts/views/option-view.ts +37 -18
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import { Libs } from "../utils/libs";
|
|
3
2
|
import { Refresher } from "../services/refresher";
|
|
4
3
|
import { PlaceHolder } from "./placeholder";
|
|
@@ -23,11 +22,18 @@ import type { SelectiveOptions } from "../types/utils/selective.type";
|
|
|
23
22
|
import { IEventToken, IEventCallback } from "../types/utils/ievents.type";
|
|
24
23
|
import { MixedItem } from "../types/core/base/mixed-adapter.type";
|
|
25
24
|
import { BinderMap } from "../types/utils/istorage.type";
|
|
26
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
ContainerRuntime,
|
|
27
|
+
SelectBoxAction,
|
|
28
|
+
SelectBoxTags,
|
|
29
|
+
} from "../types/components/searchbox.type";
|
|
27
30
|
import { AjaxConfig } from "../types/core/search-controller.type";
|
|
28
31
|
import { Selective } from "../utils/selective";
|
|
29
32
|
import { VirtualRecyclerView } from "../core/base/virtual-recyclerview";
|
|
30
|
-
import type {
|
|
33
|
+
import type {
|
|
34
|
+
PluginContext,
|
|
35
|
+
SelectivePlugin,
|
|
36
|
+
} from "../types/plugins/plugin.type";
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
39
|
* SelectBox
|
|
@@ -97,7 +103,7 @@ export class SelectBox extends Lifecycle {
|
|
|
97
103
|
* Created during {@link init} via {@link Libs.mountNode}, inserted into the DOM during {@link mount},
|
|
98
104
|
* and removed during {@link destroy}.
|
|
99
105
|
*/
|
|
100
|
-
private node
|
|
106
|
+
private node?: HTMLDivElement;
|
|
101
107
|
|
|
102
108
|
/**
|
|
103
109
|
* Parsed configuration (bound from the `<select>` element via binder map).
|
|
@@ -107,7 +113,7 @@ export class SelectBox extends Lifecycle {
|
|
|
107
113
|
*
|
|
108
114
|
* @internal
|
|
109
115
|
*/
|
|
110
|
-
private options
|
|
116
|
+
private options?: SelectiveOptions;
|
|
111
117
|
|
|
112
118
|
/**
|
|
113
119
|
* Manager that owns model resources and bridges the Adapter ↔ RecyclerView pipeline.
|
|
@@ -117,7 +123,7 @@ export class SelectBox extends Lifecycle {
|
|
|
117
123
|
*
|
|
118
124
|
* @internal
|
|
119
125
|
*/
|
|
120
|
-
private optionModelManager
|
|
126
|
+
private optionModelManager?: ModelManager<MixedItem, MixedAdapter>;
|
|
121
127
|
|
|
122
128
|
/**
|
|
123
129
|
* Whether the popup/list UI is currently open.
|
|
@@ -159,7 +165,7 @@ export class SelectBox extends Lifecycle {
|
|
|
159
165
|
*
|
|
160
166
|
* Used to locate the instance wrapper via `Selective.find(...)` and to close other open instances.
|
|
161
167
|
*/
|
|
162
|
-
public Selective
|
|
168
|
+
public Selective?: Selective;
|
|
163
169
|
|
|
164
170
|
/**
|
|
165
171
|
* Registered plugins for this SelectBox instance.
|
|
@@ -169,7 +175,7 @@ export class SelectBox extends Lifecycle {
|
|
|
169
175
|
/**
|
|
170
176
|
* Cached plugin context for this SelectBox instance.
|
|
171
177
|
*/
|
|
172
|
-
private pluginContext
|
|
178
|
+
private pluginContext?: PluginContext<SelectBoxTags>;
|
|
173
179
|
|
|
174
180
|
/**
|
|
175
181
|
* Creates a {@link SelectBox} bound to a native `<select>` element.
|
|
@@ -201,7 +207,10 @@ export class SelectBox extends Lifecycle {
|
|
|
201
207
|
this.options.disabled = value;
|
|
202
208
|
this.node.classList.toggle("disabled", value);
|
|
203
209
|
this.node.setAttribute("aria-disabled", String(value));
|
|
204
|
-
this.container.tags?.ViewPanel?.setAttribute(
|
|
210
|
+
this.container.tags?.ViewPanel?.setAttribute(
|
|
211
|
+
"aria-disabled",
|
|
212
|
+
String(value),
|
|
213
|
+
);
|
|
205
214
|
}
|
|
206
215
|
|
|
207
216
|
/**
|
|
@@ -250,7 +259,7 @@ export class SelectBox extends Lifecycle {
|
|
|
250
259
|
const bindedMap = Libs.getBinderMap<BinderMap>(select);
|
|
251
260
|
this.options = bindedMap.options;
|
|
252
261
|
this.Selective = Selective;
|
|
253
|
-
|
|
262
|
+
|
|
254
263
|
this.init(select);
|
|
255
264
|
}
|
|
256
265
|
|
|
@@ -290,15 +299,22 @@ export class SelectBox extends Lifecycle {
|
|
|
290
299
|
const directive = new Directive();
|
|
291
300
|
const searchbox = new SearchBox(options);
|
|
292
301
|
const effector = Effector();
|
|
293
|
-
const optionModelManager = new ModelManager<MixedItem, MixedAdapter>(
|
|
302
|
+
const optionModelManager = new ModelManager<MixedItem, MixedAdapter>(
|
|
303
|
+
options,
|
|
304
|
+
);
|
|
294
305
|
const accessoryBox = new AccessoryBox(options);
|
|
295
|
-
const searchController = new SearchController(
|
|
306
|
+
const searchController = new SearchController(
|
|
307
|
+
select,
|
|
308
|
+
optionModelManager,
|
|
309
|
+
this,
|
|
310
|
+
);
|
|
296
311
|
|
|
297
312
|
const selectObserver = new SelectObserver(select);
|
|
298
313
|
const datasetObserver = new DatasetObserver(select);
|
|
299
314
|
|
|
300
315
|
// ensure placeholder has id for aria-labelledby usage
|
|
301
|
-
if (placeholder.node)
|
|
316
|
+
if (placeholder.node)
|
|
317
|
+
placeholder.node.id = String(options.SEID_HOLDER ?? "");
|
|
302
318
|
|
|
303
319
|
const container = Libs.mountNode<ContainerRuntime>(
|
|
304
320
|
{
|
|
@@ -311,7 +327,11 @@ export class SelectBox extends Lifecycle {
|
|
|
311
327
|
classList: "seui-view",
|
|
312
328
|
tabIndex: 0,
|
|
313
329
|
onkeydown: (e: KeyboardEvent) => {
|
|
314
|
-
if (
|
|
330
|
+
if (
|
|
331
|
+
e.key === "Enter" ||
|
|
332
|
+
e.key === " " ||
|
|
333
|
+
e.key === "ArrowDown"
|
|
334
|
+
) {
|
|
315
335
|
e.preventDefault();
|
|
316
336
|
this.getAction()?.open();
|
|
317
337
|
}
|
|
@@ -326,7 +346,7 @@ export class SelectBox extends Lifecycle {
|
|
|
326
346
|
},
|
|
327
347
|
},
|
|
328
348
|
},
|
|
329
|
-
null
|
|
349
|
+
null,
|
|
330
350
|
);
|
|
331
351
|
|
|
332
352
|
this.container = container;
|
|
@@ -350,7 +370,9 @@ export class SelectBox extends Lifecycle {
|
|
|
350
370
|
} else {
|
|
351
371
|
optionModelManager.setupRecyclerView(RecyclerView);
|
|
352
372
|
}
|
|
353
|
-
optionModelManager.createModelResources(
|
|
373
|
+
optionModelManager.createModelResources(
|
|
374
|
+
Libs.parseSelectToArray(select),
|
|
375
|
+
);
|
|
354
376
|
|
|
355
377
|
optionModelManager.on("onUpdate", () => {
|
|
356
378
|
container.popup?.triggerResize?.();
|
|
@@ -360,7 +382,7 @@ export class SelectBox extends Lifecycle {
|
|
|
360
382
|
|
|
361
383
|
// Popup
|
|
362
384
|
const popup = new Popup(select, options, optionModelManager);
|
|
363
|
-
container.popup = popup
|
|
385
|
+
container.popup = popup;
|
|
364
386
|
popup!.setupEffector(effector);
|
|
365
387
|
popup!.setupInfiniteScroll(searchController, options);
|
|
366
388
|
|
|
@@ -377,8 +399,19 @@ export class SelectBox extends Lifecycle {
|
|
|
377
399
|
accessoryBox.setRoot(container.tags.ViewPanel);
|
|
378
400
|
accessoryBox.setModelManager(optionModelManager);
|
|
379
401
|
|
|
380
|
-
this.setupEventHandlers(
|
|
381
|
-
|
|
402
|
+
this.setupEventHandlers(
|
|
403
|
+
select,
|
|
404
|
+
container,
|
|
405
|
+
options,
|
|
406
|
+
searchController,
|
|
407
|
+
searchbox,
|
|
408
|
+
);
|
|
409
|
+
this.setupObservers(
|
|
410
|
+
selectObserver,
|
|
411
|
+
datasetObserver,
|
|
412
|
+
select,
|
|
413
|
+
optionModelManager,
|
|
414
|
+
);
|
|
382
415
|
|
|
383
416
|
this.plugins = this.Selective?.getPlugins?.() ?? [];
|
|
384
417
|
if (this.plugins.length) {
|
|
@@ -392,7 +425,9 @@ export class SelectBox extends Lifecycle {
|
|
|
392
425
|
actions: this.getAction(),
|
|
393
426
|
};
|
|
394
427
|
this.pluginContext = pluginContext;
|
|
395
|
-
this.runPluginHook("init", (plugin) =>
|
|
428
|
+
this.runPluginHook("init", (plugin) =>
|
|
429
|
+
plugin.init?.(pluginContext),
|
|
430
|
+
);
|
|
396
431
|
}
|
|
397
432
|
|
|
398
433
|
// Initial states
|
|
@@ -427,10 +462,13 @@ export class SelectBox extends Lifecycle {
|
|
|
427
462
|
select.parentNode?.insertBefore(this.node, select);
|
|
428
463
|
this.node.insertBefore(select, container.tags.ViewPanel);
|
|
429
464
|
|
|
430
|
-
container.tags.ViewPanel.addEventListener(
|
|
431
|
-
|
|
432
|
-
e
|
|
433
|
-
|
|
465
|
+
container.tags.ViewPanel.addEventListener(
|
|
466
|
+
"mousedown",
|
|
467
|
+
(e: MouseEvent) => {
|
|
468
|
+
e.stopPropagation();
|
|
469
|
+
e.preventDefault();
|
|
470
|
+
},
|
|
471
|
+
);
|
|
434
472
|
|
|
435
473
|
Refresher.resizeBox(select, container.tags.ViewPanel);
|
|
436
474
|
select.classList.add("init");
|
|
@@ -495,10 +533,10 @@ export class SelectBox extends Lifecycle {
|
|
|
495
533
|
container: ContainerRuntime,
|
|
496
534
|
options: SelectiveOptions,
|
|
497
535
|
searchController: SearchController,
|
|
498
|
-
searchbox: SearchBox
|
|
536
|
+
searchbox: SearchBox,
|
|
499
537
|
): void {
|
|
500
538
|
const optionAdapter = container.popup!.optionAdapter;
|
|
501
|
-
let hightlightTimer:
|
|
539
|
+
let hightlightTimer: NodeJS.Timeout | null = null;
|
|
502
540
|
|
|
503
541
|
const searchHandle = (keyword: string, isTrigger: boolean) => {
|
|
504
542
|
if (!isTrigger && keyword === "") {
|
|
@@ -510,7 +548,9 @@ export class SelectBox extends Lifecycle {
|
|
|
510
548
|
.search(keyword)
|
|
511
549
|
.then((result: any) => {
|
|
512
550
|
clearTimeout(hightlightTimer!);
|
|
513
|
-
Libs.callbackScheduler.clear(
|
|
551
|
+
Libs.callbackScheduler.clear(
|
|
552
|
+
`sche_vis_proxy_${optionAdapter.adapterKey}`,
|
|
553
|
+
);
|
|
514
554
|
Libs.callbackScheduler.on(
|
|
515
555
|
`sche_vis_proxy_${optionAdapter.adapterKey}`,
|
|
516
556
|
() => {
|
|
@@ -523,7 +563,7 @@ export class SelectBox extends Lifecycle {
|
|
|
523
563
|
}, options.animationtime ?? 0);
|
|
524
564
|
}
|
|
525
565
|
},
|
|
526
|
-
{ debounce: 10 }
|
|
566
|
+
{ debounce: 10 },
|
|
527
567
|
);
|
|
528
568
|
})
|
|
529
569
|
.catch((error: unknown) => {
|
|
@@ -532,7 +572,7 @@ export class SelectBox extends Lifecycle {
|
|
|
532
572
|
}
|
|
533
573
|
};
|
|
534
574
|
|
|
535
|
-
let searchHandleTimer:
|
|
575
|
+
let searchHandleTimer: NodeJS.Timeout | null = null;
|
|
536
576
|
|
|
537
577
|
searchbox.onSearch = (keyword: string, isTrigger: boolean) => {
|
|
538
578
|
if (!searchController.compareSearchTrigger(keyword)) return;
|
|
@@ -600,7 +640,7 @@ export class SelectBox extends Lifecycle {
|
|
|
600
640
|
selectObserver: SelectObserver,
|
|
601
641
|
datasetObserver: DatasetObserver,
|
|
602
642
|
select: HTMLSelectElement,
|
|
603
|
-
optionModelManager: ModelManager<MixedItem, MixedAdapter
|
|
643
|
+
optionModelManager: ModelManager<MixedItem, MixedAdapter>,
|
|
604
644
|
): void {
|
|
605
645
|
selectObserver.connect();
|
|
606
646
|
selectObserver.onChanged = (sel) => {
|
|
@@ -727,7 +767,7 @@ export class SelectBox extends Lifecycle {
|
|
|
727
767
|
*
|
|
728
768
|
* @returns An action facade for controlling this instance, or `null` if not bound.
|
|
729
769
|
*/
|
|
730
|
-
public getAction(): SelectBoxAction
|
|
770
|
+
public getAction?(): SelectBoxAction {
|
|
731
771
|
const container = this.container;
|
|
732
772
|
const superThis = this;
|
|
733
773
|
const getInstance = () => {
|
|
@@ -764,7 +804,11 @@ export class SelectBox extends Lifecycle {
|
|
|
764
804
|
get value() {
|
|
765
805
|
const item_list = this.valueArray as string[];
|
|
766
806
|
const valLength = item_list.length;
|
|
767
|
-
return valLength > 1
|
|
807
|
+
return valLength > 1
|
|
808
|
+
? item_list
|
|
809
|
+
: valLength === 0
|
|
810
|
+
? ""
|
|
811
|
+
: item_list[0];
|
|
768
812
|
},
|
|
769
813
|
|
|
770
814
|
get valueArray() {
|
|
@@ -803,7 +847,11 @@ export class SelectBox extends Lifecycle {
|
|
|
803
847
|
item_list.push(m.text);
|
|
804
848
|
});
|
|
805
849
|
const valLength = item_list.length;
|
|
806
|
-
return valLength > 1
|
|
850
|
+
return valLength > 1
|
|
851
|
+
? item_list
|
|
852
|
+
: valLength === 0
|
|
853
|
+
? ""
|
|
854
|
+
: item_list[0];
|
|
807
855
|
},
|
|
808
856
|
|
|
809
857
|
get isOpen() {
|
|
@@ -814,10 +862,16 @@ export class SelectBox extends Lifecycle {
|
|
|
814
862
|
return container.view.parentElement;
|
|
815
863
|
},
|
|
816
864
|
|
|
817
|
-
valueDataset(
|
|
865
|
+
valueDataset(
|
|
866
|
+
_evtToken?: IEventCallback,
|
|
867
|
+
strDataset: string = null,
|
|
868
|
+
isArray: boolean = false,
|
|
869
|
+
) {
|
|
818
870
|
var item_list = [];
|
|
819
871
|
superThis.getModelOption(true).forEach((m) => {
|
|
820
|
-
item_list.push(
|
|
872
|
+
item_list.push(
|
|
873
|
+
strDataset ? m.dataset[strDataset] : m.dataset,
|
|
874
|
+
);
|
|
821
875
|
});
|
|
822
876
|
|
|
823
877
|
if (!isArray) {
|
|
@@ -833,13 +887,21 @@ export class SelectBox extends Lifecycle {
|
|
|
833
887
|
|
|
834
888
|
selectAll(_evtToken?: IEventCallback, trigger: boolean = true) {
|
|
835
889
|
if (bindedOptions.multiple && bindedOptions.maxSelected > 0) {
|
|
836
|
-
if (
|
|
890
|
+
if (
|
|
891
|
+
superThis.getModelOption().length >
|
|
892
|
+
bindedOptions.maxSelected
|
|
893
|
+
)
|
|
894
|
+
return;
|
|
837
895
|
}
|
|
838
896
|
|
|
839
|
-
if (this.disabled || this.readonly || !bindedOptions.multiple)
|
|
897
|
+
if (this.disabled || this.readonly || !bindedOptions.multiple)
|
|
898
|
+
return;
|
|
840
899
|
|
|
841
900
|
if (trigger) {
|
|
842
|
-
const beforeChangeToken = iEvents.callEvent(
|
|
901
|
+
const beforeChangeToken = iEvents.callEvent(
|
|
902
|
+
[getInstance()],
|
|
903
|
+
...bindedOptions.on.beforeChange,
|
|
904
|
+
);
|
|
843
905
|
if (beforeChangeToken.isCancel) return;
|
|
844
906
|
superThis.oldValue = this.value;
|
|
845
907
|
}
|
|
@@ -852,10 +914,14 @@ export class SelectBox extends Lifecycle {
|
|
|
852
914
|
},
|
|
853
915
|
|
|
854
916
|
deSelectAll(_evtToken?: IEventCallback, trigger: boolean = true) {
|
|
855
|
-
if (this.disabled || this.readonly || !bindedOptions.multiple)
|
|
917
|
+
if (this.disabled || this.readonly || !bindedOptions.multiple)
|
|
918
|
+
return;
|
|
856
919
|
|
|
857
920
|
if (trigger) {
|
|
858
|
-
const beforeChangeToken = iEvents.callEvent(
|
|
921
|
+
const beforeChangeToken = iEvents.callEvent(
|
|
922
|
+
[getInstance()],
|
|
923
|
+
...bindedOptions.on.beforeChange,
|
|
924
|
+
);
|
|
859
925
|
if (beforeChangeToken.isCancel) return;
|
|
860
926
|
superThis.oldValue = this.value;
|
|
861
927
|
}
|
|
@@ -867,14 +933,22 @@ export class SelectBox extends Lifecycle {
|
|
|
867
933
|
this.change(false, trigger);
|
|
868
934
|
},
|
|
869
935
|
|
|
870
|
-
deSelectByDataset(
|
|
936
|
+
deSelectByDataset(
|
|
937
|
+
_evtToken?: IEventCallback,
|
|
938
|
+
dataset?: any,
|
|
939
|
+
trigger: boolean = true,
|
|
940
|
+
) {
|
|
871
941
|
if (dataset) {
|
|
872
|
-
superThis.getModelOption().forEach(optionModel => {
|
|
942
|
+
superThis.getModelOption().forEach((optionModel) => {
|
|
873
943
|
if (optionModel.dataset) {
|
|
874
944
|
for (let searchKey in dataset) {
|
|
875
945
|
let value = dataset[searchKey];
|
|
876
946
|
!Array.isArray(value) && (value = [value]);
|
|
877
|
-
if (
|
|
947
|
+
if (
|
|
948
|
+
value.includes(
|
|
949
|
+
optionModel.dataset[searchKey],
|
|
950
|
+
)
|
|
951
|
+
) {
|
|
878
952
|
optionModel.selectedNonTrigger = false;
|
|
879
953
|
}
|
|
880
954
|
}
|
|
@@ -884,19 +958,28 @@ export class SelectBox extends Lifecycle {
|
|
|
884
958
|
}
|
|
885
959
|
},
|
|
886
960
|
|
|
887
|
-
setValue(
|
|
961
|
+
setValue(
|
|
962
|
+
_evtToken?: IEventCallback,
|
|
963
|
+
value?: any,
|
|
964
|
+
trigger: boolean = true,
|
|
965
|
+
force: boolean = false,
|
|
966
|
+
) {
|
|
888
967
|
if (!Array.isArray(value)) value = [value];
|
|
889
968
|
value = value.filter((v: any) => v !== "" && v != null);
|
|
890
969
|
|
|
891
970
|
if (value.length === 0) {
|
|
892
|
-
superThis
|
|
971
|
+
superThis
|
|
972
|
+
.getModelOption()
|
|
973
|
+
.forEach((m) => (m.selectedNonTrigger = false));
|
|
893
974
|
this.change(false, trigger);
|
|
894
975
|
return;
|
|
895
976
|
}
|
|
896
977
|
|
|
897
978
|
if (bindedOptions.multiple && bindedOptions.maxSelected > 0) {
|
|
898
979
|
if (value.length > bindedOptions.maxSelected) {
|
|
899
|
-
console.warn(
|
|
980
|
+
console.warn(
|
|
981
|
+
`Cannot select more than ${bindedOptions.maxSelected} items`,
|
|
982
|
+
);
|
|
900
983
|
return;
|
|
901
984
|
}
|
|
902
985
|
}
|
|
@@ -905,33 +988,53 @@ export class SelectBox extends Lifecycle {
|
|
|
905
988
|
|
|
906
989
|
// AJAX: load missing values
|
|
907
990
|
if (container.searchController?.isAjax?.()) {
|
|
908
|
-
const { missing } =
|
|
991
|
+
const { missing } =
|
|
992
|
+
container.searchController.checkMissingValues(value);
|
|
909
993
|
|
|
910
994
|
if (missing.length > 0) {
|
|
911
995
|
(async () => {
|
|
912
|
-
if (bindedOptions.loadingfield)
|
|
996
|
+
if (bindedOptions.loadingfield)
|
|
997
|
+
container.popup?.showLoading?.();
|
|
913
998
|
|
|
914
999
|
try {
|
|
915
1000
|
container.searchController.resetPagination();
|
|
916
|
-
const result =
|
|
1001
|
+
const result =
|
|
1002
|
+
await container.searchController.loadByValues(
|
|
1003
|
+
missing,
|
|
1004
|
+
);
|
|
917
1005
|
if (result.success && result.items.length > 0) {
|
|
918
1006
|
result.items.forEach((it: any) => {
|
|
919
|
-
if (
|
|
1007
|
+
if (
|
|
1008
|
+
missing.includes(it.value) ||
|
|
1009
|
+
missing.includes(it.text)
|
|
1010
|
+
)
|
|
1011
|
+
it.selected = true;
|
|
920
1012
|
});
|
|
921
1013
|
|
|
922
|
-
container.searchController.applyAjaxResult?.(
|
|
923
|
-
|
|
1014
|
+
container.searchController.applyAjaxResult?.(
|
|
1015
|
+
result.items,
|
|
1016
|
+
false,
|
|
1017
|
+
false,
|
|
1018
|
+
);
|
|
1019
|
+
|
|
924
1020
|
setTimeout(() => {
|
|
925
1021
|
container.searchController.resetPagination();
|
|
926
1022
|
this.change(false, trigger);
|
|
927
1023
|
}, 200);
|
|
928
1024
|
} else if (missing.length > 0) {
|
|
929
|
-
console.warn(
|
|
1025
|
+
console.warn(
|
|
1026
|
+
`Could not load ${missing.length} values:`,
|
|
1027
|
+
missing,
|
|
1028
|
+
);
|
|
930
1029
|
}
|
|
931
1030
|
} catch (error) {
|
|
932
|
-
console.error(
|
|
1031
|
+
console.error(
|
|
1032
|
+
"Error loading missing values:",
|
|
1033
|
+
error,
|
|
1034
|
+
);
|
|
933
1035
|
} finally {
|
|
934
|
-
if (bindedOptions.loadingfield)
|
|
1036
|
+
if (bindedOptions.loadingfield)
|
|
1037
|
+
container.popup?.hideLoading?.();
|
|
935
1038
|
}
|
|
936
1039
|
})();
|
|
937
1040
|
return;
|
|
@@ -939,7 +1042,10 @@ export class SelectBox extends Lifecycle {
|
|
|
939
1042
|
}
|
|
940
1043
|
|
|
941
1044
|
if (trigger) {
|
|
942
|
-
const beforeChangeToken = iEvents.callEvent(
|
|
1045
|
+
const beforeChangeToken = iEvents.callEvent(
|
|
1046
|
+
[getInstance()],
|
|
1047
|
+
...bindedOptions.on.beforeChange,
|
|
1048
|
+
);
|
|
943
1049
|
if (beforeChangeToken.isCancel) return;
|
|
944
1050
|
superThis.oldValue = this.value;
|
|
945
1051
|
}
|
|
@@ -956,18 +1062,24 @@ export class SelectBox extends Lifecycle {
|
|
|
956
1062
|
},
|
|
957
1063
|
|
|
958
1064
|
load() {
|
|
959
|
-
if (
|
|
1065
|
+
if (
|
|
1066
|
+
(!superThis.hasLoadedOnce || superThis.isBeforeSearch) &&
|
|
1067
|
+
bindedOptions?.ajax
|
|
1068
|
+
) {
|
|
960
1069
|
container.searchController.resetPagination();
|
|
961
1070
|
container.popup.showLoading();
|
|
962
1071
|
superThis.hasLoadedOnce = true;
|
|
963
1072
|
superThis.isBeforeSearch = false;
|
|
964
1073
|
|
|
965
1074
|
setTimeout(() => {
|
|
966
|
-
if (!container.popup || !container.searchController)
|
|
1075
|
+
if (!container.popup || !container.searchController)
|
|
1076
|
+
return;
|
|
967
1077
|
container.searchController
|
|
968
1078
|
.search("")
|
|
969
1079
|
.then(() => container.popup?.triggerResize?.())
|
|
970
|
-
.catch((err: unknown) =>
|
|
1080
|
+
.catch((err: unknown) =>
|
|
1081
|
+
console.error("Initial ajax load error:", err),
|
|
1082
|
+
);
|
|
971
1083
|
}, bindedOptions.animationtime);
|
|
972
1084
|
container.popup.load();
|
|
973
1085
|
} else {
|
|
@@ -988,7 +1100,10 @@ export class SelectBox extends Lifecycle {
|
|
|
988
1100
|
return;
|
|
989
1101
|
}
|
|
990
1102
|
|
|
991
|
-
const beforeShowToken = iEvents.callEvent(
|
|
1103
|
+
const beforeShowToken = iEvents.callEvent(
|
|
1104
|
+
[getInstance()],
|
|
1105
|
+
...bindedOptions.on.beforeShow,
|
|
1106
|
+
);
|
|
992
1107
|
if (beforeShowToken.isCancel) {
|
|
993
1108
|
return;
|
|
994
1109
|
}
|
|
@@ -1005,15 +1120,24 @@ export class SelectBox extends Lifecycle {
|
|
|
1005
1120
|
}
|
|
1006
1121
|
|
|
1007
1122
|
this.load();
|
|
1008
|
-
container.popup.open(
|
|
1123
|
+
container.popup.open(
|
|
1124
|
+
null,
|
|
1125
|
+
!container.popup.loadingState.isVisible,
|
|
1126
|
+
);
|
|
1009
1127
|
|
|
1010
1128
|
container.searchbox.show();
|
|
1011
1129
|
|
|
1012
1130
|
const ViewPanel: HTMLElement = container.tags.ViewPanel;
|
|
1013
1131
|
ViewPanel.setAttribute("aria-expanded", "true");
|
|
1014
|
-
ViewPanel.setAttribute(
|
|
1132
|
+
ViewPanel.setAttribute(
|
|
1133
|
+
"aria-controls",
|
|
1134
|
+
bindedOptions.SEID_LIST,
|
|
1135
|
+
);
|
|
1015
1136
|
ViewPanel.setAttribute("aria-haspopup", "listbox");
|
|
1016
|
-
ViewPanel.setAttribute(
|
|
1137
|
+
ViewPanel.setAttribute(
|
|
1138
|
+
"aria-labelledby",
|
|
1139
|
+
bindedOptions.SEID_HOLDER,
|
|
1140
|
+
);
|
|
1017
1141
|
|
|
1018
1142
|
if (bindedOptions.multiple) {
|
|
1019
1143
|
ViewPanel.setAttribute("aria-multiselectable", "true");
|
|
@@ -1021,7 +1145,9 @@ export class SelectBox extends Lifecycle {
|
|
|
1021
1145
|
|
|
1022
1146
|
iEvents.callEvent([getInstance()], ...bindedOptions.on.show);
|
|
1023
1147
|
if (superThis.pluginContext) {
|
|
1024
|
-
superThis.runPluginHook("onOpen", (plugin) =>
|
|
1148
|
+
superThis.runPluginHook("onOpen", (plugin) =>
|
|
1149
|
+
plugin.onOpen?.(superThis.pluginContext),
|
|
1150
|
+
);
|
|
1025
1151
|
}
|
|
1026
1152
|
return;
|
|
1027
1153
|
},
|
|
@@ -1029,7 +1155,10 @@ export class SelectBox extends Lifecycle {
|
|
|
1029
1155
|
close() {
|
|
1030
1156
|
if (!superThis.isOpen) return;
|
|
1031
1157
|
|
|
1032
|
-
const beforeCloseToken = iEvents.callEvent(
|
|
1158
|
+
const beforeCloseToken = iEvents.callEvent(
|
|
1159
|
+
[getInstance()],
|
|
1160
|
+
...bindedOptions.on.beforeClose,
|
|
1161
|
+
);
|
|
1033
1162
|
if (beforeCloseToken.isCancel) return;
|
|
1034
1163
|
|
|
1035
1164
|
superThis.isOpen = false;
|
|
@@ -1044,7 +1173,9 @@ export class SelectBox extends Lifecycle {
|
|
|
1044
1173
|
|
|
1045
1174
|
iEvents.callEvent([getInstance()], ...bindedOptions.on.close);
|
|
1046
1175
|
if (superThis.pluginContext) {
|
|
1047
|
-
superThis.runPluginHook("onClose", (plugin) =>
|
|
1176
|
+
superThis.runPluginHook("onClose", (plugin) =>
|
|
1177
|
+
plugin.onClose?.(superThis.pluginContext),
|
|
1178
|
+
);
|
|
1048
1179
|
}
|
|
1049
1180
|
return;
|
|
1050
1181
|
},
|
|
@@ -1054,10 +1185,15 @@ export class SelectBox extends Lifecycle {
|
|
|
1054
1185
|
else this.open();
|
|
1055
1186
|
},
|
|
1056
1187
|
|
|
1057
|
-
change(_evtToken
|
|
1188
|
+
change(_evtToken?: IEventCallback, canTrigger: boolean = true) {
|
|
1058
1189
|
if (canTrigger) {
|
|
1059
|
-
if (
|
|
1060
|
-
|
|
1190
|
+
if (
|
|
1191
|
+
bindedOptions.multiple &&
|
|
1192
|
+
bindedOptions.maxSelected > 0
|
|
1193
|
+
) {
|
|
1194
|
+
if (
|
|
1195
|
+
this.valueArray.length > bindedOptions.maxSelected
|
|
1196
|
+
) {
|
|
1061
1197
|
this.setValue(null, this.oldValue, false, true);
|
|
1062
1198
|
}
|
|
1063
1199
|
}
|
|
@@ -1067,7 +1203,10 @@ export class SelectBox extends Lifecycle {
|
|
|
1067
1203
|
return;
|
|
1068
1204
|
}
|
|
1069
1205
|
|
|
1070
|
-
const beforeChangeToken = iEvents.callEvent(
|
|
1206
|
+
const beforeChangeToken = iEvents.callEvent(
|
|
1207
|
+
[getInstance(), this.value],
|
|
1208
|
+
...bindedOptions.on.beforeChange,
|
|
1209
|
+
);
|
|
1071
1210
|
if (beforeChangeToken.isCancel) {
|
|
1072
1211
|
this.setValue(null, this.oldValue, false);
|
|
1073
1212
|
return;
|
|
@@ -1078,8 +1217,12 @@ export class SelectBox extends Lifecycle {
|
|
|
1078
1217
|
container.accessorybox.setModelData(this.valueOptions);
|
|
1079
1218
|
|
|
1080
1219
|
if (canTrigger) {
|
|
1081
|
-
if (container.targetElement)
|
|
1082
|
-
|
|
1220
|
+
if (container.targetElement)
|
|
1221
|
+
iEvents.trigger(container.targetElement, "change");
|
|
1222
|
+
iEvents.callEvent(
|
|
1223
|
+
[getInstance(), this.value],
|
|
1224
|
+
...bindedOptions.on.change,
|
|
1225
|
+
);
|
|
1083
1226
|
|
|
1084
1227
|
if (superThis.options?.autoclose) this.close();
|
|
1085
1228
|
}
|
|
@@ -1090,9 +1233,15 @@ export class SelectBox extends Lifecycle {
|
|
|
1090
1233
|
}
|
|
1091
1234
|
|
|
1092
1235
|
if (superThis.pluginContext && superThis.optionModelManager) {
|
|
1093
|
-
const resources =
|
|
1236
|
+
const resources =
|
|
1237
|
+
superThis.optionModelManager.getResources();
|
|
1094
1238
|
superThis.runPluginHook("onChange", (plugin) =>
|
|
1095
|
-
plugin.onChange?.(
|
|
1239
|
+
plugin.onChange?.(
|
|
1240
|
+
this.value,
|
|
1241
|
+
resources.modelList,
|
|
1242
|
+
resources.adapter,
|
|
1243
|
+
superThis.pluginContext,
|
|
1244
|
+
),
|
|
1096
1245
|
);
|
|
1097
1246
|
}
|
|
1098
1247
|
},
|
|
@@ -1100,7 +1249,10 @@ export class SelectBox extends Lifecycle {
|
|
|
1100
1249
|
refreshMask() {
|
|
1101
1250
|
let mask = bindedOptions.placeholder;
|
|
1102
1251
|
|
|
1103
|
-
if (
|
|
1252
|
+
if (
|
|
1253
|
+
!bindedOptions.multiple &&
|
|
1254
|
+
superThis.getModelOption().length > 0
|
|
1255
|
+
) {
|
|
1104
1256
|
mask = this.mask[0];
|
|
1105
1257
|
}
|
|
1106
1258
|
|
|
@@ -1110,7 +1262,11 @@ export class SelectBox extends Lifecycle {
|
|
|
1110
1262
|
container.searchbox.setPlaceHolder(mask);
|
|
1111
1263
|
},
|
|
1112
1264
|
|
|
1113
|
-
on(
|
|
1265
|
+
on(
|
|
1266
|
+
_evtToken: IEventCallback,
|
|
1267
|
+
evtName: string,
|
|
1268
|
+
handle: (...args: any[]) => any,
|
|
1269
|
+
) {
|
|
1114
1270
|
if (!bindedOptions.on[evtName]) bindedOptions.on[evtName] = [];
|
|
1115
1271
|
bindedOptions.on[evtName].push(handle);
|
|
1116
1272
|
},
|
|
@@ -1183,7 +1339,7 @@ export class SelectBox extends Lifecycle {
|
|
|
1183
1339
|
private createSymProp(
|
|
1184
1340
|
obj: Record<string, any>,
|
|
1185
1341
|
prop: "disabled" | "readonly" | "visible",
|
|
1186
|
-
privateProp: "isDisabled" | "isReadOnly" | "isVisible"
|
|
1342
|
+
privateProp: "isDisabled" | "isReadOnly" | "isVisible",
|
|
1187
1343
|
): void {
|
|
1188
1344
|
const superThis = this;
|
|
1189
1345
|
|
|
@@ -1194,7 +1350,8 @@ export class SelectBox extends Lifecycle {
|
|
|
1194
1350
|
set(value: any) {
|
|
1195
1351
|
superThis[privateProp] = !!value;
|
|
1196
1352
|
if (superThis.container?.targetElement?.dataset) {
|
|
1197
|
-
superThis.container.targetElement.dataset[prop] =
|
|
1353
|
+
superThis.container.targetElement.dataset[prop] =
|
|
1354
|
+
String(!!value);
|
|
1198
1355
|
}
|
|
1199
1356
|
},
|
|
1200
1357
|
enumerable: true,
|
|
@@ -1223,7 +1380,7 @@ export class SelectBox extends Lifecycle {
|
|
|
1223
1380
|
* @returns A flat array of option models (possibly filtered).
|
|
1224
1381
|
* @internal
|
|
1225
1382
|
*/
|
|
1226
|
-
private getModelOption(isSelected
|
|
1383
|
+
private getModelOption(isSelected?: boolean): OptionModel[] {
|
|
1227
1384
|
if (!this.optionModelManager) return [];
|
|
1228
1385
|
|
|
1229
1386
|
const { modelList } = this.optionModelManager.getResources();
|
|
@@ -1233,7 +1390,8 @@ export class SelectBox extends Lifecycle {
|
|
|
1233
1390
|
if (m instanceof OptionModel) {
|
|
1234
1391
|
flatOptions.push(m);
|
|
1235
1392
|
} else if (m instanceof GroupModel) {
|
|
1236
|
-
if (Array.isArray(m.items) && m.items.length)
|
|
1393
|
+
if (Array.isArray(m.items) && m.items.length)
|
|
1394
|
+
flatOptions.push(...m.items);
|
|
1237
1395
|
}
|
|
1238
1396
|
}
|
|
1239
1397
|
|
|
@@ -1253,7 +1411,10 @@ export class SelectBox extends Lifecycle {
|
|
|
1253
1411
|
* @param runner - Hook invocation handler.
|
|
1254
1412
|
* @internal
|
|
1255
1413
|
*/
|
|
1256
|
-
private runPluginHook(
|
|
1414
|
+
private runPluginHook(
|
|
1415
|
+
hook: string,
|
|
1416
|
+
runner: (plugin: SelectivePlugin) => void,
|
|
1417
|
+
): void {
|
|
1257
1418
|
if (!this.plugins.length) return;
|
|
1258
1419
|
|
|
1259
1420
|
this.plugins.forEach((plugin) => {
|