@schukai/monster 3.73.2 → 3.73.4

Sign up to get free protection for your applications and to get access to all the features.
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>