@schukai/monster 3.80.2 → 3.80.4

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