Bug 1909074. Don't pass OFFSET_BY_ORIGIN to GetResultingTransformMatrix when it's...
[gecko.git] / browser / base / content / browser-a11yUtils.js
blob935ddc6a554f17b6255c850108e5e5bdf3e8baa4
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // This file is loaded into the browser window scope.
6 /* eslint-env mozilla/browser-window */
8 /**
9  * Utility functions for UI accessibility.
10  */
12 var A11yUtils = {
13   /**
14    * Announce a message to the user.
15    * This should only be used when something happens that is important to the
16    * user and will be noticed visually, but is not related to the focused
17    * control and is not a pop-up such as a doorhanger.
18    * For example, this could be used to indicate that Reader View is available
19    * or that Firefox is making a recommendation via the toolbar.
20    * This must be used with caution, as it can create unwanted verbosity and
21    * can thus hinder rather than help users if used incorrectly.
22    * Please only use this after consultation with the Mozilla accessibility
23    * team.
24    * @param {object} [options]
25    * @param {string} [options.id] The Fluent id of the message to announce. The
26    *        ftl file must already be included in browser.xhtml. This must be
27    *        specified unless a raw message is specified instead.
28    * @param {object} [options.args] Arguments for the Fluent message.
29    * @param {string} [options.raw] The raw, already localized message to
30    *        announce. You should generally prefer a Fluent id instead, but in
31    *        rare cases, this might not be feasible.
32    */
33   async announce({ id = null, args = {}, raw = null } = {}) {
34     if ((!id && !raw) || (id && raw)) {
35       throw new Error("One of raw or id must be specified.");
36     }
38     // Cancel a previous pending call if any.
39     if (this._cancelAnnounce) {
40       this._cancelAnnounce();
41       this._cancelAnnounce = null;
42     }
44     let message;
45     if (id) {
46       let cancel = false;
47       this._cancelAnnounce = () => (cancel = true);
48       message = await document.l10n.formatValue(id, args);
49       if (cancel) {
50         // announce() was called again while we were waiting for translation.
51         return;
52       }
53       // No more async operations from this point.
54       this._cancelAnnounce = null;
55     } else {
56       // We run fully synchronously if a raw message is provided.
57       message = raw;
58     }
60     // For now, we don't use source, but it might be useful in future.
61     // For example, we might use it when we support announcement events on
62     // more platforms or it could be used to have a keyboard shortcut which
63     // focuses the last element to announce a message.
64     let live = document.getElementById("a11y-announcement");
65     // We use role="alert" because JAWS doesn't support aria-live in browser
66     // chrome.
67     // Gecko a11y needs an insertion to trigger an alert event. This is why
68     // we can't just use aria-label on the alert.
69     if (live.firstChild) {
70       live.firstChild.remove();
71     }
72     let label = document.createElement("label");
73     label.setAttribute("aria-label", message);
74     live.appendChild(label);
75   },