From 0788c4d9188d1df79d817e33f75a4bbc60e62ea6 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 18 Apr 2024 11:59:49 +0200 Subject: [PATCH] Remove event listeners with `signal` in web/pdf_presentation_mode.js By using the `signal` option when invoking `addEventListener`, see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#signal), we're able to remove an arbitrary number of event listeners with (effectively) a single line of code. Besides getting rid of a bunch of `removeEventListener`-calls, which means shorter code, we no longer need to manually keep track of event-handling functions. --- web/pdf_presentation_mode.js | 93 +++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/web/pdf_presentation_mode.js b/web/pdf_presentation_mode.js index cc2be0c2f..004af1af1 100644 --- a/web/pdf_presentation_mode.js +++ b/web/pdf_presentation_mode.js @@ -49,6 +49,10 @@ class PDFPresentationMode { #args = null; + #fullscreenChangeAbortController = null; + + #windowAbortController = null; + /** * @param {PDFPresentationModeOptions} options */ @@ -346,59 +350,62 @@ class PDFPresentationMode { } #addWindowListeners() { - this.showControlsBind = this.#showControls.bind(this); - this.mouseDownBind = this.#mouseDown.bind(this); - this.mouseWheelBind = this.#mouseWheel.bind(this); - this.resetMouseScrollStateBind = this.#resetMouseScrollState.bind(this); - this.contextMenuBind = this.#contextMenu.bind(this); - this.touchSwipeBind = this.#touchSwipe.bind(this); + if (this.#windowAbortController) { + return; + } + this.#windowAbortController = new AbortController(); + const { signal } = this.#windowAbortController; - window.addEventListener("mousemove", this.showControlsBind); - window.addEventListener("mousedown", this.mouseDownBind); - window.addEventListener("wheel", this.mouseWheelBind, { passive: false }); - window.addEventListener("keydown", this.resetMouseScrollStateBind); - window.addEventListener("contextmenu", this.contextMenuBind); - window.addEventListener("touchstart", this.touchSwipeBind); - window.addEventListener("touchmove", this.touchSwipeBind); - window.addEventListener("touchend", this.touchSwipeBind); + const touchSwipeBind = this.#touchSwipe.bind(this); + + window.addEventListener("mousemove", this.#showControls.bind(this), { + signal, + }); + window.addEventListener("mousedown", this.#mouseDown.bind(this), { + signal, + }); + window.addEventListener("wheel", this.#mouseWheel.bind(this), { + passive: false, + signal, + }); + window.addEventListener("keydown", this.#resetMouseScrollState.bind(this), { + signal, + }); + window.addEventListener("contextmenu", this.#contextMenu.bind(this), { + signal, + }); + window.addEventListener("touchstart", touchSwipeBind, { signal }); + window.addEventListener("touchmove", touchSwipeBind, { signal }); + window.addEventListener("touchend", touchSwipeBind, { signal }); } #removeWindowListeners() { - window.removeEventListener("mousemove", this.showControlsBind); - window.removeEventListener("mousedown", this.mouseDownBind); - window.removeEventListener("wheel", this.mouseWheelBind, { - passive: false, - }); - window.removeEventListener("keydown", this.resetMouseScrollStateBind); - window.removeEventListener("contextmenu", this.contextMenuBind); - window.removeEventListener("touchstart", this.touchSwipeBind); - window.removeEventListener("touchmove", this.touchSwipeBind); - window.removeEventListener("touchend", this.touchSwipeBind); - - delete this.showControlsBind; - delete this.mouseDownBind; - delete this.mouseWheelBind; - delete this.resetMouseScrollStateBind; - delete this.contextMenuBind; - delete this.touchSwipeBind; - } - - #fullscreenChange() { - if (/* isFullscreen = */ document.fullscreenElement) { - this.#enter(); - } else { - this.#exit(); - } + this.#windowAbortController?.abort(); + this.#windowAbortController = null; } #addFullscreenChangeListeners() { - this.fullscreenChangeBind = this.#fullscreenChange.bind(this); - window.addEventListener("fullscreenchange", this.fullscreenChangeBind); + if (this.#fullscreenChangeAbortController) { + return; + } + this.#fullscreenChangeAbortController = new AbortController(); + + window.addEventListener( + "fullscreenchange", + () => { + if (/* isFullscreen = */ document.fullscreenElement) { + this.#enter(); + } else { + this.#exit(); + } + }, + { signal: this.#fullscreenChangeAbortController.signal } + ); } #removeFullscreenChangeListeners() { - window.removeEventListener("fullscreenchange", this.fullscreenChangeBind); - delete this.fullscreenChangeBind; + this.#fullscreenChangeAbortController?.abort(); + this.#fullscreenChangeAbortController = null; } }