Last active
February 11, 2021 15:55
-
-
Save amacfie/04b1da41137ed0bb20c554468f34b67c to your computer and use it in GitHub Desktop.
Greasemonkey script to add keybindings for focusing the next/previous form element
This file contains 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== | |
// @namespace https://gist.github.com/amacfie/04b1da41137ed0bb20c554468f34b67c | |
// @description Add keybindings for focusing the next/previous form element | |
// @include http* | |
// @run-at document-start | |
// @noframes | |
// ==/UserScript== | |
var isGoodEl = function (node) { | |
var formTags = ['INPUT', 'SELECT', 'BUTTON', 'TEXTAREA']; | |
var isFormEl = 'tagName' in node && formTags.includes(node.tagName); | |
if (!isFormEl) return false; | |
if ('type' in node && node.type === 'hidden') return false; | |
if ('readOnly' in node && node.readOnly) return false; | |
if ('disabled' in node && node.disabled) return false; | |
return true; | |
}; | |
// will start from selected/focused element but not highlighted search match | |
// because the DOM has no access to that | |
var focusNext = function (forwards, nodePred) { | |
var start; | |
if (document.activeElement !== document.body) { | |
start = document.activeElement; | |
} else if (document.getSelection().focusNode) { | |
start = document.getSelection().focusNode; | |
} else { | |
start = document.body; | |
} | |
var walker = document.createTreeWalker( | |
document.body, | |
5, // NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT doesn't work in GM | |
null, | |
false | |
); | |
var node; | |
var nodes = [document.body]; | |
while(node = walker.nextNode()) { | |
nodes.push(node); | |
} | |
var startIndex = nodes.indexOf(start); | |
for (var i=1; i <= nodes.length - 1; ++i) { | |
var pos; | |
if (forwards) { | |
pos = (startIndex + i) % nodes.length; | |
} else { | |
pos = (startIndex - i + nodes.length) % nodes.length; | |
} | |
if (nodePred(nodes[pos])) { | |
var prev = document.activeElement; | |
nodes[pos].focus(); | |
if (prev !== document.activeElement) break; | |
} | |
} | |
}; | |
// bind ctrl-` and ctrl-~ | |
var handleKey = function (e) { | |
if (e.ctrlKey && e.key === '`') { | |
focusNext(true, isGoodEl); | |
} else if (e.ctrlKey && e.key === '~') { | |
focusNext(false, isGoodEl); | |
} | |
}; | |
document.addEventListener('keydown', handleKey, false); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment