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 ChromeVox predicates for the automation extension API. | 6 * @fileoverview ChromeVox predicates for the automation extension API. |
7 */ | 7 */ |
8 | 8 |
9 goog.provide('AutomationPredicate'); | 9 goog.provide('AutomationPredicate'); |
10 goog.provide('AutomationPredicate.Binary'); | 10 goog.provide('AutomationPredicate.Binary'); |
(...skipping 21 matching lines...) Expand all Loading... |
32 * @typedef {function(!AutomationNode, !AutomationNode) : boolean} | 32 * @typedef {function(!AutomationNode, !AutomationNode) : boolean} |
33 */ | 33 */ |
34 AutomationPredicate.Binary; | 34 AutomationPredicate.Binary; |
35 | 35 |
36 /** | 36 /** |
37 * Constructs a predicate given a list of roles. | 37 * Constructs a predicate given a list of roles. |
38 * @param {!Array<Role>} roles | 38 * @param {!Array<Role>} roles |
39 * @return {AutomationPredicate.Unary} | 39 * @return {AutomationPredicate.Unary} |
40 */ | 40 */ |
41 AutomationPredicate.roles = function(roles) { | 41 AutomationPredicate.roles = function(roles) { |
42 return AutomationPredicate.match({anyRole: roles }); | 42 return AutomationPredicate.match({anyRole: roles}); |
43 }; | 43 }; |
44 | 44 |
45 /** | 45 /** |
46 * Constructs a predicate given a list of roles or predicates. | 46 * Constructs a predicate given a list of roles or predicates. |
47 * @param {{anyRole: (Array<Role>|undefined), | 47 * @param {{anyRole: (Array<Role>|undefined), |
48 * anyPredicate: (Array<AutomationPredicate.Unary>|undefined)}} params | 48 * anyPredicate: (Array<AutomationPredicate.Unary>|undefined)}} params |
49 * @return {AutomationPredicate.Unary} | 49 * @return {AutomationPredicate.Unary} |
50 */ | 50 */ |
51 AutomationPredicate.match = function(params) { | 51 AutomationPredicate.match = function(params) { |
52 var anyRole = params.anyRole || []; | 52 var anyRole = params.anyRole || []; |
53 var anyPredicate = params.anyPredicate || []; | 53 var anyPredicate = params.anyPredicate || []; |
54 return function(node) { | 54 return function(node) { |
55 return anyRole.some(function(role) { return role == node.role; }) || | 55 return anyRole.some(function(role) { |
56 anyPredicate.some(function(p) { return p(node); }); | 56 return role == node.role; |
| 57 }) || |
| 58 anyPredicate.some(function(p) { |
| 59 return p(node); |
| 60 }); |
57 }; | 61 }; |
58 }; | 62 }; |
59 | 63 |
60 /** @type {AutomationPredicate.Unary} */ | 64 /** @type {AutomationPredicate.Unary} */ |
61 AutomationPredicate.checkBox = | 65 AutomationPredicate.checkBox = |
62 AutomationPredicate.roles([Role.CHECK_BOX, Role.SWITCH]); | 66 AutomationPredicate.roles([Role.CHECK_BOX, Role.SWITCH]); |
63 /** @type {AutomationPredicate.Unary} */ | 67 /** @type {AutomationPredicate.Unary} */ |
64 AutomationPredicate.comboBox = AutomationPredicate.roles( | 68 AutomationPredicate.comboBox = AutomationPredicate.roles( |
65 [Role.COMBO_BOX, Role.POP_UP_BUTTON, Role.MENU_LIST_POPUP]); | 69 [Role.COMBO_BOX, Role.POP_UP_BUTTON, Role.MENU_LIST_POPUP]); |
66 /** @type {AutomationPredicate.Unary} */ | 70 /** @type {AutomationPredicate.Unary} */ |
(...skipping 14 matching lines...) Expand all Loading... |
81 */ | 85 */ |
82 AutomationPredicate.button = function(node) { | 86 AutomationPredicate.button = function(node) { |
83 return /button/i.test(node.role); | 87 return /button/i.test(node.role); |
84 }; | 88 }; |
85 | 89 |
86 /** | 90 /** |
87 * @param {!AutomationNode} node | 91 * @param {!AutomationNode} node |
88 * @return {boolean} | 92 * @return {boolean} |
89 */ | 93 */ |
90 AutomationPredicate.editText = function(node) { | 94 AutomationPredicate.editText = function(node) { |
91 return node.state.editable && | 95 return node.state.editable && node.parent && !node.parent.state.editable; |
92 node.parent && | |
93 !node.parent.state.editable; | |
94 }; | 96 }; |
95 | 97 |
96 /** @type {AutomationPredicate.Unary} */ | 98 /** @type {AutomationPredicate.Unary} */ |
97 AutomationPredicate.formField = AutomationPredicate.match({ | 99 AutomationPredicate.formField = AutomationPredicate.match({ |
98 anyPredicate: [ | 100 anyPredicate: [ |
99 AutomationPredicate.button, | 101 AutomationPredicate.button, AutomationPredicate.comboBox, |
100 AutomationPredicate.comboBox, | |
101 AutomationPredicate.editText | 102 AutomationPredicate.editText |
102 ], | 103 ], |
103 anyRole: [ | 104 anyRole: [ |
104 Role.CHECK_BOX, | 105 Role.CHECK_BOX, Role.COLOR_WELL, Role.LIST_BOX, Role.SLIDER, Role.SWITCH, |
105 Role.COLOR_WELL, | 106 Role.TAB, Role.TREE |
106 Role.LIST_BOX, | |
107 Role.SLIDER, | |
108 Role.SWITCH, | |
109 Role.TAB, | |
110 Role.TREE | |
111 ] | 107 ] |
112 }); | 108 }); |
113 | 109 |
114 /** @type {AutomationPredicate.Unary} */ | 110 /** @type {AutomationPredicate.Unary} */ |
115 AutomationPredicate.control = AutomationPredicate.match({ | 111 AutomationPredicate.control = AutomationPredicate.match({ |
116 anyPredicate: [ | 112 anyPredicate: [ |
117 AutomationPredicate.formField, | 113 AutomationPredicate.formField, |
118 ], | 114 ], |
119 anyRole: [ | 115 anyRole: [ |
120 Role.DISCLOSURE_TRIANGLE, | 116 Role.DISCLOSURE_TRIANGLE, Role.MENU_ITEM, Role.MENU_ITEM_CHECK_BOX, |
121 Role.MENU_ITEM, | 117 Role.MENU_ITEM_RADIO, Role.MENU_LIST_OPTION, Role.SCROLL_BAR |
122 Role.MENU_ITEM_CHECK_BOX, | |
123 Role.MENU_ITEM_RADIO, | |
124 Role.MENU_LIST_OPTION, | |
125 Role.SCROLL_BAR | |
126 ] | 118 ] |
127 }); | 119 }); |
128 | 120 |
129 /** | 121 /** |
130 * @param {!AutomationNode} node | 122 * @param {!AutomationNode} node |
131 * @return {boolean} | 123 * @return {boolean} |
132 */ | 124 */ |
133 AutomationPredicate.image = function(node) { | 125 AutomationPredicate.image = function(node) { |
134 return node.role == Role.IMAGE && !!(node.name || node.url); | 126 return node.role == Role.IMAGE && !!(node.name || node.url); |
135 }; | 127 }; |
136 | 128 |
137 /** @type {AutomationPredicate.Unary} */ | 129 /** @type {AutomationPredicate.Unary} */ |
138 AutomationPredicate.linkOrControl = AutomationPredicate.match({ | 130 AutomationPredicate.linkOrControl = AutomationPredicate.match( |
139 anyPredicate: [ | 131 {anyPredicate: [AutomationPredicate.control], anyRole: [Role.LINK]}); |
140 AutomationPredicate.control | |
141 ], | |
142 anyRole: [ | |
143 Role.LINK | |
144 ] | |
145 }); | |
146 | 132 |
147 /** @type {AutomationPredicate.Unary} */ | 133 /** @type {AutomationPredicate.Unary} */ |
148 AutomationPredicate.landmark = AutomationPredicate.roles([ | 134 AutomationPredicate.landmark = AutomationPredicate.roles([ |
149 Role.APPLICATION, | 135 Role.APPLICATION, Role.BANNER, Role.COMPLEMENTARY, Role.CONTENT_INFO, |
150 Role.BANNER, | 136 Role.FORM, Role.MAIN, Role.NAVIGATION, Role.REGION, Role.SEARCH |
151 Role.COMPLEMENTARY, | 137 ]); |
152 Role.CONTENT_INFO, | |
153 Role.FORM, | |
154 Role.MAIN, | |
155 Role.NAVIGATION, | |
156 Role.REGION, | |
157 Role.SEARCH]); | |
158 | 138 |
159 /** | 139 /** |
160 * @param {!AutomationNode} node | 140 * @param {!AutomationNode} node |
161 * @return {boolean} | 141 * @return {boolean} |
162 */ | 142 */ |
163 AutomationPredicate.visitedLink = function(node) { | 143 AutomationPredicate.visitedLink = function(node) { |
164 return node.state.visited; | 144 return node.state.visited; |
165 }; | 145 }; |
166 | 146 |
167 /** | 147 /** |
168 * @param {!AutomationNode} node | 148 * @param {!AutomationNode} node |
169 * @return {boolean} | 149 * @return {boolean} |
170 */ | 150 */ |
171 AutomationPredicate.focused = function(node) { | 151 AutomationPredicate.focused = function(node) { |
172 return node.state.focused; | 152 return node.state.focused; |
173 }; | 153 }; |
174 | 154 |
175 /** | 155 /** |
176 * @param {!AutomationNode} node | 156 * @param {!AutomationNode} node |
177 * @return {boolean} | 157 * @return {boolean} |
178 */ | 158 */ |
179 AutomationPredicate.leaf = function(node) { | 159 AutomationPredicate.leaf = function(node) { |
180 return !node.firstChild || | 160 return !node.firstChild || node.role == Role.BUTTON || |
181 node.role == Role.BUTTON || | 161 node.role == Role.BUTTON_DROP_DOWN || node.role == Role.POP_UP_BUTTON || |
182 node.role == Role.BUTTON_DROP_DOWN || | 162 node.role == Role.SLIDER || node.role == Role.TEXT_FIELD || |
183 node.role == Role.POP_UP_BUTTON || | 163 node.state[State.INVISIBLE] || node.children.every(function(n) { |
184 node.role == Role.SLIDER || | |
185 node.role == Role.TEXT_FIELD || | |
186 node.state[State.INVISIBLE] || | |
187 node.children.every(function(n) { | |
188 return n.state[State.INVISIBLE]; | 164 return n.state[State.INVISIBLE]; |
189 }); | 165 }); |
190 }; | 166 }; |
191 | 167 |
192 /** | 168 /** |
193 * @param {!AutomationNode} node | 169 * @param {!AutomationNode} node |
194 * @return {boolean} | 170 * @return {boolean} |
195 */ | 171 */ |
196 AutomationPredicate.leafWithText = function(node) { | 172 AutomationPredicate.leafWithText = function(node) { |
197 return AutomationPredicate.leaf(node) && | 173 return AutomationPredicate.leaf(node) && !!(node.name || node.value); |
198 !!(node.name || node.value); | |
199 }; | 174 }; |
200 | 175 |
201 /** | 176 /** |
202 * Matches against leaves or static text nodes. Useful when restricting | 177 * Matches against leaves or static text nodes. Useful when restricting |
203 * traversal to non-inline textboxes while still allowing them if navigation | 178 * traversal to non-inline textboxes while still allowing them if navigation |
204 * already entered into an inline textbox. | 179 * already entered into an inline textbox. |
205 * @param {!AutomationNode} node | 180 * @param {!AutomationNode} node |
206 * @return {boolean} | 181 * @return {boolean} |
207 */ | 182 */ |
208 AutomationPredicate.leafOrStaticText = function(node) { | 183 AutomationPredicate.leafOrStaticText = function(node) { |
209 return AutomationPredicate.leaf(node) || | 184 return AutomationPredicate.leaf(node) || node.role == Role.STATIC_TEXT; |
210 node.role == Role.STATIC_TEXT; | |
211 }; | 185 }; |
212 | 186 |
213 /** | 187 /** |
214 * Matches against nodes visited during object navigation. An object as | 188 * Matches against nodes visited during object navigation. An object as |
215 * defined below, are all nodes that are focusable or static text. When used in | 189 * defined below, are all nodes that are focusable or static text. When used in |
216 * tree walking, it should visit all nodes that tab traversal would as well as | 190 * tree walking, it should visit all nodes that tab traversal would as well as |
217 * non-focusable static text. | 191 * non-focusable static text. |
218 * @param {!AutomationNode} node | 192 * @param {!AutomationNode} node |
219 * @return {boolean} | 193 * @return {boolean} |
220 */ | 194 */ |
221 AutomationPredicate.object = function(node) { | 195 AutomationPredicate.object = function(node) { |
222 // Editable nodes are within a text-like field and don't make sense when | 196 // Editable nodes are within a text-like field and don't make sense when |
223 // performing object navigation. Users should use line, word, or character | 197 // performing object navigation. Users should use line, word, or character |
224 // navigation. Only navigate to the top level node. | 198 // navigation. Only navigate to the top level node. |
225 if (node.parent && node.parent.state.editable) | 199 if (node.parent && node.parent.state.editable) |
226 return false; | 200 return false; |
227 | 201 |
228 // Descend into large nodes. | 202 // Descend into large nodes. |
229 if (node.name && node.name.length > constants.OBJECT_MAX_CHARCOUNT) | 203 if (node.name && node.name.length > constants.OBJECT_MAX_CHARCOUNT) |
230 return false; | 204 return false; |
231 | 205 |
232 return node.state.focusable || | 206 return node.state.focusable || |
233 (AutomationPredicate.leafOrStaticText(node) && | 207 (AutomationPredicate.leafOrStaticText(node) && |
234 (/\S+/.test(node.name) || | 208 (/\S+/.test(node.name) || |
235 (node.role != Role.LINE_BREAK && | 209 (node.role != Role.LINE_BREAK && node.role != Role.STATIC_TEXT && |
236 node.role != Role.STATIC_TEXT && | |
237 node.role != Role.INLINE_TEXT_BOX))); | 210 node.role != Role.INLINE_TEXT_BOX))); |
238 }; | 211 }; |
239 | 212 |
240 /** | 213 /** |
241 * Matches against nodes visited during group navigation. An object as | 214 * Matches against nodes visited during group navigation. An object as |
242 * @param {!AutomationNode} node | 215 * @param {!AutomationNode} node |
243 * @return {boolean} | 216 * @return {boolean} |
244 */ | 217 */ |
245 AutomationPredicate.group = AutomationPredicate.match({ | 218 AutomationPredicate.group = AutomationPredicate.match({ |
246 anyRole: [ | 219 anyRole: [Role.HEADING, Role.LIST, Role.PARAGRAPH], |
247 Role.HEADING, | |
248 Role.LIST, | |
249 Role.PARAGRAPH | |
250 ], | |
251 anyPredicate: [ | 220 anyPredicate: [ |
252 AutomationPredicate.editText, | 221 AutomationPredicate.editText, AutomationPredicate.formField, |
253 AutomationPredicate.formField, | 222 AutomationPredicate.object, AutomationPredicate.table |
254 AutomationPredicate.object, | |
255 AutomationPredicate.table | |
256 ] | 223 ] |
257 }); | 224 }); |
258 | 225 |
259 /** | 226 /** |
260 * @param {!AutomationNode} first | 227 * @param {!AutomationNode} first |
261 * @param {!AutomationNode} second | 228 * @param {!AutomationNode} second |
262 * @return {boolean} | 229 * @return {boolean} |
263 */ | 230 */ |
264 AutomationPredicate.linebreak = function(first, second) { | 231 AutomationPredicate.linebreak = function(first, second) { |
265 // TODO(dtseng): Use next/previousOnLin once available. | 232 // TODO(dtseng): Use next/previousOnLin once available. |
266 var fl = first.location; | 233 var fl = first.location; |
267 var sl = second.location; | 234 var sl = second.location; |
268 return fl.top != sl.top || | 235 return fl.top != sl.top || (fl.top + fl.height != sl.top + sl.height); |
269 (fl.top + fl.height != sl.top + sl.height); | |
270 }; | 236 }; |
271 | 237 |
272 /** | 238 /** |
273 * Matches against a node that contains other interesting nodes. | 239 * Matches against a node that contains other interesting nodes. |
274 * These nodes should always have their subtrees scanned when navigating. | 240 * These nodes should always have their subtrees scanned when navigating. |
275 * @param {!AutomationNode} node | 241 * @param {!AutomationNode} node |
276 * @return {boolean} | 242 * @return {boolean} |
277 */ | 243 */ |
278 AutomationPredicate.container = function(node) { | 244 AutomationPredicate.container = function(node) { |
279 return AutomationPredicate.match({ | 245 return AutomationPredicate.match({ |
280 anyRole: [ | 246 anyRole: [ |
281 Role.GENERIC_CONTAINER, | 247 Role.GENERIC_CONTAINER, Role.DOCUMENT, Role.GROUP, Role.LIST_ITEM, |
282 Role.DOCUMENT, | 248 Role.TOOLBAR, Role.WINDOW |
283 Role.GROUP, | 249 ], |
284 Role.LIST_ITEM, | |
285 Role.TOOLBAR, | |
286 Role.WINDOW], | |
287 anyPredicate: [ | 250 anyPredicate: [ |
288 AutomationPredicate.landmark, | 251 AutomationPredicate.landmark, AutomationPredicate.structuralContainer, |
289 AutomationPredicate.structuralContainer, | |
290 function(node) { | 252 function(node) { |
291 // For example, crosh. | 253 // For example, crosh. |
292 return (node.role == Role.TEXT_FIELD && node.state.readOnly); | 254 return (node.role == Role.TEXT_FIELD && node.state.readOnly); |
293 }, | 255 }, |
294 function(node) { | 256 function(node) { |
295 return (node.state.editable && | 257 return ( |
296 node.parent && | 258 node.state.editable && node.parent && !node.parent.state.editable); |
297 !node.parent.state.editable); | 259 } |
298 }] | 260 ] |
299 })(node); | 261 })(node); |
300 }; | 262 }; |
301 | 263 |
302 /** | 264 /** |
303 * Matches against nodes that contain interesting nodes, but should never be | 265 * Matches against nodes that contain interesting nodes, but should never be |
304 * visited. | 266 * visited. |
305 * @param {!AutomationNode} node | 267 * @param {!AutomationNode} node |
306 * @return {boolean} | 268 * @return {boolean} |
307 */ | 269 */ |
308 AutomationPredicate.structuralContainer = AutomationPredicate.roles([ | 270 AutomationPredicate.structuralContainer = AutomationPredicate.roles([ |
309 Role.ALERT_DIALOG, | 271 Role.ALERT_DIALOG, Role.DIALOG, Role.ROOT_WEB_AREA, Role.WEB_VIEW, |
310 Role.DIALOG, | 272 Role.WINDOW, Role.EMBEDDED_OBJECT, Role.IFRAME, Role.IFRAME_PRESENTATIONAL, |
311 Role.ROOT_WEB_AREA, | 273 Role.UNKNOWN |
312 Role.WEB_VIEW, | 274 ]); |
313 Role.WINDOW, | |
314 Role.EMBEDDED_OBJECT, | |
315 Role.IFRAME, | |
316 Role.IFRAME_PRESENTATIONAL, | |
317 Role.UNKNOWN]); | |
318 | 275 |
319 /** | 276 /** |
320 * Returns whether the given node should not be crossed when performing | 277 * Returns whether the given node should not be crossed when performing |
321 * traversals up the ancestry chain. | 278 * traversals up the ancestry chain. |
322 * @param {AutomationNode} node | 279 * @param {AutomationNode} node |
323 * @return {boolean} | 280 * @return {boolean} |
324 */ | 281 */ |
325 AutomationPredicate.root = function(node) { | 282 AutomationPredicate.root = function(node) { |
326 switch (node.role) { | 283 switch (node.role) { |
327 case Role.WINDOW: | 284 case Role.WINDOW: |
328 return true; | 285 return true; |
329 case Role.DIALOG: | 286 case Role.DIALOG: |
330 // The below logic handles nested dialogs properly in the desktop tree | 287 // The below logic handles nested dialogs properly in the desktop tree |
331 // like that found in a bubble view. | 288 // like that found in a bubble view. |
332 return node.root.role != Role.DESKTOP || | 289 return node.root.role != Role.DESKTOP || |
333 (!!node.parent && | 290 (!!node.parent && node.parent.role == Role.WINDOW && |
334 node.parent.role == Role.WINDOW && | |
335 node.parent.children.every(function(child) { | 291 node.parent.children.every(function(child) { |
336 return node.role == Role.WINDOW || node.role == Role.DIALOG; | 292 return node.role == Role.WINDOW || node.role == Role.DIALOG; |
337 })); | 293 })); |
338 case Role.TOOLBAR: | 294 case Role.TOOLBAR: |
339 return node.root.role == Role.DESKTOP; | 295 return node.root.role == Role.DESKTOP; |
340 case Role.ROOT_WEB_AREA: | 296 case Role.ROOT_WEB_AREA: |
341 return !node.parent || node.parent.root.role == Role.DESKTOP; | 297 return !node.parent || node.parent.root.role == Role.DESKTOP; |
342 default: | 298 default: |
343 return false; | 299 return false; |
344 } | 300 } |
(...skipping 17 matching lines...) Expand all Loading... |
362 | 318 |
363 // Ignore list markers since we already announce listitem role. | 319 // Ignore list markers since we already announce listitem role. |
364 if (node.role == Role.LIST_MARKER) | 320 if (node.role == Role.LIST_MARKER) |
365 return true; | 321 return true; |
366 | 322 |
367 // Don't ignore nodes with names or name-like attribute. | 323 // Don't ignore nodes with names or name-like attribute. |
368 if (node.name || node.value || node.description || node.url) | 324 if (node.name || node.value || node.description || node.url) |
369 return false; | 325 return false; |
370 | 326 |
371 // Ignore some roles. | 327 // Ignore some roles. |
372 return AutomationPredicate.leaf(node) && | 328 return AutomationPredicate.leaf(node) && (AutomationPredicate.roles([ |
373 (AutomationPredicate.roles([Role.CLIENT, | 329 Role.CLIENT, Role.COLUMN, Role.GENERIC_CONTAINER, Role.GROUP, |
374 Role.COLUMN, | 330 Role.IMAGE, Role.STATIC_TEXT, Role.SVG_ROOT, |
375 Role.GENERIC_CONTAINER, | 331 Role.TABLE_HEADER_CONTAINER, Role.UNKNOWN |
376 Role.GROUP, | 332 ])(node)); |
377 Role.IMAGE, | |
378 Role.STATIC_TEXT, | |
379 Role.SVG_ROOT, | |
380 Role.TABLE_HEADER_CONTAINER, | |
381 Role.UNKNOWN | |
382 ])(node)); | |
383 }; | 333 }; |
384 | 334 |
385 /** | 335 /** |
386 * Returns if the node has a meaningful checked state. | 336 * Returns if the node has a meaningful checked state. |
387 * @param {!AutomationNode} node | 337 * @param {!AutomationNode} node |
388 * @return {boolean} | 338 * @return {boolean} |
389 */ | 339 */ |
390 AutomationPredicate.checkable = AutomationPredicate.roles([ | 340 AutomationPredicate.checkable = AutomationPredicate.roles([ |
391 Role.CHECK_BOX, | 341 Role.CHECK_BOX, Role.RADIO_BUTTON, Role.MENU_ITEM_CHECK_BOX, |
392 Role.RADIO_BUTTON, | 342 Role.MENU_ITEM_RADIO, Role.TREE_ITEM |
393 Role.MENU_ITEM_CHECK_BOX, | 343 ]); |
394 Role.MENU_ITEM_RADIO, | |
395 Role.TREE_ITEM]); | |
396 | 344 |
397 // Table related predicates. | 345 // Table related predicates. |
398 /** | 346 /** |
399 * Returns if the node has a cell like role. | 347 * Returns if the node has a cell like role. |
400 * @param {!AutomationNode} node | 348 * @param {!AutomationNode} node |
401 * @return {boolean} | 349 * @return {boolean} |
402 */ | 350 */ |
403 AutomationPredicate.cellLike = AutomationPredicate.roles([ | 351 AutomationPredicate.cellLike = |
404 Role.CELL, | 352 AutomationPredicate.roles([Role.CELL, Role.ROW_HEADER, Role.COLUMN_HEADER]); |
405 Role.ROW_HEADER, | |
406 Role.COLUMN_HEADER]); | |
407 | 353 |
408 /** | 354 /** |
409 * Returns a predicate that will match against the directed next cell taking | 355 * Returns a predicate that will match against the directed next cell taking |
410 * into account the current ancestor cell's position in the table. | 356 * into account the current ancestor cell's position in the table. |
411 * @param {AutomationNode} start | 357 * @param {AutomationNode} start |
412 * @param {{dir: (Dir|undefined), | 358 * @param {{dir: (Dir|undefined), |
413 * row: (boolean|undefined), | 359 * row: (boolean|undefined), |
414 * col: (boolean|undefined)}} opts | 360 * col: (boolean|undefined)}} opts |
415 * |dir|, specifies direction for |row or/and |col| movement by one cell. | 361 * |dir|, specifies direction for |row or/and |col| movement by one cell. |
416 * |dir| defaults to forward. | 362 * |dir| defaults to forward. |
417 * |row| and |col| are both false by default. | 363 * |row| and |col| are both false by default. |
418 * |end| defaults to false. If set to true, |col| must also be set to true. | 364 * |end| defaults to false. If set to true, |col| must also be set to true. |
419 * It will then return the first or last cell in the current column. | 365 * It will then return the first or last cell in the current column. |
420 * @return {?AutomationPredicate.Unary} Returns null if not in a table. | 366 * @return {?AutomationPredicate.Unary} Returns null if not in a table. |
421 */ | 367 */ |
422 AutomationPredicate.makeTableCellPredicate = function(start, opts) { | 368 AutomationPredicate.makeTableCellPredicate = function(start, opts) { |
423 if (!opts.row && !opts.col) | 369 if (!opts.row && !opts.col) |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 return function(node) { | 431 return function(node) { |
486 return node.role == Role.HEADING && node.hierarchicalLevel == level; | 432 return node.role == Role.HEADING && node.hierarchicalLevel == level; |
487 }; | 433 }; |
488 }; | 434 }; |
489 | 435 |
490 /** | 436 /** |
491 * Matches against nodes that we may be able to retrieve image data from. | 437 * Matches against nodes that we may be able to retrieve image data from. |
492 * @param {!AutomationNode} node | 438 * @param {!AutomationNode} node |
493 * @return {boolean} | 439 * @return {boolean} |
494 */ | 440 */ |
495 AutomationPredicate.supportsImageData = AutomationPredicate.roles([ | 441 AutomationPredicate.supportsImageData = |
496 Role.CANVAS, | 442 AutomationPredicate.roles([Role.CANVAS, Role.IMAGE, Role.VIDEO]); |
497 Role.IMAGE, | |
498 Role.VIDEO]); | |
499 | 443 |
500 }); // goog.scope | 444 }); // goog.scope |
OLD | NEW |