Quick n' Dirty: Keyboard Navigation
I was recently on a comic website and was struggling heavily with their poor UI layout that made navigating pages quite painful so I wrote a tiny tampermonkey script to add in WASD style navigation. This particular site has both between issue and in-issue Previous/Next, so there is a “next page” and a “next comic” button.
For compatibility this is written as an ES5 IIFE with ye-olde dom events instead of some sexier DOM 3 tricks. Links are grabbed by text content which is expensive but this particular site didn’t have consistent classes or ids. I use focusin
and focusout
to make sure we aren’t in a textfield when navigating so you can still use search and whatnot (and it’s way cheaper/easier than patching every input with custom events and pretty well supported in most browsers).
For some potential upgrades, move to ES6, use compositionstart
and compositionend
, and use the new keyboard API instead of fighting keyCode.
// ==UserScript==
// @name e6 key
// @namespace http://tampermonkey.net/
// @version 0.1
// @description add keyboard navigation
// @include *://blah.com/*
// @exclude *.json
// @exclude *.xml
// @grant none
// ==/UserScript==
(function(window, document) {
'use strict';
var isEditing = false;
//patch so we can disable ourselves on editing events
document.addEventListener('focusin', function(){
isEditing = true;
});
document.addEventListener('focusout', function(){
isEditing = false;
});
function getLinkByText(text) {
var aTags = document.getElementsByTagName("a");
for (var i = 0; i < aTags.length; i++) {
if (aTags[i].textContent === text) return aTags[i];
}
}
document.addEventListener('keydown', function(event) {
var target;
if(isEditing) return;
switch(event.keyCode) {
case 87: //w
window.scrollBy(0, -250);
break;
case 83: //s
window.scrollBy(0, 250);
break;
case 81: //q
target = getLinkByText('Previous');
if(target) return target.click();
event.preventDefault();
break;
case 69: //e
target = getLinkByText('Next');
if(target) return target.click();
event.preventDefault();
break;
case 65: //a
target = getLinkByText('<< Previous');
if(target) return target.click();
event.preventDefault();
break;
case 68: //d
target = getLinkByText('Next >>');
if(target) return target.click();
event.preventDefault();
break;
case 82: //r
target = getLinkByText('Random');
if(target) return target.click();
event.preventDefault();
break;
}
});
})(window, document);