@schukai/monster 3.48.0 → 3.50.0

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