@schukai/monster 3.91.0 → 3.92.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 +19 -0
- package/package.json +1 -1
- package/source/components/datatable/save-button.mjs +3 -0
- package/source/components/form/context-error.mjs +2 -13
- package/source/components/form/context-help.mjs +1 -1
- package/source/components/form/password.mjs +2 -2
- package/source/components/form/reload.mjs +1 -1
- package/source/components/form/shadow-reload.mjs +1 -1
- package/source/components/form/template.mjs +49 -18
- package/source/components/form/tree-select.mjs +60 -42
- package/source/components/layout/tabs.mjs +889 -825
- 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 +136 -59
@@ -12,55 +12,55 @@
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
13
13
|
*/
|
14
14
|
|
15
|
-
import {
|
16
|
-
import {
|
17
|
-
import {
|
18
|
-
import {
|
15
|
+
import {instanceSymbol} from "../../constants.mjs";
|
16
|
+
import {createPopper} from "@popperjs/core";
|
17
|
+
import {extend} from "../../data/extend.mjs";
|
18
|
+
import {Pathfinder} from "../../data/pathfinder.mjs";
|
19
19
|
import {
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
addAttributeToken,
|
21
|
+
addToObjectLink,
|
22
|
+
hasObjectLink,
|
23
23
|
} from "../../dom/attributes.mjs";
|
24
24
|
import {
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
ATTRIBUTE_ERRORMESSAGE,
|
26
|
+
ATTRIBUTE_PREFIX,
|
27
|
+
ATTRIBUTE_ROLE,
|
28
28
|
} from "../../dom/constants.mjs";
|
29
29
|
import {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
assembleMethodSymbol,
|
31
|
+
CustomElement,
|
32
|
+
getSlottedElements,
|
33
|
+
registerCustomElement,
|
34
34
|
} from "../../dom/customelement.mjs";
|
35
35
|
import {
|
36
|
-
|
37
|
-
|
36
|
+
findTargetElementFromEvent,
|
37
|
+
fireCustomEvent,
|
38
38
|
} from "../../dom/events.mjs";
|
39
|
-
import {
|
40
|
-
import {
|
41
|
-
import {
|
42
|
-
import {
|
43
|
-
import {
|
44
|
-
import {
|
45
|
-
import {
|
46
|
-
import {
|
47
|
-
import {
|
39
|
+
import {getDocument} from "../../dom/util.mjs";
|
40
|
+
import {random} from "../../math/random.mjs";
|
41
|
+
import {getGlobal} from "../../types/global.mjs";
|
42
|
+
import {ID} from "../../types/id.mjs";
|
43
|
+
import {isArray, isString} from "../../types/is.mjs";
|
44
|
+
import {TokenList} from "../../types/tokenlist.mjs";
|
45
|
+
import {clone} from "../../util/clone.mjs";
|
46
|
+
import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
|
47
|
+
import {Processing} from "../../util/processing.mjs";
|
48
48
|
import {
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
ATTRIBUTE_BUTTON_LABEL,
|
50
|
+
ATTRIBUTE_FORM_RELOAD,
|
51
|
+
ATTRIBUTE_FORM_URL,
|
52
|
+
STYLE_DISPLAY_MODE_BLOCK,
|
53
53
|
} from "../form/constants.mjs";
|
54
54
|
|
55
|
-
import {
|
56
|
-
import {
|
57
|
-
import {
|
55
|
+
import {TabsStyleSheet} from "./stylesheet/tabs.mjs";
|
56
|
+
import {loadAndAssignContent} from "../form/util/fetch.mjs";
|
57
|
+
import {ThemeStyleSheet} from "../stylesheet/theme.mjs";
|
58
58
|
import {
|
59
|
-
|
60
|
-
|
59
|
+
popperInstanceSymbol,
|
60
|
+
setEventListenersModifiers,
|
61
61
|
} from "../form/util/popper.mjs";
|
62
62
|
|
63
|
-
export {
|
63
|
+
export {Tabs};
|
64
64
|
|
65
65
|
/**
|
66
66
|
* @private
|
@@ -146,408 +146,414 @@ const resizeObserverSymbol = Symbol("resizeObserver");
|
|
146
146
|
* @fragments /fragments/components/layout/tabs/
|
147
147
|
*
|
148
148
|
* @example /examples/components/layout/tabs-simple
|
149
|
+
* @example /examples/components/layout/tabs-active
|
150
|
+
* @example /examples/components/layout/tabs-removable
|
151
|
+
*
|
152
|
+
* @issue https://localhost.alvine.dev:8443/development/issues/closed/268.html
|
149
153
|
*
|
150
154
|
* @since 3.74.0
|
151
155
|
* @copyright schukai GmbH
|
152
156
|
* @summary This CustomControl creates a tab element with a variety of options.
|
153
157
|
*/
|
154
158
|
class Tabs extends CustomElement {
|
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
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
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
|
-
|
159
|
+
/**
|
160
|
+
* This method is called by the `instanceof` operator.
|
161
|
+
* @return {symbol}
|
162
|
+
*/
|
163
|
+
static get [instanceSymbol]() {
|
164
|
+
return Symbol.for("@schukai/monster/components/layout/tabs");
|
165
|
+
}
|
166
|
+
|
167
|
+
/**
|
168
|
+
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
|
169
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
170
|
+
*
|
171
|
+
* The individual configuration values can be found in the table.
|
172
|
+
*
|
173
|
+
* @property {Object} templates Template definitions
|
174
|
+
* @property {string} templates.main Main template
|
175
|
+
* @property {Object} labels
|
176
|
+
* @property {string} labels.new-tab-label="New Tab"
|
177
|
+
* @property {Object} features
|
178
|
+
* @property {number} features.openDelay=500 Open delay in milliseconds
|
179
|
+
* @property {string} features.removeBehavior="auto" Remove behavior, auto (default), next, previous and none
|
180
|
+
* @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
|
181
|
+
* @property {String} fetch.redirect=error
|
182
|
+
* @property {String} fetch.method=GET
|
183
|
+
* @property {String} fetch.mode=same-origin
|
184
|
+
* @property {String} fetch.credentials=same-origin
|
185
|
+
* @property {Object} fetch.headers={"accept":"text/html"}}
|
186
|
+
* @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/)
|
187
|
+
* @property {string} popper.placement=bottom PopperJS placement
|
188
|
+
* @property {Object[]} modifiers={name:offset} PopperJS placement
|
189
|
+
*/
|
190
|
+
get defaults() {
|
191
|
+
return Object.assign({}, super.defaults, {
|
192
|
+
templates: {
|
193
|
+
main: getTemplate(),
|
194
|
+
},
|
195
|
+
labels: {
|
196
|
+
"new-tab-label": "New Tab",
|
197
|
+
},
|
198
|
+
buttons: {
|
199
|
+
standard: [],
|
200
|
+
popper: [],
|
201
|
+
},
|
202
|
+
fetch: {
|
203
|
+
redirect: "error",
|
204
|
+
method: "GET",
|
205
|
+
mode: "same-origin",
|
206
|
+
credentials: "same-origin",
|
207
|
+
headers: {
|
208
|
+
accept: "text/html",
|
209
|
+
},
|
210
|
+
},
|
211
|
+
|
212
|
+
features: {
|
213
|
+
openDelay: null,
|
214
|
+
removeBehavior: "auto",
|
215
|
+
},
|
216
|
+
|
217
|
+
classes: {
|
218
|
+
button: "monster-theme-primary-1",
|
219
|
+
popper: "monster-theme-primary-1",
|
220
|
+
navigation: "monster-theme-primary-1",
|
221
|
+
},
|
222
|
+
|
223
|
+
popper: {
|
224
|
+
placement: "bottom",
|
225
|
+
modifiers: [
|
226
|
+
{
|
227
|
+
name: "offset",
|
228
|
+
options: {
|
229
|
+
offset: [0, 2],
|
230
|
+
},
|
231
|
+
},
|
232
|
+
|
233
|
+
{
|
234
|
+
name: "eventListeners",
|
235
|
+
enabled: false,
|
236
|
+
},
|
237
|
+
],
|
238
|
+
},
|
239
|
+
});
|
240
|
+
}
|
241
|
+
|
242
|
+
/**
|
243
|
+
* This method is called internal and should not be called directly.
|
244
|
+
*/
|
245
|
+
[assembleMethodSymbol]() {
|
246
|
+
super[assembleMethodSymbol]();
|
247
|
+
|
248
|
+
initControlReferences.call(this);
|
249
|
+
|
250
|
+
this[dimensionsSymbol] = new Pathfinder({data: {}});
|
251
|
+
|
252
|
+
initEventHandler.call(this);
|
253
|
+
|
254
|
+
// setup structure
|
255
|
+
initTabButtons.call(this).then(() => {
|
256
|
+
initPopperSwitch.call(this);
|
257
|
+
initPopper.call(this);
|
258
|
+
attachResizeObserver.call(this);
|
259
|
+
attachTabChangeObserver.call(this);
|
260
|
+
});
|
261
|
+
}
|
262
|
+
|
263
|
+
/**
|
264
|
+
* This method is called internal and should not be called directly.
|
265
|
+
*
|
266
|
+
* @return {CSSStyleSheet[]}
|
267
|
+
*/
|
268
|
+
static getCSSStyleSheet() {
|
269
|
+
return [TabsStyleSheet];
|
270
|
+
}
|
271
|
+
|
272
|
+
/**
|
273
|
+
* This method is called internal and should not be called directly.
|
274
|
+
*
|
275
|
+
* @return {string}
|
276
|
+
*/
|
277
|
+
static getTag() {
|
278
|
+
return "monster-tabs";
|
279
|
+
}
|
280
|
+
|
281
|
+
/**
|
282
|
+
* A function that activates a tab based on the provided name.
|
283
|
+
*
|
284
|
+
* The tabs have to be named with the `data-monster-name` attribute.
|
285
|
+
*
|
286
|
+
* @param {type} idOrName - the name or id of the tab to activate
|
287
|
+
* @return {Tabs} - The current instance
|
288
|
+
*/
|
289
|
+
activeTab(idOrName) {
|
290
|
+
let found = false;
|
291
|
+
|
292
|
+
getSlottedElements.call(this).forEach((node) => {
|
293
|
+
if (found === true) {
|
294
|
+
return;
|
295
|
+
}
|
296
|
+
|
297
|
+
if (node.getAttribute("data-monster-name") === idOrName) {
|
298
|
+
this.shadowRoot
|
299
|
+
.querySelector(
|
300
|
+
`[data-monster-tab-reference="${node.getAttribute("id")}"]`,
|
301
|
+
)
|
302
|
+
.click();
|
303
|
+
found = true;
|
304
|
+
}
|
305
|
+
|
306
|
+
if (node.getAttribute("id") === idOrName) {
|
307
|
+
this.shadowRoot
|
308
|
+
.querySelector(
|
309
|
+
`[data-monster-tab-reference="${node.getAttribute("id")}"]`,
|
310
|
+
)
|
311
|
+
.click();
|
312
|
+
found = true;
|
313
|
+
}
|
314
|
+
});
|
315
|
+
|
316
|
+
return this;
|
317
|
+
}
|
318
|
+
|
319
|
+
/**
|
320
|
+
* A function that returns the name or id of the currently active tab.
|
321
|
+
*
|
322
|
+
* The tabs have to be named with the `data-monster-name` attribute.
|
323
|
+
*
|
324
|
+
* @return {string|null}
|
325
|
+
*/
|
326
|
+
getActiveTab() {
|
327
|
+
const nodes = getSlottedElements.call(this);
|
328
|
+
for (const node of nodes) {
|
329
|
+
if (node.matches(".active") === true) {
|
330
|
+
if (node.hasAttribute("data-monster-name")) {
|
331
|
+
return node.getAttribute("data-monster-name");
|
332
|
+
}
|
333
|
+
|
334
|
+
return node.getAttribute("id");
|
335
|
+
}
|
336
|
+
}
|
337
|
+
return null;
|
338
|
+
}
|
339
|
+
|
340
|
+
/**
|
341
|
+
* This method is called by the dom and should not be called directly.
|
342
|
+
*
|
343
|
+
* @return {void}
|
344
|
+
*/
|
345
|
+
connectedCallback() {
|
346
|
+
super.connectedCallback();
|
347
|
+
|
348
|
+
const document = getDocument();
|
349
|
+
|
350
|
+
for (const [, type] of Object.entries(["click", "touch"])) {
|
351
|
+
// close on outside ui-events
|
352
|
+
document.addEventListener(type, this[closeEventHandler]);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
/**
|
357
|
+
* This method is called by the dom and should not be called directly.
|
358
|
+
*
|
359
|
+
* @return {void}
|
360
|
+
*/
|
361
|
+
disconnectedCallback() {
|
362
|
+
super.disconnectedCallback();
|
363
|
+
|
364
|
+
const document = getDocument();
|
365
|
+
|
366
|
+
// close on outside ui-events
|
367
|
+
for (const [, type] of Object.entries(["click", "touch"])) {
|
368
|
+
document.removeEventListener(type, this[closeEventHandler]);
|
369
|
+
}
|
370
|
+
}
|
365
371
|
}
|
366
372
|
|
367
373
|
/**
|
368
374
|
* @private
|
369
375
|
*/
|
370
376
|
function initPopperSwitch() {
|
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
|
-
|
377
|
+
const nodes = getSlottedElements.call(this, `[${ATTRIBUTE_ROLE}="switch"]`); // null ↦ only unnamed slots
|
378
|
+
let switchButton;
|
379
|
+
if (nodes.size === 0) {
|
380
|
+
switchButton = document.createElement("button");
|
381
|
+
switchButton.setAttribute(ATTRIBUTE_ROLE, "switch");
|
382
|
+
switchButton.setAttribute("part", "switch");
|
383
|
+
switchButton.classList.add("hidden");
|
384
|
+
const classList = this.getOption("classes.button");
|
385
|
+
if (classList) {
|
386
|
+
switchButton.classList.add(classList);
|
387
|
+
}
|
388
|
+
switchButton.innerHTML =
|
389
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg>';
|
390
|
+
this[navElementSymbol].prepend(switchButton);
|
391
|
+
} else {
|
392
|
+
switchButton = nodes.next();
|
393
|
+
}
|
394
|
+
|
395
|
+
/**
|
396
|
+
* @param {Event} event
|
397
|
+
*/
|
398
|
+
this[popperSwitchEventHandler] = (event) => {
|
399
|
+
const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "switch");
|
400
|
+
|
401
|
+
if (element instanceof HTMLButtonElement) {
|
402
|
+
togglePopper.call(this);
|
403
|
+
}
|
404
|
+
};
|
405
|
+
|
406
|
+
for (const type of ["click", "touch"]) {
|
407
|
+
switchButton.addEventListener(type, this[popperSwitchEventHandler]);
|
408
|
+
}
|
409
|
+
|
410
|
+
this[switchElementSymbol] = switchButton;
|
405
411
|
}
|
406
412
|
|
407
413
|
/**
|
408
414
|
* @private
|
409
415
|
*/
|
410
416
|
function hidePopper() {
|
411
|
-
|
412
|
-
|
413
|
-
|
417
|
+
if (!this[popperInstanceSymbol]) {
|
418
|
+
return;
|
419
|
+
}
|
414
420
|
|
415
|
-
|
416
|
-
|
417
|
-
|
421
|
+
this[popperElementSymbol].style.display = "none";
|
422
|
+
// performance https://popper.js.org/docs/v2/tutorial/#performance
|
423
|
+
setEventListenersModifiers.call(this, false);
|
418
424
|
}
|
419
425
|
|
420
426
|
/**
|
421
427
|
* @private
|
422
428
|
*/
|
423
429
|
function showPopper() {
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
430
|
+
if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
|
431
|
+
return;
|
432
|
+
}
|
433
|
+
|
434
|
+
this[popperElementSymbol].style.visibility = "hidden";
|
435
|
+
this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
|
436
|
+
// performance https://popper.js.org/docs/v2/tutorial/#performance
|
437
|
+
setEventListenersModifiers.call(this, true);
|
438
|
+
|
439
|
+
this[popperInstanceSymbol].update();
|
440
|
+
|
441
|
+
new Processing(() => {
|
442
|
+
this[popperElementSymbol].style.removeProperty("visibility");
|
443
|
+
})
|
444
|
+
.run(undefined)
|
445
|
+
.then(() => {
|
446
|
+
})
|
447
|
+
.catch((e) => {
|
448
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
|
449
|
+
});
|
443
450
|
}
|
444
451
|
|
445
452
|
/**
|
446
453
|
* @private
|
447
454
|
*/
|
448
455
|
function togglePopper() {
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
456
|
+
if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
|
457
|
+
hidePopper.call(this);
|
458
|
+
} else {
|
459
|
+
showPopper.call(this);
|
460
|
+
}
|
454
461
|
}
|
455
462
|
|
456
463
|
/**
|
457
464
|
* @private
|
458
465
|
*/
|
459
466
|
function attachResizeObserver() {
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
467
|
+
// against flickering
|
468
|
+
this[resizeObserverSymbol] = new ResizeObserver((entries) => {
|
469
|
+
if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
|
470
|
+
try {
|
471
|
+
this[timerCallbackSymbol].touch();
|
472
|
+
return;
|
473
|
+
} catch (e) {
|
474
|
+
delete this[timerCallbackSymbol];
|
475
|
+
}
|
476
|
+
}
|
477
|
+
|
478
|
+
this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
|
479
|
+
this[dimensionsSymbol].setVia("data.calculated", false);
|
480
|
+
checkAndRearrangeButtons.call(this);
|
481
|
+
});
|
482
|
+
});
|
483
|
+
|
484
|
+
this[resizeObserverSymbol].observe(this[navElementSymbol]);
|
478
485
|
}
|
479
486
|
|
480
487
|
/**
|
481
488
|
* @private
|
482
489
|
*/
|
483
490
|
function attachTabChangeObserver() {
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
491
|
+
// against flickering
|
492
|
+
new MutationObserver((mutations) => {
|
493
|
+
let runUpdate = false;
|
494
|
+
|
495
|
+
for (const mutation of mutations) {
|
496
|
+
if (mutation.type === "childList") {
|
497
|
+
if (
|
498
|
+
mutation.addedNodes.length > 0 ||
|
499
|
+
mutation.removedNodes.length > 0
|
500
|
+
) {
|
501
|
+
runUpdate = true;
|
502
|
+
break;
|
503
|
+
}
|
504
|
+
}
|
505
|
+
}
|
506
|
+
|
507
|
+
if (runUpdate === true) {
|
508
|
+
this[dimensionsSymbol].setVia("data.calculated", false);
|
509
|
+
initTabButtons.call(this);
|
510
|
+
}
|
511
|
+
}).observe(this, {
|
512
|
+
childList: true,
|
513
|
+
});
|
507
514
|
}
|
508
515
|
|
509
516
|
/**
|
510
517
|
* @private
|
511
518
|
* @return {Select}
|
512
519
|
* @external "external:createPopper"
|
513
|
-
* @see {@link Plugins}
|
514
520
|
*/
|
515
521
|
function initPopper() {
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
522
|
+
const self = this;
|
523
|
+
|
524
|
+
const options = extend({}, self.getOption("popper"));
|
525
|
+
|
526
|
+
self[popperInstanceSymbol] = createPopper(
|
527
|
+
self[switchElementSymbol],
|
528
|
+
self[popperElementSymbol],
|
529
|
+
options,
|
530
|
+
);
|
531
|
+
|
532
|
+
const observer1 = new MutationObserver(function (mutations) {
|
533
|
+
let runUpdate = false;
|
534
|
+
for (const mutation of mutations) {
|
535
|
+
if (mutation.type === "childList") {
|
536
|
+
if (
|
537
|
+
mutation.addedNodes.length > 0 ||
|
538
|
+
mutation.removedNodes.length > 0
|
539
|
+
) {
|
540
|
+
runUpdate = true;
|
541
|
+
break;
|
542
|
+
}
|
543
|
+
}
|
544
|
+
}
|
545
|
+
|
546
|
+
if (runUpdate === true) {
|
547
|
+
self[popperInstanceSymbol].update();
|
548
|
+
}
|
549
|
+
});
|
550
|
+
|
551
|
+
observer1.observe(self[popperNavElementSymbol], {
|
552
|
+
childList: true,
|
553
|
+
subtree: true,
|
554
|
+
});
|
555
|
+
|
556
|
+
return self;
|
551
557
|
}
|
552
558
|
|
553
559
|
/**
|
@@ -555,172 +561,229 @@ function initPopper() {
|
|
555
561
|
* @param {HTMLElement} element
|
556
562
|
*/
|
557
563
|
function show(element) {
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
564
|
+
if (!this.shadowRoot) {
|
565
|
+
throw new Error("no shadow-root is defined");
|
566
|
+
}
|
567
|
+
|
568
|
+
const reference = element.getAttribute(`${ATTRIBUTE_PREFIX}tab-reference`);
|
569
|
+
|
570
|
+
const nodes = getSlottedElements.call(this);
|
571
|
+
for (const node of nodes) {
|
572
|
+
const id = node.getAttribute("id");
|
573
|
+
|
574
|
+
if (id === reference) {
|
575
|
+
node.classList.add("active");
|
576
|
+
|
577
|
+
const openDelay = parseInt(this.getOption("features.openDelay"), 10);
|
578
|
+
|
579
|
+
if (!isNaN(openDelay) && openDelay > 0) {
|
580
|
+
node.style.visibility = "hidden";
|
581
|
+
|
582
|
+
setTimeout(() => {
|
583
|
+
node.style.visibility = "visible";
|
584
|
+
}, openDelay);
|
585
|
+
}
|
586
|
+
|
587
|
+
// get all data- from button and filter out data-monster-attributes and data-monster-insert
|
588
|
+
const data = {};
|
589
|
+
const mask = [
|
590
|
+
"data-monster-attributes",
|
591
|
+
"data-monster-insert-reference",
|
592
|
+
"data-monster-state",
|
593
|
+
"data-monster-button-label",
|
594
|
+
"data-monster-objectlink",
|
595
|
+
"data-monster-role",
|
596
|
+
];
|
597
|
+
|
598
|
+
for (const [, attr] of Object.entries(node.attributes)) {
|
599
|
+
if (attr.name.startsWith("data-") && mask.indexOf(attr.name) === -1) {
|
600
|
+
data[attr.name] = attr.value;
|
601
|
+
}
|
602
|
+
}
|
603
|
+
|
604
|
+
if (node.hasAttribute(ATTRIBUTE_FORM_URL)) {
|
605
|
+
const url = node.getAttribute(ATTRIBUTE_FORM_URL);
|
606
|
+
|
607
|
+
if (
|
608
|
+
!node.hasAttribute(ATTRIBUTE_FORM_RELOAD) ||
|
609
|
+
node.getAttribute(ATTRIBUTE_FORM_RELOAD).toLowerCase() === "onshow"
|
610
|
+
) {
|
611
|
+
node.removeAttribute(ATTRIBUTE_FORM_URL);
|
612
|
+
}
|
613
|
+
|
614
|
+
const options = this.getOption("fetch", {});
|
615
|
+
const filter = undefined;
|
616
|
+
loadAndAssignContent(node, url, options, filter)
|
617
|
+
.then(() => {
|
618
|
+
fireCustomEvent(this, "monster-tab-changed", {
|
619
|
+
reference,
|
620
|
+
});
|
621
|
+
})
|
622
|
+
.catch((e) => {
|
623
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
|
624
|
+
});
|
625
|
+
} else {
|
626
|
+
fireCustomEvent(this, "monster-tab-changed", {
|
627
|
+
reference,
|
628
|
+
data,
|
629
|
+
});
|
630
|
+
}
|
631
|
+
} else {
|
632
|
+
node.classList.remove("active");
|
633
|
+
}
|
634
|
+
}
|
635
|
+
|
636
|
+
const standardButtons = this.getOption("buttons.standard");
|
637
|
+
for (const index in standardButtons) {
|
638
|
+
const button = standardButtons[index];
|
639
|
+
const state = button["reference"] === reference ? "active" : "inactive";
|
640
|
+
this.setOption(`buttons.standard.${index}.state`, state);
|
641
|
+
}
|
642
|
+
|
643
|
+
const popperButton = this.getOption("buttons.popper");
|
644
|
+
for (const index in popperButton) {
|
645
|
+
const button = popperButton[index];
|
646
|
+
const state = button["reference"] === reference ? "active" : "inactive";
|
647
|
+
this.setOption(`buttons.popper.${index}.state`, state);
|
648
|
+
}
|
649
|
+
|
650
|
+
hidePopper.call(this);
|
645
651
|
}
|
646
652
|
|
647
653
|
/**
|
648
654
|
* @private
|
649
655
|
*/
|
650
656
|
function initEventHandler() {
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
657
|
+
const self = this;
|
658
|
+
|
659
|
+
if (!this.shadowRoot) {
|
660
|
+
throw new Error("no shadow-root is defined");
|
661
|
+
}
|
662
|
+
|
663
|
+
/**
|
664
|
+
* @param {Event} event
|
665
|
+
* @fires monster-tab-remove
|
666
|
+
*/
|
667
|
+
this[removeTabEventHandler] = (event) => {
|
668
|
+
|
669
|
+
const element = findTargetElementFromEvent(
|
670
|
+
event,
|
671
|
+
ATTRIBUTE_ROLE,
|
672
|
+
"remove-tab",
|
673
|
+
);
|
674
|
+
|
675
|
+
if (element instanceof HTMLElement) {
|
676
|
+
const button = findTargetElementFromEvent(
|
677
|
+
event,
|
678
|
+
ATTRIBUTE_ROLE,
|
679
|
+
"button",
|
680
|
+
);
|
681
|
+
|
682
|
+
if (button instanceof HTMLButtonElement && button.disabled !== true) {
|
683
|
+
const reference = button.getAttribute(
|
684
|
+
`${ATTRIBUTE_PREFIX}tab-reference`,
|
685
|
+
);
|
686
|
+
|
687
|
+
let doChange = false;
|
688
|
+
let nextName = null
|
689
|
+
let previousName = null;
|
690
|
+
|
691
|
+
const btn = this.getOption("buttons")
|
692
|
+
for (let i = 0; i < btn.standard.length; i++) {
|
693
|
+
if (btn.standard[i].reference === reference) {
|
694
|
+
if (btn.standard[i].state === "active") {
|
695
|
+
doChange = i
|
696
|
+
if (i < btn.standard.length - 1) {
|
697
|
+
nextName = btn.standard[i + 1]?.reference
|
698
|
+
}
|
699
|
+
if (i > 0) {
|
700
|
+
previousName = btn.standard[i - 1]?.reference
|
701
|
+
}
|
702
|
+
}
|
703
|
+
break;
|
704
|
+
}
|
705
|
+
}
|
706
|
+
|
707
|
+
if (reference) {
|
708
|
+
const container = this.querySelector(`[id=${reference}]`);
|
709
|
+
if (container instanceof HTMLElement) {
|
710
|
+
|
711
|
+
if (doChange) {
|
712
|
+
|
713
|
+
switch (this.getOption("features.removeBehavior")) {
|
714
|
+
case "auto":
|
715
|
+
if (nextName !== null) {
|
716
|
+
self.activeTab(nextName);
|
717
|
+
} else {
|
718
|
+
if (previousName !== null) {
|
719
|
+
self.activeTab(previousName);
|
720
|
+
}
|
721
|
+
}
|
722
|
+
break;
|
723
|
+
case "next":
|
724
|
+
if (nextName !== null) {
|
725
|
+
self.activeTab(nextName);
|
726
|
+
}
|
727
|
+
break;
|
728
|
+
case "previous":
|
729
|
+
if (previousName !== null) {
|
730
|
+
self.activeTab(previousName);
|
731
|
+
}
|
732
|
+
break;
|
733
|
+
|
734
|
+
default: // and "none"
|
735
|
+
break;
|
736
|
+
}
|
737
|
+
}
|
738
|
+
|
739
|
+
container.remove();
|
740
|
+
initTabButtons.call(this);
|
741
|
+
fireCustomEvent(this, "monster-tab-remove", {
|
742
|
+
reference,
|
743
|
+
});
|
744
|
+
}
|
745
|
+
}
|
746
|
+
|
747
|
+
}
|
748
|
+
}
|
749
|
+
};
|
750
|
+
|
751
|
+
/**
|
752
|
+
* @param {Event} event
|
753
|
+
*/
|
754
|
+
this[changeTabEventHandler] = (event) => {
|
755
|
+
|
756
|
+
const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "button");
|
757
|
+
|
758
|
+
if (element instanceof HTMLButtonElement && element.disabled !== true) {
|
759
|
+
show.call(this, element);
|
760
|
+
}
|
761
|
+
};
|
762
|
+
|
763
|
+
/**
|
764
|
+
* @param {Event} event
|
765
|
+
*/
|
766
|
+
this[closeEventHandler] = (event) => {
|
767
|
+
const path = event.composedPath();
|
768
|
+
|
769
|
+
for (const [, element] of Object.entries(path)) {
|
770
|
+
if (element === this) {
|
771
|
+
return;
|
772
|
+
}
|
773
|
+
}
|
774
|
+
|
775
|
+
hidePopper.call(this);
|
776
|
+
};
|
777
|
+
|
778
|
+
|
779
|
+
// the order is important, because the remove must be before the change
|
780
|
+
this[navElementSymbol].addEventListener("touch", this[removeTabEventHandler]);
|
781
|
+
this[navElementSymbol].addEventListener("click", this[removeTabEventHandler]);
|
782
|
+
|
783
|
+
this[navElementSymbol].addEventListener("touch", this[changeTabEventHandler]);
|
784
|
+
this[navElementSymbol].addEventListener("click", this[changeTabEventHandler]);
|
785
|
+
|
786
|
+
return this;
|
724
787
|
}
|
725
788
|
|
726
789
|
/**
|
@@ -728,37 +791,37 @@ function initEventHandler() {
|
|
728
791
|
* @param observedNode
|
729
792
|
*/
|
730
793
|
function attachTabMutationObserver(observedNode) {
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
794
|
+
const self = this;
|
795
|
+
|
796
|
+
if (hasObjectLink(observedNode, mutationObserverSymbol)) {
|
797
|
+
return;
|
798
|
+
}
|
799
|
+
|
800
|
+
/**
|
801
|
+
* this construct monitors a node whether it is disabled or modified
|
802
|
+
* @type {MutationObserver}
|
803
|
+
*/
|
804
|
+
const observer = new MutationObserver(function (mutations) {
|
805
|
+
if (isArray(mutations)) {
|
806
|
+
const mutation = mutations.pop();
|
807
|
+
if (mutation instanceof MutationRecord) {
|
808
|
+
initTabButtons.call(self);
|
809
|
+
}
|
810
|
+
}
|
811
|
+
});
|
812
|
+
|
813
|
+
observer.observe(observedNode, {
|
814
|
+
childList: false,
|
815
|
+
attributes: true,
|
816
|
+
subtree: false,
|
817
|
+
attributeFilter: [
|
818
|
+
"disabled",
|
819
|
+
ATTRIBUTE_BUTTON_LABEL,
|
820
|
+
`${ATTRIBUTE_PREFIX}button-icon`,
|
821
|
+
],
|
822
|
+
});
|
823
|
+
|
824
|
+
addToObjectLink(observedNode, mutationObserverSymbol, observer);
|
762
825
|
}
|
763
826
|
|
764
827
|
/**
|
@@ -767,22 +830,22 @@ function attachTabMutationObserver(observedNode) {
|
|
767
830
|
* @throws {Error} no shadow-root is defined
|
768
831
|
*/
|
769
832
|
function initControlReferences() {
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
833
|
+
if (!this.shadowRoot) {
|
834
|
+
throw new Error("no shadow-root is defined");
|
835
|
+
}
|
836
|
+
|
837
|
+
this[controlElementSymbol] = this.shadowRoot.querySelector(
|
838
|
+
`[${ATTRIBUTE_ROLE}=control]`,
|
839
|
+
);
|
840
|
+
this[navElementSymbol] = this.shadowRoot.querySelector(
|
841
|
+
`nav[${ATTRIBUTE_ROLE}=nav]`,
|
842
|
+
);
|
843
|
+
this[popperElementSymbol] = this.shadowRoot.querySelector(
|
844
|
+
`[${ATTRIBUTE_ROLE}=popper]`,
|
845
|
+
);
|
846
|
+
this[popperNavElementSymbol] = this.shadowRoot.querySelector(
|
847
|
+
`[${ATTRIBUTE_ROLE}=popper-nav]`,
|
848
|
+
);
|
786
849
|
}
|
787
850
|
|
788
851
|
/**
|
@@ -792,101 +855,102 @@ function initControlReferences() {
|
|
792
855
|
*
|
793
856
|
*/
|
794
857
|
function initTabButtons() {
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
858
|
+
if (!this.shadowRoot) {
|
859
|
+
throw new Error("no shadow-root is defined");
|
860
|
+
}
|
861
|
+
|
862
|
+
let activeReference;
|
863
|
+
|
864
|
+
const dimensionsCalculated = this[dimensionsSymbol].getVia(
|
865
|
+
"data.calculated",
|
866
|
+
false,
|
867
|
+
);
|
868
|
+
|
869
|
+
const buttons = [];
|
870
|
+
const nodes = getSlottedElements.call(this, undefined, null); // null ↦ only unnamed slots
|
871
|
+
|
872
|
+
for (const node of nodes) {
|
873
|
+
if (!(node instanceof HTMLElement)) continue;
|
874
|
+
let label = getButtonLabel.call(this, node);
|
875
|
+
|
876
|
+
let reference;
|
877
|
+
if (node.hasAttribute("id")) {
|
878
|
+
reference = node.getAttribute("id");
|
879
|
+
}
|
880
|
+
|
881
|
+
let disabled;
|
882
|
+
if (node.hasAttribute("disabled") || node.disabled === true) {
|
883
|
+
disabled = true;
|
884
|
+
}
|
885
|
+
|
886
|
+
if (!reference) {
|
887
|
+
reference = new ID("tab").toString();
|
888
|
+
node.setAttribute("id", reference);
|
889
|
+
}
|
890
|
+
|
891
|
+
if (node.hasAttribute(`${ATTRIBUTE_PREFIX}button-icon`)) {
|
892
|
+
label = `<span part="label">${label}</span><img part="icon" alt="this is an icon" src="${node.getAttribute(
|
893
|
+
`${ATTRIBUTE_PREFIX}button-icon`,
|
894
|
+
)}">`;
|
895
|
+
}
|
896
|
+
|
897
|
+
let remove = false;
|
898
|
+
if (node.hasAttribute(`${ATTRIBUTE_PREFIX}removable`)) {
|
899
|
+
remove = true;
|
900
|
+
}
|
901
|
+
|
902
|
+
if (node.matches(".active") === true && disabled !== true) {
|
903
|
+
node.classList.remove("active");
|
904
|
+
activeReference = reference;
|
905
|
+
}
|
906
|
+
|
907
|
+
const state = "";
|
908
|
+
const classes = dimensionsCalculated ? "" : "invisible";
|
909
|
+
|
910
|
+
buttons.push({
|
911
|
+
reference,
|
912
|
+
label,
|
913
|
+
state,
|
914
|
+
class: classes,
|
915
|
+
disabled,
|
916
|
+
remove,
|
917
|
+
});
|
918
|
+
|
919
|
+
attachTabMutationObserver.call(this, node);
|
920
|
+
}
|
921
|
+
|
922
|
+
this.setOption("buttons.standard", clone(buttons));
|
923
|
+
this.setOption("buttons.popper", []);
|
924
|
+
this.setOption("marker", random());
|
925
|
+
|
926
|
+
return adjustButtonVisibility.call(this).then(() => {
|
927
|
+
if (activeReference) {
|
928
|
+
return new Processing(() => {
|
929
|
+
const button = this.shadowRoot.querySelector(
|
930
|
+
`[${ATTRIBUTE_PREFIX}tab-reference="${activeReference}"]`,
|
931
|
+
);
|
932
|
+
if (button instanceof HTMLButtonElement && button.disabled !== true) {
|
933
|
+
show.call(this, button);
|
934
|
+
}
|
935
|
+
})
|
936
|
+
.run(undefined)
|
937
|
+
.then(() => {
|
938
|
+
})
|
939
|
+
.catch((e) => {
|
940
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
|
941
|
+
});
|
942
|
+
}
|
943
|
+
|
944
|
+
return Promise.resolve();
|
945
|
+
});
|
882
946
|
}
|
883
947
|
|
884
948
|
function checkAndRearrangeButtons() {
|
885
|
-
|
886
|
-
|
887
|
-
|
949
|
+
if (this[dimensionsSymbol].getVia("data.calculated", false) !== true) {
|
950
|
+
calculateNavigationButtonsDimensions.call(this);
|
951
|
+
}
|
888
952
|
|
889
|
-
|
953
|
+
rearrangeButtons.call(this);
|
890
954
|
}
|
891
955
|
|
892
956
|
/**
|
@@ -894,29 +958,29 @@ function checkAndRearrangeButtons() {
|
|
894
958
|
* @return {Promise<unknown>}
|
895
959
|
*/
|
896
960
|
function adjustButtonVisibility() {
|
897
|
-
|
961
|
+
const self = this;
|
898
962
|
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
963
|
+
return new Promise((resolve) => {
|
964
|
+
const observer = new MutationObserver(function (mutations) {
|
965
|
+
const defCount = self.getOption("buttons.standard").length;
|
966
|
+
const domCount = self[navElementSymbol].querySelectorAll(
|
967
|
+
'button[data-monster-role="button"]',
|
968
|
+
).length;
|
905
969
|
|
906
|
-
|
907
|
-
|
970
|
+
// in drawing
|
971
|
+
if (defCount !== domCount) return;
|
908
972
|
|
909
|
-
|
973
|
+
observer.disconnect();
|
910
974
|
|
911
|
-
|
975
|
+
checkAndRearrangeButtons.call(self);
|
912
976
|
|
913
|
-
|
914
|
-
|
977
|
+
resolve();
|
978
|
+
});
|
915
979
|
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
980
|
+
observer.observe(self[navElementSymbol], {
|
981
|
+
attributes: true,
|
982
|
+
});
|
983
|
+
});
|
920
984
|
}
|
921
985
|
|
922
986
|
/**
|
@@ -925,17 +989,17 @@ function adjustButtonVisibility() {
|
|
925
989
|
* @return {number}
|
926
990
|
*/
|
927
991
|
function getDimValue(value) {
|
928
|
-
|
929
|
-
|
930
|
-
|
992
|
+
if ([undefined, null].indexOf(value) !== -1) {
|
993
|
+
return 0;
|
994
|
+
}
|
931
995
|
|
932
|
-
|
996
|
+
const valueAsInt = parseInt(value, 10);
|
933
997
|
|
934
|
-
|
935
|
-
|
936
|
-
|
998
|
+
if (isNaN(valueAsInt)) {
|
999
|
+
return 0;
|
1000
|
+
}
|
937
1001
|
|
938
|
-
|
1002
|
+
return valueAsInt;
|
939
1003
|
}
|
940
1004
|
|
941
1005
|
/**
|
@@ -944,18 +1008,18 @@ function getDimValue(value) {
|
|
944
1008
|
* @return {number}
|
945
1009
|
*/
|
946
1010
|
function calcBoxWidth(node) {
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
1011
|
+
const dim = getGlobal("window").getComputedStyle(node);
|
1012
|
+
const bounding = node.getBoundingClientRect();
|
1013
|
+
|
1014
|
+
return (
|
1015
|
+
getDimValue(dim["border-left-width"]) +
|
1016
|
+
getDimValue(dim["padding-left"]) +
|
1017
|
+
getDimValue(dim["margin-left"]) +
|
1018
|
+
getDimValue(bounding["width"]) +
|
1019
|
+
getDimValue(dim["border-right-width"]) +
|
1020
|
+
getDimValue(dim["margin-right"]) +
|
1021
|
+
getDimValue(dim["padding-left"])
|
1022
|
+
);
|
959
1023
|
}
|
960
1024
|
|
961
1025
|
/**
|
@@ -963,35 +1027,35 @@ function calcBoxWidth(node) {
|
|
963
1027
|
* @return {Object}
|
964
1028
|
*/
|
965
1029
|
function rearrangeButtons() {
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
1030
|
+
const standardButtons = [];
|
1031
|
+
const popperButtons = [];
|
1032
|
+
|
1033
|
+
let sum = 0;
|
1034
|
+
const space = this[dimensionsSymbol].getVia("data.space");
|
1035
|
+
|
1036
|
+
const buttons = this.getOption("buttons.standard");
|
1037
|
+
for (const [, button] of buttons.entries()) {
|
1038
|
+
const ref = button?.reference;
|
1039
|
+
|
1040
|
+
sum += this[dimensionsSymbol].getVia(`data.button.${ref}`);
|
1041
|
+
|
1042
|
+
if (sum > space) {
|
1043
|
+
popperButtons.push(clone(button));
|
1044
|
+
} else {
|
1045
|
+
standardButtons.push(clone(button));
|
1046
|
+
}
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
this.setOption("buttons.standard", standardButtons);
|
1050
|
+
this.setOption("buttons.popper", popperButtons);
|
1051
|
+
|
1052
|
+
if (this[switchElementSymbol]) {
|
1053
|
+
if (popperButtons.length > 0) {
|
1054
|
+
this[switchElementSymbol].classList.remove("hidden");
|
1055
|
+
} else {
|
1056
|
+
this[switchElementSymbol].classList.add("hidden");
|
1057
|
+
}
|
1058
|
+
}
|
995
1059
|
}
|
996
1060
|
|
997
1061
|
/**
|
@@ -999,50 +1063,50 @@ function rearrangeButtons() {
|
|
999
1063
|
* @return {Object}
|
1000
1064
|
*/
|
1001
1065
|
function calculateNavigationButtonsDimensions() {
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1066
|
+
const width = this[navElementSymbol].getBoundingClientRect().width;
|
1067
|
+
|
1068
|
+
let startEndWidth = 0;
|
1069
|
+
|
1070
|
+
getSlottedElements.call(this, undefined, "start").forEach((node) => {
|
1071
|
+
startEndWidth += calcBoxWidth.call(this, node);
|
1072
|
+
});
|
1073
|
+
|
1074
|
+
getSlottedElements.call(this, undefined, "end").forEach((node) => {
|
1075
|
+
startEndWidth += calcBoxWidth.call(this, node);
|
1076
|
+
});
|
1077
|
+
|
1078
|
+
this[dimensionsSymbol].setVia("data.space", width - startEndWidth - 2);
|
1079
|
+
this[dimensionsSymbol].setVia("data.visible", !(width === 0));
|
1080
|
+
|
1081
|
+
const buttons = this.getOption("buttons.standard").concat(
|
1082
|
+
this.getOption("buttons.popper"),
|
1083
|
+
);
|
1084
|
+
|
1085
|
+
for (const [i, button] of buttons.entries()) {
|
1086
|
+
const ref = button?.reference;
|
1087
|
+
const element = this[navElementSymbol].querySelector(
|
1088
|
+
`:scope > [${ATTRIBUTE_PREFIX}tab-reference="${ref}"]`,
|
1089
|
+
);
|
1090
|
+
if (!(element instanceof HTMLButtonElement)) continue;
|
1091
|
+
|
1092
|
+
this[dimensionsSymbol].setVia(
|
1093
|
+
`data.button.${ref}`,
|
1094
|
+
calcBoxWidth.call(this, element),
|
1095
|
+
);
|
1096
|
+
button["class"] = new TokenList(button["class"])
|
1097
|
+
.remove("invisible")
|
1098
|
+
.toString();
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
const slots = this[controlElementSymbol].querySelectorAll(
|
1102
|
+
`nav[${ATTRIBUTE_PREFIX}role=nav] > slot.invisible, slot[${ATTRIBUTE_PREFIX}role=slot].invisible`,
|
1103
|
+
);
|
1104
|
+
for (const [, slot] of slots.entries()) {
|
1105
|
+
slot.classList.remove("invisible");
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
this[dimensionsSymbol].setVia("data.calculated", true);
|
1109
|
+
this.setOption("buttons.standard", clone(buttons));
|
1046
1110
|
}
|
1047
1111
|
|
1048
1112
|
/**
|
@@ -1051,34 +1115,34 @@ function calculateNavigationButtonsDimensions() {
|
|
1051
1115
|
* @return {string}
|
1052
1116
|
*/
|
1053
1117
|
function getButtonLabel(node) {
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1118
|
+
let label;
|
1119
|
+
let setLabel = false;
|
1120
|
+
if (node.hasAttribute(ATTRIBUTE_BUTTON_LABEL)) {
|
1121
|
+
label = node.getAttribute(ATTRIBUTE_BUTTON_LABEL);
|
1122
|
+
} else {
|
1123
|
+
label = node.innerText;
|
1124
|
+
setLabel = true;
|
1125
|
+
}
|
1126
|
+
|
1127
|
+
if (!isString(label)) {
|
1128
|
+
label = "";
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
label = label.trim();
|
1132
|
+
|
1133
|
+
if (label === "") {
|
1134
|
+
label = this.getOption("labels.new-tab-label", "New Tab");
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
if (label.length > 100) {
|
1138
|
+
label = `${label.substring(0, 99)}…`;
|
1139
|
+
}
|
1140
|
+
|
1141
|
+
if (setLabel === true) {
|
1142
|
+
node.setAttribute(ATTRIBUTE_BUTTON_LABEL, label);
|
1143
|
+
}
|
1144
|
+
|
1145
|
+
return label;
|
1082
1146
|
}
|
1083
1147
|
|
1084
1148
|
/**
|
@@ -1086,8 +1150,8 @@ function getButtonLabel(node) {
|
|
1086
1150
|
* @return {string}
|
1087
1151
|
*/
|
1088
1152
|
function getTemplate() {
|
1089
|
-
|
1090
|
-
|
1153
|
+
// language=HTML
|
1154
|
+
return `
|
1091
1155
|
<template id="buttons">
|
1092
1156
|
<button part="button"
|
1093
1157
|
data-monster-role="button"
|
@@ -1107,7 +1171,7 @@ function getTemplate() {
|
|
1107
1171
|
data-monster-insert="buttons path:buttons.standard">
|
1108
1172
|
<slot name="start" class="invisible"></slot>
|
1109
1173
|
<div data-monster-role="popper" part="popper" tabindex="-1"
|
1110
|
-
|
1174
|
+
data-monster-attributes="class path:classes.popper">
|
1111
1175
|
<div data-popper-arrow></div>
|
1112
1176
|
|
1113
1177
|
|