define('jira/util/assistive', ['jira/util/navigator'], function (Navigator) { 'use strict'; /** * When things become visible it takes a while for the browsers to expose * that information to the screen readers (or for the screen readers to recognise it). * The duration below is the shortest timeout that worked with AWS + NVDA + VoiceOver. */ var ASSISTIVE_TIMEOUT = 50; /** * This is a workaround to fix JRA-45778 as suggested here: * http://connect.microsoft.com/IE/feedbackdetail/view/851144/assigning-textcontent-crashes-the-browser-tab * Basically for IE we are using the "innerText" property instead of "textContent" to set text on the element. */ var textProperty = Navigator.isIE() ? "innerText" : "textContent"; /** * Special hidden div. Its contents will be read by a screen reader. */ var assistiveEl = void 0; var assistiveId = 0; /** * When things become visible it takes a while for the browsers to expose * that information to the screen readers (or for the screen readers to recognise it). * Using this function will make sure it happens at the right time. * * @param callback to be executed after the timeout */ function wait(callback) { setTimeout(callback, ASSISTIVE_TIMEOUT); } /** * Sometimes it is needed to read some assistive text to the user through screen reader * even though it doesn't make much sense to give focus to the element that contains it. * E.g. "no results" message on a combobox. * * @param toRead text to be read by the screen reader */ function readText(toRead) { if (!assistiveEl) { assistiveEl = document.createElement("div"); assistiveEl.setAttribute("id", "assistive-text"); assistiveEl.setAttribute("class", "visually-hidden"); assistiveEl.setAttribute("aria-hidden", "false"); assistiveEl.setAttribute("role", "status"); assistiveEl.setAttribute("aria-live", "assertive"); assistiveEl.setAttribute("aria-relevant", "additions"); document.body.appendChild(assistiveEl); } // This needs to be an empty space because Chrome has/d an issue where it would only announce content to screen readers // when it changes from something, to something else. It doesn't announce if going from null to something. assistiveEl[textProperty] = " "; wait(function () { assistiveEl[textProperty] = toRead; }); } /** * Creates an element that can later be used as "aria-describedby" on other * element to provide extra description for people with disabilities. * * If only text is passed, new element with random id will be created. * If id is passed, depending on the need, new element will be created * or the existing one will get updated with the new text. * * @param text the label should contain * @param id optional id of the element * * @returns id of the existing or created element */ function createOrUpdateLabel(text, id) { if (!id) { id = 'label-' + assistiveId; assistiveId += 1; } var element = document.getElementById(id); if (!element) { element = document.createElement("div"); element.setAttribute("id", id); element.setAttribute("class", "visually-hidden"); element.setAttribute("aria-hidden", "false"); document.body.appendChild(element); } element[textProperty] = text; return id; } return { wait: wait, readText: readText, createOrUpdateLabel: createOrUpdateLabel }; });