Bug 1585907 part 2: Allow A11yUtils.announce to take a Fluent id. r=Gijs

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
James Teh 2019-10-14 10:31:26 +00:00
Родитель eb04b6c810
Коммит af76f6473c
2 изменённых файлов: 69 добавлений и 11 удалений

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

@ -12,7 +12,7 @@ loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
async function runTests() {
const alert = document.getElementById("a11y-announcement");
let alerted = waitForEvent(EVENT_ALERT, alert);
A11yUtils.announce("first");
A11yUtils.announce({ raw: "first" });
let event = await alerted;
const alertAcc = event.accessible;
is(alertAcc.role, ROLE_ALERT);
@ -21,11 +21,37 @@ async function runTests() {
is(alertAcc.firstChild.name, "first");
alerted = waitForEvent(EVENT_ALERT, alertAcc);
A11yUtils.announce("second");
A11yUtils.announce({ raw: "second" });
event = await alerted;
ok(!alertAcc.name);
is(alertAcc.childCount, 1);
is(alertAcc.firstChild.name, "second");
info("Testing Fluent message");
// We need a simple Fluent message here without arguments or attributes.
const fluentId = "search-one-offs-with-title";
const fluentMessage = await document.l10n.formatValue(fluentId);
alerted = waitForEvent(EVENT_ALERT, alertAcc);
A11yUtils.announce({ id: fluentId });
event = await alerted;
ok(!alertAcc.name);
is(alertAcc.childCount, 1);
is(alertAcc.firstChild.name, fluentMessage);
info("Ensuring Fluent message is cancelled if announce is re-entered");
alerted = waitForEvent(EVENT_ALERT, alertAcc);
// This call runs async.
let asyncAnnounce = A11yUtils.announce({ id: fluentId });
// Before the async call finishes, call announce again.
A11yUtils.announce({ raw: "third" });
// Wait for the async call to complete.
await asyncAnnounce;
event = await alerted;
ok(!alertAcc.name);
is(alertAcc.childCount, 1);
// The async call should have been cancelled. If it wasn't, we would get
// fluentMessage here instead of "third".
is(alertAcc.firstChild.name, "third");
}
addAccessibleTask(``, runTests);

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

@ -21,15 +21,47 @@ var A11yUtils = {
* can thus hinder rather than help users if used incorrectly.
* Please only use this after consultation with the Mozilla accessibility
* team.
* @param aMessage The message to announce.
* @param aSource The element with which the announcement is associated.
* This should generally be something the user can interact with to
* respond to the announcement.
* For example, for an announcement indicating that Reader View is
* available, this should be the Reader View button on the toolbar.
* @param {string} [options.id] The Fluent id of the message to announce. The
* ftl file must already be included in browser.xhtml. This must be
* specified unless a raw message is specified instead.
* @param {object} [options.args] Arguments for the Fluent message.
* @param {string} [options.raw] The raw, already localized message to
* announce. You should generally prefer a Fluent id instead, but in
* rare cases, this might not be feasible.
* @param {Element} [options.source] The element with which the announcement
* is associated. This should generally be something the user can
* interact with to respond to the announcement. For example, for an
* announcement indicating that Reader View is available, this should
* be the Reader View button on the toolbar.
*/
announce(aMessage, aSource = document) {
// For now, we don't use aSource, but it might be useful in future.
async announce({ id = null, args = {}, raw = null, source = document } = {}) {
if ((!id && !raw) || (id && raw)) {
throw new Error("One of raw or id must be specified.");
}
// Cancel a previous pending call if any.
if (this._cancelAnnounce) {
this._cancelAnnounce();
this._cancelAnnounce = null;
}
let message;
if (id) {
let cancel = false;
this._cancelAnnounce = () => (cancel = true);
message = await document.l10n.formatValue(id, args);
if (cancel) {
// announce() was called again while we were waiting for translation.
return;
}
// No more async operations from this point.
this._cancelAnnounce = null;
} else {
// We run fully synchronously if a raw message is provided.
message = raw;
}
// For now, we don't use source, but it might be useful in future.
// For example, we might use it when we support announcement events on
// more platforms or it could be used to have a keyboard shortcut which
// focuses the last element to announce a message.
@ -42,7 +74,7 @@ var A11yUtils = {
live.firstChild.remove();
}
let label = document.createElement("label");
label.setAttribute("aria-label", aMessage);
label.setAttribute("aria-label", message);
live.appendChild(label);
},
};