js: Move focus-tracking to entirely "focus" events

When we disable a button, it loses focus but doesn't generate a "blur"
event.  This means our "focus-within" class goes wrong.  Instead of
relying on "blur" events to remove the class, remove it from any
inappropriate elements in the "focus" handler.  This requires attaching
the handler to the root element of the document, but I've got plans that
need that anyway.
This commit is contained in:
Ben Harris
2022-11-19 16:30:28 +00:00
parent 8445f07827
commit 2d439dd00e

View File

@ -525,23 +525,20 @@ function initPuzzle() {
command(4); command(4);
}); });
// Event handlers to fake :focus-within on browsers too old for // Event handler to fake :focus-within on browsers too old for
// it (like KaiOS 2.5). Browsers without :focus-within are also // it (like KaiOS 2.5). Browsers without :focus-within are also
// too old for focusin/out events, so we have to use focus and // too old for focusin/out events, so we have to use focus events
// which don't bubble but can be captured. // which don't bubble but can be captured.
menuform.addEventListener("focus", function(event) { //
var elem = event.target; // A button losing focus because it was disabled doesn't generate
while (elem && elem !== menuform) { // a blur event, so we do this entirely in the focus handler.
document.documentElement.addEventListener("focus", function(event) {
for (var elem = event.target; elem; elem = elem.parentElement)
elem.classList.add("focus-within"); elem.classList.add("focus-within");
elem = elem.parentElement; for (elem of
} Array.from(document.getElementsByClassName("focus-within")))
}, true); if (!elem.contains(event.target))
menuform.addEventListener("blur", function(event) { elem.classList.remove("focus-within");
var elem = event.target;
while (elem && !elem.contains(event.relatedTarget)) {
elem.classList.remove("focus-within");
elem = elem.parentElement;
}
}, true); }, true);
// Set up the function pointers we haven't already grabbed. // Set up the function pointers we haven't already grabbed.