selective-ui 1.2.6 → 1.3.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/README.md +0 -7
- package/dist/selective-ui.esm.js +169 -79
- 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.js +2 -2
- package/dist/selective-ui.min.js.br +0 -0
- package/dist/selective-ui.umd.js +170 -80
- package/dist/selective-ui.umd.js.map +1 -1
- package/package.json +11 -2
- package/src/ts/adapter/mixed-adapter.ts +15 -3
- package/src/ts/components/popup/popup.ts +48 -21
- package/src/ts/components/selectbox.ts +48 -28
- package/src/ts/core/search-controller.ts +2 -1
- package/src/ts/global.ts +2 -2
- package/src/ts/index.ts +2 -2
- package/src/ts/models/group-model.ts +1 -2
- package/src/ts/services/ea-observer.ts +7 -5
- package/src/ts/types/components/searchbox.type.ts +6 -0
- package/src/ts/types/core/base/mixed-adapter.type.ts +9 -5
- package/src/ts/types/core/search-controller.type.ts +69 -35
- package/src/ts/types/services/select-observer.type.ts +9 -5
- package/src/ts/types/utils/istorage.type.ts +1 -0
- package/src/ts/utils/istorage.ts +3 -2
- package/src/ts/utils/libs.ts +17 -10
- package/src/ts/views/group-view.ts +31 -5
- package/src/ts/views/option-view.ts +16 -3
package/README.md
CHANGED
|
@@ -5,12 +5,5 @@ Advanced Custom Select Component - Pure JavaScript, Zero Dependencies
|
|
|
5
5
|
|
|
6
6
|
Full docs with examples: http://selective-ui.maisoft.io.vn/
|
|
7
7
|
|
|
8
|
-
## Usage
|
|
9
|
-
|
|
10
|
-
```ts
|
|
11
|
-
registerPlugin(MyPlugin);
|
|
12
|
-
bind(".my-select");
|
|
13
|
-
```
|
|
14
|
-
|
|
15
8
|
# License
|
|
16
9
|
This is commercial software. See [LICENSE](https://github.com/maihcx/selective-ui/blob/main/LICENSE) for more info.
|
package/dist/selective-ui.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Selective UI v1.
|
|
1
|
+
/*! Selective UI v1.3.0 | MIT License */
|
|
2
2
|
/**
|
|
3
3
|
* @class
|
|
4
4
|
*/
|
|
@@ -27,6 +27,7 @@ class iStorage {
|
|
|
27
27
|
autofocus: true,
|
|
28
28
|
searchable: true,
|
|
29
29
|
loadingfield: true,
|
|
30
|
+
preload: false,
|
|
30
31
|
visible: true,
|
|
31
32
|
skipError: false,
|
|
32
33
|
customDelimiter: ",",
|
|
@@ -36,8 +37,8 @@ class iStorage {
|
|
|
36
37
|
textSelectAll: "Select all",
|
|
37
38
|
textDeselectAll: "Deselect all",
|
|
38
39
|
textAccessoryDeselect: "Deselect: ",
|
|
39
|
-
animationtime: 200, //
|
|
40
|
-
delaysearchtime: 200, //
|
|
40
|
+
animationtime: 200, // milliseconds
|
|
41
|
+
delaysearchtime: 200, // milliseconds
|
|
41
42
|
allowHtml: false,
|
|
42
43
|
maxSelected: 0,
|
|
43
44
|
labelHalign: "left",
|
|
@@ -655,8 +656,7 @@ class Libs {
|
|
|
655
656
|
tmp.innerHTML = s;
|
|
656
657
|
tmp.querySelectorAll("script, style, iframe, object, embed, link").forEach((n) => n.remove());
|
|
657
658
|
tmp.querySelectorAll("*").forEach((n) => {
|
|
658
|
-
for (const
|
|
659
|
-
const a = n.attributes[k];
|
|
659
|
+
for (const a of Array.from(n.attributes)) {
|
|
660
660
|
const name = a.name ?? "";
|
|
661
661
|
const value = a.value ?? "";
|
|
662
662
|
if (/^on/i.test(name)) {
|
|
@@ -697,26 +697,34 @@ class Libs {
|
|
|
697
697
|
return s.replace(/đ/g, "d").replace(/Đ/g, "d");
|
|
698
698
|
}
|
|
699
699
|
/**
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
700
|
+
* Flattens a `<select>` element into an ordered array that includes optgroups
|
|
701
|
+
* and their child options.
|
|
702
|
+
*
|
|
703
|
+
* Notes:
|
|
704
|
+
* - Keeps original DOM order.
|
|
705
|
+
* - Adds a non-standard `__parentGroup` pointer on options inside optgroups.
|
|
706
|
+
*
|
|
707
|
+
* @param {HTMLSelectElement} selectElement - The source select element.
|
|
708
|
+
* @returns {Array<HTMLOptGroupElement | HTMLOptionElement>} Flattened node list.
|
|
703
709
|
*/
|
|
704
710
|
static parseSelectToArray(selectElement) {
|
|
705
711
|
const result = [];
|
|
706
|
-
const children =
|
|
707
|
-
children.
|
|
712
|
+
const children = selectElement.children;
|
|
713
|
+
for (let childIndex = 0; childIndex < children.length; childIndex++) {
|
|
714
|
+
const child = children[childIndex];
|
|
708
715
|
if (child.tagName === "OPTGROUP") {
|
|
709
716
|
const group = child;
|
|
710
717
|
result.push(group);
|
|
711
|
-
|
|
718
|
+
for (let optionIndex = 0; optionIndex < group.children.length; optionIndex++) {
|
|
719
|
+
const option = group.children[optionIndex];
|
|
712
720
|
option["__parentGroup"] = group;
|
|
713
721
|
result.push(option);
|
|
714
|
-
}
|
|
722
|
+
}
|
|
715
723
|
}
|
|
716
724
|
else if (child.tagName === "OPTION") {
|
|
717
725
|
result.push(child);
|
|
718
726
|
}
|
|
719
|
-
}
|
|
727
|
+
}
|
|
720
728
|
return result;
|
|
721
729
|
}
|
|
722
730
|
/**
|
|
@@ -2398,7 +2406,7 @@ class Popup extends Lifecycle {
|
|
|
2398
2406
|
}
|
|
2399
2407
|
: {};
|
|
2400
2408
|
// Load ModelManager resources into the list container
|
|
2401
|
-
this.modelManager.load(this.optionsContainer, { isMultiple: options.multiple }, recyclerViewOpt);
|
|
2409
|
+
this.modelManager.load(this.optionsContainer, { isMultiple: options.multiple, options: options }, recyclerViewOpt);
|
|
2402
2410
|
const MMResources = this.modelManager.getResources();
|
|
2403
2411
|
this.optionAdapter = MMResources.adapter;
|
|
2404
2412
|
this.recyclerView = MMResources.recyclerView;
|
|
@@ -2525,36 +2533,60 @@ class Popup extends Lifecycle {
|
|
|
2525
2533
|
setupEffector(effectorSvc) {
|
|
2526
2534
|
this.effSvc = effectorSvc;
|
|
2527
2535
|
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Loads and initializes the popup (one-time setup):
|
|
2538
|
+
* - Appends the popup node to `document.body`
|
|
2539
|
+
* - Initializes the resize observer service
|
|
2540
|
+
* - Binds the effect service to the popup element
|
|
2541
|
+
* - Blocks mousedown events inside the popup to prevent auto-close
|
|
2542
|
+
*
|
|
2543
|
+
* Safely no-ops when the popup has already been created
|
|
2544
|
+
* or required dependencies are missing.
|
|
2545
|
+
*/
|
|
2546
|
+
load() {
|
|
2547
|
+
if (!this.node || !this.parent || !this.effSvc)
|
|
2548
|
+
return;
|
|
2549
|
+
if (this.isCreated)
|
|
2550
|
+
return;
|
|
2551
|
+
document.body.appendChild(this.node);
|
|
2552
|
+
this.isCreated = true;
|
|
2553
|
+
this.resizeObser = new ResizeObserverService();
|
|
2554
|
+
this.effSvc.setElement(this.node);
|
|
2555
|
+
this.node.addEventListener("mousedown", (e) => {
|
|
2556
|
+
e.stopPropagation();
|
|
2557
|
+
e.preventDefault();
|
|
2558
|
+
});
|
|
2559
|
+
}
|
|
2528
2560
|
/**
|
|
2529
2561
|
* Opens (expands) the popup:
|
|
2530
|
-
* -
|
|
2531
|
-
* - Synchronizes
|
|
2532
|
-
* -
|
|
2533
|
-
* -
|
|
2562
|
+
* - Ensures the popup is loaded and initialized
|
|
2563
|
+
* - Synchronizes option handle visibility
|
|
2564
|
+
* - Optionally evaluates and applies the empty/not-found state
|
|
2565
|
+
* - Computes placement relative to the parent anchor
|
|
2566
|
+
* - Runs the expand animation
|
|
2567
|
+
* - Connects the resize observer after animation completes
|
|
2568
|
+
* - Resumes the recycler view
|
|
2569
|
+
*
|
|
2570
|
+
* Safely no-ops when required dependencies are missing.
|
|
2534
2571
|
*
|
|
2535
2572
|
* @param callback - Optional callback invoked when the opening animation completes.
|
|
2536
|
-
* @param isShowEmptyState - If true,
|
|
2573
|
+
* @param isShowEmptyState - If true, applies the empty/not-found state before animation.
|
|
2537
2574
|
*/
|
|
2538
2575
|
open(callback = null, isShowEmptyState) {
|
|
2539
2576
|
if (!this.node || !this.options || !this.optionHandle || !this.parent || !this.effSvc)
|
|
2540
2577
|
return;
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
this.resizeObser = new ResizeObserverService();
|
|
2545
|
-
this.effSvc.setElement(this.node);
|
|
2546
|
-
// Prevent the popup from closing when clicking inside
|
|
2547
|
-
this.node.addEventListener("mousedown", (e) => {
|
|
2548
|
-
e.stopPropagation();
|
|
2549
|
-
e.preventDefault();
|
|
2550
|
-
});
|
|
2551
|
-
}
|
|
2578
|
+
// Ensure one-time initialization
|
|
2579
|
+
this.load();
|
|
2580
|
+
// Sync option visibility state
|
|
2552
2581
|
this.optionHandle.update();
|
|
2582
|
+
// Apply empty state if requested
|
|
2553
2583
|
if (isShowEmptyState) {
|
|
2554
2584
|
this.updateEmptyState();
|
|
2555
2585
|
}
|
|
2586
|
+
// Compute placement based on parent anchor
|
|
2556
2587
|
const location = this.getParentLocation();
|
|
2557
2588
|
const { position, top, maxHeight, realHeight } = this.calculatePosition(location);
|
|
2589
|
+
// Run expand animation
|
|
2558
2590
|
this.effSvc.expand({
|
|
2559
2591
|
duration: this.options.animationtime,
|
|
2560
2592
|
display: "flex",
|
|
@@ -2567,13 +2599,14 @@ class Popup extends Lifecycle {
|
|
|
2567
2599
|
onComplete: () => {
|
|
2568
2600
|
if (!this.resizeObser || !this.parent)
|
|
2569
2601
|
return;
|
|
2602
|
+
// Recompute position on parent resize to keep behavior consistent
|
|
2570
2603
|
this.resizeObser.onChanged = (_metrics) => {
|
|
2571
|
-
// Recompute from parent each time to keep behavior identical.
|
|
2572
2604
|
const loc = this.getParentLocation();
|
|
2573
2605
|
this.handleResize(loc);
|
|
2574
2606
|
};
|
|
2575
2607
|
this.resizeObser.connect(this.parent.container.tags.ViewPanel);
|
|
2576
2608
|
callback?.();
|
|
2609
|
+
// Resume recycler view rendering after animation
|
|
2577
2610
|
const rv = this.recyclerView;
|
|
2578
2611
|
rv?.resume?.();
|
|
2579
2612
|
},
|
|
@@ -3782,6 +3815,7 @@ class GroupModel extends Model {
|
|
|
3782
3815
|
*/
|
|
3783
3816
|
this.privOnCollapsedChanged = [];
|
|
3784
3817
|
this.label = this.targetElement.label;
|
|
3818
|
+
this.collapsed = Libs.string2Boolean(this.targetElement.dataset?.collapsed);
|
|
3785
3819
|
}
|
|
3786
3820
|
/**
|
|
3787
3821
|
* Initializes group state from the backing `<optgroup>` (if present) and mounts the model.
|
|
@@ -3798,7 +3832,6 @@ class GroupModel extends Model {
|
|
|
3798
3832
|
* @override
|
|
3799
3833
|
*/
|
|
3800
3834
|
init() {
|
|
3801
|
-
this.collapsed = Libs.string2Boolean(this.targetElement.dataset?.collapsed);
|
|
3802
3835
|
super.init();
|
|
3803
3836
|
this.mount();
|
|
3804
3837
|
}
|
|
@@ -5518,7 +5551,8 @@ class SearchController extends Lifecycle {
|
|
|
5518
5551
|
.join(",");
|
|
5519
5552
|
let payload;
|
|
5520
5553
|
if (typeof cfg.data === "function") {
|
|
5521
|
-
|
|
5554
|
+
const selectiveInstance = this.selectBox?.Selective?.find(this.selectBox?.container?.targetElement);
|
|
5555
|
+
payload = cfg.data.call(selectiveInstance, keyword, page);
|
|
5522
5556
|
if (payload && typeof payload.selectedValue === "undefined")
|
|
5523
5557
|
payload.selectedValue = selectedValues;
|
|
5524
5558
|
}
|
|
@@ -6463,8 +6497,18 @@ class View extends Lifecycle {
|
|
|
6463
6497
|
* @see {@link View}
|
|
6464
6498
|
*/
|
|
6465
6499
|
class GroupView extends View {
|
|
6466
|
-
|
|
6467
|
-
|
|
6500
|
+
/**
|
|
6501
|
+
* Creates a new GroupView bound to the given parent element.
|
|
6502
|
+
*
|
|
6503
|
+
* Initialization flow:
|
|
6504
|
+
* 1. Calls `super(parent)` (View base constructor).
|
|
6505
|
+
*
|
|
6506
|
+
* @public
|
|
6507
|
+
* @param {HTMLElement} parent - Container element that will host this group view.
|
|
6508
|
+
* @param {SelectiveOptions} options - Optional configuration for this group view.
|
|
6509
|
+
*/
|
|
6510
|
+
constructor(parent, options) {
|
|
6511
|
+
super(parent);
|
|
6468
6512
|
/**
|
|
6469
6513
|
* Strongly-typed reference to the mounted group view structure.
|
|
6470
6514
|
*
|
|
@@ -6479,6 +6523,16 @@ class GroupView extends View {
|
|
|
6479
6523
|
* @public
|
|
6480
6524
|
*/
|
|
6481
6525
|
this.view = null;
|
|
6526
|
+
/**
|
|
6527
|
+
* Parsed configuration (bound from the `<select>` element via binder map).
|
|
6528
|
+
*
|
|
6529
|
+
* Provides feature flags (multiple/disabled/readonly/visible/virtualScroll/ajax/autoclose…),
|
|
6530
|
+
* a11y ids (e.g. `SEID_LIST`, `SEID_HOLDER`) and user callbacks under `options.on`.
|
|
6531
|
+
*
|
|
6532
|
+
* @internal
|
|
6533
|
+
*/
|
|
6534
|
+
this.options = null;
|
|
6535
|
+
this.options = options;
|
|
6482
6536
|
}
|
|
6483
6537
|
/**
|
|
6484
6538
|
* Mounts the group view into the DOM.
|
|
@@ -6486,8 +6540,8 @@ class GroupView extends View {
|
|
|
6486
6540
|
* Creation flow:
|
|
6487
6541
|
* 1. Generates unique group ID (7-character random string).
|
|
6488
6542
|
* 2. Creates DOM structure via {@link Libs.mountNode}:
|
|
6489
|
-
* - Root: `<div role="group" aria-labelledby="seui-{id}-header">`
|
|
6490
|
-
* - Header: `<div role="presentation" id="seui-{id}-header">`
|
|
6543
|
+
* - Root: `<div role="group" aria-labelledby="seui-{this.options?.SEID || default}-{id}-header">`
|
|
6544
|
+
* - Header: `<div role="presentation" id="seui-{this.options?.SEID || default}-{id}-header">`
|
|
6491
6545
|
* - Items: `<div role="group">` (nested group for child items)
|
|
6492
6546
|
* 3. Appends root to {@link parent} container.
|
|
6493
6547
|
* 4. Transitions `INITIALIZED → MOUNTED` via `super.mount()`.
|
|
@@ -6513,8 +6567,8 @@ class GroupView extends View {
|
|
|
6513
6567
|
node: "div",
|
|
6514
6568
|
classList: ["seui-group"],
|
|
6515
6569
|
role: "group",
|
|
6516
|
-
ariaLabelledby: `seui-${group_id}-header`,
|
|
6517
|
-
id: `seui-${group_id}-group`,
|
|
6570
|
+
ariaLabelledby: `seui-${this.options?.SEID || "default"}-${group_id}-header`,
|
|
6571
|
+
id: `seui-${this.options?.SEID || "default"}-${group_id}-group`,
|
|
6518
6572
|
},
|
|
6519
6573
|
child: {
|
|
6520
6574
|
GroupHeader: {
|
|
@@ -6522,7 +6576,7 @@ class GroupView extends View {
|
|
|
6522
6576
|
node: "div",
|
|
6523
6577
|
classList: ["seui-group-header"],
|
|
6524
6578
|
role: "presentation",
|
|
6525
|
-
id: `seui-${group_id}-header`,
|
|
6579
|
+
id: `seui-${this.options?.SEID || "default"}-${group_id}-header`,
|
|
6526
6580
|
},
|
|
6527
6581
|
},
|
|
6528
6582
|
GroupItems: {
|
|
@@ -6731,8 +6785,9 @@ class OptionView extends View {
|
|
|
6731
6785
|
*
|
|
6732
6786
|
* @public
|
|
6733
6787
|
* @param {HTMLElement} parent - Container element that will host this option view.
|
|
6788
|
+
* @param {SelectiveOptions} options - Optional configuration for this option view.
|
|
6734
6789
|
*/
|
|
6735
|
-
constructor(parent) {
|
|
6790
|
+
constructor(parent, options) {
|
|
6736
6791
|
super(parent);
|
|
6737
6792
|
/**
|
|
6738
6793
|
* Strongly-typed reference to the mounted option view structure.
|
|
@@ -6748,6 +6803,15 @@ class OptionView extends View {
|
|
|
6748
6803
|
* @public
|
|
6749
6804
|
*/
|
|
6750
6805
|
this.view = null;
|
|
6806
|
+
/**
|
|
6807
|
+
* Parsed configuration (bound from the `<select>` element via binder map).
|
|
6808
|
+
*
|
|
6809
|
+
* Provides feature flags (multiple/disabled/readonly/visible/virtualScroll/ajax/autoclose…),
|
|
6810
|
+
* a11y ids (e.g. `SEID_LIST`, `SEID_HOLDER`) and user callbacks under `options.on`.
|
|
6811
|
+
*
|
|
6812
|
+
* @internal
|
|
6813
|
+
*/
|
|
6814
|
+
this.options = null;
|
|
6751
6815
|
/**
|
|
6752
6816
|
* Internal configuration object (Proxy target).
|
|
6753
6817
|
*
|
|
@@ -6789,6 +6853,7 @@ class OptionView extends View {
|
|
|
6789
6853
|
* @private
|
|
6790
6854
|
*/
|
|
6791
6855
|
this.isRendered = false;
|
|
6856
|
+
this.options = options;
|
|
6792
6857
|
this.initialize();
|
|
6793
6858
|
}
|
|
6794
6859
|
/**
|
|
@@ -6993,7 +7058,7 @@ class OptionView extends View {
|
|
|
6993
7058
|
mount() {
|
|
6994
7059
|
const viewClass = ["seui-option-view"];
|
|
6995
7060
|
const opt_id = Libs.randomString(7);
|
|
6996
|
-
const inputID = `option_${opt_id}`;
|
|
7061
|
+
const inputID = `option_${this.options?.SEID ?? "default"}_${opt_id}`;
|
|
6997
7062
|
if (this.config.isMultiple)
|
|
6998
7063
|
viewClass.push("multiple");
|
|
6999
7064
|
if (this.config.hasImage) {
|
|
@@ -7039,7 +7104,7 @@ class OptionView extends View {
|
|
|
7039
7104
|
OptionView: {
|
|
7040
7105
|
tag: {
|
|
7041
7106
|
node: "div",
|
|
7042
|
-
id: `seui-${opt_id}-option`,
|
|
7107
|
+
id: `seui-${this.options?.SEID ?? "default"}-${opt_id}-option`,
|
|
7043
7108
|
classList: viewClass,
|
|
7044
7109
|
role: "option",
|
|
7045
7110
|
ariaSelected: "false",
|
|
@@ -7253,6 +7318,15 @@ class MixedAdapter extends Adapter {
|
|
|
7253
7318
|
super(items);
|
|
7254
7319
|
/** Whether the adapter operates in multi-selection mode. */
|
|
7255
7320
|
this.isMultiple = false;
|
|
7321
|
+
/**
|
|
7322
|
+
* Parsed configuration (bound from the `<select>` element via binder map).
|
|
7323
|
+
*
|
|
7324
|
+
* Provides feature flags (multiple/disabled/readonly/visible/virtualScroll/ajax/autoclose…),
|
|
7325
|
+
* a11y ids (e.g. `SEID_LIST`, `SEID_HOLDER`) and user callbacks under `options.on`.
|
|
7326
|
+
*
|
|
7327
|
+
* @internal
|
|
7328
|
+
*/
|
|
7329
|
+
this.options = null;
|
|
7256
7330
|
/**
|
|
7257
7331
|
* Subscribers for aggregated visibility statistics.
|
|
7258
7332
|
* Fired via a debounced scheduler to avoid repeated recomputation during batch updates.
|
|
@@ -7345,8 +7419,8 @@ class MixedAdapter extends Adapter {
|
|
|
7345
7419
|
*/
|
|
7346
7420
|
viewHolder(parent, item) {
|
|
7347
7421
|
if (item instanceof GroupModel)
|
|
7348
|
-
return new GroupView(parent);
|
|
7349
|
-
return new OptionView(parent);
|
|
7422
|
+
return new GroupView(parent, this.options);
|
|
7423
|
+
return new OptionView(parent, this.options);
|
|
7350
7424
|
}
|
|
7351
7425
|
/**
|
|
7352
7426
|
* Binds a model (group or option) to its view and delegates to specialized handlers.
|
|
@@ -7414,7 +7488,7 @@ class MixedAdapter extends Adapter {
|
|
|
7414
7488
|
groupModel.items.forEach((optionModel, idx) => {
|
|
7415
7489
|
let optionViewer = optionModel.view;
|
|
7416
7490
|
if (!optionModel.isInit || !optionViewer) {
|
|
7417
|
-
optionViewer = new OptionView(itemsContainer);
|
|
7491
|
+
optionViewer = new OptionView(itemsContainer, this.options);
|
|
7418
7492
|
}
|
|
7419
7493
|
this.handleOptionView(optionModel, optionViewer, idx);
|
|
7420
7494
|
optionModel.isInit = true;
|
|
@@ -9171,16 +9245,17 @@ class SelectBox extends Lifecycle {
|
|
|
9171
9245
|
});
|
|
9172
9246
|
this.optionModelManager = optionModelManager;
|
|
9173
9247
|
// Popup
|
|
9174
|
-
|
|
9175
|
-
container.popup
|
|
9176
|
-
|
|
9177
|
-
|
|
9248
|
+
const popup = new Popup(select, options, optionModelManager);
|
|
9249
|
+
container.popup = popup;
|
|
9250
|
+
popup.setupEffector(effector);
|
|
9251
|
+
popup.setupInfiniteScroll(searchController, options);
|
|
9252
|
+
popup.onAdapterPropChanged("selected", () => {
|
|
9178
9253
|
this.getAction()?.change(null, true);
|
|
9179
9254
|
});
|
|
9180
|
-
|
|
9255
|
+
popup.onAdapterPropChanged("selected_internal", () => {
|
|
9181
9256
|
this.getAction()?.change(null, false);
|
|
9182
9257
|
});
|
|
9183
|
-
|
|
9258
|
+
popup.onAdapterPropChanging("select", () => {
|
|
9184
9259
|
this.oldValue = this.getAction()?.value ?? "";
|
|
9185
9260
|
});
|
|
9186
9261
|
accessoryBox.setRoot(container.tags.ViewPanel);
|
|
@@ -9237,7 +9312,11 @@ class SelectBox extends Lifecycle {
|
|
|
9237
9312
|
Refresher.resizeBox(select, container.tags.ViewPanel);
|
|
9238
9313
|
select.classList.add("init");
|
|
9239
9314
|
// initial mask
|
|
9240
|
-
this.getAction()
|
|
9315
|
+
const action = this.getAction();
|
|
9316
|
+
action?.change?.(null, false);
|
|
9317
|
+
if (this.options.preload) {
|
|
9318
|
+
action?.load?.();
|
|
9319
|
+
}
|
|
9241
9320
|
// Call parent lifecycle mount
|
|
9242
9321
|
super.mount();
|
|
9243
9322
|
}
|
|
@@ -9677,6 +9756,26 @@ class SelectBox extends Lifecycle {
|
|
|
9677
9756
|
}
|
|
9678
9757
|
this.change(false, trigger);
|
|
9679
9758
|
},
|
|
9759
|
+
load() {
|
|
9760
|
+
if ((!superThis.hasLoadedOnce || superThis.isBeforeSearch) && bindedOptions?.ajax) {
|
|
9761
|
+
container.searchController.resetPagination();
|
|
9762
|
+
container.popup.showLoading();
|
|
9763
|
+
superThis.hasLoadedOnce = true;
|
|
9764
|
+
superThis.isBeforeSearch = false;
|
|
9765
|
+
setTimeout(() => {
|
|
9766
|
+
if (!container.popup || !container.searchController)
|
|
9767
|
+
return;
|
|
9768
|
+
container.searchController
|
|
9769
|
+
.search("")
|
|
9770
|
+
.then(() => container.popup?.triggerResize?.())
|
|
9771
|
+
.catch((err) => console.error("Initial ajax load error:", err));
|
|
9772
|
+
}, bindedOptions.animationtime);
|
|
9773
|
+
container.popup.load();
|
|
9774
|
+
}
|
|
9775
|
+
else {
|
|
9776
|
+
container.popup.load();
|
|
9777
|
+
}
|
|
9778
|
+
},
|
|
9680
9779
|
open() {
|
|
9681
9780
|
if (superThis.isOpen)
|
|
9682
9781
|
return;
|
|
@@ -9686,45 +9785,34 @@ class SelectBox extends Lifecycle {
|
|
|
9686
9785
|
if (closeToken.isCancel)
|
|
9687
9786
|
return;
|
|
9688
9787
|
}
|
|
9689
|
-
if (this.disabled)
|
|
9788
|
+
if (this.disabled) {
|
|
9690
9789
|
return;
|
|
9790
|
+
}
|
|
9691
9791
|
const beforeShowToken = iEvents.callEvent([getInstance()], ...bindedOptions.on.beforeShow);
|
|
9692
|
-
if (beforeShowToken.isCancel)
|
|
9792
|
+
if (beforeShowToken.isCancel) {
|
|
9693
9793
|
return;
|
|
9794
|
+
}
|
|
9694
9795
|
superThis.isOpen = true;
|
|
9695
9796
|
container.directive.setDropdown(true);
|
|
9696
9797
|
const adapter = container.popup.optionAdapter;
|
|
9697
9798
|
const selectedOption = adapter.getSelectedItem();
|
|
9698
|
-
if (selectedOption)
|
|
9799
|
+
if (selectedOption) {
|
|
9699
9800
|
adapter.setHighlight(selectedOption, false);
|
|
9700
|
-
else
|
|
9701
|
-
adapter.resetHighlight();
|
|
9702
|
-
if ((!superThis.hasLoadedOnce || superThis.isBeforeSearch) && bindedOptions?.ajax) {
|
|
9703
|
-
container.searchController.resetPagination();
|
|
9704
|
-
container.popup.showLoading();
|
|
9705
|
-
superThis.hasLoadedOnce = true;
|
|
9706
|
-
superThis.isBeforeSearch = false;
|
|
9707
|
-
setTimeout(() => {
|
|
9708
|
-
if (!container.popup || !container.searchController)
|
|
9709
|
-
return;
|
|
9710
|
-
container.searchController
|
|
9711
|
-
.search("")
|
|
9712
|
-
.then(() => container.popup?.triggerResize?.())
|
|
9713
|
-
.catch((err) => console.error("Initial ajax load error:", err));
|
|
9714
|
-
}, bindedOptions.animationtime);
|
|
9715
|
-
container.popup.open(null, false);
|
|
9716
9801
|
}
|
|
9717
9802
|
else {
|
|
9718
|
-
|
|
9803
|
+
adapter.resetHighlight();
|
|
9719
9804
|
}
|
|
9805
|
+
this.load();
|
|
9806
|
+
container.popup.open(null, !container.popup.loadingState.isVisible);
|
|
9720
9807
|
container.searchbox.show();
|
|
9721
9808
|
const ViewPanel = container.tags.ViewPanel;
|
|
9722
9809
|
ViewPanel.setAttribute("aria-expanded", "true");
|
|
9723
9810
|
ViewPanel.setAttribute("aria-controls", bindedOptions.SEID_LIST);
|
|
9724
9811
|
ViewPanel.setAttribute("aria-haspopup", "listbox");
|
|
9725
9812
|
ViewPanel.setAttribute("aria-labelledby", bindedOptions.SEID_HOLDER);
|
|
9726
|
-
if (bindedOptions.multiple)
|
|
9813
|
+
if (bindedOptions.multiple) {
|
|
9727
9814
|
ViewPanel.setAttribute("aria-multiselectable", "true");
|
|
9815
|
+
}
|
|
9728
9816
|
iEvents.callEvent([getInstance()], ...bindedOptions.on.show);
|
|
9729
9817
|
if (superThis.pluginContext) {
|
|
9730
9818
|
superThis.runPluginHook("onOpen", (plugin) => plugin.onOpen?.(superThis.pluginContext));
|
|
@@ -9998,7 +10086,7 @@ class ElementAdditionObserver {
|
|
|
9998
10086
|
*
|
|
9999
10087
|
* @internal
|
|
10000
10088
|
*/
|
|
10001
|
-
this.actions =
|
|
10089
|
+
this.actions = new Set();
|
|
10002
10090
|
}
|
|
10003
10091
|
/**
|
|
10004
10092
|
* Registers a callback invoked whenever a matching element is detected as added to the DOM.
|
|
@@ -10010,7 +10098,7 @@ class ElementAdditionObserver {
|
|
|
10010
10098
|
* @param action - Function executed with the newly detected element.
|
|
10011
10099
|
*/
|
|
10012
10100
|
onDetect(action) {
|
|
10013
|
-
this.actions.
|
|
10101
|
+
this.actions.add(action);
|
|
10014
10102
|
}
|
|
10015
10103
|
/**
|
|
10016
10104
|
* Clears all registered detection callbacks.
|
|
@@ -10019,7 +10107,7 @@ class ElementAdditionObserver {
|
|
|
10019
10107
|
* to scan mutations but will not invoke any listeners until new callbacks are registered.
|
|
10020
10108
|
*/
|
|
10021
10109
|
clearDetect() {
|
|
10022
|
-
this.actions
|
|
10110
|
+
this.actions.clear();
|
|
10023
10111
|
}
|
|
10024
10112
|
/**
|
|
10025
10113
|
* Starts observing the document for additions of elements matching the given tag name.
|
|
@@ -10093,7 +10181,9 @@ class ElementAdditionObserver {
|
|
|
10093
10181
|
* @internal
|
|
10094
10182
|
*/
|
|
10095
10183
|
handle(element) {
|
|
10096
|
-
this.actions
|
|
10184
|
+
for (const action of this.actions) {
|
|
10185
|
+
action(element);
|
|
10186
|
+
}
|
|
10097
10187
|
}
|
|
10098
10188
|
}
|
|
10099
10189
|
|
|
@@ -10802,7 +10892,7 @@ const SECLASS = new Selective();
|
|
|
10802
10892
|
*
|
|
10803
10893
|
* Declared as `const` literal type to enable strict typing and easy tree-shaking.
|
|
10804
10894
|
*/
|
|
10805
|
-
const version = "1.
|
|
10895
|
+
const version = "1.3.0";
|
|
10806
10896
|
/**
|
|
10807
10897
|
* Library name identifier.
|
|
10808
10898
|
*
|