@schukai/monster 3.80.4 → 3.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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="