There is a fixed div with some links that are shown when user clicks a button. For accessibility purposes, I want to close this div when it loses keyboard focus, but I can`t find the correct DOM event to handle.
I've tried blur
and focusout
events but they are also triggered even when children elements still has focus.
Example:
function openMenu() {
var menu = document.getElementById("menu");
menu.setAttribute("open", "");
menu.addEventListener("focusout", handleMenuFocusOut);
menu.focus();
}
function closeMenu() {
var menu = document.getElementById("menu");
menu.removeAttribute("open");
}
function handleMenuFocusOut() {
console.log("Event triggered!");
menu.removeEventListener("focusout", handleMenuFocusOut);
closeMenu();
}
#menu {
display: none;
position: fixed;
top: 50px;
padding: 20px;
background-color: gray;
}
#menu[open] {
display: block;
}
#menu:focus, a:focus {
background-color: cyan;
}
<div>
<button onclick="openMenu()">Click Me</button>
<div id="menu" tabindex="0">
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</div>
<input type="text"/>
</div>
To reproduce the case, click the button and press tab to navigate between links. The expected behavior is to close div only when focusing outside elements, like the textbox.
CodePudding user response:
Ok, I've completely changed this answer.
You can do this using pure CSS using focus-within
and ~
(which is used to show the menu when the open-button is focused.
Take a look at this snippet which uses no JS:
#menu {
display: block;
position: fixed;
top: 50px;
padding: 20px;
background-color: cyan;
opacity: 0;
pointer-events: none;
}
*:focus { outline: 3px solid #ff0; }
#menu:focus-within, #open-btn:focus ~ #menu {opacity: 1; pointer-events: all;}
<div>
<button id="open-btn">Click Me</button>
<div id="menu" tabindex="0">
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</div>
<input type="text" />
</div>