| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview A collection of JavaScript utilities used to simplify working | 6 * @fileoverview A collection of JavaScript utilities used to simplify working |
| 7 * with ARIA (http://www.w3.org/TR/wai-aria). | 7 * with ARIA (http://www.w3.org/TR/wai-aria). |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 * A constant indicating no role name. | 27 * A constant indicating no role name. |
| 28 * @type {string} | 28 * @type {string} |
| 29 */ | 29 */ |
| 30 cvox.AriaUtil.NO_ROLE_NAME = ' '; | 30 cvox.AriaUtil.NO_ROLE_NAME = ' '; |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * A mapping from ARIA role names to their message ids. | 33 * A mapping from ARIA role names to their message ids. |
| 34 * Note: If you are adding a new mapping, the new message identifier needs a | 34 * Note: If you are adding a new mapping, the new message identifier needs a |
| 35 * corresponding braille message. For example, a message id 'tag_button' | 35 * corresponding braille message. For example, a message id 'tag_button' |
| 36 * requires another message 'tag_button_brl' within messages.js. | 36 * requires another message 'tag_button_brl' within messages.js. |
| 37 * @type {Object.<string, string>} | 37 * @type {Object<string, string>} |
| 38 */ | 38 */ |
| 39 cvox.AriaUtil.WIDGET_ROLE_TO_NAME = { | 39 cvox.AriaUtil.WIDGET_ROLE_TO_NAME = { |
| 40 'alert' : 'aria_role_alert', | 40 'alert' : 'aria_role_alert', |
| 41 'alertdialog' : 'aria_role_alertdialog', | 41 'alertdialog' : 'aria_role_alertdialog', |
| 42 'button' : 'aria_role_button', | 42 'button' : 'aria_role_button', |
| 43 'checkbox' : 'aria_role_checkbox', | 43 'checkbox' : 'aria_role_checkbox', |
| 44 'columnheader' : 'aria_role_columnheader', | 44 'columnheader' : 'aria_role_columnheader', |
| 45 'combobox' : 'aria_role_combobox', | 45 'combobox' : 'aria_role_combobox', |
| 46 'dialog' : 'aria_role_dialog', | 46 'dialog' : 'aria_role_dialog', |
| 47 'grid' : 'aria_role_grid', | 47 'grid' : 'aria_role_grid', |
| (...skipping 24 matching lines...) Expand all Loading... |
| 72 'toolbar' : 'aria_role_toolbar', | 72 'toolbar' : 'aria_role_toolbar', |
| 73 'tooltip' : 'aria_role_tooltip', | 73 'tooltip' : 'aria_role_tooltip', |
| 74 'treeitem' : 'aria_role_treeitem' | 74 'treeitem' : 'aria_role_treeitem' |
| 75 }; | 75 }; |
| 76 | 76 |
| 77 | 77 |
| 78 /** | 78 /** |
| 79 * Note: If you are adding a new mapping, the new message identifier needs a | 79 * Note: If you are adding a new mapping, the new message identifier needs a |
| 80 * corresponding braille message. For example, a message id 'tag_button' | 80 * corresponding braille message. For example, a message id 'tag_button' |
| 81 * requires another message 'tag_button_brl' within messages.js. | 81 * requires another message 'tag_button_brl' within messages.js. |
| 82 * @type {Object.<string, string>} | 82 * @type {Object<string, string>} |
| 83 */ | 83 */ |
| 84 cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME = { | 84 cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME = { |
| 85 'article' : 'aria_role_article', | 85 'article' : 'aria_role_article', |
| 86 'application' : 'aria_role_application', | 86 'application' : 'aria_role_application', |
| 87 'banner' : 'aria_role_banner', | 87 'banner' : 'aria_role_banner', |
| 88 'columnheader' : 'aria_role_columnheader', | 88 'columnheader' : 'aria_role_columnheader', |
| 89 'complementary' : 'aria_role_complementary', | 89 'complementary' : 'aria_role_complementary', |
| 90 'contentinfo' : 'aria_role_contentinfo', | 90 'contentinfo' : 'aria_role_contentinfo', |
| 91 'definition' : 'aria_role_definition', | 91 'definition' : 'aria_role_definition', |
| 92 'directory' : 'aria_role_directory', | 92 'directory' : 'aria_role_directory', |
| 93 'document' : 'aria_role_document', | 93 'document' : 'aria_role_document', |
| 94 'form' : 'aria_role_form', | 94 'form' : 'aria_role_form', |
| 95 'group' : 'aria_role_group', | 95 'group' : 'aria_role_group', |
| 96 'heading' : 'aria_role_heading', | 96 'heading' : 'aria_role_heading', |
| 97 'img' : 'aria_role_img', | 97 'img' : 'aria_role_img', |
| 98 'list' : 'aria_role_list', | 98 'list' : 'aria_role_list', |
| 99 'listitem' : 'aria_role_listitem', | 99 'listitem' : 'aria_role_listitem', |
| 100 'main' : 'aria_role_main', | 100 'main' : 'aria_role_main', |
| 101 'math' : 'aria_role_math', | 101 'math' : 'aria_role_math', |
| 102 'navigation' : 'aria_role_navigation', | 102 'navigation' : 'aria_role_navigation', |
| 103 'note' : 'aria_role_note', | 103 'note' : 'aria_role_note', |
| 104 'region' : 'aria_role_region', | 104 'region' : 'aria_role_region', |
| 105 'rowheader' : 'aria_role_rowheader', | 105 'rowheader' : 'aria_role_rowheader', |
| 106 'search' : 'aria_role_search', | 106 'search' : 'aria_role_search', |
| 107 'separator' : 'aria_role_separator' | 107 'separator' : 'aria_role_separator' |
| 108 }; | 108 }; |
| 109 | 109 |
| 110 | 110 |
| 111 /** | 111 /** |
| 112 * @type {Array.<Object>} | 112 * @type {Array<Object>} |
| 113 */ | 113 */ |
| 114 cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS = [ | 114 cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS = [ |
| 115 { name: 'aria-autocomplete', values: | 115 { name: 'aria-autocomplete', values: |
| 116 {'inline' : 'aria_autocomplete_inline', | 116 {'inline' : 'aria_autocomplete_inline', |
| 117 'list' : 'aria_autocomplete_list', | 117 'list' : 'aria_autocomplete_list', |
| 118 'both' : 'aria_autocomplete_both'} }, | 118 'both' : 'aria_autocomplete_both'} }, |
| 119 { name: 'aria-checked', values: | 119 { name: 'aria-checked', values: |
| 120 {'true' : 'aria_checked_true', | 120 {'true' : 'aria_checked_true', |
| 121 'false' : 'aria_checked_false', | 121 'false' : 'aria_checked_false', |
| 122 'mixed' : 'aria_checked_mixed'} }, | 122 'mixed' : 'aria_checked_mixed'} }, |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 */ | 374 */ |
| 375 cvox.AriaUtil.getStateMsgs = function(targetNode, primary) { | 375 cvox.AriaUtil.getStateMsgs = function(targetNode, primary) { |
| 376 var state = []; | 376 var state = []; |
| 377 if (!targetNode || !targetNode.getAttribute) { | 377 if (!targetNode || !targetNode.getAttribute) { |
| 378 return state; | 378 return state; |
| 379 } | 379 } |
| 380 | 380 |
| 381 for (var i = 0, attr; attr = cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS[i]; | 381 for (var i = 0, attr; attr = cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS[i]; |
| 382 i++) { | 382 i++) { |
| 383 var value = targetNode.getAttribute(attr.name); | 383 var value = targetNode.getAttribute(attr.name); |
| 384 var msg_id = attr.values[value]; | 384 var msgId = attr.values[value]; |
| 385 if (msg_id) { | 385 if (msgId) { |
| 386 state.push([msg_id]); | 386 state.push([msgId]); |
| 387 } | 387 } |
| 388 } | 388 } |
| 389 if (targetNode.getAttribute('role') == 'grid') { | 389 if (targetNode.getAttribute('role') == 'grid') { |
| 390 return cvox.AriaUtil.getGridState_(targetNode, targetNode); | 390 return cvox.AriaUtil.getGridState_(targetNode, targetNode); |
| 391 } | 391 } |
| 392 | 392 |
| 393 var role = cvox.AriaUtil.getRoleAttribute(targetNode); | 393 var role = cvox.AriaUtil.getRoleAttribute(targetNode); |
| 394 if (targetNode.getAttribute('aria-haspopup') == 'true') { | 394 if (targetNode.getAttribute('aria-haspopup') == 'true') { |
| 395 if (role == 'menuitem') { | 395 if (role == 'menuitem') { |
| 396 state.push(['has_submenu']); | 396 state.push(['has_submenu']); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 return null; | 576 return null; |
| 577 } | 577 } |
| 578 return activeId; | 578 return activeId; |
| 579 }; | 579 }; |
| 580 | 580 |
| 581 | 581 |
| 582 /** | 582 /** |
| 583 * Returns the list of elements that are one aria-level below. | 583 * Returns the list of elements that are one aria-level below. |
| 584 * | 584 * |
| 585 * @param {Node} parentControl The node whose descendants should be analyzed. | 585 * @param {Node} parentControl The node whose descendants should be analyzed. |
| 586 * @param {Array.<string>} role The role(s) of descendant we are looking for. | 586 * @param {Array<string>} role The role(s) of descendant we are looking for. |
| 587 * @return {Array.<Node>} The array of matching nodes. | 587 * @return {Array<Node>} The array of matching nodes. |
| 588 */ | 588 */ |
| 589 cvox.AriaUtil.getNextLevel = function(parentControl, role) { | 589 cvox.AriaUtil.getNextLevel = function(parentControl, role) { |
| 590 var result = []; | 590 var result = []; |
| 591 var children = parentControl.childNodes; | 591 var children = parentControl.childNodes; |
| 592 var length = children.length; | 592 var length = children.length; |
| 593 for (var i = 0; i < children.length; i++) { | 593 for (var i = 0; i < children.length; i++) { |
| 594 if (cvox.AriaUtil.isHidden(children[i]) || | 594 if (cvox.AriaUtil.isHidden(children[i]) || |
| 595 !cvox.DomUtil.isVisible(children[i])) { | 595 !cvox.DomUtil.isVisible(children[i])) { |
| 596 continue; | 596 continue; |
| 597 } | 597 } |
| 598 var nextLevel = cvox.AriaUtil.getNextLevelItems(children[i], role); | 598 var nextLevel = cvox.AriaUtil.getNextLevelItems(children[i], role); |
| 599 if (nextLevel.length > 0) { | 599 if (nextLevel.length > 0) { |
| 600 result = result.concat(nextLevel); | 600 result = result.concat(nextLevel); |
| 601 } | 601 } |
| 602 } | 602 } |
| 603 return result; | 603 return result; |
| 604 }; | 604 }; |
| 605 | 605 |
| 606 | 606 |
| 607 /** | 607 /** |
| 608 * Recursively finds the first node(s) that match the role. | 608 * Recursively finds the first node(s) that match the role. |
| 609 * | 609 * |
| 610 * @param {Element} current The node to start looking at. | 610 * @param {Element} current The node to start looking at. |
| 611 * @param {Array.<string>} role The role(s) to match. | 611 * @param {Array<string>} role The role(s) to match. |
| 612 * @return {Array.<Element>} The array of matching nodes. | 612 * @return {Array<Element>} The array of matching nodes. |
| 613 */ | 613 */ |
| 614 cvox.AriaUtil.getNextLevelItems = function(current, role) { | 614 cvox.AriaUtil.getNextLevelItems = function(current, role) { |
| 615 if (current.nodeType != 1) { // If reached a node that is not an element. | 615 if (current.nodeType != 1) { // If reached a node that is not an element. |
| 616 return []; | 616 return []; |
| 617 } | 617 } |
| 618 if (role.indexOf(cvox.AriaUtil.getRoleAttribute(current)) != -1) { | 618 if (role.indexOf(cvox.AriaUtil.getRoleAttribute(current)) != -1) { |
| 619 return [current]; | 619 return [current]; |
| 620 } else { | 620 } else { |
| 621 var children = current.childNodes; | 621 var children = current.childNodes; |
| 622 var length = children.length; | 622 var length = children.length; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 return (tokens.indexOf(change) >= 0); | 831 return (tokens.indexOf(change) >= 0); |
| 832 } | 832 } |
| 833 }; | 833 }; |
| 834 | 834 |
| 835 | 835 |
| 836 /** | 836 /** |
| 837 * Given a node, return all live regions that are either rooted at this | 837 * Given a node, return all live regions that are either rooted at this |
| 838 * node or contain this node. | 838 * node or contain this node. |
| 839 * | 839 * |
| 840 * @param {Node} node The node to be checked. | 840 * @param {Node} node The node to be checked. |
| 841 * @return {Array.<Element>} All live regions affected by this node changing. | 841 * @return {Array<Element>} All live regions affected by this node changing. |
| 842 */ | 842 */ |
| 843 cvox.AriaUtil.getLiveRegions = function(node) { | 843 cvox.AriaUtil.getLiveRegions = function(node) { |
| 844 var result = []; | 844 var result = []; |
| 845 if (node.querySelectorAll) { | 845 if (node.querySelectorAll) { |
| 846 var nodes = node.querySelectorAll( | 846 var nodes = node.querySelectorAll( |
| 847 '[role="alert"], [role="log"], [role="marquee"], ' + | 847 '[role="alert"], [role="log"], [role="marquee"], ' + |
| 848 '[role="status"], [role="timer"], [aria-live]'); | 848 '[role="status"], [role="timer"], [aria-live]'); |
| 849 if (nodes) { | 849 if (nodes) { |
| 850 for (var i = 0; i < nodes.length; i++) { | 850 for (var i = 0; i < nodes.length; i++) { |
| 851 result.push(nodes[i]); | 851 result.push(nodes[i]); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 * @param {Node} node The node to be checked. | 979 * @param {Node} node The node to be checked. |
| 980 * @return {boolean} Whether or not the node is an ARIA math node. | 980 * @return {boolean} Whether or not the node is an ARIA math node. |
| 981 */ | 981 */ |
| 982 cvox.AriaUtil.isMath = function(node) { | 982 cvox.AriaUtil.isMath = function(node) { |
| 983 if (!node || !node.getAttribute) { | 983 if (!node || !node.getAttribute) { |
| 984 return false; | 984 return false; |
| 985 } | 985 } |
| 986 var role = cvox.AriaUtil.getRoleAttribute(node); | 986 var role = cvox.AriaUtil.getRoleAttribute(node); |
| 987 return role == 'math'; | 987 return role == 'math'; |
| 988 }; | 988 }; |
| OLD | NEW |