Skip to content

Commit 79d76c7

Browse files
committed
♻️ Cleaned up event listeners
1 parent 507546d commit 79d76c7

1 file changed

Lines changed: 57 additions & 16 deletions

File tree

src/scripts/explain-code.ts

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
const sheets = new Map<string, HTMLDivElement>();
2-
let isInitialized = false;
2+
const sheetListeners = new WeakMap<
3+
HTMLElement,
4+
{
5+
closeButton: () => void;
6+
escapeKey: (e: KeyboardEvent) => void;
7+
}
8+
>();
9+
let clickHandler: ((e: MouseEvent) => void) | null = null;
310

411
function initExplainCodeButtons() {
5-
// Prevent multiple initializations
6-
if (isInitialized) return;
7-
isInitialized = true;
12+
// Remove existing handler if present
13+
if (clickHandler) {
14+
document.body.removeEventListener("click", clickHandler);
15+
}
816

9-
// Use event delegation on document body to catch all clicks
10-
document.body.addEventListener("click", (e) => {
17+
// Create new click handler
18+
clickHandler = (e: MouseEvent) => {
1119
const target = e.target as HTMLElement;
1220
const button = target.closest<HTMLButtonElement>(
1321
"button[data-sheet-trigger]",
@@ -34,7 +42,21 @@ function initExplainCodeButtons() {
3442
}
3543

3644
openSheet(sheet);
37-
});
45+
};
46+
47+
// Attach the new handler
48+
document.body.addEventListener("click", clickHandler);
49+
}
50+
51+
function cleanup() {
52+
// Remove click handler
53+
if (clickHandler) {
54+
document.body.removeEventListener("click", clickHandler);
55+
clickHandler = null;
56+
}
57+
58+
// Restore body overflow in case a sheet was open
59+
document.body.style.overflow = "";
3860
}
3961

4062
function createSheet(
@@ -154,6 +176,9 @@ function initSheet(container: HTMLElement) {
154176

155177
if (!content) return;
156178

179+
// Check if listeners already exist for this sheet
180+
if (sheetListeners.has(content)) return;
181+
157182
function closeSheet() {
158183
const side = content.dataset.side || "right";
159184
const slideInClass = `slide-in-from-${side}`;
@@ -172,13 +197,23 @@ function initSheet(container: HTMLElement) {
172197
document.body.style.overflow = "";
173198
}
174199

175-
closeButton?.addEventListener("click", closeSheet);
176-
177-
document.addEventListener("keydown", (e) => {
200+
// Create listener functions that can be removed later
201+
const closeButtonHandler = () => closeSheet();
202+
const escapeKeyHandler = (e: KeyboardEvent) => {
178203
if (e.key === "Escape" && content.dataset.state === "open") {
179204
closeSheet();
180205
}
206+
};
207+
208+
// Store listener references for potential cleanup
209+
sheetListeners.set(content, {
210+
closeButton: closeButtonHandler,
211+
escapeKey: escapeKeyHandler,
181212
});
213+
214+
// Attach listeners
215+
closeButton?.addEventListener("click", closeButtonHandler);
216+
document.addEventListener("keydown", escapeKeyHandler);
182217
}
183218

184219
function openSheet(container: HTMLElement) {
@@ -200,16 +235,22 @@ function openSheet(container: HTMLElement) {
200235
firstFocusable?.focus();
201236
}
202237

203-
document.addEventListener("astro:page-load", () => {
204-
initExplainCodeButtons();
238+
// Clean up before Astro swaps pages (view transitions)
239+
document.addEventListener("astro:before-swap", () => {
240+
cleanup();
205241
});
206242

207-
// Also try DOMContentLoaded as a fallback
208-
document.addEventListener("DOMContentLoaded", () => {
243+
// Initialize on every page load (works with view transitions)
244+
document.addEventListener("astro:page-load", () => {
209245
initExplainCodeButtons();
210246
});
211247

212-
// And try running immediately if DOM is already loaded
213-
if (document.readyState !== "loading") {
248+
// Fallback for non-Astro environments or initial page load
249+
if (document.readyState === "loading") {
250+
document.addEventListener("DOMContentLoaded", () => {
251+
initExplainCodeButtons();
252+
});
253+
} else {
254+
// DOM already loaded, initialize immediately
214255
initExplainCodeButtons();
215256
}

0 commit comments

Comments
 (0)