@schukai/monster 4.70.0 → 4.70.1
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 +8 -0
- package/package.json +1 -1
- package/source/components/datatable/dataset.mjs +1 -2
- package/source/components/datatable/save-button.mjs +103 -80
- package/source/components/datatable/util.mjs +12 -6
- package/source/components/form/select.mjs +116 -25
- package/source/components/layout/slider.mjs +3 -3
- package/source/dom/customelement.mjs +76 -0
- package/source/dom/util/set-option-from-attribute.mjs +26 -6
- 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 +181 -30
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@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":"4.70.
|
|
1
|
+
{"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@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":"4.70.1"}
|
|
@@ -155,9 +155,8 @@ class DataSet extends CustomElement {
|
|
|
155
155
|
refresh() {
|
|
156
156
|
// makes sure that handleDataSourceChanges is called
|
|
157
157
|
return new Promise((resolve) => {
|
|
158
|
-
this.setOption("data", {});
|
|
159
158
|
queueMicrotask(() => {
|
|
160
|
-
handleDataSourceChanges.call(this);
|
|
159
|
+
handleDataSourceChanges.call(this, true);
|
|
161
160
|
resolve();
|
|
162
161
|
});
|
|
163
162
|
});
|
|
@@ -61,6 +61,7 @@ const originValuesSymbol = Symbol("originValues");
|
|
|
61
61
|
const badgeElementSymbol = Symbol("badgeElement");
|
|
62
62
|
const saveInFlightSymbol = Symbol("saveInFlight");
|
|
63
63
|
const pendingResetSymbol = Symbol("pendingReset");
|
|
64
|
+
const fetchInFlightSymbol = Symbol("fetchInFlight");
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
67
|
* A save button component
|
|
@@ -186,8 +187,21 @@ class SaveButton extends CustomElement {
|
|
|
186
187
|
self[pendingResetSymbol] = true;
|
|
187
188
|
return;
|
|
188
189
|
}
|
|
190
|
+
self[fetchInFlightSymbol] = true;
|
|
189
191
|
self[originValuesSymbol] = null;
|
|
190
192
|
});
|
|
193
|
+
element.addEventListener("monster-datasource-fetched", () => {
|
|
194
|
+
self[fetchInFlightSymbol] = false;
|
|
195
|
+
if (!self[originValuesSymbol]) {
|
|
196
|
+
self[originValuesSymbol] = clone(
|
|
197
|
+
self[datasourceLinkedElementSymbol].data,
|
|
198
|
+
);
|
|
199
|
+
updateChangesState.call(self);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
element.addEventListener("monster-datasource-error", () => {
|
|
203
|
+
self[fetchInFlightSymbol] = false;
|
|
204
|
+
});
|
|
191
205
|
}
|
|
192
206
|
|
|
193
207
|
this[datasourceLinkedElementSymbol] = element;
|
|
@@ -199,92 +213,16 @@ class SaveButton extends CustomElement {
|
|
|
199
213
|
|
|
200
214
|
element.datasource.attachObserver(
|
|
201
215
|
new Observer(function () {
|
|
216
|
+
if (self[fetchInFlightSymbol] === true) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
202
219
|
if (!self[originValuesSymbol]) {
|
|
203
220
|
self[originValuesSymbol] = clone(
|
|
204
221
|
self[datasourceLinkedElementSymbol].data,
|
|
205
222
|
);
|
|
206
223
|
}
|
|
207
224
|
|
|
208
|
-
|
|
209
|
-
const ignoreChanges = self.getOption("ignoreChanges");
|
|
210
|
-
|
|
211
|
-
const result = diff(self[originValuesSymbol], currentValues);
|
|
212
|
-
if (
|
|
213
|
-
self.getOption("logLevel") === "debug" ||
|
|
214
|
-
location.search.includes("logLevel=debug")
|
|
215
|
-
) {
|
|
216
|
-
console.groupCollapsed("SaveButton");
|
|
217
|
-
console.log(
|
|
218
|
-
"originValues",
|
|
219
|
-
JSON.parse(JSON.stringify(currentValues)),
|
|
220
|
-
);
|
|
221
|
-
console.log("result of diff", result);
|
|
222
|
-
console.log("ignoreChanges", ignoreChanges);
|
|
223
|
-
|
|
224
|
-
if (isArray(result) && result.length > 0) {
|
|
225
|
-
const formattedDiff = result.map((change) => ({
|
|
226
|
-
Operator: change?.operator,
|
|
227
|
-
Path: change?.path?.join("."),
|
|
228
|
-
"First Value": change?.first?.value,
|
|
229
|
-
"First Type": change?.first?.type,
|
|
230
|
-
"Second Value": change?.second?.value,
|
|
231
|
-
"Second Type": change?.second?.type,
|
|
232
|
-
}));
|
|
233
|
-
|
|
234
|
-
console.table(formattedDiff);
|
|
235
|
-
} else {
|
|
236
|
-
console.log("There are no changes to save");
|
|
237
|
-
}
|
|
238
|
-
console.groupEnd();
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (isArray(ignoreChanges) && ignoreChanges.length > 0) {
|
|
242
|
-
const itemsToRemove = [];
|
|
243
|
-
for (const item of result) {
|
|
244
|
-
for (const ignorePattern of ignoreChanges) {
|
|
245
|
-
const p = new RegExp(ignorePattern);
|
|
246
|
-
|
|
247
|
-
let matchPath = item.path;
|
|
248
|
-
if (isArray(item.path)) {
|
|
249
|
-
matchPath = item.path.join(".");
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (p.test(matchPath)) {
|
|
253
|
-
itemsToRemove.push(item);
|
|
254
|
-
break;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
for (const itemToRemove of itemsToRemove) {
|
|
260
|
-
const index = result.indexOf(itemToRemove);
|
|
261
|
-
if (index > -1) {
|
|
262
|
-
result.splice(index, 1);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (isArray(result) && result.length > 0) {
|
|
268
|
-
self[stateButtonElementSymbol].setState("changed");
|
|
269
|
-
self[stateButtonElementSymbol].setOption("disabled", false);
|
|
270
|
-
self.setOption("changes", result.length);
|
|
271
|
-
self.setOption(
|
|
272
|
-
"classes.badge",
|
|
273
|
-
new TokenList(self.getOption("classes.badge"))
|
|
274
|
-
.remove("hidden")
|
|
275
|
-
.toString(),
|
|
276
|
-
);
|
|
277
|
-
} else {
|
|
278
|
-
self[stateButtonElementSymbol].removeState();
|
|
279
|
-
self[stateButtonElementSymbol].setOption("disabled", true);
|
|
280
|
-
self.setOption("changes", 0);
|
|
281
|
-
self.setOption(
|
|
282
|
-
"classes.badge",
|
|
283
|
-
new TokenList(self.getOption("classes.badge"))
|
|
284
|
-
.add("hidden")
|
|
285
|
-
.toString(),
|
|
286
|
-
);
|
|
287
|
-
}
|
|
225
|
+
updateChangesState.call(self);
|
|
288
226
|
}),
|
|
289
227
|
);
|
|
290
228
|
}
|
|
@@ -440,6 +378,91 @@ function initEventHandler() {
|
|
|
440
378
|
});
|
|
441
379
|
}
|
|
442
380
|
|
|
381
|
+
/**
|
|
382
|
+
* @private
|
|
383
|
+
*/
|
|
384
|
+
function updateChangesState() {
|
|
385
|
+
const currentValues = this[datasourceLinkedElementSymbol]?.datasource?.get();
|
|
386
|
+
const ignoreChanges = this.getOption("ignoreChanges");
|
|
387
|
+
let result = diff(this[originValuesSymbol], currentValues);
|
|
388
|
+
|
|
389
|
+
if (
|
|
390
|
+
this.getOption("logLevel") === "debug" ||
|
|
391
|
+
location.search.includes("logLevel=debug")
|
|
392
|
+
) {
|
|
393
|
+
console.groupCollapsed("SaveButton");
|
|
394
|
+
console.log(
|
|
395
|
+
"originValues",
|
|
396
|
+
JSON.parse(JSON.stringify(this[originValuesSymbol])),
|
|
397
|
+
);
|
|
398
|
+
console.log("currentValues", JSON.parse(JSON.stringify(currentValues)));
|
|
399
|
+
console.log("result of diff", result);
|
|
400
|
+
console.log("ignoreChanges", ignoreChanges);
|
|
401
|
+
|
|
402
|
+
if (isArray(result) && result.length > 0) {
|
|
403
|
+
const formattedDiff = result.map((change) => ({
|
|
404
|
+
Operator: change?.operator,
|
|
405
|
+
Path: change?.path?.join("."),
|
|
406
|
+
"First Value": change?.first?.value,
|
|
407
|
+
"First Type": change?.first?.type,
|
|
408
|
+
"Second Value": change?.second?.value,
|
|
409
|
+
"Second Type": change?.second?.type,
|
|
410
|
+
}));
|
|
411
|
+
|
|
412
|
+
console.table(formattedDiff);
|
|
413
|
+
} else {
|
|
414
|
+
console.log("There are no changes to save");
|
|
415
|
+
}
|
|
416
|
+
console.groupEnd();
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (isArray(ignoreChanges) && ignoreChanges.length > 0) {
|
|
420
|
+
const itemsToRemove = [];
|
|
421
|
+
for (const item of result) {
|
|
422
|
+
for (const ignorePattern of ignoreChanges) {
|
|
423
|
+
const p = new RegExp(ignorePattern);
|
|
424
|
+
|
|
425
|
+
let matchPath = item.path;
|
|
426
|
+
if (isArray(item.path)) {
|
|
427
|
+
matchPath = item.path.join(".");
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (p.test(matchPath)) {
|
|
431
|
+
itemsToRemove.push(item);
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
for (const itemToRemove of itemsToRemove) {
|
|
438
|
+
const index = result.indexOf(itemToRemove);
|
|
439
|
+
if (index > -1) {
|
|
440
|
+
result.splice(index, 1);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (isArray(result) && result.length > 0) {
|
|
446
|
+
this[stateButtonElementSymbol].setState("changed");
|
|
447
|
+
this[stateButtonElementSymbol].setOption("disabled", false);
|
|
448
|
+
this.setOption("changes", result.length);
|
|
449
|
+
this.setOption(
|
|
450
|
+
"classes.badge",
|
|
451
|
+
new TokenList(this.getOption("classes.badge"))
|
|
452
|
+
.remove("hidden")
|
|
453
|
+
.toString(),
|
|
454
|
+
);
|
|
455
|
+
} else {
|
|
456
|
+
this[stateButtonElementSymbol].removeState();
|
|
457
|
+
this[stateButtonElementSymbol].setOption("disabled", true);
|
|
458
|
+
this.setOption("changes", 0);
|
|
459
|
+
this.setOption(
|
|
460
|
+
"classes.badge",
|
|
461
|
+
new TokenList(this.getOption("classes.badge")).add("hidden").toString(),
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
443
466
|
/**
|
|
444
467
|
* @param {Object} options
|
|
445
468
|
* @deprecated 2024-12-31
|
|
@@ -16,6 +16,7 @@ import { diff } from "../../data/diff.mjs";
|
|
|
16
16
|
import { Pathfinder } from "../../data/pathfinder.mjs";
|
|
17
17
|
import { isObject, isPrimitive } from "../../types/is.mjs";
|
|
18
18
|
import { Observer } from "../../types/observer.mjs";
|
|
19
|
+
import { clone } from "../../util/clone.mjs";
|
|
19
20
|
|
|
20
21
|
export { handleDataSourceChanges, datasourceLinkedElementSymbol };
|
|
21
22
|
|
|
@@ -29,7 +30,7 @@ const dataChangeVersionSymbol = Symbol("dataChangeVersion");
|
|
|
29
30
|
/**
|
|
30
31
|
* @private
|
|
31
32
|
*/
|
|
32
|
-
function handleDataSourceChanges() {
|
|
33
|
+
function handleDataSourceChanges(force = false) {
|
|
33
34
|
if (!this[datasourceLinkedElementSymbol]) {
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
@@ -69,15 +70,20 @@ function handleDataSourceChanges() {
|
|
|
69
70
|
data = [];
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
const result = diff(data, actualDataAsObj);
|
|
73
|
-
if (result.length === 0) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
73
|
queueMicrotask(() => {
|
|
78
74
|
if (this[dataChangeVersionSymbol] !== version) {
|
|
79
75
|
return;
|
|
80
76
|
}
|
|
77
|
+
if (force) {
|
|
78
|
+
this.setOption("data", clone(data));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const result = diff(data, actualDataAsObj);
|
|
83
|
+
if (result.length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
this.setOption("data", data);
|
|
82
88
|
});
|
|
83
89
|
}
|
|
@@ -252,6 +252,11 @@ const runLookupOnceSymbol = Symbol("runLookupOnce");
|
|
|
252
252
|
* @type {symbol}
|
|
253
253
|
*/
|
|
254
254
|
const cleanupOptionsListSymbol = Symbol("cleanupOptionsList");
|
|
255
|
+
const optionsVersionSymbol = Symbol("optionsVersion");
|
|
256
|
+
const pendingSelectionSymbol = Symbol("pendingSelection");
|
|
257
|
+
const selectionSyncScheduledSymbol = Symbol("selectionSyncScheduled");
|
|
258
|
+
const optionsSnapshotSymbol = Symbol("optionsSnapshot");
|
|
259
|
+
const selectionVersionSymbol = Symbol("selectionVersion");
|
|
255
260
|
|
|
256
261
|
/**
|
|
257
262
|
* @private
|
|
@@ -950,6 +955,77 @@ function processAndApplyPaginationData(data) {
|
|
|
950
955
|
}
|
|
951
956
|
}
|
|
952
957
|
|
|
958
|
+
/**
|
|
959
|
+
* @private
|
|
960
|
+
* @returns {number}
|
|
961
|
+
*/
|
|
962
|
+
function bumpOptionsVersion() {
|
|
963
|
+
if (!isInteger(this[optionsVersionSymbol])) {
|
|
964
|
+
this[optionsVersionSymbol] = 0;
|
|
965
|
+
}
|
|
966
|
+
this[optionsVersionSymbol] += 1;
|
|
967
|
+
return this[optionsVersionSymbol];
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* @private
|
|
972
|
+
* @returns {*}
|
|
973
|
+
*/
|
|
974
|
+
function getSelectionSyncState() {
|
|
975
|
+
const attrValue = this.getAttribute("value");
|
|
976
|
+
const selection = this.getOption("selection");
|
|
977
|
+
const options = this.getOption("options");
|
|
978
|
+
const optionsLength = Array.isArray(options) ? options.length : 0;
|
|
979
|
+
return { attrValue, selection, optionsLength };
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* @private
|
|
984
|
+
* @param {number} version
|
|
985
|
+
*/
|
|
986
|
+
function scheduleSelectionSync(version) {
|
|
987
|
+
const state = getSelectionSyncState.call(this);
|
|
988
|
+
const selectionIsEmpty =
|
|
989
|
+
Array.isArray(state.selection) && state.selection.length === 0;
|
|
990
|
+
|
|
991
|
+
if (state.attrValue === null && selectionIsEmpty) {
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
const pending = {
|
|
996
|
+
version,
|
|
997
|
+
selectionVersion: this[selectionVersionSymbol] || 0,
|
|
998
|
+
value: state.attrValue !== null ? state.attrValue : state.selection,
|
|
999
|
+
};
|
|
1000
|
+
this[pendingSelectionSymbol] = pending;
|
|
1001
|
+
|
|
1002
|
+
if (this[selectionSyncScheduledSymbol] === true) {
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
this[selectionSyncScheduledSymbol] = true;
|
|
1006
|
+
|
|
1007
|
+
queueMicrotask(() => {
|
|
1008
|
+
this[selectionSyncScheduledSymbol] = false;
|
|
1009
|
+
const current = this[pendingSelectionSymbol];
|
|
1010
|
+
if (!current) {
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
if (current.version !== this[optionsVersionSymbol]) {
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
if (current.selectionVersion !== (this[selectionVersionSymbol] || 0)) {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
setSelection
|
|
1021
|
+
.call(this, current.value)
|
|
1022
|
+
.then(() => {})
|
|
1023
|
+
.catch((e) => {
|
|
1024
|
+
addErrorAttribute(this, e);
|
|
1025
|
+
});
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
|
|
953
1029
|
/**
|
|
954
1030
|
* @private
|
|
955
1031
|
* @param data
|
|
@@ -1011,8 +1087,9 @@ function importOptionsIntern(data) {
|
|
|
1011
1087
|
const map = buildMap(data, selector, labelTemplate, valueTemplate, filter);
|
|
1012
1088
|
|
|
1013
1089
|
let options = [];
|
|
1090
|
+
const currentOptions = this.getOption("options");
|
|
1014
1091
|
if (this[cleanupOptionsListSymbol] !== true) {
|
|
1015
|
-
options =
|
|
1092
|
+
options = currentOptions ?? [];
|
|
1016
1093
|
}
|
|
1017
1094
|
|
|
1018
1095
|
this[cleanupOptionsListSymbol] = false;
|
|
@@ -1092,17 +1169,10 @@ function importOptionsIntern(data) {
|
|
|
1092
1169
|
options,
|
|
1093
1170
|
});
|
|
1094
1171
|
|
|
1095
|
-
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
setSelection
|
|
1100
|
-
.call(this, selection)
|
|
1101
|
-
.then(() => {})
|
|
1102
|
-
.catch((e) => {
|
|
1103
|
-
addErrorAttribute(this, e);
|
|
1104
|
-
});
|
|
1105
|
-
}, 10);
|
|
1172
|
+
if (options === currentOptions) {
|
|
1173
|
+
const version = bumpOptionsVersion.call(this);
|
|
1174
|
+
scheduleSelectionSync.call(this, version);
|
|
1175
|
+
}
|
|
1106
1176
|
|
|
1107
1177
|
return this;
|
|
1108
1178
|
}
|
|
@@ -1675,24 +1745,13 @@ function fetchIt(url, controlOptions) {
|
|
|
1675
1745
|
|
|
1676
1746
|
this[lastFetchedDataSymbol] = map;
|
|
1677
1747
|
|
|
1678
|
-
let result;
|
|
1679
|
-
const selection = this.getOption("selection");
|
|
1680
|
-
let newValue = [];
|
|
1681
|
-
if (selection) {
|
|
1682
|
-
newValue = selection;
|
|
1683
|
-
} else if (this.hasAttribute("value")) {
|
|
1684
|
-
newValue = this.getAttribute("value");
|
|
1685
|
-
}
|
|
1686
|
-
|
|
1687
|
-
result = setSelection.call(this, newValue);
|
|
1688
|
-
|
|
1689
1748
|
queueMicrotask(() => {
|
|
1690
1749
|
checkOptionState.call(this);
|
|
1691
1750
|
setTotalText.call(this);
|
|
1692
1751
|
updatePopper.call(this);
|
|
1693
1752
|
setStatusOrRemoveBadges.call(this, "closed");
|
|
1694
1753
|
|
|
1695
|
-
resolve(
|
|
1754
|
+
resolve();
|
|
1696
1755
|
});
|
|
1697
1756
|
|
|
1698
1757
|
return;
|
|
@@ -1831,6 +1890,7 @@ function getSummaryTemplate() {
|
|
|
1831
1890
|
*/
|
|
1832
1891
|
function parseSlotsToOptions() {
|
|
1833
1892
|
let options = this.getOption("options");
|
|
1893
|
+
const currentOptions = options;
|
|
1834
1894
|
if (!isIterable(options)) {
|
|
1835
1895
|
options = [];
|
|
1836
1896
|
}
|
|
@@ -1858,6 +1918,8 @@ function parseSlotsToOptions() {
|
|
|
1858
1918
|
});
|
|
1859
1919
|
|
|
1860
1920
|
this.setOption("options", options);
|
|
1921
|
+
const version = bumpOptionsVersion.call(this);
|
|
1922
|
+
scheduleSelectionSync.call(this, version);
|
|
1861
1923
|
}
|
|
1862
1924
|
|
|
1863
1925
|
/**
|
|
@@ -2044,6 +2106,13 @@ function initOptionObserver() {
|
|
|
2044
2106
|
|
|
2045
2107
|
self.attachObserver(
|
|
2046
2108
|
new Observer(function () {
|
|
2109
|
+
const options = self.getOption("options");
|
|
2110
|
+
if (options !== self[optionsSnapshotSymbol]) {
|
|
2111
|
+
self[optionsSnapshotSymbol] = options;
|
|
2112
|
+
const version = bumpOptionsVersion.call(self);
|
|
2113
|
+
scheduleSelectionSync.call(self, version);
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2047
2116
|
new Processing(() => {
|
|
2048
2117
|
try {
|
|
2049
2118
|
self.updateI18n();
|
|
@@ -2785,6 +2854,11 @@ function gatherState() {
|
|
|
2785
2854
|
throw new Error("no shadow-root is defined");
|
|
2786
2855
|
}
|
|
2787
2856
|
|
|
2857
|
+
const inputElements = this.shadowRoot.querySelectorAll(`input[type=${type}]`);
|
|
2858
|
+
if (inputElements.length === 0) {
|
|
2859
|
+
return this;
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2788
2862
|
let filteredSelection = [];
|
|
2789
2863
|
if (type === "radio") {
|
|
2790
2864
|
const selection = [];
|
|
@@ -2802,7 +2876,7 @@ function gatherState() {
|
|
|
2802
2876
|
filteredSelection = selection;
|
|
2803
2877
|
} else {
|
|
2804
2878
|
const selection = [...this.getOption("selection", [])];
|
|
2805
|
-
const allElements =
|
|
2879
|
+
const allElements = inputElements;
|
|
2806
2880
|
const checkedElements = this.shadowRoot.querySelectorAll(
|
|
2807
2881
|
`input[type=${type}]:checked`,
|
|
2808
2882
|
);
|
|
@@ -3006,6 +3080,10 @@ function areOptionsAvailableAndInitInternal() {
|
|
|
3006
3080
|
|
|
3007
3081
|
if (updated) {
|
|
3008
3082
|
this.setOption("options", options);
|
|
3083
|
+
if (options === currentOptions) {
|
|
3084
|
+
const version = bumpOptionsVersion.call(this);
|
|
3085
|
+
scheduleSelectionSync.call(this, version);
|
|
3086
|
+
}
|
|
3009
3087
|
}
|
|
3010
3088
|
|
|
3011
3089
|
setStatusOrRemoveBadges.call(this);
|
|
@@ -3036,11 +3114,19 @@ function checkOptionState() {
|
|
|
3036
3114
|
return a.value;
|
|
3037
3115
|
});
|
|
3038
3116
|
|
|
3117
|
+
const CLASSNAME = "selected";
|
|
3039
3118
|
for (const e of elements) {
|
|
3119
|
+
const parent = e.closest(`[${ATTRIBUTE_ROLE}=option]`);
|
|
3040
3120
|
if (checkedValues.indexOf(e.value) !== -1) {
|
|
3041
3121
|
if (e.checked !== true) e.checked = true;
|
|
3122
|
+
if (parent) {
|
|
3123
|
+
parent.classList.add(CLASSNAME);
|
|
3124
|
+
}
|
|
3042
3125
|
} else {
|
|
3043
3126
|
if (e.checked !== false) e.checked = false;
|
|
3127
|
+
if (parent) {
|
|
3128
|
+
parent.classList.remove(CLASSNAME);
|
|
3129
|
+
}
|
|
3044
3130
|
}
|
|
3045
3131
|
}
|
|
3046
3132
|
}
|
|
@@ -3191,6 +3277,11 @@ function setSelection(selection) {
|
|
|
3191
3277
|
|
|
3192
3278
|
selection = resultSelection;
|
|
3193
3279
|
|
|
3280
|
+
if (!isInteger(this[selectionVersionSymbol])) {
|
|
3281
|
+
this[selectionVersionSymbol] = 0;
|
|
3282
|
+
}
|
|
3283
|
+
this[selectionVersionSymbol] += 1;
|
|
3284
|
+
|
|
3194
3285
|
this.setOption("selection", selection);
|
|
3195
3286
|
|
|
3196
3287
|
checkOptionState.call(this);
|
|
@@ -916,14 +916,14 @@ function getTemplate() {
|
|
|
916
916
|
// language=HTML
|
|
917
917
|
return `
|
|
918
918
|
<div data-monster-role="control" part="control">
|
|
919
|
-
<div class="prev" data-monster-role="prev" part="prev">
|
|
919
|
+
<div class="prev hidden" data-monster-role="prev" part="prev">
|
|
920
920
|
<slot name="prev"></slot>
|
|
921
921
|
</div>
|
|
922
922
|
<div data-monster-role="slider" part="slides">
|
|
923
923
|
<slot></slot>
|
|
924
924
|
</div>
|
|
925
|
-
<div data-monster-role="thumbnails" part="thumbnails"></div>
|
|
926
|
-
<div class="next" data-monster-role="next" part="next">
|
|
925
|
+
<div class="hidden" data-monster-role="thumbnails" part="thumbnails"></div>
|
|
926
|
+
<div class="next hidden" data-monster-role="next" part="next">
|
|
927
927
|
<slot name="next"></slot>
|
|
928
928
|
</div>
|
|
929
929
|
</div>`;
|
|
@@ -98,6 +98,12 @@ const attributeObserverSymbol = Symbol.for(
|
|
|
98
98
|
const attributeMutationObserverSymbol = Symbol(
|
|
99
99
|
"@schukai/monster/dom/@@mutationObserver",
|
|
100
100
|
);
|
|
101
|
+
const childMutationObserverSymbol = Symbol(
|
|
102
|
+
"@schukai/monster/dom/@@childMutationObserver",
|
|
103
|
+
);
|
|
104
|
+
const childMutationTimerSymbol = Symbol(
|
|
105
|
+
"@schukai/monster/dom/@@childMutationTimer",
|
|
106
|
+
);
|
|
101
107
|
|
|
102
108
|
/**
|
|
103
109
|
* @private
|
|
@@ -221,6 +227,9 @@ class CustomElement extends HTMLElement {
|
|
|
221
227
|
this[initMethodSymbol]();
|
|
222
228
|
initOptionObserver.call(this);
|
|
223
229
|
this[scriptHostElementSymbol] = [];
|
|
230
|
+
// Catch attribute changes made before connectedCallback runs.
|
|
231
|
+
attachAttributeChangeMutationObserver.call(this);
|
|
232
|
+
attachChildMutationObserver.call(this);
|
|
224
233
|
}
|
|
225
234
|
|
|
226
235
|
/**
|
|
@@ -679,6 +688,14 @@ class CustomElement extends HTMLElement {
|
|
|
679
688
|
connectedCallback() {
|
|
680
689
|
// Check if the object has already been initialized
|
|
681
690
|
if (!hasObjectLink(this, customElementUpdaterLinkSymbol)) {
|
|
691
|
+
try {
|
|
692
|
+
initOptionsFromAttributes(
|
|
693
|
+
this,
|
|
694
|
+
this[internalSymbol].getSubject()?.["options"],
|
|
695
|
+
);
|
|
696
|
+
} catch (e) {
|
|
697
|
+
addErrorAttribute(this, e);
|
|
698
|
+
}
|
|
682
699
|
// If not, call the assembleMethod to initialize the object
|
|
683
700
|
this[assembleMethodSymbol]();
|
|
684
701
|
}
|
|
@@ -874,6 +891,65 @@ function attachAttributeChangeMutationObserver() {
|
|
|
874
891
|
}
|
|
875
892
|
}
|
|
876
893
|
|
|
894
|
+
/**
|
|
895
|
+
* @private
|
|
896
|
+
* @this CustomElement
|
|
897
|
+
*/
|
|
898
|
+
function attachChildMutationObserver() {
|
|
899
|
+
const self = this;
|
|
900
|
+
|
|
901
|
+
if (self[childMutationObserverSymbol]) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
if (self.getOption("features.mutationObserver") !== true) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
self[childMutationObserverSymbol] = new MutationObserver((mutations) => {
|
|
910
|
+
let hasAdditions = false;
|
|
911
|
+
for (const mutation of mutations) {
|
|
912
|
+
if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
|
|
913
|
+
hasAdditions = true;
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
if (!hasAdditions) {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if (self[childMutationTimerSymbol]) {
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
self[childMutationTimerSymbol] = setTimeout(() => {
|
|
927
|
+
self[childMutationTimerSymbol] = null;
|
|
928
|
+
if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
const updaters = getLinkedObjects(self, customElementUpdaterLinkSymbol);
|
|
933
|
+
for (const list of updaters) {
|
|
934
|
+
for (const updater of list) {
|
|
935
|
+
updater.run().catch((e) => {
|
|
936
|
+
addErrorAttribute(self, e);
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}, 50);
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
try {
|
|
944
|
+
self[childMutationObserverSymbol].observe(self, {
|
|
945
|
+
childList: true,
|
|
946
|
+
subtree: true,
|
|
947
|
+
});
|
|
948
|
+
} catch (e) {
|
|
949
|
+
addErrorAttribute(self, e);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
877
953
|
/**
|
|
878
954
|
* @this CustomElement
|
|
879
955
|
* @private
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { Pathfinder } from "../../data/pathfinder.mjs";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
isFunction,
|
|
18
|
+
isBoolean,
|
|
19
|
+
isString,
|
|
20
|
+
isObject,
|
|
21
|
+
isNumber,
|
|
22
|
+
isArray,
|
|
23
|
+
isInteger,
|
|
24
|
+
} from "../../types/is.mjs";
|
|
17
25
|
import { attributeObserverSymbol } from "../customelement.mjs";
|
|
18
26
|
import { extractKeys } from "./extract-keys.mjs";
|
|
19
27
|
|
|
@@ -77,15 +85,27 @@ function setOptionFromAttribute(
|
|
|
77
85
|
value = mapping[optionName](value);
|
|
78
86
|
}
|
|
79
87
|
|
|
80
|
-
|
|
81
|
-
if (
|
|
88
|
+
let optionValue = finder.getVia(optionName);
|
|
89
|
+
if (optionValue === null || optionValue === undefined) {
|
|
90
|
+
optionValue = value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (optionValue === null || optionValue === undefined) {
|
|
94
|
+
value = null;
|
|
95
|
+
} else if (isBoolean(optionValue)) {
|
|
82
96
|
value = value === "true";
|
|
83
|
-
} else if (
|
|
97
|
+
} else if (isInteger(optionValue)) {
|
|
98
|
+
value = Number(value);
|
|
99
|
+
} else if (isNumber(optionValue)) {
|
|
84
100
|
value = Number(value);
|
|
85
|
-
} else if (
|
|
101
|
+
} else if (isString(optionValue)) {
|
|
86
102
|
value = String(value);
|
|
87
|
-
} else if (
|
|
103
|
+
} else if (isObject(optionValue)) {
|
|
88
104
|
value = JSON.parse(value);
|
|
105
|
+
} else if (isArray(optionValue)) {
|
|
106
|
+
value = value.split("::");
|
|
107
|
+
} else {
|
|
108
|
+
value = optionValue;
|
|
89
109
|
}
|
|
90
110
|
|
|
91
111
|
finder.setVia(optionName, value);
|