@schukai/monster 3.92.2 → 3.93.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.
@@ -12,36 +12,36 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import { internalSymbol } from "../constants.mjs";
16
- import { diff } from "../data/diff.mjs";
17
- import { Pathfinder } from "../data/pathfinder.mjs";
18
- import { Pipe } from "../data/pipe.mjs";
15
+ import {internalSymbol} from "../constants.mjs";
16
+ import {diff} from "../data/diff.mjs";
17
+ import {Pathfinder} from "../data/pathfinder.mjs";
18
+ import {Pipe} from "../data/pipe.mjs";
19
19
  import {
20
- ATTRIBUTE_ERRORMESSAGE,
21
- ATTRIBUTE_UPDATER_ATTRIBUTES,
22
- ATTRIBUTE_UPDATER_BIND,
23
- ATTRIBUTE_UPDATER_BIND_TYPE,
24
- ATTRIBUTE_UPDATER_INSERT,
25
- ATTRIBUTE_UPDATER_INSERT_REFERENCE,
26
- ATTRIBUTE_UPDATER_REMOVE,
27
- ATTRIBUTE_UPDATER_REPLACE,
28
- ATTRIBUTE_UPDATER_SELECT_THIS,
20
+ ATTRIBUTE_ERRORMESSAGE,
21
+ ATTRIBUTE_UPDATER_ATTRIBUTES,
22
+ ATTRIBUTE_UPDATER_BIND,
23
+ ATTRIBUTE_UPDATER_BIND_TYPE,
24
+ ATTRIBUTE_UPDATER_INSERT,
25
+ ATTRIBUTE_UPDATER_INSERT_REFERENCE,
26
+ ATTRIBUTE_UPDATER_REMOVE,
27
+ ATTRIBUTE_UPDATER_REPLACE,
28
+ ATTRIBUTE_UPDATER_SELECT_THIS,
29
29
  } from "./constants.mjs";
30
30
 
31
- import { Base } from "../types/base.mjs";
32
- import { isArray, isString, isInstance, isIterable } from "../types/is.mjs";
33
- import { Observer } from "../types/observer.mjs";
34
- import { ProxyObserver } from "../types/proxyobserver.mjs";
35
- import { validateArray, validateInstance } from "../types/validate.mjs";
36
- import { clone } from "../util/clone.mjs";
37
- import { trimSpaces } from "../util/trimspaces.mjs";
38
- import { addAttributeToken, addToObjectLink } from "./attributes.mjs";
39
- import { updaterTransformerMethodsSymbol } from "./customelement.mjs";
40
- import { findTargetElementFromEvent } from "./events.mjs";
41
- import { findDocumentTemplate } from "./template.mjs";
42
- import { getWindow } from "./util.mjs";
43
-
44
- export { Updater, addObjectWithUpdaterToElement };
31
+ import {Base} from "../types/base.mjs";
32
+ import {isArray, isString, isInstance, isIterable} from "../types/is.mjs";
33
+ import {Observer} from "../types/observer.mjs";
34
+ import {ProxyObserver} from "../types/proxyobserver.mjs";
35
+ import {validateArray, validateInstance} from "../types/validate.mjs";
36
+ import {clone} from "../util/clone.mjs";
37
+ import {trimSpaces} from "../util/trimspaces.mjs";
38
+ import {addAttributeToken, addToObjectLink} from "./attributes.mjs";
39
+ import {updaterTransformerMethodsSymbol} from "./customelement.mjs";
40
+ import {findTargetElementFromEvent} from "./events.mjs";
41
+ import {findDocumentTemplate} from "./template.mjs";
42
+ import {getWindow} from "./util.mjs";
43
+
44
+ export {Updater, addObjectWithUpdaterToElement};
45
45
 
46
46
  /**
47
47
  * The updater class connects an object with the DOM. In this way, structures and contents in the DOM can be
@@ -68,190 +68,190 @@ export { Updater, addObjectWithUpdaterToElement };
68
68
  * @summary The updater class connects an object with the dom
69
69
  */
70
70
  class Updater extends Base {
71
- /**
72
- * @since 1.8.0
73
- * @param {HTMLElement} element
74
- * @param {object|ProxyObserver|undefined} subject
75
- * @throws {TypeError} value is not a object
76
- * @throws {TypeError} value is not an instance of HTMLElement
77
- * @see {@link Monster.DOM.findDocumentTemplate}
78
- */
79
- constructor(element, subject) {
80
- super();
81
-
82
- /**
83
- * @type {HTMLElement}
84
- */
85
- if (subject === undefined) subject = {};
86
- if (!isInstance(subject, ProxyObserver)) {
87
- subject = new ProxyObserver(subject);
88
- }
89
-
90
- this[internalSymbol] = {
91
- element: validateInstance(element, HTMLElement),
92
- last: {},
93
- callbacks: new Map(),
94
- eventTypes: ["keyup", "click", "change", "drop", "touchend", "input"],
95
- subject: subject,
96
- };
97
-
98
- this[internalSymbol].callbacks.set(
99
- "checkstate",
100
- getCheckStateCallback.call(this),
101
- );
102
-
103
- this[internalSymbol].subject.attachObserver(
104
- new Observer(() => {
105
- const s = this[internalSymbol].subject.getRealSubject();
106
-
107
- const diffResult = diff(this[internalSymbol].last, s);
108
- this[internalSymbol].last = clone(s);
109
-
110
- const promises = [];
111
-
112
- for (const [, change] of Object.entries(diffResult)) {
113
- promises.push(
114
- new Promise((resolve, reject) => {
115
- getWindow().requestAnimationFrame(() => {
116
- try {
117
- removeElement.call(this, change);
118
- insertElement.call(this, change);
119
- updateContent.call(this, change);
120
- updateAttributes.call(this, change);
121
-
122
- resolve();
123
- } catch (error) {
124
- reject(error);
125
- }
126
- });
127
- }),
128
- );
129
- }
130
-
131
- return Promise.all(promises);
132
- }),
133
- );
134
- }
135
-
136
- /**
137
- * Defaults: 'keyup', 'click', 'change', 'drop', 'touchend'
138
- *
139
- * @see {@link https://developer.mozilla.org/de/docs/Web/Events}
140
- * @since 1.9.0
141
- * @param {Array} types
142
- * @return {Updater}
143
- */
144
- setEventTypes(types) {
145
- this[internalSymbol].eventTypes = validateArray(types);
146
- return this;
147
- }
148
-
149
- /**
150
- * With this method, the eventlisteners are hooked in and the magic begins.
151
- *
152
- * ```js
153
- * updater.run().then(() => {
154
- * updater.enableEventProcessing();
155
- * });
156
- * ```
157
- *
158
- * @since 1.9.0
159
- * @return {Updater}
160
- * @throws {Error} the bind argument must start as a value with a path
161
- */
162
- enableEventProcessing() {
163
- this.disableEventProcessing();
164
-
165
- for (const type of this[internalSymbol].eventTypes) {
166
- // @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
167
- this[internalSymbol].element.addEventListener(
168
- type,
169
- getControlEventHandler.call(this),
170
- {
171
- capture: true,
172
- passive: true,
173
- },
174
- );
175
- }
176
-
177
- return this;
178
- }
179
-
180
- /**
181
- * This method turns off the magic or who loves it more profane it removes the eventListener.
182
- *
183
- * @since 1.9.0
184
- * @return {Updater}
185
- */
186
- disableEventProcessing() {
187
- for (const type of this[internalSymbol].eventTypes) {
188
- this[internalSymbol].element.removeEventListener(
189
- type,
190
- getControlEventHandler.call(this),
191
- );
192
- }
193
-
194
- return this;
195
- }
196
-
197
- /**
198
- * The run method must be called for the update to start working.
199
- * The method ensures that changes are detected.
200
- *
201
- * ```js
202
- * updater.run().then(() => {
203
- * updater.enableEventProcessing();
204
- * });
205
- * ```
206
- *
207
- * @summary Let the magic begin
208
- * @return {Promise}
209
- */
210
- run() {
211
- // the key __init__has no further meaning and is only
212
- // used to create the diff for empty objects.
213
- this[internalSymbol].last = { __init__: true };
214
- return this[internalSymbol].subject.notifyObservers();
215
- }
216
-
217
- /**
218
- * Gets the values of bound elements and changes them in subject
219
- *
220
- * @since 1.27.0
221
- * @return {Monster.DOM.Updater}
222
- */
223
- retrieve() {
224
- retrieveFromBindings.call(this);
225
- return this;
226
- }
227
-
228
- /**
229
- * If you have passed a ProxyObserver in the constructor, you will get the object that the ProxyObserver manages here.
230
- * However, if you passed a simple object, here you will get a proxy for that object.
231
- *
232
- * For changes, the ProxyObserver must be used.
233
- *
234
- * @since 1.8.0
235
- * @return {Proxy}
236
- */
237
- getSubject() {
238
- return this[internalSymbol].subject.getSubject();
239
- }
240
-
241
- /**
242
- * This method can be used to register commands that can be called via call: instruction.
243
- * This can be used to provide a pipe with its own functionality.
244
- *
245
- * @param {string} name
246
- * @param {function} callback
247
- * @return {Transformer}
248
- * @throws {TypeError} value is not a string
249
- * @throws {TypeError} value is not a function
250
- */
251
- setCallback(name, callback) {
252
- this[internalSymbol].callbacks.set(name, callback);
253
- return this;
254
- }
71
+ /**
72
+ * @since 1.8.0
73
+ * @param {HTMLElement} element
74
+ * @param {object|ProxyObserver|undefined} subject
75
+ * @throws {TypeError} value is not a object
76
+ * @throws {TypeError} value is not an instance of HTMLElement
77
+ * @see {@link Monster.DOM.findDocumentTemplate}
78
+ */
79
+ constructor(element, subject) {
80
+ super();
81
+
82
+ /**
83
+ * @type {HTMLElement}
84
+ */
85
+ if (subject === undefined) subject = {};
86
+ if (!isInstance(subject, ProxyObserver)) {
87
+ subject = new ProxyObserver(subject);
88
+ }
89
+
90
+ this[internalSymbol] = {
91
+ element: validateInstance(element, HTMLElement),
92
+ last: {},
93
+ callbacks: new Map(),
94
+ eventTypes: ["keyup", "click", "change", "drop", "touchend", "input"],
95
+ subject: subject,
96
+ };
97
+
98
+ this[internalSymbol].callbacks.set(
99
+ "checkstate",
100
+ getCheckStateCallback.call(this),
101
+ );
102
+
103
+ this[internalSymbol].subject.attachObserver(
104
+ new Observer(() => {
105
+ const s = this[internalSymbol].subject.getRealSubject();
106
+
107
+ const diffResult = diff(this[internalSymbol].last, s);
108
+ this[internalSymbol].last = clone(s);
109
+
110
+ const promises = [];
111
+
112
+ for (const [, change] of Object.entries(diffResult)) {
113
+ promises.push(
114
+ new Promise((resolve, reject) => {
115
+ getWindow().requestAnimationFrame(() => {
116
+ try {
117
+ removeElement.call(this, change);
118
+ insertElement.call(this, change);
119
+ updateContent.call(this, change);
120
+ updateAttributes.call(this, change);
121
+
122
+ resolve();
123
+ } catch (error) {
124
+ reject(error);
125
+ }
126
+ });
127
+ }),
128
+ );
129
+ }
130
+
131
+ return Promise.all(promises);
132
+ }),
133
+ );
134
+ }
135
+
136
+ /**
137
+ * Defaults: 'keyup', 'click', 'change', 'drop', 'touchend'
138
+ *
139
+ * @see {@link https://developer.mozilla.org/de/docs/Web/Events}
140
+ * @since 1.9.0
141
+ * @param {Array} types
142
+ * @return {Updater}
143
+ */
144
+ setEventTypes(types) {
145
+ this[internalSymbol].eventTypes = validateArray(types);
146
+ return this;
147
+ }
148
+
149
+ /**
150
+ * With this method, the eventlisteners are hooked in and the magic begins.
151
+ *
152
+ * ```js
153
+ * updater.run().then(() => {
154
+ * updater.enableEventProcessing();
155
+ * });
156
+ * ```
157
+ *
158
+ * @since 1.9.0
159
+ * @return {Updater}
160
+ * @throws {Error} the bind argument must start as a value with a path
161
+ */
162
+ enableEventProcessing() {
163
+ this.disableEventProcessing();
164
+
165
+ for (const type of this[internalSymbol].eventTypes) {
166
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
167
+ this[internalSymbol].element.addEventListener(
168
+ type,
169
+ getControlEventHandler.call(this),
170
+ {
171
+ capture: true,
172
+ passive: true,
173
+ },
174
+ );
175
+ }
176
+
177
+ return this;
178
+ }
179
+
180
+ /**
181
+ * This method turns off the magic or who loves it more profane it removes the eventListener.
182
+ *
183
+ * @since 1.9.0
184
+ * @return {Updater}
185
+ */
186
+ disableEventProcessing() {
187
+ for (const type of this[internalSymbol].eventTypes) {
188
+ this[internalSymbol].element.removeEventListener(
189
+ type,
190
+ getControlEventHandler.call(this),
191
+ );
192
+ }
193
+
194
+ return this;
195
+ }
196
+
197
+ /**
198
+ * The run method must be called for the update to start working.
199
+ * The method ensures that changes are detected.
200
+ *
201
+ * ```js
202
+ * updater.run().then(() => {
203
+ * updater.enableEventProcessing();
204
+ * });
205
+ * ```
206
+ *
207
+ * @summary Let the magic begin
208
+ * @return {Promise}
209
+ */
210
+ run() {
211
+ // the key __init__has no further meaning and is only
212
+ // used to create the diff for empty objects.
213
+ this[internalSymbol].last = {__init__: true};
214
+ return this[internalSymbol].subject.notifyObservers();
215
+ }
216
+
217
+ /**
218
+ * Gets the values of bound elements and changes them in subject
219
+ *
220
+ * @since 1.27.0
221
+ * @return {Monster.DOM.Updater}
222
+ */
223
+ retrieve() {
224
+ retrieveFromBindings.call(this);
225
+ return this;
226
+ }
227
+
228
+ /**
229
+ * If you have passed a ProxyObserver in the constructor, you will get the object that the ProxyObserver manages here.
230
+ * However, if you passed a simple object, here you will get a proxy for that object.
231
+ *
232
+ * For changes, the ProxyObserver must be used.
233
+ *
234
+ * @since 1.8.0
235
+ * @return {Proxy}
236
+ */
237
+ getSubject() {
238
+ return this[internalSymbol].subject.getSubject();
239
+ }
240
+
241
+ /**
242
+ * This method can be used to register commands that can be called via call: instruction.
243
+ * This can be used to provide a pipe with its own functionality.
244
+ *
245
+ * @param {string} name
246
+ * @param {function} callback
247
+ * @return {Transformer}
248
+ * @throws {TypeError} value is not a string
249
+ * @throws {TypeError} value is not a function
250
+ */
251
+ setCallback(name, callback) {
252
+ this[internalSymbol].callbacks.set(name, callback);
253
+ return this;
254
+ }
255
255
  }
256
256
 
257
257
  /**
@@ -262,20 +262,20 @@ class Updater extends Base {
262
262
  * @this Updater
263
263
  */
264
264
  function getCheckStateCallback() {
265
- return function (current) {
266
- // this is a reference to the current object (therefore no array function here)
267
- if (this instanceof HTMLInputElement) {
268
- if (["radio", "checkbox"].indexOf(this.type) !== -1) {
269
- return `${this.value}` === `${current}` ? "true" : undefined;
270
- }
271
- } else if (this instanceof HTMLOptionElement) {
272
- if (isArray(current) && current.indexOf(this.value) !== -1) {
273
- return "true";
274
- }
275
-
276
- return undefined;
277
- }
278
- };
265
+ return function (current) {
266
+ // this is a reference to the current object (therefore no array function here)
267
+ if (this instanceof HTMLInputElement) {
268
+ if (["radio", "checkbox"].indexOf(this.type) !== -1) {
269
+ return `${this.value}` === `${current}` ? "true" : undefined;
270
+ }
271
+ } else if (this instanceof HTMLOptionElement) {
272
+ if (isArray(current) && current.indexOf(this.value) !== -1) {
273
+ return "true";
274
+ }
275
+
276
+ return undefined;
277
+ }
278
+ };
279
279
  }
280
280
 
281
281
  /**
@@ -290,27 +290,27 @@ const symbol = Symbol("@schukai/monster/updater@@EventHandler");
290
290
  * @throws {Error} the bind argument must start as a value with a path
291
291
  */
292
292
  function getControlEventHandler() {
293
- if (this[symbol]) {
294
- return this[symbol];
295
- }
296
-
297
- /**
298
- * @throws {Error} the bind argument must start as a value with a path.
299
- * @throws {Error} unsupported object
300
- * @param {Event} event
301
- */
302
- this[symbol] = (event) => {
303
- const element = findTargetElementFromEvent(event, ATTRIBUTE_UPDATER_BIND);
304
-
305
- if (element === undefined) {
306
- return;
307
- }
308
- queueMicrotask(() => {
309
- retrieveAndSetValue.call(this, element);
310
- });
311
- };
312
-
313
- return this[symbol];
293
+ if (this[symbol]) {
294
+ return this[symbol];
295
+ }
296
+
297
+ /**
298
+ * @throws {Error} the bind argument must start as a value with a path.
299
+ * @throws {Error} unsupported object
300
+ * @param {Event} event
301
+ */
302
+ this[symbol] = (event) => {
303
+ const element = findTargetElementFromEvent(event, ATTRIBUTE_UPDATER_BIND);
304
+
305
+ if (element === undefined) {
306
+ return;
307
+ }
308
+ queueMicrotask(() => {
309
+ retrieveAndSetValue.call(this, element);
310
+ });
311
+ };
312
+
313
+ return this[symbol];
314
314
  }
315
315
 
316
316
  /**
@@ -320,101 +320,101 @@ function getControlEventHandler() {
320
320
  * @private
321
321
  */
322
322
  function retrieveAndSetValue(element) {
323
- const pathfinder = new Pathfinder(this[internalSymbol].subject.getSubject());
324
-
325
- let path = element.getAttribute(ATTRIBUTE_UPDATER_BIND);
326
- if (path === null)
327
- throw new Error("the bind argument must start as a value with a path");
328
-
329
- if (path.indexOf("path:") !== 0) {
330
- throw new Error("the bind argument must start as a value with a path");
331
- }
332
-
333
- path = path.substring(5); // remove path: from the string
334
-
335
- let value;
336
-
337
- if (element instanceof HTMLInputElement) {
338
- switch (element.type) {
339
- case "checkbox":
340
- value = element.checked ? element.value : undefined;
341
- break;
342
- default:
343
- value = element.value;
344
- break;
345
- }
346
- } else if (element instanceof HTMLTextAreaElement) {
347
- value = element.value;
348
- } else if (element instanceof HTMLSelectElement) {
349
- switch (element.type) {
350
- case "select-one":
351
- value = element.value;
352
- break;
353
- case "select-multiple":
354
- value = element.value;
355
-
356
- let options = element?.selectedOptions;
357
- if (options === undefined)
358
- options = element.querySelectorAll(":scope option:checked");
359
- value = Array.from(options).map(({ value }) => value);
360
-
361
- break;
362
- }
363
-
364
- // values from custom elements
365
- } else if (
366
- (element?.constructor?.prototype &&
367
- !!Object.getOwnPropertyDescriptor(
368
- element.constructor.prototype,
369
- "value",
370
- )?.["get"]) ||
371
- element.hasOwnProperty("value")
372
- ) {
373
- value = element?.["value"];
374
- } else {
375
- throw new Error("unsupported object");
376
- }
377
-
378
- if (isString(value)) {
379
- const type = element.getAttribute(ATTRIBUTE_UPDATER_BIND_TYPE);
380
- switch (type) {
381
- case "number":
382
- case "int":
383
- case "float":
384
- case "integer":
385
- value = Number(value);
386
- if (isNaN(value)) {
387
- value = 0;
388
- }
389
- break;
390
- case "boolean":
391
- case "bool":
392
- case "checkbox":
393
- value = value === "true" || value === "1" || value === "on";
394
- break;
395
- case "array":
396
- case "list":
397
- value = value.split(",");
398
- break;
399
- case "object":
400
- case "json":
401
- value = JSON.parse(value);
402
- break;
403
- default:
404
- break;
405
- }
406
- }
407
-
408
- const copy = clone(this[internalSymbol].subject.getRealSubject());
409
-
410
- const pf = new Pathfinder(copy);
411
- pf.setVia(path, value);
412
-
413
- const diffResult = diff(copy, this[internalSymbol].subject.getRealSubject());
414
-
415
- if (diffResult.length > 0) {
416
- pathfinder.setVia(path, value);
417
- }
323
+ const pathfinder = new Pathfinder(this[internalSymbol].subject.getSubject());
324
+
325
+ let path = element.getAttribute(ATTRIBUTE_UPDATER_BIND);
326
+ if (path === null)
327
+ throw new Error("the bind argument must start as a value with a path");
328
+
329
+ if (path.indexOf("path:") !== 0) {
330
+ throw new Error("the bind argument must start as a value with a path");
331
+ }
332
+
333
+ path = path.substring(5); // remove path: from the string
334
+
335
+ let value;
336
+
337
+ if (element instanceof HTMLInputElement) {
338
+ switch (element.type) {
339
+ case "checkbox":
340
+ value = element.checked ? element.value : undefined;
341
+ break;
342
+ default:
343
+ value = element.value;
344
+ break;
345
+ }
346
+ } else if (element instanceof HTMLTextAreaElement) {
347
+ value = element.value;
348
+ } else if (element instanceof HTMLSelectElement) {
349
+ switch (element.type) {
350
+ case "select-one":
351
+ value = element.value;
352
+ break;
353
+ case "select-multiple":
354
+ value = element.value;
355
+
356
+ let options = element?.selectedOptions;
357
+ if (options === undefined)
358
+ options = element.querySelectorAll(":scope option:checked");
359
+ value = Array.from(options).map(({value}) => value);
360
+
361
+ break;
362
+ }
363
+
364
+ // values from custom elements
365
+ } else if (
366
+ (element?.constructor?.prototype &&
367
+ !!Object.getOwnPropertyDescriptor(
368
+ element.constructor.prototype,
369
+ "value",
370
+ )?.["get"]) ||
371
+ element.hasOwnProperty("value")
372
+ ) {
373
+ value = element?.["value"];
374
+ } else {
375
+ throw new Error("unsupported object");
376
+ }
377
+
378
+ if (isString(value)) {
379
+ const type = element.getAttribute(ATTRIBUTE_UPDATER_BIND_TYPE);
380
+ switch (type) {
381
+ case "number":
382
+ case "int":
383
+ case "float":
384
+ case "integer":
385
+ value = Number(value);
386
+ if (isNaN(value)) {
387
+ value = 0;
388
+ }
389
+ break;
390
+ case "boolean":
391
+ case "bool":
392
+ case "checkbox":
393
+ value = value === "true" || value === "1" || value === "on";
394
+ break;
395
+ case "array":
396
+ case "list":
397
+ value = value.split(",");
398
+ break;
399
+ case "object":
400
+ case "json":
401
+ value = JSON.parse(value);
402
+ break;
403
+ default:
404
+ break;
405
+ }
406
+ }
407
+
408
+ const copy = clone(this[internalSymbol].subject.getRealSubject());
409
+
410
+ const pf = new Pathfinder(copy);
411
+ pf.setVia(path, value);
412
+
413
+ const diffResult = diff(copy, this[internalSymbol].subject.getRealSubject());
414
+
415
+ if (diffResult.length > 0) {
416
+ pathfinder.setVia(path, value);
417
+ }
418
418
  }
419
419
 
420
420
  /**
@@ -424,15 +424,15 @@ function retrieveAndSetValue(element) {
424
424
  * @private
425
425
  */
426
426
  function retrieveFromBindings() {
427
- if (this[internalSymbol].element.matches(`[${ATTRIBUTE_UPDATER_BIND}]`)) {
428
- retrieveAndSetValue.call(this, this[internalSymbol].element);
429
- }
430
-
431
- for (const [, element] of this[internalSymbol].element
432
- .querySelectorAll(`[${ATTRIBUTE_UPDATER_BIND}]`)
433
- .entries()) {
434
- retrieveAndSetValue.call(this, element);
435
- }
427
+ if (this[internalSymbol].element.matches(`[${ATTRIBUTE_UPDATER_BIND}]`)) {
428
+ retrieveAndSetValue.call(this, this[internalSymbol].element);
429
+ }
430
+
431
+ for (const [, element] of this[internalSymbol].element
432
+ .querySelectorAll(`[${ATTRIBUTE_UPDATER_BIND}]`)
433
+ .entries()) {
434
+ retrieveAndSetValue.call(this, element);
435
+ }
436
436
  }
437
437
 
438
438
  /**
@@ -443,11 +443,11 @@ function retrieveFromBindings() {
443
443
  * @return {void}
444
444
  */
445
445
  function removeElement(change) {
446
- for (const [, element] of this[internalSymbol].element
447
- .querySelectorAll(`:scope [${ATTRIBUTE_UPDATER_REMOVE}]`)
448
- .entries()) {
449
- element.parentNode.removeChild(element);
450
- }
446
+ for (const [, element] of this[internalSymbol].element
447
+ .querySelectorAll(`:scope [${ATTRIBUTE_UPDATER_REMOVE}]`)
448
+ .entries()) {
449
+ element.parentNode.removeChild(element);
450
+ }
451
451
  }
452
452
 
453
453
  /**
@@ -463,133 +463,133 @@ function removeElement(change) {
463
463
  * @this Updater
464
464
  */
465
465
  function insertElement(change) {
466
- const subject = this[internalSymbol].subject.getRealSubject();
466
+ const subject = this[internalSymbol].subject.getRealSubject();
467
467
 
468
- const mem = new WeakSet();
469
- let wd = 0;
468
+ const mem = new WeakSet();
469
+ let wd = 0;
470
470
 
471
- const container = this[internalSymbol].element;
471
+ const container = this[internalSymbol].element;
472
472
 
473
- while (true) {
474
- let found = false;
475
- wd++;
476
-
477
- const p = clone(change?.["path"]);
478
- if (!isArray(p)) return;
479
-
480
- while (p.length > 0) {
481
- const current = p.join(".");
482
-
483
- let iterator = new Set();
484
- const query = `[${ATTRIBUTE_UPDATER_INSERT}*="path:${current}"]`;
485
-
486
- const e = container.querySelectorAll(query);
487
-
488
- if (e.length > 0) {
489
- iterator = new Set([...e]);
490
- }
491
-
492
- if (container.matches(query)) {
493
- iterator.add(container);
494
- }
495
-
496
- for (const [, containerElement] of iterator.entries()) {
497
- if (mem.has(containerElement)) continue;
498
- mem.add(containerElement);
499
-
500
- found = true;
501
-
502
- const attributes = containerElement.getAttribute(
503
- ATTRIBUTE_UPDATER_INSERT,
504
- );
505
- if (attributes === null) continue;
506
-
507
- const def = trimSpaces(attributes);
508
- const i = def.indexOf(" ");
509
- const key = trimSpaces(def.substr(0, i));
510
- const refPrefix = `${key}-`;
511
- const cmd = trimSpaces(def.substr(i));
512
-
513
- // this case is actually excluded by the query but is nevertheless checked again here
514
- if (cmd.indexOf("|") > 0) {
515
- throw new Error("pipes are not allowed when cloning a node.");
516
- }
517
-
518
- const pipe = new Pipe(cmd);
519
- this[internalSymbol].callbacks.forEach((f, n) => {
520
- pipe.setCallback(n, f);
521
- });
522
-
523
- let value;
524
- try {
525
- containerElement.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
526
- value = pipe.run(subject);
527
- } catch (e) {
528
- containerElement.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
529
- }
530
-
531
- const dataPath = cmd.split(":").pop();
532
-
533
- let insertPoint;
534
- if (containerElement.hasChildNodes()) {
535
- insertPoint = containerElement.lastChild;
536
- }
537
-
538
- if (!isIterable(value)) {
539
- throw new Error("the value is not iterable");
540
- }
541
-
542
- const available = new Set();
543
-
544
- for (const [i] of Object.entries(value)) {
545
- const ref = refPrefix + i;
546
- const currentPath = `${dataPath}.${i}`;
547
-
548
- available.add(ref);
549
- const refElement = containerElement.querySelector(
550
- `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}="${ref}"]`,
551
- );
552
-
553
- if (refElement instanceof HTMLElement) {
554
- insertPoint = refElement;
555
- continue;
556
- }
557
-
558
- appendNewDocumentFragment(containerElement, key, ref, currentPath);
559
- }
560
-
561
- const nodes = containerElement.querySelectorAll(
562
- `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}*="${refPrefix}"]`,
563
- );
564
-
565
- for (const [, node] of Object.entries(nodes)) {
566
- if (
567
- !available.has(
568
- node.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE),
569
- )
570
- ) {
571
- try {
572
- containerElement.removeChild(node);
573
- } catch (e) {
574
- containerElement.setAttribute(
575
- ATTRIBUTE_ERRORMESSAGE,
576
- `${containerElement.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
577
- e.message
578
- }`.trim(),
579
- );
580
- }
581
- }
582
- }
583
- }
584
-
585
- p.pop();
586
- }
587
-
588
- if (found === false) break;
589
- if (wd++ > 200) {
590
- throw new Error("the maximum depth for the recursion is reached.");
591
- }
592
- }
473
+ while (true) {
474
+ let found = false;
475
+ wd++;
476
+
477
+ const p = clone(change?.["path"]);
478
+ if (!isArray(p)) return;
479
+
480
+ while (p.length > 0) {
481
+ const current = p.join(".");
482
+
483
+ let iterator = new Set();
484
+ const query = `[${ATTRIBUTE_UPDATER_INSERT}*="path:${current}"]`;
485
+
486
+ const e = container.querySelectorAll(query);
487
+
488
+ if (e.length > 0) {
489
+ iterator = new Set([...e]);
490
+ }
491
+
492
+ if (container.matches(query)) {
493
+ iterator.add(container);
494
+ }
495
+
496
+ for (const [, containerElement] of iterator.entries()) {
497
+ if (mem.has(containerElement)) continue;
498
+ mem.add(containerElement);
499
+
500
+ found = true;
501
+
502
+ const attributes = containerElement.getAttribute(
503
+ ATTRIBUTE_UPDATER_INSERT,
504
+ );
505
+ if (attributes === null) continue;
506
+
507
+ const def = trimSpaces(attributes);
508
+ const i = def.indexOf(" ");
509
+ const key = trimSpaces(def.substr(0, i));
510
+ const refPrefix = `${key}-`;
511
+ const cmd = trimSpaces(def.substr(i));
512
+
513
+ // this case is actually excluded by the query but is nevertheless checked again here
514
+ if (cmd.indexOf("|") > 0) {
515
+ throw new Error("pipes are not allowed when cloning a node.");
516
+ }
517
+
518
+ const pipe = new Pipe(cmd);
519
+ this[internalSymbol].callbacks.forEach((f, n) => {
520
+ pipe.setCallback(n, f);
521
+ });
522
+
523
+ let value;
524
+ try {
525
+ containerElement.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
526
+ value = pipe.run(subject);
527
+ } catch (e) {
528
+ containerElement.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
529
+ }
530
+
531
+ const dataPath = cmd.split(":").pop();
532
+
533
+ let insertPoint;
534
+ if (containerElement.hasChildNodes()) {
535
+ insertPoint = containerElement.lastChild;
536
+ }
537
+
538
+ if (!isIterable(value)) {
539
+ throw new Error("the value is not iterable");
540
+ }
541
+
542
+ const available = new Set();
543
+
544
+ for (const [i] of Object.entries(value)) {
545
+ const ref = refPrefix + i;
546
+ const currentPath = `${dataPath}.${i}`;
547
+
548
+ available.add(ref);
549
+ const refElement = containerElement.querySelector(
550
+ `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}="${ref}"]`,
551
+ );
552
+
553
+ if (refElement instanceof HTMLElement) {
554
+ insertPoint = refElement;
555
+ continue;
556
+ }
557
+
558
+ appendNewDocumentFragment(containerElement, key, ref, currentPath);
559
+ }
560
+
561
+ const nodes = containerElement.querySelectorAll(
562
+ `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}*="${refPrefix}"]`,
563
+ );
564
+
565
+ for (const [, node] of Object.entries(nodes)) {
566
+ if (
567
+ !available.has(
568
+ node.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE),
569
+ )
570
+ ) {
571
+ try {
572
+ containerElement.removeChild(node);
573
+ } catch (e) {
574
+ containerElement.setAttribute(
575
+ ATTRIBUTE_ERRORMESSAGE,
576
+ `${containerElement.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
577
+ e.message
578
+ }`.trim(),
579
+ );
580
+ }
581
+ }
582
+ }
583
+ }
584
+
585
+ p.pop();
586
+ }
587
+
588
+ if (found === false) break;
589
+ if (wd++ > 200) {
590
+ throw new Error("the maximum depth for the recursion is reached.");
591
+ }
592
+ }
593
593
  }
594
594
 
595
595
  /**
@@ -604,17 +604,17 @@ function insertElement(change) {
604
604
  * @throws {Error} no template was found with the specified key.
605
605
  */
606
606
  function appendNewDocumentFragment(container, key, ref, path) {
607
- const template = findDocumentTemplate(key, container);
607
+ const template = findDocumentTemplate(key, container);
608
608
 
609
- const nodes = template.createDocumentFragment();
610
- for (const [, node] of Object.entries(nodes.childNodes)) {
611
- if (node instanceof HTMLElement) {
612
- applyRecursive(node, key, path);
613
- node.setAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE, ref);
614
- }
609
+ const nodes = template.createDocumentFragment();
610
+ for (const [, node] of Object.entries(nodes.childNodes)) {
611
+ if (node instanceof HTMLElement) {
612
+ applyRecursive(node, key, path);
613
+ node.setAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE, ref);
614
+ }
615
615
 
616
- container.appendChild(node);
617
- }
616
+ container.appendChild(node);
617
+ }
618
618
  }
619
619
 
620
620
  /**
@@ -627,27 +627,27 @@ function appendNewDocumentFragment(container, key, ref, path) {
627
627
  * @return {void}
628
628
  */
629
629
  function applyRecursive(node, key, path) {
630
- if (node instanceof HTMLElement) {
631
- if (node.hasAttribute(ATTRIBUTE_UPDATER_REPLACE)) {
632
- const value = node.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
633
- node.setAttribute(
634
- ATTRIBUTE_UPDATER_REPLACE,
635
- value.replaceAll(`path:${key}`, `path:${path}`),
636
- );
637
- }
638
-
639
- if (node.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
640
- const value = node.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
641
- node.setAttribute(
642
- ATTRIBUTE_UPDATER_ATTRIBUTES,
643
- value.replaceAll(`path:${key}`, `path:${path}`),
644
- );
645
- }
646
-
647
- for (const [, child] of Object.entries(node.childNodes)) {
648
- applyRecursive(child, key, path);
649
- }
650
- }
630
+ if (node instanceof HTMLElement) {
631
+ if (node.hasAttribute(ATTRIBUTE_UPDATER_REPLACE)) {
632
+ const value = node.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
633
+ node.setAttribute(
634
+ ATTRIBUTE_UPDATER_REPLACE,
635
+ value.replaceAll(`path:${key}`, `path:${path}`),
636
+ );
637
+ }
638
+
639
+ if (node.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
640
+ const value = node.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
641
+ node.setAttribute(
642
+ ATTRIBUTE_UPDATER_ATTRIBUTES,
643
+ value.replaceAll(`path:${key}`, `path:${path}`),
644
+ );
645
+ }
646
+
647
+ for (const [, child] of Object.entries(node.childNodes)) {
648
+ applyRecursive(child, key, path);
649
+ }
650
+ }
651
651
  }
652
652
 
653
653
  /**
@@ -659,19 +659,19 @@ function applyRecursive(node, key, path) {
659
659
  * @this Updater
660
660
  */
661
661
  function updateContent(change) {
662
- const subject = this[internalSymbol].subject.getRealSubject();
663
-
664
- const p = clone(change?.["path"]);
665
- runUpdateContent.call(this, this[internalSymbol].element, p, subject);
666
-
667
- const slots = this[internalSymbol].element.querySelectorAll("slot");
668
- if (slots.length > 0) {
669
- for (const [, slot] of Object.entries(slots)) {
670
- for (const [, element] of Object.entries(slot.assignedNodes())) {
671
- runUpdateContent.call(this, element, p, subject);
672
- }
673
- }
674
- }
662
+ const subject = this[internalSymbol].subject.getRealSubject();
663
+
664
+ const p = clone(change?.["path"]);
665
+ runUpdateContent.call(this, this[internalSymbol].element, p, subject);
666
+
667
+ const slots = this[internalSymbol].element.querySelectorAll("slot");
668
+ if (slots.length > 0) {
669
+ for (const [, slot] of Object.entries(slots)) {
670
+ for (const [, element] of Object.entries(slot.assignedNodes())) {
671
+ runUpdateContent.call(this, element, p, subject);
672
+ }
673
+ }
674
+ }
675
675
  }
676
676
 
677
677
  /**
@@ -684,69 +684,69 @@ function updateContent(change) {
684
684
  * @return {void}
685
685
  */
686
686
  function runUpdateContent(container, parts, subject) {
687
- if (!isArray(parts)) return;
688
- if (!(container instanceof HTMLElement)) return;
689
- parts = clone(parts);
690
-
691
- const mem = new WeakSet();
692
-
693
- while (parts.length > 0) {
694
- const current = parts.join(".");
695
- parts.pop();
696
-
697
- // Unfortunately, static data is always changed as well, since it is not possible to react to changes here.
698
- const query = `[${ATTRIBUTE_UPDATER_REPLACE}^="path:${current}"], [${ATTRIBUTE_UPDATER_REPLACE}^="static:"], [${ATTRIBUTE_UPDATER_REPLACE}^="i18n:"]`;
699
- const e = container.querySelectorAll(`${query}`);
700
-
701
- const iterator = new Set([...e]);
702
-
703
- if (container.matches(query)) {
704
- iterator.add(container);
705
- }
706
-
707
- /**
708
- * @type {HTMLElement}
709
- */
710
- for (const [element] of iterator.entries()) {
711
- if (mem.has(element)) return;
712
- mem.add(element);
713
-
714
- const attributes = element.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
715
- const cmd = trimSpaces(attributes);
716
-
717
- const pipe = new Pipe(cmd);
718
- this[internalSymbol].callbacks.forEach((f, n) => {
719
- pipe.setCallback(n, f);
720
- });
721
-
722
- let value;
723
- try {
724
- element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
725
- value = pipe.run(subject);
726
- } catch (e) {
727
- element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
728
- }
729
-
730
- if (value instanceof HTMLElement) {
731
- while (element.firstChild) {
732
- element.removeChild(element.firstChild);
733
- }
734
-
735
- try {
736
- element.appendChild(value);
737
- } catch (e) {
738
- element.setAttribute(
739
- ATTRIBUTE_ERRORMESSAGE,
740
- `${element.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
741
- e.message
742
- }`.trim(),
743
- );
744
- }
745
- } else {
746
- element.innerHTML = value;
747
- }
748
- }
749
- }
687
+ if (!isArray(parts)) return;
688
+ if (!(container instanceof HTMLElement)) return;
689
+ parts = clone(parts);
690
+
691
+ const mem = new WeakSet();
692
+
693
+ while (parts.length > 0) {
694
+ const current = parts.join(".");
695
+ parts.pop();
696
+
697
+ // Unfortunately, static data is always changed as well, since it is not possible to react to changes here.
698
+ const query = `[${ATTRIBUTE_UPDATER_REPLACE}^="path:${current}"], [${ATTRIBUTE_UPDATER_REPLACE}^="static:"], [${ATTRIBUTE_UPDATER_REPLACE}^="i18n:"]`;
699
+ const e = container.querySelectorAll(`${query}`);
700
+
701
+ const iterator = new Set([...e]);
702
+
703
+ if (container.matches(query)) {
704
+ iterator.add(container);
705
+ }
706
+
707
+ /**
708
+ * @type {HTMLElement}
709
+ */
710
+ for (const [element] of iterator.entries()) {
711
+ if (mem.has(element)) return;
712
+ mem.add(element);
713
+
714
+ const attributes = element.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
715
+ const cmd = trimSpaces(attributes);
716
+
717
+ const pipe = new Pipe(cmd);
718
+ this[internalSymbol].callbacks.forEach((f, n) => {
719
+ pipe.setCallback(n, f);
720
+ });
721
+
722
+ let value;
723
+ try {
724
+ element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
725
+ value = pipe.run(subject);
726
+ } catch (e) {
727
+ element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
728
+ }
729
+
730
+ if (value instanceof HTMLElement) {
731
+ while (element.firstChild) {
732
+ element.removeChild(element.firstChild);
733
+ }
734
+
735
+ try {
736
+ element.appendChild(value);
737
+ } catch (e) {
738
+ element.setAttribute(
739
+ ATTRIBUTE_ERRORMESSAGE,
740
+ `${element.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
741
+ e.message
742
+ }`.trim(),
743
+ );
744
+ }
745
+ } else {
746
+ element.innerHTML = value;
747
+ }
748
+ }
749
+ }
750
750
  }
751
751
 
752
752
  /**
@@ -756,9 +756,9 @@ function runUpdateContent(container, parts, subject) {
756
756
  * @return {void}
757
757
  */
758
758
  function updateAttributes(change) {
759
- const subject = this[internalSymbol].subject.getRealSubject();
760
- const p = clone(change?.["path"]);
761
- runUpdateAttributes.call(this, this[internalSymbol].element, p, subject);
759
+ const subject = this[internalSymbol].subject.getRealSubject();
760
+ const p = clone(change?.["path"]);
761
+ runUpdateAttributes.call(this, this[internalSymbol].element, p, subject);
762
762
  }
763
763
 
764
764
  /**
@@ -770,70 +770,70 @@ function updateAttributes(change) {
770
770
  * @this Updater
771
771
  */
772
772
  function runUpdateAttributes(container, parts, subject) {
773
- if (!isArray(parts)) return;
774
- parts = clone(parts);
773
+ if (!isArray(parts)) return;
774
+ parts = clone(parts);
775
775
 
776
- const mem = new WeakSet();
776
+ const mem = new WeakSet();
777
777
 
778
- while (parts.length > 0) {
779
- const current = parts.join(".");
780
- parts.pop();
778
+ while (parts.length > 0) {
779
+ const current = parts.join(".");
780
+ parts.pop();
781
781
 
782
- let iterator = new Set();
782
+ let iterator = new Set();
783
783
 
784
- const query = `[${ATTRIBUTE_UPDATER_SELECT_THIS}][${ATTRIBUTE_UPDATER_ATTRIBUTES}], [${ATTRIBUTE_UPDATER_ATTRIBUTES}*="path:${current}"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="static:"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="i18n:"]`;
784
+ const query = `[${ATTRIBUTE_UPDATER_SELECT_THIS}][${ATTRIBUTE_UPDATER_ATTRIBUTES}], [${ATTRIBUTE_UPDATER_ATTRIBUTES}*="path:${current}"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="static:"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="i18n:"]`;
785
785
 
786
- const e = container.querySelectorAll(query);
786
+ const e = container.querySelectorAll(query);
787
787
 
788
- if (e.length > 0) {
789
- iterator = new Set([...e]);
790
- }
788
+ if (e.length > 0) {
789
+ iterator = new Set([...e]);
790
+ }
791
791
 
792
- if (container.matches(query)) {
793
- iterator.add(container);
794
- }
792
+ if (container.matches(query)) {
793
+ iterator.add(container);
794
+ }
795
795
 
796
- for (const [element] of iterator.entries()) {
797
- if (mem.has(element)) return;
798
- mem.add(element);
796
+ for (const [element] of iterator.entries()) {
797
+ if (mem.has(element)) return;
798
+ mem.add(element);
799
799
 
800
- // this case occurs when the ATTRIBUTE_UPDATER_SELECT_THIS attribute is set
801
- if (!element.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
802
- continue;
803
- }
800
+ // this case occurs when the ATTRIBUTE_UPDATER_SELECT_THIS attribute is set
801
+ if (!element.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
802
+ continue;
803
+ }
804
804
 
805
- const attributes = element.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
805
+ const attributes = element.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
806
806
 
807
- for (let [, def] of Object.entries(attributes.split(","))) {
808
- def = trimSpaces(def);
809
- const i = def.indexOf(" ");
810
- const name = trimSpaces(def.substr(0, i));
811
- const cmd = trimSpaces(def.substr(i));
807
+ for (let [, def] of Object.entries(attributes.split(","))) {
808
+ def = trimSpaces(def);
809
+ const i = def.indexOf(" ");
810
+ const name = trimSpaces(def.substr(0, i));
811
+ const cmd = trimSpaces(def.substr(i));
812
812
 
813
- const pipe = new Pipe(cmd);
813
+ const pipe = new Pipe(cmd);
814
814
 
815
- this[internalSymbol].callbacks.forEach((f, n) => {
816
- pipe.setCallback(n, f, element);
817
- });
815
+ this[internalSymbol].callbacks.forEach((f, n) => {
816
+ pipe.setCallback(n, f, element);
817
+ });
818
818
 
819
- let value;
820
- try {
821
- element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
822
- value = pipe.run(subject);
823
- } catch (e) {
824
- element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
825
- }
819
+ let value;
820
+ try {
821
+ element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
822
+ value = pipe.run(subject);
823
+ } catch (e) {
824
+ element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
825
+ }
826
826
 
827
- if (value === undefined) {
828
- element.removeAttribute(name);
829
- } else if (element.getAttribute(name) !== value) {
830
- element.setAttribute(name, value);
831
- }
827
+ if (value === undefined) {
828
+ element.removeAttribute(name);
829
+ } else if (element.getAttribute(name) !== value) {
830
+ element.setAttribute(name, value);
831
+ }
832
832
 
833
- handleInputControlAttributeUpdate.call(this, element, name, value);
834
- }
835
- }
836
- }
833
+ handleInputControlAttributeUpdate.call(this, element, name, value);
834
+ }
835
+ }
836
+ }
837
837
  }
838
838
 
839
839
  /**
@@ -846,58 +846,58 @@ function runUpdateAttributes(container, parts, subject) {
846
846
  */
847
847
 
848
848
  function handleInputControlAttributeUpdate(element, name, value) {
849
- if (element instanceof HTMLSelectElement) {
850
- switch (element.type) {
851
- case "select-multiple":
852
- for (const [index, opt] of Object.entries(element.options)) {
853
- if (value.indexOf(opt.value) !== -1) {
854
- opt.selected = true;
855
- } else {
856
- opt.selected = false;
857
- }
858
- }
859
-
860
- break;
861
- case "select-one":
862
- // Only one value may be selected
863
-
864
- for (const [index, opt] of Object.entries(element.options)) {
865
- if (opt.value === value) {
866
- element.selectedIndex = index;
867
- break;
868
- }
869
- }
870
-
871
- break;
872
- }
873
- } else if (element instanceof HTMLInputElement) {
874
- switch (element.type) {
875
- case "radio":
876
- if (name === "checked") {
877
- element.checked = value !== undefined;
878
- }
879
-
880
- break;
881
-
882
- case "checkbox":
883
- if (name === "checked") {
884
- element.checked = value !== undefined;
885
- }
886
-
887
- break;
888
- case "text":
889
- default:
890
- if (name === "value") {
891
- element.value = value === undefined ? "" : value;
892
- }
893
-
894
- break;
895
- }
896
- } else if (element instanceof HTMLTextAreaElement) {
897
- if (name === "value") {
898
- element.value = value === undefined ? "" : value;
899
- }
900
- }
849
+ if (element instanceof HTMLSelectElement) {
850
+ switch (element.type) {
851
+ case "select-multiple":
852
+ for (const [index, opt] of Object.entries(element.options)) {
853
+ if (value.indexOf(opt.value) !== -1) {
854
+ opt.selected = true;
855
+ } else {
856
+ opt.selected = false;
857
+ }
858
+ }
859
+
860
+ break;
861
+ case "select-one":
862
+ // Only one value may be selected
863
+
864
+ for (const [index, opt] of Object.entries(element.options)) {
865
+ if (opt.value === value) {
866
+ element.selectedIndex = index;
867
+ break;
868
+ }
869
+ }
870
+
871
+ break;
872
+ }
873
+ } else if (element instanceof HTMLInputElement) {
874
+ switch (element.type) {
875
+ case "radio":
876
+ if (name === "checked") {
877
+ element.checked = value !== undefined;
878
+ }
879
+
880
+ break;
881
+
882
+ case "checkbox":
883
+ if (name === "checked") {
884
+ element.checked = value !== undefined;
885
+ }
886
+
887
+ break;
888
+ case "text":
889
+ default:
890
+ if (name === "value") {
891
+ element.value = value === undefined ? "" : value;
892
+ }
893
+
894
+ break;
895
+ }
896
+ } else if (element instanceof HTMLTextAreaElement) {
897
+ if (name === "value") {
898
+ element.value = value === undefined ? "" : value;
899
+ }
900
+ }
901
901
  }
902
902
 
903
903
  /**
@@ -916,83 +916,83 @@ function handleInputControlAttributeUpdate(element, name, value) {
916
916
  * @throws {TypeError} symbol must be an instance of Symbol
917
917
  */
918
918
  function addObjectWithUpdaterToElement(elements, symbol, object, config = {}) {
919
- if (!(this instanceof HTMLElement)) {
920
- throw new TypeError(
921
- "the context of this function must be an instance of HTMLElement",
922
- );
923
- }
924
-
925
- if (!(typeof symbol === "symbol")) {
926
- throw new TypeError("symbol must be an instance of Symbol");
927
- }
928
-
929
- const updaters = new Set();
930
-
931
- if (elements instanceof NodeList) {
932
- elements = new Set([...elements]);
933
- } else if (elements instanceof HTMLElement) {
934
- elements = new Set([elements]);
935
- } else if (elements instanceof Set) {
936
- } else {
937
- throw new TypeError(
938
- `elements is not a valid type. (actual: ${typeof elements})`,
939
- );
940
- }
941
-
942
- const result = [];
943
-
944
- const updaterCallbacks = [];
945
- const cb = this?.[updaterTransformerMethodsSymbol];
946
- if (this instanceof HTMLElement && typeof cb === "function") {
947
- const callbacks = cb.call(this);
948
- if (typeof callbacks === "object") {
949
- for (const [name, callback] of Object.entries(callbacks)) {
950
- if (typeof callback === "function") {
951
- updaterCallbacks.push([name, callback]);
952
- } else {
953
- addAttributeToken(
954
- this,
955
- ATTRIBUTE_ERRORMESSAGE,
956
- `onUpdaterPipeCallbacks: ${name} is not a function`,
957
- );
958
- }
959
- }
960
- } else {
961
- addAttributeToken(
962
- this,
963
- ATTRIBUTE_ERRORMESSAGE,
964
- `onUpdaterPipeCallbacks do not return an object with functions`,
965
- );
966
- }
967
- }
968
-
969
- elements.forEach((element) => {
970
- if (!(element instanceof HTMLElement)) return;
971
- if (element instanceof HTMLTemplateElement) return;
972
-
973
- const u = new Updater(element, object);
974
- updaters.add(u);
975
-
976
- if (updaterCallbacks.length > 0) {
977
- for (const [name, callback] of updaterCallbacks) {
978
- u.setCallback(name, callback);
979
- }
980
- }
981
-
982
- result.push(
983
- u.run().then(() => {
984
- if (config.eventProcessing === true) {
985
- u.enableEventProcessing();
986
- }
987
-
988
- return u;
989
- }),
990
- );
991
- });
992
-
993
- if (updaters.size > 0) {
994
- addToObjectLink(this, symbol, updaters);
995
- }
996
-
997
- return result;
919
+ if (!(this instanceof HTMLElement)) {
920
+ throw new TypeError(
921
+ "the context of this function must be an instance of HTMLElement",
922
+ );
923
+ }
924
+
925
+ if (!(typeof symbol === "symbol")) {
926
+ throw new TypeError("symbol must be an instance of Symbol");
927
+ }
928
+
929
+ const updaters = new Set();
930
+
931
+ if (elements instanceof NodeList) {
932
+ elements = new Set([...elements]);
933
+ } else if (elements instanceof HTMLElement) {
934
+ elements = new Set([elements]);
935
+ } else if (elements instanceof Set) {
936
+ } else {
937
+ throw new TypeError(
938
+ `elements is not a valid type. (actual: ${typeof elements})`,
939
+ );
940
+ }
941
+
942
+ const result = [];
943
+
944
+ const updaterCallbacks = [];
945
+ const cb = this?.[updaterTransformerMethodsSymbol];
946
+ if (this instanceof HTMLElement && typeof cb === "function") {
947
+ const callbacks = cb.call(this);
948
+ if (typeof callbacks === "object") {
949
+ for (const [name, callback] of Object.entries(callbacks)) {
950
+ if (typeof callback === "function") {
951
+ updaterCallbacks.push([name, callback]);
952
+ } else {
953
+ addAttributeToken(
954
+ this,
955
+ ATTRIBUTE_ERRORMESSAGE,
956
+ `onUpdaterPipeCallbacks: ${name} is not a function`,
957
+ );
958
+ }
959
+ }
960
+ } else {
961
+ addAttributeToken(
962
+ this,
963
+ ATTRIBUTE_ERRORMESSAGE,
964
+ `onUpdaterPipeCallbacks do not return an object with functions`,
965
+ );
966
+ }
967
+ }
968
+
969
+ elements.forEach((element) => {
970
+ if (!(element instanceof HTMLElement)) return;
971
+ if (element instanceof HTMLTemplateElement) return;
972
+
973
+ const u = new Updater(element, object);
974
+ updaters.add(u);
975
+
976
+ if (updaterCallbacks.length > 0) {
977
+ for (const [name, callback] of updaterCallbacks) {
978
+ u.setCallback(name, callback);
979
+ }
980
+ }
981
+
982
+ result.push(
983
+ u.run().then(() => {
984
+ if (config.eventProcessing === true) {
985
+ u.enableEventProcessing();
986
+ }
987
+
988
+ return u;
989
+ }),
990
+ );
991
+ });
992
+
993
+ if (updaters.size > 0) {
994
+ addToObjectLink(this, symbol, updaters);
995
+ }
996
+
997
+ return result;
998
998
  }