summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js')
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js978
1 files changed, 0 insertions, 978 deletions
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
deleted file mode 100644
index 09b36bdf1a1..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
+++ /dev/null
@@ -1,978 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A collection of JavaScript utilities used to simplify working
- * with ARIA (http://www.w3.org/TR/wai-aria).
- */
-
-
-goog.provide('cvox.AriaUtil');
-goog.require('cvox.AbstractEarcons');
-goog.require('cvox.ChromeVox');
-goog.require('cvox.NodeState');
-goog.require('cvox.NodeStateUtil');
-
-
-/**
- * Create the namespace
- * @constructor
- */
-cvox.AriaUtil = function() {
-};
-
-
-/**
- * A mapping from ARIA role names to their message ids.
- * Note: If you are adding a new mapping, the new message identifier needs a
- * corresponding braille message. For example, a message id 'tag_button'
- * requires another message 'tag_button_brl' within messages.js.
- * @type {Object<string>}
- */
-cvox.AriaUtil.WIDGET_ROLE_TO_NAME = {
- 'alert' : 'role_alert',
- 'alertdialog' : 'role_alertdialog',
- 'button' : 'role_button',
- 'checkbox' : 'role_checkbox',
- 'columnheader' : 'role_columnheader',
- 'combobox' : 'role_combobox',
- 'dialog' : 'role_dialog',
- 'grid' : 'role_grid',
- 'gridcell' : 'role_gridcell',
- 'link' : 'role_link',
- 'listbox' : 'role_listbox',
- 'log' : 'role_log',
- 'marquee' : 'role_marquee',
- 'menu' : 'role_menu',
- 'menubar' : 'role_menubar',
- 'menuitem' : 'role_menuitem',
- 'menuitemcheckbox' : 'role_menuitemcheckbox',
- 'menuitemradio' : 'role_menuitemradio',
- 'option' : 'role_option',
- 'progressbar' : 'role_progressbar',
- 'radio' : 'role_radio',
- 'radiogroup' : 'role_radiogroup',
- 'rowheader' : 'role_rowheader',
- 'scrollbar' : 'role_scrollbar',
- 'slider' : 'role_slider',
- 'spinbutton' : 'role_spinbutton',
- 'status' : 'role_status',
- 'tab' : 'role_tab',
- 'tablist' : 'role_tablist',
- 'tabpanel' : 'role_tabpanel',
- 'textbox' : 'role_textbox',
- 'timer' : 'role_timer',
- 'toolbar' : 'role_toolbar',
- 'tooltip' : 'role_tooltip',
- 'treeitem' : 'role_treeitem'
-};
-
-
-/**
- * Note: If you are adding a new mapping, the new message identifier needs a
- * corresponding braille message. For example, a message id 'tag_button'
- * requires another message 'tag_button_brl' within messages.js.
- * @type {Object<string>}
- */
-cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME = {
- 'article' : 'role_article',
- 'application' : 'role_application',
- 'banner' : 'role_banner',
- 'columnheader' : 'role_columnheader',
- 'complementary' : 'role_complementary',
- 'contentinfo' : 'role_contentinfo',
- 'definition' : 'role_definition',
- 'directory' : 'role_directory',
- 'document' : 'role_document',
- 'form' : 'role_form',
- 'group' : 'role_group',
- 'heading' : 'role_heading',
- 'img' : 'role_img',
- 'list' : 'role_list',
- 'listitem' : 'role_listitem',
- 'main' : 'role_main',
- 'math' : 'role_math',
- 'navigation' : 'role_navigation',
- 'note' : 'role_note',
- 'region' : 'role_region',
- 'rowheader' : 'role_rowheader',
- 'search' : 'role_search',
- 'separator' : 'role_separator'
-};
-
-
-/**
- * @type {Array<Object>}
- */
-cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS = [
- { name: 'aria-autocomplete', values:
- {'inline' : 'aria_autocomplete_inline',
- 'list' : 'aria_autocomplete_list',
- 'both' : 'aria_autocomplete_both'} },
- { name: 'aria-checked', values:
- {'true' : 'aria_checked_true',
- 'false' : 'aria_checked_false',
- 'mixed' : 'aria_checked_mixed'} },
- { name: 'aria-disabled', values:
- {'true' : 'aria_disabled_true'} },
- { name: 'aria-expanded', values:
- {'true' : 'aria_expanded_true',
- 'false' : 'aria_expanded_false'} },
- { name: 'aria-invalid', values:
- {'true' : 'aria_invalid_true',
- 'grammar' : 'aria_invalid_grammar',
- 'spelling' : 'aria_invalid_spelling'} },
- { name: 'aria-multiline', values:
- {'true' : 'aria_multiline_true'} },
- { name: 'aria-multiselectable', values:
- {'true' : 'aria_multiselectable_true'} },
- { name: 'aria-pressed', values:
- {'true' : 'aria_pressed_true',
- 'false' : 'aria_pressed_false',
- 'mixed' : 'aria_pressed_mixed'} },
- { name: 'aria-readonly', values:
- {'true' : 'aria_readonly_true'} },
- { name: 'aria-required', values:
- {'true' : 'aria_required_true'} },
- { name: 'aria-selected', values:
- {'true' : 'aria_selected_true',
- 'false' : 'aria_selected_false'} }
-];
-
-
-/**
- * Checks if a node should be treated as a hidden node because of its ARIA
- * markup.
- *
- * @param {Node} targetNode The node to check.
- * @return {boolean} True if the targetNode should be treated as hidden.
- */
-cvox.AriaUtil.isHiddenRecursive = function(targetNode) {
- if (cvox.AriaUtil.isHidden(targetNode)) {
- return true;
- }
- var parent = targetNode.parentElement;
- while (parent) {
- if ((parent.getAttribute('aria-hidden') == 'true') &&
- (parent.getAttribute('chromevoxignoreariahidden') != 'true')) {
- return true;
- }
- parent = parent.parentElement;
- }
- return false;
-};
-
-
-/**
- * Checks if a node should be treated as a hidden node because of its ARIA
- * markup. Does not check parents, so if you need to know if this is a
- * descendant of a hidden node, call isHiddenRecursive.
- *
- * @param {Node} targetNode The node to check.
- * @return {boolean} True if the targetNode should be treated as hidden.
- */
-cvox.AriaUtil.isHidden = function(targetNode) {
- if (!targetNode) {
- return true;
- }
- if (targetNode.getAttribute) {
- if ((targetNode.getAttribute('aria-hidden') == 'true') &&
- (targetNode.getAttribute('chromevoxignoreariahidden') != 'true')) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Checks if a node should be treated as a visible node because of its ARIA
- * markup, regardless of whatever other styling/attributes it may have.
- * It is possible to force a node to be visible by setting aria-hidden to
- * false.
- *
- * @param {Node} targetNode The node to check.
- * @return {boolean} True if the targetNode should be treated as visible.
- */
-cvox.AriaUtil.isForcedVisibleRecursive = function(targetNode) {
- var node = targetNode;
- while (node) {
- if (node.getAttribute) {
- // Stop and return the result based on the closest node that has
- // aria-hidden set.
- if (node.hasAttribute('aria-hidden') &&
- (node.getAttribute('chromevoxignoreariahidden') != 'true')) {
- return node.getAttribute('aria-hidden') == 'false';
- }
- }
- node = node.parentElement;
- }
- return false;
-};
-
-
-/**
- * Checks if a node should be treated as a leaf node because of its ARIA
- * markup. Does not check recursively, and does not check isControlWidget.
- * Note that elements with aria-label are treated as leaf elements. See:
- * http://www.w3.org/TR/wai-aria/roles#textalternativecomputation
- *
- * @param {Element} targetElement The node to check.
- * @return {boolean} True if the targetNode should be treated as a leaf node.
- */
-cvox.AriaUtil.isLeafElement = function(targetElement) {
- var role = targetElement.getAttribute('role');
- var hasArialLabel = targetElement.hasAttribute('aria-label') &&
- (targetElement.getAttribute('aria-label').length > 0);
- return (role == 'img' || role == 'progressbar' || hasArialLabel);
-};
-
-
-/**
- * Determines whether or not a node is or is the descendant of a node
- * with a particular role.
- *
- * @param {Node} node The node to be checked.
- * @param {string} roleName The role to check for.
- * @return {boolean} True if the node or one of its ancestor has the specified
- * role.
- */
-cvox.AriaUtil.isDescendantOfRole = function(node, roleName) {
- while (node) {
- if (roleName && node && (node.getAttribute('role') == roleName)) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
-};
-
-
-/**
- * Helper function to return the role name message identifier for a role.
- * @param {string} role The role.
- * @return {?string} The role name message identifier.
- * @private
- */
-cvox.AriaUtil.getRoleNameMsgForRole_ = function(role) {
- var msgId = cvox.AriaUtil.WIDGET_ROLE_TO_NAME[role];
- if (!msgId) {
- return null;
- }
- return msgId;
-};
-
-/**
- * Returns true is the node is any kind of button.
- *
- * @param {Node} node The node to check.
- * @return {boolean} True if the node is a button.
- */
-cvox.AriaUtil.isButton = function(node) {
- var role = cvox.AriaUtil.getRoleAttribute(node);
- if (role == 'button') {
- return true;
- }
- if (node.tagName == 'BUTTON') {
- return true;
- }
- if (node.tagName == 'INPUT') {
- return (node.type == 'submit' ||
- node.type == 'reset' ||
- node.type == 'button');
- }
- return false;
-};
-
-/**
- * Returns a role message identifier for a node.
- * For a localized string, see cvox.AriaUtil.getRoleName.
- * @param {Node} targetNode The node to get the role name for.
- * @return {string} The role name message identifier for the targetNode.
- */
-cvox.AriaUtil.getRoleNameMsg = function(targetNode) {
- var roleName;
- if (targetNode && targetNode.getAttribute) {
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
-
- // Special case for pop-up buttons.
- if (targetNode.getAttribute('aria-haspopup') == 'true' &&
- cvox.AriaUtil.isButton(targetNode)) {
- return 'role_popup_button';
- }
-
- if (role) {
- roleName = cvox.AriaUtil.getRoleNameMsgForRole_(role);
- if (!roleName) {
- roleName = cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME[role];
- }
- }
-
- // To a user, a menu item within a menu bar is called a "menu";
- // any other menu item is called a "menu item".
- //
- // TODO(deboer): This block feels like a hack. dmazzoni suggests
- // using css-like syntax for names. Investigate further if
- // we need more of these hacks.
- if (role == 'menuitem') {
- var container = targetNode.parentElement;
- while (container) {
- if (container.getAttribute &&
- (cvox.AriaUtil.getRoleAttribute(container) == 'menu' ||
- cvox.AriaUtil.getRoleAttribute(container) == 'menubar')) {
- break;
- }
- container = container.parentElement;
- }
- if (container && cvox.AriaUtil.getRoleAttribute(container) == 'menubar') {
- roleName = cvox.AriaUtil.getRoleNameMsgForRole_('menu');
- } // else roleName is already 'Menu item', no need to change it.
- }
- }
- if (!roleName) {
- roleName = '';
- }
- return roleName;
-};
-
-/**
- * Returns a string to be presented to the user that identifies what the
- * targetNode's role is.
- *
- * @param {Node} targetNode The node to get the role name for.
- * @return {string} The role name for the targetNode.
- */
-cvox.AriaUtil.getRoleName = function(targetNode) {
- var roleMsg = cvox.AriaUtil.getRoleNameMsg(targetNode);
- var roleName = Msgs.getMsg(roleMsg);
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- if ((role == 'heading') && (targetNode.hasAttribute('aria-level'))) {
- roleName += ' ' + targetNode.getAttribute('aria-level');
- }
- return roleName ? roleName : '';
-};
-
-/**
- * Returns a string that gives information about the state of the targetNode.
- *
- * @param {Node} targetNode The node to get the state information for.
- * @param {boolean} primary Whether this is the primary node we're
- * interested in, where we might want extra information - as
- * opposed to an ancestor, where we might be more brief.
- * @return {cvox.NodeState} The status information about the node.
- */
-cvox.AriaUtil.getStateMsgs = function(targetNode, primary) {
- var state = [];
- if (!targetNode || !targetNode.getAttribute) {
- return state;
- }
-
- for (var i = 0, attr; attr = cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS[i];
- i++) {
- var value = targetNode.getAttribute(attr.name);
- var msgId = attr.values[value];
- if (msgId) {
- state.push([msgId]);
- }
- }
- if (targetNode.getAttribute('role') == 'grid') {
- return cvox.AriaUtil.getGridState_(targetNode, targetNode);
- }
-
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- if (targetNode.getAttribute('aria-haspopup') == 'true') {
- if (role == 'menuitem') {
- state.push(['has_submenu']);
- } else if (cvox.AriaUtil.isButton(targetNode)) {
- // Do nothing - the role name will be 'pop-up button'.
- } else {
- state.push(['has_popup']);
- }
- }
-
- var valueText = targetNode.getAttribute('aria-valuetext');
- if (valueText) {
- // If there is a valueText, that always wins.
- state.push(['aria_value_text', valueText]);
- return state;
- }
-
- var valueNow = targetNode.getAttribute('aria-valuenow');
- var valueMin = targetNode.getAttribute('aria-valuemin');
- var valueMax = targetNode.getAttribute('aria-valuemax');
-
- // Scrollbar and progressbar should speak the percentage.
- // http://www.w3.org/TR/wai-aria/roles#scrollbar
- // http://www.w3.org/TR/wai-aria/roles#progressbar
- if ((valueNow != null) && (valueMin != null) && (valueMax != null)) {
- if ((role == 'scrollbar') || (role == 'progressbar')) {
- var percent = Math.round((valueNow / (valueMax - valueMin)) * 100);
- state.push(['state_percent', percent]);
- return state;
- }
- }
-
- // Return as many of the value attributes as possible.
- if (valueNow != null) {
- state.push(['aria_value_now', valueNow]);
- }
- if (valueMin != null) {
- state.push(['aria_value_min', valueMin]);
- }
- if (valueMax != null) {
- state.push(['aria_value_max', valueMax]);
- }
-
- // If this is a composite control or an item within a composite control,
- // get the index and count of the current descendant or active
- // descendant.
- var parentControl = targetNode;
- var currentDescendant = null;
-
- if (cvox.AriaUtil.isCompositeControl(parentControl) && primary) {
- currentDescendant = cvox.AriaUtil.getActiveDescendant(parentControl);
- } else {
- role = cvox.AriaUtil.getRoleAttribute(targetNode);
- if (role == 'option' ||
- role == 'menuitem' ||
- role == 'menuitemcheckbox' ||
- role == 'menuitemradio' ||
- role == 'radio' ||
- role == 'tab' ||
- role == 'treeitem') {
- currentDescendant = targetNode;
- parentControl = targetNode.parentElement;
- while (parentControl &&
- !cvox.AriaUtil.isCompositeControl(parentControl)) {
- parentControl = parentControl.parentElement;
- if (parentControl &&
- cvox.AriaUtil.getRoleAttribute(parentControl) == 'treeitem') {
- break;
- }
- }
- }
- }
-
- if (parentControl &&
- (cvox.AriaUtil.isCompositeControl(parentControl) ||
- cvox.AriaUtil.getRoleAttribute(parentControl) == 'treeitem') &&
- currentDescendant) {
- var parentRole = cvox.AriaUtil.getRoleAttribute(parentControl);
- var descendantRoleList;
- switch (parentRole) {
- case 'combobox':
- case 'listbox':
- descendantRoleList = ['option'];
- break;
- case 'menu':
- descendantRoleList = ['menuitem',
- 'menuitemcheckbox',
- 'menuitemradio'];
- break;
- case 'radiogroup':
- descendantRoleList = ['radio'];
- break;
- case 'tablist':
- descendantRoleList = ['tab'];
- break;
- case 'tree':
- case 'treegrid':
- case 'treeitem':
- descendantRoleList = ['treeitem'];
- break;
- }
-
- if (descendantRoleList) {
- var listLength;
- var currentIndex;
-
- var ariaLength =
- parseInt(currentDescendant.getAttribute('aria-setsize'), 10);
- if (!isNaN(ariaLength)) {
- listLength = ariaLength;
- }
- var ariaIndex =
- parseInt(currentDescendant.getAttribute('aria-posinset'), 10);
- if (!isNaN(ariaIndex)) {
- currentIndex = ariaIndex;
- }
-
- if (listLength == undefined || currentIndex == undefined) {
- var descendants = cvox.AriaUtil.getNextLevel(parentControl,
- descendantRoleList);
- if (listLength == undefined) {
- listLength = descendants.length;
- }
- if (currentIndex == undefined) {
- for (var j = 0; j < descendants.length; j++) {
- if (descendants[j] == currentDescendant) {
- currentIndex = j + 1;
- }
- }
- }
- }
- if (currentIndex && listLength) {
- state.push(['list_position', currentIndex, listLength]);
- }
- }
- }
- return state;
-};
-
-
-/**
- * Returns a string that gives information about the state of the grid node.
- *
- * @param {Node} targetNode The node to get the state information for.
- * @param {Node} parentControl The parent composite control.
- * @return {cvox.NodeState} The status information about the node.
- * @private
- */
-cvox.AriaUtil.getGridState_ = function(targetNode, parentControl) {
- var activeDescendant = cvox.AriaUtil.getActiveDescendant(parentControl);
-
- if (activeDescendant) {
- var descendantSelector = '*[role~="row"]';
- var rows = parentControl.querySelectorAll(descendantSelector);
- var currentIndex = null;
- for (var j = 0; j < rows.length; j++) {
- var gridcells = rows[j].querySelectorAll('*[role~="gridcell"]');
- for (var k = 0; k < gridcells.length; k++) {
- if (gridcells[k] == activeDescendant) {
- return /** @type {cvox.NodeState} */ (
- [['role_gridcell_pos', j + 1, k + 1]]);
- }
- }
- }
- }
- return [];
-};
-
-
-/**
- * Returns the id of a node's active descendant
- * @param {Node} targetNode The node.
- * @return {?string} The id of the active descendant.
- * @private
- */
-cvox.AriaUtil.getActiveDescendantId_ = function(targetNode) {
- if (!targetNode.getAttribute) {
- return null;
- }
-
- var activeId = targetNode.getAttribute('aria-activedescendant');
- if (!activeId) {
- return null;
- }
- return activeId;
-};
-
-
-/**
- * Returns the list of elements that are one aria-level below.
- *
- * @param {Node} parentControl The node whose descendants should be analyzed.
- * @param {Array<string>} role The role(s) of descendant we are looking for.
- * @return {Array<Node>} The array of matching nodes.
- */
-cvox.AriaUtil.getNextLevel = function(parentControl, role) {
- var result = [];
- var children = parentControl.childNodes;
- var length = children.length;
- for (var i = 0; i < children.length; i++) {
- if (cvox.AriaUtil.isHidden(children[i]) ||
- !cvox.DomUtil.isVisible(children[i])) {
- continue;
- }
- var nextLevel = cvox.AriaUtil.getNextLevelItems(children[i], role);
- if (nextLevel.length > 0) {
- result = result.concat(nextLevel);
- }
- }
- return result;
-};
-
-
-/**
- * Recursively finds the first node(s) that match the role.
- *
- * @param {Element} current The node to start looking at.
- * @param {Array<string>} role The role(s) to match.
- * @return {Array<Element>} The array of matching nodes.
- */
-cvox.AriaUtil.getNextLevelItems = function(current, role) {
- if (current.nodeType != 1) { // If reached a node that is not an element.
- return [];
- }
- if (role.indexOf(cvox.AriaUtil.getRoleAttribute(current)) != -1) {
- return [current];
- } else {
- var children = current.childNodes;
- var length = children.length;
- if (length == 0) {
- return [];
- } else {
- var resultArray = [];
- for (var i = 0; i < length; i++) {
- var result = cvox.AriaUtil.getNextLevelItems(children[i], role);
- if (result.length > 0) {
- resultArray = resultArray.concat(result);
- }
- }
- return resultArray;
- }
- }
-};
-
-
-/**
- * If the node is an object with an active descendant, returns the
- * descendant node.
- *
- * This function will fully resolve an active descendant chain. If a circular
- * chain is detected, it will return null.
- *
- * @param {Node} targetNode The node to get descendant information for.
- * @return {Node} The descendant node or null if no node exists.
- */
-cvox.AriaUtil.getActiveDescendant = function(targetNode) {
- var seenIds = {};
- var node = targetNode;
-
- while (node) {
- var activeId = cvox.AriaUtil.getActiveDescendantId_(node);
- if (!activeId) {
- break;
- }
- if (activeId in seenIds) {
- // A circlar activeDescendant is an error, so return null.
- return null;
- }
- seenIds[activeId] = true;
- node = document.getElementById(activeId);
- }
-
- if (node == targetNode) {
- return null;
- }
- return node;
-};
-
-
-/**
- * Given a node, returns true if it's an ARIA control widget. Control widgets
- * are treated as leaf nodes.
- *
- * @param {Node} targetNode The node to be checked.
- * @return {boolean} Whether the targetNode is an ARIA control widget.
- */
-cvox.AriaUtil.isControlWidget = function(targetNode) {
- if (targetNode && targetNode.getAttribute) {
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- switch (role) {
- case 'button':
- case 'checkbox':
- case 'combobox':
- case 'listbox':
- case 'menu':
- case 'menuitemcheckbox':
- case 'menuitemradio':
- case 'radio':
- case 'slider':
- case 'progressbar':
- case 'scrollbar':
- case 'spinbutton':
- case 'tab':
- case 'tablist':
- case 'textbox':
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Given a node, returns true if it's an ARIA composite control.
- *
- * @param {Node} targetNode The node to be checked.
- * @return {boolean} Whether the targetNode is an ARIA composite control.
- */
-cvox.AriaUtil.isCompositeControl = function(targetNode) {
- if (targetNode && targetNode.getAttribute) {
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- switch (role) {
- case 'combobox':
- case 'grid':
- case 'listbox':
- case 'menu':
- case 'menubar':
- case 'radiogroup':
- case 'tablist':
- case 'tree':
- case 'treegrid':
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Given a node, returns its 'aria-live' value if it's a live region, or
- * null otherwise.
- *
- * @param {Node} node The node to be checked.
- * @return {?string} The live region value, like 'polite' or
- * 'assertive', or null if 'off' or none.
- */
-cvox.AriaUtil.getAriaLive = function(node) {
- if (!node.hasAttribute)
- return null;
- var value = node.getAttribute('aria-live');
- if (value == 'off') {
- return null;
- } else if (value) {
- return value;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'alert':
- return 'assertive';
- case 'log':
- case 'status':
- return 'polite';
- default:
- return null;
- }
-};
-
-
-/**
- * Given a node, returns its 'aria-atomic' value.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} The aria-atomic live region value, either true or false.
- */
-cvox.AriaUtil.getAriaAtomic = function(node) {
- if (!node.hasAttribute)
- return false;
- var value = node.getAttribute('aria-atomic');
- if (value) {
- return (value === 'true');
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- if (role == 'alert') {
- return true;
- }
- return false;
-};
-
-
-/**
- * Given a node, returns its 'aria-busy' value.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} The aria-busy live region value, either true or false.
- */
-cvox.AriaUtil.getAriaBusy = function(node) {
- if (!node.hasAttribute)
- return false;
- var value = node.getAttribute('aria-busy');
- if (value) {
- return (value === 'true');
- }
- return false;
-};
-
-
-/**
- * Given a node, checks its aria-relevant attribute (with proper inheritance)
- * and determines whether the given change (additions, removals, text, all)
- * is relevant and should be announced.
- *
- * @param {Node} node The node to be checked.
- * @param {string} change The name of the change to check - one of
- * 'additions', 'removals', 'text', 'all'.
- * @return {boolean} True if that change is relevant to that node as part of
- * a live region.
- */
-cvox.AriaUtil.getAriaRelevant = function(node, change) {
- if (!node.hasAttribute)
- return false;
- var value;
- if (node.hasAttribute('aria-relevant')) {
- value = node.getAttribute('aria-relevant');
- } else {
- value = 'additions text';
- }
- if (value == 'all') {
- value = 'additions removals text';
- }
-
- var tokens = value.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '').split(' ');
-
- if (change == 'all') {
- return (tokens.indexOf('additions') >= 0 &&
- tokens.indexOf('text') >= 0 &&
- tokens.indexOf('removals') >= 0);
- } else {
- return (tokens.indexOf(change) >= 0);
- }
-};
-
-
-/**
- * Given a node, return all live regions that are either rooted at this
- * node or contain this node.
- *
- * @param {Node} node The node to be checked.
- * @return {Array<Element>} All live regions affected by this node changing.
- */
-cvox.AriaUtil.getLiveRegions = function(node) {
- var result = [];
- if (node.querySelectorAll) {
- var nodes = node.querySelectorAll(
- '[role="alert"], [role="log"], [role="marquee"], ' +
- '[role="status"], [role="timer"], [aria-live]');
- if (nodes) {
- for (var i = 0; i < nodes.length; i++) {
- result.push(nodes[i]);
- }
- }
- }
-
- while (node) {
- if (cvox.AriaUtil.getAriaLive(node)) {
- result.push(node);
- return result;
- }
- node = node.parentElement;
- }
-
- return result;
-};
-
-
-/**
- * Checks to see whether or not a node is an ARIA landmark.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} Whether or not the node is an ARIA landmark.
- */
-cvox.AriaUtil.isLandmark = function(node) {
- if (!node || !node.getAttribute) {
- return false;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'application':
- case 'banner':
- case 'complementary':
- case 'contentinfo':
- case 'form':
- case 'main':
- case 'navigation':
- case 'search':
- return true;
- }
- return false;
-};
-
-
-/**
- * Checks to see whether or not a node is an ARIA grid.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} Whether or not the node is an ARIA grid.
- */
-cvox.AriaUtil.isGrid = function(node) {
- if (!node || !node.getAttribute) {
- return false;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'grid':
- case 'treegrid':
- return true;
- }
- return false;
-};
-
-
-/**
- * Returns the id of an earcon to play along with the description for a node.
- *
- * @param {Node} node The node to get the earcon for.
- * @return {cvox.Earcon?} The earcon id, or null if none applies.
- */
-cvox.AriaUtil.getEarcon = function(node) {
- if (!node || !node.getAttribute) {
- return null;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'button':
- return cvox.Earcon.BUTTON;
- case 'checkbox':
- case 'radio':
- case 'menuitemcheckbox':
- case 'menuitemradio':
- var checked = node.getAttribute('aria-checked');
- if (checked == 'true') {
- return cvox.Earcon.CHECK_ON;
- } else {
- return cvox.Earcon.CHECK_OFF;
- }
- case 'combobox':
- case 'listbox':
- return cvox.Earcon.LISTBOX;
- case 'textbox':
- return cvox.Earcon.EDITABLE_TEXT;
- case 'listitem':
- return cvox.Earcon.LIST_ITEM;
- case 'link':
- return cvox.Earcon.LINK;
- }
-
- return null;
-};
-
-
-/**
- * Returns the role of the node.
- *
- * This is equivalent to targetNode.getAttribute('role')
- * except it also takes into account cases where ChromeVox
- * itself has changed the role (ie, adding role="application"
- * to BODY elements for better screen reader compatibility.
- *
- * @param {Node} targetNode The node to get the role for.
- * @return {string} role of the targetNode.
- */
-cvox.AriaUtil.getRoleAttribute = function(targetNode) {
- if (!targetNode.getAttribute) {
- return '';
- }
- var role = targetNode.getAttribute('role');
- if (targetNode.hasAttribute('chromevoxoriginalrole')) {
- role = targetNode.getAttribute('chromevoxoriginalrole');
- }
- return role;
-};
-
-
-/**
- * Checks to see whether or not a node is an ARIA math node.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} Whether or not the node is an ARIA math node.
- */
-cvox.AriaUtil.isMath = function(node) {
- if (!node || !node.getAttribute) {
- return false;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- return role == 'math';
-};