Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(923)

Side by Side Diff: chrome/browser/resources/chromeos/switch_access/tree_walker.js

Issue 2863613003: Implemented scanning by group (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 * Class to move to the appropriate node in the accessibility tree. 6 * Class to move to the appropriate node in the accessibility tree. Stays in a
7 * subtree determined by restrictions passed to it.
7 * 8 *
8 * @constructor 9 * @constructor
10 * @param {!chrome.automation.AutomationNode} start
11 * @param {!chrome.automation.AutomationNode} scope
12 * @param {!AutomationTreeWalker.Restriction} restrictions
9 */ 13 */
10 function AutomationTreeWalker() {}; 14 function AutomationTreeWalker(start, scope, restrictions) {
15 /**
16 * Currently highlighted node.
17 *
18 * @private {!chrome.automation.AutomationNode}
19 */
20 this.node_ = start;
21
22 /**
23 * The root of the subtree that the user is navigating through.
24 *
25 * @private {!chrome.automation.AutomationNode}
26 */
27 this.scope_ = scope;
28
29 /**
30 * Function that returns true for a node that is a leaf of the current
31 * subtree.
32 *
33 * @private {!AutomationTreeWalker.Unary}
34 */
35 this.leafPred_ = restrictions.leaf;
36
37 /**
38 * Function that returns true for a node in the current subtree that should
39 * be visited.
40 *
41 * @private {!AutomationTreeWalker.Unary}
42 */
43 this.visitPred_ = restrictions.visit;
44 };
45
46 /**
47 * @typedef {{leaf: AutomationTreeWalker.Unary,
48 * visit: AutomationTreeWalker.Unary}}
49 */
50 AutomationTreeWalker.Restriction;
51
52 /**
53 * @typedef {function(!chrome.automation.AutomationNode) : boolean}
54 */
55 AutomationTreeWalker.Unary;
11 56
12 AutomationTreeWalker.prototype = { 57 AutomationTreeWalker.prototype = {
13 /** 58 /**
14 * Return the next/previous interesting node from |start|. If no interesting 59 * Set this.node_ to the next/previous interesting node and return it. If no
15 * node is found, return the first/last interesting node. If |doNext| is true, 60 * interesting node is found, return the first/last interesting node. If
16 * will search for next node. Otherwise, will search for previous node. 61 * |doNext| is true, will search for next node. Otherwise, will search for
62 * previous node.
dmazzoni 2017/05/05 18:23:19 Maybe mention that it stays within scope_?
elichtenberg 2017/05/06 00:13:53 Done.
17 * 63 *
18 * @param {chrome.automation.AutomationNode} start
19 * @param {chrome.automation.AutomationNode} root
20 * @param {boolean} doNext 64 * @param {boolean} doNext
21 * @return {chrome.automation.AutomationNode} 65 * @return {chrome.automation.AutomationNode}
22 */ 66 */
23 moveToNode: function(start, root, doNext) { 67 moveToNode: function(doNext) {
24 let node = start; 68 let node = this.node_;
69 do {
70 node = doNext ? this.getNextNode_(node) : this.getPreviousNode_(node);
71 } while (node && !this.visitPred_(node));
25 if (node) { 72 if (node) {
26 do { 73 this.node_ = node;
27 node = doNext ? this.getNextNode_(node) : this.getPreviousNode_(node); 74 return node;
28 } while (node && !this.isInteresting_(node));
29 if (node)
30 return node;
31 } 75 }
32 76
33 if (root) { 77 console.log('Restarting search for node at ' + (doNext ? 'first' : 'last'));
34 console.log( 78 node = doNext ? this.scope_ : this.getYoungestDescendant_(this.scope_);
35 'Restarting search for node at ' + (doNext ? 'first' : 'last')); 79 while (node && !this.visitPred_(node))
36 node = doNext ? root.firstChild : this.getYoungestDescendant_(root); 80 node = doNext ? this.getNextNode_(node) : this.getPreviousNode_(node);
37 while (node && !this.isInteresting_(node)) 81 if (node) {
38 node = doNext ? this.getNextNode_(node) : this.getPreviousNode_(node); 82 this.node_ = node;
39 if (node) 83 return node;
40 return node;
41 } 84 }
42 85
43 console.log('Found no interesting nodes to visit.'); 86 console.log('Found no interesting nodes to visit.');
44 return null; 87 return null;
45 }, 88 },
46 89
90
47 /** 91 /**
48 * Given a flat list of nodes in pre-order, get the node that comes after 92 * Given a flat list of nodes in pre-order, get the node that comes after
49 * |node|. 93 * |node|.
50 * 94 *
51 * @param {!chrome.automation.AutomationNode} node 95 * @param {!chrome.automation.AutomationNode} node
52 * @return {!chrome.automation.AutomationNode|undefined} 96 * @return {!chrome.automation.AutomationNode|undefined}
53 * @private 97 * @private
54 */ 98 */
55 getNextNode_: function(node) { 99 getNextNode_: function(node) {
56 // Check for child. 100 // Check for child.
57 let child = node.firstChild; 101 let child = node.firstChild;
58 if (child) 102 if (child && !this.leafPred_(node))
59 return child; 103 return child;
60 104
105 // Has no children, and if node is root of subtree, don't check siblings
106 // or parent.
107 if (node === this.scope_)
108 return undefined;
109
61 // No child. Check for right-sibling. 110 // No child. Check for right-sibling.
62 let sibling = node.nextSibling; 111 let sibling = node.nextSibling;
63 if (sibling) 112 if (sibling)
64 return sibling; 113 return sibling;
65 114
66 // No right-sibling. Get right-sibling of closest ancestor. 115 // No right-sibling. Get right-sibling of closest ancestor.
67 let ancestor = node.parent; 116 let ancestor = node.parent;
68 while (ancestor) { 117 while (ancestor && ancestor !== this.scope_) {
69 let aunt = ancestor.nextSibling; 118 let aunt = ancestor.nextSibling;
70 if (aunt) 119 if (aunt)
71 return aunt; 120 return aunt;
72 ancestor = ancestor.parent; 121 ancestor = ancestor.parent;
73 } 122 }
74 123
75 // No node found after |node|, so return undefined. 124 // No node found after |node|, so return undefined.
76 return undefined; 125 return undefined;
77 }, 126 },
78 127
79 /** 128 /**
80 * Given a flat list of nodes in pre-order, get the node that comes before 129 * Given a flat list of nodes in pre-order, get the node that comes before
81 * |node|. 130 * |node|.
82 * 131 *
83 * @param {!chrome.automation.AutomationNode} node 132 * @param {!chrome.automation.AutomationNode} node
84 * @return {!chrome.automation.AutomationNode|undefined} 133 * @return {!chrome.automation.AutomationNode|undefined}
85 * @private 134 * @private
86 */ 135 */
87 getPreviousNode_: function(node) { 136 getPreviousNode_: function(node) {
137 // If node is root of subtree, there is no previous node.
138 if (node === this.scope_)
139 return undefined;
140
88 // Check for left-sibling. If a left-sibling exists, return its youngest 141 // Check for left-sibling. If a left-sibling exists, return its youngest
89 // descendant if it has one, or otherwise return the sibling. 142 // descendant if it has one, or otherwise return the sibling.
90 let sibling = node.previousSibling; 143 let sibling = node.previousSibling;
91 if (sibling) 144 if (sibling)
92 return this.getYoungestDescendant_(sibling) || sibling; 145 return this.getYoungestDescendant_(sibling) || sibling;
93 146
94 // No left-sibling. Return parent if it exists; otherwise return undefined. 147 // No left-sibling. Return parent if it exists; otherwise return undefined.
95 return node.parent; 148 //return node.parent;
149 let parent = node.parent;
150 if (parent)
151 return parent;
152
153 return undefined;
96 }, 154 },
97 155
98 /** 156 /**
99 * Get the youngest descendant of |node| if it has one. 157 * Get the youngest descendant of |node| if it has one.
100 * 158 *
101 * @param {!chrome.automation.AutomationNode} node 159 * @param {!chrome.automation.AutomationNode} node
102 * @return {!chrome.automation.AutomationNode|undefined} 160 * @return {!chrome.automation.AutomationNode|undefined}
103 * @private 161 * @private
104 */ 162 */
105 getYoungestDescendant_: function(node) { 163 getYoungestDescendant_: function(node) {
106 if (!node.lastChild) 164 if (!node.lastChild || this.leafPred_(node))
107 return undefined; 165 return undefined;
108 166
109 while (node.lastChild) 167 while (node.lastChild && !this.leafPred_(node))
110 node = node.lastChild; 168 node = node.lastChild;
111 169
112 return node; 170 return node;
113 }, 171 },
114 172
115 /** 173 /**
116 * Returns true if |node| is interesting.
117 *
118 * @param {!chrome.automation.AutomationNode} node
119 * @return {boolean}
120 * @private
121 */
122 isInteresting_: function(node) {
123 let loc = node.location;
124 let parent = node.parent;
125 let root = node.root;
126 let role = node.role;
127 let state = node.state;
128
129 // Skip things that are offscreen
130 if (state[chrome.automation.StateType.OFFSCREEN]
131 || loc.top < 0 || loc.left < 0)
132 return false;
133
134 if (parent) {
135 // crbug.com/710559
136 // Work around for browser tabs
137 if (role === chrome.automation.RoleType.TAB
138 && parent.role === chrome.automation.RoleType.TAB_LIST
139 && root.role === chrome.automation.RoleType.DESKTOP)
140 return true;
141 }
142
143 // The general rule that applies to everything.
144 return state[chrome.automation.StateType.FOCUSABLE] === true;
145 },
146
147 /**
148 * Return the next sibling of |node| if it has one. 174 * Return the next sibling of |node| if it has one.
149 * 175 *
150 * @param {chrome.automation.AutomationNode} node 176 * @param {chrome.automation.AutomationNode} node
151 * @return {chrome.automation.AutomationNode} 177 * @return {chrome.automation.AutomationNode}
152 */ 178 */
153 debugMoveToNext: function(node) { 179 debugMoveToNext: function(node) {
154 if (!node) 180 if (!node)
155 return null; 181 return null;
156 182
157 let next = node.nextSibling; 183 let next = node.nextSibling;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 let parent = node.parent; 243 let parent = node.parent;
218 if (parent) { 244 if (parent) {
219 return parent; 245 return parent;
220 } else { 246 } else {
221 console.log('Node has no parent'); 247 console.log('Node has no parent');
222 console.log('\n'); 248 console.log('\n');
223 return null; 249 return null;
224 } 250 }
225 } 251 }
226 }; 252 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698