diff --git a/core/misc/drupal.js b/core/misc/drupal.js index 627e264a7843..d7a4e4033ae6 100644 --- a/core/misc/drupal.js +++ b/core/misc/drupal.js @@ -258,6 +258,69 @@ Drupal.t = function (str, args, options) { return str; }; +/** + * Adds an HTML element and method to trigger audio UAs to read system messages. + */ +(function (document, Drupal) { + + var liveElement; + + /** + * Builds a div element with the aria-live attribute and attaches it + * to the DOM. + */ + Drupal.behaviors.drupalAnnounce = { + attach: function (settings, context) { + liveElement = document.createElement('div'); + liveElement.id = 'drupal-live-announce'; + liveElement.className = 'element-invisible'; + liveElement.setAttribute('aria-live', 'polite'); + liveElement.setAttribute('aria-busy', 'false'); + document.body.appendChild(liveElement); + } + }; + + /** + * Triggers audio UAs to read the supplied text. + * + * @param {String} text + * - A string to be read by the UA. + * + * @param {String} priority + * - A string to indicate the priority of the message. Can be either + * 'polite' or 'assertive'. Polite is the default. + * + * Use Drupal.announce to indicate to screen reader users that an element on + * the page has changed state. For instance, if clicking a link loads 10 more + * items into a list, one might announce the change like this. + * $('#search-list') + * .on('itemInsert', function (event, data) { + * // Insert the new items. + * $(data.container.el).append(data.items.el); + * // Announce the change to the page contents. + * Drupal.announce(Drupal.t('@count items added to @container', + * {'@count': data.items.length, '@container': data.container.title} + * )); + * }); + * + * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops + */ + Drupal.announce = function (text, priority) { + if (typeof text === 'string') { + // Clear the liveElement so that repeated strings will be read. + liveElement.innerHTML = ''; + // Set the busy state to true until the node changes are complete. + liveElement.setAttribute('aria-busy', 'true'); + // Set the priority to assertive, or default to polite. + liveElement.setAttribute('aria-live', (priority === 'assertive') ? 'assertive' : 'polite'); + // Print the text to the live region. + liveElement.innerHTML = Drupal.checkPlain(text); + // The live text area is updated. Allow the AT to announce the text. + liveElement.setAttribute('aria-busy', 'false'); + } + }; +}(document, Drupal)); + /** * Returns the URL to a Drupal page. */ diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocalePluralFormatTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocalePluralFormatTest.php index 8119199d7ecd..a5ed01ba28cc 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocalePluralFormatTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocalePluralFormatTest.php @@ -186,8 +186,9 @@ class LocalePluralFormatTest extends WebTestBase { $this->assertText('@count sati'); // Edit langcode hr translations and see if that took effect. + $lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND context = ''", array(':source' => "1 hour" . LOCALE_PLURAL_DELIMITER . "@count hours"))->fetchField(); $edit = array( - 'strings[10][translations][1]' => '@count sata edited', + "strings[$lid][translations][1]" => '@count sata edited', ); $this->drupalPost($path, $edit, t('Save translations')); @@ -202,7 +203,7 @@ class LocalePluralFormatTest extends WebTestBase { // Edit langcode fr translations and see if that took effect. $edit = array( - 'strings[10][translations][0]' => '@count heure edited', + "strings[$lid][translations][0]" => '@count heure edited', ); $this->drupalPost($path, $edit, t('Save translations'));