I want to detect when user focuses a link or input field by pressing the Tab key. Does anyone know of a way to do this? I have tried using the onFocus event, but it does not seem to work.
(I am not using jQuery, and I want to detect focus on links as well, so the similar question 16144611 is not the same as this one.)
By combining keyUp
and document.activeElement
we can see if an element is currently focused.
We then need to look for the Tab key on keyup and you have a reasonable start at a solution.
const els = document.querySelectorAll('a, input');
window.addEventListener('keyup', function(e){
// check the key code
const code = (e.keyCode ? e.keyCode : e.which);
if(code == 9 && els.length){
checkFocus();
}
});
function checkFocus(){
// loop all elements (within our selector at the start) and see if they match the document.activeElement
for (const el of els) {
if(document.activeElement == el){
console.log("focused tag:" + el.tagName);
}
}
}
<button>Click me for focus, I am not checked</button>
<a href="#">Focused Link</a>
<label for="input1">I am also reported</label>
<input id="input1">
<button>Another button not announced</button>
Note that if you only ever want to check for links and inputs only a more efficient way to check would be:
const els = ['A', 'INPUT'];
window.addEventListener('keyup', function(e){
// check the key code
const code = (e.keyCode ? e.keyCode : e.which);
if(code == 9 && els.length){
checkFocus();
}
});
function checkFocus(){
// by checking the tagName we only have to do 2 loops no matter how many links or inputs there are on a page, which is far more efficient. The downside is it will check **every** link and input on the page. You would access the element with document.activeElelemnt instead if you need to know which item was focused.
for (const el of els) {
if(document.activeElement.tagName == el){
console.log("focused tag:" + document.activeElement.tagName);
}
}
}
<button>Click me for focus, I am not checked</button>
<a href="#">Focused Link</a>
<label for="input1">I am also reported</label>
<input id="input1">
<button>Another button not announced</button>