@schukai/monster 3.96.1 → 3.96.3

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +20 -5
  2. package/package.json +1 -1
  3. package/source/components/datatable/change-button.mjs +39 -41
  4. package/source/components/datatable/dataset.mjs +335 -325
  5. package/source/components/datatable/datasource/rest.mjs +33 -29
  6. package/source/components/datatable/embedded-pagination.mjs +3 -1
  7. package/source/components/datatable/filter.mjs +164 -63
  8. package/source/components/datatable/pagination.mjs +13 -6
  9. package/source/components/datatable/save-button.mjs +25 -3
  10. package/source/components/datatable/status.mjs +21 -26
  11. package/source/components/datatable/style/status.pcss +12 -2
  12. package/source/components/datatable/stylesheet/status.mjs +1 -1
  13. package/source/components/datatable/util.mjs +1 -2
  14. package/source/components/form/form.mjs +5 -4
  15. package/source/components/form/select.mjs +2008 -2013
  16. package/source/components/form/style/field-set.pcss +28 -7
  17. package/source/components/form/style/toggle-switch.pcss +13 -2
  18. package/source/components/form/stylesheet/field-set.mjs +14 -7
  19. package/source/components/form/stylesheet/toggle-switch.mjs +14 -7
  20. package/source/components/form/toggle-switch.mjs +372 -380
  21. package/source/components/layout/tabs.mjs +1 -2
  22. package/source/constants.mjs +14 -1
  23. package/source/data/extend.mjs +2 -1
  24. package/source/data/transformer.mjs +2 -0
  25. package/source/dom/constants.mjs +0 -1
  26. package/source/dom/customelement.mjs +7 -3
  27. package/source/dom/updater.mjs +5 -1
  28. package/source/monster.mjs +1 -1
  29. package/source/text/formatter.mjs +5 -3
  30. package/source/types/is.mjs +13 -0
  31. package/source/types/proxyobserver.mjs +7 -2
  32. package/source/types/version.mjs +1 -1
  33. package/source/util/clone.mjs +9 -14
  34. package/test/cases/data/pathfinder.mjs +18 -0
  35. package/test/cases/monster.mjs +1 -1
  36. package/test/cases/text/formatter.mjs +21 -1
  37. package/test/web/test.html +2 -2
  38. package/test/web/tests.js +266 -176
@@ -12,61 +12,61 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import {instanceSymbol} from "../../constants.mjs";
16
- import {internalSymbol} from "../../constants.mjs";
17
- import {buildMap} from "../../data/buildmap.mjs";
18
- import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
19
- import {positionPopper} from "./util/floating-ui.mjs";
15
+ import { instanceSymbol } from "../../constants.mjs";
16
+ import { internalSymbol } from "../../constants.mjs";
17
+ import { buildMap } from "../../data/buildmap.mjs";
18
+ import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
19
+ import { positionPopper } from "./util/floating-ui.mjs";
20
20
  import {
21
- addAttributeToken,
22
- findClosestByAttribute,
23
- removeAttributeToken,
21
+ addAttributeToken,
22
+ findClosestByAttribute,
23
+ removeAttributeToken,
24
24
  } from "../../dom/attributes.mjs";
25
25
  import {
26
- ATTRIBUTE_ERRORMESSAGE,
27
- ATTRIBUTE_PREFIX,
28
- ATTRIBUTE_ROLE,
26
+ ATTRIBUTE_ERRORMESSAGE,
27
+ ATTRIBUTE_PREFIX,
28
+ ATTRIBUTE_ROLE,
29
29
  } from "../../dom/constants.mjs";
30
- import {CustomControl} from "../../dom/customcontrol.mjs";
30
+ import { CustomControl } from "../../dom/customcontrol.mjs";
31
31
  import {
32
- assembleMethodSymbol,
33
- getSlottedElements,
34
- registerCustomElement,
32
+ assembleMethodSymbol,
33
+ getSlottedElements,
34
+ registerCustomElement,
35
35
  } from "../../dom/customelement.mjs";
36
36
  import {
37
- findTargetElementFromEvent,
38
- fireCustomEvent,
39
- fireEvent,
37
+ findTargetElementFromEvent,
38
+ fireCustomEvent,
39
+ fireEvent,
40
40
  } from "../../dom/events.mjs";
41
- import {getDocument, getWindow} from "../../dom/util.mjs";
42
- import {Formatter} from "../../text/formatter.mjs";
43
- import {getGlobal} from "../../types/global.mjs";
44
- import {ID} from "../../types/id.mjs";
41
+ import { getDocument, getWindow } from "../../dom/util.mjs";
42
+ import { Formatter } from "../../text/formatter.mjs";
43
+ import { getGlobal } from "../../types/global.mjs";
44
+ import { ID } from "../../types/id.mjs";
45
45
  import {
46
- isArray,
47
- isFunction,
48
- isInteger,
49
- isIterable,
50
- isObject,
51
- isPrimitive,
52
- isString,
46
+ isArray,
47
+ isFunction,
48
+ isInteger,
49
+ isIterable,
50
+ isObject,
51
+ isPrimitive,
52
+ isString,
53
53
  } from "../../types/is.mjs";
54
- import {Observer} from "../../types/observer.mjs";
55
- import {ProxyObserver} from "../../types/proxyobserver.mjs";
56
- import {validateArray, validateString} from "../../types/validate.mjs";
57
- import {Processing} from "../../util/processing.mjs";
58
- import {STYLE_DISPLAY_MODE_BLOCK} from "./constants.mjs";
59
- import {SelectStyleSheet} from "./stylesheet/select.mjs";
54
+ import { Observer } from "../../types/observer.mjs";
55
+ import { ProxyObserver } from "../../types/proxyobserver.mjs";
56
+ import { validateArray, validateString } from "../../types/validate.mjs";
57
+ import { Processing } from "../../util/processing.mjs";
58
+ import { STYLE_DISPLAY_MODE_BLOCK } from "./constants.mjs";
59
+ import { SelectStyleSheet } from "./stylesheet/select.mjs";
60
60
  import {
61
- getDocumentTranslations,
62
- Translations,
61
+ getDocumentTranslations,
62
+ Translations,
63
63
  } from "../../i18n/translations.mjs";
64
64
 
65
65
  export {
66
- Select,
67
- popperElementSymbol,
68
- getSummaryTemplate,
69
- getSelectionTemplate,
66
+ Select,
67
+ popperElementSymbol,
68
+ getSummaryTemplate,
69
+ getSelectionTemplate,
70
70
  };
71
71
 
72
72
  /**
@@ -199,7 +199,7 @@ const popperFilterElementSymbol = Symbol("popperFilterElement");
199
199
  * @type {Symbol}
200
200
  */
201
201
  const popperFilterContainerElementSymbol = Symbol(
202
- "popperFilterContainerElement",
202
+ "popperFilterContainerElement",
203
203
  );
204
204
 
205
205
  /**
@@ -294,613 +294,611 @@ const FILTER_POSITION_INLINE = "inline";
294
294
  * @fires monster-changed
295
295
  */
296
296
  class Select extends CustomControl {
297
- /**
298
- *
299
- */
300
- constructor() {
301
- super();
302
- initOptionObserver.call(this);
303
- }
304
-
305
- /**
306
- * This method is called by the `instanceof` operator.
307
- * @return {Symbol}
308
- */
309
- static get [instanceSymbol]() {
310
- return Symbol.for("@schukai/monster/components/form/select@@instance");
311
- }
312
-
313
- /**
314
- * The current selection of the Select
315
- *
316
- * ```
317
- * e = document.querySelector('monster-select');
318
- * console.log(e.value)
319
- * // ↦ 1
320
- * // ↦ ['1','2']
321
- * ```
322
- *
323
- * @return {string}
324
- */
325
- get value() {
326
- return convertSelectionToValue.call(this, this.getOption("selection"));
327
- }
328
-
329
- /**
330
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals}
331
- * @return {boolean}
332
- */
333
- static get formAssociated() {
334
- return true;
335
- }
336
-
337
- /**
338
- * Set selection
339
- *
340
- * ```
341
- * e = document.querySelector('monster-select');
342
- * e.value=1
343
- * ```
344
- *
345
- * @property {string|array} value
346
- * @throws {Error} unsupported type
347
- * @fires monster-selected this event is fired when the selection is set
348
- */
349
- set value(value) {
350
- const result = convertValueToSelection.call(this, value);
351
- setSelection
352
- .call(this, result.selection)
353
- .then(() => {
354
- })
355
- .catch((e) => {
356
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
357
- });
358
- }
359
-
360
- /**
361
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
362
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
363
- *
364
- * The individual configuration values can be found in the table.
365
- *
366
- * @property {Object} toggleEventType=click,touch List of event types to be observed for opening the dropdown
367
- * @property {boolean} delegatesFocus=false lorem [see mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus)
368
- * @property {Object[]} options Selection of key identifier pairs available for selection and displayed in the dropdown.
369
- * @property {string} options[].label
370
- * @property {string} options[].value
371
- * @property {string} options[].visibility hidden or visible
372
- * @property {Array} selection Selected options
373
- * @property {Integer} showMaxOptions=10 Maximum number of visible options before a scroll bar should be displayed.
374
- * @property {string} type=radio Multiple (checkbox) or single selection (radio)
375
- * @property {string} name=(random id) Name of the form field
376
- * @property {string} url Load options from server per url
377
- * @property {object} lookup Load options from server per url
378
- * @property {string} lookup.url=null Load options from server per url
379
- * @property {boolean} lookup.grouping=false Load all selected options from server per url at once (true) or one by one (false)
380
- * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
381
- * @property {String} fetch.redirect=error
382
- * @property {String} fetch.method=GET
383
- * @property {String} fetch.mode=same-origin
384
- * @property {String} fetch.credentials=same-origin
385
- * @property {Object} fetch.headers={"accept":"application/json"}}
386
- * @property {Object} labels
387
- * @property {string} labels.cannot-be-loaded cannot be loaded
388
- * @property {string} labels.no-options-available no options available
389
- * @property {string} labels.select-an-option select an option
390
- * @property {string} labels.no-option no option in the list, maybe you have to change the filter
391
- * @property {Object} features List with features
392
- * @property {Boolean} features.clearAll=true Display of a delete button to delete the entire selection
393
- * @property {Boolean} features.clear=true Display of a delete key for deleting the specific selection
394
- * @property {Boolean} features.lazyLoad=false Load options when first opening the dropdown. (Hint; lazylLoad is not supported with remote filter)
395
- * @property {Boolean} features.closeOnSelect=false Close the dropdown when an option is selected (since 3.54.0)
396
- * @property {Boolean} features.emptyValueIfNoOptions=false If no options are available, the selection is set to an empty array
397
- * @property {Boolean} features.storeFetchedData=false Store fetched data in the object
398
- * @property {Boolean} features.useStrictValueComparison=true Use strict value comparison for the selection
399
- * @property {string} filter.defaultValue=null Default filter value, if the filter is empty, if the default value is null, then no request is made
400
- * @property {Boolean} filter.mode=options Filter mode, values: options, remote, disabled (Hint; lazylLoad is not supported with remote filter, if you use remote filter, the lazyLoad is disabled)
401
- * @property {Object} templates Template definitions
402
- * @property {string} templates.main Main template
403
- * @property {string} templateMapping Mapping of the template placeholders
404
- * @property {string} templateMapping.selected Selected Template
405
- * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/)
406
- * @property {string} popper.placement=bottom PopperJS placement
407
- * @property {Object[]} modifiers={name:offset} PopperJS placement
408
- * @property {Object} mapping
409
- * @property {String} mapping.selector=* Path to select the appropriate entries
410
- * @property {String} mapping.labelTemplate="" template with the label placeholders in the form ${name}, where name is the key (**)
411
- * @property {String} mapping.valueTemplate="" template with the value placeholders in the form ${name}, where name is the key
412
- * @property {Monster.Components.Form~exampleFilterCallback|undefined} mapping.filter Filtering of values via a function
413
- * @property {Object} formatter
414
- * @property {Monster.Components.Form~formatterSelectionCallback|undefined} formatter.selection format selection label
415
- */
416
- get defaults() {
417
- return Object.assign(
418
- {},
419
- super.defaults,
420
- {
421
- toggleEventType: ["click", "touch"],
422
- delegatesFocus: false,
423
- options: [],
424
- selection: [],
425
- showMaxOptions: 10,
426
- type: "radio",
427
- name: new ID("s").toString(),
428
- features: {
429
- clearAll: true,
430
- clear: true,
431
- lazyLoad: false,
432
- closeOnSelect: false,
433
- emptyValueIfNoOptions: false,
434
- storeFetchedData: false,
435
- useStrictValueComparison: false,
436
- },
437
- url: null,
438
- lookup: {
439
- url: null,
440
- grouping: false,
441
- },
442
- labels: {
443
- "cannot-be-loaded": "Cannot be loaded",
444
- "no-options-available": noOptionsAvailableMessage,
445
- "click-to-load-options": clickToLoadOptionsMessage,
446
- "select-an-option": "Select an option",
447
- "summary-text": {
448
- zero: "No entries were selected",
449
- one: '<span class="monster-badge-primary-pill">1</span> entry was selected',
450
- other:
451
- '<span class="monster-badge-primary-pill">${count}</span> entries were selected',
452
- },
453
- "no-options":
454
- "Unfortunately, there are no options available in the list.",
455
- "no-options-found":
456
- "No options are available in the list. Please consider modifying the filter.",
457
- },
458
- messages: {
459
- control: null,
460
- selected: null,
461
- emptyOptions: null,
462
- },
463
- fetch: {
464
- redirect: "error",
465
- method: "GET",
466
- mode: "same-origin",
467
- credentials: "same-origin",
468
- headers: {
469
- accept: "application/json",
470
- },
471
- },
472
- filter: {
473
- defaultValue: null,
474
- mode: FILTER_MODE_DISABLED,
475
- position: FILTER_POSITION_INLINE,
476
- marker: {
477
- open: "{",
478
- close: "}",
479
- },
480
- },
481
- classes: {
482
- badge: "monster-badge-primary",
483
- statusOrRemoveBadge: "empty",
484
- },
485
- mapping: {
486
- selector: "*",
487
- labelTemplate: "",
488
- valueTemplate: "",
489
- filter: null,
490
- },
491
- formatter: {
492
- selection: buildSelectionLabel,
493
- },
494
- templates: {
495
- main: getTemplate(),
496
- },
497
- templateMapping: {
498
- /** with the attribute `data-monster-selected-template` the template for the selected options can be defined. */
499
- selected: getSelectionTemplate(),
500
- },
501
-
502
- popper: {
503
- placement: "bottom",
504
- middleware: ["flip", "offset:1"],
505
- },
506
- },
507
- initOptionsFromArguments.call(this),
508
- );
509
- }
510
-
511
- /**
512
- * @return {Select}
513
- */
514
- [assembleMethodSymbol]() {
515
- const self = this;
516
- super[assembleMethodSymbol]();
517
-
518
- initControlReferences.call(self);
519
- initEventHandler.call(self);
520
-
521
- let lazyLoadFlag = self.getOption("features.lazyLoad", false);
522
- let remoteFilterFlag = getFilterMode.call(this) === FILTER_MODE_REMOTE;
523
-
524
- if (getFilterMode.call(this) === FILTER_MODE_REMOTE) {
525
- self.getOption("features.lazyLoad", false);
526
- if (lazyLoadFlag === true) {
527
- addAttributeToken(
528
- this,
529
- ATTRIBUTE_ERRORMESSAGE,
530
- "lazyLoad is not supported with remote filter",
531
- );
532
- lazyLoadFlag = false;
533
- }
534
- }
535
-
536
- if (self.hasAttribute("value")) {
537
- new Processing(10, () => {
538
- this.value = this.getAttribute("value");
539
- })
540
- .run()
541
- .catch((e) => {
542
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
543
- });
544
- }
545
-
546
- if (self.getOption("url") !== null) {
547
- if (lazyLoadFlag || remoteFilterFlag) {
548
- lookupSelection.call(self);
549
- } else {
550
- self.fetch().catch((e) => {
551
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
552
- });
553
- }
554
- }
555
-
556
- let lastValue = self.value;
557
- self[internalSymbol].attachObserver(
558
- new Observer(function () {
559
- if (isObject(this) && this instanceof ProxyObserver) {
560
- const n = this.getSubject()?.options?.value;
561
-
562
- if (lastValue !== n) {
563
- lastValue = n;
564
- setSelection
565
- .call(self, n)
566
- .then(() => {
567
- })
568
- .catch((e) => {
569
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
570
- });
571
- }
572
- }
573
- }),
574
- );
575
-
576
- areOptionsAvailableAndInit.call(self);
577
-
578
- return this;
579
- }
580
-
581
- /**
582
- *
583
- * @return {*}
584
- * @throws {Error} storeFetchedData is not enabled
585
- * @since 3.66.0
586
- */
587
- getLastFetchedData() {
588
- if (this.getOption("features.storeFetchedData") === false) {
589
- throw new Error("storeFetchedData is not enabled");
590
- }
591
-
592
- return this?.[lastFetchedDataSymbol];
593
- }
594
-
595
- /**
596
- * The Button.click() method simulates a click on the internal button element.
597
- *
598
- * @since 3.27.0
599
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click}
600
- */
601
- click() {
602
- if (this.getOption("disabled") === true) {
603
- return;
604
- }
605
-
606
- toggle.call(this);
607
- }
608
-
609
- /**
610
- * The Button.focus() method sets focus on the internal button element.
611
- *
612
- * @since 3.27.0
613
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus}
614
- */
615
- focus(options) {
616
- if (this.getOption("disabled") === true) {
617
- return;
618
- }
619
-
620
- new Processing(() => {
621
- gatherState.call(this);
622
- focusFilter.call(this, options);
623
- })
624
- .run()
625
- .catch((e) => {
626
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
627
- });
628
- }
629
-
630
- /**
631
- * The Button.blur() method removes focus from the internal button element.
632
- * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur
633
- */
634
- blur() {
635
- new Processing(() => {
636
- gatherState.call(this);
637
- blurFilter.call(this);
638
- })
639
- .run()
640
- .catch((e) => {
641
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
642
- });
643
- }
644
-
645
- /**
646
- * If no url is specified, the options are taken from the Component itself.
647
- *
648
- * @param {string|URL} url URL to fetch the options
649
- * @return {Promise}
650
- */
651
- fetch(url) {
652
- return fetchIt.call(this, url);
653
- }
654
-
655
- /**
656
- * @return {void}
657
- */
658
- connectedCallback() {
659
- super.connectedCallback();
660
- const document = getDocument();
661
-
662
- for (const [, type] of Object.entries(["click", "touch"])) {
663
- // close on outside ui-events
664
- document.addEventListener(type, this[closeEventHandler]);
665
- }
666
-
667
- parseSlotsToOptions.call(this);
668
- attachResizeObserver.call(this);
669
- updatePopper.call(this);
670
-
671
- new Processing(() => {
672
- gatherState.call(this);
673
- focusFilter.call(this);
674
- })
675
- .run()
676
- .catch((e) => {
677
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
678
- });
679
- }
680
-
681
- /**
682
- * @return {void}
683
- */
684
- disconnectedCallback() {
685
- super.disconnectedCallback();
686
- const document = getDocument();
687
-
688
- // close on outside ui-events
689
- for (const [, type] of Object.entries(["click", "touch"])) {
690
- document.removeEventListener(type, this[closeEventHandler]);
691
- }
692
-
693
- disconnectResizeObserver.call(this);
694
- }
695
-
696
- /**
697
- * Import Select Options from dataset
698
- * Not to be confused with the control defaults/options
699
- *
700
- * @param {array|object|Map|Set} data
701
- * @return {Select}
702
- * @throws {Error} map is not iterable
703
- * @throws {Error} missing label configuration
704
- * @fires monster-options-set this event is fired when the options are set
705
- */
706
- importOptions(data) {
707
- const mappingOptions = this.getOption("mapping", {});
708
- const selector = mappingOptions?.["selector"];
709
- const labelTemplate = mappingOptions?.["labelTemplate"];
710
- const valueTemplate = mappingOptions?.["valueTemplate"];
711
- const filter = mappingOptions?.["filter"];
712
-
713
- let flag = false;
714
- if (labelTemplate === "") {
715
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template");
716
- flag = true;
717
- }
718
-
719
- if (valueTemplate === "") {
720
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty value template");
721
- flag = true;
722
- }
723
-
724
- if (flag === true) {
725
- throw new Error("missing label configuration");
726
- }
727
-
728
- const map = buildMap(data, selector, labelTemplate, valueTemplate, filter);
729
-
730
- const options = [];
731
-
732
- if (!isIterable(map)) {
733
- throw new Error("map is not iterable");
734
- }
735
-
736
- const visibility = "visible";
737
-
738
- map.forEach((label, value) => {
739
- options.push({
740
- value,
741
- label,
742
- visibility,
743
- data: map.get(value),
744
- });
745
- });
746
-
747
- runAsOptionLengthChanged.call(this, map.size);
748
- this.setOption("options", options);
749
-
750
- fireCustomEvent(this, "monster-options-set", {
751
- options,
752
- });
753
-
754
- return this;
755
- }
756
-
757
- /**
758
- * @private
759
- * @return {Select}
760
- */
761
- calcAndSetOptionsDimension() {
762
- calcAndSetOptionsDimension.call(this);
763
- return this;
764
- }
765
-
766
- /**
767
- *
768
- * @return {string}
769
- */
770
- static getTag() {
771
- return "monster-select";
772
- }
773
-
774
- /**
775
- *
776
- * @return {CSSStyleSheet[]}
777
- */
778
- static getCSSStyleSheet() {
779
- return [SelectStyleSheet];
780
- }
297
+ /**
298
+ *
299
+ */
300
+ constructor() {
301
+ super();
302
+ initOptionObserver.call(this);
303
+ }
304
+
305
+ /**
306
+ * This method is called by the `instanceof` operator.
307
+ * @return {Symbol}
308
+ */
309
+ static get [instanceSymbol]() {
310
+ return Symbol.for("@schukai/monster/components/form/select@@instance");
311
+ }
312
+
313
+ /**
314
+ * The current selection of the Select
315
+ *
316
+ * ```
317
+ * e = document.querySelector('monster-select');
318
+ * console.log(e.value)
319
+ * // ↦ 1
320
+ * // ↦ ['1','2']
321
+ * ```
322
+ *
323
+ * @return {string}
324
+ */
325
+ get value() {
326
+ return convertSelectionToValue.call(this, this.getOption("selection"));
327
+ }
328
+
329
+ /**
330
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals}
331
+ * @return {boolean}
332
+ */
333
+ static get formAssociated() {
334
+ return true;
335
+ }
336
+
337
+ /**
338
+ * Set selection
339
+ *
340
+ * ```
341
+ * e = document.querySelector('monster-select');
342
+ * e.value=1
343
+ * ```
344
+ *
345
+ * @property {string|array} value
346
+ * @throws {Error} unsupported type
347
+ * @fires monster-selected this event is fired when the selection is set
348
+ */
349
+ set value(value) {
350
+ const result = convertValueToSelection.call(this, value);
351
+ setSelection
352
+ .call(this, result.selection)
353
+ .then(() => {})
354
+ .catch((e) => {
355
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
356
+ });
357
+ }
358
+
359
+ /**
360
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
361
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
362
+ *
363
+ * The individual configuration values can be found in the table.
364
+ *
365
+ * @property {Object} toggleEventType=click,touch List of event types to be observed for opening the dropdown
366
+ * @property {boolean} delegatesFocus=false lorem [see mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus)
367
+ * @property {Object[]} options Selection of key identifier pairs available for selection and displayed in the dropdown.
368
+ * @property {string} options[].label
369
+ * @property {string} options[].value
370
+ * @property {string} options[].visibility hidden or visible
371
+ * @property {Array} selection Selected options
372
+ * @property {Integer} showMaxOptions=10 Maximum number of visible options before a scroll bar should be displayed.
373
+ * @property {string} type=radio Multiple (checkbox) or single selection (radio)
374
+ * @property {string} name=(random id) Name of the form field
375
+ * @property {string} url Load options from server per url
376
+ * @property {object} lookup Load options from server per url
377
+ * @property {string} lookup.url=null Load options from server per url
378
+ * @property {boolean} lookup.grouping=false Load all selected options from server per url at once (true) or one by one (false)
379
+ * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
380
+ * @property {String} fetch.redirect=error
381
+ * @property {String} fetch.method=GET
382
+ * @property {String} fetch.mode=same-origin
383
+ * @property {String} fetch.credentials=same-origin
384
+ * @property {Object} fetch.headers={"accept":"application/json"}}
385
+ * @property {Object} labels
386
+ * @property {string} labels.cannot-be-loaded cannot be loaded
387
+ * @property {string} labels.no-options-available no options available
388
+ * @property {string} labels.select-an-option select an option
389
+ * @property {string} labels.no-option no option in the list, maybe you have to change the filter
390
+ * @property {Object} features List with features
391
+ * @property {Boolean} features.clearAll=true Display of a delete button to delete the entire selection
392
+ * @property {Boolean} features.clear=true Display of a delete key for deleting the specific selection
393
+ * @property {Boolean} features.lazyLoad=false Load options when first opening the dropdown. (Hint; lazylLoad is not supported with remote filter)
394
+ * @property {Boolean} features.closeOnSelect=false Close the dropdown when an option is selected (since 3.54.0)
395
+ * @property {Boolean} features.emptyValueIfNoOptions=false If no options are available, the selection is set to an empty array
396
+ * @property {Boolean} features.storeFetchedData=false Store fetched data in the object
397
+ * @property {Boolean} features.useStrictValueComparison=true Use strict value comparison for the selection
398
+ * @property {string} filter.defaultValue=null Default filter value, if the filter is empty, if the default value is null, then no request is made
399
+ * @property {Boolean} filter.mode=options Filter mode, values: options, remote, disabled (Hint; lazylLoad is not supported with remote filter, if you use remote filter, the lazyLoad is disabled)
400
+ * @property {Object} templates Template definitions
401
+ * @property {string} templates.main Main template
402
+ * @property {string} templateMapping Mapping of the template placeholders
403
+ * @property {string} templateMapping.selected Selected Template
404
+ * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/)
405
+ * @property {string} popper.placement=bottom PopperJS placement
406
+ * @property {Object[]} modifiers={name:offset} PopperJS placement
407
+ * @property {Object} mapping
408
+ * @property {String} mapping.selector=* Path to select the appropriate entries
409
+ * @property {String} mapping.labelTemplate="" template with the label placeholders in the form ${name}, where name is the key (**)
410
+ * @property {String} mapping.valueTemplate="" template with the value placeholders in the form ${name}, where name is the key
411
+ * @property {Monster.Components.Form~exampleFilterCallback|undefined} mapping.filter Filtering of values via a function
412
+ * @property {Object} formatter
413
+ * @property {Monster.Components.Form~formatterSelectionCallback|undefined} formatter.selection format selection label
414
+ */
415
+ get defaults() {
416
+ return Object.assign(
417
+ {},
418
+ super.defaults,
419
+ {
420
+ toggleEventType: ["click", "touch"],
421
+ delegatesFocus: false,
422
+ options: [],
423
+ selection: [],
424
+ showMaxOptions: 10,
425
+ type: "radio",
426
+ name: new ID("s").toString(),
427
+ features: {
428
+ clearAll: true,
429
+ clear: true,
430
+ lazyLoad: false,
431
+ closeOnSelect: false,
432
+ emptyValueIfNoOptions: false,
433
+ storeFetchedData: false,
434
+ useStrictValueComparison: false,
435
+ },
436
+ url: null,
437
+ lookup: {
438
+ url: null,
439
+ grouping: false,
440
+ },
441
+ labels: {
442
+ "cannot-be-loaded": "Cannot be loaded",
443
+ "no-options-available": noOptionsAvailableMessage,
444
+ "click-to-load-options": clickToLoadOptionsMessage,
445
+ "select-an-option": "Select an option",
446
+ "summary-text": {
447
+ zero: "No entries were selected",
448
+ one: '<span class="monster-badge-primary-pill">1</span> entry was selected',
449
+ other:
450
+ '<span class="monster-badge-primary-pill">${count}</span> entries were selected',
451
+ },
452
+ "no-options":
453
+ "Unfortunately, there are no options available in the list.",
454
+ "no-options-found":
455
+ "No options are available in the list. Please consider modifying the filter.",
456
+ },
457
+ messages: {
458
+ control: null,
459
+ selected: null,
460
+ emptyOptions: null,
461
+ },
462
+ fetch: {
463
+ redirect: "error",
464
+ method: "GET",
465
+ mode: "same-origin",
466
+ credentials: "same-origin",
467
+ headers: {
468
+ accept: "application/json",
469
+ },
470
+ },
471
+ filter: {
472
+ defaultValue: null,
473
+ mode: FILTER_MODE_DISABLED,
474
+ position: FILTER_POSITION_INLINE,
475
+ marker: {
476
+ open: "{",
477
+ close: "}",
478
+ },
479
+ },
480
+ classes: {
481
+ badge: "monster-badge-primary",
482
+ statusOrRemoveBadge: "empty",
483
+ },
484
+ mapping: {
485
+ selector: "*",
486
+ labelTemplate: "",
487
+ valueTemplate: "",
488
+ filter: null,
489
+ },
490
+ formatter: {
491
+ selection: buildSelectionLabel,
492
+ },
493
+ templates: {
494
+ main: getTemplate(),
495
+ },
496
+ templateMapping: {
497
+ /** with the attribute `data-monster-selected-template` the template for the selected options can be defined. */
498
+ selected: getSelectionTemplate(),
499
+ },
500
+
501
+ popper: {
502
+ placement: "bottom",
503
+ middleware: ["flip", "offset:1"],
504
+ },
505
+ },
506
+ initOptionsFromArguments.call(this),
507
+ );
508
+ }
509
+
510
+ /**
511
+ * @return {Select}
512
+ */
513
+ [assembleMethodSymbol]() {
514
+ const self = this;
515
+ super[assembleMethodSymbol]();
516
+
517
+ initControlReferences.call(self);
518
+ initEventHandler.call(self);
519
+
520
+ let lazyLoadFlag = self.getOption("features.lazyLoad", false);
521
+ let remoteFilterFlag = getFilterMode.call(this) === FILTER_MODE_REMOTE;
522
+
523
+ if (getFilterMode.call(this) === FILTER_MODE_REMOTE) {
524
+ self.getOption("features.lazyLoad", false);
525
+ if (lazyLoadFlag === true) {
526
+ addAttributeToken(
527
+ this,
528
+ ATTRIBUTE_ERRORMESSAGE,
529
+ "lazyLoad is not supported with remote filter",
530
+ );
531
+ lazyLoadFlag = false;
532
+ }
533
+ }
534
+
535
+ if (self.hasAttribute("value")) {
536
+ new Processing(10, () => {
537
+ this.value = this.getAttribute("value");
538
+ })
539
+ .run()
540
+ .catch((e) => {
541
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
542
+ });
543
+ }
544
+
545
+ if (self.getOption("url") !== null) {
546
+ if (lazyLoadFlag || remoteFilterFlag) {
547
+ lookupSelection.call(self);
548
+ } else {
549
+ self.fetch().catch((e) => {
550
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
551
+ });
552
+ }
553
+ }
554
+
555
+ let lastValue = self.value;
556
+ self[internalSymbol].attachObserver(
557
+ new Observer(function () {
558
+ if (isObject(this) && this instanceof ProxyObserver) {
559
+ const n = this.getSubject()?.options?.value;
560
+
561
+ if (lastValue !== n) {
562
+ lastValue = n;
563
+ setSelection
564
+ .call(self, n)
565
+ .then(() => {})
566
+ .catch((e) => {
567
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
568
+ });
569
+ }
570
+ }
571
+ }),
572
+ );
573
+
574
+ areOptionsAvailableAndInit.call(self);
575
+
576
+ return this;
577
+ }
578
+
579
+ /**
580
+ *
581
+ * @return {*}
582
+ * @throws {Error} storeFetchedData is not enabled
583
+ * @since 3.66.0
584
+ */
585
+ getLastFetchedData() {
586
+ if (this.getOption("features.storeFetchedData") === false) {
587
+ throw new Error("storeFetchedData is not enabled");
588
+ }
589
+
590
+ return this?.[lastFetchedDataSymbol];
591
+ }
592
+
593
+ /**
594
+ * The Button.click() method simulates a click on the internal button element.
595
+ *
596
+ * @since 3.27.0
597
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click}
598
+ */
599
+ click() {
600
+ if (this.getOption("disabled") === true) {
601
+ return;
602
+ }
603
+
604
+ toggle.call(this);
605
+ }
606
+
607
+ /**
608
+ * The Button.focus() method sets focus on the internal button element.
609
+ *
610
+ * @since 3.27.0
611
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus}
612
+ */
613
+ focus(options) {
614
+ if (this.getOption("disabled") === true) {
615
+ return;
616
+ }
617
+
618
+ new Processing(() => {
619
+ gatherState.call(this);
620
+ focusFilter.call(this, options);
621
+ })
622
+ .run()
623
+ .catch((e) => {
624
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
625
+ });
626
+ }
627
+
628
+ /**
629
+ * The Button.blur() method removes focus from the internal button element.
630
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur
631
+ */
632
+ blur() {
633
+ new Processing(() => {
634
+ gatherState.call(this);
635
+ blurFilter.call(this);
636
+ })
637
+ .run()
638
+ .catch((e) => {
639
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
640
+ });
641
+ }
642
+
643
+ /**
644
+ * If no url is specified, the options are taken from the Component itself.
645
+ *
646
+ * @param {string|URL} url URL to fetch the options
647
+ * @return {Promise}
648
+ */
649
+ fetch(url) {
650
+ return fetchIt.call(this, url);
651
+ }
652
+
653
+ /**
654
+ * @return {void}
655
+ */
656
+ connectedCallback() {
657
+ super.connectedCallback();
658
+ const document = getDocument();
659
+
660
+ for (const [, type] of Object.entries(["click", "touch"])) {
661
+ // close on outside ui-events
662
+ document.addEventListener(type, this[closeEventHandler]);
663
+ }
664
+
665
+ parseSlotsToOptions.call(this);
666
+ attachResizeObserver.call(this);
667
+ updatePopper.call(this);
668
+
669
+ new Processing(() => {
670
+ gatherState.call(this);
671
+ focusFilter.call(this);
672
+ })
673
+ .run()
674
+ .catch((e) => {
675
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
676
+ });
677
+ }
678
+
679
+ /**
680
+ * @return {void}
681
+ */
682
+ disconnectedCallback() {
683
+ super.disconnectedCallback();
684
+ const document = getDocument();
685
+
686
+ // close on outside ui-events
687
+ for (const [, type] of Object.entries(["click", "touch"])) {
688
+ document.removeEventListener(type, this[closeEventHandler]);
689
+ }
690
+
691
+ disconnectResizeObserver.call(this);
692
+ }
693
+
694
+ /**
695
+ * Import Select Options from dataset
696
+ * Not to be confused with the control defaults/options
697
+ *
698
+ * @param {array|object|Map|Set} data
699
+ * @return {Select}
700
+ * @throws {Error} map is not iterable
701
+ * @throws {Error} missing label configuration
702
+ * @fires monster-options-set this event is fired when the options are set
703
+ */
704
+ importOptions(data) {
705
+ const mappingOptions = this.getOption("mapping", {});
706
+ const selector = mappingOptions?.["selector"];
707
+ const labelTemplate = mappingOptions?.["labelTemplate"];
708
+ const valueTemplate = mappingOptions?.["valueTemplate"];
709
+ const filter = mappingOptions?.["filter"];
710
+
711
+ let flag = false;
712
+ if (labelTemplate === "") {
713
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template");
714
+ flag = true;
715
+ }
716
+
717
+ if (valueTemplate === "") {
718
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty value template");
719
+ flag = true;
720
+ }
721
+
722
+ if (flag === true) {
723
+ throw new Error("missing label configuration");
724
+ }
725
+
726
+ const map = buildMap(data, selector, labelTemplate, valueTemplate, filter);
727
+
728
+ const options = [];
729
+
730
+ if (!isIterable(map)) {
731
+ throw new Error("map is not iterable");
732
+ }
733
+
734
+ const visibility = "visible";
735
+
736
+ map.forEach((label, value) => {
737
+ options.push({
738
+ value,
739
+ label,
740
+ visibility,
741
+ data: map.get(value),
742
+ });
743
+ });
744
+
745
+ runAsOptionLengthChanged.call(this, map.size);
746
+ this.setOption("options", options);
747
+
748
+ fireCustomEvent(this, "monster-options-set", {
749
+ options,
750
+ });
751
+
752
+ return this;
753
+ }
754
+
755
+ /**
756
+ * @private
757
+ * @return {Select}
758
+ */
759
+ calcAndSetOptionsDimension() {
760
+ calcAndSetOptionsDimension.call(this);
761
+ return this;
762
+ }
763
+
764
+ /**
765
+ *
766
+ * @return {string}
767
+ */
768
+ static getTag() {
769
+ return "monster-select";
770
+ }
771
+
772
+ /**
773
+ *
774
+ * @return {CSSStyleSheet[]}
775
+ */
776
+ static getCSSStyleSheet() {
777
+ return [SelectStyleSheet];
778
+ }
781
779
  }
782
780
 
783
781
  /**
784
782
  * @private
785
783
  */
786
784
  function lookupSelection() {
787
- const self = this;
788
-
789
- setTimeout(() => {
790
- const selection = self.getOption("selection");
791
- if (selection.length === 0) {
792
- return;
793
- }
794
-
795
- if (self[isLoadingSymbol] === true) {
796
- return;
797
- }
798
-
799
- if (self[lazyLoadDoneSymbol] === true) {
800
- return;
801
- }
802
-
803
- let url = self.getOption("url");
804
- let lookupUrl = self.getOption("lookup.url");
805
- if (lookupUrl !== null) {
806
- url = lookupUrl;
807
- }
808
-
809
- if (this.getOption("lookup.grouping") === true) {
810
- filterFromRemoteByValue
811
- .call(
812
- self,
813
- url,
814
- selection.map((s) => s?.["value"]),
815
- )
816
- .catch((e) => {
817
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
818
- });
819
- return;
820
- }
821
-
822
- for (const s of selection) {
823
- if (s?.["value"]) {
824
- filterFromRemoteByValue.call(self, url, s?.["value"]).catch((e) => {
825
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
826
- });
827
- }
828
- }
829
- }, 100);
785
+ const self = this;
786
+
787
+ setTimeout(() => {
788
+ const selection = self.getOption("selection");
789
+ if (selection.length === 0) {
790
+ return;
791
+ }
792
+
793
+ if (self[isLoadingSymbol] === true) {
794
+ return;
795
+ }
796
+
797
+ if (self[lazyLoadDoneSymbol] === true) {
798
+ return;
799
+ }
800
+
801
+ let url = self.getOption("url");
802
+ let lookupUrl = self.getOption("lookup.url");
803
+ if (lookupUrl !== null) {
804
+ url = lookupUrl;
805
+ }
806
+
807
+ if (this.getOption("lookup.grouping") === true) {
808
+ filterFromRemoteByValue
809
+ .call(
810
+ self,
811
+ url,
812
+ selection.map((s) => s?.["value"]),
813
+ )
814
+ .catch((e) => {
815
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
816
+ });
817
+ return;
818
+ }
819
+
820
+ for (const s of selection) {
821
+ if (s?.["value"]) {
822
+ filterFromRemoteByValue.call(self, url, s?.["value"]).catch((e) => {
823
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
824
+ });
825
+ }
826
+ }
827
+ }, 100);
830
828
  }
831
829
 
832
830
  function fetchIt(url, controlOptions) {
833
- if (url instanceof URL) {
834
- url = url.toString();
835
- }
836
-
837
- if (url !== undefined && url !== null) {
838
- url = validateString(url);
839
- } else {
840
- url = this.getOption("url");
841
- if (url === null) {
842
- return Promise.reject(new Error("No url defined"));
843
- }
844
- }
845
-
846
- return new Promise((resolve, reject) => {
847
- setStatusOrRemoveBadges.call(this, "loading");
848
-
849
- new Processing(10, () => {
850
- fetchData
851
- .call(this, url)
852
- .then((map) => {
853
- if (
854
- isObject(map) ||
855
- isArray(map) ||
856
- map instanceof Set ||
857
- map instanceof Map
858
- ) {
859
- try {
860
- this.importOptions(map);
861
- } catch (e) {
862
- setStatusOrRemoveBadges.call(this, "error");
863
- reject(e);
864
- return;
865
- }
866
-
867
- this[lastFetchedDataSymbol] = map;
868
-
869
- let result;
870
- const selection = this.getOption("selection");
871
- let newValue = [];
872
- if (selection) {
873
- newValue = selection;
874
- } else if (this.hasAttribute("value")) {
875
- newValue = this.getAttribute("value");
876
- }
877
-
878
- result = setSelection.call(this, newValue);
879
- requestAnimationFrame(() => {
880
- checkOptionState.call(this);
881
- setStatusOrRemoveBadges.call(this, "closed");
882
- updatePopper.call(this);
883
- resolve(result);
884
- });
885
-
886
- return;
887
- }
888
-
889
- setStatusOrRemoveBadges.call(this, "error");
890
- reject(new Error("invalid response"));
891
- })
892
- .catch((e) => {
893
- setStatusOrRemoveBadges.call(this, "error");
894
- reject(e);
895
- });
896
- })
897
- .run()
898
- .catch((e) => {
899
- setStatusOrRemoveBadges.call(this, "error");
900
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
901
- reject(e);
902
- });
903
- });
831
+ if (url instanceof URL) {
832
+ url = url.toString();
833
+ }
834
+
835
+ if (url !== undefined && url !== null) {
836
+ url = validateString(url);
837
+ } else {
838
+ url = this.getOption("url");
839
+ if (url === null) {
840
+ return Promise.reject(new Error("No url defined"));
841
+ }
842
+ }
843
+
844
+ return new Promise((resolve, reject) => {
845
+ setStatusOrRemoveBadges.call(this, "loading");
846
+
847
+ new Processing(10, () => {
848
+ fetchData
849
+ .call(this, url)
850
+ .then((map) => {
851
+ if (
852
+ isObject(map) ||
853
+ isArray(map) ||
854
+ map instanceof Set ||
855
+ map instanceof Map
856
+ ) {
857
+ try {
858
+ this.importOptions(map);
859
+ } catch (e) {
860
+ setStatusOrRemoveBadges.call(this, "error");
861
+ reject(e);
862
+ return;
863
+ }
864
+
865
+ this[lastFetchedDataSymbol] = map;
866
+
867
+ let result;
868
+ const selection = this.getOption("selection");
869
+ let newValue = [];
870
+ if (selection) {
871
+ newValue = selection;
872
+ } else if (this.hasAttribute("value")) {
873
+ newValue = this.getAttribute("value");
874
+ }
875
+
876
+ result = setSelection.call(this, newValue);
877
+ requestAnimationFrame(() => {
878
+ checkOptionState.call(this);
879
+ setStatusOrRemoveBadges.call(this, "closed");
880
+ updatePopper.call(this);
881
+ resolve(result);
882
+ });
883
+
884
+ return;
885
+ }
886
+
887
+ setStatusOrRemoveBadges.call(this, "error");
888
+ reject(new Error("invalid response"));
889
+ })
890
+ .catch((e) => {
891
+ setStatusOrRemoveBadges.call(this, "error");
892
+ reject(e);
893
+ });
894
+ })
895
+ .run()
896
+ .catch((e) => {
897
+ setStatusOrRemoveBadges.call(this, "error");
898
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
899
+ reject(e);
900
+ });
901
+ });
904
902
  }
905
903
 
906
904
  /**
@@ -915,64 +913,64 @@ function fetchIt(url, controlOptions) {
915
913
  * @return {object}
916
914
  */
917
915
  function initOptionsFromArguments() {
918
- const options = {};
919
-
920
- const template = this.getAttribute("data-monster-selected-template");
921
- if (isString(template)) {
922
- if (!options["templateMapping"]) options["templateMapping"] = {};
923
-
924
- switch (template) {
925
- case "summary":
926
- case "default":
927
- options["templateMapping"]["selected"] = getSummaryTemplate();
928
- break;
929
- case "selected":
930
- options["templateMapping"]["selected"] = getSelectionTemplate();
931
- break;
932
- default:
933
- addAttributeToken(
934
- this,
935
- ATTRIBUTE_ERRORMESSAGE,
936
- "invalid template, use summary or selected",
937
- );
938
- }
939
- }
940
-
941
- return options;
916
+ const options = {};
917
+
918
+ const template = this.getAttribute("data-monster-selected-template");
919
+ if (isString(template)) {
920
+ if (!options["templateMapping"]) options["templateMapping"] = {};
921
+
922
+ switch (template) {
923
+ case "summary":
924
+ case "default":
925
+ options["templateMapping"]["selected"] = getSummaryTemplate();
926
+ break;
927
+ case "selected":
928
+ options["templateMapping"]["selected"] = getSelectionTemplate();
929
+ break;
930
+ default:
931
+ addAttributeToken(
932
+ this,
933
+ ATTRIBUTE_ERRORMESSAGE,
934
+ "invalid template, use summary or selected",
935
+ );
936
+ }
937
+ }
938
+
939
+ return options;
942
940
  }
943
941
 
944
942
  /**
945
943
  * @private
946
944
  */
947
945
  function attachResizeObserver() {
948
- // against flickering
949
- this[resizeObserverSymbol] = new ResizeObserver((entries) => {
950
- if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
951
- try {
952
- this[timerCallbackSymbol].touch();
953
- return;
954
- } catch (e) {
955
- delete this[timerCallbackSymbol];
956
- }
957
- }
958
-
959
- this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
960
- updatePopper.call(this);
961
- delete this[timerCallbackSymbol];
962
- });
963
- });
964
-
965
- this[resizeObserverSymbol].observe(this.parentElement);
946
+ // against flickering
947
+ this[resizeObserverSymbol] = new ResizeObserver((entries) => {
948
+ if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
949
+ try {
950
+ this[timerCallbackSymbol].touch();
951
+ return;
952
+ } catch (e) {
953
+ delete this[timerCallbackSymbol];
954
+ }
955
+ }
956
+
957
+ this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
958
+ updatePopper.call(this);
959
+ delete this[timerCallbackSymbol];
960
+ });
961
+ });
962
+
963
+ this[resizeObserverSymbol].observe(this.parentElement);
966
964
  }
967
965
 
968
966
  function disconnectResizeObserver() {
969
- if (this[resizeObserverSymbol] instanceof ResizeObserver) {
970
- this[resizeObserverSymbol].disconnect();
971
- }
967
+ if (this[resizeObserverSymbol] instanceof ResizeObserver) {
968
+ this[resizeObserverSymbol].disconnect();
969
+ }
972
970
  }
973
971
 
974
972
  function getSelectionTemplate() {
975
- return `<div data-monster-role="selection" part="selection"
973
+ return `<div data-monster-role="selection" part="selection"
976
974
  data-monster-insert="selection path:selection" role="search"
977
975
  ><input type="text" role="searchbox"
978
976
  part="inline-filter" name="inline-filter"
@@ -984,7 +982,7 @@ function getSelectionTemplate() {
984
982
  }
985
983
 
986
984
  function getSummaryTemplate() {
987
- return `<div data-monster-role="selection" role="search" part="summary">
985
+ return `<div data-monster-role="selection" role="search" part="summary">
988
986
  <input type="text" role="searchbox"
989
987
  part="inline-filter" name="inline-filter"
990
988
  data-monster-role="filter"
@@ -1000,35 +998,35 @@ function getSummaryTemplate() {
1000
998
  * @private
1001
999
  */
1002
1000
  function parseSlotsToOptions() {
1003
- let options = this.getOption("options");
1004
- if (!isIterable(options)) {
1005
- options = [];
1006
- }
1007
-
1008
- let counter = 1;
1009
- getSlottedElements.call(this, "div").forEach((node) => {
1010
- let value = (counter++).toString();
1011
- let visibility = "visible";
1012
-
1013
- if (node.hasAttribute("data-monster-value")) {
1014
- value = node.getAttribute("data-monster-value");
1015
- }
1016
-
1017
- let label = node.outerHTML;
1018
-
1019
- if (node.style.display === "none") {
1020
- visibility = "hidden";
1021
- }
1022
-
1023
- options.push({
1024
- value,
1025
- label,
1026
- visibility,
1027
- });
1028
- });
1029
-
1030
- runAsOptionLengthChanged.call(this, options.length);
1031
- this.setOption("options", options);
1001
+ let options = this.getOption("options");
1002
+ if (!isIterable(options)) {
1003
+ options = [];
1004
+ }
1005
+
1006
+ let counter = 1;
1007
+ getSlottedElements.call(this, "div").forEach((node) => {
1008
+ let value = (counter++).toString();
1009
+ let visibility = "visible";
1010
+
1011
+ if (node.hasAttribute("data-monster-value")) {
1012
+ value = node.getAttribute("data-monster-value");
1013
+ }
1014
+
1015
+ let label = node.outerHTML;
1016
+
1017
+ if (node.style.display === "none") {
1018
+ visibility = "hidden";
1019
+ }
1020
+
1021
+ options.push({
1022
+ value,
1023
+ label,
1024
+ visibility,
1025
+ });
1026
+ });
1027
+
1028
+ runAsOptionLengthChanged.call(this, options.length);
1029
+ this.setOption("options", options);
1032
1030
  }
1033
1031
 
1034
1032
  /**
@@ -1038,39 +1036,39 @@ function parseSlotsToOptions() {
1038
1036
  * @param {int} targetLength
1039
1037
  */
1040
1038
  function runAsOptionLengthChanged(targetLength) {
1041
- const self = this;
1042
-
1043
- if (!self[optionsElementSymbol]) {
1044
- return;
1045
- }
1046
-
1047
- const callback = function (mutationsList, observer) {
1048
- const run = false;
1049
- for (const mutation of mutationsList) {
1050
- if (mutation.type === "childList") {
1051
- const run = true;
1052
- break;
1053
- }
1054
- }
1055
-
1056
- if (run === true) {
1057
- const nodes = self[optionsElementSymbol].querySelectorAll(
1058
- `div[${ATTRIBUTE_ROLE}=option]`,
1059
- );
1060
-
1061
- if (nodes.length === targetLength) {
1062
- checkOptionState.call(self);
1063
- observer.disconnect();
1064
- }
1065
- }
1066
- };
1067
-
1068
- const observer = new MutationObserver(callback);
1069
- observer.observe(self[optionsElementSymbol], {
1070
- attributes: false,
1071
- childList: true,
1072
- subtree: true,
1073
- });
1039
+ const self = this;
1040
+
1041
+ if (!self[optionsElementSymbol]) {
1042
+ return;
1043
+ }
1044
+
1045
+ const callback = function (mutationsList, observer) {
1046
+ const run = false;
1047
+ for (const mutation of mutationsList) {
1048
+ if (mutation.type === "childList") {
1049
+ const run = true;
1050
+ break;
1051
+ }
1052
+ }
1053
+
1054
+ if (run === true) {
1055
+ const nodes = self[optionsElementSymbol].querySelectorAll(
1056
+ `div[${ATTRIBUTE_ROLE}=option]`,
1057
+ );
1058
+
1059
+ if (nodes.length === targetLength) {
1060
+ checkOptionState.call(self);
1061
+ observer.disconnect();
1062
+ }
1063
+ }
1064
+ };
1065
+
1066
+ const observer = new MutationObserver(callback);
1067
+ observer.observe(self[optionsElementSymbol], {
1068
+ attributes: false,
1069
+ childList: true,
1070
+ subtree: true,
1071
+ });
1074
1072
  }
1075
1073
 
1076
1074
  /**
@@ -1079,38 +1077,38 @@ function runAsOptionLengthChanged(targetLength) {
1079
1077
  * @return {*}
1080
1078
  */
1081
1079
  function buildSelectionLabel(value) {
1082
- const options = this.getOption("options");
1083
-
1084
- for (let i = 0; i < options.length; i++) {
1085
- let o = options?.[i];
1086
- let l, v, v2;
1087
-
1088
- if (this.getOption("features.useStrictValueComparison") === true) {
1089
- v = value;
1090
- } else {
1091
- v = `${value}`;
1092
- }
1093
-
1094
- if (isPrimitive(o) && o === value) {
1095
- return o;
1096
- } else if (!isObject(o)) {
1097
- continue;
1098
- }
1099
-
1100
- if (this.getOption("features.useStrictValueComparison") === true) {
1101
- l = o?.["label"];
1102
- v2 = o?.["value"];
1103
- } else {
1104
- l = `${o?.["label"]}`;
1105
- v2 = `${o?.["value"]}`;
1106
- }
1107
-
1108
- if (v2 === v) {
1109
- return l;
1110
- }
1111
- }
1112
-
1113
- return undefined;
1080
+ const options = this.getOption("options");
1081
+
1082
+ for (let i = 0; i < options.length; i++) {
1083
+ let o = options?.[i];
1084
+ let l, v, v2;
1085
+
1086
+ if (this.getOption("features.useStrictValueComparison") === true) {
1087
+ v = value;
1088
+ } else {
1089
+ v = `${value}`;
1090
+ }
1091
+
1092
+ if (isPrimitive(o) && o === value) {
1093
+ return o;
1094
+ } else if (!isObject(o)) {
1095
+ continue;
1096
+ }
1097
+
1098
+ if (this.getOption("features.useStrictValueComparison") === true) {
1099
+ l = o?.["label"];
1100
+ v2 = o?.["value"];
1101
+ } else {
1102
+ l = `${o?.["label"]}`;
1103
+ v2 = `${o?.["value"]}`;
1104
+ }
1105
+
1106
+ if (v2 === v) {
1107
+ return l;
1108
+ }
1109
+ }
1110
+
1111
+ return undefined;
1114
1112
  }
1115
1113
 
1116
1114
  /**
@@ -1120,17 +1118,17 @@ function buildSelectionLabel(value) {
1120
1118
  * @throws {Error} no value found
1121
1119
  */
1122
1120
  function getSelectionLabel(value) {
1123
- const callback = this.getOption("formatter.selection");
1124
- if (isFunction(callback)) {
1125
- const label = callback.call(this, value);
1126
- if (isString(label)) return label;
1127
- }
1121
+ const callback = this.getOption("formatter.selection");
1122
+ if (isFunction(callback)) {
1123
+ const label = callback.call(this, value);
1124
+ if (isString(label)) return label;
1125
+ }
1128
1126
 
1129
- if (isString(value) || isInteger(value)) {
1130
- return `${value}`;
1131
- }
1127
+ if (isString(value) || isInteger(value)) {
1128
+ return `${value}`;
1129
+ }
1132
1130
 
1133
- return this.getOption("labels.cannot-be-loaded", value);
1131
+ return this.getOption("labels.cannot-be-loaded", value);
1134
1132
  }
1135
1133
 
1136
1134
  /**
@@ -1138,25 +1136,25 @@ function getSelectionLabel(value) {
1138
1136
  * @param {Event} event
1139
1137
  */
1140
1138
  function handleToggleKeyboardEvents(event) {
1141
- switch (event?.["code"]) {
1142
- case "Escape":
1143
- toggle.call(this);
1144
- event.preventDefault();
1145
- break;
1146
- case "Space":
1147
- toggle.call(this);
1148
- event.preventDefault();
1149
- break;
1150
- case "ArrowDown":
1151
- show.call(this);
1152
- activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1153
- event.preventDefault();
1154
- break;
1155
- case "ArrowUp":
1156
- hide.call(this);
1157
- event.preventDefault();
1158
- break;
1159
- }
1139
+ switch (event?.["code"]) {
1140
+ case "Escape":
1141
+ toggle.call(this);
1142
+ event.preventDefault();
1143
+ break;
1144
+ case "Space":
1145
+ toggle.call(this);
1146
+ event.preventDefault();
1147
+ break;
1148
+ case "ArrowDown":
1149
+ show.call(this);
1150
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1151
+ event.preventDefault();
1152
+ break;
1153
+ case "ArrowUp":
1154
+ hide.call(this);
1155
+ event.preventDefault();
1156
+ break;
1157
+ }
1160
1158
  }
1161
1159
 
1162
1160
  /**
@@ -1166,46 +1164,45 @@ function handleToggleKeyboardEvents(event) {
1166
1164
  * @this CustomElement
1167
1165
  */
1168
1166
  function initOptionObserver() {
1169
- const self = this;
1170
-
1171
- self.attachObserver(
1172
- new Observer(function () {
1173
- new Processing(() => {
1174
- try {
1175
- self.updateI18n();
1176
- } catch (e) {
1177
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
1178
- requestAnimationFrame(() => {
1179
- setStatusOrRemoveBadges.call(self, "error");
1180
- });
1181
- }
1182
- try {
1183
- areOptionsAvailableAndInit.call(self);
1184
- } catch (e) {
1185
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
1186
- requestAnimationFrame(() => {
1187
- setStatusOrRemoveBadges.call(self, "error");
1188
- });
1189
- }
1190
-
1191
- setSummaryAndControlText.call(self);
1192
- }).run();
1193
- }),
1194
- );
1167
+ const self = this;
1168
+
1169
+ self.attachObserver(
1170
+ new Observer(function () {
1171
+ new Processing(() => {
1172
+ try {
1173
+ self.updateI18n();
1174
+ } catch (e) {
1175
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
1176
+ requestAnimationFrame(() => {
1177
+ setStatusOrRemoveBadges.call(self, "error");
1178
+ });
1179
+ }
1180
+ try {
1181
+ areOptionsAvailableAndInit.call(self);
1182
+ } catch (e) {
1183
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
1184
+ requestAnimationFrame(() => {
1185
+ setStatusOrRemoveBadges.call(self, "error");
1186
+ });
1187
+ }
1188
+
1189
+ setSummaryAndControlText.call(self);
1190
+ }).run();
1191
+ }),
1192
+ );
1195
1193
  }
1196
1194
 
1197
1195
  function getDefaultTranslation() {
1198
- const translation = new Translations("en").assignTranslations(
1199
- this.getOption("labels", {}),
1200
- );
1196
+ const translation = new Translations("en").assignTranslations(
1197
+ this.getOption("labels", {}),
1198
+ );
1201
1199
 
1202
- try {
1203
- const doc = getDocumentTranslations();
1204
- translation.locale = doc.locale;
1205
- } catch (e) {
1206
- }
1200
+ try {
1201
+ const doc = getDocumentTranslations();
1202
+ translation.locale = doc.locale;
1203
+ } catch (e) {}
1207
1204
 
1208
- return translation;
1205
+ return translation;
1209
1206
  }
1210
1207
 
1211
1208
  /**
@@ -1213,36 +1210,36 @@ function getDefaultTranslation() {
1213
1210
  * @return {string|*}
1214
1211
  */
1215
1212
  function setSummaryAndControlText() {
1216
- const translations = getDefaultTranslation.call(this);
1217
- const selections = this.getOption("selection");
1218
-
1219
- const text = translations.getPluralRuleText(
1220
- "summary-text",
1221
- selections.length,
1222
- "",
1223
- );
1224
-
1225
- const selectedText = new Formatter({
1226
- count: String(selections.length),
1227
- }).format(text);
1228
-
1229
- this.setOption("messages.selected", selectedText);
1230
-
1231
- const current = this.getOption("messages.control");
1232
- const msg = this.getOption("labels.select-an-option");
1233
-
1234
- if (
1235
- current === "" ||
1236
- current === undefined ||
1237
- current === msg ||
1238
- current === null
1239
- ) {
1240
- if (selections.length === 0) {
1241
- this.setOption("messages.control", msg);
1242
- } else {
1243
- this.setOption("messages.control", "");
1244
- }
1245
- }
1213
+ const translations = getDefaultTranslation.call(this);
1214
+ const selections = this.getOption("selection");
1215
+
1216
+ const text = translations.getPluralRuleText(
1217
+ "summary-text",
1218
+ selections.length,
1219
+ "",
1220
+ );
1221
+
1222
+ const selectedText = new Formatter({
1223
+ count: String(selections.length),
1224
+ }).format(text);
1225
+
1226
+ this.setOption("messages.selected", selectedText);
1227
+
1228
+ const current = this.getOption("messages.control");
1229
+ const msg = this.getOption("labels.select-an-option");
1230
+
1231
+ if (
1232
+ current === "" ||
1233
+ current === undefined ||
1234
+ current === msg ||
1235
+ current === null
1236
+ ) {
1237
+ if (selections.length === 0) {
1238
+ this.setOption("messages.control", msg);
1239
+ } else {
1240
+ this.setOption("messages.control", "");
1241
+ }
1242
+ }
1246
1243
  }
1247
1244
 
1248
1245
  /**
@@ -1250,9 +1247,9 @@ function setSummaryAndControlText() {
1250
1247
  * @return {NodeList}
1251
1248
  */
1252
1249
  function getOptionElements() {
1253
- return this[optionsElementSymbol].querySelectorAll(
1254
- `[${ATTRIBUTE_ROLE}=option]`,
1255
- );
1250
+ return this[optionsElementSymbol].querySelectorAll(
1251
+ `[${ATTRIBUTE_ROLE}=option]`,
1252
+ );
1256
1253
  }
1257
1254
 
1258
1255
  /**
@@ -1276,75 +1273,75 @@ function getOptionElements() {
1276
1273
  * @private
1277
1274
  */
1278
1275
  function calcAndSetOptionsDimension() {
1279
- const options = getOptionElements.call(this);
1280
- const container = this[optionsElementSymbol];
1281
- if (!(container instanceof HTMLElement && options instanceof NodeList)) {
1282
- return;
1283
- }
1284
-
1285
- let visible = 0;
1286
- let optionHeight = 0;
1287
- const max = this.getOption("showMaxOptions", 10);
1288
-
1289
- let scrollFlag = false;
1290
- for (const [, option] of Object.entries(options)) {
1291
- const computedStyle = getGlobal().getComputedStyle(option);
1292
- if (computedStyle.display === "none") continue;
1293
-
1294
- let h = option.getBoundingClientRect().height;
1295
- h += parseInt(computedStyle.getPropertyValue("margin-top"), 10);
1296
- h += parseInt(computedStyle.getPropertyValue("margin-bottom"), 10);
1297
- optionHeight += h;
1298
-
1299
- visible++;
1300
-
1301
- if (visible > max) {
1302
- break;
1303
- }
1304
- }
1305
-
1306
- if (visible > max) {
1307
- visible = max;
1308
- scrollFlag = true;
1309
- }
1310
-
1311
- if (visible === 0) {
1312
- if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1313
- this.setOption(
1314
- "messages.emptyOptions",
1315
- this.getOption("labels.no-options-available"),
1316
- );
1317
- } else {
1318
- this.setOption(
1319
- "messages.emptyOptions",
1320
- this.getOption("labels.no-options-found"),
1321
- );
1322
- }
1323
- this[noOptionsAvailableElementSymbol].classList.remove("d-none");
1324
- } else {
1325
- this[noOptionsAvailableElementSymbol].classList.add("d-none");
1326
- }
1327
-
1328
- const styles = getGlobal().getComputedStyle(this[optionsElementSymbol]);
1329
- let padding = parseInt(styles.getPropertyValue("padding-top"), 10);
1330
- padding += parseInt(styles.getPropertyValue("padding-bottom"), 10);
1331
-
1332
- let margin = parseInt(styles.getPropertyValue("margin-top"), 10);
1333
- margin += parseInt(styles.getPropertyValue("margin-bottom"), 10);
1334
-
1335
- const containerHeight = optionHeight + padding + margin;
1336
- container.style.height = `${containerHeight}px`;
1337
-
1338
- if (scrollFlag === true) {
1339
- container.style.overflowY = "scroll";
1340
- } else {
1341
- container.style.overflowY = "auto";
1342
- }
1343
-
1344
- const domRect = this[controlElementSymbol].getBoundingClientRect();
1345
-
1346
- this[popperElementSymbol].style.width = `${domRect.width}px`;
1347
- container.style.overflowX = "auto";
1276
+ const options = getOptionElements.call(this);
1277
+ const container = this[optionsElementSymbol];
1278
+ if (!(container instanceof HTMLElement && options instanceof NodeList)) {
1279
+ return;
1280
+ }
1281
+
1282
+ let visible = 0;
1283
+ let optionHeight = 0;
1284
+ const max = this.getOption("showMaxOptions", 10);
1285
+
1286
+ let scrollFlag = false;
1287
+ for (const [, option] of Object.entries(options)) {
1288
+ const computedStyle = getGlobal().getComputedStyle(option);
1289
+ if (computedStyle.display === "none") continue;
1290
+
1291
+ let h = option.getBoundingClientRect().height;
1292
+ h += parseInt(computedStyle.getPropertyValue("margin-top"), 10);
1293
+ h += parseInt(computedStyle.getPropertyValue("margin-bottom"), 10);
1294
+ optionHeight += h;
1295
+
1296
+ visible++;
1297
+
1298
+ if (visible > max) {
1299
+ break;
1300
+ }
1301
+ }
1302
+
1303
+ if (visible > max) {
1304
+ visible = max;
1305
+ scrollFlag = true;
1306
+ }
1307
+
1308
+ if (visible === 0) {
1309
+ if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1310
+ this.setOption(
1311
+ "messages.emptyOptions",
1312
+ this.getOption("labels.no-options-available"),
1313
+ );
1314
+ } else {
1315
+ this.setOption(
1316
+ "messages.emptyOptions",
1317
+ this.getOption("labels.no-options-found"),
1318
+ );
1319
+ }
1320
+ this[noOptionsAvailableElementSymbol].classList.remove("d-none");
1321
+ } else {
1322
+ this[noOptionsAvailableElementSymbol].classList.add("d-none");
1323
+ }
1324
+
1325
+ const styles = getGlobal().getComputedStyle(this[optionsElementSymbol]);
1326
+ let padding = parseInt(styles.getPropertyValue("padding-top"), 10);
1327
+ padding += parseInt(styles.getPropertyValue("padding-bottom"), 10);
1328
+
1329
+ let margin = parseInt(styles.getPropertyValue("margin-top"), 10);
1330
+ margin += parseInt(styles.getPropertyValue("margin-bottom"), 10);
1331
+
1332
+ const containerHeight = optionHeight + padding + margin;
1333
+ container.style.height = `${containerHeight}px`;
1334
+
1335
+ if (scrollFlag === true) {
1336
+ container.style.overflowY = "scroll";
1337
+ } else {
1338
+ container.style.overflowY = "auto";
1339
+ }
1340
+
1341
+ const domRect = this[controlElementSymbol].getBoundingClientRect();
1342
+
1343
+ this[popperElementSymbol].style.width = `${domRect.width}px`;
1344
+ container.style.overflowX = "auto";
1348
1345
  }
1349
1346
 
1350
1347
  /**
@@ -1353,126 +1350,126 @@ function calcAndSetOptionsDimension() {
1353
1350
  * @throws {Error} no shadow-root is defined
1354
1351
  */
1355
1352
  function activateCurrentOption(direction) {
1356
- if (!this.shadowRoot) {
1357
- throw new Error("no shadow-root is defined");
1358
- }
1359
-
1360
- let focused = this.shadowRoot.querySelector(`[${ATTRIBUTE_PREFIX}focused]`);
1361
-
1362
- if (
1363
- !(focused instanceof HTMLElement) ||
1364
- focused.matches("[data-monster-visibility=hidden]")
1365
- ) {
1366
- for (const [, e] of Object.entries(
1367
- this.shadowRoot.querySelectorAll(`[${ATTRIBUTE_ROLE}=option]`),
1368
- )) {
1369
- if (e.matches("[data-monster-visibility=visible]")) {
1370
- focused = e;
1371
- break;
1372
- }
1373
- }
1374
- } else {
1375
- if (direction === FOCUS_DIRECTION_DOWN) {
1376
- while (focused.nextSibling) {
1377
- focused = focused.nextSibling;
1378
-
1379
- if (
1380
- focused instanceof HTMLElement &&
1381
- focused.hasAttribute(ATTRIBUTE_ROLE) &&
1382
- focused.getAttribute(ATTRIBUTE_ROLE) === "option" &&
1383
- focused.matches("[data-monster-visibility=visible]") &&
1384
- focused.matches(":not([data-monster-filtered=true])")
1385
- ) {
1386
- break;
1387
- }
1388
- }
1389
- } else {
1390
- let found = false;
1391
- while (focused.previousSibling) {
1392
- focused = focused.previousSibling;
1393
- if (
1394
- focused instanceof HTMLElement &&
1395
- focused.hasAttribute(ATTRIBUTE_ROLE) &&
1396
- focused.getAttribute(ATTRIBUTE_ROLE) === "option" &&
1397
- focused.matches("[data-monster-visibility=visible]") &&
1398
- focused.matches(":not([data-monster-filtered=true])")
1399
- ) {
1400
- found = true;
1401
- break;
1402
- }
1403
- }
1404
- if (found === false) {
1405
- focusFilter.call(this);
1406
- }
1407
- }
1408
- }
1409
-
1410
- new Processing(() => {
1411
- if (focused instanceof HTMLElement) {
1412
- this.shadowRoot
1413
- .querySelectorAll(`[${ATTRIBUTE_PREFIX}focused]`)
1414
- .forEach((e) => {
1415
- e.removeAttribute(`${ATTRIBUTE_PREFIX}focused`);
1416
- });
1417
-
1418
- focused.focus();
1419
- focused.setAttribute(`${ATTRIBUTE_PREFIX}focused`, true);
1420
- }
1421
- })
1422
- .run()
1423
- .catch((e) => {
1424
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1425
- });
1353
+ if (!this.shadowRoot) {
1354
+ throw new Error("no shadow-root is defined");
1355
+ }
1356
+
1357
+ let focused = this.shadowRoot.querySelector(`[${ATTRIBUTE_PREFIX}focused]`);
1358
+
1359
+ if (
1360
+ !(focused instanceof HTMLElement) ||
1361
+ focused.matches("[data-monster-visibility=hidden]")
1362
+ ) {
1363
+ for (const [, e] of Object.entries(
1364
+ this.shadowRoot.querySelectorAll(`[${ATTRIBUTE_ROLE}=option]`),
1365
+ )) {
1366
+ if (e.matches("[data-monster-visibility=visible]")) {
1367
+ focused = e;
1368
+ break;
1369
+ }
1370
+ }
1371
+ } else {
1372
+ if (direction === FOCUS_DIRECTION_DOWN) {
1373
+ while (focused.nextSibling) {
1374
+ focused = focused.nextSibling;
1375
+
1376
+ if (
1377
+ focused instanceof HTMLElement &&
1378
+ focused.hasAttribute(ATTRIBUTE_ROLE) &&
1379
+ focused.getAttribute(ATTRIBUTE_ROLE) === "option" &&
1380
+ focused.matches("[data-monster-visibility=visible]") &&
1381
+ focused.matches(":not([data-monster-filtered=true])")
1382
+ ) {
1383
+ break;
1384
+ }
1385
+ }
1386
+ } else {
1387
+ let found = false;
1388
+ while (focused.previousSibling) {
1389
+ focused = focused.previousSibling;
1390
+ if (
1391
+ focused instanceof HTMLElement &&
1392
+ focused.hasAttribute(ATTRIBUTE_ROLE) &&
1393
+ focused.getAttribute(ATTRIBUTE_ROLE) === "option" &&
1394
+ focused.matches("[data-monster-visibility=visible]") &&
1395
+ focused.matches(":not([data-monster-filtered=true])")
1396
+ ) {
1397
+ found = true;
1398
+ break;
1399
+ }
1400
+ }
1401
+ if (found === false) {
1402
+ focusFilter.call(this);
1403
+ }
1404
+ }
1405
+ }
1406
+
1407
+ new Processing(() => {
1408
+ if (focused instanceof HTMLElement) {
1409
+ this.shadowRoot
1410
+ .querySelectorAll(`[${ATTRIBUTE_PREFIX}focused]`)
1411
+ .forEach((e) => {
1412
+ e.removeAttribute(`${ATTRIBUTE_PREFIX}focused`);
1413
+ });
1414
+
1415
+ focused.focus();
1416
+ focused.setAttribute(`${ATTRIBUTE_PREFIX}focused`, true);
1417
+ }
1418
+ })
1419
+ .run()
1420
+ .catch((e) => {
1421
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1422
+ });
1426
1423
  }
1427
1424
 
1428
1425
  /**
1429
1426
  * @private
1430
1427
  */
1431
1428
  function filterOptions() {
1432
- new Processing(() => {
1433
- let filterValue;
1434
-
1435
- switch (this.getOption("filter.position")) {
1436
- case FILTER_POSITION_INLINE:
1437
- if (this[inlineFilterElementSymbol] instanceof HTMLElement) {
1438
- filterValue = this[inlineFilterElementSymbol].value.toLowerCase();
1439
- } else {
1440
- return;
1441
- }
1442
-
1443
- break;
1444
- case FILTER_POSITION_POPPER:
1445
- default:
1446
- if (this[popperFilterElementSymbol] instanceof HTMLInputElement) {
1447
- filterValue = this[popperFilterElementSymbol].value.toLowerCase();
1448
- } else {
1449
- return;
1450
- }
1451
- }
1452
-
1453
- const options = this.getOption("options");
1454
- for (const [i, option] of Object.entries(options)) {
1455
- if (option.label.toLowerCase().indexOf(filterValue) === -1) {
1456
- this.setOption(`options.${i}.filtered`, "true");
1457
- } else {
1458
- this.setOption(`options.${i}.filtered`, undefined);
1459
- }
1460
- }
1461
- })
1462
- .run()
1463
- .then(() => {
1464
- new Processing(100, () => {
1465
- calcAndSetOptionsDimension.call(this);
1466
- focusFilter.call(this);
1467
- })
1468
- .run()
1469
- .catch((e) => {
1470
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1471
- });
1472
- })
1473
- .catch((e) => {
1474
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1475
- });
1429
+ new Processing(() => {
1430
+ let filterValue;
1431
+
1432
+ switch (this.getOption("filter.position")) {
1433
+ case FILTER_POSITION_INLINE:
1434
+ if (this[inlineFilterElementSymbol] instanceof HTMLElement) {
1435
+ filterValue = this[inlineFilterElementSymbol].value.toLowerCase();
1436
+ } else {
1437
+ return;
1438
+ }
1439
+
1440
+ break;
1441
+ case FILTER_POSITION_POPPER:
1442
+ default:
1443
+ if (this[popperFilterElementSymbol] instanceof HTMLInputElement) {
1444
+ filterValue = this[popperFilterElementSymbol].value.toLowerCase();
1445
+ } else {
1446
+ return;
1447
+ }
1448
+ }
1449
+
1450
+ const options = this.getOption("options");
1451
+ for (const [i, option] of Object.entries(options)) {
1452
+ if (option.label.toLowerCase().indexOf(filterValue) === -1) {
1453
+ this.setOption(`options.${i}.filtered`, "true");
1454
+ } else {
1455
+ this.setOption(`options.${i}.filtered`, undefined);
1456
+ }
1457
+ }
1458
+ })
1459
+ .run()
1460
+ .then(() => {
1461
+ new Processing(100, () => {
1462
+ calcAndSetOptionsDimension.call(this);
1463
+ focusFilter.call(this);
1464
+ })
1465
+ .run()
1466
+ .catch((e) => {
1467
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1468
+ });
1469
+ })
1470
+ .catch((e) => {
1471
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1472
+ });
1476
1473
  }
1477
1474
 
1478
1475
  /**
@@ -1480,37 +1477,37 @@ function filterOptions() {
1480
1477
  * @param {Event} event
1481
1478
  */
1482
1479
  function handleFilterKeyboardEvents(event) {
1483
- const shiftKey = event?.["shiftKey"];
1484
-
1485
- switch (event?.["code"]) {
1486
- case "Tab":
1487
- activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1488
- event.preventDefault();
1489
- break;
1490
- case "Escape":
1491
- toggle.call(this);
1492
- event.preventDefault();
1493
- break;
1494
- case "Tab" && shiftKey === true:
1495
- case "ArrowUp":
1496
- activateCurrentOption.call(this, FOCUS_DIRECTION_UP);
1497
- event.preventDefault();
1498
- break;
1499
- case "Tab" && !shiftKey:
1500
- case "ArrowDown":
1501
- activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1502
- event.preventDefault();
1503
- break;
1504
- default:
1505
- if (
1506
- this.getOption("features.lazyLoad") === true &&
1507
- this[lazyLoadDoneSymbol] !== true
1508
- ) {
1509
- this.click();
1510
- }
1511
-
1512
- handleFilterKeyEvents.call(this);
1513
- }
1480
+ const shiftKey = event?.["shiftKey"];
1481
+
1482
+ switch (event?.["code"]) {
1483
+ case "Tab":
1484
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1485
+ event.preventDefault();
1486
+ break;
1487
+ case "Escape":
1488
+ toggle.call(this);
1489
+ event.preventDefault();
1490
+ break;
1491
+ case "Tab" && shiftKey === true:
1492
+ case "ArrowUp":
1493
+ activateCurrentOption.call(this, FOCUS_DIRECTION_UP);
1494
+ event.preventDefault();
1495
+ break;
1496
+ case "Tab" && !shiftKey:
1497
+ case "ArrowDown":
1498
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1499
+ event.preventDefault();
1500
+ break;
1501
+ default:
1502
+ if (
1503
+ this.getOption("features.lazyLoad") === true &&
1504
+ this[lazyLoadDoneSymbol] !== true
1505
+ ) {
1506
+ this.click();
1507
+ }
1508
+
1509
+ handleFilterKeyEvents.call(this);
1510
+ }
1514
1511
  }
1515
1512
 
1516
1513
  /**
@@ -1524,90 +1521,90 @@ function handleFilterKeyboardEvents(event) {
1524
1521
  * @return {void} This method does not return anything.
1525
1522
  */
1526
1523
  function handleFilterKeyEvents() {
1527
- if (this[keyFilterEventSymbol] instanceof DeadMansSwitch) {
1528
- try {
1529
- this[keyFilterEventSymbol].touch();
1530
- return;
1531
- } catch (e) {
1532
- delete this[keyFilterEventSymbol];
1533
- }
1534
- }
1535
-
1536
- this[keyFilterEventSymbol] = new DeadMansSwitch(200, () => {
1537
- if (getFilterMode.call(this) !== FILTER_MODE_REMOTE) {
1538
- filterOptions.call(this);
1539
- } else {
1540
- filterFromRemote.call(this).catch((e) => {
1541
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1542
- });
1543
- }
1544
-
1545
- delete this[keyFilterEventSymbol];
1546
- });
1524
+ if (this[keyFilterEventSymbol] instanceof DeadMansSwitch) {
1525
+ try {
1526
+ this[keyFilterEventSymbol].touch();
1527
+ return;
1528
+ } catch (e) {
1529
+ delete this[keyFilterEventSymbol];
1530
+ }
1531
+ }
1532
+
1533
+ this[keyFilterEventSymbol] = new DeadMansSwitch(200, () => {
1534
+ if (getFilterMode.call(this) !== FILTER_MODE_REMOTE) {
1535
+ filterOptions.call(this);
1536
+ } else {
1537
+ filterFromRemote.call(this).catch((e) => {
1538
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1539
+ });
1540
+ }
1541
+
1542
+ delete this[keyFilterEventSymbol];
1543
+ });
1547
1544
  }
1548
1545
 
1549
1546
  /**
1550
1547
  * @private
1551
1548
  */
1552
1549
  function filterFromRemote() {
1553
- if (
1554
- !(this[inlineFilterElementSymbol] instanceof HTMLElement) &&
1555
- !(this[popperFilterElementSymbol] instanceof HTMLElement)
1556
- ) {
1557
- return;
1558
- }
1559
-
1560
- show.call(this);
1561
-
1562
- const url = this.getOption("url");
1563
- if (!url) {
1564
- addAttributeToken(
1565
- this,
1566
- ATTRIBUTE_ERRORMESSAGE,
1567
- "Missing URL for Remote Filter.",
1568
- );
1569
- return;
1570
- }
1571
-
1572
- let filterValue;
1573
-
1574
- switch (this.getOption("filter.position")) {
1575
- case FILTER_POSITION_INLINE:
1576
- if (this[inlineFilterElementSymbol] instanceof HTMLElement) {
1577
- filterValue = this[inlineFilterElementSymbol].value.toLowerCase();
1578
- }
1579
-
1580
- break;
1581
- case FILTER_POSITION_POPPER:
1582
- default:
1583
- if (this[popperFilterElementSymbol] instanceof HTMLInputElement) {
1584
- filterValue = this[popperFilterElementSymbol].value.toLowerCase();
1585
- }
1586
- }
1587
-
1588
- return filterFromRemoteByValue.call(this, url, filterValue);
1550
+ if (
1551
+ !(this[inlineFilterElementSymbol] instanceof HTMLElement) &&
1552
+ !(this[popperFilterElementSymbol] instanceof HTMLElement)
1553
+ ) {
1554
+ return;
1555
+ }
1556
+
1557
+ show.call(this);
1558
+
1559
+ const url = this.getOption("url");
1560
+ if (!url) {
1561
+ addAttributeToken(
1562
+ this,
1563
+ ATTRIBUTE_ERRORMESSAGE,
1564
+ "Missing URL for Remote Filter.",
1565
+ );
1566
+ return;
1567
+ }
1568
+
1569
+ let filterValue;
1570
+
1571
+ switch (this.getOption("filter.position")) {
1572
+ case FILTER_POSITION_INLINE:
1573
+ if (this[inlineFilterElementSymbol] instanceof HTMLElement) {
1574
+ filterValue = this[inlineFilterElementSymbol].value.toLowerCase();
1575
+ }
1576
+
1577
+ break;
1578
+ case FILTER_POSITION_POPPER:
1579
+ default:
1580
+ if (this[popperFilterElementSymbol] instanceof HTMLInputElement) {
1581
+ filterValue = this[popperFilterElementSymbol].value.toLowerCase();
1582
+ }
1583
+ }
1584
+
1585
+ return filterFromRemoteByValue.call(this, url, filterValue);
1589
1586
  }
1590
1587
 
1591
1588
  function formatURL(url, value) {
1592
- if (value === undefined || value === null || value === "") {
1593
- value = this.getOption("filter.defaultValue");
1594
- if (value === undefined || value === null || value === "") {
1595
- value = disabledRequestMarker.toString();
1596
- }
1597
- }
1598
-
1599
- const formatter = new Formatter({filter: encodeURI(value)});
1600
- const openMarker = this.getOption("filter.marker.open");
1601
- let closeMarker = this.getOption("filter.marker.close");
1602
- if (!closeMarker) {
1603
- closeMarker = openMarker;
1604
- }
1605
-
1606
- if (openMarker && closeMarker) {
1607
- formatter.setMarker(openMarker, closeMarker);
1608
- }
1609
-
1610
- return formatter.format(url);
1589
+ if (value === undefined || value === null || value === "") {
1590
+ value = this.getOption("filter.defaultValue");
1591
+ if (value === undefined || value === null || value === "") {
1592
+ value = disabledRequestMarker.toString();
1593
+ }
1594
+ }
1595
+
1596
+ const formatter = new Formatter({ filter: encodeURI(value) });
1597
+ const openMarker = this.getOption("filter.marker.open");
1598
+ let closeMarker = this.getOption("filter.marker.close");
1599
+ if (!closeMarker) {
1600
+ closeMarker = openMarker;
1601
+ }
1602
+
1603
+ if (openMarker && closeMarker) {
1604
+ formatter.setMarker(openMarker, closeMarker);
1605
+ }
1606
+
1607
+ return formatter.format(url);
1611
1608
  }
1612
1609
 
1613
1610
  /**
@@ -1617,28 +1614,28 @@ function formatURL(url, value) {
1617
1614
  * @returns {Promise<unknown>}
1618
1615
  */
1619
1616
  function filterFromRemoteByValue(optionUrl, value) {
1620
- return new Processing(() => {
1621
- let url = formatURL.call(this, optionUrl, value);
1622
- if (url.indexOf(disabledRequestMarker.toString()) !== -1) {
1623
- return;
1624
- }
1625
-
1626
- fetchIt
1627
- .call(this, url, {
1628
- disableHiding: true,
1629
- })
1630
- .then(() => {
1631
- checkOptionState.call(this);
1632
- show.call(this);
1633
- })
1634
- .catch((e) => {
1635
- throw e;
1636
- });
1637
- })
1638
- .run()
1639
- .catch((e) => {
1640
- throw e;
1641
- });
1617
+ return new Processing(() => {
1618
+ let url = formatURL.call(this, optionUrl, value);
1619
+ if (url.indexOf(disabledRequestMarker.toString()) !== -1) {
1620
+ return;
1621
+ }
1622
+
1623
+ fetchIt
1624
+ .call(this, url, {
1625
+ disableHiding: true,
1626
+ })
1627
+ .then(() => {
1628
+ checkOptionState.call(this);
1629
+ show.call(this);
1630
+ })
1631
+ .catch((e) => {
1632
+ throw e;
1633
+ });
1634
+ })
1635
+ .run()
1636
+ .catch((e) => {
1637
+ throw e;
1638
+ });
1642
1639
  }
1643
1640
 
1644
1641
  /**
@@ -1646,50 +1643,50 @@ function filterFromRemoteByValue(optionUrl, value) {
1646
1643
  * @private
1647
1644
  */
1648
1645
  function handleOptionKeyboardEvents(event) {
1649
- const shiftKey = event?.["shiftKey"];
1650
-
1651
- switch (event?.["code"]) {
1652
- case "Escape":
1653
- toggle.call(this);
1654
- event.preventDefault();
1655
- break;
1656
- case "Enter":
1657
- case "Space":
1658
- const path = event.composedPath();
1659
- const element = path?.[0];
1660
- if (element instanceof HTMLElement) {
1661
- const input = element.getElementsByTagName("input");
1662
- if (!input) {
1663
- return;
1664
- }
1665
- fireEvent(input, "click");
1666
- }
1667
- event.preventDefault();
1668
- break;
1669
-
1670
- case "Tab" && shiftKey === true:
1671
- case "ArrowUp":
1672
- activateCurrentOption.call(this, FOCUS_DIRECTION_UP);
1673
- event.preventDefault();
1674
- break;
1675
-
1676
- case "Tab" && !shiftKey:
1677
- case "ArrowLeft":
1678
- case "ArrowRight":
1679
- // handled by tree select
1680
- break;
1681
- case "ArrowDown":
1682
- activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1683
- event.preventDefault();
1684
- break;
1685
- default:
1686
- const p = event.composedPath();
1687
- if (p?.[0] instanceof HTMLInputElement) {
1688
- return;
1689
- }
1690
- focusFilter.call(this);
1691
- break;
1692
- }
1646
+ const shiftKey = event?.["shiftKey"];
1647
+
1648
+ switch (event?.["code"]) {
1649
+ case "Escape":
1650
+ toggle.call(this);
1651
+ event.preventDefault();
1652
+ break;
1653
+ case "Enter":
1654
+ case "Space":
1655
+ const path = event.composedPath();
1656
+ const element = path?.[0];
1657
+ if (element instanceof HTMLElement) {
1658
+ const input = element.getElementsByTagName("input");
1659
+ if (!input) {
1660
+ return;
1661
+ }
1662
+ fireEvent(input, "click");
1663
+ }
1664
+ event.preventDefault();
1665
+ break;
1666
+
1667
+ case "Tab" && shiftKey === true:
1668
+ case "ArrowUp":
1669
+ activateCurrentOption.call(this, FOCUS_DIRECTION_UP);
1670
+ event.preventDefault();
1671
+ break;
1672
+
1673
+ case "Tab" && !shiftKey:
1674
+ case "ArrowLeft":
1675
+ case "ArrowRight":
1676
+ // handled by tree select
1677
+ break;
1678
+ case "ArrowDown":
1679
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1680
+ event.preventDefault();
1681
+ break;
1682
+ default:
1683
+ const p = event.composedPath();
1684
+ if (p?.[0] instanceof HTMLInputElement) {
1685
+ return;
1686
+ }
1687
+ focusFilter.call(this);
1688
+ break;
1689
+ }
1693
1690
  }
1694
1691
 
1695
1692
  /**
@@ -1697,33 +1694,33 @@ function handleOptionKeyboardEvents(event) {
1697
1694
  * @return {string}
1698
1695
  */
1699
1696
  function getFilterMode() {
1700
- switch (this.getOption("filter.mode")) {
1701
- case FILTER_MODE_OPTIONS:
1702
- return FILTER_MODE_OPTIONS;
1703
- case FILTER_MODE_REMOTE:
1704
- return FILTER_MODE_REMOTE;
1705
- default:
1706
- return FILTER_MODE_DISABLED;
1707
- }
1697
+ switch (this.getOption("filter.mode")) {
1698
+ case FILTER_MODE_OPTIONS:
1699
+ return FILTER_MODE_OPTIONS;
1700
+ case FILTER_MODE_REMOTE:
1701
+ return FILTER_MODE_REMOTE;
1702
+ default:
1703
+ return FILTER_MODE_DISABLED;
1704
+ }
1708
1705
  }
1709
1706
 
1710
1707
  /**
1711
1708
  * @private
1712
1709
  */
1713
1710
  function blurFilter() {
1714
- if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) {
1715
- return;
1716
- }
1711
+ if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) {
1712
+ return;
1713
+ }
1717
1714
 
1718
- if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1719
- return;
1720
- }
1715
+ if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1716
+ return;
1717
+ }
1721
1718
 
1722
- this[popperFilterContainerElementSymbol].classList.remove("active");
1723
- this[popperFilterContainerElementSymbol].blur();
1719
+ this[popperFilterContainerElementSymbol].classList.remove("active");
1720
+ this[popperFilterContainerElementSymbol].blur();
1724
1721
 
1725
- this[inlineFilterElementSymbol].classList.remove("active");
1726
- this[inlineFilterElementSymbol].blur();
1722
+ this[inlineFilterElementSymbol].classList.remove("active");
1723
+ this[inlineFilterElementSymbol].blur();
1727
1724
  }
1728
1725
 
1729
1726
  /**
@@ -1731,29 +1728,29 @@ function blurFilter() {
1731
1728
  * @param focusOptions
1732
1729
  */
1733
1730
  function focusPopperFilter(focusOptions) {
1734
- this[popperFilterContainerElementSymbol].classList.remove("d-none");
1735
- this[popperFilterElementSymbol].classList.add("active");
1736
- this[inlineFilterElementSymbol].classList.remove("active");
1737
- this[inlineFilterElementSymbol].classList.add("d-none");
1738
-
1739
- if (!(this[popperFilterElementSymbol] instanceof HTMLElement)) {
1740
- addAttributeToken(
1741
- this,
1742
- ATTRIBUTE_ERRORMESSAGE,
1743
- "Missing Popper Filter Element.",
1744
- );
1745
- return;
1746
- }
1747
-
1748
- // visibility is set to visible, because focus() does not work on invisible elements
1749
- // and the class definition is assigned later in the processing
1750
- setTimeout(() => {
1751
- if (focusOptions === undefined || focusOptions === null) {
1752
- this[popperFilterElementSymbol].focus();
1753
- } else {
1754
- this[popperFilterElementSymbol].focus(focusOptions);
1755
- }
1756
- }, 100);
1731
+ this[popperFilterContainerElementSymbol].classList.remove("d-none");
1732
+ this[popperFilterElementSymbol].classList.add("active");
1733
+ this[inlineFilterElementSymbol].classList.remove("active");
1734
+ this[inlineFilterElementSymbol].classList.add("d-none");
1735
+
1736
+ if (!(this[popperFilterElementSymbol] instanceof HTMLElement)) {
1737
+ addAttributeToken(
1738
+ this,
1739
+ ATTRIBUTE_ERRORMESSAGE,
1740
+ "Missing Popper Filter Element.",
1741
+ );
1742
+ return;
1743
+ }
1744
+
1745
+ // visibility is set to visible, because focus() does not work on invisible elements
1746
+ // and the class definition is assigned later in the processing
1747
+ setTimeout(() => {
1748
+ if (focusOptions === undefined || focusOptions === null) {
1749
+ this[popperFilterElementSymbol].focus();
1750
+ } else {
1751
+ this[popperFilterElementSymbol].focus(focusOptions);
1752
+ }
1753
+ }, 100);
1757
1754
  }
1758
1755
 
1759
1756
  /**
@@ -1761,44 +1758,44 @@ function focusPopperFilter(focusOptions) {
1761
1758
  * @param focusOptions
1762
1759
  */
1763
1760
  function focusInlineFilter(focusOptions) {
1764
- const options = this.getOption("options");
1765
- if (
1766
- (!isArray(options) || options.length === 0) &&
1767
- getFilterMode.call(this) !== FILTER_MODE_REMOTE
1768
- ) {
1769
- return;
1770
- }
1771
-
1772
- this[popperFilterContainerElementSymbol].classList.add("d-none");
1773
- this[inlineFilterElementSymbol].classList.add("active");
1774
- this[inlineFilterElementSymbol].classList.remove("d-none");
1775
-
1776
- // visibility is set to visible, because focus() does not work on invisible elements
1777
- // and the class definition is assigned later in the processing
1778
- setTimeout(() => {
1779
- if (focusOptions === undefined || focusOptions === null) {
1780
- this[inlineFilterElementSymbol].focus();
1781
- } else {
1782
- this[inlineFilterElementSymbol].focus(focusOptions);
1783
- }
1784
- }, 100);
1761
+ const options = this.getOption("options");
1762
+ if (
1763
+ (!isArray(options) || options.length === 0) &&
1764
+ getFilterMode.call(this) !== FILTER_MODE_REMOTE
1765
+ ) {
1766
+ return;
1767
+ }
1768
+
1769
+ this[popperFilterContainerElementSymbol].classList.add("d-none");
1770
+ this[inlineFilterElementSymbol].classList.add("active");
1771
+ this[inlineFilterElementSymbol].classList.remove("d-none");
1772
+
1773
+ // visibility is set to visible, because focus() does not work on invisible elements
1774
+ // and the class definition is assigned later in the processing
1775
+ setTimeout(() => {
1776
+ if (focusOptions === undefined || focusOptions === null) {
1777
+ this[inlineFilterElementSymbol].focus();
1778
+ } else {
1779
+ this[inlineFilterElementSymbol].focus(focusOptions);
1780
+ }
1781
+ }, 100);
1785
1782
  }
1786
1783
 
1787
1784
  /**
1788
1785
  * @private
1789
1786
  */
1790
1787
  function focusFilter(focusOptions) {
1791
- if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1792
- this[popperFilterContainerElementSymbol].classList.add("d-none");
1793
- this[inlineFilterElementSymbol].classList.add("d-none");
1794
- return;
1795
- }
1788
+ if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1789
+ this[popperFilterContainerElementSymbol].classList.add("d-none");
1790
+ this[inlineFilterElementSymbol].classList.add("d-none");
1791
+ return;
1792
+ }
1796
1793
 
1797
- if (this.getOption("filter.position") === FILTER_POSITION_INLINE) {
1798
- return focusInlineFilter.call(this, focusOptions);
1799
- }
1794
+ if (this.getOption("filter.position") === FILTER_POSITION_INLINE) {
1795
+ return focusInlineFilter.call(this, focusOptions);
1796
+ }
1800
1797
 
1801
- return focusPopperFilter.call(this, focusOptions);
1798
+ return focusPopperFilter.call(this, focusOptions);
1802
1799
  }
1803
1800
 
1804
1801
  /**
@@ -1808,40 +1805,39 @@ function focusFilter(focusOptions) {
1808
1805
  * @throws {Error} unsupported type
1809
1806
  */
1810
1807
  function gatherState() {
1811
- const type = this.getOption("type");
1812
- if (["radio", "checkbox"].indexOf(type) === -1) {
1813
- throw new Error("unsupported type");
1814
- }
1815
-
1816
- if (!this.shadowRoot) {
1817
- throw new Error("no shadow-root is defined");
1818
- }
1819
-
1820
- const selection = [];
1821
- const elements = this.shadowRoot.querySelectorAll(
1822
- `input[type=${type}]:checked`,
1823
- );
1824
-
1825
- for (const e of elements) {
1826
- selection.push({
1827
- label: getSelectionLabel.call(this, e.value),
1828
- value: e.value,
1829
- });
1830
- }
1831
-
1832
- setSelection
1833
- .call(this, selection)
1834
- .then(() => {
1835
- })
1836
- .catch((e) => {
1837
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
1838
- });
1839
-
1840
- if (this.getOption("features.closeOnSelect") === true) {
1841
- toggle.call(this);
1842
- }
1843
-
1844
- return this;
1808
+ const type = this.getOption("type");
1809
+ if (["radio", "checkbox"].indexOf(type) === -1) {
1810
+ throw new Error("unsupported type");
1811
+ }
1812
+
1813
+ if (!this.shadowRoot) {
1814
+ throw new Error("no shadow-root is defined");
1815
+ }
1816
+
1817
+ const selection = [];
1818
+ const elements = this.shadowRoot.querySelectorAll(
1819
+ `input[type=${type}]:checked`,
1820
+ );
1821
+
1822
+ for (const e of elements) {
1823
+ selection.push({
1824
+ label: getSelectionLabel.call(this, e.value),
1825
+ value: e.value,
1826
+ });
1827
+ }
1828
+
1829
+ setSelection
1830
+ .call(this, selection)
1831
+ .then(() => {})
1832
+ .catch((e) => {
1833
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
1834
+ });
1835
+
1836
+ if (this.getOption("features.closeOnSelect") === true) {
1837
+ toggle.call(this);
1838
+ }
1839
+
1840
+ return this;
1845
1841
  }
1846
1842
 
1847
1843
  /**
@@ -1850,121 +1846,120 @@ function gatherState() {
1850
1846
  * @throws {Error} unsupported type
1851
1847
  */
1852
1848
  function clearSelection() {
1853
- const type = this.getOption("type");
1854
- if (["radio", "checkbox"].indexOf(type) === -1) {
1855
- throw new Error("unsupported type");
1856
- }
1857
-
1858
- if (!this.shadowRoot) {
1859
- throw new Error("no shadow-root is defined");
1860
- }
1861
-
1862
- setSelection
1863
- .call(this, [])
1864
- .then(() => {
1865
- })
1866
- .catch((e) => {
1867
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
1868
- });
1849
+ const type = this.getOption("type");
1850
+ if (["radio", "checkbox"].indexOf(type) === -1) {
1851
+ throw new Error("unsupported type");
1852
+ }
1853
+
1854
+ if (!this.shadowRoot) {
1855
+ throw new Error("no shadow-root is defined");
1856
+ }
1857
+
1858
+ setSelection
1859
+ .call(this, [])
1860
+ .then(() => {})
1861
+ .catch((e) => {
1862
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
1863
+ });
1869
1864
  }
1870
1865
 
1871
1866
  /**
1872
1867
  * @private
1873
1868
  */
1874
1869
  function areOptionsAvailableAndInit() {
1875
- // prevent multiple calls
1876
- if (this[areOptionsAvailableAndInitSymbol] === undefined) {
1877
- this[areOptionsAvailableAndInitSymbol] = 0;
1878
- }
1879
-
1880
- if (this[areOptionsAvailableAndInitSymbol] > 0) {
1881
- this[areOptionsAvailableAndInitSymbol]--;
1882
- return true;
1883
- }
1884
-
1885
- this[areOptionsAvailableAndInitSymbol]++;
1886
-
1887
- const options = this.getOption("options");
1888
-
1889
- if (
1890
- options === undefined ||
1891
- options === null ||
1892
- (isArray(options) && options.length === 0)
1893
- ) {
1894
- setStatusOrRemoveBadges.call(this, "empty");
1895
-
1896
- // hide.call(this);
1897
-
1898
- let msg = this.getOption("labels.no-options-available");
1899
-
1900
- if (
1901
- this.getOption("url") !== null &&
1902
- this.getOption("features.lazyLoad") === true &&
1903
- this[lazyLoadDoneSymbol] !== true
1904
- ) {
1905
- msg = this.getOption("labels.click-to-load-options");
1906
- }
1907
-
1908
- this.setOption("messages.control", msg);
1909
- this.setOption("messages.summary", "");
1910
-
1911
- if (this.getOption("features.emptyValueIfNoOptions") === true) {
1912
- this.value = "";
1913
- }
1914
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage);
1915
- return false;
1916
- }
1917
-
1918
- const selections = this.getOption("selection");
1919
- if (
1920
- selections === undefined ||
1921
- selections === null ||
1922
- selections.length === 0
1923
- ) {
1924
- this.setOption(
1925
- "messages.control",
1926
- this.getOption("labels.select-an-option"),
1927
- );
1928
- } else {
1929
- this.setOption("messages.control", "");
1930
- }
1931
-
1932
- this.setOption("messages.summary", setSummaryAndControlText.call(this));
1933
-
1934
- let updated = false;
1935
- let valueCounter = 1;
1936
- for (const option of options) {
1937
- if (option?.visibility === undefined) {
1938
- option.visibility = "visible";
1939
- updated = true;
1940
- }
1941
-
1942
- if (option?.value === undefined && option?.label === undefined) {
1943
- option.value = `${valueCounter++}`;
1944
- option.label = option.value;
1945
- updated = true;
1946
- continue;
1947
- }
1948
-
1949
- if (option?.value === undefined) {
1950
- option.value = option.label;
1951
- updated = true;
1952
- }
1953
-
1954
- if (option?.label === undefined) {
1955
- option.label = option.value;
1956
- updated = true;
1957
- }
1958
- }
1959
-
1960
- if (updated) {
1961
- this.setOption("options", options);
1962
- }
1963
-
1964
- setStatusOrRemoveBadges.call(this);
1965
-
1966
- removeAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage);
1967
- return true;
1870
+ // prevent multiple calls
1871
+ if (this[areOptionsAvailableAndInitSymbol] === undefined) {
1872
+ this[areOptionsAvailableAndInitSymbol] = 0;
1873
+ }
1874
+
1875
+ if (this[areOptionsAvailableAndInitSymbol] > 0) {
1876
+ this[areOptionsAvailableAndInitSymbol]--;
1877
+ return true;
1878
+ }
1879
+
1880
+ this[areOptionsAvailableAndInitSymbol]++;
1881
+
1882
+ const options = this.getOption("options");
1883
+
1884
+ if (
1885
+ options === undefined ||
1886
+ options === null ||
1887
+ (isArray(options) && options.length === 0)
1888
+ ) {
1889
+ setStatusOrRemoveBadges.call(this, "empty");
1890
+
1891
+ // hide.call(this);
1892
+
1893
+ let msg = this.getOption("labels.no-options-available");
1894
+
1895
+ if (
1896
+ this.getOption("url") !== null &&
1897
+ this.getOption("features.lazyLoad") === true &&
1898
+ this[lazyLoadDoneSymbol] !== true
1899
+ ) {
1900
+ msg = this.getOption("labels.click-to-load-options");
1901
+ }
1902
+
1903
+ this.setOption("messages.control", msg);
1904
+ this.setOption("messages.summary", "");
1905
+
1906
+ if (this.getOption("features.emptyValueIfNoOptions") === true) {
1907
+ this.value = "";
1908
+ }
1909
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage);
1910
+ return false;
1911
+ }
1912
+
1913
+ const selections = this.getOption("selection");
1914
+ if (
1915
+ selections === undefined ||
1916
+ selections === null ||
1917
+ selections.length === 0
1918
+ ) {
1919
+ this.setOption(
1920
+ "messages.control",
1921
+ this.getOption("labels.select-an-option"),
1922
+ );
1923
+ } else {
1924
+ this.setOption("messages.control", "");
1925
+ }
1926
+
1927
+ this.setOption("messages.summary", setSummaryAndControlText.call(this));
1928
+
1929
+ let updated = false;
1930
+ let valueCounter = 1;
1931
+ for (const option of options) {
1932
+ if (option?.visibility === undefined) {
1933
+ option.visibility = "visible";
1934
+ updated = true;
1935
+ }
1936
+
1937
+ if (option?.value === undefined && option?.label === undefined) {
1938
+ option.value = `${valueCounter++}`;
1939
+ option.label = option.value;
1940
+ updated = true;
1941
+ continue;
1942
+ }
1943
+
1944
+ if (option?.value === undefined) {
1945
+ option.value = option.label;
1946
+ updated = true;
1947
+ }
1948
+
1949
+ if (option?.label === undefined) {
1950
+ option.label = option.value;
1951
+ updated = true;
1952
+ }
1953
+ }
1954
+
1955
+ if (updated) {
1956
+ this.setOption("options", options);
1957
+ }
1958
+
1959
+ setStatusOrRemoveBadges.call(this);
1960
+
1961
+ removeAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage);
1962
+ return true;
1968
1963
  }
1969
1964
 
1970
1965
  /**
@@ -1972,30 +1967,30 @@ function areOptionsAvailableAndInit() {
1972
1967
  * @throws {Error} no shadow-root is defined
1973
1968
  */
1974
1969
  function checkOptionState() {
1975
- if (!this.shadowRoot) {
1976
- throw new Error("no shadow-root is defined");
1977
- }
1978
-
1979
- const elements = this.shadowRoot.querySelectorAll(
1980
- `[${ATTRIBUTE_ROLE}=option] input`,
1981
- );
1982
-
1983
- let selection = this.getOption("selection");
1984
- if (!isArray(selection)) {
1985
- selection = [];
1986
- }
1987
-
1988
- const checkedValues = selection.map((a) => {
1989
- return a.value;
1990
- });
1991
-
1992
- for (const e of elements) {
1993
- if (checkedValues.indexOf(e.value) !== -1) {
1994
- if (e.checked !== true) e.checked = true;
1995
- } else {
1996
- if (e.checked !== false) e.checked = false;
1997
- }
1998
- }
1970
+ if (!this.shadowRoot) {
1971
+ throw new Error("no shadow-root is defined");
1972
+ }
1973
+
1974
+ const elements = this.shadowRoot.querySelectorAll(
1975
+ `[${ATTRIBUTE_ROLE}=option] input`,
1976
+ );
1977
+
1978
+ let selection = this.getOption("selection");
1979
+ if (!isArray(selection)) {
1980
+ selection = [];
1981
+ }
1982
+
1983
+ const checkedValues = selection.map((a) => {
1984
+ return a.value;
1985
+ });
1986
+
1987
+ for (const e of elements) {
1988
+ if (checkedValues.indexOf(e.value) !== -1) {
1989
+ if (e.checked !== true) e.checked = true;
1990
+ } else {
1991
+ if (e.checked !== false) e.checked = false;
1992
+ }
1993
+ }
1999
1994
  }
2000
1995
 
2001
1996
  /**
@@ -2004,41 +1999,41 @@ function checkOptionState() {
2004
1999
  * @return {Object}
2005
2000
  */
2006
2001
  function convertValueToSelection(value) {
2007
- const selection = [];
2008
-
2009
- if (isString(value)) {
2010
- value = value
2011
- .split(",")
2012
- .map((a) => {
2013
- return a.trim();
2014
- })
2015
- .filter((a) => {
2016
- return a !== "";
2017
- });
2018
- }
2019
-
2020
- if (isString(value) || isInteger(value)) {
2021
- selection.push({
2022
- label: getSelectionLabel.call(this, value),
2023
- value: value,
2024
- });
2025
- } else if (isArray(value)) {
2026
- for (const v of value) {
2027
- selection.push({
2028
- label: getSelectionLabel.call(this, v),
2029
- value: v,
2030
- });
2031
- }
2032
-
2033
- value = value.join(",");
2034
- } else {
2035
- throw new Error("unsupported type");
2036
- }
2037
-
2038
- return {
2039
- selection: selection,
2040
- value: value,
2041
- };
2002
+ const selection = [];
2003
+
2004
+ if (isString(value)) {
2005
+ value = value
2006
+ .split(",")
2007
+ .map((a) => {
2008
+ return a.trim();
2009
+ })
2010
+ .filter((a) => {
2011
+ return a !== "";
2012
+ });
2013
+ }
2014
+
2015
+ if (isString(value) || isInteger(value)) {
2016
+ selection.push({
2017
+ label: getSelectionLabel.call(this, value),
2018
+ value: value,
2019
+ });
2020
+ } else if (isArray(value)) {
2021
+ for (const v of value) {
2022
+ selection.push({
2023
+ label: getSelectionLabel.call(this, v),
2024
+ value: v,
2025
+ });
2026
+ }
2027
+
2028
+ value = value.join(",");
2029
+ } else {
2030
+ throw new Error("unsupported type");
2031
+ }
2032
+
2033
+ return {
2034
+ selection: selection,
2035
+ value: value,
2036
+ };
2042
2037
  }
2043
2038
 
2044
2039
  /**
@@ -2047,25 +2042,25 @@ function convertValueToSelection(value) {
2047
2042
  * @return {string}
2048
2043
  */
2049
2044
  function convertSelectionToValue(selection) {
2050
- const value = [];
2051
-
2052
- if (isArray(selection)) {
2053
- for (const obj of selection) {
2054
- const v = obj?.["value"];
2055
- if (v !== undefined) value.push(`${v}`);
2056
- }
2057
- }
2058
-
2059
- if (value.length === 0) {
2060
- return "";
2061
- } else if (value.length === 1) {
2062
- const v = value.pop();
2063
- if (v === undefined) return "";
2064
- if (v === null) return "";
2065
- return `${v}`;
2066
- }
2067
-
2068
- return value.join(",");
2045
+ const value = [];
2046
+
2047
+ if (isArray(selection)) {
2048
+ for (const obj of selection) {
2049
+ const v = obj?.["value"];
2050
+ if (v !== undefined) value.push(`${v}`);
2051
+ }
2052
+ }
2053
+
2054
+ if (value.length === 0) {
2055
+ return "";
2056
+ } else if (value.length === 1) {
2057
+ const v = value.pop();
2058
+ if (v === undefined) return "";
2059
+ if (v === null) return "";
2060
+ return `${v}`;
2061
+ }
2062
+
2063
+ return value.join(",");
2069
2064
  }
2070
2065
 
2071
2066
  /**
@@ -2075,76 +2070,76 @@ function convertSelectionToValue(selection) {
2075
2070
  * @throws {Error} no shadow-root is defined
2076
2071
  */
2077
2072
  function setSelection(selection) {
2078
- if (isString(selection)) {
2079
- const result = convertValueToSelection.call(this, selection);
2080
- selection = result?.selection;
2081
- } else if (selection === undefined) {
2082
- selection = [];
2083
- }
2084
-
2085
- validateArray(selection);
2086
-
2087
- for (let i = 0; i < selection.length; i++) {
2088
- let l = getSelectionLabel.call(this, selection[i].value);
2089
- if (l === selection[i].value) {
2090
- l = selection[i].label;
2091
- }
2092
-
2093
- selection[i] = {
2094
- label: l,
2095
- value: selection[i].value,
2096
- };
2097
- }
2098
-
2099
- this.setOption("selection", selection);
2100
- checkOptionState.call(this);
2101
- setSummaryAndControlText.call(this);
2102
-
2103
- try {
2104
- this?.setFormValue(this.value);
2105
- } catch (e) {
2106
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2107
- }
2108
-
2109
- fireCustomEvent(this, "monster-selected", {
2110
- selection,
2111
- });
2112
-
2113
- fireEvent(this, "change");
2114
-
2115
- return new Processing(() => {
2116
- const CLASSNAME = "selected";
2117
-
2118
- if (!this.shadowRoot) {
2119
- throw new Error("no shadow-root is defined");
2120
- }
2121
-
2122
- const notSelected = this.shadowRoot.querySelectorAll(":not(:checked)");
2123
-
2124
- if (notSelected) {
2125
- notSelected.forEach((node) => {
2126
- const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`);
2127
- if (parent) {
2128
- parent.classList.remove(CLASSNAME);
2129
- }
2130
- });
2131
- }
2132
-
2133
- const selected = this.shadowRoot.querySelectorAll(":checked");
2134
-
2135
- if (selected) {
2136
- selected.forEach((node) => {
2137
- const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`);
2138
- if (parent) {
2139
- parent.classList.add(CLASSNAME);
2140
- }
2141
- });
2142
- }
2143
- })
2144
- .run()
2145
- .catch((e) => {
2146
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2147
- });
2073
+ if (isString(selection) || isInteger(selection)) {
2074
+ const result = convertValueToSelection.call(this, selection);
2075
+ selection = result?.selection;
2076
+ } else if (selection === undefined || selection === null) {
2077
+ selection = [];
2078
+ }
2079
+
2080
+ validateArray(selection);
2081
+
2082
+ for (let i = 0; i < selection.length; i++) {
2083
+ let l = getSelectionLabel.call(this, selection[i].value);
2084
+ if (l === selection[i].value) {
2085
+ l = selection[i].label;
2086
+ }
2087
+
2088
+ selection[i] = {
2089
+ label: l,
2090
+ value: selection[i].value,
2091
+ };
2092
+ }
2093
+
2094
+ this.setOption("selection", selection);
2095
+ checkOptionState.call(this);
2096
+ setSummaryAndControlText.call(this);
2097
+
2098
+ try {
2099
+ this?.setFormValue(this.value);
2100
+ } catch (e) {
2101
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2102
+ }
2103
+
2104
+ fireCustomEvent(this, "monster-selected", {
2105
+ selection,
2106
+ });
2107
+
2108
+ fireEvent(this, "change");
2109
+
2110
+ return new Processing(() => {
2111
+ const CLASSNAME = "selected";
2112
+
2113
+ if (!this.shadowRoot) {
2114
+ throw new Error("no shadow-root is defined");
2115
+ }
2116
+
2117
+ const notSelected = this.shadowRoot.querySelectorAll(":not(:checked)");
2118
+
2119
+ if (notSelected) {
2120
+ notSelected.forEach((node) => {
2121
+ const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`);
2122
+ if (parent) {
2123
+ parent.classList.remove(CLASSNAME);
2124
+ }
2125
+ });
2126
+ }
2127
+
2128
+ const selected = this.shadowRoot.querySelectorAll(":checked");
2129
+
2130
+ if (selected) {
2131
+ selected.forEach((node) => {
2132
+ const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`);
2133
+ if (parent) {
2134
+ parent.classList.add(CLASSNAME);
2135
+ }
2136
+ });
2137
+ }
2138
+ })
2139
+ .run()
2140
+ .catch((e) => {
2141
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2142
+ });
2148
2143
  }
2149
2144
 
2150
2145
  /**
@@ -2155,139 +2150,139 @@ function setSelection(selection) {
2155
2150
  * @throws {TypeError} unsupported response
2156
2151
  */
2157
2152
  function fetchData(url) {
2158
- const self = this;
2159
- if (!url) url = this.getOption("url");
2160
- if (!url) return Promise.resolve();
2161
-
2162
- const fetchOptions = this.getOption("fetch", {});
2163
-
2164
- let delayWatch = false;
2165
-
2166
- // if fetch short time, do not show loading badge, because of flickering
2167
- requestAnimationFrame(() => {
2168
- if (delayWatch === true) return;
2169
- setStatusOrRemoveBadges.call(this, "loading");
2170
- delayWatch = true;
2171
- });
2172
-
2173
- url = formatURL.call(this, url);
2174
-
2175
- self[isLoadingSymbol] = true;
2176
- const global = getGlobal();
2177
- return global
2178
- .fetch(url, fetchOptions)
2179
- .then((response) => {
2180
- self[isLoadingSymbol] = false;
2181
- delayWatch = true;
2182
- const contentType = response.headers.get("content-type");
2183
- if (contentType && contentType.indexOf("application/json") !== -1) {
2184
- return response.text();
2185
- }
2186
-
2187
- throw new TypeError(`unsupported response ${contentType}`);
2188
- })
2189
- .then((text) => {
2190
- try {
2191
- return Promise.resolve(JSON.parse(String(text)));
2192
- } catch (e) {
2193
- throw new TypeError("the result cannot be parsed, check the URL");
2194
- }
2195
- })
2196
- .catch((e) => {
2197
- self[isLoadingSymbol] = false;
2198
- delayWatch = true;
2199
- throw e;
2200
- });
2153
+ const self = this;
2154
+ if (!url) url = this.getOption("url");
2155
+ if (!url) return Promise.resolve();
2156
+
2157
+ const fetchOptions = this.getOption("fetch", {});
2158
+
2159
+ let delayWatch = false;
2160
+
2161
+ // if fetch short time, do not show loading badge, because of flickering
2162
+ requestAnimationFrame(() => {
2163
+ if (delayWatch === true) return;
2164
+ setStatusOrRemoveBadges.call(this, "loading");
2165
+ delayWatch = true;
2166
+ });
2167
+
2168
+ url = formatURL.call(this, url);
2169
+
2170
+ self[isLoadingSymbol] = true;
2171
+ const global = getGlobal();
2172
+ return global
2173
+ .fetch(url, fetchOptions)
2174
+ .then((response) => {
2175
+ self[isLoadingSymbol] = false;
2176
+ delayWatch = true;
2177
+ const contentType = response.headers.get("content-type");
2178
+ if (contentType && contentType.indexOf("application/json") !== -1) {
2179
+ return response.text();
2180
+ }
2181
+
2182
+ throw new TypeError(`unsupported response ${contentType}`);
2183
+ })
2184
+ .then((text) => {
2185
+ try {
2186
+ return Promise.resolve(JSON.parse(String(text)));
2187
+ } catch (e) {
2188
+ throw new TypeError("the result cannot be parsed, check the URL");
2189
+ }
2190
+ })
2191
+ .catch((e) => {
2192
+ self[isLoadingSymbol] = false;
2193
+ delayWatch = true;
2194
+ throw e;
2195
+ });
2201
2196
  }
2202
2197
 
2203
2198
  /**
2204
2199
  * @private
2205
2200
  */
2206
2201
  function hide() {
2207
- this[popperElementSymbol].style.display = "none";
2208
- setStatusOrRemoveBadges.call(this, "closed");
2209
- removeAttributeToken(this[controlElementSymbol], "class", "open");
2202
+ this[popperElementSymbol].style.display = "none";
2203
+ setStatusOrRemoveBadges.call(this, "closed");
2204
+ removeAttributeToken(this[controlElementSymbol], "class", "open");
2210
2205
  }
2211
2206
 
2212
2207
  /**
2213
2208
  * @private
2214
2209
  */
2215
2210
  function show() {
2216
- if (this.getOption("disabled", undefined) === true) {
2217
- return;
2218
- }
2219
-
2220
- if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
2221
- return;
2222
- }
2223
-
2224
- focusFilter.call(this);
2225
-
2226
- const lazyLoadFlag =
2227
- this.getOption("features.lazyLoad") && this[lazyLoadDoneSymbol] !== true;
2228
-
2229
- if (lazyLoadFlag === true) {
2230
- this[lazyLoadDoneSymbol] = true;
2231
- setStatusOrRemoveBadges.call(this, "loading");
2232
-
2233
- new Processing(200, () => {
2234
- this.fetch()
2235
- .then(() => {
2236
- checkOptionState.call(this);
2237
- requestAnimationFrame(() => {
2238
- show.call(this);
2239
- });
2240
- })
2241
- .catch((e) => {
2242
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2243
- setStatusOrRemoveBadges.call(this, "error");
2244
- });
2245
- })
2246
- .run()
2247
- .catch((e) => {
2248
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2249
- setStatusOrRemoveBadges.call(this, "error");
2250
- });
2251
-
2252
- return;
2253
- }
2254
-
2255
- const hasPopperFilterFlag =
2256
- this.getOption("filter.position") === FILTER_POSITION_POPPER &&
2257
- getFilterMode.call(this) !== FILTER_MODE_DISABLED;
2258
-
2259
- const options = getOptionElements.call(this);
2260
- if (options.length === 0 && hasPopperFilterFlag === false) {
2261
- return;
2262
- }
2263
-
2264
- this[popperElementSymbol].style.visibility = "hidden";
2265
- this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
2266
- setStatusOrRemoveBadges.call(this, "open");
2267
-
2268
- addAttributeToken(this[controlElementSymbol], "class", "open");
2269
-
2270
- new Processing(() => {
2271
- calcAndSetOptionsDimension.call(this);
2272
- focusFilter.call(this);
2273
- this[popperElementSymbol].style.removeProperty("visibility");
2274
- updatePopper.call(this);
2275
- })
2276
- .run()
2277
- .catch((e) => {
2278
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2279
- });
2211
+ if (this.getOption("disabled", undefined) === true) {
2212
+ return;
2213
+ }
2214
+
2215
+ if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
2216
+ return;
2217
+ }
2218
+
2219
+ focusFilter.call(this);
2220
+
2221
+ const lazyLoadFlag =
2222
+ this.getOption("features.lazyLoad") && this[lazyLoadDoneSymbol] !== true;
2223
+
2224
+ if (lazyLoadFlag === true) {
2225
+ this[lazyLoadDoneSymbol] = true;
2226
+ setStatusOrRemoveBadges.call(this, "loading");
2227
+
2228
+ new Processing(200, () => {
2229
+ this.fetch()
2230
+ .then(() => {
2231
+ checkOptionState.call(this);
2232
+ requestAnimationFrame(() => {
2233
+ show.call(this);
2234
+ });
2235
+ })
2236
+ .catch((e) => {
2237
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2238
+ setStatusOrRemoveBadges.call(this, "error");
2239
+ });
2240
+ })
2241
+ .run()
2242
+ .catch((e) => {
2243
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2244
+ setStatusOrRemoveBadges.call(this, "error");
2245
+ });
2246
+
2247
+ return;
2248
+ }
2249
+
2250
+ const hasPopperFilterFlag =
2251
+ this.getOption("filter.position") === FILTER_POSITION_POPPER &&
2252
+ getFilterMode.call(this) !== FILTER_MODE_DISABLED;
2253
+
2254
+ const options = getOptionElements.call(this);
2255
+ if (options.length === 0 && hasPopperFilterFlag === false) {
2256
+ return;
2257
+ }
2258
+
2259
+ this[popperElementSymbol].style.visibility = "hidden";
2260
+ this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
2261
+ setStatusOrRemoveBadges.call(this, "open");
2262
+
2263
+ addAttributeToken(this[controlElementSymbol], "class", "open");
2264
+
2265
+ new Processing(() => {
2266
+ calcAndSetOptionsDimension.call(this);
2267
+ focusFilter.call(this);
2268
+ this[popperElementSymbol].style.removeProperty("visibility");
2269
+ updatePopper.call(this);
2270
+ })
2271
+ .run()
2272
+ .catch((e) => {
2273
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2274
+ });
2280
2275
  }
2281
2276
 
2282
2277
  /**
2283
2278
  * @private
2284
2279
  */
2285
2280
  function toggle() {
2286
- if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
2287
- hide.call(this);
2288
- } else {
2289
- show.call(this);
2290
- }
2281
+ if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
2282
+ hide.call(this);
2283
+ } else {
2284
+ show.call(this);
2285
+ }
2291
2286
  }
2292
2287
 
2293
2288
  /**
@@ -2296,188 +2291,188 @@ function toggle() {
2296
2291
  * @fires monster-selection-cleared
2297
2292
  */
2298
2293
  function initEventHandler() {
2299
- const self = this;
2300
-
2301
- /**
2302
- * @param {Event} event
2303
- */
2304
- self[clearOptionEventHandler] = (event) => {
2305
- const element = findTargetElementFromEvent(
2306
- event,
2307
- ATTRIBUTE_ROLE,
2308
- "remove-badge",
2309
- );
2310
-
2311
- if (element instanceof HTMLElement) {
2312
- const badge = findClosestByAttribute(element, ATTRIBUTE_ROLE, "badge");
2313
- if (badge instanceof HTMLElement) {
2314
- const value = badge.getAttribute(`${ATTRIBUTE_PREFIX}value`);
2315
-
2316
- let selection = self.getOption("selection");
2317
- selection = selection.filter((b) => {
2318
- return value !== b.value;
2319
- });
2320
-
2321
- setSelection
2322
- .call(self, selection)
2323
- .then(() => {
2324
- fireCustomEvent(self, "monster-selection-removed", {
2325
- value,
2326
- });
2327
- })
2328
- .catch((e) => {
2329
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
2330
- });
2331
- }
2332
- }
2333
- };
2334
-
2335
- /**
2336
- * @param {Event} event
2337
- */
2338
- self[closeEventHandler] = (event) => {
2339
- const path = event.composedPath();
2340
-
2341
- for (const [, element] of Object.entries(path)) {
2342
- if (element === self) {
2343
- return;
2344
- }
2345
- }
2346
- hide.call(self);
2347
- };
2348
-
2349
- /**
2350
- * @param {Event} event
2351
- */
2352
- self[inputEventHandler] = (event) => {
2353
- const path = event.composedPath();
2354
- const element = path?.[0];
2355
-
2356
- if (element instanceof HTMLElement) {
2357
- if (
2358
- element.hasAttribute(ATTRIBUTE_ROLE) &&
2359
- element.getAttribute(ATTRIBUTE_ROLE) === "option-control"
2360
- ) {
2361
- fireCustomEvent(self, "monster-change", {
2362
- type: event.type,
2363
- value: element.value,
2364
- checked: element.checked,
2365
- });
2366
- } else if (
2367
- element.hasAttribute(ATTRIBUTE_ROLE) &&
2368
- element.getAttribute(ATTRIBUTE_ROLE) === "filter"
2369
- ) {
2370
- }
2371
- }
2372
- };
2373
-
2374
- /**
2375
- * @param {Event} event
2376
- */
2377
- self[changeEventHandler] = (event) => {
2378
- gatherState.call(self);
2379
- fireCustomEvent(self, "monster-changed", event?.detail);
2380
- };
2381
-
2382
- self[keyEventHandler] = (event) => {
2383
- const path = event.composedPath();
2384
- const element = path.shift();
2385
-
2386
- let role;
2387
-
2388
- if (element instanceof HTMLElement) {
2389
- if (element.hasAttribute(ATTRIBUTE_ROLE)) {
2390
- role = element.getAttribute(ATTRIBUTE_ROLE);
2391
- } else if (element === this) {
2392
- show.call(this);
2393
- // focusFilter.call(self);
2394
- } else {
2395
- const e = element.closest(`[${ATTRIBUTE_ROLE}]`);
2396
- if (e instanceof HTMLElement && e.hasAttribute(ATTRIBUTE_ROLE)) {
2397
- role = e.getAttribute(ATTRIBUTE_ROLE);
2398
- }
2399
- }
2400
- } else {
2401
- return;
2402
- }
2403
-
2404
- switch (role) {
2405
- case "filter":
2406
- handleFilterKeyboardEvents.call(self, event);
2407
- break;
2408
- case "option-label":
2409
- case "option-control":
2410
- case "option":
2411
- handleOptionKeyboardEvents.call(self, event);
2412
- break;
2413
- case "control":
2414
- case "toggle":
2415
- handleToggleKeyboardEvents.call(self, event);
2416
- break;
2417
- }
2418
- };
2419
-
2420
- const types = self.getOption("toggleEventType", ["click"]);
2421
-
2422
- for (const [, type] of Object.entries(types)) {
2423
- self[controlElementSymbol]
2424
- .querySelector(`[${ATTRIBUTE_ROLE}="container"]`)
2425
- .addEventListener(type, function (event) {
2426
- const element = findTargetElementFromEvent(
2427
- event,
2428
- ATTRIBUTE_ROLE,
2429
- "remove-badge",
2430
- );
2431
- if (element instanceof HTMLElement) {
2432
- return;
2433
- }
2434
-
2435
- toggle.call(self);
2436
- });
2437
-
2438
- self[controlElementSymbol]
2439
- .querySelector(`[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`)
2440
- .addEventListener(type, function (event) {
2441
- if (self.getOption("disabled", undefined) === true) {
2442
- return;
2443
- }
2444
-
2445
- const path = event.composedPath();
2446
- const element = path?.[0];
2447
- if (element instanceof HTMLElement) {
2448
- const control = element.closest(
2449
- `[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`,
2450
- );
2451
- if (control instanceof HTMLElement) {
2452
- if (control.classList.contains("clear")) {
2453
- clearSelection.call(self);
2454
-
2455
- fireCustomEvent(self, "monster-selection-cleared", {});
2456
- } else {
2457
- const element = findTargetElementFromEvent(
2458
- event,
2459
- ATTRIBUTE_ROLE,
2460
- "remove-badge",
2461
- );
2462
- if (element instanceof HTMLElement) {
2463
- return;
2464
- }
2465
-
2466
- toggle.call(self);
2467
- }
2468
- }
2469
- }
2470
- });
2471
-
2472
- // badge, selection
2473
- self.addEventListener(type, self[clearOptionEventHandler]);
2474
- }
2475
-
2476
- self.addEventListener("monster-change", self[changeEventHandler]);
2477
- self.addEventListener("input", self[inputEventHandler]);
2478
- self.addEventListener("keydown", self[keyEventHandler]);
2479
-
2480
- return self;
2294
+ const self = this;
2295
+
2296
+ /**
2297
+ * @param {Event} event
2298
+ */
2299
+ self[clearOptionEventHandler] = (event) => {
2300
+ const element = findTargetElementFromEvent(
2301
+ event,
2302
+ ATTRIBUTE_ROLE,
2303
+ "remove-badge",
2304
+ );
2305
+
2306
+ if (element instanceof HTMLElement) {
2307
+ const badge = findClosestByAttribute(element, ATTRIBUTE_ROLE, "badge");
2308
+ if (badge instanceof HTMLElement) {
2309
+ const value = badge.getAttribute(`${ATTRIBUTE_PREFIX}value`);
2310
+
2311
+ let selection = self.getOption("selection");
2312
+ selection = selection.filter((b) => {
2313
+ return value !== b.value;
2314
+ });
2315
+
2316
+ setSelection
2317
+ .call(self, selection)
2318
+ .then(() => {
2319
+ fireCustomEvent(self, "monster-selection-removed", {
2320
+ value,
2321
+ });
2322
+ })
2323
+ .catch((e) => {
2324
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
2325
+ });
2326
+ }
2327
+ }
2328
+ };
2329
+
2330
+ /**
2331
+ * @param {Event} event
2332
+ */
2333
+ self[closeEventHandler] = (event) => {
2334
+ const path = event.composedPath();
2335
+
2336
+ for (const [, element] of Object.entries(path)) {
2337
+ if (element === self) {
2338
+ return;
2339
+ }
2340
+ }
2341
+ hide.call(self);
2342
+ };
2343
+
2344
+ /**
2345
+ * @param {Event} event
2346
+ */
2347
+ self[inputEventHandler] = (event) => {
2348
+ const path = event.composedPath();
2349
+ const element = path?.[0];
2350
+
2351
+ if (element instanceof HTMLElement) {
2352
+ if (
2353
+ element.hasAttribute(ATTRIBUTE_ROLE) &&
2354
+ element.getAttribute(ATTRIBUTE_ROLE) === "option-control"
2355
+ ) {
2356
+ fireCustomEvent(self, "monster-change", {
2357
+ type: event.type,
2358
+ value: element.value,
2359
+ checked: element.checked,
2360
+ });
2361
+ } else if (
2362
+ element.hasAttribute(ATTRIBUTE_ROLE) &&
2363
+ element.getAttribute(ATTRIBUTE_ROLE) === "filter"
2364
+ ) {
2365
+ }
2366
+ }
2367
+ };
2368
+
2369
+ /**
2370
+ * @param {Event} event
2371
+ */
2372
+ self[changeEventHandler] = (event) => {
2373
+ gatherState.call(self);
2374
+ fireCustomEvent(self, "monster-changed", event?.detail);
2375
+ };
2376
+
2377
+ self[keyEventHandler] = (event) => {
2378
+ const path = event.composedPath();
2379
+ const element = path.shift();
2380
+
2381
+ let role;
2382
+
2383
+ if (element instanceof HTMLElement) {
2384
+ if (element.hasAttribute(ATTRIBUTE_ROLE)) {
2385
+ role = element.getAttribute(ATTRIBUTE_ROLE);
2386
+ } else if (element === this) {
2387
+ show.call(this);
2388
+ // focusFilter.call(self);
2389
+ } else {
2390
+ const e = element.closest(`[${ATTRIBUTE_ROLE}]`);
2391
+ if (e instanceof HTMLElement && e.hasAttribute(ATTRIBUTE_ROLE)) {
2392
+ role = e.getAttribute(ATTRIBUTE_ROLE);
2393
+ }
2394
+ }
2395
+ } else {
2396
+ return;
2397
+ }
2398
+
2399
+ switch (role) {
2400
+ case "filter":
2401
+ handleFilterKeyboardEvents.call(self, event);
2402
+ break;
2403
+ case "option-label":
2404
+ case "option-control":
2405
+ case "option":
2406
+ handleOptionKeyboardEvents.call(self, event);
2407
+ break;
2408
+ case "control":
2409
+ case "toggle":
2410
+ handleToggleKeyboardEvents.call(self, event);
2411
+ break;
2412
+ }
2413
+ };
2414
+
2415
+ const types = self.getOption("toggleEventType", ["click"]);
2416
+
2417
+ for (const [, type] of Object.entries(types)) {
2418
+ self[controlElementSymbol]
2419
+ .querySelector(`[${ATTRIBUTE_ROLE}="container"]`)
2420
+ .addEventListener(type, function (event) {
2421
+ const element = findTargetElementFromEvent(
2422
+ event,
2423
+ ATTRIBUTE_ROLE,
2424
+ "remove-badge",
2425
+ );
2426
+ if (element instanceof HTMLElement) {
2427
+ return;
2428
+ }
2429
+
2430
+ toggle.call(self);
2431
+ });
2432
+
2433
+ self[controlElementSymbol]
2434
+ .querySelector(`[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`)
2435
+ .addEventListener(type, function (event) {
2436
+ if (self.getOption("disabled", undefined) === true) {
2437
+ return;
2438
+ }
2439
+
2440
+ const path = event.composedPath();
2441
+ const element = path?.[0];
2442
+ if (element instanceof HTMLElement) {
2443
+ const control = element.closest(
2444
+ `[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`,
2445
+ );
2446
+ if (control instanceof HTMLElement) {
2447
+ if (control.classList.contains("clear")) {
2448
+ clearSelection.call(self);
2449
+
2450
+ fireCustomEvent(self, "monster-selection-cleared", {});
2451
+ } else {
2452
+ const element = findTargetElementFromEvent(
2453
+ event,
2454
+ ATTRIBUTE_ROLE,
2455
+ "remove-badge",
2456
+ );
2457
+ if (element instanceof HTMLElement) {
2458
+ return;
2459
+ }
2460
+
2461
+ toggle.call(self);
2462
+ }
2463
+ }
2464
+ }
2465
+ });
2466
+
2467
+ // badge, selection
2468
+ self.addEventListener(type, self[clearOptionEventHandler]);
2469
+ }
2470
+
2471
+ self.addEventListener("monster-change", self[changeEventHandler]);
2472
+ self.addEventListener("input", self[inputEventHandler]);
2473
+ self.addEventListener("keydown", self[keyEventHandler]);
2474
+
2475
+ return self;
2481
2476
  }
2482
2477
 
2483
2478
  /**
@@ -2485,70 +2480,70 @@ function initEventHandler() {
2485
2480
  * @return {Select}
2486
2481
  */
2487
2482
  function setStatusOrRemoveBadges(suggestion) {
2488
- requestAnimationFrame(() => {
2489
- const selection = this.getOption("selection");
2490
-
2491
- const clearAllFlag =
2492
- isArray(selection) &&
2493
- selection.length > 0 &&
2494
- this.getOption("features.clearAll") === true;
2495
-
2496
- const current = this.getOption("classes.statusOrRemoveBadge");
2497
-
2498
- if (suggestion === "error") {
2499
- if (current !== "error") {
2500
- this.setOption("classes.statusOrRemoveBadge", "error");
2501
- }
2502
- return;
2503
- }
2504
-
2505
- if (this[isLoadingSymbol] === true) {
2506
- if (current !== "loading") {
2507
- this.setOption("classes.statusOrRemoveBadge", "loading");
2508
- }
2509
- return;
2510
- }
2511
-
2512
- if (suggestion === "loading") {
2513
- if (current !== "loading") {
2514
- this.setOption("classes.statusOrRemoveBadge", "loading");
2515
- }
2516
- return;
2517
- }
2518
-
2519
- if (clearAllFlag) {
2520
- if (current !== "clear") {
2521
- this.setOption("classes.statusOrRemoveBadge", "clear");
2522
- }
2523
- return;
2524
- }
2525
-
2526
- if (this[controlElementSymbol].classList.contains("open")) {
2527
- if (current !== "open") {
2528
- this.setOption("classes.statusOrRemoveBadge", "open");
2529
- }
2530
- return;
2531
- }
2532
-
2533
- const options = this.getOption("options");
2534
- if (
2535
- options === undefined ||
2536
- options === null ||
2537
- (isArray(options) && options.length === 0)
2538
- ) {
2539
- if (current !== "empty") {
2540
- this.setOption("classes.statusOrRemoveBadge", "empty");
2541
- }
2542
- return;
2543
- }
2544
-
2545
- if (suggestion) {
2546
- if (current !== suggestion) {
2547
- this.setOption("classes.statusOrRemoveBadge", suggestion);
2548
- }
2549
- return;
2550
- }
2551
- });
2483
+ requestAnimationFrame(() => {
2484
+ const selection = this.getOption("selection");
2485
+
2486
+ const clearAllFlag =
2487
+ isArray(selection) &&
2488
+ selection.length > 0 &&
2489
+ this.getOption("features.clearAll") === true;
2490
+
2491
+ const current = this.getOption("classes.statusOrRemoveBadge");
2492
+
2493
+ if (suggestion === "error") {
2494
+ if (current !== "error") {
2495
+ this.setOption("classes.statusOrRemoveBadge", "error");
2496
+ }
2497
+ return;
2498
+ }
2499
+
2500
+ if (this[isLoadingSymbol] === true) {
2501
+ if (current !== "loading") {
2502
+ this.setOption("classes.statusOrRemoveBadge", "loading");
2503
+ }
2504
+ return;
2505
+ }
2506
+
2507
+ if (suggestion === "loading") {
2508
+ if (current !== "loading") {
2509
+ this.setOption("classes.statusOrRemoveBadge", "loading");
2510
+ }
2511
+ return;
2512
+ }
2513
+
2514
+ if (clearAllFlag) {
2515
+ if (current !== "clear") {
2516
+ this.setOption("classes.statusOrRemoveBadge", "clear");
2517
+ }
2518
+ return;
2519
+ }
2520
+
2521
+ if (this[controlElementSymbol].classList.contains("open")) {
2522
+ if (current !== "open") {
2523
+ this.setOption("classes.statusOrRemoveBadge", "open");
2524
+ }
2525
+ return;
2526
+ }
2527
+
2528
+ const options = this.getOption("options");
2529
+ if (
2530
+ options === undefined ||
2531
+ options === null ||
2532
+ (isArray(options) && options.length === 0)
2533
+ ) {
2534
+ if (current !== "empty") {
2535
+ this.setOption("classes.statusOrRemoveBadge", "empty");
2536
+ }
2537
+ return;
2538
+ }
2539
+
2540
+ if (suggestion) {
2541
+ if (current !== suggestion) {
2542
+ this.setOption("classes.statusOrRemoveBadge", suggestion);
2543
+ }
2544
+ return;
2545
+ }
2546
+ });
2552
2547
  }
2553
2548
 
2554
2549
  /**
@@ -2557,68 +2552,68 @@ function setStatusOrRemoveBadges(suggestion) {
2557
2552
  * @throws {Error} no shadow-root is defined
2558
2553
  */
2559
2554
  function initControlReferences() {
2560
- if (!this.shadowRoot) {
2561
- throw new Error("no shadow-root is defined");
2562
- }
2563
-
2564
- this[controlElementSymbol] = this.shadowRoot.querySelector(
2565
- `[${ATTRIBUTE_ROLE}=control]`,
2566
- );
2567
- this[selectionElementSymbol] = this.shadowRoot.querySelector(
2568
- `[${ATTRIBUTE_ROLE}=selection]`,
2569
- );
2570
- this[containerElementSymbol] = this.shadowRoot.querySelector(
2571
- `[${ATTRIBUTE_ROLE}=container]`,
2572
- );
2573
- this[popperElementSymbol] = this.shadowRoot.querySelector(
2574
- `[${ATTRIBUTE_ROLE}=popper]`,
2575
- );
2576
- this[inlineFilterElementSymbol] = this.shadowRoot.querySelector(
2577
- `[${ATTRIBUTE_ROLE}=filter][name="inline-filter"]`,
2578
- );
2579
- this[popperFilterElementSymbol] = this.shadowRoot.querySelector(
2580
- `[${ATTRIBUTE_ROLE}=filter][name="popper-filter"]`,
2581
- );
2582
- this[popperFilterContainerElementSymbol] =
2583
- this[popperFilterElementSymbol].parentElement;
2584
- this[optionsElementSymbol] = this.shadowRoot.querySelector(
2585
- `[${ATTRIBUTE_ROLE}=options]`,
2586
- );
2587
- this[noOptionsAvailableElementSymbol] = this.shadowRoot.querySelector(
2588
- `[${ATTRIBUTE_ROLE}="no-options"]`,
2589
- );
2590
- this[statusOrRemoveBadgesElementSymbol] = this.shadowRoot.querySelector(
2591
- `[${ATTRIBUTE_ROLE}=status-or-remove-badges]`,
2592
- );
2555
+ if (!this.shadowRoot) {
2556
+ throw new Error("no shadow-root is defined");
2557
+ }
2558
+
2559
+ this[controlElementSymbol] = this.shadowRoot.querySelector(
2560
+ `[${ATTRIBUTE_ROLE}=control]`,
2561
+ );
2562
+ this[selectionElementSymbol] = this.shadowRoot.querySelector(
2563
+ `[${ATTRIBUTE_ROLE}=selection]`,
2564
+ );
2565
+ this[containerElementSymbol] = this.shadowRoot.querySelector(
2566
+ `[${ATTRIBUTE_ROLE}=container]`,
2567
+ );
2568
+ this[popperElementSymbol] = this.shadowRoot.querySelector(
2569
+ `[${ATTRIBUTE_ROLE}=popper]`,
2570
+ );
2571
+ this[inlineFilterElementSymbol] = this.shadowRoot.querySelector(
2572
+ `[${ATTRIBUTE_ROLE}=filter][name="inline-filter"]`,
2573
+ );
2574
+ this[popperFilterElementSymbol] = this.shadowRoot.querySelector(
2575
+ `[${ATTRIBUTE_ROLE}=filter][name="popper-filter"]`,
2576
+ );
2577
+ this[popperFilterContainerElementSymbol] =
2578
+ this[popperFilterElementSymbol].parentElement;
2579
+ this[optionsElementSymbol] = this.shadowRoot.querySelector(
2580
+ `[${ATTRIBUTE_ROLE}=options]`,
2581
+ );
2582
+ this[noOptionsAvailableElementSymbol] = this.shadowRoot.querySelector(
2583
+ `[${ATTRIBUTE_ROLE}="no-options"]`,
2584
+ );
2585
+ this[statusOrRemoveBadgesElementSymbol] = this.shadowRoot.querySelector(
2586
+ `[${ATTRIBUTE_ROLE}=status-or-remove-badges]`,
2587
+ );
2593
2588
  }
2594
2589
 
2595
2590
  /**
2596
2591
  * @private
2597
2592
  */
2598
2593
  function updatePopper() {
2599
- if (this[popperElementSymbol].style.display !== STYLE_DISPLAY_MODE_BLOCK) {
2600
- return;
2601
- }
2602
-
2603
- if (this.getOption("disabled", false) === true) {
2604
- return;
2605
- }
2606
-
2607
- new Processing(() => {
2608
- calcAndSetOptionsDimension.call(this);
2609
- positionPopper.call(
2610
- this,
2611
- this[controlElementSymbol],
2612
- this[popperElementSymbol],
2613
- this.getOption("popper", {}),
2614
- );
2615
- })
2616
- .run()
2617
- .catch((e) => {
2618
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2619
- });
2620
-
2621
- return this;
2594
+ if (this[popperElementSymbol].style.display !== STYLE_DISPLAY_MODE_BLOCK) {
2595
+ return;
2596
+ }
2597
+
2598
+ if (this.getOption("disabled", false) === true) {
2599
+ return;
2600
+ }
2601
+
2602
+ new Processing(() => {
2603
+ calcAndSetOptionsDimension.call(this);
2604
+ positionPopper.call(
2605
+ this,
2606
+ this[controlElementSymbol],
2607
+ this[popperElementSymbol],
2608
+ this.getOption("popper", {}),
2609
+ );
2610
+ })
2611
+ .run()
2612
+ .catch((e) => {
2613
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
2614
+ });
2615
+
2616
+ return this;
2622
2617
  }
2623
2618
 
2624
2619
  /**
@@ -2626,8 +2621,8 @@ function updatePopper() {
2626
2621
  * @return {string}
2627
2622
  */
2628
2623
  function getTemplate() {
2629
- // language=HTML
2630
- return `
2624
+ // language=HTML
2625
+ return `
2631
2626
  <template id="options">
2632
2627
  <div data-monster-role="option" tabindex="-1"
2633
2628
  data-monster-attributes="