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