@schukai/monster 3.55.0 → 3.55.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/package.json +1 -1
  3. package/source/components/datatable/datasource/rest.mjs +77 -46
  4. package/source/components/datatable/datatable/header.mjs +1 -1
  5. package/source/components/datatable/datatable.mjs +586 -591
  6. package/source/components/datatable/embedded-pagination.mjs +42 -49
  7. package/source/components/datatable/filter/util.mjs +115 -99
  8. package/source/components/datatable/filter.mjs +905 -842
  9. package/source/components/datatable/pagination.mjs +333 -334
  10. package/source/components/datatable/status.mjs +134 -156
  11. package/source/components/datatable/stylesheet/column-bar.mjs +14 -8
  12. package/source/components/datatable/stylesheet/dataset.mjs +14 -8
  13. package/source/components/datatable/stylesheet/datasource.mjs +14 -8
  14. package/source/components/datatable/stylesheet/datatable.mjs +14 -8
  15. package/source/components/datatable/stylesheet/embedded-pagination.mjs +14 -8
  16. package/source/components/datatable/stylesheet/filter-button.mjs +14 -8
  17. package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +14 -8
  18. package/source/components/datatable/stylesheet/filter-date-range.mjs +14 -8
  19. package/source/components/datatable/stylesheet/filter-range.mjs +14 -8
  20. package/source/components/datatable/stylesheet/filter.mjs +14 -8
  21. package/source/components/datatable/stylesheet/pagination.mjs +14 -8
  22. package/source/components/datatable/stylesheet/select-filter.mjs +14 -8
  23. package/source/components/datatable/stylesheet/status.mjs +14 -8
  24. package/source/components/form/action-button.mjs +3 -1
  25. package/source/components/form/confirm-button.mjs +3 -1
  26. package/source/components/form/context-error.mjs +161 -164
  27. package/source/components/form/context-help.mjs +3 -1
  28. package/source/components/form/form.mjs +3 -1
  29. package/source/components/form/message-state-button.mjs +3 -1
  30. package/source/components/form/popper-button.mjs +6 -4
  31. package/source/components/form/popper.mjs +310 -310
  32. package/source/components/form/select.mjs +2 -2
  33. package/source/components/form/state-button.mjs +3 -1
  34. package/source/components/form/stylesheet/action-button.mjs +14 -8
  35. package/source/components/form/stylesheet/api-button.mjs +14 -8
  36. package/source/components/form/stylesheet/button-bar.mjs +14 -8
  37. package/source/components/form/stylesheet/button.mjs +14 -8
  38. package/source/components/form/stylesheet/confirm-button.mjs +14 -8
  39. package/source/components/form/stylesheet/context-error.mjs +14 -8
  40. package/source/components/form/stylesheet/context-help.mjs +14 -8
  41. package/source/components/form/stylesheet/form.mjs +14 -8
  42. package/source/components/form/stylesheet/message-state-button.mjs +14 -8
  43. package/source/components/form/stylesheet/popper-button.mjs +14 -8
  44. package/source/components/form/stylesheet/popper.mjs +14 -8
  45. package/source/components/form/stylesheet/select.mjs +14 -8
  46. package/source/components/form/stylesheet/state-button.mjs +14 -8
  47. package/source/components/form/stylesheet/tabs.mjs +14 -8
  48. package/source/components/form/stylesheet/tree-select.mjs +14 -8
  49. package/source/components/form/tabs.mjs +754 -758
  50. package/source/components/host/collapse.mjs +2 -4
  51. package/source/components/host/config-manager.mjs +11 -9
  52. package/source/components/host/stylesheet/call-button.mjs +14 -8
  53. package/source/components/host/stylesheet/collapse.mjs +14 -8
  54. package/source/components/host/stylesheet/config-manager.mjs +14 -8
  55. package/source/components/host/stylesheet/details.mjs +14 -8
  56. package/source/components/host/stylesheet/host.mjs +14 -8
  57. package/source/components/host/stylesheet/overlay.mjs +14 -8
  58. package/source/components/host/stylesheet/toggle-button.mjs +14 -8
  59. package/source/components/host/stylesheet/viewer.mjs +14 -8
  60. package/source/components/host/util.mjs +2 -2
  61. package/source/components/notify/stylesheet/message.mjs +14 -8
  62. package/source/components/notify/stylesheet/notify.mjs +14 -8
  63. package/source/components/state/stylesheet/log.mjs +14 -8
  64. package/source/components/state/stylesheet/state.mjs +14 -8
  65. package/source/components/stylesheet/badge.mjs +14 -8
  66. package/source/components/stylesheet/border.mjs +14 -8
  67. package/source/components/stylesheet/button.mjs +14 -8
  68. package/source/components/stylesheet/card.mjs +14 -8
  69. package/source/components/stylesheet/color.mjs +14 -8
  70. package/source/components/stylesheet/common.mjs +14 -8
  71. package/source/components/stylesheet/control.mjs +14 -8
  72. package/source/components/stylesheet/data-grid.mjs +14 -8
  73. package/source/components/stylesheet/display.mjs +14 -8
  74. package/source/components/stylesheet/floating-ui.mjs +14 -8
  75. package/source/components/stylesheet/form.mjs +14 -8
  76. package/source/components/stylesheet/host.mjs +14 -8
  77. package/source/components/stylesheet/icons.mjs +14 -8
  78. package/source/components/stylesheet/link.mjs +14 -8
  79. package/source/components/stylesheet/normalize.mjs +14 -8
  80. package/source/components/stylesheet/popper.mjs +14 -8
  81. package/source/components/stylesheet/property.mjs +14 -8
  82. package/source/components/stylesheet/ripple.mjs +14 -8
  83. package/source/components/stylesheet/skeleton.mjs +14 -8
  84. package/source/components/stylesheet/space.mjs +14 -8
  85. package/source/components/stylesheet/spinner.mjs +14 -8
  86. package/source/components/stylesheet/table.mjs +14 -8
  87. package/source/components/stylesheet/theme.mjs +14 -8
  88. package/source/components/stylesheet/typography.mjs +14 -8
  89. package/source/components/tree-menu/stylesheet/tree-menu.mjs +14 -8
  90. package/source/data/datasource/server/restapi.mjs +1 -0
  91. package/source/data/transformer.mjs +6 -8
  92. package/source/dom/attributes.mjs +5 -5
  93. package/source/dom/customelement.mjs +2 -2
  94. package/source/dom/updater.mjs +697 -700
  95. package/source/dom/util.mjs +2 -2
  96. package/source/monster.mjs +0 -1
  97. package/source/types/noderecursiveiterator.mjs +9 -7
  98. package/source/types/version.mjs +1 -1
  99. package/source/util/sleep.mjs +3 -4
  100. package/test/cases/monster.mjs +1 -1
@@ -5,34 +5,34 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import {internalSymbol} from "../constants.mjs";
9
- import {diff} from "../data/diff.mjs";
10
- import {Pathfinder} from "../data/pathfinder.mjs";
11
- import {Pipe} from "../data/pipe.mjs";
8
+ import { internalSymbol } from "../constants.mjs";
9
+ import { diff } from "../data/diff.mjs";
10
+ import { Pathfinder } from "../data/pathfinder.mjs";
11
+ import { Pipe } from "../data/pipe.mjs";
12
12
  import {
13
- ATTRIBUTE_ERRORMESSAGE,
14
- ATTRIBUTE_UPDATER_ATTRIBUTES,
15
- ATTRIBUTE_UPDATER_BIND,
16
- ATTRIBUTE_UPDATER_INSERT,
17
- ATTRIBUTE_UPDATER_INSERT_REFERENCE,
18
- ATTRIBUTE_UPDATER_REMOVE,
19
- ATTRIBUTE_UPDATER_REPLACE,
20
- ATTRIBUTE_UPDATER_SELECT_THIS,
13
+ ATTRIBUTE_ERRORMESSAGE,
14
+ ATTRIBUTE_UPDATER_ATTRIBUTES,
15
+ ATTRIBUTE_UPDATER_BIND,
16
+ ATTRIBUTE_UPDATER_INSERT,
17
+ ATTRIBUTE_UPDATER_INSERT_REFERENCE,
18
+ ATTRIBUTE_UPDATER_REMOVE,
19
+ ATTRIBUTE_UPDATER_REPLACE,
20
+ ATTRIBUTE_UPDATER_SELECT_THIS,
21
21
  } from "./constants.mjs";
22
22
 
23
- import {Base} from "../types/base.mjs";
24
- import {isArray, isInstance, isIterable} from "../types/is.mjs";
25
- import {Observer} from "../types/observer.mjs";
26
- import {ProxyObserver} from "../types/proxyobserver.mjs";
27
- import {validateArray, validateInstance} from "../types/validate.mjs";
28
- import {Sleep} from "../util/sleep.mjs";
29
- import {clone} from "../util/clone.mjs";
30
- import {trimSpaces} from "../util/trimspaces.mjs";
31
- import {addToObjectLink} from "./attributes.mjs";
32
- import {findTargetElementFromEvent} from "./events.mjs";
33
- import {findDocumentTemplate} from "./template.mjs";
23
+ import { Base } from "../types/base.mjs";
24
+ import { isArray, isInstance, isIterable } from "../types/is.mjs";
25
+ import { Observer } from "../types/observer.mjs";
26
+ import { ProxyObserver } from "../types/proxyobserver.mjs";
27
+ import { validateArray, validateInstance } from "../types/validate.mjs";
28
+ import { Sleep } from "../util/sleep.mjs";
29
+ import { clone } from "../util/clone.mjs";
30
+ import { trimSpaces } from "../util/trimspaces.mjs";
31
+ import { addToObjectLink } from "./attributes.mjs";
32
+ import { findTargetElementFromEvent } from "./events.mjs";
33
+ import { findDocumentTemplate } from "./template.mjs";
34
34
 
35
- export {Updater, addObjectWithUpdaterToElement};
35
+ export { Updater, addObjectWithUpdaterToElement };
36
36
 
37
37
  /**
38
38
  * The updater class connects an object with the dom. In this way, structures and contents in the DOM can be programmatically adapted via attributes.
@@ -57,183 +57,182 @@ export {Updater, addObjectWithUpdaterToElement};
57
57
  * @summary The updater class connects an object with the dom
58
58
  */
59
59
  class Updater extends Base {
60
- /**
61
- * @since 1.8.0
62
- * @param {HTMLElement} element
63
- * @param {object|ProxyObserver|undefined} subject
64
- * @throws {TypeError} value is not a object
65
- * @throws {TypeError} value is not an instance of HTMLElement
66
- * @see {@link Monster.DOM.findDocumentTemplate}
67
- */
68
- constructor(element, subject) {
69
- super();
70
-
71
- /**
72
- * @type {HTMLElement}
73
- */
74
- if (subject === undefined) subject = {};
75
- if (!isInstance(subject, ProxyObserver)) {
76
- subject = new ProxyObserver(subject);
77
- }
78
-
79
- this[internalSymbol] = {
80
- element: validateInstance(element, HTMLElement),
81
- last: {},
82
- callbacks: new Map(),
83
- eventTypes: ["keyup", "click", "change", "drop", "touchend", "input"],
84
- subject: subject,
85
- };
86
-
87
- this[internalSymbol].callbacks.set(
88
- "checkstate",
89
- getCheckStateCallback.call(this),
90
- );
91
-
92
- this[internalSymbol].subject.attachObserver(
93
- new Observer(() => {
94
- const s = this[internalSymbol].subject.getRealSubject();
95
-
96
- const diffResult = diff(this[internalSymbol].last, s);
97
- this[internalSymbol].last = clone(s);
98
-
99
- let promises = [];
100
-
101
- for (const [, change] of Object.entries(diffResult)) {
102
- promises.push(
103
- Sleep(1).then(() => {
104
- removeElement.call(this, change);
105
- insertElement.call(this, change);
106
- updateContent.call(this, change);
107
- updateAttributes.call(this, change);
108
- })
109
- )
110
- }
111
-
112
- return Promise.all(promises)
113
-
114
- }),
115
- );
116
- }
117
-
118
- /**
119
- * Defaults: 'keyup', 'click', 'change', 'drop', 'touchend'
120
- *
121
- * @see {@link https://developer.mozilla.org/de/docs/Web/Events}
122
- * @since 1.9.0
123
- * @param {Array} types
124
- * @return {Updater}
125
- */
126
- setEventTypes(types) {
127
- this[internalSymbol].eventTypes = validateArray(types);
128
- return this;
129
- }
130
-
131
- /**
132
- * With this method, the eventlisteners are hooked in and the magic begins.
133
- *
134
- * ```
135
- * updater.run().then(() => {
136
- * updater.enableEventProcessing();
137
- * });
138
- * ```
139
- *
140
- * @since 1.9.0
141
- * @return {Updater}
142
- * @throws {Error} the bind argument must start as a value with a path
143
- */
144
- enableEventProcessing() {
145
- this.disableEventProcessing();
146
-
147
- for (const type of this[internalSymbol].eventTypes) {
148
- // @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
149
- this[internalSymbol].element.addEventListener(
150
- type,
151
- getControlEventHandler.call(this),
152
- {
153
- capture: true,
154
- passive: true,
155
- },
156
- );
157
- }
158
-
159
- return this;
160
- }
161
-
162
- /**
163
- * This method turns off the magic or who loves it more profane it removes the eventListener.
164
- *
165
- * @since 1.9.0
166
- * @return {Updater}
167
- */
168
- disableEventProcessing() {
169
- for (const type of this[internalSymbol].eventTypes) {
170
- this[internalSymbol].element.removeEventListener(
171
- type,
172
- getControlEventHandler.call(this),
173
- );
174
- }
175
-
176
- return this;
177
- }
178
-
179
- /**
180
- * The run method must be called for the update to start working.
181
- * The method ensures that changes are detected.
182
- *
183
- * ```
184
- * updater.run().then(() => {
185
- * updater.enableEventProcessing();
186
- * });
187
- * ```
188
- *
189
- * @summary Let the magic begin
190
- * @return {Promise}
191
- */
192
- run() {
193
- // the key __init__has no further meaning and is only
194
- // used to create the diff for empty objects.
195
- this[internalSymbol].last = {__init__: true};
196
- return this[internalSymbol].subject.notifyObservers();
197
- }
198
-
199
- /**
200
- * Gets the values of bound elements and changes them in subject
201
- *
202
- * @since 1.27.0
203
- * @return {Monster.DOM.Updater}
204
- */
205
- retrieve() {
206
- retrieveFromBindings.call(this);
207
- return this;
208
- }
209
-
210
- /**
211
- * If you have passed a ProxyObserver in the constructor, you will get the object that the ProxyObserver manages here.
212
- * However, if you passed a simple object, here you will get a proxy for that object.
213
- *
214
- * For changes the ProxyObserver must be used.
215
- *
216
- * @since 1.8.0
217
- * @return {Proxy}
218
- */
219
- getSubject() {
220
- return this[internalSymbol].subject.getSubject();
221
- }
222
-
223
- /**
224
- * This method can be used to register commands that can be called via call: instruction.
225
- * This can be used to provide a pipe with its own functionality.
226
- *
227
- * @param {string} name
228
- * @param {function} callback
229
- * @returns {Transformer}
230
- * @throws {TypeError} value is not a string
231
- * @throws {TypeError} value is not a function
232
- */
233
- setCallback(name, callback) {
234
- this[internalSymbol].callbacks.set(name, callback);
235
- return this;
236
- }
60
+ /**
61
+ * @since 1.8.0
62
+ * @param {HTMLElement} element
63
+ * @param {object|ProxyObserver|undefined} subject
64
+ * @throws {TypeError} value is not a object
65
+ * @throws {TypeError} value is not an instance of HTMLElement
66
+ * @see {@link Monster.DOM.findDocumentTemplate}
67
+ */
68
+ constructor(element, subject) {
69
+ super();
70
+
71
+ /**
72
+ * @type {HTMLElement}
73
+ */
74
+ if (subject === undefined) subject = {};
75
+ if (!isInstance(subject, ProxyObserver)) {
76
+ subject = new ProxyObserver(subject);
77
+ }
78
+
79
+ this[internalSymbol] = {
80
+ element: validateInstance(element, HTMLElement),
81
+ last: {},
82
+ callbacks: new Map(),
83
+ eventTypes: ["keyup", "click", "change", "drop", "touchend", "input"],
84
+ subject: subject,
85
+ };
86
+
87
+ this[internalSymbol].callbacks.set(
88
+ "checkstate",
89
+ getCheckStateCallback.call(this),
90
+ );
91
+
92
+ this[internalSymbol].subject.attachObserver(
93
+ new Observer(() => {
94
+ const s = this[internalSymbol].subject.getRealSubject();
95
+
96
+ const diffResult = diff(this[internalSymbol].last, s);
97
+ this[internalSymbol].last = clone(s);
98
+
99
+ const promises = [];
100
+
101
+ for (const [, change] of Object.entries(diffResult)) {
102
+ promises.push(
103
+ Sleep(1).then(() => {
104
+ removeElement.call(this, change);
105
+ insertElement.call(this, change);
106
+ updateContent.call(this, change);
107
+ updateAttributes.call(this, change);
108
+ }),
109
+ );
110
+ }
111
+
112
+ return Promise.all(promises);
113
+ }),
114
+ );
115
+ }
116
+
117
+ /**
118
+ * Defaults: 'keyup', 'click', 'change', 'drop', 'touchend'
119
+ *
120
+ * @see {@link https://developer.mozilla.org/de/docs/Web/Events}
121
+ * @since 1.9.0
122
+ * @param {Array} types
123
+ * @return {Updater}
124
+ */
125
+ setEventTypes(types) {
126
+ this[internalSymbol].eventTypes = validateArray(types);
127
+ return this;
128
+ }
129
+
130
+ /**
131
+ * With this method, the eventlisteners are hooked in and the magic begins.
132
+ *
133
+ * ```
134
+ * updater.run().then(() => {
135
+ * updater.enableEventProcessing();
136
+ * });
137
+ * ```
138
+ *
139
+ * @since 1.9.0
140
+ * @return {Updater}
141
+ * @throws {Error} the bind argument must start as a value with a path
142
+ */
143
+ enableEventProcessing() {
144
+ this.disableEventProcessing();
145
+
146
+ for (const type of this[internalSymbol].eventTypes) {
147
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
148
+ this[internalSymbol].element.addEventListener(
149
+ type,
150
+ getControlEventHandler.call(this),
151
+ {
152
+ capture: true,
153
+ passive: true,
154
+ },
155
+ );
156
+ }
157
+
158
+ return this;
159
+ }
160
+
161
+ /**
162
+ * This method turns off the magic or who loves it more profane it removes the eventListener.
163
+ *
164
+ * @since 1.9.0
165
+ * @return {Updater}
166
+ */
167
+ disableEventProcessing() {
168
+ for (const type of this[internalSymbol].eventTypes) {
169
+ this[internalSymbol].element.removeEventListener(
170
+ type,
171
+ getControlEventHandler.call(this),
172
+ );
173
+ }
174
+
175
+ return this;
176
+ }
177
+
178
+ /**
179
+ * The run method must be called for the update to start working.
180
+ * The method ensures that changes are detected.
181
+ *
182
+ * ```
183
+ * updater.run().then(() => {
184
+ * updater.enableEventProcessing();
185
+ * });
186
+ * ```
187
+ *
188
+ * @summary Let the magic begin
189
+ * @return {Promise}
190
+ */
191
+ run() {
192
+ // the key __init__has no further meaning and is only
193
+ // used to create the diff for empty objects.
194
+ this[internalSymbol].last = { __init__: true };
195
+ return this[internalSymbol].subject.notifyObservers();
196
+ }
197
+
198
+ /**
199
+ * Gets the values of bound elements and changes them in subject
200
+ *
201
+ * @since 1.27.0
202
+ * @return {Monster.DOM.Updater}
203
+ */
204
+ retrieve() {
205
+ retrieveFromBindings.call(this);
206
+ return this;
207
+ }
208
+
209
+ /**
210
+ * If you have passed a ProxyObserver in the constructor, you will get the object that the ProxyObserver manages here.
211
+ * However, if you passed a simple object, here you will get a proxy for that object.
212
+ *
213
+ * For changes the ProxyObserver must be used.
214
+ *
215
+ * @since 1.8.0
216
+ * @return {Proxy}
217
+ */
218
+ getSubject() {
219
+ return this[internalSymbol].subject.getSubject();
220
+ }
221
+
222
+ /**
223
+ * This method can be used to register commands that can be called via call: instruction.
224
+ * This can be used to provide a pipe with its own functionality.
225
+ *
226
+ * @param {string} name
227
+ * @param {function} callback
228
+ * @returns {Transformer}
229
+ * @throws {TypeError} value is not a string
230
+ * @throws {TypeError} value is not a function
231
+ */
232
+ setCallback(name, callback) {
233
+ this[internalSymbol].callbacks.set(name, callback);
234
+ return this;
235
+ }
237
236
  }
238
237
 
239
238
  /**
@@ -244,20 +243,20 @@ class Updater extends Base {
244
243
  * @this Updater
245
244
  */
246
245
  function getCheckStateCallback() {
247
- return function (current) {
248
- // this is a reference to the current object (therefore no array function here)
249
- if (this instanceof HTMLInputElement) {
250
- if (["radio", "checkbox"].indexOf(this.type) !== -1) {
251
- return `${this.value}` === `${current}` ? "true" : undefined;
252
- }
253
- } else if (this instanceof HTMLOptionElement) {
254
- if (isArray(current) && current.indexOf(this.value) !== -1) {
255
- return "true";
256
- }
257
-
258
- return undefined;
259
- }
260
- };
246
+ return function (current) {
247
+ // this is a reference to the current object (therefore no array function here)
248
+ if (this instanceof HTMLInputElement) {
249
+ if (["radio", "checkbox"].indexOf(this.type) !== -1) {
250
+ return `${this.value}` === `${current}` ? "true" : undefined;
251
+ }
252
+ } else if (this instanceof HTMLOptionElement) {
253
+ if (isArray(current) && current.indexOf(this.value) !== -1) {
254
+ return "true";
255
+ }
256
+
257
+ return undefined;
258
+ }
259
+ };
261
260
  }
262
261
 
263
262
  /**
@@ -272,26 +271,26 @@ const symbol = Symbol("@schukai/monster/updater@@EventHandler");
272
271
  * @throws {Error} the bind argument must start as a value with a path
273
272
  */
274
273
  function getControlEventHandler() {
275
- if (this[symbol]) {
276
- return this[symbol];
277
- }
278
-
279
- /**
280
- * @throws {Error} the bind argument must start as a value with a path.
281
- * @throws {Error} unsupported object
282
- * @param {Event} event
283
- */
284
- this[symbol] = (event) => {
285
- const element = findTargetElementFromEvent(event, ATTRIBUTE_UPDATER_BIND);
286
-
287
- if (element === undefined) {
288
- return;
289
- }
290
-
291
- retrieveAndSetValue.call(this, element);
292
- };
293
-
294
- return this[symbol];
274
+ if (this[symbol]) {
275
+ return this[symbol];
276
+ }
277
+
278
+ /**
279
+ * @throws {Error} the bind argument must start as a value with a path.
280
+ * @throws {Error} unsupported object
281
+ * @param {Event} event
282
+ */
283
+ this[symbol] = (event) => {
284
+ const element = findTargetElementFromEvent(event, ATTRIBUTE_UPDATER_BIND);
285
+
286
+ if (element === undefined) {
287
+ return;
288
+ }
289
+
290
+ retrieveAndSetValue.call(this, element);
291
+ };
292
+
293
+ return this[symbol];
295
294
  }
296
295
 
297
296
  /**
@@ -302,70 +301,70 @@ function getControlEventHandler() {
302
301
  * @private
303
302
  */
304
303
  function retrieveAndSetValue(element) {
305
- const pathfinder = new Pathfinder(this[internalSymbol].subject.getSubject());
306
-
307
- let path = element.getAttribute(ATTRIBUTE_UPDATER_BIND);
308
- if (path === null)
309
- throw new Error("the bind argument must start as a value with a path");
310
-
311
- if (path.indexOf("path:") !== 0) {
312
- throw new Error("the bind argument must start as a value with a path");
313
- }
314
-
315
- path = path.substring(5);
316
-
317
- let value;
318
-
319
- if (element instanceof HTMLInputElement) {
320
- switch (element.type) {
321
- case "checkbox":
322
- value = element.checked ? element.value : undefined;
323
- break;
324
- default:
325
- value = element.value;
326
- break;
327
- }
328
- } else if (element instanceof HTMLTextAreaElement) {
329
- value = element.value;
330
- } else if (element instanceof HTMLSelectElement) {
331
- switch (element.type) {
332
- case "select-one":
333
- value = element.value;
334
- break;
335
- case "select-multiple":
336
- value = element.value;
337
-
338
- let options = element?.selectedOptions;
339
- if (options === undefined)
340
- options = element.querySelectorAll(":scope option:checked");
341
- value = Array.from(options).map(({value}) => value);
342
-
343
- break;
344
- }
345
-
346
- // values from customelements
347
- } else if (
348
- (element?.constructor?.prototype &&
349
- !!Object.getOwnPropertyDescriptor(
350
- element.constructor.prototype,
351
- "value",
352
- )?.["get"]) ||
353
- element.hasOwnProperty("value")
354
- ) {
355
- value = element?.["value"];
356
- } else {
357
- throw new Error("unsupported object");
358
- }
359
-
360
- const copy = clone(this[internalSymbol].subject.getRealSubject());
361
- const pf = new Pathfinder(copy);
362
- pf.setVia(path, value);
363
-
364
- const diffResult = diff(copy, this[internalSymbol].subject.getRealSubject());
365
-
366
- if (diffResult.length > 0) {
367
- pathfinder.setVia(path, value);
368
- }
304
+ const pathfinder = new Pathfinder(this[internalSymbol].subject.getSubject());
305
+
306
+ let path = element.getAttribute(ATTRIBUTE_UPDATER_BIND);
307
+ if (path === null)
308
+ throw new Error("the bind argument must start as a value with a path");
309
+
310
+ if (path.indexOf("path:") !== 0) {
311
+ throw new Error("the bind argument must start as a value with a path");
312
+ }
313
+
314
+ path = path.substring(5);
315
+
316
+ let value;
317
+
318
+ if (element instanceof HTMLInputElement) {
319
+ switch (element.type) {
320
+ case "checkbox":
321
+ value = element.checked ? element.value : undefined;
322
+ break;
323
+ default:
324
+ value = element.value;
325
+ break;
326
+ }
327
+ } else if (element instanceof HTMLTextAreaElement) {
328
+ value = element.value;
329
+ } else if (element instanceof HTMLSelectElement) {
330
+ switch (element.type) {
331
+ case "select-one":
332
+ value = element.value;
333
+ break;
334
+ case "select-multiple":
335
+ value = element.value;
336
+
337
+ let options = element?.selectedOptions;
338
+ if (options === undefined)
339
+ options = element.querySelectorAll(":scope option:checked");
340
+ value = Array.from(options).map(({ value }) => value);
341
+
342
+ break;
343
+ }
344
+
345
+ // values from customelements
346
+ } else if (
347
+ (element?.constructor?.prototype &&
348
+ !!Object.getOwnPropertyDescriptor(
349
+ element.constructor.prototype,
350
+ "value",
351
+ )?.["get"]) ||
352
+ element.hasOwnProperty("value")
353
+ ) {
354
+ value = element?.["value"];
355
+ } else {
356
+ throw new Error("unsupported object");
357
+ }
358
+
359
+ const copy = clone(this[internalSymbol].subject.getRealSubject());
360
+ const pf = new Pathfinder(copy);
361
+ pf.setVia(path, value);
362
+
363
+ const diffResult = diff(copy, this[internalSymbol].subject.getRealSubject());
364
+
365
+ if (diffResult.length > 0) {
366
+ pathfinder.setVia(path, value);
367
+ }
369
368
  }
370
369
 
371
370
  /**
@@ -375,15 +374,15 @@ function retrieveAndSetValue(element) {
375
374
  * @private
376
375
  */
377
376
  function retrieveFromBindings() {
378
- if (this[internalSymbol].element.matches(`[${ATTRIBUTE_UPDATER_BIND}]`)) {
379
- retrieveAndSetValue.call(this, this[internalSymbol].element);
380
- }
381
-
382
- for (const [, element] of this[internalSymbol].element
383
- .querySelectorAll(`[${ATTRIBUTE_UPDATER_BIND}]`)
384
- .entries()) {
385
- retrieveAndSetValue.call(this, element);
386
- }
377
+ if (this[internalSymbol].element.matches(`[${ATTRIBUTE_UPDATER_BIND}]`)) {
378
+ retrieveAndSetValue.call(this, this[internalSymbol].element);
379
+ }
380
+
381
+ for (const [, element] of this[internalSymbol].element
382
+ .querySelectorAll(`[${ATTRIBUTE_UPDATER_BIND}]`)
383
+ .entries()) {
384
+ retrieveAndSetValue.call(this, element);
385
+ }
387
386
  }
388
387
 
389
388
  /**
@@ -394,11 +393,11 @@ function retrieveFromBindings() {
394
393
  * @return {void}
395
394
  */
396
395
  function removeElement(change) {
397
- for (const [, element] of this[internalSymbol].element
398
- .querySelectorAll(`:scope [${ATTRIBUTE_UPDATER_REMOVE}]`)
399
- .entries()) {
400
- element.parentNode.removeChild(element);
401
- }
396
+ for (const [, element] of this[internalSymbol].element
397
+ .querySelectorAll(`:scope [${ATTRIBUTE_UPDATER_REMOVE}]`)
398
+ .entries()) {
399
+ element.parentNode.removeChild(element);
400
+ }
402
401
  }
403
402
 
404
403
  /**
@@ -414,135 +413,133 @@ function removeElement(change) {
414
413
  * @this Updater
415
414
  */
416
415
  function insertElement(change) {
417
- const subject = this[internalSymbol].subject.getRealSubject();
416
+ const subject = this[internalSymbol].subject.getRealSubject();
418
417
 
419
- const mem = new WeakSet();
420
- let wd = 0;
418
+ const mem = new WeakSet();
419
+ let wd = 0;
421
420
 
422
- const container = this[internalSymbol].element;
421
+ const container = this[internalSymbol].element;
423
422
 
424
- while (true) {
425
- let found = false;
426
- wd++;
427
-
428
- const p = clone(change?.["path"]);
429
- if (!isArray(p)) return;
430
-
431
- while (p.length > 0) {
432
- const current = p.join(".");
433
-
434
- let iterator = new Set();
435
- const query = `[${ATTRIBUTE_UPDATER_INSERT}*="path:${current}"]`;
436
-
437
- const e = container.querySelectorAll(query);
438
-
439
- if (e.length > 0) {
440
- iterator = new Set([...e]);
441
- }
442
-
443
- if (container.matches(query)) {
444
- iterator.add(container);
445
- }
446
-
447
- for (const [, containerElement] of iterator.entries()) {
448
- if (mem.has(containerElement)) continue;
449
- mem.add(containerElement);
450
-
451
- found = true;
452
-
453
- const attributes = containerElement.getAttribute(
454
- ATTRIBUTE_UPDATER_INSERT,
455
- );
456
- if (attributes === null) continue;
457
-
458
- const def = trimSpaces(attributes);
459
- const i = def.indexOf(" ");
460
- const key = trimSpaces(def.substr(0, i));
461
- const refPrefix = `${key}-`;
462
- const cmd = trimSpaces(def.substr(i));
463
-
464
- // this case is actually excluded by the query but is nevertheless checked again here
465
- if (cmd.indexOf("|") > 0) {
466
- throw new Error("pipes are not allowed when cloning a node.");
467
- }
468
-
469
- const pipe = new Pipe(cmd);
470
- this[internalSymbol].callbacks.forEach((f, n) => {
471
- pipe.setCallback(n, f);
472
- });
473
-
474
- let value;
475
- try {
476
- containerElement.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
477
- value = pipe.run(subject);
478
- } catch (e) {
479
- containerElement.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
480
- }
481
-
482
- const dataPath = cmd.split(":").pop();
483
-
484
- let insertPoint;
485
- if (containerElement.hasChildNodes()) {
486
- insertPoint = containerElement.lastChild;
487
- }
488
-
489
- if (!isIterable(value)) {
490
- throw new Error("the value is not iterable");
491
- }
492
-
493
- const available = new Set();
494
-
495
- for (const [i, obj] of Object.entries(value)) {
496
- const ref = refPrefix + i;
497
- const currentPath = `${dataPath}.${i}`;
498
-
499
- available.add(ref);
500
- const refElement = containerElement.querySelector(
501
- `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}="${ref}"]`,
502
- );
503
-
504
- if (refElement instanceof HTMLElement) {
505
- insertPoint = refElement;
506
- continue;
507
- }
508
-
509
- appendNewDocumentFragment(containerElement, key, ref, currentPath);
510
- }
511
-
512
- const nodes = containerElement.querySelectorAll(
513
- `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}*="${refPrefix}"]`,
514
- );
515
-
516
- for (const [, node] of Object.entries(nodes)) {
517
- if (
518
- !available.has(
519
- node.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE),
520
- )
521
- ) {
522
- try {
523
- containerElement.removeChild(node);
524
- } catch (e) {
525
- containerElement.setAttribute(
526
- ATTRIBUTE_ERRORMESSAGE,
527
- `${containerElement.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
528
- e.message
529
- }`.trim(),
530
- );
531
- }
532
- }
533
-
534
- }
535
-
536
- }
537
-
538
- p.pop();
539
- }
540
-
541
- if (found === false) break;
542
- if (wd++ > 200) {
543
- throw new Error("the maximum depth for the recursion is reached.");
544
- }
545
- }
423
+ while (true) {
424
+ let found = false;
425
+ wd++;
426
+
427
+ const p = clone(change?.["path"]);
428
+ if (!isArray(p)) return;
429
+
430
+ while (p.length > 0) {
431
+ const current = p.join(".");
432
+
433
+ let iterator = new Set();
434
+ const query = `[${ATTRIBUTE_UPDATER_INSERT}*="path:${current}"]`;
435
+
436
+ const e = container.querySelectorAll(query);
437
+
438
+ if (e.length > 0) {
439
+ iterator = new Set([...e]);
440
+ }
441
+
442
+ if (container.matches(query)) {
443
+ iterator.add(container);
444
+ }
445
+
446
+ for (const [, containerElement] of iterator.entries()) {
447
+ if (mem.has(containerElement)) continue;
448
+ mem.add(containerElement);
449
+
450
+ found = true;
451
+
452
+ const attributes = containerElement.getAttribute(
453
+ ATTRIBUTE_UPDATER_INSERT,
454
+ );
455
+ if (attributes === null) continue;
456
+
457
+ const def = trimSpaces(attributes);
458
+ const i = def.indexOf(" ");
459
+ const key = trimSpaces(def.substr(0, i));
460
+ const refPrefix = `${key}-`;
461
+ const cmd = trimSpaces(def.substr(i));
462
+
463
+ // this case is actually excluded by the query but is nevertheless checked again here
464
+ if (cmd.indexOf("|") > 0) {
465
+ throw new Error("pipes are not allowed when cloning a node.");
466
+ }
467
+
468
+ const pipe = new Pipe(cmd);
469
+ this[internalSymbol].callbacks.forEach((f, n) => {
470
+ pipe.setCallback(n, f);
471
+ });
472
+
473
+ let value;
474
+ try {
475
+ containerElement.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
476
+ value = pipe.run(subject);
477
+ } catch (e) {
478
+ containerElement.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
479
+ }
480
+
481
+ const dataPath = cmd.split(":").pop();
482
+
483
+ let insertPoint;
484
+ if (containerElement.hasChildNodes()) {
485
+ insertPoint = containerElement.lastChild;
486
+ }
487
+
488
+ if (!isIterable(value)) {
489
+ throw new Error("the value is not iterable");
490
+ }
491
+
492
+ const available = new Set();
493
+
494
+ for (const [i, obj] of Object.entries(value)) {
495
+ const ref = refPrefix + i;
496
+ const currentPath = `${dataPath}.${i}`;
497
+
498
+ available.add(ref);
499
+ const refElement = containerElement.querySelector(
500
+ `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}="${ref}"]`,
501
+ );
502
+
503
+ if (refElement instanceof HTMLElement) {
504
+ insertPoint = refElement;
505
+ continue;
506
+ }
507
+
508
+ appendNewDocumentFragment(containerElement, key, ref, currentPath);
509
+ }
510
+
511
+ const nodes = containerElement.querySelectorAll(
512
+ `[${ATTRIBUTE_UPDATER_INSERT_REFERENCE}*="${refPrefix}"]`,
513
+ );
514
+
515
+ for (const [, node] of Object.entries(nodes)) {
516
+ if (
517
+ !available.has(
518
+ node.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE),
519
+ )
520
+ ) {
521
+ try {
522
+ containerElement.removeChild(node);
523
+ } catch (e) {
524
+ containerElement.setAttribute(
525
+ ATTRIBUTE_ERRORMESSAGE,
526
+ `${containerElement.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
527
+ e.message
528
+ }`.trim(),
529
+ );
530
+ }
531
+ }
532
+ }
533
+ }
534
+
535
+ p.pop();
536
+ }
537
+
538
+ if (found === false) break;
539
+ if (wd++ > 200) {
540
+ throw new Error("the maximum depth for the recursion is reached.");
541
+ }
542
+ }
546
543
  }
547
544
 
548
545
  /**
@@ -557,17 +554,17 @@ function insertElement(change) {
557
554
  * @throws {Error} no template was found with the specified key.
558
555
  */
559
556
  function appendNewDocumentFragment(container, key, ref, path) {
560
- const template = findDocumentTemplate(key, container);
557
+ const template = findDocumentTemplate(key, container);
561
558
 
562
- const nodes = template.createDocumentFragment();
563
- for (const [, node] of Object.entries(nodes.childNodes)) {
564
- if (node instanceof HTMLElement) {
565
- applyRecursive(node, key, path);
566
- node.setAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE, ref);
567
- }
559
+ const nodes = template.createDocumentFragment();
560
+ for (const [, node] of Object.entries(nodes.childNodes)) {
561
+ if (node instanceof HTMLElement) {
562
+ applyRecursive(node, key, path);
563
+ node.setAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE, ref);
564
+ }
568
565
 
569
- container.appendChild(node);
570
- }
566
+ container.appendChild(node);
567
+ }
571
568
  }
572
569
 
573
570
  /**
@@ -580,27 +577,27 @@ function appendNewDocumentFragment(container, key, ref, path) {
580
577
  * @return {void}
581
578
  */
582
579
  function applyRecursive(node, key, path) {
583
- if (node instanceof HTMLElement) {
584
- if (node.hasAttribute(ATTRIBUTE_UPDATER_REPLACE)) {
585
- const value = node.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
586
- node.setAttribute(
587
- ATTRIBUTE_UPDATER_REPLACE,
588
- value.replaceAll(`path:${key}`, `path:${path}`),
589
- );
590
- }
591
-
592
- if (node.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
593
- const value = node.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
594
- node.setAttribute(
595
- ATTRIBUTE_UPDATER_ATTRIBUTES,
596
- value.replaceAll(`path:${key}`, `path:${path}`),
597
- );
598
- }
599
-
600
- for (const [, child] of Object.entries(node.childNodes)) {
601
- applyRecursive(child, key, path);
602
- }
603
- }
580
+ if (node instanceof HTMLElement) {
581
+ if (node.hasAttribute(ATTRIBUTE_UPDATER_REPLACE)) {
582
+ const value = node.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
583
+ node.setAttribute(
584
+ ATTRIBUTE_UPDATER_REPLACE,
585
+ value.replaceAll(`path:${key}`, `path:${path}`),
586
+ );
587
+ }
588
+
589
+ if (node.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
590
+ const value = node.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
591
+ node.setAttribute(
592
+ ATTRIBUTE_UPDATER_ATTRIBUTES,
593
+ value.replaceAll(`path:${key}`, `path:${path}`),
594
+ );
595
+ }
596
+
597
+ for (const [, child] of Object.entries(node.childNodes)) {
598
+ applyRecursive(child, key, path);
599
+ }
600
+ }
604
601
  }
605
602
 
606
603
  /**
@@ -612,19 +609,19 @@ function applyRecursive(node, key, path) {
612
609
  * @this Updater
613
610
  */
614
611
  function updateContent(change) {
615
- const subject = this[internalSymbol].subject.getRealSubject();
616
-
617
- const p = clone(change?.["path"]);
618
- runUpdateContent.call(this, this[internalSymbol].element, p, subject);
619
-
620
- const slots = this[internalSymbol].element.querySelectorAll("slot");
621
- if (slots.length > 0) {
622
- for (const [, slot] of Object.entries(slots)) {
623
- for (const [, element] of Object.entries(slot.assignedNodes())) {
624
- runUpdateContent.call(this, element, p, subject);
625
- }
626
- }
627
- }
612
+ const subject = this[internalSymbol].subject.getRealSubject();
613
+
614
+ const p = clone(change?.["path"]);
615
+ runUpdateContent.call(this, this[internalSymbol].element, p, subject);
616
+
617
+ const slots = this[internalSymbol].element.querySelectorAll("slot");
618
+ if (slots.length > 0) {
619
+ for (const [, slot] of Object.entries(slots)) {
620
+ for (const [, element] of Object.entries(slot.assignedNodes())) {
621
+ runUpdateContent.call(this, element, p, subject);
622
+ }
623
+ }
624
+ }
628
625
  }
629
626
 
630
627
  /**
@@ -637,69 +634,69 @@ function updateContent(change) {
637
634
  * @return {void}
638
635
  */
639
636
  function runUpdateContent(container, parts, subject) {
640
- if (!isArray(parts)) return;
641
- if (!(container instanceof HTMLElement)) return;
642
- parts = clone(parts);
643
-
644
- const mem = new WeakSet();
645
-
646
- while (parts.length > 0) {
647
- const current = parts.join(".");
648
- parts.pop();
649
-
650
- // Unfortunately, static data is always changed as well, since it is not possible to react to changes here.
651
- const query = `[${ATTRIBUTE_UPDATER_REPLACE}^="path:${current}"], [${ATTRIBUTE_UPDATER_REPLACE}^="static:"], [${ATTRIBUTE_UPDATER_REPLACE}^="i18n:"]`;
652
- const e = container.querySelectorAll(`${query}`);
653
-
654
- const iterator = new Set([...e]);
655
-
656
- if (container.matches(query)) {
657
- iterator.add(container);
658
- }
659
-
660
- /**
661
- * @type {HTMLElement}
662
- */
663
- for (const [element] of iterator.entries()) {
664
- if (mem.has(element)) return;
665
- mem.add(element);
666
-
667
- const attributes = element.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
668
- const cmd = trimSpaces(attributes);
669
-
670
- const pipe = new Pipe(cmd);
671
- this[internalSymbol].callbacks.forEach((f, n) => {
672
- pipe.setCallback(n, f);
673
- });
674
-
675
- let value;
676
- try {
677
- element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
678
- value = pipe.run(subject);
679
- } catch (e) {
680
- element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
681
- }
682
-
683
- if (value instanceof HTMLElement) {
684
- while (element.firstChild) {
685
- element.removeChild(element.firstChild);
686
- }
687
-
688
- try {
689
- element.appendChild(value);
690
- } catch (e) {
691
- element.setAttribute(
692
- ATTRIBUTE_ERRORMESSAGE,
693
- `${element.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
694
- e.message
695
- }`.trim(),
696
- );
697
- }
698
- } else {
699
- element.innerHTML = value;
700
- }
701
- }
702
- }
637
+ if (!isArray(parts)) return;
638
+ if (!(container instanceof HTMLElement)) return;
639
+ parts = clone(parts);
640
+
641
+ const mem = new WeakSet();
642
+
643
+ while (parts.length > 0) {
644
+ const current = parts.join(".");
645
+ parts.pop();
646
+
647
+ // Unfortunately, static data is always changed as well, since it is not possible to react to changes here.
648
+ const query = `[${ATTRIBUTE_UPDATER_REPLACE}^="path:${current}"], [${ATTRIBUTE_UPDATER_REPLACE}^="static:"], [${ATTRIBUTE_UPDATER_REPLACE}^="i18n:"]`;
649
+ const e = container.querySelectorAll(`${query}`);
650
+
651
+ const iterator = new Set([...e]);
652
+
653
+ if (container.matches(query)) {
654
+ iterator.add(container);
655
+ }
656
+
657
+ /**
658
+ * @type {HTMLElement}
659
+ */
660
+ for (const [element] of iterator.entries()) {
661
+ if (mem.has(element)) return;
662
+ mem.add(element);
663
+
664
+ const attributes = element.getAttribute(ATTRIBUTE_UPDATER_REPLACE);
665
+ const cmd = trimSpaces(attributes);
666
+
667
+ const pipe = new Pipe(cmd);
668
+ this[internalSymbol].callbacks.forEach((f, n) => {
669
+ pipe.setCallback(n, f);
670
+ });
671
+
672
+ let value;
673
+ try {
674
+ element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
675
+ value = pipe.run(subject);
676
+ } catch (e) {
677
+ element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
678
+ }
679
+
680
+ if (value instanceof HTMLElement) {
681
+ while (element.firstChild) {
682
+ element.removeChild(element.firstChild);
683
+ }
684
+
685
+ try {
686
+ element.appendChild(value);
687
+ } catch (e) {
688
+ element.setAttribute(
689
+ ATTRIBUTE_ERRORMESSAGE,
690
+ `${element.getAttribute(ATTRIBUTE_ERRORMESSAGE)}, ${
691
+ e.message
692
+ }`.trim(),
693
+ );
694
+ }
695
+ } else {
696
+ element.innerHTML = value;
697
+ }
698
+ }
699
+ }
703
700
  }
704
701
 
705
702
  /**
@@ -711,9 +708,9 @@ function runUpdateContent(container, parts, subject) {
711
708
  * @return {void}
712
709
  */
713
710
  function updateAttributes(change) {
714
- const subject = this[internalSymbol].subject.getRealSubject();
715
- const p = clone(change?.["path"]);
716
- runUpdateAttributes.call(this, this[internalSymbol].element, p, subject);
711
+ const subject = this[internalSymbol].subject.getRealSubject();
712
+ const p = clone(change?.["path"]);
713
+ runUpdateAttributes.call(this, this[internalSymbol].element, p, subject);
717
714
  }
718
715
 
719
716
  /**
@@ -725,70 +722,70 @@ function updateAttributes(change) {
725
722
  * @this Updater
726
723
  */
727
724
  function runUpdateAttributes(container, parts, subject) {
728
- if (!isArray(parts)) return;
729
- parts = clone(parts);
725
+ if (!isArray(parts)) return;
726
+ parts = clone(parts);
730
727
 
731
- const mem = new WeakSet();
728
+ const mem = new WeakSet();
732
729
 
733
- while (parts.length > 0) {
734
- const current = parts.join(".");
735
- parts.pop();
730
+ while (parts.length > 0) {
731
+ const current = parts.join(".");
732
+ parts.pop();
736
733
 
737
- let iterator = new Set();
734
+ let iterator = new Set();
738
735
 
739
- const query = `[${ATTRIBUTE_UPDATER_SELECT_THIS}][${ATTRIBUTE_UPDATER_ATTRIBUTES}], [${ATTRIBUTE_UPDATER_ATTRIBUTES}*="path:${current}"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="static:"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="i18n:"]`;
736
+ const query = `[${ATTRIBUTE_UPDATER_SELECT_THIS}][${ATTRIBUTE_UPDATER_ATTRIBUTES}], [${ATTRIBUTE_UPDATER_ATTRIBUTES}*="path:${current}"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="static:"], [${ATTRIBUTE_UPDATER_ATTRIBUTES}^="i18n:"]`;
740
737
 
741
- const e = container.querySelectorAll(query);
738
+ const e = container.querySelectorAll(query);
742
739
 
743
- if (e.length > 0) {
744
- iterator = new Set([...e]);
745
- }
740
+ if (e.length > 0) {
741
+ iterator = new Set([...e]);
742
+ }
746
743
 
747
- if (container.matches(query)) {
748
- iterator.add(container);
749
- }
744
+ if (container.matches(query)) {
745
+ iterator.add(container);
746
+ }
750
747
 
751
- for (const [element] of iterator.entries()) {
752
- if (mem.has(element)) return;
753
- mem.add(element);
748
+ for (const [element] of iterator.entries()) {
749
+ if (mem.has(element)) return;
750
+ mem.add(element);
754
751
 
755
- // this case occurs when the ATTRIBUTE_UPDATER_SELECT_THIS attribute is set
756
- if (!element.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
757
- continue;
758
- }
752
+ // this case occurs when the ATTRIBUTE_UPDATER_SELECT_THIS attribute is set
753
+ if (!element.hasAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES)) {
754
+ continue;
755
+ }
759
756
 
760
- const attributes = element.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
757
+ const attributes = element.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
761
758
 
762
- for (let [, def] of Object.entries(attributes.split(","))) {
763
- def = trimSpaces(def);
764
- const i = def.indexOf(" ");
765
- const name = trimSpaces(def.substr(0, i));
766
- const cmd = trimSpaces(def.substr(i));
759
+ for (let [, def] of Object.entries(attributes.split(","))) {
760
+ def = trimSpaces(def);
761
+ const i = def.indexOf(" ");
762
+ const name = trimSpaces(def.substr(0, i));
763
+ const cmd = trimSpaces(def.substr(i));
767
764
 
768
- const pipe = new Pipe(cmd);
765
+ const pipe = new Pipe(cmd);
769
766
 
770
- this[internalSymbol].callbacks.forEach((f, n) => {
771
- pipe.setCallback(n, f, element);
772
- });
767
+ this[internalSymbol].callbacks.forEach((f, n) => {
768
+ pipe.setCallback(n, f, element);
769
+ });
773
770
 
774
- let value;
775
- try {
776
- element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
777
- value = pipe.run(subject);
778
- } catch (e) {
779
- element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
780
- }
771
+ let value;
772
+ try {
773
+ element.removeAttribute(ATTRIBUTE_ERRORMESSAGE);
774
+ value = pipe.run(subject);
775
+ } catch (e) {
776
+ element.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.message);
777
+ }
781
778
 
782
- if (value === undefined) {
783
- element.removeAttribute(name);
784
- } else if (element.getAttribute(name) !== value) {
785
- element.setAttribute(name, value);
786
- }
779
+ if (value === undefined) {
780
+ element.removeAttribute(name);
781
+ } else if (element.getAttribute(name) !== value) {
782
+ element.setAttribute(name, value);
783
+ }
787
784
 
788
- handleInputControlAttributeUpdate.call(this, element, name, value);
789
- }
790
- }
791
- }
785
+ handleInputControlAttributeUpdate.call(this, element, name, value);
786
+ }
787
+ }
788
+ }
792
789
  }
793
790
 
794
791
  /**
@@ -801,66 +798,66 @@ function runUpdateAttributes(container, parts, subject) {
801
798
  */
802
799
 
803
800
  function handleInputControlAttributeUpdate(element, name, value) {
804
- if (element instanceof HTMLSelectElement) {
805
- switch (element.type) {
806
- case "select-multiple":
807
- for (const [index, opt] of Object.entries(element.options)) {
808
- if (value.indexOf(opt.value) !== -1) {
809
- opt.selected = true;
810
- } else {
811
- opt.selected = false;
812
- }
813
- }
814
-
815
- break;
816
- case "select-one":
817
- // Only one value may be selected
818
-
819
- for (const [index, opt] of Object.entries(element.options)) {
820
- if (opt.value === value) {
821
- element.selectedIndex = index;
822
- break;
823
- }
824
- }
825
-
826
- break;
827
- }
828
- } else if (element instanceof HTMLInputElement) {
829
- switch (element.type) {
830
- case "radio":
831
- if (name === "checked") {
832
- if (value !== undefined) {
833
- element.checked = true;
834
- } else {
835
- element.checked = false;
836
- }
837
- }
838
-
839
- break;
840
-
841
- case "checkbox":
842
- if (name === "checked") {
843
- if (value !== undefined) {
844
- element.checked = true;
845
- } else {
846
- element.checked = false;
847
- }
848
- }
849
-
850
- break;
851
- case "text":
852
- default:
853
- if (name === "value") {
854
- element.value = value === undefined ? "" : value;
855
- }
856
-
857
- break;
858
- }
859
- } else if (element instanceof HTMLTextAreaElement) {
860
- if (name === "value") {
861
- element.value = value === undefined ? "" : value;
862
- }
863
- }
801
+ if (element instanceof HTMLSelectElement) {
802
+ switch (element.type) {
803
+ case "select-multiple":
804
+ for (const [index, opt] of Object.entries(element.options)) {
805
+ if (value.indexOf(opt.value) !== -1) {
806
+ opt.selected = true;
807
+ } else {
808
+ opt.selected = false;
809
+ }
810
+ }
811
+
812
+ break;
813
+ case "select-one":
814
+ // Only one value may be selected
815
+
816
+ for (const [index, opt] of Object.entries(element.options)) {
817
+ if (opt.value === value) {
818
+ element.selectedIndex = index;
819
+ break;
820
+ }
821
+ }
822
+
823
+ break;
824
+ }
825
+ } else if (element instanceof HTMLInputElement) {
826
+ switch (element.type) {
827
+ case "radio":
828
+ if (name === "checked") {
829
+ if (value !== undefined) {
830
+ element.checked = true;
831
+ } else {
832
+ element.checked = false;
833
+ }
834
+ }
835
+
836
+ break;
837
+
838
+ case "checkbox":
839
+ if (name === "checked") {
840
+ if (value !== undefined) {
841
+ element.checked = true;
842
+ } else {
843
+ element.checked = false;
844
+ }
845
+ }
846
+
847
+ break;
848
+ case "text":
849
+ default:
850
+ if (name === "value") {
851
+ element.value = value === undefined ? "" : value;
852
+ }
853
+
854
+ break;
855
+ }
856
+ } else if (element instanceof HTMLTextAreaElement) {
857
+ if (name === "value") {
858
+ element.value = value === undefined ? "" : value;
859
+ }
860
+ }
864
861
  }
865
862
 
866
863
  /**
@@ -876,48 +873,48 @@ function handleInputControlAttributeUpdate(element, name, value) {
876
873
  * @throws {TypeError} symbol must be an instance of Symbol
877
874
  */
878
875
  function addObjectWithUpdaterToElement(elements, symbol, object) {
879
- if (!(this instanceof HTMLElement)) {
880
- throw new TypeError(
881
- "the context of this function must be an instance of HTMLElement",
882
- );
883
- }
884
-
885
- if (!(typeof symbol === "symbol")) {
886
- throw new TypeError("symbol must be an instance of Symbol");
887
- }
888
-
889
- const updaters = new Set();
890
-
891
- if (elements instanceof NodeList) {
892
- elements = new Set([...elements]);
893
- } else if (elements instanceof HTMLElement) {
894
- elements = new Set([elements]);
895
- } else if (elements instanceof Set) {
896
- } else {
897
- throw new TypeError(
898
- `elements is not a valid type. (actual: ${typeof elements})`,
899
- );
900
- }
901
-
902
- const result = [];
903
-
904
- elements.forEach((element) => {
905
- if (!(element instanceof HTMLElement)) return;
906
- if (element instanceof HTMLTemplateElement) return;
907
-
908
- const u = new Updater(element, object);
909
- updaters.add(u);
910
-
911
- result.push(
912
- u.run().then(() => {
913
- return u.enableEventProcessing();
914
- }),
915
- );
916
- });
917
-
918
- if (updaters.size > 0) {
919
- addToObjectLink(this, symbol, updaters);
920
- }
921
-
922
- return result;
876
+ if (!(this instanceof HTMLElement)) {
877
+ throw new TypeError(
878
+ "the context of this function must be an instance of HTMLElement",
879
+ );
880
+ }
881
+
882
+ if (!(typeof symbol === "symbol")) {
883
+ throw new TypeError("symbol must be an instance of Symbol");
884
+ }
885
+
886
+ const updaters = new Set();
887
+
888
+ if (elements instanceof NodeList) {
889
+ elements = new Set([...elements]);
890
+ } else if (elements instanceof HTMLElement) {
891
+ elements = new Set([elements]);
892
+ } else if (elements instanceof Set) {
893
+ } else {
894
+ throw new TypeError(
895
+ `elements is not a valid type. (actual: ${typeof elements})`,
896
+ );
897
+ }
898
+
899
+ const result = [];
900
+
901
+ elements.forEach((element) => {
902
+ if (!(element instanceof HTMLElement)) return;
903
+ if (element instanceof HTMLTemplateElement) return;
904
+
905
+ const u = new Updater(element, object);
906
+ updaters.add(u);
907
+
908
+ result.push(
909
+ u.run().then(() => {
910
+ return u.enableEventProcessing();
911
+ }),
912
+ );
913
+ });
914
+
915
+ if (updaters.size > 0) {
916
+ addToObjectLink(this, symbol, updaters);
917
+ }
918
+
919
+ return result;
923
920
  }