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 |