From f8b5743a339907fd84d2475849b642845555bba3 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Fri, 24 Nov 2023 14:39:36 +0800 Subject: [PATCH 1/4] feat: keyboard event fallthrough --- src/navigator/IFrameNavigator.ts | 13 +++++++++++++ src/utils/KeyboardEventHandler.ts | 27 +++++++++++++++------------ viewer/index_dita.html | 6 ++++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/navigator/IFrameNavigator.ts b/src/navigator/IFrameNavigator.ts index 311a535f..df576fc9 100644 --- a/src/navigator/IFrameNavigator.ts +++ b/src/navigator/IFrameNavigator.ts @@ -97,6 +97,7 @@ import { ConsumptionModule, ConsumptionModuleConfig, } from "../modules/consumption/ConsumptionModule"; +import KeyDownEvent = JQuery.KeyDownEvent; export type GetContent = (href: string) => Promise; export type GetContentBytesLength = ( @@ -117,6 +118,7 @@ export interface NavigatorAPI { resourceAtEnd: any; resourceFitsScreen: any; updateCurrentLocation: any; + keydownFallthrough: any; direction: any; onError?: (e: Error) => void; } @@ -1004,6 +1006,8 @@ export class IFrameNavigator extends EventEmitter implements Navigator { this.handlePreviousChapterClick.bind(this); this.keyboardEventHandler.onForwardSwipe = this.handleNextChapterClick.bind(this); + this.keyboardEventHandler.onKeydown = + this.handleKeydownFallthrough.bind(this); } if (this.touchEventHandler) { this.touchEventHandler.onBackwardSwipe = @@ -1048,6 +1052,8 @@ export class IFrameNavigator extends EventEmitter implements Navigator { this.handlePreviousPageClick.bind(this); this.keyboardEventHandler.onForwardSwipe = this.handleNextPageClick.bind(this); + this.keyboardEventHandler.onKeydown = + this.handleKeydownFallthrough.bind(this); } } else { if (this.infoBottom) this.infoBottom.style.display = "none"; @@ -1168,6 +1174,8 @@ export class IFrameNavigator extends EventEmitter implements Navigator { this.handlePreviousPageClick.bind(this); this.keyboardEventHandler.onForwardSwipe = this.handleNextPageClick.bind(this); + this.keyboardEventHandler.onKeydown = + this.handleKeydownFallthrough.bind(this); } } }); @@ -2815,6 +2823,11 @@ export class IFrameNavigator extends EventEmitter implements Navigator { } } + private handleKeydownFallthrough(event: KeyDownEvent | undefined): void { + if (this.api?.keydownFallthrough) this.api?.keydownFallthrough(event); + this.emit("keydown", event); + } + private hideView(): void { if (this.view?.layout !== "fixed") { if (this.view?.isScrollMode()) { diff --git a/src/utils/KeyboardEventHandler.ts b/src/utils/KeyboardEventHandler.ts index 6ec58714..69c1a0ef 100644 --- a/src/utils/KeyboardEventHandler.ts +++ b/src/utils/KeyboardEventHandler.ts @@ -29,6 +29,7 @@ export default class KeyboardEventHandler { public onBackwardSwipe: (event: UIEvent) => void = () => {}; public onForwardSwipe: (event: UIEvent) => void = () => {}; + public onKeydown: (event: UIEvent) => void = () => {}; public setupEvents = (element: HTMLElement | Document | null): void => { if (element) { @@ -93,20 +94,22 @@ export default class KeyboardEventHandler { switch (key) { case "ArrowRight": self.rtl ? self.onBackwardSwipe(event) : self.onForwardSwipe(event); - break; + return; case "ArrowLeft": self.rtl ? self.onForwardSwipe(event) : self.onBackwardSwipe(event); - break; - } - switch (event.code) { - case "Space": - if (event.ctrlKey) { - self.onBackwardSwipe(event); - } else { - self.onForwardSwipe(event); - } - break; - } + return; + } + switch (event.code) { + case "Space": + if (event.ctrlKey) { + self.onBackwardSwipe(event); + return; + } else { + self.onForwardSwipe(event); + return; + } + } + self.onKeydown(event); }) ); } diff --git a/viewer/index_dita.html b/viewer/index_dita.html index 0f6b0be0..27763daa 100644 --- a/viewer/index_dita.html +++ b/viewer/index_dita.html @@ -1402,6 +1402,9 @@ ); }); }, + keydownFallthrough: function(event) { + console.log("api.keydownFallthrough:" + event.key); + }, onError: function(error) { console.log(error); }, @@ -1449,6 +1452,9 @@ instance.addEventListener("resource.ready", () => { console.log("listener ready"); }); + instance.addEventListener("keydown", (event) => { + console.log("keydown: " + event.key); + }); }).catch(error => { console.error(error); From 75afdbe7965603984ec890389764149552334381 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Mon, 27 Nov 2023 14:30:44 +0800 Subject: [PATCH 2/4] feat: click event fallthrough had to replace onclick by event listener in Popup.ts so that the events can be captured and propagation can be stopped --- src/modules/search/Popup.ts | 38 ++++++++++++++++++++------------ src/navigator/IFrameNavigator.ts | 6 ++++- src/utils/EventHandler.ts | 2 +- viewer/index_dita.html | 6 +++++ 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/modules/search/Popup.ts b/src/modules/search/Popup.ts index 88b18f2e..c02a1b46 100644 --- a/src/modules/search/Popup.ts +++ b/src/modules/search/Popup.ts @@ -151,16 +151,21 @@ export class Popup { return; } let self = this; - win.onclick = function (ev) { - if (event.target !== ev.target) { - if (d2popover.parentElement) { - self.hidePopover(); - if (win) { - win.onclick = null; + win.addEventListener( + "click", + function (ev) { + if (event.target !== ev.target) { + if (d2popover.parentElement) { + self.hidePopover(); + ev.stopImmediatePropagation(); } } + }, + { + once: true, + capture: true, } - }; + ); } } else if (src) { let absolute = getAbsoluteHref(src); @@ -207,16 +212,21 @@ export class Popup { return; } let self = this; - win.onclick = function (ev) { - if (event.target !== ev.target) { - if (d2popover.parentElement) { - self.hidePopover(); - if (win) { - win.onclick = null; + win.addEventListener( + "click", + function (ev) { + if (event.target !== ev.target) { + if (d2popover.parentElement) { + self.hidePopover(); + ev.stopImmediatePropagation(); } } + }, + { + once: true, + capture: true, } - }; + ); } } } diff --git a/src/navigator/IFrameNavigator.ts b/src/navigator/IFrameNavigator.ts index df576fc9..66841dd5 100644 --- a/src/navigator/IFrameNavigator.ts +++ b/src/navigator/IFrameNavigator.ts @@ -119,6 +119,7 @@ export interface NavigatorAPI { resourceFitsScreen: any; updateCurrentLocation: any; keydownFallthrough: any; + clickThrough: any; direction: any; onError?: (e: Error) => void; } @@ -2491,7 +2492,10 @@ export class IFrameNavigator extends EventEmitter implements Navigator { } } - private handleClickThrough(_event: MouseEvent | TouchEvent) {} + private handleClickThrough(event: MouseEvent | TouchEvent) { + if (this.api?.clickThrough) this.api?.clickThrough(event); + this.emit("click", event); + } private handleInternalLink(event: MouseEvent | TouchEvent) { const element = event.target; diff --git a/src/utils/EventHandler.ts b/src/utils/EventHandler.ts index 3e3be158..6ef95771 100644 --- a/src/utils/EventHandler.ts +++ b/src/utils/EventHandler.ts @@ -68,7 +68,7 @@ export default class EventHandler { // Most click handling is done in the touchend and mouseup event handlers, // but if there's a click on an external link we need to cancel the click // event to prevent it from opening in the iframe. - element.addEventListener("click", this.handleLinks.bind(this)); + element.addEventListener("click", this.handleLinks.bind(this), true); } else { throw "cannot setup events for null"; } diff --git a/viewer/index_dita.html b/viewer/index_dita.html index 27763daa..d6277591 100644 --- a/viewer/index_dita.html +++ b/viewer/index_dita.html @@ -1405,6 +1405,9 @@ keydownFallthrough: function(event) { console.log("api.keydownFallthrough:" + event.key); }, + clickThrough: function(event) { + console.log("api.clickThrough"); + }, onError: function(error) { console.log(error); }, @@ -1455,6 +1458,9 @@ instance.addEventListener("keydown", (event) => { console.log("keydown: " + event.key); }); + instance.addEventListener("click", (event) => { + console.log("click through: " + event.detail); + }); }).catch(error => { console.error(error); From 9ba2531641c57e08bfbb274ff7e2a84c04e007fe Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Wed, 13 Dec 2023 15:05:19 +0800 Subject: [PATCH 3/4] fix: add click through for fixed view --- src/navigator/IFrameNavigator.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/navigator/IFrameNavigator.ts b/src/navigator/IFrameNavigator.ts index 66841dd5..a4ad9d02 100644 --- a/src/navigator/IFrameNavigator.ts +++ b/src/navigator/IFrameNavigator.ts @@ -1002,6 +1002,9 @@ export class IFrameNavigator extends EventEmitter implements Navigator { this.nextChapterBottomAnchorElement.style.display = "none"; if (this.previousChapterTopAnchorElement) this.previousChapterTopAnchorElement.style.display = "none"; + if (this.eventHandler) { + this.eventHandler.onClickThrough = this.handleClickThrough.bind(this); + } if (this.keyboardEventHandler) { this.keyboardEventHandler.onBackwardSwipe = this.handlePreviousChapterClick.bind(this); From a1ba5aba81d17df99c04aad13626b4c231a2f17e Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 20 Feb 2024 11:13:14 +0800 Subject: [PATCH 4/4] style: lint --- src/navigator/IFrameNavigator.ts | 4 ++-- src/utils/KeyboardEventHandler.ts | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/navigator/IFrameNavigator.ts b/src/navigator/IFrameNavigator.ts index a4ad9d02..f1900d99 100644 --- a/src/navigator/IFrameNavigator.ts +++ b/src/navigator/IFrameNavigator.ts @@ -1708,8 +1708,8 @@ export class IFrameNavigator extends EventEmitter implements Navigator { e instanceof Error ? e : typeof e === "string" - ? new Error(e) - : new Error("An unknown error occurred in the IFrameNavigator."); + ? new Error(e) + : new Error("An unknown error occurred in the IFrameNavigator."); this.api.onError(trueError); } else { // otherwise just display the standard error UI diff --git a/src/utils/KeyboardEventHandler.ts b/src/utils/KeyboardEventHandler.ts index 69c1a0ef..7ea49b72 100644 --- a/src/utils/KeyboardEventHandler.ts +++ b/src/utils/KeyboardEventHandler.ts @@ -98,17 +98,17 @@ export default class KeyboardEventHandler { case "ArrowLeft": self.rtl ? self.onForwardSwipe(event) : self.onBackwardSwipe(event); return; - } - switch (event.code) { - case "Space": - if (event.ctrlKey) { - self.onBackwardSwipe(event); - return; - } else { - self.onForwardSwipe(event); - return; - } - } + } + switch (event.code) { + case "Space": + if (event.ctrlKey) { + self.onBackwardSwipe(event); + return; + } else { + self.onForwardSwipe(event); + return; + } + } self.onKeydown(event); }) );