@schukai/monster 3.96.0 → 3.96.1

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