diff -u b/core/lib/Drupal/Core/Render/Element/StatusMessages.php b/core/lib/Drupal/Core/Render/Element/StatusMessages.php --- b/core/lib/Drupal/Core/Render/Element/StatusMessages.php +++ b/core/lib/Drupal/Core/Render/Element/StatusMessages.php @@ -73,7 +73,6 @@ * @see drupal_get_messages() */ public static function renderMessages($type) { - $render = []; $messages = drupal_get_messages($type); // Render the messages. $render = [ reverted: --- b/core/misc/announce.js +++ a/core/misc/announce.js @@ -50,23 +50,21 @@ /** * Concatenates announcements to a single string; appends to the live region. */ + function announce() { - function processAnnounce() { var text = []; var priority = 'polite'; var announcement; + // Create an array of announcement strings to be joined and appended to the + // aria live region. + var il = announcements.length; + for (var i = 0; i < il; i++) { + announcement = announcements.pop(); + text.unshift(announcement.text); + // If any of the announcements has a priority of assertive then the group + // of joined announcements will have this priority. + if (announcement.priority === 'assertive') { + priority = 'assertive'; - if (announcements.length) { - // Create an array of announcement strings to be joined and appended to - // the aria live region. - var il = announcements.length; - for (var i = 0; i < il; i++) { - announcement = announcements.pop(); - text.unshift(announcement.text); - // If any of the announcements has a priority of assertive then the - // group of joined announcements will have this priority. - if (announcement.priority === 'assertive') { - priority = 'assertive'; - } } } @@ -83,13 +81,8 @@ // The live text area is updated. Allow the AT to announce the text. liveElement.setAttribute('aria-busy', 'false'); } - } - // 200 ms is right at the cusp where humans notice a pause, so we will wait - // at most this much time before the set of queued announcements is read. - var debouncedProcessAnnounce = debounce(processAnnounce, 200); - /** * Triggers audio UAs to read the supplied text. * @@ -103,24 +96,25 @@ * * @param {string} text * A string to be read by the UA. + * @param {string} [priority='polite'] - * @param {string} priority * A string to indicate the priority of the message. Can be either * 'polite' or 'assertive'. * + * @return {function} + * The return of the call to debounce. + * * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops */ Drupal.announce = function (text, priority) { + // Save the text and priority into a closure variable. Multiple simultaneous + // announcements will be concatenated and read in sequence. + announcements.push({ + text: text, + priority: priority + }); + // Immediately invoke the function that debounce returns. 200 ms is right at + // the cusp where humans notice a pause, so we will wait + // at most this much time before the set of queued announcements is read. + return (debounce(announce, 200)()); - if (typeof text === 'string') { - // Save the text and priority into a closure variable. Multiple - // simultaneous announcements will be concatenated and read in sequence. - announcements.push({ - text: text, - priority: priority - }); - debouncedProcessAnnounce(announcements); - } - else { - throw new Error(Drupal.t('"text" passed Drupal.announce must be a string.')); - } }; }(Drupal, Drupal.debounce)); diff -u b/core/misc/message.js b/core/misc/message.js --- b/core/misc/message.js +++ b/core/misc/message.js @@ -62,8 +62,9 @@ options = options || {}; // Send message to screen reader. announce(message, type, options); - // Generate a unique key to allow message deletion. - options.index = Math.random().toFixed(15).replace('0.', ''); + // Use the provided index for the message or generate a unique key to + // allow message deletion. + options.index = options.index || Math.random().toFixed(15).replace('0.', ''); messageWrapper.innerHTML += Drupal.theme('message', {text: message, type: type}, options); return options.index; @@ -74,7 +75,7 @@ * * @name Drupal.message~messageDefinition.remove * - * @param {string|Array.} messages + * @param {string|Array.} index * Index of the message to remove, as returned by * {@link Drupal.message~messageDefinition.add}, or an * array of indexes. @@ -82,14 +83,14 @@ * @return {number} * Number of removed messages. */ - function messageRemove(messages) { + function messageRemove(index) { // If there is no argument or if the argument is an empty array, // no message can be removed. - if (!messages || (Array.isArray(messages) && messages.length === 0)) { + if (!index || (Array.isArray(index) && index.length === 0)) { return 0; } - var removeSelectors = (Array.isArray(messages) ? messages : [messages]) + var removeSelectors = (Array.isArray(index) ? index : [index]) .map(function (messageIndex) { return '[data-drupal-message="' + messageIndex + '"]'; }); @@ -154,12 +155,15 @@ function announce(message, type, options) { // Check this. Might be too much. if (!options.priority && type !== 'status') { - options.priority = 'assertive'; + options.priority = 'polite'; } + // Always announce the priority of the upcomming message. + Drupal.announce(options.priority); + // If screen reader message is not disabled announce screen reader specific // text or fallback to the displayed message. if (options.announce !== '') { - Drupal.announce(options.announce || message, options.priority); + Drupal.announce(message, options.priority); } } diff -u b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php --- b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php +++ b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php @@ -24,7 +24,7 @@ '#title' => "Message area: $messagesSelector", '#attributes' => [ 'data-drupal-messages-area' => $messagesSelector, - ] + ], ]; foreach (JsMessageTestCases::getTypes() as $type) { $buttons[$messagesSelector]["add-$type"] = [ @@ -121,7 +121,7 @@ 'types' => JsMessageTestCases::getTypes(), ], ], - ] + ], ]; }