Skip to content

Commit

Permalink
Merge pull request #682 from gotson/fix/keyboard-removelistener
Browse files Browse the repository at this point in the history
fix: properly unregister keydown event on top-level document on stop
  • Loading branch information
aferditamuriqi authored Jan 31, 2024
2 parents 87c1123 + 0552d19 commit 0022920
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 45 deletions.
3 changes: 3 additions & 0 deletions src/navigator/IFrameNavigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ export class IFrameNavigator extends EventEmitter implements Navigator {
this.iframes.forEach((iframe) => {
removeEventListenerOptional(iframe, "resize", this.onResize);
});

if (this.didInitKeyboardEventHandler)
this.keyboardEventHandler.removeEvents(document);
}
spreads: HTMLDivElement;
firstSpread: HTMLDivElement;
Expand Down
108 changes: 63 additions & 45 deletions src/utils/KeyboardEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,59 +35,77 @@ export default class KeyboardEventHandler {
}
};

public removeEvents = (element: HTMLElement | Document | null): void => {
if (element) {
const self = this;
element.removeEventListener("focusin", this.onFocusIn(self), true);
element.removeEventListener("keydown", this.onKeyDown(self), false);
}
};

public focusin = (element: HTMLElement | Document): void => {
const self = this;
element.addEventListener(
"focusin",
function (event: KeyboardEvent) {
self.navigator.view?.snap(event.target as HTMLElement);
},
true
);
element.addEventListener("focusin", this.onFocusIn(self), true);
};

public keydown = (element: HTMLElement | Document): void => {
const self = this;
if (!this.navigator.rights.customKeyboardEvents) {
element.addEventListener(
"keydown",
function (event: KeyboardEvent) {
// Ignore input elements
const eventTarget = event.target as HTMLElement;
if (/input|select|option|textarea/i.test(eventTarget.tagName)) {
return;
}
element.addEventListener("keydown", this.onKeyDown(self), false);
}
};

// Ignore when active text selection
const ownerDocument = (eventTarget.ownerDocument ||
eventTarget) as HTMLDocument;
const ownerWindow = ownerDocument.defaultView as Window;
const selection = ownerWindow.getSelection() as Selection;
if (!selection.isCollapsed) {
return;
}
// store the generated event handlers, so they can be returned
// when removing the event listeners
private handlers = {};

const key = event.key;
switch (key) {
case "ArrowRight":
self.onForwardSwipe(event);
break;
case "ArrowLeft":
private onFocusIn(self: this) {
return (
this.handlers["onFocusIn"] ||
(this.handlers["onFocusIn"] = function (event: KeyboardEvent) {
self.navigator.view?.snap(event.target as HTMLElement);
})
);
}

private onKeyDown(self: this) {
return (
this.handlers["onKeyDown"] ||
(this.handlers["onKeyDown"] = function(event: KeyboardEvent) {
// Ignore input elements
const eventTarget = event.target as HTMLElement;
if (/input|select|option|textarea/i.test(eventTarget.tagName)) {
return;
}

// Ignore when active text selection
const ownerDocument = (eventTarget.ownerDocument ||
eventTarget) as HTMLDocument;
const ownerWindow = ownerDocument.defaultView as Window;
const selection = ownerWindow.getSelection() as Selection;
if (!selection.isCollapsed) {
return;
}

const key = event.key;
switch (key) {
case "ArrowRight":
self.onForwardSwipe(event);
break;
case "ArrowLeft":
self.onBackwardSwipe(event);
break;
}
switch (event.code) {
case "Space":
if (event.ctrlKey) {
self.onBackwardSwipe(event);
break;
}
switch (event.code) {
case "Space":
if (event.ctrlKey) {
self.onBackwardSwipe(event);
} else {
self.onForwardSwipe(event);
}
break;
}
},
false
);
}
};
} else {
self.onForwardSwipe(event);
}
break;
}
})
);
}
}

0 comments on commit 0022920

Please sign in to comment.