@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 CHANGED
@@ -2,25 +2,38 @@
2
2
 
3
3
 
4
4
 
5
- ## [3.73.2] - 2024-07-01
5
+ ## [3.73.4] - 2024-07-02
6
6
 
7
7
  ### Bug Fixes
8
8
 
9
- - id not defined
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 deadman switch assignment
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 create documentation fragments and optimize create class 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.6","@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.2"}
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].data;
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
- const selector = this.getOption("datasource.selector");
252
+ if (!this[datasourceLinkedElementSymbol]) {
253
+ const selector = this.getOption("datasource.selector");
248
254
 
249
- if (isString(selector)) {
250
- const element = findElementWithSelectorUpwards(this, selector);
251
- if (element === null) {
252
- throw new Error("the selector must match exactly one element");
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
- if (!(element instanceof Datasource)) {
256
- throw new TypeError("the element must be a datasource");
257
- }
261
+ if (!(element instanceof Datasource)) {
262
+ throw new TypeError("the element must be a datasource");
263
+ }
258
264
 
259
- this[datasourceLinkedElementSymbol] = element;
260
- element.datasource.attachObserver(
261
- new Observer(handleDataSourceChanges.bind(this)),
262
- );
263
- } else {
264
- throw new Error("the selector must be a string");
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 (
@@ -274,6 +274,7 @@ class Filter extends CustomElement {
274
274
 
275
275
  query: undefined,
276
276
  defaultQuery: "",
277
+ eventProcessing: true,
277
278
  });
278
279
  }
279
280
 
@@ -201,7 +201,6 @@ class ContextError extends Popper {
201
201
  }
202
202
 
203
203
  if (c === "<slot></slot>") {
204
-
205
204
  const sr = this.shadowRoot;
206
205
  if (!sr) {
207
206
  return false;
@@ -12,15 +12,7 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import { internalSymbol } from "../../constants.mjs";
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
@@ -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
- return u.enableEventProcessing();
978
+ if (config.eventProcessing === true) {
979
+ u.enableEventProcessing();
980
+ }
981
+
982
+ return u;
978
983
  }),
979
984
  );
980
985
  });
@@ -159,7 +159,7 @@ function getMonsterVersion() {
159
159
  }
160
160
 
161
161
  /** don't touch, replaced by make with package.json version */
162
- monsterVersion = new Version("3.65.0");
162
+ monsterVersion = new Version("3.73.2");
163
163
 
164
164
  return monsterVersion;
165
165
  }
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version("3.65.0")
10
+ monsterVersion = new Version("3.73.2")
11
11
 
12
12
  let m = getMonsterVersion();
13
13
 
@@ -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.65.0</h1>
13
- <div id="lastupdate" style='font-size:0.7em'>last update Di 18. Jun 22:58:11 CEST 2024</div>
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>