Skip to content

Instantly share code, notes, and snippets.

@AutoSponge
Last active October 29, 2018 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AutoSponge/6b54f2afa7ec30591cbfa1eaead483d5 to your computer and use it in GitHub Desktop.
Save AutoSponge/6b54f2afa7ec30591cbfa1eaead483d5 to your computer and use it in GitHub Desktop.
function createWalker(el = document.body) {
const walker = document.createTreeWalker(
el,
NodeFilter.SHOW_ELEMENT,
{ acceptNode: node => {
if (node.tabIndex > -1) {
if (!isVisible(node)) {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_SKIP;
}},
false
);
return walker;
};
function isVisible (el) {
while (!(/body/i).test(el.tagName)) {
style = getComputedStyle(el, null);
if (style.visibility === 'hidden' || style.display === 'none') {
return false;
}
el = el.parentNode;
}
return true;
}
function sendEvents(el) {
const opts = {bubbles: true, cancelable: true};
const tab = Object.assign({
code: 'Tab', which: 9, key: 'Tab', keyCode : 9,
altKey: false, ctrlKey: false, shiftKey: false, metaKey: false
}, opts);
const shift = Object.assign({}, tab, {shiftKey: true});
const events = [
new KeyboardEvent('keydown', tab),
new KeyboardEvent('keyup', tab),
new KeyboardEvent('keypress', tab),
new KeyboardEvent('keydown', shift),
new KeyboardEvent('keyup', shift),
new KeyboardEvent('keypress', shift),
new Event('blur', opts),
new Event('focusout', opts),
new Event('focusin', opts)
];
events.forEach(event => {
el.dispatchEvent(event);
if (document.activeElement !== el) {
console.log('found focus-changing listener', el, event);
el.focus();
}
});
}
function getTabbable() {
const tabIndexOrder = [];
const sourceOrder = [];
const walker = createWalker();
walker.nextNode();
let el = walker.currentNode;
while (el) {
el.focus();
if (el === document.activeElement) {
sendEvents(el);
if (el.tabIndex <= 0) {
sourceOrder.push(el)
} else {
tabIndexOrder.push(el);
}
} else {
console.log('unable to focus', el);
}
walker.nextNode();
if (el === walker.currentNode) {
break; // we were unable to skip the last el
}
el = walker.currentNode;
}
return [].concat(tabIndexOrder.sort((a, b) => b.tabIndex > a.tabIndex), sourceOrder);
}
console.log(getTabbable())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment