@profitlich/template-toolkit 2.22.0 → 3.0.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.
|
@@ -4,26 +4,48 @@ export class MenuToggle {
|
|
|
4
4
|
static #instance;
|
|
5
5
|
#menuButton;
|
|
6
6
|
#menu;
|
|
7
|
-
#
|
|
7
|
+
#menuLinkSelector;
|
|
8
8
|
#menuItemClass;
|
|
9
9
|
#scrollbarWidth;
|
|
10
10
|
#shiftElement;
|
|
11
11
|
#shiftDelay;
|
|
12
12
|
#deferPositionFixed;
|
|
13
|
+
#fixBody;
|
|
13
14
|
#y;
|
|
14
15
|
#bodyClickHandler;
|
|
15
16
|
#resizeHandler;
|
|
16
17
|
#escapeHandler;
|
|
17
18
|
isActive;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} options
|
|
22
|
+
* @param {string} options.menuButtonId ID des Buttons, der das Menü öffnet/schliesst.
|
|
23
|
+
* @param {string} options.menuId ID des Menü-Containers.
|
|
24
|
+
* @param {string} options.menuLinkSelector Selektor für Menü-Links, die das Menü beim Klick schliessen (z.B. '.menu-link').
|
|
25
|
+
* @param {string} options.menuItemClass Klassenname (ohne Punkt) des Menü-Wrappers; Klicks ausserhalb schliessen das Menü.
|
|
26
|
+
* @param {string?} options.shiftElementId Optional: Element, das beim Öffnen um die Scrollbar-Breite verschoben/verbreitert wird, damit z.B. ein fixierter Header nicht springt.
|
|
27
|
+
* @param {number} options.shiftDelay Verzögerung in Sekunden, bevor Scrollbar gemessen und Body fixiert wird – nützlich, wenn vorher noch eine CSS-Animation läuft, die die Scrollbar entfernt.
|
|
28
|
+
* @param {boolean} options.deferPositionFixed Setzt `data-menu-fixed` erst nach `shiftDelay` statt sofort. Nötig, wenn das Fixieren eine laufende Öffnungs-Animation stören würde.
|
|
29
|
+
* @param {boolean} options.fixBody Wenn `false`, bleibt der Body scrollbar; kein Scrollbar-Ausgleich und kein Shift. Für Menüs, die nur einen Teil der Seite bedecken und Hintergrund-Scroll erlauben sollen.
|
|
30
|
+
*/
|
|
31
|
+
constructor({
|
|
32
|
+
menuButtonId,
|
|
33
|
+
menuId,
|
|
34
|
+
menuLinkSelector,
|
|
35
|
+
menuItemClass,
|
|
36
|
+
shiftElementId = null,
|
|
37
|
+
shiftDelay = 0,
|
|
38
|
+
deferPositionFixed = false,
|
|
39
|
+
fixBody = true,
|
|
40
|
+
}) {
|
|
20
41
|
this.#menuButton = document.getElementById(menuButtonId);
|
|
21
42
|
this.#menu = document.getElementById(menuId);
|
|
22
|
-
this.#
|
|
43
|
+
this.#menuLinkSelector = menuLinkSelector;
|
|
23
44
|
this.#menuItemClass = menuItemClass;
|
|
24
45
|
this.#shiftElement = shiftElementId ? document.getElementById(shiftElementId) : null;
|
|
25
46
|
this.#shiftDelay = shiftDelay * 1000;
|
|
26
47
|
this.#deferPositionFixed = deferPositionFixed;
|
|
48
|
+
this.#fixBody = fixBody;
|
|
27
49
|
this.#scrollbarWidth = 0;
|
|
28
50
|
this.isActive = false;
|
|
29
51
|
this.#y = 0;
|
|
@@ -39,7 +61,7 @@ export class MenuToggle {
|
|
|
39
61
|
});
|
|
40
62
|
|
|
41
63
|
this.#menu.addEventListener('click', (event) => {
|
|
42
|
-
if (this.isActive && event.target.matches(this.#
|
|
64
|
+
if (this.isActive && event.target.matches(this.#menuLinkSelector)) {
|
|
43
65
|
this.#toggleMenu();
|
|
44
66
|
}
|
|
45
67
|
});
|
|
@@ -49,12 +71,12 @@ export class MenuToggle {
|
|
|
49
71
|
this.#setBodyAttribute('data-menu-fixed', 'false');
|
|
50
72
|
}
|
|
51
73
|
|
|
52
|
-
static getInstance(
|
|
74
|
+
static getInstance(options) {
|
|
53
75
|
if (!MenuToggle.#instance) {
|
|
54
|
-
if (!menuButtonId || !menuId || !
|
|
55
|
-
throw new Error("MenuToggle muss beim ersten Aufruf mit menuButtonId, menuId,
|
|
76
|
+
if (!options || !options.menuButtonId || !options.menuId || !options.menuLinkSelector || !options.menuItemClass) {
|
|
77
|
+
throw new Error("MenuToggle muss beim ersten Aufruf mit menuButtonId, menuId, menuLinkSelector und menuItemClass initialisiert werden.");
|
|
56
78
|
}
|
|
57
|
-
MenuToggle.#instance = new MenuToggle(
|
|
79
|
+
MenuToggle.#instance = new MenuToggle(options);
|
|
58
80
|
}
|
|
59
81
|
return MenuToggle.#instance;
|
|
60
82
|
}
|
|
@@ -65,39 +87,43 @@ export class MenuToggle {
|
|
|
65
87
|
document.body.removeEventListener('click', this.#bodyClickHandler);
|
|
66
88
|
window.removeEventListener('resize', this.#resizeHandler);
|
|
67
89
|
this.#setBodyAttribute('data-menu-active', 'false');
|
|
68
|
-
this.#
|
|
69
|
-
|
|
70
|
-
this.#shiftElement
|
|
71
|
-
|
|
90
|
+
if (this.#fixBody) {
|
|
91
|
+
this.#setBodyAttribute('data-menu-fixed', 'false');
|
|
92
|
+
if (this.#shiftElement) {
|
|
93
|
+
this.#shiftElement.style.marginRight = '';
|
|
94
|
+
this.#shiftElement.style.width = '';
|
|
95
|
+
}
|
|
96
|
+
document.body.style.paddingRight = '';
|
|
97
|
+
document.body.style.top = '';
|
|
98
|
+
window.scrollTo(0, this.#y);
|
|
72
99
|
}
|
|
73
|
-
document.body.style.paddingRight = '';
|
|
74
|
-
document.body.style.top = '';
|
|
75
|
-
window.scrollTo(0, this.#y);
|
|
76
100
|
this.#toggleEscape(false);
|
|
77
101
|
} else {
|
|
78
102
|
this.isActive = true;
|
|
79
103
|
document.body.addEventListener('click', this.#bodyClickHandler);
|
|
80
|
-
window.addEventListener('resize', this.#resizeHandler);
|
|
81
104
|
this.#setBodyAttribute('data-menu-active', 'true');
|
|
82
|
-
this.#
|
|
83
|
-
|
|
84
|
-
this.#setBodyAttribute('data-menu-
|
|
85
|
-
|
|
86
|
-
setTimeout(() => {
|
|
87
|
-
this.#scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
88
|
-
this.#y = window.scrollY;
|
|
89
|
-
document.body.style.paddingRight = `${this.#scrollbarWidth}px`;
|
|
90
|
-
document.body.style.top = `-${this.#y}px`;
|
|
91
|
-
if (this.#deferPositionFixed) {
|
|
105
|
+
if (this.#fixBody) {
|
|
106
|
+
window.addEventListener('resize', this.#resizeHandler);
|
|
107
|
+
this.#setBodyAttribute('data-menu-moving', 'true');
|
|
108
|
+
if (!this.#deferPositionFixed) {
|
|
92
109
|
this.#setBodyAttribute('data-menu-fixed', 'true');
|
|
93
110
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this.#
|
|
97
|
-
this.#
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
this.#scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
113
|
+
this.#y = window.scrollY;
|
|
114
|
+
document.body.style.paddingRight = `${this.#scrollbarWidth}px`;
|
|
115
|
+
document.body.style.top = `-${this.#y}px`;
|
|
116
|
+
if (this.#deferPositionFixed) {
|
|
117
|
+
this.#setBodyAttribute('data-menu-fixed', 'true');
|
|
118
|
+
}
|
|
119
|
+
if (this.#shiftElement) {
|
|
120
|
+
const marginOriginal = parseFloat(window.getComputedStyle(this.#menuButton).marginRight);
|
|
121
|
+
this.#shiftElement.style.marginRight = `${marginOriginal + this.#scrollbarWidth}px`;
|
|
122
|
+
this.#adjustShiftElementWidth();
|
|
123
|
+
}
|
|
124
|
+
this.#setBodyAttribute('data-menu-moving', 'false');
|
|
125
|
+
}, this.#shiftDelay);
|
|
126
|
+
}
|
|
101
127
|
this.#toggleEscape(true);
|
|
102
128
|
}
|
|
103
129
|
const event = new CustomEvent('eventMenuestatus', {
|
|
@@ -69,13 +69,12 @@ export class MuxPlayer {
|
|
|
69
69
|
player.dataset.isSetup = 'true';
|
|
70
70
|
|
|
71
71
|
if (autoplay) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
72
|
+
// Kein Warten auf loadeddata: Das Event feuert auf Mobile bei aktivem
|
|
73
|
+
// Data-Saver gar nicht (MDN) und auf iOS Safari mit nativem HLS oft erst
|
|
74
|
+
// nach dem ersten play()-Aufruf. IntersectionObserver feuert beim observe()
|
|
75
|
+
// direkt mit dem aktuellen Status — play() darf vor loadeddata aufgerufen
|
|
76
|
+
// werden, der Browser kümmert sich ums Buffering.
|
|
77
|
+
this.#playPauseObserver.observe(player);
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
|
package/package.json
CHANGED