Bug 1608554: Initialize toolbartabstops in dynamically added widgets. r=Gijs

When ToolbarKeyboardNavigator initializes, it sets aria-hidden and adds a focus listener on toolbartabstop elements.
This is necessary for proper functionality of toolbar keyboard navigation.
However, widgets can be dynamically added by CustomizableUI after ToolbarKeyboardNavigator initializes.
The search bar is one such widget and it does contain toolbartabstop elements.
We now watch for this and initialize any toolbartabstop elements inside added widgets.

Differential Revision: https://phabricator.services.mozilla.com/D62178

--HG--
extra : moz-landing-system : lando
This commit is contained in:
James Teh 2020-02-10 10:18:17 +00:00
Родитель 89d18db033
Коммит a534503c00
2 изменённых файлов: 38 добавлений и 7 удалений

Просмотреть файл

@ -86,6 +86,16 @@ ToolbarKeyboardNavigator = {
return aRoot._toolbarKeyNavWalker; return aRoot._toolbarKeyNavWalker;
}, },
_initTabStops(aRoot) {
for (let stop of aRoot.getElementsByTagName("toolbartabstop")) {
// These are invisible, but because they need to be in the tab order,
// they can't get display: none or similar. They must therefore be
// explicitly hidden for accessibility.
stop.setAttribute("aria-hidden", "true");
stop.addEventListener("focus", this);
}
},
init() { init() {
for (let id of this.kToolbars) { for (let id of this.kToolbars) {
let toolbar = document.getElementById(id); let toolbar = document.getElementById(id);
@ -93,16 +103,11 @@ ToolbarKeyboardNavigator = {
// We manage toolbar focus completely. This attribute ensures that CSS // We manage toolbar focus completely. This attribute ensures that CSS
// doesn't set -moz-user-focus: normal. // doesn't set -moz-user-focus: normal.
toolbar.setAttribute("keyNav", "true"); toolbar.setAttribute("keyNav", "true");
for (let stop of toolbar.getElementsByTagName("toolbartabstop")) { this._initTabStops(toolbar);
// These are invisible, but because they need to be in the tab order,
// they can't get display: none or similar. They must therefore be
// explicitly hidden for accessibility.
stop.setAttribute("aria-hidden", "true");
stop.addEventListener("focus", this);
}
toolbar.addEventListener("keydown", this); toolbar.addEventListener("keydown", this);
toolbar.addEventListener("keypress", this); toolbar.addEventListener("keypress", this);
} }
CustomizableUI.addListener(this);
}, },
uninit() { uninit() {
@ -115,6 +120,19 @@ ToolbarKeyboardNavigator = {
toolbar.removeEventListener("keypress", this); toolbar.removeEventListener("keypress", this);
toolbar.removeAttribute("keyNav"); toolbar.removeAttribute("keyNav");
} }
CustomizableUI.removeListener(this);
},
// CustomizableUI event handler
onWidgetAdded(aWidgetId, aArea, aPosition) {
if (!this.kToolbars.includes(aArea)) {
return;
}
let widget = document.getElementById(aWidgetId);
if (!widget) {
return;
}
this._initTabStops(widget);
}, },
_focusButton(aButton) { _focusButton(aButton) {

Просмотреть файл

@ -452,3 +452,16 @@ add_task(async function testCharacterInPanelMultiView() {
view.closest("panel").hidePopup(); view.closest("panel").hidePopup();
await hidden; await hidden;
}); });
// Test tab stops after the search bar is added.
add_task(async function testTabStopsAfterSearchBarAdded() {
await SpecialPowers.pushPrefEnv({
set: [["browser.search.widget.inNavBar", 1]],
});
await withNewBlankTab(async function() {
startFromUrlBar();
await expectFocusAfterKey("Tab", "searchbar", true);
await expectFocusAfterKey("Tab", "library-button");
});
await SpecialPowers.popPrefEnv();
});