@schukai/monster 3.102.5 → 3.103.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.
@@ -29,20 +29,33 @@ import {
29
29
  } from "./constants.mjs";
30
30
 
31
31
  import {Base} from "../types/base.mjs";
32
- import {isArray, isString, isInstance, isIterable} from "../types/is.mjs";
32
+ import {isArray, isInteger, isString, isInstance, isIterable} from "../types/is.mjs";
33
33
  import {Observer} from "../types/observer.mjs";
34
34
  import {ProxyObserver} from "../types/proxyobserver.mjs";
35
35
  import {validateArray, validateInstance} from "../types/validate.mjs";
36
36
  import {clone} from "../util/clone.mjs";
37
37
  import {trimSpaces} from "../util/trimspaces.mjs";
38
38
  import {addAttributeToken, addToObjectLink} from "./attributes.mjs";
39
- import {CustomElement, updaterTransformerMethodsSymbol} from "./customelement.mjs";
39
+ import {
40
+ CustomElement,
41
+ updaterTransformerMethodsSymbol,
42
+ } from "./customelement.mjs";
40
43
  import {findTargetElementFromEvent} from "./events.mjs";
41
44
  import {findDocumentTemplate} from "./template.mjs";
42
45
  import {getWindow} from "./util.mjs";
46
+ import {DeadMansSwitch} from "../util/deadmansswitch.mjs";
47
+ import {addErrorAttribute, removeErrorAttribute} from "./error.mjs";
48
+
43
49
 
44
50
  export {Updater, addObjectWithUpdaterToElement};
45
51
 
52
+
53
+ /**
54
+ * @private
55
+ * @type {symbol}
56
+ */
57
+ const timerElementEventHandlerSymbol = Symbol("timerElementEventHandler");
58
+
46
59
  /**
47
60
  * The updater class connects an object with the DOM. In this way, structures and contents in the DOM can be
48
61
  * programmatically adapted via attributes.
@@ -306,11 +319,20 @@ function getControlEventHandler() {
306
319
  return;
307
320
  }
308
321
 
309
- queueMicrotask(() => {
322
+ if (this[timerElementEventHandlerSymbol] instanceof DeadMansSwitch) {
323
+ try {
324
+ this[timerElementEventHandlerSymbol].touch();
325
+ return;
326
+ } catch (e) {
327
+ delete this[timerElementEventHandlerSymbol];
328
+ }
329
+ }
330
+
331
+ this[timerElementEventHandlerSymbol] = new DeadMansSwitch(50, () => {
310
332
  try {
311
333
  retrieveAndSetValue.call(this, element);
312
334
  } catch (e) {
313
- addAttributeToken(element, ATTRIBUTE_ERRORMESSAGE, e.message || `${e}`);
335
+ addErrorAttribute(element, e);
314
336
  }
315
337
  });
316
338
  };
@@ -380,62 +402,109 @@ function retrieveAndSetValue(element) {
380
402
  throw new Error("unsupported object");
381
403
  }
382
404
 
383
- if (isString(value)) {
384
- const type = element.getAttribute(ATTRIBUTE_UPDATER_BIND_TYPE);
385
- switch (type) {
386
- case "number":
387
- case "int":
388
- case "float":
389
- case "integer":
390
- value = Number(value);
391
- if (isNaN(value)) {
392
- value = 0;
405
+ const type = element.getAttribute(ATTRIBUTE_UPDATER_BIND_TYPE);
406
+ switch (type) {
407
+ case "number":
408
+ case "int":
409
+ case "float":
410
+ case "integer":
411
+ value = Number(value);
412
+ if (isNaN(value)) {
413
+ value = 0;
414
+ }
415
+ break;
416
+ case "boolean":
417
+ case "bool":
418
+ case "checkbox":
419
+ value = value === "true" || value === "1" || value === "on" || value === true;
420
+ break;
421
+
422
+ case "string[]":
423
+ if (isString(value)) {
424
+
425
+ if (value.trim() === "") {
426
+ value = [];
427
+ } else {
428
+ value = value.split(",").map((v) => `${v}`);
393
429
  }
394
- break;
395
- case "boolean":
396
- case "bool":
397
- case "checkbox":
398
- value = value === "true" || value === "1" || value === "on";
399
- break;
430
+ } else if (isInteger(value)) {
431
+ value = [`${value}`];
432
+ } else if (value === undefined || value === null) {
433
+ value = [];
434
+ } else if (isArray(value)) {
435
+ value = value.map((v) => `${v}`);
436
+ } else {
437
+ throw new Error("unsupported value");
438
+ }
439
+
440
+ break;
400
441
 
401
- case "string[]":
402
- if (value === "") {
442
+ case "int[]":
443
+ case "integer[]":
444
+
445
+ if (isString(value)) {
446
+
447
+ if (value.trim() === "") {
403
448
  value = [];
449
+ } else {
450
+ value = value.split(",").map((v) => {
451
+ try {
452
+ return parseInt(v, 10);
453
+ } catch (e) {
454
+ }
455
+ return -1;
456
+ }).filter((v) => v !== -1);
404
457
  }
405
458
 
406
- value = value.split(",").map((v) => `${v}`);
407
- break;
459
+ } else if (isInteger(value)) {
460
+ value = [value];
461
+ } else if (value === undefined || value === null) {
462
+ value = [];
463
+ } else if (isArray(value)) {
464
+ value = value.split(",").map((v) => {
465
+ try {
466
+ return parseInt(v, 10);
467
+ } catch (e) {
468
+ }
469
+ return -1;
470
+ }).filter((v) => v !== -1);
471
+ } else {
472
+ throw new Error("unsupported value");
473
+ }
474
+
475
+ break;
476
+ case "[]":
477
+ case "array":
478
+ case "list":
408
479
 
409
- case "int[]":
410
- case "integer[]":
411
- if (value === "") {
480
+ if (isString(value)) {
481
+ if (value.trim() === "") {
412
482
  value = [];
413
483
  } else {
414
- value = value
415
- .split(",")
416
- .map((v) => {
417
- try {
418
- return parseInt(v, 10);
419
- } catch (e) {
420
- }
421
- return -1;
422
- })
423
- .filter((v) => v !== -1);
484
+ value = value.split(",");
424
485
  }
486
+ } else if (isInteger(value)) {
487
+ value = [value];
488
+ } else if (value === undefined || value === null) {
489
+ value = [];
490
+ } else if (isArray(value)) {
491
+ // nothing to do
492
+ } else {
493
+ throw new Error("unsupported value for array");
494
+ }
495
+ break;
496
+ case "object":
497
+ case "json":
425
498
 
426
- break;
427
- case "[]":
428
- case "array":
429
- case "list":
430
- value = value.split(",");
431
- break;
432
- case "object":
433
- case "json":
499
+ if (isString(value)) {
434
500
  value = JSON.parse(value);
435
- break;
436
- default:
437
- break;
438
- }
501
+ } else {
502
+ throw new Error("unsupported value for object");
503
+ }
504
+
505
+ break;
506
+ default:
507
+ break;
439
508
  }
440
509
 
441
510
  const copy = clone(this[internalSymbol].subject.getRealSubject());
@@ -558,7 +627,7 @@ function insertElement(change) {
558
627
  containerElement.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
559
628
  value = pipe.run(subject);
560
629
  } catch (e) {
561
- containerElement.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
630
+ addErrorAttribute(containerElement, e);
562
631
  }
563
632
 
564
633
  const dataPath = cmd.split(":").pop();
@@ -604,12 +673,7 @@ function insertElement(change) {
604
673
  try {
605
674
  containerElement.removeChild(node);
606
675
  } catch (e) {
607
- containerElement.setAttribute(
608
- ATTRIBUTE_ERRORMESSAGE,
609
- `${containerElement.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
610
- e.message
611
- }`.trim(),
612
- );
676
+ addErrorAttribute(containerElement, e);
613
677
  }
614
678
  }
615
679
  }
@@ -660,27 +724,32 @@ function appendNewDocumentFragment(container, key, ref, path) {
660
724
  * @return {void}
661
725
  */
662
726
  function applyRecursive(node, key, path) {
663
- if (node instanceof HTMLElement) {
664
- if (node.hasAttribute(ATTRIBUTE_UPDATER_REPLACE)) {
665
- const value = node.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
666
- node.setAttribute(
667
- ATTRIBUTE_UPDATER_REPLACE,
668
- value.replaceAll(`path:${key}`, `path:${path}`),
669
- );
670
- }
727
+ if (!(node instanceof HTMLElement)) {
728
+ return
729
+ }
671
730
 
672
- if (node.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
673
- const value = node.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
674
- node.setAttribute(
675
- ATTRIBUTE_UPDATER_ATTRIBUTES,
676
- value.replaceAll(`path:${key}`, `path:${path}`),
677
- );
678
- }
731
+ if (node.hasAttribute(ATTRIBUTE_UPDATER_REPLACE)) {
732
+ const value = node.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
733
+ node.setAttribute(
734
+ ATTRIBUTE_UPDATER_REPLACE,
735
+ value.replaceAll(`path:${key}`, `path:${path}`),
736
+ );
737
+ }
679
738
 
680
- for (const [, child] of Object.entries(node.childNodes)) {
739
+ if (node.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
740
+ const value = node.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
741
+ node.setAttribute(
742
+ ATTRIBUTE_UPDATER_ATTRIBUTES,
743
+ value.replaceAll(`path:${key}`, `path:${path}`),
744
+ );
745
+ }
746
+
747
+ for (const [, child] of Object.entries(node.childNodes)) {
748
+ if (child instanceof HTMLElement) {
681
749
  applyRecursive(child, key, path);
682
750
  }
683
751
  }
752
+
684
753
  }
685
754
 
686
755
  /**
@@ -768,12 +837,7 @@ function runUpdateContent(container, parts, subject) {
768
837
  try {
769
838
  element.appendChild(value);
770
839
  } catch (e) {
771
- element.setAttribute(
772
- ATTRIBUTE_ERRORMESSAGE,
773
- `${element.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
774
- e.message
775
- }`.trim(),
776
- );
840
+ addErrorAttribute(element, e);
777
841
  }
778
842
  } else {
779
843
  element.innerHTML = value;
@@ -854,7 +918,7 @@ function runUpdateAttributes(container, parts, subject) {
854
918
  element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
855
919
  value = pipe.run(subject);
856
920
  } catch (e) {
857
- element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
921
+ addErrorAttribute(element, e);
858
922
  }
859
923
 
860
924
  if (value === undefined) {
@@ -879,7 +943,6 @@ function runUpdateAttributes(container, parts, subject) {
879
943
  */
880
944
 
881
945
  function handleInputControlAttributeUpdate(element, name, value) {
882
-
883
946
  if (element instanceof HTMLSelectElement) {
884
947
  switch (element.type) {
885
948
  case "select-multiple":
@@ -920,7 +983,6 @@ function handleInputControlAttributeUpdate(element, name, value) {
920
983
  element.value = value === undefined ? "" : value;
921
984
  }
922
985
  break;
923
-
924
986
  }
925
987
  } else if (element instanceof HTMLTextAreaElement) {
926
988
  if (name === "value") {
@@ -979,18 +1041,13 @@ function addObjectWithUpdaterToElement(elements, symbol, object, config = {}) {
979
1041
  if (typeof callback === "function") {
980
1042
  updaterCallbacks.push([name, callback]);
981
1043
  } else {
982
- addAttributeToken(
983
- this,
984
- ATTRIBUTE_ERRORMESSAGE,
985
- `onUpdaterPipeCallbacks: ${name} is not a function`,
986
- );
1044
+ addErrorAttribute(this, `onUpdaterPipeCallbacks: ${name} is not a function`);
987
1045
  }
988
1046
  }
989
1047
  } else {
990
- addAttributeToken(
1048
+ addErrorAttribute(
991
1049
  this,
992
- ATTRIBUTE_ERRORMESSAGE,
993
- `onUpdaterPipeCallbacks do not return an object with functions`,
1050
+ `onUpdaterPipeCallbacks do not return an object with functions`
994
1051
  );
995
1052
  }
996
1053
  }
@@ -156,7 +156,7 @@ function getMonsterVersion() {
156
156
  }
157
157
 
158
158
  /** don't touch, replaced by make with package.json version */
159
- monsterVersion = new Version("3.102.3");
159
+ monsterVersion = new Version("3.102.6");
160
160
 
161
161
  return monsterVersion;
162
162
  }
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version("3.102.3")
10
+ monsterVersion = new Version("3.102.6")
11
11
 
12
12
  let m = getMonsterVersion();
13
13
 
@@ -9,8 +9,8 @@
9
9
  </head>
10
10
  <body>
11
11
  <div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
12
- <h1 style='margin-bottom: 0.1em;'>Monster 3.102.3</h1>
13
- <div id="lastupdate" style='font-size:0.7em'>last update Mi 29. Jan 14:48:17 CET 2025</div>
12
+ <h1 style='margin-bottom: 0.1em;'>Monster 3.102.6</h1>
13
+ <div id="lastupdate" style='font-size:0.7em'>last update So 2. Feb 23:18:18 CET 2025</div>
14
14
  </div>
15
15
  <div id="mocha-errors"
16
16
  style="color: red;font-weight: bold;display: flex;align-items: center;justify-content: center;flex-direction: column;margin:20px;"></div>