Path: blob/trunk/third_party/closure/goog/a11y/aria/announcer.js
2884 views
// Copyright 2007 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.131415/**16* @fileoverview Announcer that allows messages to be spoken by assistive17* technologies.18*/1920goog.provide('goog.a11y.aria.Announcer');2122goog.require('goog.Disposable');23goog.require('goog.Timer');24goog.require('goog.a11y.aria');25goog.require('goog.a11y.aria.LivePriority');26goog.require('goog.a11y.aria.State');27goog.require('goog.dom');28goog.require('goog.dom.TagName');29goog.require('goog.object');30313233/**34* Class that allows messages to be spoken by assistive technologies that the35* user may have active.36*37* @param {goog.dom.DomHelper=} opt_domHelper DOM helper.38* @constructor39* @extends {goog.Disposable}40* @final41*/42goog.a11y.aria.Announcer = function(opt_domHelper) {43goog.a11y.aria.Announcer.base(this, 'constructor');4445/**46* @type {goog.dom.DomHelper}47* @private48*/49this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();5051/**52* Map of priority to live region elements to use for communicating updates.53* Elements are created on demand.54* @type {Object<goog.a11y.aria.LivePriority, !Element>}55* @private56*/57this.liveRegions_ = {};58};59goog.inherits(goog.a11y.aria.Announcer, goog.Disposable);606162/** @override */63goog.a11y.aria.Announcer.prototype.disposeInternal = function() {64goog.object.forEach(65this.liveRegions_, this.domHelper_.removeNode, this.domHelper_);66this.liveRegions_ = null;67this.domHelper_ = null;68goog.a11y.aria.Announcer.base(this, 'disposeInternal');69};707172/**73* Announce a message to be read by any assistive technologies the user may74* have active.75* @param {string} message The message to announce to screen readers.76* @param {goog.a11y.aria.LivePriority=} opt_priority The priority of the77* message. Defaults to POLITE.78*/79goog.a11y.aria.Announcer.prototype.say = function(message, opt_priority) {80var priority = opt_priority || goog.a11y.aria.LivePriority.POLITE;81var liveRegion = this.getLiveRegion_(priority);82// Resets text content to force a DOM mutation (so that the setTextContent83// post-timeout function will be noticed by the screen reader). This is to84// avoid the problem of when the same message is "said" twice, which doesn't85// trigger a DOM mutation.86goog.dom.setTextContent(liveRegion, '');87// Uses non-zero timer to make VoiceOver and NVDA work88goog.Timer.callOnce(function() {89goog.dom.setTextContent(liveRegion, message);90}, 1);91};929394/**95* Returns an aria-live region that can be used to communicate announcements.96* @param {!goog.a11y.aria.LivePriority} priority The required priority.97* @return {!Element} A live region of the requested priority.98* @private99*/100goog.a11y.aria.Announcer.prototype.getLiveRegion_ = function(priority) {101var liveRegion = this.liveRegions_[priority];102if (liveRegion) {103// Make sure the live region is not aria-hidden.104goog.a11y.aria.removeState(liveRegion, goog.a11y.aria.State.HIDDEN);105return liveRegion;106}107108liveRegion = this.domHelper_.createElement(goog.dom.TagName.DIV);109// Note that IE has a habit of declaring things that aren't display:none as110// invisible to third-party tools like JAWs, so we can't just use height:0.111liveRegion.style.position = 'absolute';112liveRegion.style.top = '-1000px';113liveRegion.style.height = '1px';114liveRegion.style.overflow = 'hidden';115goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.LIVE, priority);116goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.ATOMIC, 'true');117this.domHelper_.getDocument().body.appendChild(liveRegion);118this.liveRegions_[priority] = liveRegion;119return liveRegion;120};121122123