Last active
March 5, 2023 03:37
-
-
Save lionel-rowe/25b9ccf76379e3e12988bff837f6f492 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Disable arrow key hijacking | |
// @description Stop websites from hijacking left and right arrow keys. | |
// @author Lionel Rowe | |
// @run-at document-start | |
// @match http://*/* | |
// @match https://*/* | |
// @grant none | |
// @version 0.3 | |
// @namespace https://github.com/lionel-rowe | |
// ==/UserScript== | |
/** | |
* @returns { 'mdbook' | 'gitbook' | null } The generator used to create the | |
* current website, if any. `null` = none or unknown; any truthy value is a | |
* site generator that is known to hijack arrow keys. | |
*/ | |
const getSiteGeneratorName = () => { | |
const walker = document.createTreeWalker( | |
document.head, | |
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, | |
) | |
let node | |
while (node = walker.nextNode()) { | |
switch (node.nodeType) { | |
case Node.COMMENT_NODE: { | |
if (/\bmdbook\b/i.test(node.textContent)) { | |
return 'mdbook' | |
} | |
break | |
} | |
case Node.ELEMENT_NODE: { | |
if (node.tagName === 'META' | |
&& node.name === 'generator' | |
&& /\bgitbook\b/i.test(node.getAttribute('content')) | |
) { | |
return 'gitbook' | |
} | |
break | |
} | |
} | |
} | |
return null | |
} | |
const modifiers = Object.fromEntries(['ctrl', 'alt', 'shift', 'meta'] | |
.map((k) => [k, `${k}Key`])) | |
const matches = (event) => (matcher) => Object.values(modifiers) | |
.every((v) => matcher.includes(v) === event[v]) | |
const disableArrowKeyHijacking = () => { | |
document.addEventListener('keydown', (e) => { | |
const { ctrl, alt, shift } = modifiers | |
const normalScrolling = [[]] | |
const textSelection = [[shift], [ctrl, shift]] | |
const browserHistoryNavigation = [[alt]] | |
const nativeCombos = [normalScrolling, textSelection, browserHistoryNavigation].flat(1) | |
const isTextInputMode = ['INPUT', 'TEXTAREA'].includes(document.activeElement.nodeName) | |
if (['ArrowLeft', 'ArrowRight'].includes(e.key) && nativeCombos.some(matches(e)) || isTextInputMode) { | |
e.stopImmediatePropagation() | |
console.error(`Possible hijacking of ${e.key} was prevented.`) | |
} | |
}) | |
} | |
const reduceClickableNavHitboxes = (siteGeneratorName) => { | |
const selectors = { | |
mdbook: '.nav-chapters', | |
gitbook: '.navigation', | |
} | |
const selector = selectors[siteGeneratorName] | |
if (selector) { | |
document.head.insertAdjacentHTML('beforeend', `<style>${selector} { | |
height: 10rem; | |
top: 50%; | |
transform: translateY(-50%); | |
}</style>`); | |
} | |
} | |
const siteGeneratorName = getSiteGeneratorName() | |
if (siteGeneratorName) { | |
disableArrowKeyHijacking() | |
reduceClickableNavHitboxes(siteGeneratorName) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment