@schukai/monster 1.26.1 → 1.29.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 (198) hide show
  1. package/CHANGELOG +38 -1
  2. package/README.md +4 -4
  3. package/dist/modules/constants.js +1 -1
  4. package/dist/modules/constraints/abstract.js +1 -1
  5. package/dist/modules/constraints/abstractoperator.js +1 -1
  6. package/dist/modules/constraints/andoperator.js +1 -1
  7. package/dist/modules/constraints/invalid.js +1 -1
  8. package/dist/modules/constraints/isarray.js +1 -1
  9. package/dist/modules/constraints/isobject.js +1 -1
  10. package/dist/modules/constraints/namespace.js +1 -1
  11. package/dist/modules/constraints/oroperator.js +1 -1
  12. package/dist/modules/constraints/valid.js +1 -1
  13. package/dist/modules/data/buildmap.js +2 -2
  14. package/dist/modules/data/buildtree.js +2 -2
  15. package/dist/modules/data/datasource/namespace.js +1 -1
  16. package/dist/modules/data/datasource/restapi/writeerror.js +1 -1
  17. package/dist/modules/data/datasource/restapi.js +1 -1
  18. package/dist/modules/data/datasource/storage/localstorage.js +1 -1
  19. package/dist/modules/data/datasource/storage/namespace.js +1 -1
  20. package/dist/modules/data/datasource/storage/sessionstorage.js +1 -1
  21. package/dist/modules/data/datasource/storage.js +1 -1
  22. package/dist/modules/data/datasource.js +1 -1
  23. package/dist/modules/data/diff.js +1 -1
  24. package/dist/modules/data/extend.js +1 -1
  25. package/dist/modules/data/namespace.js +1 -1
  26. package/dist/modules/data/pathfinder.js +1 -1
  27. package/dist/modules/data/pipe.js +1 -1
  28. package/dist/modules/data/transformer.js +1 -1
  29. package/dist/modules/dom/assembler.js +1 -1
  30. package/dist/modules/dom/attributes.js +2 -2
  31. package/dist/modules/dom/constants.js +2 -2
  32. package/dist/modules/dom/customcontrol.js +1 -1
  33. package/dist/modules/dom/customelement.js +2 -2
  34. package/dist/modules/dom/events.js +2 -2
  35. package/dist/modules/dom/focusmanager.js +1 -1
  36. package/dist/modules/dom/locale.js +1 -1
  37. package/dist/modules/dom/namespace.js +1 -1
  38. package/dist/modules/dom/resource/data.js +1 -1
  39. package/dist/modules/dom/resource/link/stylesheet.js +1 -1
  40. package/dist/modules/dom/resource/link.js +1 -1
  41. package/dist/modules/dom/resource/script.js +1 -1
  42. package/dist/modules/dom/resource.js +1 -1
  43. package/dist/modules/dom/resourcemanager.js +1 -1
  44. package/dist/modules/dom/template.js +2 -2
  45. package/dist/modules/dom/theme.js +1 -1
  46. package/dist/modules/dom/updater.js +2 -2
  47. package/dist/modules/dom/util.js +1 -1
  48. package/dist/modules/dom/worker/factory.js +1 -1
  49. package/dist/modules/i18n/formatter.js +1 -1
  50. package/dist/modules/i18n/locale.js +1 -1
  51. package/dist/modules/i18n/namespace.js +1 -1
  52. package/dist/modules/i18n/provider.js +1 -1
  53. package/dist/modules/i18n/providers/fetch.js +1 -1
  54. package/dist/modules/i18n/providers/namespace.js +1 -1
  55. package/dist/modules/i18n/translations.js +1 -1
  56. package/dist/modules/logging/handler/console.js +1 -1
  57. package/dist/modules/logging/handler/namespace.js +1 -1
  58. package/dist/modules/logging/handler.js +1 -1
  59. package/dist/modules/logging/logentry.js +1 -1
  60. package/dist/modules/logging/logger.js +1 -1
  61. package/dist/modules/logging/namespace.js +1 -1
  62. package/dist/modules/math/namespace.js +1 -1
  63. package/dist/modules/math/random.js +1 -1
  64. package/dist/modules/monster.js +1 -1
  65. package/dist/modules/namespace.js +1 -1
  66. package/dist/modules/text/formatter.js +1 -1
  67. package/dist/modules/text/namespace.js +1 -1
  68. package/dist/modules/types/base.js +1 -1
  69. package/dist/modules/types/basewithoptions.js +1 -1
  70. package/dist/modules/types/binary.js +1 -1
  71. package/dist/modules/types/dataurl.js +1 -1
  72. package/dist/modules/types/global.js +1 -1
  73. package/dist/modules/types/id.js +1 -1
  74. package/dist/modules/types/is.js +1 -1
  75. package/dist/modules/types/mediatype.js +1 -1
  76. package/dist/modules/types/namespace.js +1 -1
  77. package/dist/modules/types/node.js +2 -2
  78. package/dist/modules/types/nodelist.js +2 -2
  79. package/dist/modules/types/noderecursiveiterator.js +2 -2
  80. package/dist/modules/types/observer.js +1 -1
  81. package/dist/modules/types/observerlist.js +1 -1
  82. package/dist/modules/types/proxyobserver.js +1 -1
  83. package/dist/modules/types/queue.js +1 -1
  84. package/dist/modules/types/randomid.js +1 -1
  85. package/dist/modules/types/regex.js +1 -1
  86. package/dist/modules/types/stack.js +1 -1
  87. package/dist/modules/types/tokenlist.js +1 -1
  88. package/dist/modules/types/typeof.js +1 -1
  89. package/dist/modules/types/uniquequeue.js +1 -1
  90. package/dist/modules/types/uuid.js +1 -1
  91. package/dist/modules/types/validate.js +1 -1
  92. package/dist/modules/types/version.js +2 -2
  93. package/dist/modules/util/clone.js +1 -1
  94. package/dist/modules/util/comparator.js +1 -1
  95. package/dist/modules/util/deadmansswitch.js +2 -0
  96. package/dist/modules/util/freeze.js +1 -1
  97. package/dist/modules/util/namespace.js +1 -1
  98. package/dist/modules/util/processing.js +1 -1
  99. package/dist/modules/util/trimspaces.js +1 -1
  100. package/dist/monster.dev.js +906 -619
  101. package/dist/monster.dev.js.map +1 -1
  102. package/dist/monster.js +2 -2
  103. package/package.json +1 -1
  104. package/source/constraints/andoperator.js +5 -5
  105. package/source/constraints/invalid.js +3 -3
  106. package/source/constraints/isarray.js +3 -3
  107. package/source/constraints/isobject.js +3 -3
  108. package/source/constraints/oroperator.js +5 -5
  109. package/source/constraints/valid.js +3 -3
  110. package/source/data/buildmap.js +10 -11
  111. package/source/data/buildtree.js +51 -17
  112. package/source/data/datasource/restapi.js +3 -3
  113. package/source/data/datasource/storage/localstorage.js +2 -2
  114. package/source/data/datasource/storage/sessionstorage.js +2 -2
  115. package/source/data/datasource/storage.js +3 -3
  116. package/source/data/datasource.js +3 -3
  117. package/source/data/diff.js +3 -3
  118. package/source/data/extend.js +2 -2
  119. package/source/data/pathfinder.js +4 -4
  120. package/source/data/pipe.js +3 -3
  121. package/source/data/transformer.js +3 -3
  122. package/source/dom/assembler.js +2 -2
  123. package/source/dom/attributes.js +111 -28
  124. package/source/dom/constants.js +17 -1
  125. package/source/dom/customcontrol.js +1 -1
  126. package/source/dom/customelement.js +27 -13
  127. package/source/dom/events.js +68 -12
  128. package/source/dom/focusmanager.js +2 -2
  129. package/source/dom/locale.js +2 -2
  130. package/source/dom/resource/data.js +2 -2
  131. package/source/dom/resource/link/stylesheet.js +2 -2
  132. package/source/dom/resource/link.js +2 -2
  133. package/source/dom/resource/script.js +2 -2
  134. package/source/dom/resource.js +2 -2
  135. package/source/dom/resourcemanager.js +2 -2
  136. package/source/dom/template.js +41 -11
  137. package/source/dom/theme.js +3 -3
  138. package/source/dom/updater.js +183 -100
  139. package/source/dom/util.js +6 -6
  140. package/source/dom/worker/factory.js +2 -2
  141. package/source/i18n/formatter.js +4 -4
  142. package/source/i18n/locale.js +4 -4
  143. package/source/i18n/provider.js +2 -2
  144. package/source/i18n/providers/fetch.js +3 -3
  145. package/source/i18n/translations.js +4 -4
  146. package/source/logging/handler/console.js +2 -2
  147. package/source/logging/handler.js +2 -2
  148. package/source/logging/logentry.js +2 -2
  149. package/source/logging/logger.js +2 -2
  150. package/source/math/random.js +2 -2
  151. package/source/namespace.js +1 -1
  152. package/source/text/formatter.js +3 -3
  153. package/source/types/base.js +2 -2
  154. package/source/types/basewithoptions.js +2 -2
  155. package/source/types/binary.js +4 -4
  156. package/source/types/dataurl.js +4 -4
  157. package/source/types/global.js +4 -4
  158. package/source/types/id.js +2 -2
  159. package/source/types/is.js +20 -20
  160. package/source/types/mediatype.js +4 -4
  161. package/source/types/node.js +33 -2
  162. package/source/types/nodelist.js +9 -5
  163. package/source/types/noderecursiveiterator.js +29 -7
  164. package/source/types/observer.js +5 -13
  165. package/source/types/observerlist.js +2 -2
  166. package/source/types/proxyobserver.js +5 -5
  167. package/source/types/queue.js +3 -3
  168. package/source/types/randomid.js +2 -2
  169. package/source/types/regex.js +2 -2
  170. package/source/types/stack.js +2 -2
  171. package/source/types/tokenlist.js +2 -2
  172. package/source/types/typeof.js +3 -3
  173. package/source/types/uniquequeue.js +2 -2
  174. package/source/types/uuid.js +2 -2
  175. package/source/types/validate.js +20 -20
  176. package/source/types/version.js +6 -6
  177. package/source/util/clone.js +2 -2
  178. package/source/util/comparator.js +3 -3
  179. package/source/util/deadmansswitch.js +124 -0
  180. package/source/util/freeze.js +2 -2
  181. package/source/util/processing.js +3 -3
  182. package/source/util/trimspaces.js +2 -2
  183. package/test/cases/data/buildtree.js +84 -21
  184. package/test/cases/dom/attributes.js +29 -6
  185. package/test/cases/dom/events.js +66 -1
  186. package/test/cases/dom/template.js +72 -14
  187. package/test/cases/dom/updater.js +102 -75
  188. package/test/cases/math/random.js +3 -0
  189. package/test/cases/monster.js +1 -1
  190. package/test/cases/types/node.js +57 -1
  191. package/test/cases/types/nodelist.js +7 -0
  192. package/test/cases/types/noderecursiveiterator.js +21 -0
  193. package/test/cases/util/deadmansswitch.js +71 -0
  194. package/test/web/import.js +1 -0
  195. package/test/web/monster-dev.html +3 -3
  196. package/test/web/monster.html +2 -2
  197. package/test/web/test.html +3 -3
  198. package/test/web/tests.js +2 -2
@@ -4,6 +4,7 @@
4
4
  * @author schukai GmbH
5
5
  */
6
6
 
7
+ import {internalSymbol} from "../constants.js";
7
8
  import {diff} from "../data/diff.js";
8
9
  import {Pathfinder} from "../data/pathfinder.js";
9
10
  import {Pipe} from "../data/pipe.js";
@@ -14,7 +15,8 @@ import {
14
15
  ATTRIBUTE_UPDATER_INSERT,
15
16
  ATTRIBUTE_UPDATER_INSERT_REFERENCE,
16
17
  ATTRIBUTE_UPDATER_REMOVE,
17
- ATTRIBUTE_UPDATER_REPLACE
18
+ ATTRIBUTE_UPDATER_REPLACE,
19
+ ATTRIBUTE_UPDATER_SELECT_THIS
18
20
  } from "../dom/constants.js";
19
21
  import {assignToNamespace, Monster} from '../namespace.js';
20
22
  import {Base} from "../types/base.js";
@@ -24,6 +26,7 @@ import {ProxyObserver} from "../types/proxyobserver.js";
24
26
  import {validateArray, validateInstance} from "../types/validate.js";
25
27
  import {clone} from "../util/clone.js";
26
28
  import {trimSpaces} from "../util/trimspaces.js";
29
+ import {findTargetElementFromEvent} from "./events.js";
27
30
  import {findDocumentTemplate} from "./template.js";
28
31
  import {getDocument} from "./util.js";
29
32
 
@@ -34,11 +37,14 @@ import {getDocument} from "./util.js";
34
37
  * For example, to include a string from an object, the attribute `data-monster-replace` can be used.
35
38
  * a further explanation can be found under {@tutorial dom-based-templating-implementation}.
36
39
  *
40
+ * Changes to attributes are made only when the direct values are changed. If you want to assign changes to other values
41
+ * as well, you have to insert the attribute `data-monster-select-this`. This should be done with care, as it can reduce performance.
42
+ *
37
43
  * You can create an object of this class using the monster namespace `new Monster.DOM.Updater()`.
38
44
  *
39
45
  * ```
40
46
  * <script type="module">
41
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/monster.js';
47
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/monster.js';
42
48
  * new Monster.DOM.Updater()
43
49
  * </script>
44
50
  * ```
@@ -47,14 +53,14 @@ import {getDocument} from "./util.js";
47
53
  *
48
54
  * ```
49
55
  * <script type="module">
50
- * import {Updater} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/dom/updater.js';
56
+ * import {Updater} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/dom/updater.js';
51
57
  * new Updater()
52
58
  * </script>
53
59
  * ```
54
60
  *
55
61
  * @example
56
62
  *
57
- * import {Updater} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/dom/updater.js';
63
+ * import {Updater} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/dom/updater.js';
58
64
  *
59
65
  * // First we prepare the html document.
60
66
  * // This is done here via script, but can also be inserted into the document as pure html.
@@ -68,7 +74,7 @@ import {getDocument} from "./util.js";
68
74
  * let obj = {
69
75
  * headline: "Hello World",
70
76
  * };
71
- *
77
+ *
72
78
  * // Now comes the real magic. we pass the updater the parent HTMLElement
73
79
  * // and the desired data structure.
74
80
  * const updater = new Updater(body, obj);
@@ -105,27 +111,27 @@ class Updater extends Base {
105
111
  /**
106
112
  * @type {HTMLElement}
107
113
  */
108
- this.element = validateInstance(element, HTMLElement);
109
-
110
114
  if (subject === undefined) subject = {}
111
- let a = subject;
112
115
  if (!isInstance(subject, ProxyObserver)) {
113
116
  subject = new ProxyObserver(subject);
114
117
  }
115
118
 
116
- this.last = {};
117
- this.callbacks = new Map();
118
- this.callbacks.set('checkstate', getCheckStateCallback.call(this));
119
+ this[internalSymbol] = {
120
+ element: validateInstance(element, HTMLElement),
121
+ last: {},
122
+ callbacks: new Map(),
123
+ eventTypes: ['keyup', 'click', 'change', 'drop', 'touchend', 'input'],
124
+ subject: subject
125
+ }
119
126
 
120
- /**
121
- * @type {object}
122
- */
123
- this.subject = subject.attachObserver(new Observer(() => {
127
+ this[internalSymbol].callbacks.set('checkstate', getCheckStateCallback.call(this));
128
+
129
+ this[internalSymbol].subject.attachObserver(new Observer(() => {
124
130
 
125
- const s = this.subject.getRealSubject();
131
+ const s = this[internalSymbol].subject.getRealSubject();
126
132
 
127
- const diffResult = diff(this.last, s)
128
- this.last = clone(s);
133
+ const diffResult = diff(this[internalSymbol].last, s)
134
+ this[internalSymbol].last = clone(s);
129
135
 
130
136
  for (const [, change] of Object.entries(diffResult)) {
131
137
  removeElement.call(this, change);
@@ -135,8 +141,6 @@ class Updater extends Base {
135
141
  }
136
142
  }));
137
143
 
138
- this.eventTypes = ['keyup', 'click', 'change', 'drop', 'touchend', 'input'];
139
-
140
144
  }
141
145
 
142
146
  /**
@@ -148,7 +152,7 @@ class Updater extends Base {
148
152
  * @return {Updater}
149
153
  */
150
154
  setEventTypes(types) {
151
- this.eventTypes = validateArray(types);
155
+ this[internalSymbol].eventTypes = validateArray(types);
152
156
  return this;
153
157
  }
154
158
 
@@ -163,12 +167,17 @@ class Updater extends Base {
163
167
  *
164
168
  * @since 1.9.0
165
169
  * @return {Updater}
170
+ * @throws {Error} the bind argument must start as a value with a path
166
171
  */
167
172
  enableEventProcessing() {
168
173
  this.disableEventProcessing();
169
174
 
170
- for (const type of this.eventTypes) {
171
- this.element.addEventListener(type, getControlEventHandler.call(this));
175
+ for (const type of this[internalSymbol].eventTypes) {
176
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
177
+ this[internalSymbol].element.addEventListener(type, getControlEventHandler.call(this), {
178
+ capture: true,
179
+ passive: true
180
+ });
172
181
  }
173
182
 
174
183
  return this;
@@ -183,8 +192,8 @@ class Updater extends Base {
183
192
  */
184
193
  disableEventProcessing() {
185
194
 
186
- for (const type of this.eventTypes) {
187
- this.element.removeEventListener(type, getControlEventHandler.call(this));
195
+ for (const type of this[internalSymbol].eventTypes) {
196
+ this[internalSymbol].element.removeEventListener(type, getControlEventHandler.call(this));
188
197
  }
189
198
 
190
199
  return this;
@@ -207,8 +216,19 @@ class Updater extends Base {
207
216
  run() {
208
217
  // the key __init__has no further meaning and is only
209
218
  // used to create the diff for empty objects.
210
- this.last = {'__init__': true};
211
- return this.subject.notifyObservers();
219
+ this[internalSymbol].last = {'__init__': true};
220
+ return this[internalSymbol].subject.notifyObservers();
221
+ }
222
+
223
+ /**
224
+ * Gets the values of bound elements and changes them in subject
225
+ *
226
+ * @since 1.27.0
227
+ * @return {Monster.DOM.Updater}
228
+ */
229
+ retrieve() {
230
+ retrieveFromBindings.call(this);
231
+ return this;
212
232
  }
213
233
 
214
234
  /**
@@ -221,7 +241,7 @@ class Updater extends Base {
221
241
  * @return {Proxy}
222
242
  */
223
243
  getSubject() {
224
- return this.subject.getSubject();
244
+ return this[internalSymbol].subject.getSubject();
225
245
  }
226
246
 
227
247
  /**
@@ -235,7 +255,7 @@ class Updater extends Base {
235
255
  * @throws {TypeError} value is not a function
236
256
  */
237
257
  setCallback(name, callback) {
238
- this.callbacks.set(name, callback);
258
+ this[internalSymbol].callbacks.set(name, callback);
239
259
  return this;
240
260
  }
241
261
 
@@ -252,6 +272,7 @@ function getCheckStateCallback() {
252
272
 
253
273
  return function (current) {
254
274
 
275
+ // this is a reference to the current object (therefore no array function here)
255
276
  if (this instanceof HTMLInputElement) {
256
277
  if (['radio', 'checkbox'].indexOf(this.type) !== -1) {
257
278
  return (this.value + "" === current + "") ? 'true' : undefined
@@ -261,9 +282,8 @@ function getCheckStateCallback() {
261
282
  if (isArray(current) && current.indexOf(this.value) !== -1) {
262
283
  return 'true'
263
284
  }
264
- return undefined;
265
-
266
285
 
286
+ return undefined;
267
287
  }
268
288
  }
269
289
  }
@@ -277,6 +297,7 @@ const symbol = Symbol('EventHandler');
277
297
  * @private
278
298
  * @return {function}
279
299
  * @this Updater
300
+ * @throws {Error} the bind argument must start as a value with a path
280
301
  */
281
302
  function getControlEventHandler() {
282
303
 
@@ -286,83 +307,115 @@ function getControlEventHandler() {
286
307
  return self[symbol];
287
308
  }
288
309
 
289
- const pathfinder = new Pathfinder(this.subject.getSubject());
290
-
291
310
  /**
292
311
  * @throws {Error} the bind argument must start as a value with a path.
293
312
  * @throws {Error} unsupported object
294
313
  * @param {Event} event
295
314
  */
296
315
  self[symbol] = (event) => {
297
- const element = event.target;
316
+ const element = findTargetElementFromEvent(event, ATTRIBUTE_UPDATER_BIND);
298
317
 
299
- if (!element.hasAttribute(ATTRIBUTE_UPDATER_BIND)) {
318
+ if (element === undefined) {
300
319
  return;
301
320
  }
302
321
 
303
- let path = element.getAttribute(ATTRIBUTE_UPDATER_BIND);
322
+ retrieveAndSetValue.call(self, element);
304
323
 
305
- if (path.indexOf('path:') !== 0) {
306
- throw new Error('the bind argument must start as a value with a path.');
307
- }
324
+ }
308
325
 
309
- path = path.substr(5);
326
+ return self[symbol];
310
327
 
311
- let value;
312
328
 
313
- if (element instanceof HTMLInputElement) {
314
- switch (element.type) {
329
+ }
330
+
331
+ /**
332
+ * @throws {Error} the bind argument must start as a value with a path
333
+ * @param {HTMLElement} element
334
+ * @return void
335
+ * @memberOf Monster.DOM
336
+ * @private
337
+ */
338
+ function retrieveAndSetValue(element) {
339
+
340
+ const self = this;
315
341
 
316
- case 'checkbox':
317
- value = element.checked ? element.value : undefined;
318
- break;
319
- default:
320
- value = element.value;
321
- break;
342
+ const pathfinder = new Pathfinder(self[internalSymbol].subject.getSubject());
322
343
 
344
+ let path = element.getAttribute(ATTRIBUTE_UPDATER_BIND);
323
345
 
324
- }
325
- } else if (element instanceof HTMLTextAreaElement) {
326
- value = element.value;
346
+ if (path.indexOf('path:') !== 0) {
347
+ throw new Error('the bind argument must start as a value with a path');
348
+ }
327
349
 
328
- } else if (element instanceof HTMLSelectElement) {
350
+ path = path.substr(5);
329
351
 
330
- switch (element.type) {
331
- case 'select-one':
332
- value = element.value;
333
- break;
334
- case 'select-multiple':
335
- value = element.value;
352
+ let value;
336
353
 
337
- let options = element?.selectedOptions;
338
- if (options === undefined) options = element.querySelectorAll(":scope option:checked");
339
- value = Array.from(options).map(({value}) => value);
354
+ if (element instanceof HTMLInputElement) {
355
+ switch (element.type) {
340
356
 
341
- break;
342
- }
357
+ case 'checkbox':
358
+ value = element.checked ? element.value : undefined;
359
+ break;
360
+ default:
361
+ value = element.value;
362
+ break;
343
363
 
344
364
 
345
- // values from customelements
346
- } else if ((element?.constructor?.prototype && !!Object.getOwnPropertyDescriptor(element.constructor.prototype, 'value')?.['get']) || element.hasOwnProperty('value')) {
347
- value = element?.['value'];
348
- } else {
349
- throw new Error("unsupported object");
350
365
  }
366
+ } else if (element instanceof HTMLTextAreaElement) {
367
+ value = element.value;
351
368
 
352
- const copy = clone(self.subject.getRealSubject());
353
- const pf = new Pathfinder(copy);
354
- pf.setVia(path, value);
369
+ } else if (element instanceof HTMLSelectElement) {
355
370
 
356
- const diffResult = diff(copy, self.subject.getRealSubject());
371
+ switch (element.type) {
372
+ case 'select-one':
373
+ value = element.value;
374
+ break;
375
+ case 'select-multiple':
376
+ value = element.value;
377
+
378
+ let options = element?.selectedOptions;
379
+ if (options === undefined) options = element.querySelectorAll(":scope option:checked");
380
+ value = Array.from(options).map(({value}) => value);
357
381
 
358
- if (diffResult.length > 0) {
359
- pathfinder.setVia(path, value);
382
+ break;
360
383
  }
361
384
 
385
+
386
+ // values from customelements
387
+ } else if ((element?.constructor?.prototype && !!Object.getOwnPropertyDescriptor(element.constructor.prototype, 'value')?.['get']) || element.hasOwnProperty('value')) {
388
+ value = element?.['value'];
389
+ } else {
390
+ throw new Error("unsupported object");
362
391
  }
363
392
 
364
- return self[symbol];
393
+ const copy = clone(self[internalSymbol].subject.getRealSubject());
394
+ const pf = new Pathfinder(copy);
395
+ pf.setVia(path, value);
396
+
397
+ const diffResult = diff(copy, self[internalSymbol].subject.getRealSubject());
398
+
399
+ if (diffResult.length > 0) {
400
+ pathfinder.setVia(path, value);
401
+ }
402
+ }
403
+
404
+ /**
405
+ * @since 1.27.0
406
+ * @return void
407
+ * @private
408
+ */
409
+ function retrieveFromBindings() {
410
+ const self = this;
365
411
 
412
+ if (self[internalSymbol].element.matches('[' + ATTRIBUTE_UPDATER_BIND + ']')) {
413
+ retrieveAndSetValue.call(self, element)
414
+ }
415
+
416
+ for (const [, element] of self[internalSymbol].element.querySelectorAll('[' + ATTRIBUTE_UPDATER_BIND + ']').entries()) {
417
+ retrieveAndSetValue.call(self, element)
418
+ }
366
419
 
367
420
  }
368
421
 
@@ -373,7 +426,9 @@ function getControlEventHandler() {
373
426
  * @return {void}
374
427
  */
375
428
  function removeElement(change) {
376
- for (const [, element] of this.element.querySelectorAll(':scope [' + ATTRIBUTE_UPDATER_REMOVE + ']').entries()) {
429
+ const self = this;
430
+
431
+ for (const [, element] of self[internalSymbol].element.querySelectorAll(':scope [' + ATTRIBUTE_UPDATER_REMOVE + ']').entries()) {
377
432
  element.parentNode.removeChild(element);
378
433
  }
379
434
  }
@@ -391,25 +446,40 @@ function removeElement(change) {
391
446
  */
392
447
  function insertElement(change) {
393
448
  const self = this;
394
- const subject = self.subject.getRealSubject();
449
+ const subject = self[internalSymbol].subject.getRealSubject();
395
450
  const document = getDocument();
396
451
 
397
452
  let mem = new WeakSet;
398
453
  let wd = 0;
399
-
454
+
455
+ const container = self[internalSymbol].element;
400
456
 
401
457
  while (true) {
402
458
  let found = false;
403
459
  wd++;
404
460
 
405
461
  let p = clone(change?.['path']);
406
- if (!isArray(p)) return this;
462
+ if (!isArray(p)) return self;
407
463
 
408
464
  while (p.length > 0) {
409
465
  const current = p.join('.');
410
- const list = this.element.querySelectorAll(':scope [' + ATTRIBUTE_UPDATER_INSERT + '*="path:' + current + '"]').entries()
411
466
 
412
- for (const [, containerElement] of list) {
467
+ let iterator = new Set;
468
+ const query = '[' + ATTRIBUTE_UPDATER_INSERT + '*="path:' + current + '"]';
469
+
470
+ const e = container.querySelectorAll(query);
471
+
472
+ if (e.length > 0) {
473
+ iterator = new Set(
474
+ [...e]
475
+ )
476
+ }
477
+
478
+ if (container.matches(query)) {
479
+ iterator.add(container);
480
+ }
481
+
482
+ for (const [, containerElement] of iterator.entries()) {
413
483
 
414
484
  if (mem.has(containerElement)) continue;
415
485
  mem.add(containerElement)
@@ -429,7 +499,7 @@ function insertElement(change) {
429
499
  }
430
500
 
431
501
  let pipe = new Pipe(cmd);
432
- this.callbacks.forEach((f, n) => {
502
+ self[internalSymbol].callbacks.forEach((f, n) => {
433
503
  pipe.setCallback(n, f);
434
504
  })
435
505
 
@@ -472,7 +542,12 @@ function insertElement(change) {
472
542
  let nodes = containerElement.querySelectorAll('[' + ATTRIBUTE_UPDATER_INSERT_REFERENCE + '*="' + refPrefix + '"]');
473
543
  for (const [, node] of Object.entries(nodes)) {
474
544
  if (!available.has(node.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE))) {
475
- containerElement.removeChild(node);
545
+ try {
546
+ containerElement.removeChild(node);
547
+ } catch(e) {
548
+
549
+ }
550
+
476
551
  }
477
552
  }
478
553
  }
@@ -553,12 +628,12 @@ function applyRecursive(node, key, path) {
553
628
  */
554
629
  function updateContent(change) {
555
630
  const self = this;
556
- const subject = self.subject.getRealSubject();
631
+ const subject = self[internalSymbol].subject.getRealSubject();
557
632
 
558
633
  let p = clone(change?.['path']);
559
- runUpdateContent.call(this, this.element, p, subject);
634
+ runUpdateContent.call(this, this[internalSymbol].element, p, subject);
560
635
 
561
- const slots = this.element.querySelectorAll('slot');
636
+ const slots = this[internalSymbol].element.querySelectorAll('slot');
562
637
  if (slots.length > 0) {
563
638
  for (const [, slot] of Object.entries(slots)) {
564
639
  for (const [, element] of Object.entries(slot.assignedNodes())) {
@@ -610,7 +685,7 @@ function runUpdateContent(container, parts, subject) {
610
685
  let cmd = trimSpaces(attributes);
611
686
 
612
687
  let pipe = new Pipe(cmd);
613
- this.callbacks.forEach((f, n) => {
688
+ this[internalSymbol].callbacks.forEach((f, n) => {
614
689
  pipe.setCallback(n, f);
615
690
  })
616
691
 
@@ -646,9 +721,9 @@ function runUpdateContent(container, parts, subject) {
646
721
  * @return {void}
647
722
  */
648
723
  function updateAttributes(change) {
649
- const subject = this.subject.getRealSubject();
724
+ const subject = this[internalSymbol].subject.getRealSubject();
650
725
  let p = clone(change?.['path']);
651
- runUpdateAttributes.call(this, this.element, p, subject);
726
+ runUpdateAttributes.call(this, this[internalSymbol].element, p, subject);
652
727
  }
653
728
 
654
729
  /**
@@ -674,7 +749,8 @@ function runUpdateAttributes(container, parts, subject) {
674
749
 
675
750
  let iterator = new Set;
676
751
 
677
- const query = '[' + ATTRIBUTE_UPDATER_ATTRIBUTES + '*="path:' + current + '"], [' + ATTRIBUTE_UPDATER_ATTRIBUTES + '^="static:"]';
752
+ const query = '[' + ATTRIBUTE_UPDATER_SELECT_THIS + '], [' + ATTRIBUTE_UPDATER_ATTRIBUTES + '*="path:' + current + '"], [' + ATTRIBUTE_UPDATER_ATTRIBUTES + '^="static:"]';
753
+
678
754
  const e = container.querySelectorAll(query);
679
755
 
680
756
  if (e.length > 0) {
@@ -702,7 +778,7 @@ function runUpdateAttributes(container, parts, subject) {
702
778
 
703
779
  let pipe = new Pipe(cmd);
704
780
 
705
- self.callbacks.forEach((f, n) => {
781
+ self[internalSymbol].callbacks.forEach((f, n) => {
706
782
  pipe.setCallback(n, f, element);
707
783
  })
708
784
 
@@ -776,19 +852,26 @@ function handleInputControlAttributeUpdate(element, name, value) {
776
852
  switch (element.type) {
777
853
 
778
854
  case 'radio':
779
- if (name === 'checked' && value !== undefined) {
780
- element.checked = true;
781
- } else {
782
- element.checked = false;
855
+ if (name === 'checked') {
856
+
857
+ if (value !== undefined) {
858
+ element.checked = true;
859
+ } else {
860
+ element.checked = false;
861
+ }
783
862
  }
784
863
 
785
864
  break;
786
865
 
787
866
  case 'checkbox':
788
- if (name === 'checked' && value !== undefined) {
789
- element.checked = true;
790
- } else {
791
- element.checked = false;
867
+
868
+ if (name === 'checked') {
869
+
870
+ if (value !== undefined) {
871
+ element.checked = true;
872
+ } else {
873
+ element.checked = false;
874
+ }
792
875
  }
793
876
 
794
877
  break;
@@ -13,7 +13,7 @@ import {validateString} from "../types/validate.js";
13
13
  *
14
14
  * ```
15
15
  * <script type="module">
16
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/monster.js';
16
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/monster.js';
17
17
  * console.log(Monster.DOM.getDocument())
18
18
  * </script>
19
19
  * ```
@@ -22,7 +22,7 @@ import {validateString} from "../types/validate.js";
22
22
  *
23
23
  * ```
24
24
  * <script type="module">
25
- * import {getDocument} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/dom/util.js';
25
+ * import {getDocument} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/dom/util.js';
26
26
  * console.log(getDocument())
27
27
  * </script>
28
28
  * ```
@@ -74,7 +74,7 @@ function getDocument() {
74
74
  *
75
75
  * ```
76
76
  * <script type="module">
77
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/monster.js';
77
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/monster.js';
78
78
  * console.log(Monster.DOM.getWindow())
79
79
  * </script>
80
80
  * ```
@@ -83,7 +83,7 @@ function getDocument() {
83
83
  *
84
84
  * ```
85
85
  * <script type="module">
86
- * import {getWindow} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/dom/util.js';
86
+ * import {getWindow} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/dom/util.js';
87
87
  * console.log(getWindow(null))
88
88
  * </script>
89
89
  * ```
@@ -140,7 +140,7 @@ function getWindow() {
140
140
  *
141
141
  * ```
142
142
  * <script type="module">
143
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/monster.js';
143
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/monster.js';
144
144
  * console.log(Monster.DOM.getDocumentFragmentFromString())
145
145
  * </script>
146
146
  * ```
@@ -149,7 +149,7 @@ function getWindow() {
149
149
  *
150
150
  * ```
151
151
  * <script type="module">
152
- * import {getDocumentFragmentFromString} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/dom/util.js';
152
+ * import {getDocumentFragmentFromString} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/dom/util.js';
153
153
  * console.log(getDocumentFragmentFromString('<div></div>'))
154
154
  * </script>
155
155
  * ```
@@ -20,7 +20,7 @@ import {validateInstance, validateString} from "../../types/validate.js";
20
20
  *
21
21
  * ```
22
22
  * <script type="module">
23
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/monster.js';
23
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/monster.js';
24
24
  * console.log(new Monster.DOM.Worker.Factory())
25
25
  * </script>
26
26
  * ```
@@ -29,7 +29,7 @@ import {validateInstance, validateString} from "../../types/validate.js";
29
29
  *
30
30
  * ```
31
31
  * <script type="module">
32
- * import {Factory} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/dom/worker/factory.js';
32
+ * import {Factory} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/dom/worker/factory.js';
33
33
  * console.log(new Factory())
34
34
  * </script>
35
35
  * ```
@@ -25,7 +25,7 @@ const internalTranslationSymbol = Symbol('internalTranslation')
25
25
  *
26
26
  * ```
27
27
  * <script type="module">
28
- * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/monster.js';
28
+ * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/monster.js';
29
29
  * new Monster.I18n.Formatter()
30
30
  * </script>
31
31
  * ```
@@ -34,15 +34,15 @@ const internalTranslationSymbol = Symbol('internalTranslation')
34
34
  *
35
35
  * ```
36
36
  * <script type="module">
37
- * import {Formatter} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/i18n/formatter.js';
37
+ * import {Formatter} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/i18n/formatter.js';
38
38
  * new Formatter()
39
39
  * </script>
40
40
  * ```
41
41
  *
42
42
  * @example
43
43
  *
44
- * import {Formatter} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/i18n/formatter.js';
45
- * import {Translations} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.26.1/dist/modules/i18n/translations.js';
44
+ * import {Formatter} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/i18n/formatter.js';
45
+ * import {Translations} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.29.0/dist/modules/i18n/translations.js';
46
46
  *
47
47
  * const translations = new Translations('en')
48
48
  * .assignTranslations({