@schukai/monster 3.72.0 → 3.73.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 +28 -12
- package/package.json +1 -1
- package/source/components/datatable/dataset.mjs +2 -6
- package/source/components/form/context-error.mjs +0 -1
- package/source/components/form/context-help.mjs +1 -1
- package/source/components/form/form.mjs +196 -7
- package/source/components/form/stylesheet/form.mjs +13 -6
- package/source/components/layout/tabs.mjs +0 -1
- package/source/components/tree-menu/stylesheet/tree-menu.mjs +13 -6
- package/source/components/tree-menu/tree-menu.mjs +424 -433
- package/source/dom/constants.mjs +18 -0
- package/source/dom/slotted.mjs +90 -89
- package/source/dom/updater.mjs +2 -0
|
@@ -12,37 +12,38 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {buildTree} from "../../data/buildtree.mjs";
|
|
16
|
-
import {Datasource} from "../datatable/datasource.mjs";
|
|
17
|
-
import {addAttributeToken} from "../../dom/attributes.mjs";
|
|
15
|
+
import { buildTree } from "../../data/buildtree.mjs";
|
|
16
|
+
import { Datasource } from "../datatable/datasource.mjs";
|
|
17
|
+
import { addAttributeToken } from "../../dom/attributes.mjs";
|
|
18
18
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
ATTRIBUTE_ERRORMESSAGE,
|
|
20
|
+
ATTRIBUTE_ROLE,
|
|
21
|
+
ATTRIBUTE_UPDATER_INSERT_REFERENCE,
|
|
22
22
|
} from "../../dom/constants.mjs";
|
|
23
23
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
assembleMethodSymbol,
|
|
25
|
+
CustomElement,
|
|
26
|
+
getSlottedElements,
|
|
27
|
+
initMethodSymbol,
|
|
28
|
+
registerCustomElement,
|
|
28
29
|
} from "../../dom/customelement.mjs";
|
|
29
|
-
import {findTargetElementFromEvent} from "../../dom/events.mjs";
|
|
30
|
-
import {findElementWithSelectorUpwards} from "../../dom/util.mjs";
|
|
31
|
-
import {Formatter} from "../../text/formatter.mjs";
|
|
32
|
-
import {isFunction, isString} from "../../types/is.mjs";
|
|
33
|
-
import {Node} from "../../types/node.mjs";
|
|
34
|
-
import {NodeRecursiveIterator} from "../../types/noderecursiveiterator.mjs";
|
|
35
|
-
import {Observer} from "../../types/observer.mjs";
|
|
36
|
-
import {validateInstance} from "../../types/validate.mjs";
|
|
30
|
+
import { findTargetElementFromEvent } from "../../dom/events.mjs";
|
|
31
|
+
import { findElementWithSelectorUpwards } from "../../dom/util.mjs";
|
|
32
|
+
import { Formatter } from "../../text/formatter.mjs";
|
|
33
|
+
import { isFunction, isString } from "../../types/is.mjs";
|
|
34
|
+
import { Node } from "../../types/node.mjs";
|
|
35
|
+
import { NodeRecursiveIterator } from "../../types/noderecursiveiterator.mjs";
|
|
36
|
+
import { Observer } from "../../types/observer.mjs";
|
|
37
|
+
import { validateInstance } from "../../types/validate.mjs";
|
|
37
38
|
import {
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
datasourceLinkedElementSymbol,
|
|
40
|
+
handleDataSourceChanges,
|
|
40
41
|
} from "../datatable/util.mjs";
|
|
41
|
-
import {ATTRIBUTE_INTEND} from "./../constants.mjs";
|
|
42
|
-
import {CommonStyleSheet} from "../stylesheet/common.mjs";
|
|
43
|
-
import {TreeMenuStyleSheet} from "./stylesheet/tree-menu.mjs";
|
|
42
|
+
import { ATTRIBUTE_INTEND } from "./../constants.mjs";
|
|
43
|
+
import { CommonStyleSheet } from "../stylesheet/common.mjs";
|
|
44
|
+
import { TreeMenuStyleSheet } from "./stylesheet/tree-menu.mjs";
|
|
44
45
|
|
|
45
|
-
export {TreeMenu};
|
|
46
|
+
export { TreeMenu };
|
|
46
47
|
|
|
47
48
|
/**
|
|
48
49
|
* @private
|
|
@@ -99,353 +100,344 @@ const openEntryEventHandlerSymbol = Symbol("openEntryEventHandler");
|
|
|
99
100
|
* @fires Monster.Components.TreeMenu.event:monster-fetched
|
|
100
101
|
*/
|
|
101
102
|
class TreeMenu extends CustomElement {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
103
|
+
constructor() {
|
|
104
|
+
super();
|
|
105
|
+
this[preventChangeSymbol] = false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* This method is called internal and should not be called directly.
|
|
110
|
+
*
|
|
111
|
+
* The defaults can be set either directly in the object or via an attribute in the HTML tag.
|
|
112
|
+
* The value of the attribute `data-monster-options` in the HTML tag must be a JSON string.
|
|
113
|
+
*
|
|
114
|
+
* ```
|
|
115
|
+
* <monster-treemenu data-monster-options="{}"></monster-treemenu>
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* Since 1.18.0 the JSON can be specified as a DataURI.
|
|
119
|
+
*
|
|
120
|
+
* ```
|
|
121
|
+
* new Monster.Types.DataUrl(btoa(JSON.stringify({
|
|
122
|
+
* shadowMode: 'open',
|
|
123
|
+
* })),'application/json',true).toString()
|
|
124
|
+
* ```
|
|
125
|
+
* @property {Object} templates Template definitions
|
|
126
|
+
* @property {string} templates.main Main template
|
|
127
|
+
* @property {Datasource} datasource data source
|
|
128
|
+
* @property {Object} mapping
|
|
129
|
+
* @property {String} mapping.selector=* Path to select the appropriate entries
|
|
130
|
+
* @property {String} mapping.labelTemplate="" template with the label placeholders in the form ${name}, where name is the key
|
|
131
|
+
* @property {String} mapping.keyTemplate="" template with the key placeholders in the form ${name}, where name is the key
|
|
132
|
+
* @property {String} mapping.rootReferences=['0', undefined, null]
|
|
133
|
+
* @property {String} mapping.idTemplate=id
|
|
134
|
+
* @property {String} mapping.parentKey=parent
|
|
135
|
+
* @property {String} mapping.selection
|
|
136
|
+
*/
|
|
137
|
+
get defaults() {
|
|
138
|
+
return Object.assign({}, super.defaults, {
|
|
139
|
+
classes: {
|
|
140
|
+
control: "monster-theme-primary-1",
|
|
141
|
+
label: "monster-theme-primary-1",
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
mapping: {
|
|
145
|
+
rootReferences: ["0", undefined, null],
|
|
146
|
+
idTemplate: "id",
|
|
147
|
+
parentKey: "parent",
|
|
148
|
+
selector: "*",
|
|
149
|
+
labelTemplate: "",
|
|
150
|
+
valueTemplate: "",
|
|
151
|
+
iconTemplate: "",
|
|
152
|
+
filter: undefined,
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
templates: {
|
|
156
|
+
main: getTemplate(),
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
datasource: {
|
|
160
|
+
selector: null,
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
actions: {
|
|
164
|
+
open: null,
|
|
165
|
+
close: null,
|
|
166
|
+
select: (entry) => {
|
|
167
|
+
throw new Error("no action defined for select");
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
data: [],
|
|
172
|
+
entries: [],
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
*
|
|
178
|
+
*/
|
|
179
|
+
[initMethodSymbol]() {
|
|
180
|
+
super[initMethodSymbol]();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @return {void}
|
|
185
|
+
*/
|
|
186
|
+
[assembleMethodSymbol]() {
|
|
187
|
+
super[assembleMethodSymbol]();
|
|
188
|
+
|
|
189
|
+
initControlReferences.call(this);
|
|
190
|
+
initEventHandler.call(this);
|
|
191
|
+
initObserver.call(this);
|
|
192
|
+
setTimeout(() => {
|
|
193
|
+
copyIconMap.call(this);
|
|
194
|
+
}, 0);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* This method is called internal and should not be called directly.
|
|
199
|
+
*
|
|
200
|
+
* @return {CSSStyleSheet[]}
|
|
201
|
+
*/
|
|
202
|
+
static getCSSStyleSheet() {
|
|
203
|
+
return [CommonStyleSheet, TreeMenuStyleSheet];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* This method is called internal and should not be called directly.
|
|
208
|
+
*
|
|
209
|
+
* @return {string}
|
|
210
|
+
*/
|
|
211
|
+
static getTag() {
|
|
212
|
+
return "monster-tree-menu";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @param {string} value
|
|
217
|
+
* @param value
|
|
218
|
+
*/
|
|
219
|
+
selectEntry(value) {
|
|
220
|
+
this.shadowRoot
|
|
221
|
+
.querySelectorAll("[data-monster-role=entry]")
|
|
222
|
+
.forEach((entry) => {
|
|
223
|
+
entry.classList.remove("selected");
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
value = String(value);
|
|
227
|
+
|
|
228
|
+
const entries = this.getOption("entries");
|
|
229
|
+
const index = entries.findIndex((entry) => entry.value === value);
|
|
230
|
+
|
|
231
|
+
if (index === -1) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const currentNode = this.shadowRoot.querySelector(
|
|
236
|
+
"[data-monster-insert-reference=entries-" + index + "]",
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
currentNode.click();
|
|
240
|
+
|
|
241
|
+
let intend = parseInt(currentNode.getAttribute(ATTRIBUTE_INTEND));
|
|
242
|
+
|
|
243
|
+
if (intend > 0) {
|
|
244
|
+
let ref = currentNode.previousElementSibling;
|
|
245
|
+
while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
246
|
+
const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
|
|
247
|
+
|
|
248
|
+
if (isNaN(i)) {
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (i < intend) {
|
|
253
|
+
if (ref.getAttribute("data-monster-state") !== "open") {
|
|
254
|
+
ref.click();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (i === 0) {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
intend = i;
|
|
261
|
+
}
|
|
262
|
+
ref = ref.previousElementSibling;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
270
266
|
}
|
|
271
267
|
|
|
272
268
|
/**
|
|
273
269
|
* @private
|
|
274
270
|
*/
|
|
275
271
|
function copyIconMap() {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
272
|
+
const nodes = getSlottedElements.call(this, "svg", null);
|
|
273
|
+
if (nodes.size > 0) {
|
|
274
|
+
for (const node of nodes) {
|
|
275
|
+
this.shadowRoot.appendChild(node);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
282
278
|
}
|
|
283
279
|
|
|
284
280
|
/**
|
|
285
281
|
* @private
|
|
286
282
|
*/
|
|
287
283
|
function initEventHandler() {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
return this;
|
|
284
|
+
const selector = this.getOption("datasource.selector");
|
|
285
|
+
|
|
286
|
+
if (isString(selector)) {
|
|
287
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
|
288
|
+
if (element === null) {
|
|
289
|
+
throw new Error("the selector must match exactly one element");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (!(element instanceof HTMLElement)) {
|
|
293
|
+
throw new TypeError("the element must be an HTMLElement");
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
customElements.whenDefined(element.tagName.toLocaleLowerCase()).then(() => {
|
|
297
|
+
if (!(element instanceof Datasource)) {
|
|
298
|
+
throw new TypeError("the element must be a datasource");
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
this[datasourceLinkedElementSymbol] = element;
|
|
302
|
+
|
|
303
|
+
handleDataSourceChanges.call(this);
|
|
304
|
+
element.datasource.attachObserver(
|
|
305
|
+
new Observer(handleDataSourceChanges.bind(this)),
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
this.attachObserver(
|
|
309
|
+
new Observer(() => {
|
|
310
|
+
if (this[preventChangeSymbol] === true) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this[preventChangeSymbol] = true;
|
|
314
|
+
importEntries.call(this);
|
|
315
|
+
}),
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
this[openEntryEventHandlerSymbol] = (event) => {
|
|
321
|
+
const container = findTargetElementFromEvent(
|
|
322
|
+
event,
|
|
323
|
+
ATTRIBUTE_ROLE,
|
|
324
|
+
"entry",
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
if (!(container instanceof HTMLElement)) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const index = container
|
|
332
|
+
.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
|
|
333
|
+
.split("-")
|
|
334
|
+
.pop();
|
|
335
|
+
|
|
336
|
+
const currentEntry = this.getOption("entries." + index);
|
|
337
|
+
|
|
338
|
+
if (currentEntry["has-children"] === false) {
|
|
339
|
+
const doAction = this.getOption("actions.select");
|
|
340
|
+
|
|
341
|
+
this.shadowRoot
|
|
342
|
+
.querySelectorAll("[data-monster-role=entry].selected")
|
|
343
|
+
.forEach((entry) => {
|
|
344
|
+
entry.classList.remove("selected");
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
let intend = currentEntry.intend;
|
|
348
|
+
if (intend > 0) {
|
|
349
|
+
let ref = container.previousElementSibling;
|
|
350
|
+
while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
351
|
+
const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
|
|
352
|
+
|
|
353
|
+
if (isNaN(i)) {
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (i < intend) {
|
|
358
|
+
ref.classList.add("selected");
|
|
359
|
+
if (i === 0) {
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
intend = i;
|
|
363
|
+
}
|
|
364
|
+
ref = ref.previousElementSibling;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
container.classList.add("selected");
|
|
369
|
+
|
|
370
|
+
if (isFunction(doAction)) {
|
|
371
|
+
doAction.call(this, currentEntry, index);
|
|
372
|
+
}
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const currentState = this.getOption("entries." + index + ".state");
|
|
377
|
+
|
|
378
|
+
const newState = currentState === "close" ? "open" : "close";
|
|
379
|
+
|
|
380
|
+
const doAction = this.getOption("actions." + newState);
|
|
381
|
+
if (isFunction(doAction)) {
|
|
382
|
+
doAction.call(this, this.getOption("entries." + index), index);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
this.setOption("entries." + index + ".state", newState);
|
|
386
|
+
const newVisibility = newState === "open" ? "visible" : "hidden";
|
|
387
|
+
|
|
388
|
+
if (container.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
389
|
+
const intend = container.getAttribute(ATTRIBUTE_INTEND);
|
|
390
|
+
let ref = container.nextElementSibling;
|
|
391
|
+
const childIntend = parseInt(intend) + 1;
|
|
392
|
+
|
|
393
|
+
const cmp = (a, b) => {
|
|
394
|
+
if (newState === "open") {
|
|
395
|
+
return a === b;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return a >= b;
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
402
|
+
const refIntend = ref.getAttribute(ATTRIBUTE_INTEND);
|
|
403
|
+
|
|
404
|
+
if (!cmp(parseInt(refIntend), childIntend)) {
|
|
405
|
+
if (refIntend === intend) {
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
ref = ref.nextElementSibling;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const refIndex = ref
|
|
413
|
+
.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
|
|
414
|
+
.split("-")
|
|
415
|
+
.pop();
|
|
416
|
+
|
|
417
|
+
this.setOption("entries." + refIndex + ".visibility", newVisibility);
|
|
418
|
+
|
|
419
|
+
if (newState === "close") {
|
|
420
|
+
this.setOption("entries." + refIndex + ".state", "close");
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
ref = ref.nextElementSibling;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const types = this.getOption("toggleEventType", ["click"]);
|
|
429
|
+
for (const [, type] of Object.entries(types)) {
|
|
430
|
+
this.shadowRoot.addEventListener(type, this[openEntryEventHandlerSymbol]);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return this;
|
|
441
434
|
}
|
|
442
435
|
|
|
443
436
|
/**
|
|
444
437
|
* @private
|
|
445
438
|
* @this {TreeMenu}
|
|
446
439
|
*/
|
|
447
|
-
function initObserver() {
|
|
448
|
-
}
|
|
440
|
+
function initObserver() {}
|
|
449
441
|
|
|
450
442
|
/**
|
|
451
443
|
* Import Menu Entries from dataset
|
|
@@ -456,61 +448,60 @@ function initObserver() {
|
|
|
456
448
|
* @private
|
|
457
449
|
*/
|
|
458
450
|
function importEntries() {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
return this;
|
|
451
|
+
const data = this.getOption("data");
|
|
452
|
+
this[internalNodesSymbol] = new Map();
|
|
453
|
+
|
|
454
|
+
const mappingOptions = this.getOption("mapping", {});
|
|
455
|
+
|
|
456
|
+
const filter = mappingOptions?.["filter"];
|
|
457
|
+
const rootReferences = mappingOptions?.["rootReferences"];
|
|
458
|
+
|
|
459
|
+
const id = this.getOption("mapping.idTemplate");
|
|
460
|
+
const parentKey = this.getOption("mapping.parentKey");
|
|
461
|
+
|
|
462
|
+
const selector = mappingOptions?.["selector"];
|
|
463
|
+
|
|
464
|
+
let nodes;
|
|
465
|
+
try {
|
|
466
|
+
nodes = buildTree(data, selector, id, parentKey, {
|
|
467
|
+
filter,
|
|
468
|
+
rootReferences,
|
|
469
|
+
});
|
|
470
|
+
} catch (error) {
|
|
471
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const options = [];
|
|
475
|
+
for (const node of nodes) {
|
|
476
|
+
const iterator = new NodeRecursiveIterator(node);
|
|
477
|
+
for (const n of iterator) {
|
|
478
|
+
const formattedValues = formatKeyLabel.call(this, n);
|
|
479
|
+
|
|
480
|
+
const label = formattedValues?.label;
|
|
481
|
+
const value = formattedValues?.value;
|
|
482
|
+
const icon = formattedValues?.icon;
|
|
483
|
+
const intend = n.level;
|
|
484
|
+
|
|
485
|
+
const visibility = intend > 0 ? "hidden" : "visible";
|
|
486
|
+
const state = "close";
|
|
487
|
+
|
|
488
|
+
this[internalNodesSymbol].set(value, n);
|
|
489
|
+
|
|
490
|
+
options.push({
|
|
491
|
+
value,
|
|
492
|
+
label,
|
|
493
|
+
icon,
|
|
494
|
+
intend,
|
|
495
|
+
state,
|
|
496
|
+
visibility,
|
|
497
|
+
["has-children"]: n.hasChildNodes(),
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
this.setOption("entries", options);
|
|
503
|
+
|
|
504
|
+
return this;
|
|
514
505
|
}
|
|
515
506
|
|
|
516
507
|
/**
|
|
@@ -520,27 +511,27 @@ function importEntries() {
|
|
|
520
511
|
* @private
|
|
521
512
|
*/
|
|
522
513
|
function formatKeyLabel(node) {
|
|
523
|
-
|
|
514
|
+
validateInstance(node, Node);
|
|
524
515
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
516
|
+
const label = new Formatter(node.value).format(
|
|
517
|
+
this.getOption("mapping.labelTemplate"),
|
|
518
|
+
);
|
|
528
519
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
520
|
+
const value = new Formatter(node.value).format(
|
|
521
|
+
this.getOption("mapping.valueTemplate"),
|
|
522
|
+
);
|
|
532
523
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
524
|
+
const iconID = new Formatter(node.value).format(
|
|
525
|
+
this.getOption("mapping.iconTemplate"),
|
|
526
|
+
);
|
|
536
527
|
|
|
537
|
-
|
|
528
|
+
const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><use xlink:href="#${iconID}"></use></svg>`;
|
|
538
529
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
530
|
+
return {
|
|
531
|
+
value,
|
|
532
|
+
label,
|
|
533
|
+
icon,
|
|
534
|
+
};
|
|
544
535
|
}
|
|
545
536
|
|
|
546
537
|
/**
|
|
@@ -548,15 +539,15 @@ function formatKeyLabel(node) {
|
|
|
548
539
|
* @return {TreeMenu}
|
|
549
540
|
*/
|
|
550
541
|
function initControlReferences() {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
542
|
+
if (!this.shadowRoot) {
|
|
543
|
+
throw new Error("no shadow-root is defined");
|
|
544
|
+
}
|
|
554
545
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
546
|
+
this[controlElementSymbol] = this.shadowRoot.querySelector(
|
|
547
|
+
"[data-monster-role=control]",
|
|
548
|
+
);
|
|
558
549
|
|
|
559
|
-
|
|
550
|
+
return this;
|
|
560
551
|
}
|
|
561
552
|
|
|
562
553
|
/**
|
|
@@ -564,8 +555,8 @@ function initControlReferences() {
|
|
|
564
555
|
* @return {string}
|
|
565
556
|
*/
|
|
566
557
|
function getTemplate() {
|
|
567
|
-
|
|
568
|
-
|
|
558
|
+
// language=HTML
|
|
559
|
+
return `
|
|
569
560
|
<slot></slot>
|
|
570
561
|
|
|
571
562
|
<template id="entries">
|