@schukai/monster 3.92.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 +8 -0
- package/package.json +1 -1
- package/source/components/layout/tabs.mjs +884 -855
@@ -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
|
@@ -156,360 +156,361 @@ const resizeObserverSymbol = Symbol("resizeObserver");
|
|
156
156
|
* @summary This CustomControl creates a tab element with a variety of options.
|
157
157
|
*/
|
158
158
|
class Tabs extends CustomElement {
|
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
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
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
|
+
}
|
371
371
|
}
|
372
372
|
|
373
373
|
/**
|
374
374
|
* @private
|
375
375
|
*/
|
376
376
|
function initPopperSwitch() {
|
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
|
-
|
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;
|
411
411
|
}
|
412
412
|
|
413
413
|
/**
|
414
414
|
* @private
|
415
415
|
*/
|
416
416
|
function hidePopper() {
|
417
|
-
|
418
|
-
|
419
|
-
|
417
|
+
if (!this[popperInstanceSymbol]) {
|
418
|
+
return;
|
419
|
+
}
|
420
420
|
|
421
|
-
|
422
|
-
|
423
|
-
|
421
|
+
this[popperElementSymbol].style.display = "none";
|
422
|
+
// performance https://popper.js.org/docs/v2/tutorial/#performance
|
423
|
+
setEventListenersModifiers.call(this, false);
|
424
424
|
}
|
425
425
|
|
426
426
|
/**
|
427
427
|
* @private
|
428
428
|
*/
|
429
429
|
function showPopper() {
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
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
|
+
});
|
449
450
|
}
|
450
451
|
|
451
452
|
/**
|
452
453
|
* @private
|
453
454
|
*/
|
454
455
|
function togglePopper() {
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
456
|
+
if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
|
457
|
+
hidePopper.call(this);
|
458
|
+
} else {
|
459
|
+
showPopper.call(this);
|
460
|
+
}
|
460
461
|
}
|
461
462
|
|
462
463
|
/**
|
463
464
|
* @private
|
464
465
|
*/
|
465
466
|
function attachResizeObserver() {
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
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]);
|
484
485
|
}
|
485
486
|
|
486
487
|
/**
|
487
488
|
* @private
|
488
489
|
*/
|
489
490
|
function attachTabChangeObserver() {
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
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
|
+
});
|
513
514
|
}
|
514
515
|
|
515
516
|
/**
|
@@ -518,41 +519,41 @@ function attachTabChangeObserver() {
|
|
518
519
|
* @external "external:createPopper"
|
519
520
|
*/
|
520
521
|
function initPopper() {
|
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
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
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;
|
556
557
|
}
|
557
558
|
|
558
559
|
/**
|
@@ -560,202 +561,229 @@ function initPopper() {
|
|
560
561
|
* @param {HTMLElement} element
|
561
562
|
*/
|
562
563
|
function show(element) {
|
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
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
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);
|
650
651
|
}
|
651
652
|
|
652
653
|
/**
|
653
654
|
* @private
|
654
655
|
*/
|
655
656
|
function initEventHandler() {
|
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
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
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
|
-
|
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;
|
759
787
|
}
|
760
788
|
|
761
789
|
/**
|
@@ -763,37 +791,37 @@ function initEventHandler() {
|
|
763
791
|
* @param observedNode
|
764
792
|
*/
|
765
793
|
function attachTabMutationObserver(observedNode) {
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
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);
|
797
825
|
}
|
798
826
|
|
799
827
|
/**
|
@@ -802,22 +830,22 @@ function attachTabMutationObserver(observedNode) {
|
|
802
830
|
* @throws {Error} no shadow-root is defined
|
803
831
|
*/
|
804
832
|
function initControlReferences() {
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
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
|
+
);
|
821
849
|
}
|
822
850
|
|
823
851
|
/**
|
@@ -827,101 +855,102 @@ function initControlReferences() {
|
|
827
855
|
*
|
828
856
|
*/
|
829
857
|
function initTabButtons() {
|
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
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
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
|
+
});
|
917
946
|
}
|
918
947
|
|
919
948
|
function checkAndRearrangeButtons() {
|
920
|
-
|
921
|
-
|
922
|
-
|
949
|
+
if (this[dimensionsSymbol].getVia("data.calculated", false) !== true) {
|
950
|
+
calculateNavigationButtonsDimensions.call(this);
|
951
|
+
}
|
923
952
|
|
924
|
-
|
953
|
+
rearrangeButtons.call(this);
|
925
954
|
}
|
926
955
|
|
927
956
|
/**
|
@@ -929,29 +958,29 @@ function checkAndRearrangeButtons() {
|
|
929
958
|
* @return {Promise<unknown>}
|
930
959
|
*/
|
931
960
|
function adjustButtonVisibility() {
|
932
|
-
|
961
|
+
const self = this;
|
933
962
|
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
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;
|
940
969
|
|
941
|
-
|
942
|
-
|
970
|
+
// in drawing
|
971
|
+
if (defCount !== domCount) return;
|
943
972
|
|
944
|
-
|
973
|
+
observer.disconnect();
|
945
974
|
|
946
|
-
|
975
|
+
checkAndRearrangeButtons.call(self);
|
947
976
|
|
948
|
-
|
949
|
-
|
977
|
+
resolve();
|
978
|
+
});
|
950
979
|
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
980
|
+
observer.observe(self[navElementSymbol], {
|
981
|
+
attributes: true,
|
982
|
+
});
|
983
|
+
});
|
955
984
|
}
|
956
985
|
|
957
986
|
/**
|
@@ -960,17 +989,17 @@ function adjustButtonVisibility() {
|
|
960
989
|
* @return {number}
|
961
990
|
*/
|
962
991
|
function getDimValue(value) {
|
963
|
-
|
964
|
-
|
965
|
-
|
992
|
+
if ([undefined, null].indexOf(value) !== -1) {
|
993
|
+
return 0;
|
994
|
+
}
|
966
995
|
|
967
|
-
|
996
|
+
const valueAsInt = parseInt(value, 10);
|
968
997
|
|
969
|
-
|
970
|
-
|
971
|
-
|
998
|
+
if (isNaN(valueAsInt)) {
|
999
|
+
return 0;
|
1000
|
+
}
|
972
1001
|
|
973
|
-
|
1002
|
+
return valueAsInt;
|
974
1003
|
}
|
975
1004
|
|
976
1005
|
/**
|
@@ -979,18 +1008,18 @@ function getDimValue(value) {
|
|
979
1008
|
* @return {number}
|
980
1009
|
*/
|
981
1010
|
function calcBoxWidth(node) {
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
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
|
+
);
|
994
1023
|
}
|
995
1024
|
|
996
1025
|
/**
|
@@ -998,35 +1027,35 @@ function calcBoxWidth(node) {
|
|
998
1027
|
* @return {Object}
|
999
1028
|
*/
|
1000
1029
|
function rearrangeButtons() {
|
1001
|
-
|
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
|
+
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
|
+
}
|
1030
1059
|
}
|
1031
1060
|
|
1032
1061
|
/**
|
@@ -1034,50 +1063,50 @@ function rearrangeButtons() {
|
|
1034
1063
|
* @return {Object}
|
1035
1064
|
*/
|
1036
1065
|
function calculateNavigationButtonsDimensions() {
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
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
|
-
|
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));
|
1081
1110
|
}
|
1082
1111
|
|
1083
1112
|
/**
|
@@ -1086,34 +1115,34 @@ function calculateNavigationButtonsDimensions() {
|
|
1086
1115
|
* @return {string}
|
1087
1116
|
*/
|
1088
1117
|
function getButtonLabel(node) {
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
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;
|
1117
1146
|
}
|
1118
1147
|
|
1119
1148
|
/**
|
@@ -1121,8 +1150,8 @@ function getButtonLabel(node) {
|
|
1121
1150
|
* @return {string}
|
1122
1151
|
*/
|
1123
1152
|
function getTemplate() {
|
1124
|
-
|
1125
|
-
|
1153
|
+
// language=HTML
|
1154
|
+
return `
|
1126
1155
|
<template id="buttons">
|
1127
1156
|
<button part="button"
|
1128
1157
|
data-monster-role="button"
|