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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js

Issue 2601333002: Update json_schema_compiler to handle the Automation extension API (Closed)
Patch Set: Rebase Created 3 years, 11 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 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');
11 goog.provide('AutomationPredicate.Unary'); 11 goog.provide('AutomationPredicate.Unary');
12 12
13 goog.require('constants'); 13 goog.require('constants');
14 14
15 goog.scope(function() { 15 goog.scope(function() {
16 var AutomationNode = chrome.automation.AutomationNode; 16 var AutomationNode = chrome.automation.AutomationNode;
17 var Dir = constants.Dir; 17 var Dir = constants.Dir;
18 var Role = chrome.automation.RoleType; 18 var Role = chrome.automation.RoleType;
19 var State = chrome.automation.StateType;
19 20
20 /** 21 /**
21 * @constructor 22 * @constructor
22 */ 23 */
23 AutomationPredicate = function() {}; 24 AutomationPredicate = function() {};
24 25
25 /** 26 /**
26 * @typedef {function(!AutomationNode) : boolean} 27 * @typedef {function(!AutomationNode) : boolean}
27 */ 28 */
28 AutomationPredicate.Unary; 29 AutomationPredicate.Unary;
(...skipping 22 matching lines...) Expand all
51 var anyRole = params.anyRole || []; 52 var anyRole = params.anyRole || [];
52 var anyPredicate = params.anyPredicate || []; 53 var anyPredicate = params.anyPredicate || [];
53 return function(node) { 54 return function(node) {
54 return anyRole.some(function(role) { return role == node.role; }) || 55 return anyRole.some(function(role) { return role == node.role; }) ||
55 anyPredicate.some(function(p) { return p(node); }); 56 anyPredicate.some(function(p) { return p(node); });
56 }; 57 };
57 }; 58 };
58 59
59 /** @type {AutomationPredicate.Unary} */ 60 /** @type {AutomationPredicate.Unary} */
60 AutomationPredicate.checkBox = 61 AutomationPredicate.checkBox =
61 AutomationPredicate.roles([Role.checkBox, Role.switch]); 62 AutomationPredicate.roles([Role.CHECK_BOX, Role.SWITCH]);
62 /** @type {AutomationPredicate.Unary} */ 63 /** @type {AutomationPredicate.Unary} */
63 AutomationPredicate.comboBox = AutomationPredicate.roles( 64 AutomationPredicate.comboBox = AutomationPredicate.roles(
64 [Role.comboBox, Role.popUpButton, Role.menuListPopup]); 65 [Role.COMBO_BOX, Role.POP_UP_BUTTON, Role.MENU_LIST_POPUP]);
65 /** @type {AutomationPredicate.Unary} */ 66 /** @type {AutomationPredicate.Unary} */
66 AutomationPredicate.heading = AutomationPredicate.roles([Role.heading]); 67 AutomationPredicate.heading = AutomationPredicate.roles([Role.HEADING]);
67 /** @type {AutomationPredicate.Unary} */ 68 /** @type {AutomationPredicate.Unary} */
68 AutomationPredicate.inlineTextBox = 69 AutomationPredicate.inlineTextBox =
69 AutomationPredicate.roles([Role.inlineTextBox]); 70 AutomationPredicate.roles([Role.INLINE_TEXT_BOX]);
70 /** @type {AutomationPredicate.Unary} */ 71 /** @type {AutomationPredicate.Unary} */
71 AutomationPredicate.link = AutomationPredicate.roles([Role.link]); 72 AutomationPredicate.link = AutomationPredicate.roles([Role.LINK]);
72 /** @type {AutomationPredicate.Unary} */ 73 /** @type {AutomationPredicate.Unary} */
73 AutomationPredicate.row = AutomationPredicate.roles([Role.row]); 74 AutomationPredicate.row = AutomationPredicate.roles([Role.ROW]);
74 /** @type {AutomationPredicate.Unary} */ 75 /** @type {AutomationPredicate.Unary} */
75 AutomationPredicate.table = AutomationPredicate.roles([Role.grid, Role.table]); 76 AutomationPredicate.table = AutomationPredicate.roles([Role.GRID, Role.TABLE]);
76 77
77 /** 78 /**
78 * @param {!AutomationNode} node 79 * @param {!AutomationNode} node
79 * @return {boolean} 80 * @return {boolean}
80 */ 81 */
81 AutomationPredicate.button = function(node) { 82 AutomationPredicate.button = function(node) {
82 return /button/i.test(node.role); 83 return /button/i.test(node.role);
83 }; 84 };
84 85
85 /** 86 /**
86 * @param {!AutomationNode} node 87 * @param {!AutomationNode} node
87 * @return {boolean} 88 * @return {boolean}
88 */ 89 */
89 AutomationPredicate.editText = function(node) { 90 AutomationPredicate.editText = function(node) {
90 return node.state.editable && 91 return node.state.editable &&
91 node.parent && 92 node.parent &&
92 !node.parent.state.editable; 93 !node.parent.state.editable;
93 }; 94 };
94 95
95 /** @type {AutomationPredicate.Unary} */ 96 /** @type {AutomationPredicate.Unary} */
96 AutomationPredicate.formField = AutomationPredicate.match({ 97 AutomationPredicate.formField = AutomationPredicate.match({
97 anyPredicate: [ 98 anyPredicate: [
98 AutomationPredicate.button, 99 AutomationPredicate.button,
99 AutomationPredicate.comboBox, 100 AutomationPredicate.comboBox,
100 AutomationPredicate.editText 101 AutomationPredicate.editText
101 ], 102 ],
102 anyRole: [ 103 anyRole: [
103 Role.checkBox, 104 Role.CHECK_BOX,
104 Role.colorWell, 105 Role.COLOR_WELL,
105 Role.listBox, 106 Role.LIST_BOX,
106 Role.slider, 107 Role.SLIDER,
107 Role.switch, 108 Role.SWITCH,
108 Role.tab, 109 Role.TAB,
109 Role.tree 110 Role.TREE
110 ] 111 ]
111 }); 112 });
112 113
113 /** @type {AutomationPredicate.Unary} */ 114 /** @type {AutomationPredicate.Unary} */
114 AutomationPredicate.control = AutomationPredicate.match({ 115 AutomationPredicate.control = AutomationPredicate.match({
115 anyPredicate: [ 116 anyPredicate: [
116 AutomationPredicate.formField, 117 AutomationPredicate.formField,
117 ], 118 ],
118 anyRole: [ 119 anyRole: [
119 Role.disclosureTriangle, 120 Role.DISCLOSURE_TRIANGLE,
120 Role.menuItem, 121 Role.MENU_ITEM,
121 Role.menuItemCheckBox, 122 Role.MENU_ITEM_CHECK_BOX,
122 Role.menuItemRadio, 123 Role.MENU_ITEM_RADIO,
123 Role.menuListOption, 124 Role.MENU_LIST_OPTION,
124 Role.scrollBar 125 Role.SCROLL_BAR
125 ] 126 ]
126 }); 127 });
127 128
128 /** 129 /**
129 * @param {!AutomationNode} node 130 * @param {!AutomationNode} node
130 * @return {boolean} 131 * @return {boolean}
131 */ 132 */
132 AutomationPredicate.image = function(node) { 133 AutomationPredicate.image = function(node) {
133 return node.role == Role.image && !!(node.name || node.url); 134 return node.role == Role.IMAGE && !!(node.name || node.url);
134 }; 135 };
135 136
136 /** @type {AutomationPredicate.Unary} */ 137 /** @type {AutomationPredicate.Unary} */
137 AutomationPredicate.linkOrControl = AutomationPredicate.match({ 138 AutomationPredicate.linkOrControl = AutomationPredicate.match({
138 anyPredicate: [ 139 anyPredicate: [
139 AutomationPredicate.control 140 AutomationPredicate.control
140 ], 141 ],
141 anyRole: [ 142 anyRole: [
142 Role.link 143 Role.LINK
143 ] 144 ]
144 }); 145 });
145 146
146 /** @type {AutomationPredicate.Unary} */ 147 /** @type {AutomationPredicate.Unary} */
147 AutomationPredicate.landmark = AutomationPredicate.roles([ 148 AutomationPredicate.landmark = AutomationPredicate.roles([
148 Role.application, 149 Role.APPLICATION,
149 Role.banner, 150 Role.BANNER,
150 Role.complementary, 151 Role.COMPLEMENTARY,
151 Role.contentInfo, 152 Role.CONTENT_INFO,
152 Role.form, 153 Role.FORM,
153 Role.main, 154 Role.MAIN,
154 Role.navigation, 155 Role.NAVIGATION,
155 Role.region, 156 Role.REGION,
156 Role.search]); 157 Role.SEARCH]);
157 158
158 /** 159 /**
159 * @param {!AutomationNode} node 160 * @param {!AutomationNode} node
160 * @return {boolean} 161 * @return {boolean}
161 */ 162 */
162 AutomationPredicate.visitedLink = function(node) { 163 AutomationPredicate.visitedLink = function(node) {
163 return node.state.visited; 164 return node.state.visited;
164 }; 165 };
165 166
166 /** 167 /**
167 * @param {!AutomationNode} node 168 * @param {!AutomationNode} node
168 * @return {boolean} 169 * @return {boolean}
169 */ 170 */
170 AutomationPredicate.focused = function(node) { 171 AutomationPredicate.focused = function(node) {
171 return node.state.focused; 172 return node.state.focused;
172 }; 173 };
173 174
174 /** 175 /**
175 * @param {!AutomationNode} node 176 * @param {!AutomationNode} node
176 * @return {boolean} 177 * @return {boolean}
177 */ 178 */
178 AutomationPredicate.leaf = function(node) { 179 AutomationPredicate.leaf = function(node) {
179 return !node.firstChild || 180 return !node.firstChild ||
180 node.role == Role.button || 181 node.role == Role.BUTTON ||
181 node.role == Role.buttonDropDown || 182 node.role == Role.BUTTON_DROP_DOWN ||
182 node.role == Role.popUpButton || 183 node.role == Role.POP_UP_BUTTON ||
183 node.role == Role.slider || 184 node.role == Role.SLIDER ||
184 node.role == Role.textField || 185 node.role == Role.TEXT_FIELD ||
185 node.state.invisible || 186 node.state[State.INVISIBLE] ||
186 node.children.every(function(n) { 187 node.children.every(function(n) {
187 return n.state.invisible; 188 return n.state[State.INVISIBLE];
188 }); 189 });
189 }; 190 };
190 191
191 /** 192 /**
192 * @param {!AutomationNode} node 193 * @param {!AutomationNode} node
193 * @return {boolean} 194 * @return {boolean}
194 */ 195 */
195 AutomationPredicate.leafWithText = function(node) { 196 AutomationPredicate.leafWithText = function(node) {
196 return AutomationPredicate.leaf(node) && 197 return AutomationPredicate.leaf(node) &&
197 !!(node.name || node.value); 198 !!(node.name || node.value);
198 }; 199 };
199 200
200 /** 201 /**
201 * Matches against leaves or static text nodes. Useful when restricting 202 * Matches against leaves or static text nodes. Useful when restricting
202 * traversal to non-inline textboxes while still allowing them if navigation 203 * traversal to non-inline textboxes while still allowing them if navigation
203 * already entered into an inline textbox. 204 * already entered into an inline textbox.
204 * @param {!AutomationNode} node 205 * @param {!AutomationNode} node
205 * @return {boolean} 206 * @return {boolean}
206 */ 207 */
207 AutomationPredicate.leafOrStaticText = function(node) { 208 AutomationPredicate.leafOrStaticText = function(node) {
208 return AutomationPredicate.leaf(node) || 209 return AutomationPredicate.leaf(node) ||
209 node.role == Role.staticText; 210 node.role == Role.STATIC_TEXT;
210 }; 211 };
211 212
212 /** 213 /**
213 * Matches against nodes visited during object navigation. An object as 214 * Matches against nodes visited during object navigation. An object as
214 * defined below, are all nodes that are focusable or static text. When used in 215 * defined below, are all nodes that are focusable or static text. When used in
215 * tree walking, it should visit all nodes that tab traversal would as well as 216 * tree walking, it should visit all nodes that tab traversal would as well as
216 * non-focusable static text. 217 * non-focusable static text.
217 * @param {!AutomationNode} node 218 * @param {!AutomationNode} node
218 * @return {boolean} 219 * @return {boolean}
219 */ 220 */
220 AutomationPredicate.object = function(node) { 221 AutomationPredicate.object = function(node) {
221 // Editable nodes are within a text-like field and don't make sense when 222 // Editable nodes are within a text-like field and don't make sense when
222 // performing object navigation. Users should use line, word, or character 223 // performing object navigation. Users should use line, word, or character
223 // navigation. Only navigate to the top level node. 224 // navigation. Only navigate to the top level node.
224 if (node.parent && node.parent.state.editable) 225 if (node.parent && node.parent.state.editable)
225 return false; 226 return false;
226 227
227 // Descend into large nodes. 228 // Descend into large nodes.
228 if (node.name && node.name.length > constants.OBJECT_MAX_CHARCOUNT) 229 if (node.name && node.name.length > constants.OBJECT_MAX_CHARCOUNT)
229 return false; 230 return false;
230 231
231 return node.state.focusable || 232 return node.state.focusable ||
232 (AutomationPredicate.leafOrStaticText(node) && 233 (AutomationPredicate.leafOrStaticText(node) &&
233 (/\S+/.test(node.name) || 234 (/\S+/.test(node.name) ||
234 (node.role != Role.lineBreak && 235 (node.role != Role.LINE_BREAK &&
235 node.role != Role.staticText && 236 node.role != Role.STATIC_TEXT &&
236 node.role != Role.inlineTextBox))); 237 node.role != Role.INLINE_TEXT_BOX)));
237 }; 238 };
238 239
239 /** 240 /**
240 * Matches against nodes visited during group navigation. An object as 241 * Matches against nodes visited during group navigation. An object as
241 * @param {!AutomationNode} node 242 * @param {!AutomationNode} node
242 * @return {boolean} 243 * @return {boolean}
243 */ 244 */
244 AutomationPredicate.group = AutomationPredicate.match({ 245 AutomationPredicate.group = AutomationPredicate.match({
245 anyRole: [ 246 anyRole: [
246 Role.heading, 247 Role.HEADING,
247 Role.list, 248 Role.LIST,
248 Role.paragraph 249 Role.PARAGRAPH
249 ], 250 ],
250 anyPredicate: [ 251 anyPredicate: [
251 AutomationPredicate.editText, 252 AutomationPredicate.editText,
252 AutomationPredicate.formField, 253 AutomationPredicate.formField,
253 AutomationPredicate.object, 254 AutomationPredicate.object,
254 AutomationPredicate.table 255 AutomationPredicate.table
255 ] 256 ]
256 }); 257 });
257 258
258 /** 259 /**
(...skipping 11 matching lines...) Expand all
270 271
271 /** 272 /**
272 * Matches against a node that contains other interesting nodes. 273 * Matches against a node that contains other interesting nodes.
273 * These nodes should always have their subtrees scanned when navigating. 274 * These nodes should always have their subtrees scanned when navigating.
274 * @param {!AutomationNode} node 275 * @param {!AutomationNode} node
275 * @return {boolean} 276 * @return {boolean}
276 */ 277 */
277 AutomationPredicate.container = function(node) { 278 AutomationPredicate.container = function(node) {
278 return AutomationPredicate.match({ 279 return AutomationPredicate.match({
279 anyRole: [ 280 anyRole: [
280 Role.div, 281 Role.DIV,
281 Role.document, 282 Role.DOCUMENT,
282 Role.group, 283 Role.GROUP,
283 Role.listItem, 284 Role.LIST_ITEM,
284 Role.toolbar, 285 Role.TOOLBAR,
285 Role.window], 286 Role.WINDOW],
286 anyPredicate: [ 287 anyPredicate: [
287 AutomationPredicate.landmark, 288 AutomationPredicate.landmark,
288 AutomationPredicate.structuralContainer, 289 AutomationPredicate.structuralContainer,
289 function(node) { 290 function(node) {
290 // For example, crosh. 291 // For example, crosh.
291 return (node.role == Role.textField && node.state.readOnly); 292 return (node.role == Role.TEXT_FIELD && node.state.readOnly);
292 }, 293 },
293 function(node) { 294 function(node) {
294 return (node.state.editable && 295 return (node.state.editable &&
295 node.parent && 296 node.parent &&
296 !node.parent.state.editable); 297 !node.parent.state.editable);
297 }] 298 }]
298 })(node); 299 })(node);
299 }; 300 };
300 301
301 /** 302 /**
302 * Matches against nodes that contain interesting nodes, but should never be 303 * Matches against nodes that contain interesting nodes, but should never be
303 * visited. 304 * visited.
304 * @param {!AutomationNode} node 305 * @param {!AutomationNode} node
305 * @return {boolean} 306 * @return {boolean}
306 */ 307 */
307 AutomationPredicate.structuralContainer = AutomationPredicate.roles([ 308 AutomationPredicate.structuralContainer = AutomationPredicate.roles([
308 Role.alertDialog, 309 Role.ALERT_DIALOG,
309 Role.dialog, 310 Role.DIALOG,
310 Role.rootWebArea, 311 Role.ROOT_WEB_AREA,
311 Role.webView, 312 Role.WEB_VIEW,
312 Role.window, 313 Role.WINDOW,
313 Role.embeddedObject, 314 Role.EMBEDDED_OBJECT,
314 Role.iframe, 315 Role.IFRAME,
315 Role.iframePresentational]); 316 Role.IFRAME_PRESENTATIONAL]);
316 317
317 /** 318 /**
318 * Returns whether the given node should not be crossed when performing 319 * Returns whether the given node should not be crossed when performing
319 * traversals up the ancestry chain. 320 * traversals up the ancestry chain.
320 * @param {AutomationNode} node 321 * @param {AutomationNode} node
321 * @return {boolean} 322 * @return {boolean}
322 */ 323 */
323 AutomationPredicate.root = function(node) { 324 AutomationPredicate.root = function(node) {
324 switch (node.role) { 325 switch (node.role) {
325 case Role.window: 326 case Role.WINDOW:
326 return true; 327 return true;
327 case Role.dialog: 328 case Role.DIALOG:
328 // The below logic handles nested dialogs properly in the desktop tree 329 // The below logic handles nested dialogs properly in the desktop tree
329 // like that found in a bubble view. 330 // like that found in a bubble view.
330 return node.root.role != Role.desktop || 331 return node.root.role != Role.DESKTOP ||
331 (!!node.parent && 332 (!!node.parent &&
332 node.parent.role == Role.window && 333 node.parent.role == Role.WINDOW &&
333 node.parent.children.every(function(child) { 334 node.parent.children.every(function(child) {
334 return node.role == Role.window || node.role == Role.dialog; 335 return node.role == Role.WINDOW || node.role == Role.DIALOG;
335 })); 336 }));
336 case Role.toolbar: 337 case Role.TOOLBAR:
337 return node.root.role == Role.desktop; 338 return node.root.role == Role.DESKTOP;
338 case Role.rootWebArea: 339 case Role.ROOT_WEB_AREA:
339 return !node.parent || node.parent.root.role == Role.desktop; 340 return !node.parent || node.parent.root.role == Role.DESKTOP;
340 default: 341 default:
341 return false; 342 return false;
342 } 343 }
343 }; 344 };
344 345
345 /** 346 /**
346 * Nodes that should be ignored while traversing the automation tree. For 347 * Nodes that should be ignored while traversing the automation tree. For
347 * example, apply this predicate when moving to the next object. 348 * example, apply this predicate when moving to the next object.
348 * @param {!AutomationNode} node 349 * @param {!AutomationNode} node
349 * @return {boolean} 350 * @return {boolean}
350 */ 351 */
351 AutomationPredicate.shouldIgnoreNode = function(node) { 352 AutomationPredicate.shouldIgnoreNode = function(node) {
352 // Ignore invisible nodes. 353 // Ignore invisible nodes.
353 if (node.state.invisible || 354 if (node.state.invisible ||
354 (node.location.height == 0 && node.location.width == 0)) 355 (node.location.height == 0 && node.location.width == 0))
355 return true; 356 return true;
356 357
357 // Ignore structural containres. 358 // Ignore structural containres.
358 if (AutomationPredicate.structuralContainer(node)) 359 if (AutomationPredicate.structuralContainer(node))
359 return true; 360 return true;
360 361
361 // Ignore list markers since we already announce listitem role. 362 // Ignore list markers since we already announce listitem role.
362 if (node.role == Role.listMarker) 363 if (node.role == Role.LIST_MARKER)
363 return true; 364 return true;
364 365
365 // Don't ignore nodes with names or name-like attribute. 366 // Don't ignore nodes with names or name-like attribute.
366 if (node.name || node.value || node.description || node.url) 367 if (node.name || node.value || node.description || node.url)
367 return false; 368 return false;
368 369
369 // Ignore some roles. 370 // Ignore some roles.
370 return AutomationPredicate.leaf(node) && 371 return AutomationPredicate.leaf(node) &&
371 (AutomationPredicate.roles([Role.client, 372 (AutomationPredicate.roles([Role.CLIENT,
372 Role.column, 373 Role.COLUMN,
373 Role.div, 374 Role.DIV,
374 Role.group, 375 Role.GROUP,
375 Role.image, 376 Role.IMAGE,
376 Role.staticText, 377 Role.STATIC_TEXT,
377 Role.svgRoot, 378 Role.SVG_ROOT,
378 Role.tableHeaderContainer, 379 Role.TABLE_HEADER_CONTAINER,
379 Role.unknown 380 Role.UNKNOWN
380 ])(node)); 381 ])(node));
381 }; 382 };
382 383
383 /** 384 /**
384 * Returns if the node has a meaningful checked state. 385 * Returns if the node has a meaningful checked state.
385 * @param {!AutomationNode} node 386 * @param {!AutomationNode} node
386 * @return {boolean} 387 * @return {boolean}
387 */ 388 */
388 AutomationPredicate.checkable = AutomationPredicate.roles([ 389 AutomationPredicate.checkable = AutomationPredicate.roles([
389 Role.checkBox, 390 Role.CHECK_BOX,
390 Role.radioButton, 391 Role.RADIO_BUTTON,
391 Role.menuItemCheckBox, 392 Role.MENU_ITEM_CHECK_BOX,
392 Role.menuItemRadio, 393 Role.MENU_ITEM_RADIO,
393 Role.treeItem]); 394 Role.TREE_ITEM]);
394 395
395 // Table related predicates. 396 // Table related predicates.
396 /** 397 /**
397 * Returns if the node has a cell like role. 398 * Returns if the node has a cell like role.
398 * @param {!AutomationNode} node 399 * @param {!AutomationNode} node
399 * @return {boolean} 400 * @return {boolean}
400 */ 401 */
401 AutomationPredicate.cellLike = AutomationPredicate.roles([ 402 AutomationPredicate.cellLike = AutomationPredicate.roles([
402 Role.cell, 403 Role.CELL,
403 Role.rowHeader, 404 Role.ROW_HEADER,
404 Role.columnHeader]); 405 Role.COLUMN_HEADER]);
405 406
406 /** 407 /**
407 * Returns a predicate that will match against the directed next cell taking 408 * Returns a predicate that will match against the directed next cell taking
408 * into account the current ancestor cell's position in the table. 409 * into account the current ancestor cell's position in the table.
409 * @param {AutomationNode} start 410 * @param {AutomationNode} start
410 * @param {{dir: (Dir|undefined), 411 * @param {{dir: (Dir|undefined),
411 * row: (boolean|undefined), 412 * row: (boolean|undefined),
412 * col: (boolean|undefined)}} opts 413 * col: (boolean|undefined)}} opts
413 * |dir|, specifies direction for |row or/and |col| movement by one cell. 414 * |dir|, specifies direction for |row or/and |col| movement by one cell.
414 * |dir| defaults to forward. 415 * |dir| defaults to forward.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 }; 475 };
475 476
476 /** 477 /**
477 * Returns a predicate that will match against a heading with a specific 478 * Returns a predicate that will match against a heading with a specific
478 * hierarchical level. 479 * hierarchical level.
479 * @param {number} level 1-6 480 * @param {number} level 1-6
480 * @return {AutomationPredicate.Unary} 481 * @return {AutomationPredicate.Unary}
481 */ 482 */
482 AutomationPredicate.makeHeadingPredicate = function(level) { 483 AutomationPredicate.makeHeadingPredicate = function(level) {
483 return function(node) { 484 return function(node) {
484 return node.role == Role.heading && node.hierarchicalLevel == level; 485 return node.role == Role.HEADING && node.hierarchicalLevel == level;
485 }; 486 };
486 }; 487 };
487 488
488 }); // goog.scope 489 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698