@schukai/monster 3.73.4 → 3.73.6
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +14 -2
- package/package.json +1 -1
- package/source/components/datatable/save-button.mjs +13 -4
- package/source/components/form/button.mjs +0 -1
- package/source/components/form/select.mjs +33 -83
- package/source/components/tree-menu/tree-menu.mjs +2 -2
- package/source/data/buildtree.mjs +64 -57
- package/source/types/node.mjs +144 -134
- package/source/types/version.mjs +1 -1
- package/test/cases/data/buildtree.mjs +49 -0
- package/test/cases/dom/resource/data.mjs +1 -1
- package/test/cases/dom/resource/link/stylesheet.mjs +1 -1
- package/test/cases/dom/resource/link.mjs +1 -1
- package/test/cases/dom/resource/script.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +63 -16
package/CHANGELOG.md
CHANGED
@@ -2,13 +2,25 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
-
## [3.73.
|
5
|
+
## [3.73.6] - 2024-07-31
|
6
6
|
|
7
7
|
### Bug Fixes
|
8
8
|
|
9
|
-
-
|
9
|
+
- repair url in tests [#230](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/230)
|
10
|
+
- improvement of the tree menu to avoid recursion. [#230](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/230)
|
11
|
+
|
12
|
+
|
13
|
+
## [3.73.5] - 2024-07-02
|
14
|
+
|
15
|
+
### Bug Fixes
|
10
16
|
|
17
|
+
- originValues in the save button is now reset.
|
18
|
+
|
19
|
+
## [3.73.4] - 2024-07-02
|
20
|
+
|
21
|
+
### Bug Fixes
|
11
22
|
|
23
|
+
- event processing is now only active in selected controls: form, filter. [#224](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/224)
|
12
24
|
|
13
25
|
## [3.73.3] - 2024-07-01
|
14
26
|
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
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.
|
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.6"}
|
@@ -46,6 +46,12 @@ export { SaveButton };
|
|
46
46
|
*/
|
47
47
|
const stateButtonElementSymbol = Symbol("stateButtonElement");
|
48
48
|
|
49
|
+
/**
|
50
|
+
* @private
|
51
|
+
* @type {symbol}
|
52
|
+
*/
|
53
|
+
const originValuesSymbol = Symbol("originValues");
|
54
|
+
|
49
55
|
/**
|
50
56
|
* @private
|
51
57
|
* @type {symbol}
|
@@ -161,18 +167,20 @@ class SaveButton extends CustomElement {
|
|
161
167
|
new Observer(handleDataSourceChanges.bind(this)),
|
162
168
|
);
|
163
169
|
|
164
|
-
|
170
|
+
self[originValuesSymbol] = null;
|
165
171
|
|
166
172
|
element.datasource.attachObserver(
|
167
173
|
new Observer(function () {
|
168
|
-
if (!
|
169
|
-
|
174
|
+
if (!self[originValuesSymbol]) {
|
175
|
+
self[originValuesSymbol] = clone(
|
176
|
+
self[datasourceLinkedElementSymbol].data,
|
177
|
+
);
|
170
178
|
}
|
171
179
|
|
172
180
|
const currentValues = this.getRealSubject();
|
173
181
|
const ignoreChanges = self.getOption("ignoreChanges");
|
174
182
|
|
175
|
-
const result = diff(
|
183
|
+
const result = diff(self[originValuesSymbol], currentValues);
|
176
184
|
if (isArray(ignoreChanges) && ignoreChanges.length > 0) {
|
177
185
|
const itemsToRemove = [];
|
178
186
|
for (const item of result) {
|
@@ -285,6 +293,7 @@ function initEventHandler() {
|
|
285
293
|
this[datasourceLinkedElementSymbol]
|
286
294
|
.write()
|
287
295
|
.then(() => {
|
296
|
+
this[originValuesSymbol] = null;
|
288
297
|
this[stateButtonElementSymbol].removeState();
|
289
298
|
this[stateButtonElementSymbol].setOption("disabled", true);
|
290
299
|
this.setOption("changes", 0);
|
@@ -51,7 +51,6 @@ export const buttonElementSymbol = Symbol("buttonElement");
|
|
51
51
|
* @copyright schukai GmbH
|
52
52
|
* @summary A beautiful button that can make your life easier and also looks good.
|
53
53
|
* @fires monster-button-clicked this event is triggered when the button is clicked. It contains the field {button} with the button instance.
|
54
|
-
*
|
55
54
|
*/
|
56
55
|
class Button extends CustomControl {
|
57
56
|
/**
|
@@ -32,7 +32,6 @@ import {
|
|
32
32
|
assembleMethodSymbol,
|
33
33
|
getSlottedElements,
|
34
34
|
registerCustomElement,
|
35
|
-
updaterTransformerMethodsSymbol,
|
36
35
|
} from "../../dom/customelement.mjs";
|
37
36
|
import {
|
38
37
|
findTargetElementFromEvent,
|
@@ -84,120 +83,120 @@ const clickToLoadOptionsMessage = "Click to load options.";
|
|
84
83
|
|
85
84
|
/**
|
86
85
|
* @private
|
87
|
-
* @type {
|
86
|
+
* @type {Symbol}
|
88
87
|
*/
|
89
88
|
const timerCallbackSymbol = Symbol("timerCallback");
|
90
89
|
|
91
90
|
/**
|
92
91
|
* @private
|
93
|
-
* @type {
|
92
|
+
* @type {Symbol}
|
94
93
|
*/
|
95
94
|
const keyFilterEventSymbol = Symbol("keyFilterEvent");
|
96
95
|
|
97
96
|
/**
|
98
97
|
* @private
|
99
|
-
* @type {
|
98
|
+
* @type {Symbol}
|
100
99
|
*/
|
101
100
|
const lazyLoadDoneSymbol = Symbol("lazyLoadDone");
|
102
101
|
|
103
102
|
/**
|
104
103
|
* @private
|
105
|
-
* @type {
|
104
|
+
* @type {Symbol}
|
106
105
|
*/
|
107
106
|
const isLoadingSymbol = Symbol("isLoading");
|
108
107
|
|
109
108
|
/**
|
110
109
|
* local symbol
|
111
110
|
* @private
|
112
|
-
* @type {
|
111
|
+
* @type {Symbol}
|
113
112
|
*/
|
114
113
|
const closeEventHandler = Symbol("closeEventHandler");
|
115
114
|
|
116
115
|
/**
|
117
116
|
* local symbol
|
118
117
|
* @private
|
119
|
-
* @type {
|
118
|
+
* @type {Symbol}
|
120
119
|
*/
|
121
120
|
const clearOptionEventHandler = Symbol("clearOptionEventHandler");
|
122
121
|
|
123
122
|
/**
|
124
123
|
* local symbol
|
125
124
|
* @private
|
126
|
-
* @type {
|
125
|
+
* @type {Symbol}
|
127
126
|
*/
|
128
127
|
const resizeObserverSymbol = Symbol("resizeObserver");
|
129
128
|
|
130
129
|
/**
|
131
130
|
* local symbol
|
132
131
|
* @private
|
133
|
-
* @type {
|
132
|
+
* @type {Symbol}
|
134
133
|
*/
|
135
134
|
const keyEventHandler = Symbol("keyEventHandler");
|
136
135
|
|
137
136
|
/**
|
138
137
|
* local symbol
|
139
138
|
* @private
|
140
|
-
* @type {
|
139
|
+
* @type {Symbol}
|
141
140
|
*/
|
142
141
|
const lastFetchedDataSymbol = Symbol("lastFetchedData");
|
143
142
|
/**
|
144
143
|
* local symbol
|
145
144
|
* @private
|
146
|
-
* @type {
|
145
|
+
* @type {Symbol}
|
147
146
|
*/
|
148
147
|
const inputEventHandler = Symbol("inputEventHandler");
|
149
148
|
|
150
149
|
/**
|
151
150
|
* local symbol
|
152
151
|
* @private
|
153
|
-
* @type {
|
152
|
+
* @type {Symbol}
|
154
153
|
*/
|
155
154
|
const changeEventHandler = Symbol("changeEventHandler");
|
156
155
|
|
157
156
|
/**
|
158
157
|
* local symbol
|
159
158
|
* @private
|
160
|
-
* @type {
|
159
|
+
* @type {Symbol}
|
161
160
|
*/
|
162
161
|
const controlElementSymbol = Symbol("controlElement");
|
163
162
|
|
164
163
|
/**
|
165
164
|
* local symbol
|
166
165
|
* @private
|
167
|
-
* @type {
|
166
|
+
* @type {Symbol}
|
168
167
|
*/
|
169
168
|
const selectionElementSymbol = Symbol("selectionElement");
|
170
169
|
|
171
170
|
/**
|
172
171
|
* local symbol
|
173
172
|
* @private
|
174
|
-
* @type {
|
173
|
+
* @type {Symbol}
|
175
174
|
*/
|
176
175
|
const containerElementSymbol = Symbol("containerElement");
|
177
176
|
|
178
177
|
/**
|
179
178
|
* local symbol
|
180
179
|
* @private
|
181
|
-
* @type {
|
180
|
+
* @type {Symbol}
|
182
181
|
*/
|
183
182
|
const popperElementSymbol = Symbol("popperElement");
|
184
183
|
|
185
184
|
/**
|
186
185
|
* local symbol
|
187
186
|
* @private
|
188
|
-
* @type {
|
187
|
+
* @type {Symbol}
|
189
188
|
*/
|
190
189
|
const inlineFilterElementSymbol = Symbol("inlineFilterElement");
|
191
190
|
/**
|
192
191
|
* local symbol
|
193
192
|
* @private
|
194
|
-
* @type {
|
193
|
+
* @type {Symbol}
|
195
194
|
*/
|
196
195
|
const popperFilterElementSymbol = Symbol("popperFilterElement");
|
197
196
|
/**
|
198
197
|
* local symbol
|
199
198
|
* @private
|
200
|
-
* @type {
|
199
|
+
* @type {Symbol}
|
201
200
|
*/
|
202
201
|
const popperFilterContainerElementSymbol = Symbol(
|
203
202
|
"popperFilterContainerElement",
|
@@ -206,27 +205,27 @@ const popperFilterContainerElementSymbol = Symbol(
|
|
206
205
|
/**
|
207
206
|
* local symbol
|
208
207
|
* @private
|
209
|
-
* @type {
|
208
|
+
* @type {Symbol}
|
210
209
|
*/
|
211
210
|
const optionsElementSymbol = Symbol("optionsElement");
|
212
211
|
|
213
212
|
/**
|
214
213
|
* local symbol
|
215
214
|
* @private
|
216
|
-
* @type {
|
215
|
+
* @type {Symbol}
|
217
216
|
*/
|
218
217
|
const noOptionsAvailableElementSymbol = Symbol("noOptionsAvailableElement");
|
219
218
|
|
220
219
|
/**
|
221
220
|
* local symbol
|
222
221
|
* @private
|
223
|
-
* @type {
|
222
|
+
* @type {Symbol}
|
224
223
|
*/
|
225
224
|
const statusOrRemoveBadgesElementSymbol = Symbol("statusOrRemoveBadgesElement");
|
226
225
|
|
227
226
|
/**
|
228
227
|
* @private
|
229
|
-
* @type {
|
228
|
+
* @type {Symbol}
|
230
229
|
*/
|
231
230
|
const areOptionsAvailableAndInitSymbol = Symbol("@@areOptionsAvailableAndInit");
|
232
231
|
|
@@ -271,69 +270,20 @@ const FILTER_POSITION_POPPER = "popper";
|
|
271
270
|
const FILTER_POSITION_INLINE = "inline";
|
272
271
|
|
273
272
|
/**
|
274
|
-
*
|
275
|
-
* @property {*} value
|
276
|
-
* @property {String} label
|
277
|
-
* @memberOf Monster.Components.Form
|
278
|
-
* @since 1.2.0
|
279
|
-
*/
|
280
|
-
|
281
|
-
/**
|
282
|
-
* This CustomControl creates a select element with a variety of options.
|
283
|
-
* It supports filtering, local and remote, multiple selection and has a
|
284
|
-
* template system for displaying the options.
|
285
|
-
*
|
286
|
-
* <img src="./images/select.png">
|
273
|
+
* A select control that can be used to select one or more options from a list.
|
287
274
|
*
|
288
|
-
*
|
289
|
-
* as well as [pooperjs](https://popper.js.org/docs/v2/).
|
275
|
+
* @fragments /fragments/components/form/select/
|
290
276
|
*
|
291
|
-
*
|
292
|
-
*
|
293
|
-
*
|
294
|
-
* ```html
|
295
|
-
* <monster-select></monster-select>
|
296
|
-
* ```
|
297
|
-
*
|
298
|
-
* Or you can create this CustomControl directly in Javascript:
|
299
|
-
*
|
300
|
-
* ```js
|
301
|
-
* import {Select} from '@schukai/component-form/source/select.js';
|
302
|
-
* document.createElement('monster-select');
|
303
|
-
* ```
|
304
|
-
*
|
305
|
-
* ## Events
|
306
|
-
*
|
307
|
-
* The event `monster-change` is sent as soon as someone has clicked on a input control.
|
308
|
-
* `monster-changed` is sent as soon as the control has processed this input.
|
309
|
-
* The `monster-changed` event is sent when setting a selection. If the options have been set, the `monster-options-set` event is sent.
|
310
|
-
*
|
311
|
-
* The CustomEvent has the property [`detail`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail).
|
312
|
-
*
|
313
|
-
* ```
|
314
|
-
* node.addEventListener('monster-change',(e)=>console.log(e.detail))
|
315
|
-
* node.addEventListener('monster-changed',(e)=>console.log(e.detail))
|
316
|
-
* node.addEventListener('monster-selected',(e)=>console.log(e.detail))
|
317
|
-
* node.addEventListener('monster-options-set',(e)=>console.log(e.detail))
|
318
|
-
* ```
|
319
|
-
*
|
320
|
-
* @externalExample ../../../example/components/form/select.mjs
|
321
|
-
* @startuml select.png
|
322
|
-
* skinparam monochrome true
|
323
|
-
* skinparam shadowing false
|
324
|
-
* HTMLElement <|-- CustomElement
|
325
|
-
* CustomElement <|-- CustomControl
|
326
|
-
* CustomControl <|-- Select
|
327
|
-
* @enduml
|
277
|
+
* @example /examples/components/form/select-simple
|
278
|
+
* @example /examples/components/form/select-with-options
|
328
279
|
*
|
329
280
|
* @since 1.0.0
|
330
281
|
* @copyright schukai GmbH
|
331
|
-
* @
|
332
|
-
* @
|
333
|
-
* @fires
|
334
|
-
* @fires
|
335
|
-
* @fires
|
336
|
-
* @fires Monster.Components.Form.event:monster-changed
|
282
|
+
* @summary A beautiful select control that can make your life easier and also looks good.
|
283
|
+
* @fires monster-options-set
|
284
|
+
* @fires monster-selected
|
285
|
+
* @fires monster-change
|
286
|
+
* @fires monster-changed
|
337
287
|
*/
|
338
288
|
class Select extends CustomControl {
|
339
289
|
/**
|
@@ -346,7 +296,7 @@ class Select extends CustomControl {
|
|
346
296
|
|
347
297
|
/**
|
348
298
|
* This method is called by the `instanceof` operator.
|
349
|
-
* @returns {
|
299
|
+
* @returns {Symbol}
|
350
300
|
* @since 2.1.0
|
351
301
|
*/
|
352
302
|
static get [instanceSymbol]() {
|
@@ -540,7 +490,7 @@ class Select extends CustomControl {
|
|
540
490
|
}
|
541
491
|
|
542
492
|
/**
|
543
|
-
* @return {
|
493
|
+
* @return {Select}
|
544
494
|
*/
|
545
495
|
[assembleMethodSymbol]() {
|
546
496
|
const self = this;
|
@@ -431,7 +431,7 @@ function initEventHandler() {
|
|
431
431
|
}
|
432
432
|
|
433
433
|
return this;
|
434
|
-
}
|
434
|
+
}
|
435
435
|
|
436
436
|
/**
|
437
437
|
* @private
|
@@ -469,6 +469,7 @@ function importEntries() {
|
|
469
469
|
});
|
470
470
|
} catch (error) {
|
471
471
|
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
|
472
|
+
return this;
|
472
473
|
}
|
473
474
|
|
474
475
|
const options = [];
|
@@ -500,7 +501,6 @@ function importEntries() {
|
|
500
501
|
}
|
501
502
|
|
502
503
|
this.setOption("entries", options);
|
503
|
-
|
504
504
|
return this;
|
505
505
|
}
|
506
506
|
|
@@ -12,13 +12,14 @@
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
13
13
|
*/
|
14
14
|
|
15
|
-
import {
|
16
|
-
import {
|
17
|
-
import {
|
18
|
-
import {
|
19
|
-
import {
|
15
|
+
import {isArray, isObject} from "../types/is.mjs";
|
16
|
+
import {Node} from "../types/node.mjs";
|
17
|
+
import {NodeList} from "../types/nodelist.mjs";
|
18
|
+
import {clone} from "../util/clone.mjs";
|
19
|
+
import {assembleParts} from "./buildmap.mjs";
|
20
|
+
import {extend} from "./extend.mjs";
|
20
21
|
|
21
|
-
export {
|
22
|
+
export {buildTree};
|
22
23
|
|
23
24
|
/**
|
24
25
|
* @private
|
@@ -139,63 +140,69 @@ const rootSymbol = Symbol("root");
|
|
139
140
|
* @since 1.26.0
|
140
141
|
*/
|
141
142
|
function buildTree(subject, selector, idKey, parentIDKey, options) {
|
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
|
-
|
143
|
+
const nodes = new Map();
|
144
|
+
|
145
|
+
const maxDepth = 100;
|
146
|
+
|
147
|
+
if (!isObject(options)) {
|
148
|
+
options = {};
|
149
|
+
}
|
150
|
+
|
151
|
+
options = extend(
|
152
|
+
{},
|
153
|
+
{
|
154
|
+
rootReferences: [null, undefined],
|
155
|
+
filter: undefined,
|
156
|
+
},
|
157
|
+
options,
|
158
|
+
);
|
159
|
+
|
160
|
+
const filter = options?.filter;
|
161
|
+
let rootReferences = options.rootReferences;
|
162
|
+
if (!isArray(rootReferences)) {
|
163
|
+
rootReferences = [rootReferences];
|
164
|
+
}
|
165
|
+
|
166
|
+
const childMap = assembleParts(subject, selector, filter, function (o, k, m) {
|
167
|
+
const key = o?.[idKey];
|
168
|
+
let ref = o?.[parentIDKey];
|
169
|
+
if (rootReferences.indexOf(ref) !== -1) ref = rootSymbol;
|
170
|
+
|
171
|
+
if (key === undefined) {
|
172
|
+
throw new Error("the object has no value for the specified id");
|
173
|
+
}
|
174
|
+
|
175
|
+
o[parentSymbol] = ref;
|
176
|
+
|
177
|
+
const node = new Node(o);
|
178
|
+
this.has(ref)
|
179
|
+
? this.get(ref).add(node)
|
180
|
+
: this.set(ref, new NodeList().add(node));
|
181
|
+
nodes.set(key, node);
|
182
|
+
});
|
183
|
+
|
184
|
+
nodes.forEach((node) => {
|
182
185
|
const id = node?.["value"]?.[idKey];
|
183
186
|
|
187
|
+
if (id === undefined) {
|
188
|
+
throw new Error("the object has no value for the specified id");
|
189
|
+
}
|
190
|
+
|
184
191
|
if (childMap.has(id)) {
|
185
|
-
|
186
|
-
|
192
|
+
node.childNodes = childMap.get(id);
|
193
|
+
childMap.delete(id);
|
187
194
|
}
|
188
195
|
});
|
189
196
|
|
190
|
-
|
197
|
+
const list = new NodeList();
|
191
198
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
+
childMap.forEach((s) => {
|
200
|
+
if (s instanceof Set) {
|
201
|
+
s.forEach((n) => {
|
202
|
+
list.add(n);
|
203
|
+
});
|
204
|
+
}
|
205
|
+
});
|
199
206
|
|
200
|
-
|
207
|
+
return list;
|
201
208
|
}
|