Mercurial > hg > cmmr2012-drupal-site
comparison core/misc/announce.es6.js @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | a9cd425dd02b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 /** | |
2 * @file | |
3 * Adds an HTML element and method to trigger audio UAs to read system messages. | |
4 * | |
5 * Use {@link Drupal.announce} to indicate to screen reader users that an | |
6 * element on the page has changed state. For instance, if clicking a link | |
7 * loads 10 more items into a list, one might announce the change like this. | |
8 * | |
9 * @example | |
10 * $('#search-list') | |
11 * .on('itemInsert', function (event, data) { | |
12 * // Insert the new items. | |
13 * $(data.container.el).append(data.items.el); | |
14 * // Announce the change to the page contents. | |
15 * Drupal.announce(Drupal.t('@count items added to @container', | |
16 * {'@count': data.items.length, '@container': data.container.title} | |
17 * )); | |
18 * }); | |
19 */ | |
20 | |
21 (function (Drupal, debounce) { | |
22 let liveElement; | |
23 const announcements = []; | |
24 | |
25 /** | |
26 * Builds a div element with the aria-live attribute and add it to the DOM. | |
27 * | |
28 * @type {Drupal~behavior} | |
29 * | |
30 * @prop {Drupal~behaviorAttach} attach | |
31 * Attaches the behavior for drupalAnnouce. | |
32 */ | |
33 Drupal.behaviors.drupalAnnounce = { | |
34 attach(context) { | |
35 // Create only one aria-live element. | |
36 if (!liveElement) { | |
37 liveElement = document.createElement('div'); | |
38 liveElement.id = 'drupal-live-announce'; | |
39 liveElement.className = 'visually-hidden'; | |
40 liveElement.setAttribute('aria-live', 'polite'); | |
41 liveElement.setAttribute('aria-busy', 'false'); | |
42 document.body.appendChild(liveElement); | |
43 } | |
44 }, | |
45 }; | |
46 | |
47 /** | |
48 * Concatenates announcements to a single string; appends to the live region. | |
49 */ | |
50 function announce() { | |
51 const text = []; | |
52 let priority = 'polite'; | |
53 let announcement; | |
54 | |
55 // Create an array of announcement strings to be joined and appended to the | |
56 // aria live region. | |
57 const il = announcements.length; | |
58 for (let i = 0; i < il; i++) { | |
59 announcement = announcements.pop(); | |
60 text.unshift(announcement.text); | |
61 // If any of the announcements has a priority of assertive then the group | |
62 // of joined announcements will have this priority. | |
63 if (announcement.priority === 'assertive') { | |
64 priority = 'assertive'; | |
65 } | |
66 } | |
67 | |
68 if (text.length) { | |
69 // Clear the liveElement so that repeated strings will be read. | |
70 liveElement.innerHTML = ''; | |
71 // Set the busy state to true until the node changes are complete. | |
72 liveElement.setAttribute('aria-busy', 'true'); | |
73 // Set the priority to assertive, or default to polite. | |
74 liveElement.setAttribute('aria-live', priority); | |
75 // Print the text to the live region. Text should be run through | |
76 // Drupal.t() before being passed to Drupal.announce(). | |
77 liveElement.innerHTML = text.join('\n'); | |
78 // The live text area is updated. Allow the AT to announce the text. | |
79 liveElement.setAttribute('aria-busy', 'false'); | |
80 } | |
81 } | |
82 | |
83 /** | |
84 * Triggers audio UAs to read the supplied text. | |
85 * | |
86 * The aria-live region will only read the text that currently populates its | |
87 * text node. Replacing text quickly in rapid calls to announce results in | |
88 * only the text from the most recent call to {@link Drupal.announce} being | |
89 * read. By wrapping the call to announce in a debounce function, we allow for | |
90 * time for multiple calls to {@link Drupal.announce} to queue up their | |
91 * messages. These messages are then joined and append to the aria-live region | |
92 * as one text node. | |
93 * | |
94 * @param {string} text | |
95 * A string to be read by the UA. | |
96 * @param {string} [priority='polite'] | |
97 * A string to indicate the priority of the message. Can be either | |
98 * 'polite' or 'assertive'. | |
99 * | |
100 * @return {function} | |
101 * The return of the call to debounce. | |
102 * | |
103 * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops | |
104 */ | |
105 Drupal.announce = function (text, priority) { | |
106 // Save the text and priority into a closure variable. Multiple simultaneous | |
107 // announcements will be concatenated and read in sequence. | |
108 announcements.push({ | |
109 text, | |
110 priority, | |
111 }); | |
112 // Immediately invoke the function that debounce returns. 200 ms is right at | |
113 // the cusp where humans notice a pause, so we will wait | |
114 // at most this much time before the set of queued announcements is read. | |
115 return (debounce(announce, 200)()); | |
116 }; | |
117 }(Drupal, Drupal.debounce)); |