@schukai/monster 3.80.4 → 3.81.0

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