@hortonstudio/main 1.4.5 → 1.5.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/autoInit/accessibility.js +64 -0
- package/autoInit/counter.js +54 -238
- package/autoInit/modal.js +0 -49
- package/autoInit/navbar.js +199 -497
- package/index.js +1 -1
- package/package.json +1 -1
- package/styles.css +0 -6
|
@@ -4,6 +4,7 @@ export function init() {
|
|
|
4
4
|
|
|
5
5
|
function setupGeneralAccessibility() {
|
|
6
6
|
setupListAccessibility();
|
|
7
|
+
setupRemoveListAccessibility();
|
|
7
8
|
setupFAQAccessibility();
|
|
8
9
|
setupConvertToSpan();
|
|
9
10
|
setupYearReplacement();
|
|
@@ -25,6 +26,67 @@ export function init() {
|
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
function setupRemoveListAccessibility() {
|
|
30
|
+
const containers = document.querySelectorAll('[data-hs-a11y="remove-list"]');
|
|
31
|
+
|
|
32
|
+
containers.forEach(container => {
|
|
33
|
+
// Remove role="list" and role="listitem" from container and all descendants
|
|
34
|
+
const elementsWithListRoles = container.querySelectorAll('[role="list"], [role="listitem"]');
|
|
35
|
+
elementsWithListRoles.forEach(element => {
|
|
36
|
+
element.removeAttribute('role');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Also remove from container itself if it has these roles
|
|
40
|
+
if (container.getAttribute('role') === 'list' || container.getAttribute('role') === 'listitem') {
|
|
41
|
+
container.removeAttribute('role');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Convert semantic lists to divs in container and all descendants
|
|
45
|
+
const listsToConvert = container.querySelectorAll('ul, ol, li');
|
|
46
|
+
listsToConvert.forEach(listElement => {
|
|
47
|
+
const newDiv = document.createElement('div');
|
|
48
|
+
|
|
49
|
+
// Copy all attributes except role
|
|
50
|
+
Array.from(listElement.attributes).forEach(attr => {
|
|
51
|
+
if (attr.name !== 'role') {
|
|
52
|
+
newDiv.setAttribute(attr.name, attr.value);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Move all child nodes
|
|
57
|
+
while (listElement.firstChild) {
|
|
58
|
+
newDiv.appendChild(listElement.firstChild);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Replace the element
|
|
62
|
+
listElement.parentNode.replaceChild(newDiv, listElement);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Convert container itself if it's a semantic list
|
|
66
|
+
if (container.tagName.toLowerCase() === 'ul' || container.tagName.toLowerCase() === 'ol' || container.tagName.toLowerCase() === 'li') {
|
|
67
|
+
const newDiv = document.createElement('div');
|
|
68
|
+
|
|
69
|
+
// Copy all attributes except data-hs-a11y and role
|
|
70
|
+
Array.from(container.attributes).forEach(attr => {
|
|
71
|
+
if (attr.name !== 'data-hs-a11y' && attr.name !== 'role') {
|
|
72
|
+
newDiv.setAttribute(attr.name, attr.value);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Move all child nodes
|
|
77
|
+
while (container.firstChild) {
|
|
78
|
+
newDiv.appendChild(container.firstChild);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Replace the container
|
|
82
|
+
container.parentNode.replaceChild(newDiv, container);
|
|
83
|
+
} else {
|
|
84
|
+
// Just remove the attribute if container isn't a semantic list
|
|
85
|
+
container.removeAttribute('data-hs-a11y');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
28
90
|
function setupFAQAccessibility() {
|
|
29
91
|
const faqContainers = document.querySelectorAll('[data-hs-a11y="faq"]');
|
|
30
92
|
|
|
@@ -32,6 +94,8 @@ export function init() {
|
|
|
32
94
|
const button = container.querySelector('button');
|
|
33
95
|
const contentWrapper = button.parentElement.nextElementSibling;
|
|
34
96
|
|
|
97
|
+
if (!contentWrapper) return;
|
|
98
|
+
|
|
35
99
|
const buttonId = `faq-button-${index}`;
|
|
36
100
|
const contentId = `faq-content-${index}`;
|
|
37
101
|
|
package/autoInit/counter.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
// Named constants
|
|
2
|
-
const ACCESSIBILITY_UPDATE_DELAY = 100;
|
|
3
|
-
|
|
4
1
|
export function init() {
|
|
5
2
|
const config = {
|
|
6
3
|
duration: 3000,
|
|
7
|
-
keyboardStep: 5,
|
|
8
|
-
observerThreshold: 0,
|
|
9
|
-
observerRootMargin: "0px",
|
|
10
4
|
};
|
|
11
5
|
|
|
12
6
|
let counters = [];
|
|
@@ -16,16 +10,12 @@ export function init() {
|
|
|
16
10
|
Object.assign(config, newConfig);
|
|
17
11
|
}
|
|
18
12
|
|
|
19
|
-
// Power4 out easing function
|
|
20
13
|
function easeOutQuart(t) {
|
|
21
14
|
return 1 - Math.pow(1 - t, 4);
|
|
22
15
|
}
|
|
23
16
|
|
|
24
|
-
// Extract number and symbols from text
|
|
25
17
|
function parseText(text) {
|
|
26
|
-
const match = text.match(/([
|
|
27
|
-
if (!match) return null;
|
|
28
|
-
|
|
18
|
+
const match = text.match(/([^\d.]*)(\d*\.?\d+)(.*)/);
|
|
29
19
|
return {
|
|
30
20
|
prefix: match[1] || "",
|
|
31
21
|
number: parseFloat(match[2]),
|
|
@@ -33,37 +23,18 @@ export function init() {
|
|
|
33
23
|
};
|
|
34
24
|
}
|
|
35
25
|
|
|
36
|
-
// Format number back to text with symbols
|
|
37
26
|
function formatNumber(value, prefix, suffix, decimals = 0) {
|
|
38
|
-
const formattedNumber =
|
|
39
|
-
decimals > 0 ? value.toFixed(decimals) : Math.round(value);
|
|
27
|
+
const formattedNumber = decimals > 0 ? value.toFixed(decimals) : Math.round(value);
|
|
40
28
|
return `${prefix}${formattedNumber}${suffix}`;
|
|
41
29
|
}
|
|
42
30
|
|
|
43
|
-
// Check for reduced motion preference
|
|
44
31
|
function prefersReducedMotion() {
|
|
45
|
-
return (
|
|
46
|
-
window.matchMedia &&
|
|
47
|
-
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
48
|
-
);
|
|
32
|
+
return window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
49
33
|
}
|
|
50
34
|
|
|
51
|
-
|
|
52
|
-
function animateCounter(
|
|
53
|
-
element,
|
|
54
|
-
targetValue,
|
|
55
|
-
prefix,
|
|
56
|
-
suffix,
|
|
57
|
-
decimals,
|
|
58
|
-
duration = config.duration,
|
|
59
|
-
) {
|
|
60
|
-
// If user prefers reduced motion, show final value immediately
|
|
35
|
+
function animateCounter(element, targetValue, prefix, suffix, decimals) {
|
|
61
36
|
if (prefersReducedMotion()) {
|
|
62
|
-
|
|
63
|
-
if (originalContent) {
|
|
64
|
-
element.textContent = originalContent;
|
|
65
|
-
}
|
|
66
|
-
updateStatsAccessibility();
|
|
37
|
+
element.textContent = element.getAttribute("data-hs-original");
|
|
67
38
|
return;
|
|
68
39
|
}
|
|
69
40
|
|
|
@@ -72,267 +43,112 @@ export function init() {
|
|
|
72
43
|
|
|
73
44
|
const animate = () => {
|
|
74
45
|
const elapsed = Date.now() - startTime;
|
|
75
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
76
|
-
|
|
77
|
-
// Apply power4 out easing
|
|
46
|
+
const progress = Math.min(elapsed / config.duration, 1);
|
|
78
47
|
const easedProgress = easeOutQuart(progress);
|
|
79
|
-
const currentValue =
|
|
80
|
-
startValue + (targetValue - startValue) * easedProgress;
|
|
48
|
+
const currentValue = startValue + (targetValue - startValue) * easedProgress;
|
|
81
49
|
|
|
82
|
-
|
|
83
|
-
const animatedText = formatNumber(currentValue, prefix, suffix, decimals);
|
|
84
|
-
element.textContent = animatedText;
|
|
50
|
+
element.textContent = formatNumber(currentValue, prefix, suffix, decimals);
|
|
85
51
|
|
|
86
52
|
if (progress < 1) {
|
|
87
53
|
requestAnimationFrame(animate);
|
|
88
54
|
} else {
|
|
89
|
-
|
|
90
|
-
const originalContent = element.getAttribute("data-hs-original");
|
|
91
|
-
if (originalContent) {
|
|
92
|
-
element.textContent = originalContent;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Update accessibility after animation completes
|
|
96
|
-
updateStatsAccessibility();
|
|
55
|
+
element.textContent = element.getAttribute("data-hs-original");
|
|
97
56
|
}
|
|
98
57
|
};
|
|
99
58
|
|
|
100
|
-
// Ensure we start from 0
|
|
101
59
|
element.textContent = formatNumber(0, prefix, suffix, decimals);
|
|
102
|
-
|
|
103
|
-
// Start animation on next frame
|
|
104
60
|
requestAnimationFrame(animate);
|
|
105
61
|
}
|
|
106
62
|
|
|
107
|
-
// Set up intersection observer
|
|
108
63
|
function setupObserver() {
|
|
109
|
-
const options = {
|
|
110
|
-
root: null,
|
|
111
|
-
rootMargin: "0px",
|
|
112
|
-
threshold: 0,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
64
|
observer = new IntersectionObserver((entries) => {
|
|
116
|
-
// Group entries by their container to animate together
|
|
117
|
-
const containersToAnimate = new Set();
|
|
118
|
-
|
|
119
65
|
entries.forEach((entry) => {
|
|
120
|
-
if (!entry.target.dataset.animated) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (rect.top <= viewportHeight) {
|
|
126
|
-
// Find the parent container (like stats section)
|
|
127
|
-
const container =
|
|
128
|
-
entry.target.closest('[data-hs-accessibility="stats"]') ||
|
|
129
|
-
entry.target.closest(".g_content") ||
|
|
130
|
-
entry.target;
|
|
131
|
-
containersToAnimate.add(container);
|
|
132
|
-
}
|
|
66
|
+
if (entry.isIntersecting && !entry.target.dataset.animated) {
|
|
67
|
+
const numberElement = entry.target.querySelector('[data-hs-counter="number"]');
|
|
68
|
+
startAnimation(numberElement);
|
|
69
|
+
entry.target.dataset.animated = "true";
|
|
133
70
|
}
|
|
134
71
|
});
|
|
135
|
-
|
|
136
|
-
// Animate all counters in each container simultaneously
|
|
137
|
-
containersToAnimate.forEach((container) => {
|
|
138
|
-
const countersInContainer = container.querySelectorAll(
|
|
139
|
-
'[data-hs="stats-counter"]:not([data-animated])',
|
|
140
|
-
);
|
|
141
|
-
countersInContainer.forEach((counter) => {
|
|
142
|
-
startAnimation(counter);
|
|
143
|
-
counter.dataset.animated = "true";
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
}, options);
|
|
72
|
+
}, { threshold: 0 });
|
|
147
73
|
}
|
|
148
74
|
|
|
149
|
-
// Start animation for a specific element
|
|
150
75
|
function startAnimation(element) {
|
|
151
|
-
// Get original content from data attribute (the real value to animate to)
|
|
152
76
|
const originalText = element.getAttribute("data-hs-original");
|
|
153
|
-
if (!originalText) return;
|
|
154
|
-
|
|
155
77
|
const parsed = parseText(originalText);
|
|
156
|
-
if (!parsed) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Determine decimal places from original number
|
|
161
78
|
const decimals = (parsed.number.toString().split(".")[1] || "").length;
|
|
162
79
|
|
|
163
|
-
|
|
164
|
-
animateCounter(
|
|
165
|
-
element,
|
|
166
|
-
parsed.number,
|
|
167
|
-
parsed.prefix,
|
|
168
|
-
parsed.suffix,
|
|
169
|
-
decimals,
|
|
170
|
-
config.duration,
|
|
171
|
-
);
|
|
80
|
+
animateCounter(element, parsed.number, parsed.prefix, parsed.suffix, decimals);
|
|
172
81
|
}
|
|
173
82
|
|
|
174
|
-
// Stats accessibility functionality (moved from accessibility.js)
|
|
175
83
|
function setupStatsAccessibility() {
|
|
176
|
-
const statsElements = document.querySelectorAll(
|
|
177
|
-
'[data-hs-accessibility="stats"]',
|
|
178
|
-
);
|
|
84
|
+
const statsElements = document.querySelectorAll('[data-hs-counter="wrapper"]');
|
|
179
85
|
|
|
180
86
|
statsElements.forEach((element) => {
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
child.setAttribute("aria-hidden", "true");
|
|
192
|
-
});
|
|
193
|
-
}
|
|
87
|
+
const numberElement = element.querySelector('[data-hs-counter="number"]');
|
|
88
|
+
const originalText = numberElement.getAttribute("data-hs-original");
|
|
89
|
+
|
|
90
|
+
element.setAttribute("aria-label", originalText);
|
|
91
|
+
element.setAttribute("role", "img");
|
|
92
|
+
|
|
93
|
+
const allChildren = element.querySelectorAll("*");
|
|
94
|
+
allChildren.forEach((child) => {
|
|
95
|
+
child.setAttribute("aria-hidden", "true");
|
|
96
|
+
});
|
|
194
97
|
});
|
|
195
98
|
}
|
|
196
99
|
|
|
197
|
-
function extractTextContent(element) {
|
|
198
|
-
const textParts = [];
|
|
199
|
-
|
|
200
|
-
function processNode(node) {
|
|
201
|
-
// Skip elements with aria-hidden="true"
|
|
202
|
-
if (
|
|
203
|
-
node.nodeType === Node.ELEMENT_NODE &&
|
|
204
|
-
node.getAttribute("aria-hidden") === "true"
|
|
205
|
-
) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Use original content if available for counter elements
|
|
210
|
-
if (
|
|
211
|
-
node.nodeType === Node.ELEMENT_NODE &&
|
|
212
|
-
node.hasAttribute &&
|
|
213
|
-
node.hasAttribute("data-hs-original")
|
|
214
|
-
) {
|
|
215
|
-
const originalText = node.getAttribute("data-hs-original");
|
|
216
|
-
if (originalText) {
|
|
217
|
-
textParts.push(originalText);
|
|
218
|
-
return; // Don't process children
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Process text nodes
|
|
223
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
224
|
-
const text = node.textContent.trim();
|
|
225
|
-
if (text && text.length > 0) {
|
|
226
|
-
textParts.push(text);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Process child nodes
|
|
231
|
-
if (node.childNodes) {
|
|
232
|
-
node.childNodes.forEach(processNode);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
processNode(element);
|
|
237
|
-
|
|
238
|
-
// Combine all text parts with spaces and clean up
|
|
239
|
-
return textParts.join(" ").replace(/\s+/g, " ").trim();
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function updateStatsAccessibility() {
|
|
243
|
-
// Update accessibility after counter animations complete
|
|
244
|
-
setTimeout(() => {
|
|
245
|
-
setupStatsAccessibility();
|
|
246
|
-
}, ACCESSIBILITY_UPDATE_DELAY);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Initialize all counters
|
|
250
100
|
function initCounters() {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (parsed) {
|
|
260
|
-
// Store original content for accessibility and copy/paste
|
|
261
|
-
element.setAttribute("data-hs-original", element.textContent.trim());
|
|
262
|
-
|
|
263
|
-
// Keep original content visible until animation starts
|
|
264
|
-
// This ensures copy/paste gets real values before animation
|
|
265
|
-
|
|
266
|
-
counters.push(element);
|
|
267
|
-
}
|
|
101
|
+
const wrappers = document.querySelectorAll('[data-hs-counter="wrapper"]');
|
|
102
|
+
|
|
103
|
+
wrappers.forEach((wrapper) => {
|
|
104
|
+
const numberElement = wrapper.querySelector('[data-hs-counter="number"]');
|
|
105
|
+
const parsed = parseText(numberElement.textContent.trim());
|
|
106
|
+
|
|
107
|
+
numberElement.setAttribute("data-hs-original", numberElement.textContent.trim());
|
|
108
|
+
counters.push(wrapper);
|
|
268
109
|
});
|
|
269
110
|
|
|
270
|
-
// Set up intersection observer
|
|
271
111
|
setupObserver();
|
|
272
112
|
|
|
273
|
-
// Observe all counter elements
|
|
274
113
|
counters.forEach((counter) => {
|
|
275
114
|
observer.observe(counter);
|
|
276
115
|
});
|
|
277
116
|
|
|
278
|
-
// Set up initial accessibility (will use data-hs-original for screen readers)
|
|
279
117
|
setupStatsAccessibility();
|
|
280
118
|
}
|
|
281
119
|
|
|
282
|
-
// Method to manually trigger animation (useful for testing)
|
|
283
120
|
function triggerAnimation(selector) {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
121
|
+
const wrapper = document.querySelector(selector);
|
|
122
|
+
const numberElement = wrapper.querySelector('[data-hs-counter="number"]');
|
|
123
|
+
startAnimation(numberElement);
|
|
124
|
+
wrapper.dataset.animated = "true";
|
|
289
125
|
}
|
|
290
126
|
|
|
291
|
-
// Reset all counters (useful for re-triggering animations)
|
|
292
127
|
function reset() {
|
|
293
|
-
counters.forEach((
|
|
294
|
-
delete
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
'span[style*="position: absolute"]',
|
|
298
|
-
);
|
|
299
|
-
if (overlay) {
|
|
300
|
-
overlay.remove();
|
|
301
|
-
}
|
|
302
|
-
element.style.removeProperty("position");
|
|
303
|
-
element.style.removeProperty("color");
|
|
128
|
+
counters.forEach((wrapper) => {
|
|
129
|
+
delete wrapper.dataset.animated;
|
|
130
|
+
const numberElement = wrapper.querySelector('[data-hs-counter="number"]');
|
|
131
|
+
numberElement.textContent = numberElement.getAttribute("data-hs-original");
|
|
304
132
|
});
|
|
305
133
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
// Re-observe all counters
|
|
313
|
-
counters.forEach((counter) => {
|
|
314
|
-
observer.observe(counter);
|
|
315
|
-
});
|
|
316
|
-
}
|
|
134
|
+
counters.forEach((counter) => {
|
|
135
|
+
observer.unobserve(counter);
|
|
136
|
+
observer.observe(counter);
|
|
137
|
+
});
|
|
317
138
|
|
|
318
|
-
// Reset accessibility
|
|
319
139
|
setupStatsAccessibility();
|
|
320
140
|
}
|
|
321
141
|
|
|
322
|
-
// Initialize everything
|
|
323
142
|
initCounters();
|
|
324
143
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
counters,
|
|
334
|
-
};
|
|
335
|
-
}
|
|
144
|
+
window.hsmain = window.hsmain || {};
|
|
145
|
+
window.hsmain.counter = {
|
|
146
|
+
config,
|
|
147
|
+
updateConfig,
|
|
148
|
+
triggerAnimation,
|
|
149
|
+
reset,
|
|
150
|
+
counters,
|
|
151
|
+
};
|
|
336
152
|
|
|
337
153
|
return { result: "counter initialized" };
|
|
338
154
|
}
|
package/autoInit/modal.js
CHANGED
|
@@ -2,32 +2,10 @@ function initModal() {
|
|
|
2
2
|
const config = {
|
|
3
3
|
transitionDuration: 0.3,
|
|
4
4
|
blurOpacity: 0.5,
|
|
5
|
-
breakpoints: {
|
|
6
|
-
mobile: 767,
|
|
7
|
-
tablet: 991,
|
|
8
|
-
},
|
|
9
5
|
};
|
|
10
6
|
|
|
11
|
-
function getCurrentBreakpoint() {
|
|
12
|
-
const width = window.innerWidth;
|
|
13
|
-
if (width <= config.breakpoints.mobile) return "mobile";
|
|
14
|
-
if (width <= config.breakpoints.tablet) return "tablet";
|
|
15
|
-
return "desktop";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function shouldPreventModal(element) {
|
|
19
|
-
const preventAttr = element.getAttribute("data-hs-modalprevent");
|
|
20
|
-
if (!preventAttr) return false;
|
|
21
|
-
|
|
22
|
-
const currentBreakpoint = getCurrentBreakpoint();
|
|
23
|
-
const preventBreakpoints = preventAttr.split(",").map((bp) => bp.trim());
|
|
24
|
-
|
|
25
|
-
return preventBreakpoints.includes(currentBreakpoint);
|
|
26
|
-
}
|
|
27
7
|
|
|
28
8
|
function openModal(element) {
|
|
29
|
-
if (shouldPreventModal(element)) return;
|
|
30
|
-
|
|
31
9
|
document.body.classList.add("u-overflow-clip");
|
|
32
10
|
|
|
33
11
|
// Add blur to all other modals
|
|
@@ -53,29 +31,6 @@ function initModal() {
|
|
|
53
31
|
});
|
|
54
32
|
}
|
|
55
33
|
|
|
56
|
-
// Store modal states that were closed due to prevention
|
|
57
|
-
let preventedModalStates = new Map();
|
|
58
|
-
|
|
59
|
-
function handleBreakpointChange() {
|
|
60
|
-
document.querySelectorAll("[data-hs-modalprevent]").forEach((element) => {
|
|
61
|
-
const elementKey =
|
|
62
|
-
element.getAttribute("data-hs-modal") +
|
|
63
|
-
"_" +
|
|
64
|
-
(element.id || element.className);
|
|
65
|
-
const shouldPrevent = shouldPreventModal(element);
|
|
66
|
-
const wasStoredAsOpen = preventedModalStates.get(elementKey);
|
|
67
|
-
|
|
68
|
-
if (shouldPrevent && element.x) {
|
|
69
|
-
preventedModalStates.set(elementKey, true);
|
|
70
|
-
element.x = 0;
|
|
71
|
-
closeModal(element);
|
|
72
|
-
} else if (!shouldPrevent && wasStoredAsOpen) {
|
|
73
|
-
preventedModalStates.delete(elementKey);
|
|
74
|
-
element.x = 1;
|
|
75
|
-
openModal(element);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
34
|
|
|
80
35
|
function toggleModal(element) {
|
|
81
36
|
element.x = ((element.x || 0) + 1) % 2;
|
|
@@ -110,10 +65,6 @@ function initModal() {
|
|
|
110
65
|
});
|
|
111
66
|
});
|
|
112
67
|
|
|
113
|
-
// Handle window resize to check for prevented modals
|
|
114
|
-
window.addEventListener("resize", function () {
|
|
115
|
-
handleBreakpointChange();
|
|
116
|
-
});
|
|
117
68
|
|
|
118
69
|
return { result: "modal initialized" };
|
|
119
70
|
}
|