]> BookStack Code Mirror - hacks/commitdiff
refactor(mermaid-viewer): Use AbortController for event listener cleanup
authorAlexander Wilms <redacted>
Thu, 26 Jun 2025 22:20:35 +0000 (00:20 +0200)
committerAlexander Wilms <redacted>
Thu, 26 Jun 2025 22:20:35 +0000 (00:20 +0200)
content/mermaid-viewer/head.html

index fe9d0cd897b682f594840b15d9dc08f765132fc0..b737ba049336044d88a3c0f07a01c8b21373f779 100644 (file)
@@ -74,6 +74,9 @@
             this.zoomOutBtn = null;
             this.zoomResetBtn = null;
 
+            // Use an AbortController for robust event listener cleanup.
+            this.abortController = new AbortController();
+
             // Bind event handlers for proper addition and removal
             this.boundMouseMoveHandler = this.handleMouseMove.bind(this);
             this.boundMouseUpHandler = this.handleMouseUp.bind(this);
         }
 
         setupEventListeners() {
-            this.toggleInteractionBtn.addEventListener('click', this.boundToggleInteraction);
-            this.copyCodeBtn.addEventListener('click', this.boundCopyCode);
-            this.zoomInBtn.addEventListener('click', this.boundZoomIn);
-            this.zoomOutBtn.addEventListener('click', this.boundZoomOut);
-            this.zoomResetBtn.addEventListener('click', this.boundResetZoom);
+            const { signal } = this.abortController;
+
+            this.toggleInteractionBtn.addEventListener('click', this.boundToggleInteraction, { signal });
+            this.copyCodeBtn.addEventListener('click', this.boundCopyCode, { signal });
+            this.zoomInBtn.addEventListener('click', this.boundZoomIn, { signal });
+            this.zoomOutBtn.addEventListener('click', this.boundZoomOut, { signal });
+            this.zoomResetBtn.addEventListener('click', this.boundResetZoom, { signal });
 
-            this.viewport.addEventListener('wheel', this.boundHandleWheel, { passive: false });
-            this.viewport.addEventListener('mousedown', this.boundHandleMouseDown);
+            this.viewport.addEventListener('wheel', this.boundHandleWheel, { passive: false, signal });
+            this.viewport.addEventListener('mousedown', this.boundHandleMouseDown, { signal });
 
             // Listen on document for mousemove to handle dragging outside viewport
-            document.addEventListener('mousemove', this.boundMouseMoveHandler);
+            document.addEventListener('mousemove', this.boundMouseMoveHandler, { signal });
             // Listen on window for mouseup to ensure drag ends even if mouse is released outside
-            window.addEventListener('mouseup', this.boundMouseUpHandler, true); // Use capture phase
+            window.addEventListener('mouseup', this.boundMouseUpHandler, { signal, capture: true });
 
-            this.viewport.addEventListener('contextmenu', this.boundPreventDefault);
-            this.viewport.addEventListener('selectstart', this.boundPreventSelect);
+            this.viewport.addEventListener('contextmenu', this.boundPreventDefault, { signal });
+            this.viewport.addEventListener('selectstart', this.boundPreventSelect, { signal });
         }
 
         toggleInteraction() {
         }
 
         destroy() {
-            // Remove event listeners specific to this instance
-            this.toggleInteractionBtn.removeEventListener('click', this.boundToggleInteraction);
-            this.copyCodeBtn.removeEventListener('click', this.boundCopyCode);
-            this.zoomInBtn.removeEventListener('click', this.boundZoomIn);
-            this.zoomOutBtn.removeEventListener('click', this.boundZoomOut);
-            this.zoomResetBtn.removeEventListener('click', this.boundResetZoom);
-
-            this.viewport.removeEventListener('wheel', this.boundHandleWheel, { passive: false });
-            this.viewport.removeEventListener('mousedown', this.boundHandleMouseDown);
-            this.viewport.removeEventListener('contextmenu', this.boundPreventDefault);
-            this.viewport.removeEventListener('selectstart', this.boundPreventSelect);
-
-            document.removeEventListener('mousemove', this.boundMouseMoveHandler);
-            window.removeEventListener('mouseup', this.boundMouseUpHandler, true);
-
+            // Abort all listeners attached with this controller's signal.
+            this.abortController.abort();
             this.container.innerHTML = ''; // Clear the container's content
         }
     }