@schukai/monster 3.48.0 → 3.50.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.
@@ -5,37 +5,37 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import {findElementWithIdUpwards} from "./util.mjs";
9
- import {internalSymbol} from "../constants.mjs";
10
- import {extend} from "../data/extend.mjs";
11
- import {Pathfinder} from "../data/pathfinder.mjs";
12
- import {Formatter} from "../text/formatter.mjs";
13
-
14
- import {parseDataURL} from "../types/dataurl.mjs";
15
- import {getGlobalObject} from "../types/global.mjs";
16
- import {isArray, isFunction, isIterable, isObject, isString} from "../types/is.mjs";
17
- import {Observer} from "../types/observer.mjs";
18
- import {ProxyObserver} from "../types/proxyobserver.mjs";
19
- import {validateFunction, validateInstance, validateObject, validateString} from "../types/validate.mjs";
20
- import {clone} from "../util/clone.mjs";
21
- import {addAttributeToken, getLinkedObjects, hasObjectLink} from "./attributes.mjs";
8
+ import { findElementWithIdUpwards } from "./util.mjs";
9
+ import { internalSymbol } from "../constants.mjs";
10
+ import { extend } from "../data/extend.mjs";
11
+ import { Pathfinder } from "../data/pathfinder.mjs";
12
+ import { Formatter } from "../text/formatter.mjs";
13
+
14
+ import { parseDataURL } from "../types/dataurl.mjs";
15
+ import { getGlobalObject } from "../types/global.mjs";
16
+ import { isArray, isFunction, isIterable, isObject, isString } from "../types/is.mjs";
17
+ import { Observer } from "../types/observer.mjs";
18
+ import { ProxyObserver } from "../types/proxyobserver.mjs";
19
+ import { validateFunction, validateInstance, validateObject, validateString } from "../types/validate.mjs";
20
+ import { clone } from "../util/clone.mjs";
21
+ import { addAttributeToken, getLinkedObjects, hasObjectLink } from "./attributes.mjs";
22
22
  import {
23
23
  ATTRIBUTE_DISABLED,
24
24
  ATTRIBUTE_ERRORMESSAGE,
25
25
  ATTRIBUTE_OPTIONS,
26
- ATTRIBUTE_OPTION_CALLBACK,
26
+ ATTRIBUTE_INIT_CALLBACK,
27
27
  ATTRIBUTE_OPTIONS_SELECTOR,
28
28
  ATTRIBUTE_SCRIPT_HOST,
29
29
  customElementUpdaterLinkSymbol,
30
- initControlCallbackName
30
+ initControlCallbackName,
31
31
  } from "./constants.mjs";
32
- import {findDocumentTemplate, Template} from "./template.mjs";
33
- import {addObjectWithUpdaterToElement} from "./updater.mjs";
34
- import {instanceSymbol} from "../constants.mjs";
35
- import {getDocumentTranslations, Translations} from "../i18n/translations.mjs";
36
- import {getSlottedElements} from "./slotted.mjs";
37
- import {initOptionsFromAttributes} from "./util/init-options-from-attributes.mjs";
38
- import {setOptionFromAttribute} from "./util/set-option-from-attribute.mjs";
32
+ import { findDocumentTemplate, Template } from "./template.mjs";
33
+ import { addObjectWithUpdaterToElement } from "./updater.mjs";
34
+ import { instanceSymbol } from "../constants.mjs";
35
+ import { getDocumentTranslations, Translations } from "../i18n/translations.mjs";
36
+ import { getSlottedElements } from "./slotted.mjs";
37
+ import { initOptionsFromAttributes } from "./util/init-options-from-attributes.mjs";
38
+ import { setOptionFromAttribute } from "./util/set-option-from-attribute.mjs";
39
39
 
40
40
  export {
41
41
  CustomElement,
@@ -121,15 +121,12 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
121
121
  */
122
122
 
123
123
  /**
124
- * To define a new HTML element we need the power of CustomElement
124
+ * The `CustomElement` class provides a way to define a new HTML element using the power of Custom Elements.
125
125
  *
126
- * IMPORTANT: after defining a `CustomElement`, the `registerCustomElement` method must be called
127
- * with the new class name. only then will the tag defined via the `getTag` method be made known to the DOM.
128
- *
129
- * <img src="./images/customelement-class.png">
130
- *
131
- * You can create the object via the function `document.createElement()`.
126
+ * **IMPORTANT:** After defining a `CustomElement`, the `registerCustomElement` method must be called with the new class name
127
+ * to make the tag defined via the `getTag` method known to the DOM.
132
128
  *
129
+ * You can create an instance of the object via the `document.createElement()` function.
133
130
  *
134
131
  * ## Interaction
135
132
  *
@@ -137,15 +134,13 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
137
134
  *
138
135
  * ## Styling
139
136
  *
140
- * For optimal display of custom-elements the pseudo-class :defined can be used.
137
+ * To display custom elements optimally, the `:defined` pseudo-class can be used. To prevent custom elements from being displayed and flickering until the control is registered,
138
+ * it is recommended to create a CSS directive.
141
139
  *
142
- * To prevent the custom elements from being displayed and flickering until the control is registered, it is recommended to create a css directive.
140
+ * In the simplest case, you can simply hide the control:
143
141
  *
144
- * In the simplest case, you can simply hide the control.
145
- *
146
- * ```
142
+ * ```html
147
143
  * <style>
148
- *
149
144
  * my-custom-element:not(:defined) {
150
145
  * display: none;
151
146
  * }
@@ -153,63 +148,65 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
153
148
  * my-custom-element:defined {
154
149
  * display: flex;
155
150
  * }
156
- *
157
151
  * </style>
158
152
  * ```
159
153
  *
160
- * Alternatively you can also display a loader
154
+ * Alternatively, you can display a loader:
161
155
  *
162
- * ```
156
+ * ```css
163
157
  * my-custom-element:not(:defined) {
164
- * display: flex;
165
- * box-shadow: 0 4px 10px 0 rgba(33, 33, 33, 0.15);
166
- * border-radius: 4px;
167
- * height: 200px;
168
- * position: relative;
169
- * overflow: hidden;
170
- * }
158
+ * display: flex;
159
+ * box-shadow: 0 4px 10px 0 rgba(33, 33, 33, 0.15);
160
+ * border-radius: 4px;
161
+ * height: 200px;
162
+ * position: relative;
163
+ * overflow: hidden;
164
+ * }
171
165
  *
172
166
  * my-custom-element:not(:defined)::before {
173
- * content: '';
174
- * display: block;
175
- * position: absolute;
176
- * left: -150px;
177
- * top: 0;
178
- * height: 100%;
179
- * width: 150px;
180
- * background: linear-gradient(to right, transparent 0%, #E8E8E8 50%, transparent 100%);
181
- * animation: load 1s cubic-bezier(0.4, 0.0, 0.2, 1) infinite;
182
- * }
167
+ * content: '';
168
+ * display: block;
169
+ * position: absolute;
170
+ * left: -150px;
171
+ * top: 0;
172
+ * height: 100%;
173
+ * width: 150px;
174
+ * background: linear-gradient(to right, transparent 0%, #E8E8E8 50%, transparent 100%);
175
+ * animation: load 1s cubic-bezier(0.4, 0.0, 0.2, 1) infinite;
176
+ * }
183
177
  *
184
178
  * @keyframes load {
185
- * from {
186
- * left: -150px;
187
- * }
188
- * to {
189
- * left: 100%;
190
- * }
191
- * }
179
+ * from {
180
+ * left: -150px;
181
+ * }
182
+ * to {
183
+ * left: 100%;
184
+ * }
185
+ * }
192
186
  *
193
187
  * my-custom-element:defined {
194
- * display: flex;
195
- * }
188
+ * display: flex;
189
+ * }
196
190
  * ```
197
191
  *
192
+ * More information about Custom Elements can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements).
193
+ * And in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
194
+ *
198
195
  * @externalExample ../../example/dom/theme.mjs
199
- * @see https://github.com/WICG/webcomponents
200
- * @see https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements
201
196
  * @license AGPLv3
202
197
  * @since 1.7.0
203
198
  * @copyright schukai GmbH
204
199
  * @memberOf Monster.DOM
205
200
  * @extends external:HTMLElement
206
- * @summary A base class for HTML5 customcontrols
201
+ * @summary A base class for HTML5 custom controls.
207
202
  */
208
203
  class CustomElement extends HTMLElement {
209
204
  /**
210
205
  * A new object is created. First the `initOptions` method is called. Here the
211
206
  * options can be defined in derived classes. Subsequently, the shadowRoot is initialized.
212
207
  *
208
+ * IMPORTANT: CustomControls instances are not created via the constructor, but either via a tag in the HTML or via <code>document.createElement()</code>.
209
+ *
213
210
  * @throws {Error} the options attribute does not contain a valid json definition.
214
211
  * @since 1.7.0
215
212
  */
@@ -223,7 +220,6 @@ class CustomElement extends HTMLElement {
223
220
  this[initMethodSymbol]();
224
221
  initOptionObserver.call(this);
225
222
  this[scriptHostElementSymbol] = [];
226
-
227
223
  }
228
224
 
229
225
  /**
@@ -270,53 +266,25 @@ class CustomElement extends HTMLElement {
270
266
  }
271
267
 
272
268
  /**
273
- * Derived classes can override and extend this method as follows.
269
+ * The `defaults` property defines the default values for a control. If you want to override these,
270
+ * you can use various methods, which are described in the documentation available at
271
+ * {@link https://monsterjs.orgendocconfigurate-a-monster-control}.
274
272
  *
275
- * ```
276
- * get defaults() {
277
- * return Object.assign({}, super.defaults, {
278
- * myValue:true
279
- * });
280
- * }
281
- * ```
282
- *
283
- * To set the options via the html tag the attribute data-monster-options must be set.
284
- * As value a JSON object with the desired values must be defined.
285
- *
286
- * Since 1.18.0 the JSON can be specified as a DataURI.
287
- *
288
- * ```
289
- * new Monster.Types.DataUrl(btoa(JSON.stringify({
290
- * shadowMode: 'open',
291
- * delegatesFocus: true,
292
- * templates: {
293
- * main: undefined
294
- * }
295
- * })),'application/json',true).toString()
296
- * ```
273
+ * The individual configuration values are listed below:
297
274
  *
298
- * The attribute data-monster-options-selector can be used to access a script tag that contains additional configuration.
275
+ * More information about the shadowRoot can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow),
276
+ * in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
299
277
  *
300
- * As value a selector must be specified, which belongs to a script tag and contains the configuration as json.
278
+ * More information about the template element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).
301
279
  *
302
- * ```
303
- * <script id="id-for-this-config" type="application/json">
304
- * {
305
- * "config-key": "config-value"
306
- * }
307
- * </script>
308
- * ```
309
- *
310
- * The individual configuration values can be found in the table.
311
- *
312
- * @property {boolean} disabled=false Object The Boolean disabled attribute, when present, makes the element not mutable, focusable, or even submitted with the form.
313
- * @property {string} shadowMode=open `open` Elements of the shadow root are accessible from JavaScript outside the root, for example using. `close` Denies access to the node(s) of a closed shadow root from JavaScript outside it
314
- * @property {Boolean} delegatesFocus=true A boolean that, when set to true, specifies behavior that mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling.
315
- * @property {Object} templates Templates
316
- * @property {string} templates.main=undefined Main template
317
- * @property {Object} templateMapping Template mapping
280
+ * More information about the slot element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot).
318
281
  *
319
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow
282
+ * @property {boolean} disabled=false Specifies whether the control is disabled. When present, it makes the element non-mutable, non-focusable, and non-submittable with the form.
283
+ * @property {string} shadowMode=open Specifies the mode of the shadow root. When set to `open`, elements in the shadow root are accessible from JavaScript outside the root, while setting it to `closed` denies access to the root's nodes from JavaScript outside it.
284
+ * @property {Boolean} delegatesFocus=true Specifies the behavior of the control with respect to focusability. When set to `true`, it mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling.
285
+ * @property {Object} templates Specifies the templates used by the control.
286
+ * @property {string} templates.main=undefined Specifies the main template used by the control.
287
+ * @property {Object} templateMapping Specifies the mapping of templates.
320
288
  * @since 1.8.0
321
289
  */
322
290
  get defaults() {
@@ -383,39 +351,51 @@ class CustomElement extends HTMLElement {
383
351
  }
384
352
 
385
353
  /**
386
- * There is no check on the name by this class. the developer is responsible for assigning an appropriate tag.
387
- * if the name is not valid, registerCustomElement() will issue an error
354
+ * The `getTag()` method returns the tag name associated with the custom element. This method should be overwritten
355
+ * by the derived class.
388
356
  *
389
- * @link https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
390
- * @return {string}
391
- * @throws {Error} the method getTag must be overwritten by the derived class.
357
+ * Note that there is no check on the name of the tag in this class. It is the responsibility of
358
+ * the developer to assign an appropriate tag name. If the name is not valid, the
359
+ * `registerCustomElement()` method will issue an error.
360
+ *
361
+ * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
362
+ * @throws {Error} This method must be overridden by the derived class.
363
+ * @return {string} The tag name associated with the custom element.
392
364
  * @since 1.7.0
393
365
  */
394
366
  static getTag() {
395
- throw new Error("the method getTag must be overwritten by the derived class.");
367
+ throw new Error("The method `getTag()` must be overridden by the derived class.");
396
368
  }
397
369
 
398
370
  /**
399
- * At this point a `CSSStyleSheet` object can be returned. If the environment does not
400
- * support a constructor, then an object can also be built using the following detour.
371
+ * The `getCSSStyleSheet()` method returns a `CSSStyleSheet` object that defines the styles for the custom element.
372
+ * If the environment does not support the `CSSStyleSheet` constructor, then an object can be built using the provided detour.
373
+ *
374
+ * If `undefined` is returned, then the shadow root does not receive a stylesheet.
401
375
  *
402
- * If `undefined` is returned then the shadowRoot does not get a stylesheet.
376
+ * Example usage:
403
377
  *
378
+ * ```js
379
+ * static getCSSStyleSheet() {
380
+ * const sheet = new CSSStyleSheet();
381
+ * sheet.replaceSync("p { color: red; }");
382
+ * return sheet;
383
+ * }
404
384
  * ```
405
- * const doc = document.implementation.createHTMLDocument('title');
406
385
  *
407
- * let style = doc.createElement("style");
408
- * style.innerHTML="p{color:red;}";
386
+ * If the environment does not support the `CSSStyleSheet` constructor,
387
+ * you can use the following workaround to create the stylesheet:
409
388
  *
410
- * // WebKit Hack
389
+ * ```js
390
+ * const doc = document.implementation.createHTMLDocument('title');
391
+ * let style = doc.createElement("style");
392
+ * style.innerHTML = "p { color: red; }";
411
393
  * style.appendChild(document.createTextNode(""));
412
- * // Add the <style> element to the page
413
394
  * doc.head.appendChild(style);
414
395
  * return doc.styleSheets[0];
415
- * ;
416
396
  * ```
417
397
  *
418
- * @return {CSSStyleSheet|CSSStyleSheet[]|string|undefined}
398
+ * @return {CSSStyleSheet|CSSStyleSheet[]|string|undefined} A `CSSStyleSheet` object or an array of such objects that define the styles for the custom element, or `undefined` if no stylesheet should be applied.
419
399
  */
420
400
  static getCSSStyleSheet() {
421
401
  return undefined;
@@ -464,8 +444,7 @@ class CustomElement extends HTMLElement {
464
444
 
465
445
  try {
466
446
  value = new Pathfinder(this[internalSymbol].getRealSubject()["options"]).getVia(path);
467
- } catch (e) {
468
- }
447
+ } catch (e) {}
469
448
 
470
449
  if (value === undefined) return defaultValue;
471
450
  return value;
@@ -511,9 +490,14 @@ class CustomElement extends HTMLElement {
511
490
  }
512
491
 
513
492
  /**
514
- * Is called once when the object is included in the DOM for the first time.
493
+ * This method is called once when the object is included in the DOM for the first time. It performs the following actions:
494
+ * 1. Extracts the options from the attributes and the script tag of the element and sets them.
495
+ * 2. Initializes the shadow root and its CSS stylesheet (if specified).
496
+ * 3. Initializes the HTML content of the element.
497
+ * 4. Initializes the custom elements inside the shadow root and the slotted elements.
498
+ * 5. Attaches a mutation observer to observe changes to the attributes of the element.
515
499
  *
516
- * @return {CustomElement}
500
+ * @return {CustomElement} - The updated custom element.
517
501
  * @since 1.8.0
518
502
  */
519
503
  [assembleMethodSymbol]() {
@@ -521,22 +505,25 @@ class CustomElement extends HTMLElement {
521
505
  let elements;
522
506
  let nodeList;
523
507
 
508
+ // Extract options from attributes and set them
524
509
  const AttributeOptions = getOptionsFromAttributes.call(self);
525
510
  if (isObject(AttributeOptions) && Object.keys(AttributeOptions).length > 0) {
526
511
  self.setOptions(AttributeOptions);
527
512
  }
528
513
 
514
+ // Extract options from script tag and set them
529
515
  const ScriptOptions = getOptionsFromScriptTag.call(self);
530
516
  if (isObject(ScriptOptions) && Object.keys(ScriptOptions).length > 0) {
531
517
  self.setOptions(ScriptOptions);
532
518
  }
533
519
 
534
-
520
+ // Initialize the shadow root and its CSS stylesheet
535
521
  if (self.getOption("shadowMode", false) !== false) {
536
522
  try {
537
523
  initShadowRoot.call(self);
538
524
  elements = self.shadowRoot.childNodes;
539
525
  } catch (e) {
526
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
540
527
  }
541
528
 
542
529
  try {
@@ -546,21 +533,19 @@ class CustomElement extends HTMLElement {
546
533
  }
547
534
  }
548
535
 
536
+ // If the elements are not found inside the shadow root, initialize the HTML content of the element
549
537
  if (!(elements instanceof NodeList)) {
550
- if (!(elements instanceof NodeList)) {
551
- initHtmlContent.call(this);
552
- elements = this.childNodes;
553
- }
538
+ initHtmlContent.call(this);
539
+ elements = this.childNodes;
554
540
  }
555
541
 
542
+ // Initialize the custom elements inside the shadow root and the slotted elements
556
543
  initFromCallbackHost.call(this);
557
-
558
544
  try {
559
545
  nodeList = new Set([...elements, ...getSlottedElements.call(self)]);
560
546
  } catch (e) {
561
547
  nodeList = elements;
562
548
  }
563
-
564
549
  addObjectWithUpdaterToElement.call(
565
550
  self,
566
551
  nodeList,
@@ -568,24 +553,28 @@ class CustomElement extends HTMLElement {
568
553
  clone(self[internalSymbol].getRealSubject()["options"]),
569
554
  );
570
555
 
556
+ // Attach a mutation observer to observe changes to the attributes of the element
571
557
  attachAttributeChangeMutationObserver.call(this);
572
558
 
573
559
  return self;
574
560
  }
575
561
 
576
562
  /**
577
- * Called every time the element is inserted into the DOM. Useful for running setup code, such as
578
- * fetching resources or rendering. Generally, you should try to delay work until this time.
563
+ * This method is called every time the element is inserted into the DOM. It checks if the custom element
564
+ * has already been initialized and if not, calls the assembleMethod to initialize it.
579
565
  *
580
566
  * @return {void}
581
567
  * @since 1.7.0
568
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/connectedCallback
582
569
  */
583
570
  connectedCallback() {
584
- let self = this;
571
+ const self = this;
572
+
573
+ // Check if the object has already been initialized
585
574
  if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
575
+ // If not, call the assembleMethod to initialize the object
586
576
  self[assembleMethodSymbol]();
587
577
  }
588
-
589
578
  }
590
579
 
591
580
  /**
@@ -594,8 +583,7 @@ class CustomElement extends HTMLElement {
594
583
  * @return {void}
595
584
  * @since 1.7.0
596
585
  */
597
- disconnectedCallback() {
598
- }
586
+ disconnectedCallback() {}
599
587
 
600
588
  /**
601
589
  * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
@@ -603,8 +591,7 @@ class CustomElement extends HTMLElement {
603
591
  * @return {void}
604
592
  * @since 1.7.0
605
593
  */
606
- adoptedCallback() {
607
- }
594
+ adoptedCallback() {}
608
595
 
609
596
  /**
610
597
  * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
@@ -621,7 +608,7 @@ class CustomElement extends HTMLElement {
621
608
  const self = this;
622
609
 
623
610
  if (attrName.startsWith("data-monster-option-")) {
624
- setOptionFromAttribute(self, attrName, this[internalSymbol].getSubject()["options"])
611
+ setOptionFromAttribute(self, attrName, this[internalSymbol].getSubject()["options"]);
625
612
  }
626
613
 
627
614
  const callback = self[attributeObserverSymbol]?.[attrName];
@@ -631,7 +618,6 @@ class CustomElement extends HTMLElement {
631
618
  } catch (e) {
632
619
  addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
633
620
  }
634
-
635
621
  }
636
622
  }
637
623
 
@@ -658,7 +644,7 @@ class CustomElement extends HTMLElement {
658
644
 
659
645
  /**
660
646
  * Calls a callback function if it exists.
661
- *
647
+ *
662
648
  * @param {string} name
663
649
  * @param {*} args
664
650
  * @returns {*}
@@ -667,8 +653,6 @@ class CustomElement extends HTMLElement {
667
653
  const self = this;
668
654
  return callControlCallback.call(self, name, ...args);
669
655
  }
670
-
671
-
672
656
  }
673
657
 
674
658
  /**
@@ -685,7 +669,6 @@ function callControlCallback(callBackFunctionName, ...args) {
685
669
 
686
670
  if (callBackFunctionName in self) {
687
671
  return self[callBackFunctionName](self, ...args);
688
-
689
672
  }
690
673
 
691
674
  if (!self.hasAttribute(ATTRIBUTE_SCRIPT_HOST)) {
@@ -693,13 +676,12 @@ function callControlCallback(callBackFunctionName, ...args) {
693
676
  }
694
677
 
695
678
  if (self[scriptHostElementSymbol].length === 0) {
696
-
697
679
  const targetId = self.getAttribute(ATTRIBUTE_SCRIPT_HOST);
698
680
  if (!targetId) {
699
681
  return;
700
682
  }
701
683
 
702
- const list = targetId.split(",")
684
+ const list = targetId.split(",");
703
685
  for (const id of list) {
704
686
  const host = findElementWithIdUpwards(self, targetId);
705
687
  if (!(host instanceof HTMLElement)) {
@@ -721,33 +703,34 @@ function callControlCallback(callBackFunctionName, ...args) {
721
703
  }
722
704
 
723
705
  addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `callback ${callBackFunctionName} not found`);
724
-
725
706
  }
726
707
 
727
708
  /**
728
- * This Function is called when the element is attached to the DOM.
729
- *
730
- * It looks for the attribute `data-monster-option-callback`. Is this attribute is not set, the default callback
731
- * `initCustomControlCallback` is called.
732
- *
733
- * The callback is searched in this element and in the host element. If the callback is found, it is called with the
734
- * element as parameter.
709
+ * Initializes the custom element based on the provided callback function.
735
710
  *
736
- * The `monster
711
+ * This function is called when the element is attached to the DOM. It checks if the
712
+ * `data-monster-option-callback` attribute is set, and if not, the default callback
713
+ * `initCustomControlCallback` is called. The callback function is searched for in this
714
+ * element and in the host element. If the callback is found, it is called with the element
715
+ * as a parameter.
737
716
  *
738
717
  * @this CustomElement
718
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#providing_a_construction_callback
719
+ * @since 1.8.0
739
720
  */
740
721
  function initFromCallbackHost() {
741
722
  const self = this;
742
723
 
743
- let callBackFunctionName = initControlCallbackName // default callback
744
- if (self.hasAttribute(ATTRIBUTE_OPTION_CALLBACK)) {
745
- callBackFunctionName = self.getAttribute(ATTRIBUTE_OPTION_CALLBACK);
724
+ // Set the default callback function name
725
+ let callBackFunctionName = initControlCallbackName;
726
+
727
+ // If the `data-monster-option-callback` attribute is set, use its value as the callback function name
728
+ if (self.hasAttribute(ATTRIBUTE_INIT_CALLBACK)) {
729
+ callBackFunctionName = self.getAttribute(ATTRIBUTE_INIT_CALLBACK);
746
730
  }
747
731
 
732
+ // Call the callback function with the element as a parameter if it exists
748
733
  callControlCallback.call(self, callBackFunctionName);
749
-
750
-
751
734
  }
752
735
 
753
736
  /**
@@ -766,7 +749,11 @@ function attachAttributeChangeMutationObserver() {
766
749
  self[attributeMutationObserverSymbol] = new MutationObserver(function (mutations, observer) {
767
750
  for (const mutation of mutations) {
768
751
  if (mutation.type === "attributes") {
769
- self.attributeChangedCallback(mutation.attributeName, mutation.oldValue, mutation.target.getAttribute(mutation.attributeName));
752
+ self.attributeChangedCallback(
753
+ mutation.attributeName,
754
+ mutation.oldValue,
755
+ mutation.target.getAttribute(mutation.attributeName),
756
+ );
770
757
  }
771
758
  }
772
759
  });
@@ -776,7 +763,6 @@ function attachAttributeChangeMutationObserver() {
776
763
  attributes: true,
777
764
  attributeOldValue: true,
778
765
  });
779
-
780
766
  } catch (e) {
781
767
  addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
782
768
  }
@@ -974,8 +960,7 @@ function parseOptionsJSON(data) {
974
960
  try {
975
961
  let dataUrl = parseDataURL(data);
976
962
  data = dataUrl.content;
977
- } catch (e) {
978
- }
963
+ } catch (e) {}
979
964
 
980
965
  try {
981
966
  obj = JSON.parse(data);
@@ -75,10 +75,8 @@ function getDeviceDPI() {
75
75
  */
76
76
 
77
77
  function convertToPixels(value, parentElement = document.documentElement, fontSizeElement = document.documentElement) {
78
-
79
78
  validateString(value);
80
-
81
-
79
+
82
80
  const regex = /^(-?[\d.]+)(.*)$/;
83
81
  const matchResult = value.match(regex);
84
82
 
@@ -5,7 +5,7 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- export {extractKeys}
8
+ export { extractKeys };
9
9
 
10
10
  /**
11
11
  * Extracts the keys from the given object and returns a map with the keys and values.
@@ -17,17 +17,21 @@ export {extractKeys}
17
17
  * @param {string} valueSeparator
18
18
  * @returns {Map<any, any>}
19
19
  */
20
- function extractKeys(obj, keyPrefix = '', keySeparator = '-', valueSeparator = '.') {
20
+ function extractKeys(obj, keyPrefix = "", keySeparator = "-", valueSeparator = ".") {
21
21
  const resultMap = new Map();
22
22
 
23
23
  function helper(currentObj, currentKeyPrefix, currentValuePrefix) {
24
24
  for (const key in currentObj) {
25
- if (typeof currentObj[key] === 'object' && !Array.isArray(currentObj[key])) {
26
- const newKeyPrefix = currentKeyPrefix ? currentKeyPrefix + keySeparator + key.toLowerCase() : key.toLowerCase();
25
+ if (typeof currentObj[key] === "object" && !Array.isArray(currentObj[key])) {
26
+ const newKeyPrefix = currentKeyPrefix
27
+ ? currentKeyPrefix + keySeparator + key.toLowerCase()
28
+ : key.toLowerCase();
27
29
  const newValuePrefix = currentValuePrefix ? currentValuePrefix + valueSeparator + key : key;
28
30
  helper(currentObj[key], newKeyPrefix, newValuePrefix);
29
31
  } else {
30
- const finalKey = currentKeyPrefix ? currentKeyPrefix + keySeparator + key.toLowerCase() : key.toLowerCase();
32
+ const finalKey = currentKeyPrefix
33
+ ? currentKeyPrefix + keySeparator + key.toLowerCase()
34
+ : key.toLowerCase();
31
35
  const finalValue = currentValuePrefix ? currentValuePrefix + valueSeparator + key : key;
32
36
  resultMap.set(finalKey, finalValue);
33
37
  }
@@ -36,4 +40,4 @@ function extractKeys(obj, keyPrefix = '', keySeparator = '-', valueSeparator = '
36
40
 
37
41
  helper(obj, keyPrefix, keyPrefix);
38
42
  return resultMap;
39
- }
43
+ }