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