Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * Class to move to the appropriate node in the accessibility tree. | |
| 7 * | |
| 8 * @constructor | |
| 9 */ | |
| 10 function AutomationTreeWalker() {}; | |
| 11 | |
| 12 AutomationTreeWalker.prototype = { | |
| 13 /** | |
| 14 * Return the next interesting node after |node|. If no interesting node comes | |
| 15 * after |node|, return the first interesting node. | |
| 16 * | |
| 17 * @param {chrome.automation.AutomationNode} node | |
| 18 * @param {chrome.automation.AutomationNode} root | |
| 19 * @return {chrome.automation.AutomationNode} | |
| 20 */ | |
| 21 moveToNext: function(node, root) { | |
| 22 if (node) { | |
| 23 let next = this.getNextNode_(node); | |
|
David Tseng
2017/03/29 21:57:21
You could just have
do {
node = this...
whil
elichtenberg
2017/03/30 21:46:56
Done.
| |
| 24 while (next && !this.isInteresting_(next)) | |
| 25 next = this.getNextNode_(next); | |
| 26 if (next) | |
| 27 return next; | |
| 28 } | |
| 29 | |
| 30 if (root) { | |
| 31 console.log('Reached the last interesting node. Restarting with first.'); | |
| 32 let next = root.firstChild; | |
| 33 while (next && !this.isInteresting_(next)) | |
| 34 next = this.getNextNode_(next); | |
| 35 if (next) | |
| 36 return next; | |
| 37 } | |
| 38 | |
| 39 console.log('Found no interesting nodes to visit.'); | |
| 40 return null; | |
| 41 }, | |
| 42 | |
| 43 /** | |
| 44 * Returns the previous interesting node before |node|. If no interesting node | |
| 45 * comes before |node|, return the last interesting node. | |
| 46 * | |
| 47 * @param {chrome.automation.AutomationNode} node | |
| 48 * @param {chrome.automation.AutomationNode} root | |
| 49 * @return {chrome.automation.AutomationNode} | |
| 50 */ | |
| 51 moveToPrevious: function(node, root) { | |
| 52 if (node) { | |
| 53 let prev = this.getPreviousNode_(node); | |
| 54 while (prev && !this.isInteresting_(prev)) | |
| 55 prev = this.getPreviousNode_(prev); | |
| 56 if (prev) | |
| 57 return prev; | |
| 58 } | |
| 59 | |
| 60 if (root) { | |
| 61 console.log('Reached the first interesting node. Restarting with last.') | |
| 62 let prev = this.getYoungestDescendant_(root); | |
| 63 while (prev && !this.isInteresting_(prev)) | |
| 64 prev = this.getPreviousNode_(prev); | |
| 65 if (prev) | |
| 66 return prev; | |
| 67 } | |
|
David Tseng
2017/03/29 21:57:21
You can combine this function with the one above a
elichtenberg
2017/03/30 21:46:56
Done.
| |
| 68 | |
| 69 console.log('Found no interesting nodes to visit.') | |
| 70 return null; | |
| 71 }, | |
| 72 | |
| 73 /** | |
| 74 * Given a flat list of nodes in pre-order, get the node that comes after | |
| 75 * |node|. | |
| 76 * | |
| 77 * @param {!chrome.automation.AutomationNode} node | |
| 78 * @return {chrome.automation.AutomationNode} | |
| 79 * @private | |
| 80 */ | |
| 81 getNextNode_: function(node) { | |
| 82 // Check for child. | |
| 83 let child = node.firstChild; | |
| 84 if (child) | |
| 85 return child; | |
| 86 | |
| 87 // No child. Check for right-sibling. | |
| 88 let sibling = node.nextSibling; | |
| 89 if (sibling) | |
| 90 return sibling; | |
| 91 | |
| 92 // No right-sibling. Get right-sibling of closest ancestor. | |
| 93 let ancestor = node.parent; | |
| 94 while (ancestor) { | |
| 95 let aunt = ancestor.nextSibling; | |
| 96 if (aunt) | |
| 97 return aunt; | |
|
David Tseng
2017/03/29 21:57:21
Comment: very gender specific :).
elichtenberg
2017/03/30 21:46:56
Haha, no gender-neutral word for aunt or uncle yet
| |
| 98 ancestor = ancestor.parent; | |
| 99 } | |
| 100 | |
| 101 // No node found after |node|, so return null. | |
| 102 return null; | |
| 103 }, | |
| 104 | |
| 105 /** | |
| 106 * Given a flat list of nodes in pre-order, get the node that comes before | |
| 107 * |node|. | |
| 108 * | |
| 109 * @param {!chrome.automation.AutomationNode} node | |
| 110 * @return {chrome.automation.AutomationNode} | |
| 111 * @private | |
| 112 */ | |
| 113 getPreviousNode_: function(node) { | |
| 114 // Check for left-sibling. Return its youngest descendant if it has one. | |
| 115 // Otherwise, return the sibling. | |
| 116 let sibling = node.previousSibling; | |
| 117 if (sibling) { | |
| 118 let descendant = this.getYoungestDescendant_(sibling); | |
|
David Tseng
2017/03/29 21:57:21
return this.getYoungestDescendant_(sibling) || sib
elichtenberg
2017/03/30 21:46:56
Done.
| |
| 119 if (descendant) | |
| 120 return descendant; | |
| 121 return sibling; | |
| 122 } | |
| 123 | |
| 124 // No left-sibling. Check for parent. | |
| 125 let parent = node.parent; | |
|
David Tseng
2017/03/29 21:57:21
return node.parent; (no need to do any of the belo
elichtenberg
2017/03/30 21:46:56
Done.
| |
| 126 if (parent) | |
| 127 return parent; | |
| 128 | |
| 129 // No node found before |node|, so return null. | |
| 130 return null; | |
| 131 }, | |
| 132 | |
| 133 /** | |
| 134 * Get the youngest descendant of |node| if it has one. | |
| 135 * | |
| 136 * @param {!chrome.automation.AutomationNode} node | |
| 137 * @return {chrome.automation.AutomationNode} | |
| 138 * @private | |
| 139 */ | |
| 140 getYoungestDescendant_: function(node) { | |
| 141 if (!node.lastChild) | |
| 142 return null; | |
| 143 | |
| 144 while (node.lastChild) | |
| 145 node = node.lastChild; | |
| 146 | |
| 147 return node; | |
| 148 }, | |
| 149 | |
| 150 /** | |
| 151 * Returns true if |node| is interesting. | |
| 152 * | |
| 153 * @param {!chrome.automation.AutomationNode} node | |
| 154 * @return {boolean} | |
| 155 * @private | |
| 156 */ | |
| 157 isInteresting_: function(node) { | |
| 158 return node.state && node.state.focusable; | |
| 159 }, | |
| 160 | |
| 161 /** | |
| 162 * Return the next sibling of |node| if it has one. | |
| 163 * | |
| 164 * @param {chrome.automation.AutomationNode} node | |
| 165 * @return {chrome.automation.AutomationNode} | |
| 166 */ | |
| 167 debugMoveToNext: function(node) { | |
| 168 if (!node) | |
| 169 return null; | |
| 170 | |
| 171 let next = node.nextSibling; | |
| 172 if (next) { | |
| 173 return next; | |
| 174 } else { | |
| 175 console.log('Node is last of siblings'); | |
| 176 console.log('\n'); | |
| 177 return null; | |
| 178 } | |
| 179 }, | |
| 180 | |
| 181 /** | |
| 182 * Return the previous sibling of |node| if it has one. | |
| 183 * | |
| 184 * @param {chrome.automation.AutomationNode} node | |
| 185 * @return {chrome.automation.AutomationNode} | |
| 186 */ | |
| 187 debugMoveToPrevious: function(node) { | |
| 188 if (!node) | |
| 189 return null; | |
| 190 | |
| 191 let prev = node.previousSibling; | |
| 192 if (prev) { | |
| 193 return prev; | |
| 194 } else { | |
| 195 console.log('Node is first of siblings'); | |
| 196 console.log('\n'); | |
| 197 return null; | |
| 198 } | |
| 199 }, | |
| 200 | |
| 201 /** | |
| 202 * Return the first child of |node| if it has one. | |
| 203 * | |
| 204 * @param {chrome.automation.AutomationNode} node | |
| 205 * @return {chrome.automation.AutomationNode} | |
| 206 */ | |
| 207 debugMoveToFirstChild: function(node) { | |
| 208 if (!node) | |
| 209 return null; | |
| 210 | |
| 211 let child = node.firstChild; | |
| 212 if (child) { | |
| 213 return child; | |
| 214 } else { | |
| 215 console.log('Node has no children'); | |
| 216 console.log('\n'); | |
| 217 return null; | |
| 218 } | |
| 219 }, | |
| 220 | |
| 221 /** | |
| 222 * Return the parent of |node| if it has one. | |
| 223 * | |
| 224 * @param {chrome.automation.AutomationNode} node | |
| 225 * @return {chrome.automation.AutomationNode} | |
| 226 */ | |
| 227 debugMoveToParent: function(node) { | |
| 228 if (!node) | |
| 229 return null; | |
| 230 | |
| 231 let parent = node.parent; | |
| 232 if (parent) { | |
| 233 return parent; | |
| 234 } else { | |
| 235 console.log('Node has no parent'); | |
| 236 console.log('\n'); | |
| 237 return null; | |
| 238 } | |
| 239 } | |
| 240 }; | |
| OLD | NEW |