@schukai/monster 3.102.2 → 3.102.3

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