@schukai/monster 3.55.0 → 3.55.1
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.
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/source/components/datatable/datasource/rest.mjs +313 -326
- package/source/components/datatable/datatable/header.mjs +1 -1
- package/source/components/datatable/datatable.mjs +586 -591
- package/source/components/datatable/embedded-pagination.mjs +42 -49
- package/source/components/datatable/filter/util.mjs +115 -99
- package/source/components/datatable/filter.mjs +901 -842
- package/source/components/datatable/pagination.mjs +333 -334
- package/source/components/datatable/status.mjs +134 -156
- package/source/components/datatable/stylesheet/column-bar.mjs +14 -8
- package/source/components/datatable/stylesheet/dataset.mjs +14 -8
- package/source/components/datatable/stylesheet/datasource.mjs +14 -8
- package/source/components/datatable/stylesheet/datatable.mjs +14 -8
- package/source/components/datatable/stylesheet/embedded-pagination.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-button.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-date-range.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-range.mjs +14 -8
- package/source/components/datatable/stylesheet/filter.mjs +14 -8
- package/source/components/datatable/stylesheet/pagination.mjs +14 -8
- package/source/components/datatable/stylesheet/select-filter.mjs +14 -8
- package/source/components/datatable/stylesheet/status.mjs +14 -8
- package/source/components/form/action-button.mjs +3 -1
- package/source/components/form/confirm-button.mjs +3 -1
- package/source/components/form/context-error.mjs +161 -164
- package/source/components/form/context-help.mjs +3 -1
- package/source/components/form/form.mjs +3 -1
- package/source/components/form/message-state-button.mjs +3 -1
- package/source/components/form/popper-button.mjs +6 -4
- package/source/components/form/popper.mjs +310 -310
- package/source/components/form/select.mjs +2 -2
- package/source/components/form/state-button.mjs +3 -1
- package/source/components/form/stylesheet/action-button.mjs +14 -8
- package/source/components/form/stylesheet/api-button.mjs +14 -8
- package/source/components/form/stylesheet/button-bar.mjs +14 -8
- package/source/components/form/stylesheet/button.mjs +14 -8
- package/source/components/form/stylesheet/confirm-button.mjs +14 -8
- package/source/components/form/stylesheet/context-error.mjs +14 -8
- package/source/components/form/stylesheet/context-help.mjs +14 -8
- package/source/components/form/stylesheet/form.mjs +14 -8
- package/source/components/form/stylesheet/message-state-button.mjs +14 -8
- package/source/components/form/stylesheet/popper-button.mjs +14 -8
- package/source/components/form/stylesheet/popper.mjs +14 -8
- package/source/components/form/stylesheet/select.mjs +14 -8
- package/source/components/form/stylesheet/state-button.mjs +14 -8
- package/source/components/form/stylesheet/tabs.mjs +14 -8
- package/source/components/form/stylesheet/tree-select.mjs +14 -8
- package/source/components/form/tabs.mjs +754 -758
- package/source/components/host/collapse.mjs +2 -4
- package/source/components/host/config-manager.mjs +11 -9
- package/source/components/host/stylesheet/call-button.mjs +14 -8
- package/source/components/host/stylesheet/collapse.mjs +14 -8
- package/source/components/host/stylesheet/config-manager.mjs +14 -8
- package/source/components/host/stylesheet/details.mjs +14 -8
- package/source/components/host/stylesheet/host.mjs +14 -8
- package/source/components/host/stylesheet/overlay.mjs +14 -8
- package/source/components/host/stylesheet/toggle-button.mjs +14 -8
- package/source/components/host/stylesheet/viewer.mjs +14 -8
- package/source/components/host/util.mjs +2 -2
- package/source/components/notify/stylesheet/message.mjs +14 -8
- package/source/components/notify/stylesheet/notify.mjs +14 -8
- package/source/components/state/stylesheet/log.mjs +14 -8
- package/source/components/state/stylesheet/state.mjs +14 -8
- package/source/components/stylesheet/badge.mjs +14 -8
- package/source/components/stylesheet/border.mjs +14 -8
- package/source/components/stylesheet/button.mjs +14 -8
- package/source/components/stylesheet/card.mjs +14 -8
- package/source/components/stylesheet/color.mjs +14 -8
- package/source/components/stylesheet/common.mjs +14 -8
- package/source/components/stylesheet/control.mjs +14 -8
- package/source/components/stylesheet/data-grid.mjs +14 -8
- package/source/components/stylesheet/display.mjs +14 -8
- package/source/components/stylesheet/floating-ui.mjs +14 -8
- package/source/components/stylesheet/form.mjs +14 -8
- package/source/components/stylesheet/host.mjs +14 -8
- package/source/components/stylesheet/icons.mjs +14 -8
- package/source/components/stylesheet/link.mjs +14 -8
- package/source/components/stylesheet/normalize.mjs +14 -8
- package/source/components/stylesheet/popper.mjs +14 -8
- package/source/components/stylesheet/property.mjs +14 -8
- package/source/components/stylesheet/ripple.mjs +14 -8
- package/source/components/stylesheet/skeleton.mjs +14 -8
- package/source/components/stylesheet/space.mjs +14 -8
- package/source/components/stylesheet/spinner.mjs +14 -8
- package/source/components/stylesheet/table.mjs +14 -8
- package/source/components/stylesheet/theme.mjs +14 -8
- package/source/components/stylesheet/typography.mjs +14 -8
- package/source/components/tree-menu/stylesheet/tree-menu.mjs +14 -8
- package/source/data/transformer.mjs +6 -8
- package/source/dom/attributes.mjs +5 -5
- package/source/dom/customelement.mjs +1 -1
- package/source/dom/updater.mjs +697 -700
- package/source/dom/util.mjs +2 -2
- package/source/monster.mjs +0 -1
- package/source/types/noderecursiveiterator.mjs +9 -7
- package/source/types/version.mjs +1 -1
- package/source/util/sleep.mjs +3 -4
- package/test/cases/monster.mjs +1 -1
package/source/dom/updater.mjs
CHANGED
@@ -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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
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
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
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
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
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
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
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
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
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
|
-
|
416
|
+
const subject = this[internalSymbol].subject.getRealSubject();
|
418
417
|
|
419
|
-
|
420
|
-
|
418
|
+
const mem = new WeakSet();
|
419
|
+
let wd = 0;
|
421
420
|
|
422
|
-
|
421
|
+
const container = this[internalSymbol].element;
|
423
422
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
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
|
-
|
557
|
+
const template = findDocumentTemplate(key, container);
|
561
558
|
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
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
|
-
|
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
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
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
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
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
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
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
|
-
|
715
|
-
|
716
|
-
|
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
|
-
|
729
|
-
|
725
|
+
if (!isArray(parts)) return;
|
726
|
+
parts = clone(parts);
|
730
727
|
|
731
|
-
|
728
|
+
const mem = new WeakSet();
|
732
729
|
|
733
|
-
|
734
|
-
|
735
|
-
|
730
|
+
while (parts.length > 0) {
|
731
|
+
const current = parts.join(".");
|
732
|
+
parts.pop();
|
736
733
|
|
737
|
-
|
734
|
+
let iterator = new Set();
|
738
735
|
|
739
|
-
|
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
|
-
|
738
|
+
const e = container.querySelectorAll(query);
|
742
739
|
|
743
|
-
|
744
|
-
|
745
|
-
|
740
|
+
if (e.length > 0) {
|
741
|
+
iterator = new Set([...e]);
|
742
|
+
}
|
746
743
|
|
747
|
-
|
748
|
-
|
749
|
-
|
744
|
+
if (container.matches(query)) {
|
745
|
+
iterator.add(container);
|
746
|
+
}
|
750
747
|
|
751
|
-
|
752
|
-
|
753
|
-
|
748
|
+
for (const [element] of iterator.entries()) {
|
749
|
+
if (mem.has(element)) return;
|
750
|
+
mem.add(element);
|
754
751
|
|
755
|
-
|
756
|
-
|
757
|
-
|
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
|
-
|
757
|
+
const attributes = element.getAttribute(ATTRIBUTE_UPDATER_ATTRIBUTES);
|
761
758
|
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
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
|
-
|
765
|
+
const pipe = new Pipe(cmd);
|
769
766
|
|
770
|
-
|
771
|
-
|
772
|
-
|
767
|
+
this[internalSymbol].callbacks.forEach((f, n) => {
|
768
|
+
pipe.setCallback(n, f, element);
|
769
|
+
});
|
773
770
|
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
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
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
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
|
-
|
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
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
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
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
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
|
}
|