| 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 |