@schukai/monster 3.80.2 → 3.80.4

Sign up to get free protection for your applications and to get access to all the features.
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="