@schukai/monster 3.72.0 → 3.73.0
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 +9 -0
- package/package.json +1 -1
- package/source/components/datatable/dataset.mjs +2 -6
- package/source/components/form/context-help.mjs +1 -1
- package/source/components/form/form.mjs +180 -6
- 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 +426 -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,346 @@ 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
|
+
console.log(currentNode);
|
|
240
|
+
|
|
241
|
+
currentNode.click();
|
|
242
|
+
|
|
243
|
+
let intend = parseInt(currentNode.getAttribute(ATTRIBUTE_INTEND));
|
|
244
|
+
|
|
245
|
+
if (intend > 0) {
|
|
246
|
+
let ref = currentNode.previousElementSibling;
|
|
247
|
+
while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
248
|
+
const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
|
|
249
|
+
|
|
250
|
+
if (isNaN(i)) {
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (i < intend) {
|
|
255
|
+
if (ref.getAttribute("data-monster-state") !== "open") {
|
|
256
|
+
ref.click();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (i === 0) {
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
intend = i;
|
|
263
|
+
}
|
|
264
|
+
ref = ref.previousElementSibling;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
270
268
|
}
|
|
271
269
|
|
|
272
270
|
/**
|
|
273
271
|
* @private
|
|
274
272
|
*/
|
|
275
273
|
function copyIconMap() {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
274
|
+
const nodes = getSlottedElements.call(this, "svg", null);
|
|
275
|
+
if (nodes.size > 0) {
|
|
276
|
+
for (const node of nodes) {
|
|
277
|
+
this.shadowRoot.appendChild(node);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
282
280
|
}
|
|
283
281
|
|
|
284
282
|
/**
|
|
285
283
|
* @private
|
|
286
284
|
*/
|
|
287
285
|
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;
|
|
286
|
+
const selector = this.getOption("datasource.selector");
|
|
287
|
+
|
|
288
|
+
if (isString(selector)) {
|
|
289
|
+
const element = findElementWithSelectorUpwards(this, selector);
|
|
290
|
+
if (element === null) {
|
|
291
|
+
throw new Error("the selector must match exactly one element");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (!(element instanceof HTMLElement)) {
|
|
295
|
+
throw new TypeError("the element must be an HTMLElement");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
customElements.whenDefined(element.tagName.toLocaleLowerCase()).then(() => {
|
|
299
|
+
if (!(element instanceof Datasource)) {
|
|
300
|
+
throw new TypeError("the element must be a datasource");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
this[datasourceLinkedElementSymbol] = element;
|
|
304
|
+
|
|
305
|
+
handleDataSourceChanges.call(this);
|
|
306
|
+
element.datasource.attachObserver(
|
|
307
|
+
new Observer(handleDataSourceChanges.bind(this)),
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
this.attachObserver(
|
|
311
|
+
new Observer(() => {
|
|
312
|
+
if (this[preventChangeSymbol] === true) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
this[preventChangeSymbol] = true;
|
|
316
|
+
importEntries.call(this);
|
|
317
|
+
}),
|
|
318
|
+
);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
this[openEntryEventHandlerSymbol] = (event) => {
|
|
323
|
+
const container = findTargetElementFromEvent(
|
|
324
|
+
event,
|
|
325
|
+
ATTRIBUTE_ROLE,
|
|
326
|
+
"entry",
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
if (!(container instanceof HTMLElement)) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const index = container
|
|
334
|
+
.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
|
|
335
|
+
.split("-")
|
|
336
|
+
.pop();
|
|
337
|
+
|
|
338
|
+
const currentEntry = this.getOption("entries." + index);
|
|
339
|
+
|
|
340
|
+
if (currentEntry["has-children"] === false) {
|
|
341
|
+
const doAction = this.getOption("actions.select");
|
|
342
|
+
|
|
343
|
+
this.shadowRoot
|
|
344
|
+
.querySelectorAll("[data-monster-role=entry].selected")
|
|
345
|
+
.forEach((entry) => {
|
|
346
|
+
entry.classList.remove("selected");
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
let intend = currentEntry.intend;
|
|
350
|
+
if (intend > 0) {
|
|
351
|
+
let ref = container.previousElementSibling;
|
|
352
|
+
while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
353
|
+
const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
|
|
354
|
+
|
|
355
|
+
if (isNaN(i)) {
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (i < intend) {
|
|
360
|
+
ref.classList.add("selected");
|
|
361
|
+
if (i === 0) {
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
intend = i;
|
|
365
|
+
}
|
|
366
|
+
ref = ref.previousElementSibling;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
container.classList.add("selected");
|
|
371
|
+
|
|
372
|
+
if (isFunction(doAction)) {
|
|
373
|
+
doAction.call(this, currentEntry, index);
|
|
374
|
+
}
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const currentState = this.getOption("entries." + index + ".state");
|
|
379
|
+
|
|
380
|
+
const newState = currentState === "close" ? "open" : "close";
|
|
381
|
+
|
|
382
|
+
const doAction = this.getOption("actions." + newState);
|
|
383
|
+
if (isFunction(doAction)) {
|
|
384
|
+
doAction.call(this, this.getOption("entries." + index), index);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
this.setOption("entries." + index + ".state", newState);
|
|
388
|
+
const newVisibility = newState === "open" ? "visible" : "hidden";
|
|
389
|
+
|
|
390
|
+
if (container.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
391
|
+
const intend = container.getAttribute(ATTRIBUTE_INTEND);
|
|
392
|
+
let ref = container.nextElementSibling;
|
|
393
|
+
const childIntend = parseInt(intend) + 1;
|
|
394
|
+
|
|
395
|
+
const cmp = (a, b) => {
|
|
396
|
+
if (newState === "open") {
|
|
397
|
+
return a === b;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return a >= b;
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
|
|
404
|
+
const refIntend = ref.getAttribute(ATTRIBUTE_INTEND);
|
|
405
|
+
|
|
406
|
+
if (!cmp(parseInt(refIntend), childIntend)) {
|
|
407
|
+
if (refIntend === intend) {
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
ref = ref.nextElementSibling;
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const refIndex = ref
|
|
415
|
+
.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
|
|
416
|
+
.split("-")
|
|
417
|
+
.pop();
|
|
418
|
+
|
|
419
|
+
this.setOption("entries." + refIndex + ".visibility", newVisibility);
|
|
420
|
+
|
|
421
|
+
if (newState === "close") {
|
|
422
|
+
this.setOption("entries." + refIndex + ".state", "close");
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
ref = ref.nextElementSibling;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
const types = this.getOption("toggleEventType", ["click"]);
|
|
431
|
+
for (const [, type] of Object.entries(types)) {
|
|
432
|
+
this.shadowRoot.addEventListener(type, this[openEntryEventHandlerSymbol]);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return this;
|
|
441
436
|
}
|
|
442
437
|
|
|
443
438
|
/**
|
|
444
439
|
* @private
|
|
445
440
|
* @this {TreeMenu}
|
|
446
441
|
*/
|
|
447
|
-
function initObserver() {
|
|
448
|
-
}
|
|
442
|
+
function initObserver() {}
|
|
449
443
|
|
|
450
444
|
/**
|
|
451
445
|
* Import Menu Entries from dataset
|
|
@@ -456,61 +450,60 @@ function initObserver() {
|
|
|
456
450
|
* @private
|
|
457
451
|
*/
|
|
458
452
|
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;
|
|
453
|
+
const data = this.getOption("data");
|
|
454
|
+
this[internalNodesSymbol] = new Map();
|
|
455
|
+
|
|
456
|
+
const mappingOptions = this.getOption("mapping", {});
|
|
457
|
+
|
|
458
|
+
const filter = mappingOptions?.["filter"];
|
|
459
|
+
const rootReferences = mappingOptions?.["rootReferences"];
|
|
460
|
+
|
|
461
|
+
const id = this.getOption("mapping.idTemplate");
|
|
462
|
+
const parentKey = this.getOption("mapping.parentKey");
|
|
463
|
+
|
|
464
|
+
const selector = mappingOptions?.["selector"];
|
|
465
|
+
|
|
466
|
+
let nodes;
|
|
467
|
+
try {
|
|
468
|
+
nodes = buildTree(data, selector, id, parentKey, {
|
|
469
|
+
filter,
|
|
470
|
+
rootReferences,
|
|
471
|
+
});
|
|
472
|
+
} catch (error) {
|
|
473
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const options = [];
|
|
477
|
+
for (const node of nodes) {
|
|
478
|
+
const iterator = new NodeRecursiveIterator(node);
|
|
479
|
+
for (const n of iterator) {
|
|
480
|
+
const formattedValues = formatKeyLabel.call(this, n);
|
|
481
|
+
|
|
482
|
+
const label = formattedValues?.label;
|
|
483
|
+
const value = formattedValues?.value;
|
|
484
|
+
const icon = formattedValues?.icon;
|
|
485
|
+
const intend = n.level;
|
|
486
|
+
|
|
487
|
+
const visibility = intend > 0 ? "hidden" : "visible";
|
|
488
|
+
const state = "close";
|
|
489
|
+
|
|
490
|
+
this[internalNodesSymbol].set(value, n);
|
|
491
|
+
|
|
492
|
+
options.push({
|
|
493
|
+
value,
|
|
494
|
+
label,
|
|
495
|
+
icon,
|
|
496
|
+
intend,
|
|
497
|
+
state,
|
|
498
|
+
visibility,
|
|
499
|
+
["has-children"]: n.hasChildNodes(),
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
this.setOption("entries", options);
|
|
505
|
+
|
|
506
|
+
return this;
|
|
514
507
|
}
|
|
515
508
|
|
|
516
509
|
/**
|
|
@@ -520,27 +513,27 @@ function importEntries() {
|
|
|
520
513
|
* @private
|
|
521
514
|
*/
|
|
522
515
|
function formatKeyLabel(node) {
|
|
523
|
-
|
|
516
|
+
validateInstance(node, Node);
|
|
524
517
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
518
|
+
const label = new Formatter(node.value).format(
|
|
519
|
+
this.getOption("mapping.labelTemplate"),
|
|
520
|
+
);
|
|
528
521
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
522
|
+
const value = new Formatter(node.value).format(
|
|
523
|
+
this.getOption("mapping.valueTemplate"),
|
|
524
|
+
);
|
|
532
525
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
526
|
+
const iconID = new Formatter(node.value).format(
|
|
527
|
+
this.getOption("mapping.iconTemplate"),
|
|
528
|
+
);
|
|
536
529
|
|
|
537
|
-
|
|
530
|
+
const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><use xlink:href="#${iconID}"></use></svg>`;
|
|
538
531
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
532
|
+
return {
|
|
533
|
+
value,
|
|
534
|
+
label,
|
|
535
|
+
icon,
|
|
536
|
+
};
|
|
544
537
|
}
|
|
545
538
|
|
|
546
539
|
/**
|
|
@@ -548,15 +541,15 @@ function formatKeyLabel(node) {
|
|
|
548
541
|
* @return {TreeMenu}
|
|
549
542
|
*/
|
|
550
543
|
function initControlReferences() {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
544
|
+
if (!this.shadowRoot) {
|
|
545
|
+
throw new Error("no shadow-root is defined");
|
|
546
|
+
}
|
|
554
547
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
548
|
+
this[controlElementSymbol] = this.shadowRoot.querySelector(
|
|
549
|
+
"[data-monster-role=control]",
|
|
550
|
+
);
|
|
558
551
|
|
|
559
|
-
|
|
552
|
+
return this;
|
|
560
553
|
}
|
|
561
554
|
|
|
562
555
|
/**
|
|
@@ -564,8 +557,8 @@ function initControlReferences() {
|
|
|
564
557
|
* @return {string}
|
|
565
558
|
*/
|
|
566
559
|
function getTemplate() {
|
|
567
|
-
|
|
568
|
-
|
|
560
|
+
// language=HTML
|
|
561
|
+
return `
|
|
569
562
|
<slot></slot>
|
|
570
563
|
|
|
571
564
|
<template id="entries">
|