A current work-around I’m using is running this script in one of my nui frames:
var baseBody = window.frameElement.parentElement;
var _iframes = baseBody.getElementsByTagName('iframe')
for (var i = 0; i < _iframes.length; i += 1) {
_iframes[i].setAttribute("tabindex", -1)
}
Also, while testing that, I realized why my work-around wasn’t working. It’s because the nui frame was loading and instantly applying tabindex to all sibling iframes, even though some may have not loaded yet.
setTimeout(() => {
var baseBody = window.frameElement.parentElement;
var _iframes = baseBody.getElementsByTagName('iframe')
for (var i = 0; i < _iframes.length; i += 1) {
_iframes[i].setAttribute("tabindex", -1)
}
}, 10000);
This work-around does indeed work, although an iframe can still be escaped, it is no longer possible to enter a different one. Simply clicking the resource will regain focus.
I believe adding tabIndex = -1 to the base root.html will give us the desired resolution.
Alright, so you are right. It’s the root.html file inside the ui.zip which can be edited.
Adding frame.tabIndex = -1; in the createFrame function will stop the cross-resource tabbing.
Unfortunately, as you say, the iframe still being escapable could lead to other problems, and we won’t be able to use an onBlur:focus chain because the native library is using blur to toggle a resource active or not.
Focus traps are a big talking point with all the a11y progress made with browsers of recent, but in this case it would seem ideal to create one. Libraries like this: https://github.com/davidtheclark/focus-trap exist to enable focus traps, which would solve our particular issue here.
This is of course very primitive but it’s a small proof of concept to at least keep the active iframe as the focus target.
The above event will only fire when the iframe focus has been escaped.
I also tried attaching an onfocus listener to the body tag but it isn’t fired via tab focus for some reason. May investigate further on that because that would be the most ideal solution.