@schukai/monster 3.73.2 → 3.73.4
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 +17 -4
- package/package.json +1 -1
- package/source/components/datatable/dataset.mjs +23 -16
- package/source/components/datatable/filter.mjs +1 -0
- package/source/components/form/context-error.mjs +0 -1
- package/source/components/form/form.mjs +11 -171
- package/source/dom/customelement.mjs +9 -0
- package/source/dom/updater.mjs +10 -5
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +1989 -1799
package/CHANGELOG.md
CHANGED
|
@@ -2,25 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
## [3.73.
|
|
5
|
+
## [3.73.4] - 2024-07-02
|
|
6
6
|
|
|
7
7
|
### Bug Fixes
|
|
8
8
|
|
|
9
|
-
-
|
|
9
|
+
- eventprocessing is now only active in selected controls: form, filter. [#224](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/224)
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
## [3.73.3] - 2024-07-01
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- debouncing form handling
|
|
18
|
+
|
|
19
|
+
## [3.73.2] - 2024-07-01
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
- id not defined
|
|
24
|
+
|
|
13
25
|
## [3.73.1] - 2024-06-30
|
|
14
26
|
|
|
15
27
|
### Bug Fixes
|
|
16
28
|
|
|
17
|
-
- update
|
|
29
|
+
- update dead man switch assignment
|
|
30
|
+
|
|
18
31
|
### Changes
|
|
19
32
|
|
|
20
33
|
- update issues
|
|
21
34
|
- remove node debug flag
|
|
22
35
|
- tidy changelog
|
|
23
|
-
- new task
|
|
36
|
+
- new task creates documentation fragments and optimizes creates a class task
|
|
24
37
|
- cleanup code
|
|
25
38
|
|
|
26
39
|
## [3.73.0] - 2024-06-28
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.
|
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.7","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.73.4"}
|
|
@@ -210,7 +210,12 @@ class DataSet extends CustomElement {
|
|
|
210
210
|
pathWithIndex = String(index);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
const data = this[datasourceLinkedElementSymbol]
|
|
213
|
+
const data = this[datasourceLinkedElementSymbol]?.data;
|
|
214
|
+
if (!data) {
|
|
215
|
+
reject(new Error("No data"));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
214
219
|
const unref = JSON.stringify(data);
|
|
215
220
|
const ref = JSON.parse(unref);
|
|
216
221
|
|
|
@@ -244,24 +249,26 @@ class DataSet extends CustomElement {
|
|
|
244
249
|
|
|
245
250
|
initEventHandler.call(this);
|
|
246
251
|
|
|
247
|
-
|
|
252
|
+
if (!this[datasourceLinkedElementSymbol]) {
|
|
253
|
+
const selector = this.getOption("datasource.selector");
|
|
248
254
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
255
|
+
if (isString(selector)) {
|
|
256
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
|
257
|
+
if (element === null) {
|
|
258
|
+
throw new Error("the selector must match exactly one element");
|
|
259
|
+
}
|
|
254
260
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
261
|
+
if (!(element instanceof Datasource)) {
|
|
262
|
+
throw new TypeError("the element must be a datasource");
|
|
263
|
+
}
|
|
258
264
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
+
this[datasourceLinkedElementSymbol] = element;
|
|
266
|
+
element.datasource.attachObserver(
|
|
267
|
+
new Observer(handleDataSourceChanges.bind(this)),
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
throw new Error("the selector must be a string");
|
|
271
|
+
}
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
if (
|
|
@@ -12,15 +12,7 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
import { Pathfinder } from "../../data/pathfinder.mjs";
|
|
17
|
-
import {
|
|
18
|
-
ATTRIBUTE_FORM_BIND,
|
|
19
|
-
ATTRIBUTE_FORM_BIND_TYPE,
|
|
20
|
-
ATTRIBUTE_UPDATER_BIND,
|
|
21
|
-
} from "../../dom/constants.mjs";
|
|
22
|
-
import { findTargetElementFromEvent } from "../../dom/events.mjs";
|
|
23
|
-
import { clone } from "../../util/clone.mjs";
|
|
15
|
+
import { Datasource } from "../../data/datasource.mjs";
|
|
24
16
|
import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
|
|
25
17
|
import { DataSet } from "../datatable/dataset.mjs";
|
|
26
18
|
import {
|
|
@@ -28,9 +20,8 @@ import {
|
|
|
28
20
|
registerCustomElement,
|
|
29
21
|
getSlottedElements,
|
|
30
22
|
} from "../../dom/customelement.mjs";
|
|
23
|
+
import { datasourceLinkedElementSymbol } from "../datatable/util.mjs";
|
|
31
24
|
import { FormStyleSheet } from "./stylesheet/form.mjs";
|
|
32
|
-
import { diff } from "../../data/diff.mjs";
|
|
33
|
-
import { isString } from "../../types/is.mjs";
|
|
34
25
|
|
|
35
26
|
export { Form };
|
|
36
27
|
|
|
@@ -56,7 +47,6 @@ class Form extends DataSet {
|
|
|
56
47
|
* @property {Object} writeBack Write back definitions
|
|
57
48
|
* @property {string[]} writeBack.events Write back events
|
|
58
49
|
* @property {Object} bind Bind definitions
|
|
59
|
-
* @property {string[]} bind.events Bind events
|
|
60
50
|
* @property {Object} reportValidity Report validity definitions
|
|
61
51
|
* @property {string} reportValidity.selector Report validity selector
|
|
62
52
|
* @property {boolean} features.mutationObserver Mutation observer feature
|
|
@@ -74,21 +64,18 @@ class Form extends DataSet {
|
|
|
74
64
|
},
|
|
75
65
|
|
|
76
66
|
writeBack: {
|
|
77
|
-
events: ["keyup", "click", "change", "drop", "touchend", "input"]
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
bind: {
|
|
81
|
-
events: ["keyup", "click", "change", "drop", "touchend", "input"]
|
|
67
|
+
events: ["keyup", "click", "change", "drop", "touchend", "input"],
|
|
82
68
|
},
|
|
83
69
|
|
|
84
70
|
reportValidity: {
|
|
85
71
|
selector: "input,select,textarea",
|
|
86
72
|
},
|
|
73
|
+
|
|
74
|
+
eventProcessing: true,
|
|
87
75
|
});
|
|
88
76
|
|
|
89
77
|
obj["features"]["mutationObserver"] = false;
|
|
90
78
|
obj["features"]["writeBack"] = true;
|
|
91
|
-
obj["features"]["bind"] = true;
|
|
92
79
|
|
|
93
80
|
return obj;
|
|
94
81
|
}
|
|
@@ -112,6 +99,12 @@ class Form extends DataSet {
|
|
|
112
99
|
*
|
|
113
100
|
*/
|
|
114
101
|
[assembleMethodSymbol]() {
|
|
102
|
+
const selector = this.getOption("datasource.selector");
|
|
103
|
+
|
|
104
|
+
if (!selector) {
|
|
105
|
+
this[datasourceLinkedElementSymbol] = new Datasource(this);
|
|
106
|
+
}
|
|
107
|
+
|
|
115
108
|
super[assembleMethodSymbol]();
|
|
116
109
|
|
|
117
110
|
initControlReferences.call(this);
|
|
@@ -163,54 +156,6 @@ function initDataSourceHandler() {}
|
|
|
163
156
|
function initEventHandler() {
|
|
164
157
|
this[debounceBindSymbol] = {};
|
|
165
158
|
|
|
166
|
-
if (this.getOption("features.bind") === true) {
|
|
167
|
-
const events = this.getOption("bind.events");
|
|
168
|
-
|
|
169
|
-
for (const event of events) {
|
|
170
|
-
this.addEventListener(event, (e) => {
|
|
171
|
-
const element = findTargetElementFromEvent(e, ATTRIBUTE_FORM_BIND);
|
|
172
|
-
|
|
173
|
-
if (!(element instanceof HTMLElement)) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
let elementID = element.id;
|
|
178
|
-
|
|
179
|
-
if (elementID === "") {
|
|
180
|
-
elementID = element.getAttribute("name");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (elementID === "") {
|
|
184
|
-
elementID = element.getAttribute("data-monster-attributes");
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (elementID === "") {
|
|
188
|
-
elementID = element.innerText.substring(0, 20);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
elementID = elementID.replace(/\s/g, "_")
|
|
192
|
-
|
|
193
|
-
if (this[debounceBindSymbol][elementID] instanceof DeadMansSwitch) {
|
|
194
|
-
try {
|
|
195
|
-
this[debounceBindSymbol][elementID].touch();
|
|
196
|
-
return;
|
|
197
|
-
} catch (e) {
|
|
198
|
-
if (e.message !== "has already run") {
|
|
199
|
-
throw e;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
delete this[debounceBindSymbol][elementID];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
this[debounceBindSymbol][elementID] = new DeadMansSwitch(200, () => {
|
|
207
|
-
delete this[debounceBindSymbol][elementID];
|
|
208
|
-
retrieveAndSetValue.call(this, element);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
159
|
if (this.getOption("features.writeBack") === true) {
|
|
215
160
|
const events = this.getOption("writeBack.events");
|
|
216
161
|
for (const event of events) {
|
|
@@ -259,111 +204,6 @@ function initControlReferences() {
|
|
|
259
204
|
return this;
|
|
260
205
|
}
|
|
261
206
|
|
|
262
|
-
/**
|
|
263
|
-
* @throws {Error} the bind argument must start as a value with a path
|
|
264
|
-
* @param {HTMLElement} element
|
|
265
|
-
* @return void
|
|
266
|
-
* @memberOf Monster.DOM
|
|
267
|
-
* @private
|
|
268
|
-
*/
|
|
269
|
-
function retrieveAndSetValue(element) {
|
|
270
|
-
let path = element.getAttribute(ATTRIBUTE_FORM_BIND);
|
|
271
|
-
if (path === null)
|
|
272
|
-
throw new Error("the bind argument must start as a value with a path");
|
|
273
|
-
|
|
274
|
-
if (path.indexOf("path:") !== 0) {
|
|
275
|
-
throw new Error("the bind argument must start as a value with a path");
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
path = path.substring(5); // remove path: from the string
|
|
279
|
-
|
|
280
|
-
let value;
|
|
281
|
-
|
|
282
|
-
if (element instanceof HTMLInputElement) {
|
|
283
|
-
switch (element.type) {
|
|
284
|
-
case "checkbox":
|
|
285
|
-
value = element.checked ? element.value : undefined;
|
|
286
|
-
break;
|
|
287
|
-
default:
|
|
288
|
-
value = element.value;
|
|
289
|
-
break;
|
|
290
|
-
}
|
|
291
|
-
} else if (element instanceof HTMLTextAreaElement) {
|
|
292
|
-
value = element.value;
|
|
293
|
-
} else if (element instanceof HTMLSelectElement) {
|
|
294
|
-
switch (element.type) {
|
|
295
|
-
case "select-one":
|
|
296
|
-
value = element.value;
|
|
297
|
-
break;
|
|
298
|
-
case "select-multiple":
|
|
299
|
-
value = element.value;
|
|
300
|
-
|
|
301
|
-
let options = element?.selectedOptions;
|
|
302
|
-
if (options === undefined)
|
|
303
|
-
options = element.querySelectorAll(":scope option:checked");
|
|
304
|
-
value = Array.from(options).map(({ value }) => value);
|
|
305
|
-
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// values from custom elements
|
|
310
|
-
} else if (
|
|
311
|
-
(element?.constructor?.prototype &&
|
|
312
|
-
!!Object.getOwnPropertyDescriptor(
|
|
313
|
-
element.constructor.prototype,
|
|
314
|
-
"value",
|
|
315
|
-
)?.["get"]) ||
|
|
316
|
-
element.hasOwnProperty("value")
|
|
317
|
-
) {
|
|
318
|
-
value = element?.["value"];
|
|
319
|
-
} else {
|
|
320
|
-
throw new Error("unsupported object");
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (isString(value)) {
|
|
324
|
-
const type = element.getAttribute(ATTRIBUTE_FORM_BIND_TYPE);
|
|
325
|
-
switch (type) {
|
|
326
|
-
case "number":
|
|
327
|
-
case "int":
|
|
328
|
-
case "float":
|
|
329
|
-
case "integer":
|
|
330
|
-
value = Number(value);
|
|
331
|
-
if (isNaN(value)) {
|
|
332
|
-
value = 0;
|
|
333
|
-
}
|
|
334
|
-
break;
|
|
335
|
-
case "boolean":
|
|
336
|
-
case "bool":
|
|
337
|
-
case "checkbox":
|
|
338
|
-
value = value === "true" || value === "1" || value === "on";
|
|
339
|
-
break;
|
|
340
|
-
case "array":
|
|
341
|
-
case "list":
|
|
342
|
-
value = value.split(",");
|
|
343
|
-
break;
|
|
344
|
-
case "object":
|
|
345
|
-
case "json":
|
|
346
|
-
value = JSON.parse(value);
|
|
347
|
-
break;
|
|
348
|
-
default:
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
const copy = clone(this[internalSymbol].getRealSubject()?.options);
|
|
354
|
-
|
|
355
|
-
const pf = new Pathfinder(copy);
|
|
356
|
-
pf.setVia(path, value);
|
|
357
|
-
|
|
358
|
-
const diffResult = diff(copy, this[internalSymbol].getRealSubject()?.options);
|
|
359
|
-
|
|
360
|
-
if (diffResult.length > 0) {
|
|
361
|
-
setTimeout(() => {
|
|
362
|
-
this.setOption(path, value);
|
|
363
|
-
}, 50);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
207
|
/**
|
|
368
208
|
* @private
|
|
369
209
|
* @return {string}
|
|
@@ -327,6 +327,7 @@ class CustomElement extends HTMLElement {
|
|
|
327
327
|
* @property {Object} templates Specifies the templates used by the control.
|
|
328
328
|
* @property {string} templates.main=undefined Specifies the main template used by the control.
|
|
329
329
|
* @property {Object} templateMapping Specifies the mapping of templates.
|
|
330
|
+
* @property {Boolean} eventProcessing=false Specifies whether the control processes events.
|
|
330
331
|
* @since 1.8.0
|
|
331
332
|
*/
|
|
332
333
|
get defaults() {
|
|
@@ -338,6 +339,8 @@ class CustomElement extends HTMLElement {
|
|
|
338
339
|
main: undefined,
|
|
339
340
|
},
|
|
340
341
|
templateMapping: {},
|
|
342
|
+
|
|
343
|
+
eventProcessing: false,
|
|
341
344
|
};
|
|
342
345
|
}
|
|
343
346
|
|
|
@@ -644,11 +647,17 @@ class CustomElement extends HTMLElement {
|
|
|
644
647
|
this[internalSymbol].getRealSubject()["options"],
|
|
645
648
|
);
|
|
646
649
|
|
|
650
|
+
const cfg = {};
|
|
651
|
+
if (this.getOption("eventProcessing") === true) {
|
|
652
|
+
cfg.eventProcessing = true;
|
|
653
|
+
}
|
|
654
|
+
|
|
647
655
|
addObjectWithUpdaterToElement.call(
|
|
648
656
|
this,
|
|
649
657
|
nodeList,
|
|
650
658
|
customElementUpdaterLinkSymbol,
|
|
651
659
|
this[updateCloneDataSymbol],
|
|
660
|
+
cfg,
|
|
652
661
|
);
|
|
653
662
|
|
|
654
663
|
// Attach a mutation observer to observe changes to the attributes of the element
|
package/source/dom/updater.mjs
CHANGED
|
@@ -156,7 +156,6 @@ class Updater extends Base {
|
|
|
156
156
|
|
|
157
157
|
for (const type of this[internalSymbol].eventTypes) {
|
|
158
158
|
// @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
|
|
159
|
-
|
|
160
159
|
this[internalSymbol].element.addEventListener(
|
|
161
160
|
type,
|
|
162
161
|
getControlEventHandler.call(this),
|
|
@@ -745,9 +744,7 @@ function runUpdateContent(container, parts, subject) {
|
|
|
745
744
|
|
|
746
745
|
/**
|
|
747
746
|
* @private
|
|
748
|
-
* @license AGPLv3
|
|
749
747
|
* @since 1.8.0
|
|
750
|
-
* @param {string} path
|
|
751
748
|
* @param {object} change
|
|
752
749
|
* @return {void}
|
|
753
750
|
*/
|
|
@@ -900,6 +897,10 @@ function handleInputControlAttributeUpdate(element, name, value) {
|
|
|
900
897
|
* @param {NodeList|HTMLElement|Set<HTMLElement>} elements
|
|
901
898
|
* @param {Symbol} symbol
|
|
902
899
|
* @param {object} object
|
|
900
|
+
* @param {object} config
|
|
901
|
+
*
|
|
902
|
+
* Config: enableEventProcessing {boolean} - default: false - enables the event processing
|
|
903
|
+
*
|
|
903
904
|
* @return {Promise[]}
|
|
904
905
|
* @license AGPLv3
|
|
905
906
|
* @since 1.23.0
|
|
@@ -908,7 +909,7 @@ function handleInputControlAttributeUpdate(element, name, value) {
|
|
|
908
909
|
* @throws {TypeError} the context of the function is not an instance of HTMLElement
|
|
909
910
|
* @throws {TypeError} symbol must be an instance of Symbol
|
|
910
911
|
*/
|
|
911
|
-
function addObjectWithUpdaterToElement(elements, symbol, object) {
|
|
912
|
+
function addObjectWithUpdaterToElement(elements, symbol, object, config = {}) {
|
|
912
913
|
if (!(this instanceof HTMLElement)) {
|
|
913
914
|
throw new TypeError(
|
|
914
915
|
"the context of this function must be an instance of HTMLElement",
|
|
@@ -974,7 +975,11 @@ function addObjectWithUpdaterToElement(elements, symbol, object) {
|
|
|
974
975
|
|
|
975
976
|
result.push(
|
|
976
977
|
u.run().then(() => {
|
|
977
|
-
|
|
978
|
+
if (config.eventProcessing === true) {
|
|
979
|
+
u.enableEventProcessing();
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
return u;
|
|
978
983
|
}),
|
|
979
984
|
);
|
|
980
985
|
});
|
package/source/types/version.mjs
CHANGED
package/test/cases/monster.mjs
CHANGED
package/test/web/test.html
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
|
|
12
|
-
<h1 style='margin-bottom: 0.1em;'>Monster 3.
|
|
13
|
-
<div id="lastupdate" style='font-size:0.7em'>last update Di
|
|
12
|
+
<h1 style='margin-bottom: 0.1em;'>Monster 3.73.2</h1>
|
|
13
|
+
<div id="lastupdate" style='font-size:0.7em'>last update Di 2. Jul 20:16:21 CEST 2024</div>
|
|
14
14
|
</div>
|
|
15
15
|
<div id="mocha-errors"
|
|
16
16
|
style="color: red;font-weight: bold;display: flex;align-items: center;justify-content: center;flex-direction: column;margin:20px;"></div>
|