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

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

Issue 2939273002: DO NOT SUBMIT: what chrome/browser/resources/ could eventually look like with clang-format (Closed)
Patch Set: Created 3 years, 6 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 Provides output services for ChromeVox. 6 * @fileoverview Provides output services for ChromeVox.
7 */ 7 */
8 8
9 goog.provide('Output'); 9 goog.provide('Output');
10 goog.provide('Output.EventType'); 10 goog.provide('Output.EventType');
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 * earconId: (string|undefined), 108 * earconId: (string|undefined),
109 * inherits: (string|undefined), 109 * inherits: (string|undefined),
110 * outputContextFirst: (boolean|undefined)}>} 110 * outputContextFirst: (boolean|undefined)}>}
111 * msgId: the message id of the role. 111 * msgId: the message id of the role.
112 * earconId: an optional earcon to play when encountering the role. 112 * earconId: an optional earcon to play when encountering the role.
113 * inherits: inherits rules from this role. 113 * inherits: inherits rules from this role.
114 * outputContextFirst: where to place the context output. 114 * outputContextFirst: where to place the context output.
115 * @private 115 * @private
116 */ 116 */
117 Output.ROLE_INFO_ = { 117 Output.ROLE_INFO_ = {
118 alert: { 118 alert: {msgId: 'role_alert'},
119 msgId: 'role_alert' 119 alertDialog: {msgId: 'role_alertdialog', outputContextFirst: true},
120 }, 120 article: {msgId: 'role_article', inherits: 'abstractContainer'},
121 alertDialog: { 121 application: {msgId: 'role_application', inherits: 'abstractContainer'},
122 msgId: 'role_alertdialog', 122 banner: {msgId: 'role_banner', inherits: 'abstractContainer'},
123 outputContextFirst: true 123 button: {msgId: 'role_button', earconId: 'BUTTON'},
124 }, 124 buttonDropDown: {msgId: 'role_button', earconId: 'BUTTON'},
125 article: { 125 checkBox: {msgId: 'role_checkbox'},
126 msgId: 'role_article', 126 columnHeader: {msgId: 'role_columnheader', inherits: 'cell'},
127 inherits: 'abstractContainer' 127 comboBox: {msgId: 'role_combobox', earconId: 'LISTBOX'},
128 }, 128 complementary: {msgId: 'role_complementary', inherits: 'abstractContainer'},
129 application: { 129 contentInfo: {msgId: 'role_contentinfo', inherits: 'abstractContainer'},
130 msgId: 'role_application', 130 date: {msgId: 'input_type_date', inherits: 'abstractContainer'},
131 inherits: 'abstractContainer' 131 definition: {msgId: 'role_definition', inherits: 'abstractContainer'},
132 }, 132 dialog: {msgId: 'role_dialog', outputContextFirst: true},
133 banner: { 133 directory: {msgId: 'role_directory', inherits: 'abstractContainer'},
134 msgId: 'role_banner', 134 document: {msgId: 'role_document', inherits: 'abstractContainer'},
135 inherits: 'abstractContainer' 135 form: {msgId: 'role_form', inherits: 'abstractContainer'},
136 }, 136 grid: {msgId: 'role_grid'},
137 button: { 137 group: {msgId: 'role_group', inherits: 'abstractContainer'},
138 msgId: 'role_button',
139 earconId: 'BUTTON'
140 },
141 buttonDropDown: {
142 msgId: 'role_button',
143 earconId: 'BUTTON'
144 },
145 checkBox: {
146 msgId: 'role_checkbox'
147 },
148 columnHeader: {
149 msgId: 'role_columnheader',
150 inherits: 'cell'
151 },
152 comboBox: {
153 msgId: 'role_combobox',
154 earconId: 'LISTBOX'
155 },
156 complementary: {
157 msgId: 'role_complementary',
158 inherits: 'abstractContainer'
159 },
160 contentInfo: {
161 msgId: 'role_contentinfo',
162 inherits: 'abstractContainer'
163 },
164 date: {
165 msgId: 'input_type_date',
166 inherits: 'abstractContainer'
167 },
168 definition: {
169 msgId: 'role_definition',
170 inherits: 'abstractContainer'
171 },
172 dialog: {
173 msgId: 'role_dialog',
174 outputContextFirst: true
175 },
176 directory: {
177 msgId: 'role_directory',
178 inherits: 'abstractContainer'
179 },
180 document: {
181 msgId: 'role_document',
182 inherits: 'abstractContainer'
183 },
184 form: {
185 msgId: 'role_form',
186 inherits: 'abstractContainer'
187 },
188 grid: {
189 msgId: 'role_grid'
190 },
191 group: {
192 msgId: 'role_group',
193 inherits: 'abstractContainer'
194 },
195 heading: { 138 heading: {
196 msgId: 'role_heading', 139 msgId: 'role_heading',
197 }, 140 },
198 image: { 141 image: {
199 msgId: 'role_img', 142 msgId: 'role_img',
200 }, 143 },
201 inputTime: { 144 inputTime: {msgId: 'input_type_time', inherits: 'abstractContainer'},
202 msgId: 'input_type_time', 145 link: {msgId: 'role_link', earconId: 'LINK'},
203 inherits: 'abstractContainer' 146 listBox: {msgId: 'role_listbox', earconId: 'LISTBOX'},
204 }, 147 listBoxOption: {msgId: 'role_listitem', earconId: 'LIST_ITEM'},
205 link: { 148 listItem: {msgId: 'role_listitem', earconId: 'LIST_ITEM'},
206 msgId: 'role_link',
207 earconId: 'LINK'
208 },
209 listBox: {
210 msgId: 'role_listbox',
211 earconId: 'LISTBOX'
212 },
213 listBoxOption: {
214 msgId: 'role_listitem',
215 earconId: 'LIST_ITEM'
216 },
217 listItem: {
218 msgId: 'role_listitem',
219 earconId: 'LIST_ITEM'
220 },
221 log: { 149 log: {
222 msgId: 'role_log', 150 msgId: 'role_log',
223 }, 151 },
224 main: { 152 main: {msgId: 'role_main', inherits: 'abstractContainer'},
225 msgId: 'role_main',
226 inherits: 'abstractContainer'
227 },
228 marquee: { 153 marquee: {
229 msgId: 'role_marquee', 154 msgId: 'role_marquee',
230 }, 155 },
231 math: { 156 math: {msgId: 'role_math', inherits: 'abstractContainer'},
232 msgId: 'role_math', 157 menu: {msgId: 'role_menu', outputContextFirst: true},
233 inherits: 'abstractContainer'
234 },
235 menu: {
236 msgId: 'role_menu',
237 outputContextFirst: true
238 },
239 menuBar: { 158 menuBar: {
240 msgId: 'role_menubar', 159 msgId: 'role_menubar',
241 }, 160 },
242 menuItem: { 161 menuItem: {msgId: 'role_menuitem'},
243 msgId: 'role_menuitem' 162 menuItemCheckBox: {msgId: 'role_menuitemcheckbox'},
244 }, 163 menuItemRadio: {msgId: 'role_menuitemradio'},
245 menuItemCheckBox: { 164 menuListOption: {msgId: 'role_menuitem'},
246 msgId: 'role_menuitemcheckbox' 165 menuListPopup: {msgId: 'role_menu'},
247 }, 166 meter: {msgId: 'role_meter', inherits: 'abstractRange'},
248 menuItemRadio: { 167 navigation: {msgId: 'role_navigation', inherits: 'abstractContainer'},
249 msgId: 'role_menuitemradio' 168 note: {msgId: 'role_note', inherits: 'abstractContainer'},
250 }, 169 progressIndicator:
251 menuListOption: { 170 {msgId: 'role_progress_indicator', inherits: 'abstractRange'},
252 msgId: 'role_menuitem' 171 popUpButton: {msgId: 'role_button', earconId: 'POP_UP_BUTTON'},
253 }, 172 radioButton: {msgId: 'role_radio'},
254 menuListPopup: {
255 msgId: 'role_menu'
256 },
257 meter: {
258 msgId: 'role_meter',
259 inherits: 'abstractRange'
260 },
261 navigation: {
262 msgId: 'role_navigation',
263 inherits: 'abstractContainer'
264 },
265 note: {
266 msgId: 'role_note',
267 inherits: 'abstractContainer'
268 },
269 progressIndicator: {
270 msgId: 'role_progress_indicator',
271 inherits: 'abstractRange'
272 },
273 popUpButton: {
274 msgId: 'role_button',
275 earconId: 'POP_UP_BUTTON'
276 },
277 radioButton: {
278 msgId: 'role_radio'
279 },
280 radioGroup: { 173 radioGroup: {
281 msgId: 'role_radiogroup', 174 msgId: 'role_radiogroup',
282 }, 175 },
283 rootWebArea: { 176 rootWebArea: {outputContextFirst: true},
284 outputContextFirst: true 177 row: {msgId: 'role_row', inherits: 'abstractContainer'},
285 }, 178 rowHeader: {msgId: 'role_rowheader', inherits: 'cell'},
286 row: { 179 scrollBar: {msgId: 'role_scrollbar', inherits: 'abstractRange'},
287 msgId: 'role_row', 180 search: {msgId: 'role_search', inherits: 'abstractContainer'},
288 inherits: 'abstractContainer' 181 separator: {msgId: 'role_separator', inherits: 'abstractContainer'},
289 }, 182 slider: {msgId: 'role_slider', inherits: 'abstractRange', earconId: 'SLIDER'},
290 rowHeader: {
291 msgId: 'role_rowheader',
292 inherits: 'cell'
293 },
294 scrollBar: {
295 msgId: 'role_scrollbar',
296 inherits: 'abstractRange'
297 },
298 search: {
299 msgId: 'role_search',
300 inherits: 'abstractContainer'
301 },
302 separator: {
303 msgId: 'role_separator',
304 inherits: 'abstractContainer'
305 },
306 slider: {
307 msgId: 'role_slider',
308 inherits: 'abstractRange',
309 earconId: 'SLIDER'
310 },
311 spinButton: { 183 spinButton: {
312 msgId: 'role_spinbutton', 184 msgId: 'role_spinbutton',
313 inherits: 'abstractRange', 185 inherits: 'abstractRange',
314 earconId: 'LISTBOX' 186 earconId: 'LISTBOX'
315 }, 187 },
316 status: { 188 status: {msgId: 'role_status'},
317 msgId: 'role_status' 189 tab: {msgId: 'role_tab'},
318 }, 190 tabList: {msgId: 'role_tablist'},
319 tab: { 191 tabPanel: {msgId: 'role_tabpanel'},
320 msgId: 'role_tab' 192 textBox: {msgId: 'input_type_text', earconId: 'EDITABLE_TEXT'},
321 }, 193 textField: {msgId: 'input_type_text', earconId: 'EDITABLE_TEXT'},
322 tabList: { 194 time: {msgId: 'tag_time', inherits: 'abstractContainer'},
323 msgId: 'role_tablist' 195 timer: {msgId: 'role_timer'},
324 }, 196 toolbar: {msgId: 'role_toolbar'},
325 tabPanel: { 197 toggleButton: {msgId: 'role_button', inherits: 'checkBox'},
326 msgId: 'role_tabpanel' 198 tree: {msgId: 'role_tree'},
327 }, 199 treeItem: {msgId: 'role_treeitem'}
328 textBox: {
329 msgId: 'input_type_text',
330 earconId: 'EDITABLE_TEXT'
331 },
332 textField: {
333 msgId: 'input_type_text',
334 earconId: 'EDITABLE_TEXT'
335 },
336 time: {
337 msgId: 'tag_time',
338 inherits: 'abstractContainer'
339 },
340 timer: {
341 msgId: 'role_timer'
342 },
343 toolbar: {
344 msgId: 'role_toolbar'
345 },
346 toggleButton: {
347 msgId: 'role_button',
348 inherits: 'checkBox'
349 },
350 tree: {
351 msgId: 'role_tree'
352 },
353 treeItem: {
354 msgId: 'role_treeitem'
355 }
356 }; 200 };
357 201
358 /** 202 /**
359 * Metadata about supported automation states. 203 * Metadata about supported automation states.
360 * @const {!Object<string, {on: {msgId: string, earconId: string}, 204 * @const {!Object<string, {on: {msgId: string, earconId: string},
361 * off: {msgId: string, earconId: string}, 205 * off: {msgId: string, earconId: string},
362 * isRoleSpecific: (boolean|undefined)}>} 206 * isRoleSpecific: (boolean|undefined)}>}
363 * on: info used to describe a state that is set to true. 207 * on: info used to describe a state that is set to true.
364 * off: info used to describe a state that is set to undefined. 208 * off: info used to describe a state that is set to undefined.
365 * isRoleSpecific: info used for specific roles. 209 * isRoleSpecific: info used for specific roles.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 'false': 'aria_pressed_false', 257 'false': 'aria_pressed_false',
414 'mixed': 'aria_pressed_mixed' 258 'mixed': 'aria_pressed_mixed'
415 }; 259 };
416 260
417 /** 261 /**
418 * Rules specifying format of AutomationNodes for output. 262 * Rules specifying format of AutomationNodes for output.
419 * @type {!Object<Object<Object<string>>>} 263 * @type {!Object<Object<Object<string>>>}
420 */ 264 */
421 Output.RULES = { 265 Output.RULES = {
422 navigate: { 266 navigate: {
423 'default': { 267 'default': {speak: '$name $value $state $role $description', braille: ''},
424 speak: '$name $value $state $role $description',
425 braille: ''
426 },
427 abstractContainer: { 268 abstractContainer: {
428 enter: '$nameFromNode $role $state $description', 269 enter: '$nameFromNode $role $state $description',
429 leave: '@exited_container($role)' 270 leave: '@exited_container($role)'
430 }, 271 },
431 abstractRange: { 272 abstractRange: {
432 speak: 273 speak: '$if($valueForRange, $valueForRange, $value) ' +
433 '$if($valueForRange, $valueForRange, $value) ' +
434 '$if($minValueForRange, @aria_value_min($minValueForRange)) ' + 274 '$if($minValueForRange, @aria_value_min($minValueForRange)) ' +
435 '$if($maxValueForRange, @aria_value_max($maxValueForRange)) ' + 275 '$if($maxValueForRange, @aria_value_max($maxValueForRange)) ' +
436 '$name $role $description $state' 276 '$name $role $description $state'
437 }, 277 },
438 alert: { 278 alert: {
439 enter: '$name $role $state', 279 enter: '$name $role $state',
440 speak: '$earcon(ALERT_NONMODAL) $role $nameOrTextContent $state' 280 speak: '$earcon(ALERT_NONMODAL) $role $nameOrTextContent $state'
441 }, 281 },
442 alertDialog: { 282 alertDialog: {
443 enter: '$earcon(ALERT_MODAL) $name $state', 283 enter: '$earcon(ALERT_MODAL) $name $state',
444 speak: '$earcon(ALERT_MODAL) $name $nameOrTextContent $state $role' 284 speak: '$earcon(ALERT_MODAL) $name $nameOrTextContent $state $role'
445 }, 285 },
446 cell: { 286 cell: {
447 enter: '@cell_summary($if($ariaCellRowIndex, $ariaCellRowIndex, ' + 287 enter: '@cell_summary($if($ariaCellRowIndex, $ariaCellRowIndex, ' +
448 '$tableCellRowIndex), ' + 288 '$tableCellRowIndex), ' +
449 '$if($ariaCellColumnIndex, $ariaCellColumnIndex, ' + 289 '$if($ariaCellColumnIndex, $ariaCellColumnIndex, ' +
450 '$tableCellColumnIndex)) $node(tableColumnHeader)', 290 '$tableCellColumnIndex)) $node(tableColumnHeader)',
451 speak: '$name @cell_summary($if($ariaCellRowIndex, $ariaCellRowIndex, ' + 291 speak: '$name @cell_summary($if($ariaCellRowIndex, $ariaCellRowIndex, ' +
452 '$tableCellRowIndex), ' + 292 '$tableCellRowIndex), ' +
453 '$if($ariaCellColumnIndex, $ariaCellColumnIndex, ' + 293 '$if($ariaCellColumnIndex, $ariaCellColumnIndex, ' +
454 '$tableCellColumnIndex)) $node(tableColumnHeader) $state' 294 '$tableCellColumnIndex)) $node(tableColumnHeader) $state'
455 }, 295 },
456 checkBox: { 296 checkBox: {
457 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' + 297 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
458 '$name $role $checked $description $state' 298 '$name $role $checked $description $state'
459 }, 299 },
460 client: { 300 client: {speak: '$name'},
461 speak: '$name' 301 date: {enter: '$nameFromNode $role $description'},
462 }, 302 dialog: {enter: '$nameFromNode $role $description'},
463 date: { 303 genericContainer:
464 enter: '$nameFromNode $role $description' 304 {enter: '$nameFromNode', speak: '$nameOrTextContent $description'},
465 }, 305 embeddedObject: {speak: '$name'},
466 dialog: { 306 grid: {enter: '$nameFromNode $role $description'},
467 enter: '$nameFromNode $role $description'
468 },
469 genericContainer: {
470 enter: '$nameFromNode',
471 speak: '$nameOrTextContent $description'
472 },
473 embeddedObject: {
474 speak: '$name'
475 },
476 grid: {
477 enter: '$nameFromNode $role $description'
478 },
479 group: { 307 group: {
480 enter: '$nameFromNode $state $description', 308 enter: '$nameFromNode $state $description',
481 speak: '$nameOrDescendants $value $state $description', 309 speak: '$nameOrDescendants $value $state $description',
482 leave: '' 310 leave: ''
483 }, 311 },
484 heading: { 312 heading: {
485 enter: '!relativePitch(hierarchicalLevel) ' + 313 enter: '!relativePitch(hierarchicalLevel) ' +
486 '$nameFromNode= ' + 314 '$nameFromNode= ' +
487 '$if($hierarchicalLevel, @tag_h+$hierarchicalLevel, $role) $state', 315 '$if($hierarchicalLevel, @tag_h+$hierarchicalLevel, $role) $state',
488 speak: '!relativePitch(hierarchicalLevel) ' + 316 speak: '!relativePitch(hierarchicalLevel) ' +
489 '$nameOrDescendants= ' + 317 '$nameOrDescendants= ' +
490 '$if($hierarchicalLevel, @tag_h+$hierarchicalLevel, $role) $state' 318 '$if($hierarchicalLevel, @tag_h+$hierarchicalLevel, $role) $state'
491 }, 319 },
492 image: { 320 image: {
493 speak: '$if($name, $name, $urlFilename) ' + 321 speak: '$if($name, $name, $urlFilename) ' +
494 '$value $state $role $description', 322 '$value $state $role $description',
495 }, 323 },
496 inlineTextBox: { 324 inlineTextBox: {speak: '$name='},
497 speak: '$name=' 325 inputTime: {enter: '$nameFromNode $role $description'},
498 },
499 inputTime: {
500 enter: '$nameFromNode $role $description'
501 },
502 link: { 326 link: {
503 enter: '$nameFromNode= $role $state', 327 enter: '$nameFromNode= $role $state',
504 speak: '$name $value $state ' + 328 speak: '$name $value $state ' +
505 '$if($inPageLinkTarget, @internal_link, $role) $description', 329 '$if($inPageLinkTarget, @internal_link, $role) $description',
506 }, 330 },
507 list: { 331 list: {
508 enter: '$role @@list_with_items($countChildren(listItem))', 332 enter: '$role @@list_with_items($countChildren(listItem))',
509 speak: '$descendants $role @@list_with_items($countChildren(listItem))' 333 speak: '$descendants $role @@list_with_items($countChildren(listItem))'
510 }, 334 },
511 listBox: { 335 listBox: {
(...skipping 26 matching lines...) Expand all
538 menuItemRadio: { 362 menuItemRadio: {
539 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' + 363 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
540 '$if($checked, @describe_radio_selected($name), ' + 364 '$if($checked, @describe_radio_selected($name), ' +
541 '@describe_radio_unselected($name)) $description ' + 365 '@describe_radio_unselected($name)) $description ' +
542 '@describe_index($indexInParent, $parentChildCount) ' 366 '@describe_index($indexInParent, $parentChildCount) '
543 }, 367 },
544 menuListOption: { 368 menuListOption: {
545 speak: '$name @role_menuitem ' + 369 speak: '$name @role_menuitem ' +
546 '@describe_index($indexInParent, $parentChildCount) $description' 370 '@describe_index($indexInParent, $parentChildCount) $description'
547 }, 371 },
548 paragraph: { 372 paragraph: {speak: '$descendants'},
549 speak: '$descendants'
550 },
551 popUpButton: { 373 popUpButton: {
552 speak: '$value $name $role @aria_has_popup ' + 374 speak: '$value $name $role @aria_has_popup ' +
553 '$state $description' 375 '$state $description'
554 }, 376 },
555 radioButton: { 377 radioButton: {
556 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' + 378 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
557 '$if($checked, @describe_radio_selected($name), ' + 379 '$if($checked, @describe_radio_selected($name), ' +
558 '@describe_radio_unselected($name)) $description' 380 '@describe_radio_unselected($name)) $description'
559 }, 381 },
560 radioGroup: { 382 radioGroup: {enter: '$name $role $description'},
561 enter: '$name $role $description' 383 rootWebArea: {enter: '$name', speak: '$if($name, $name, $docUrl)'},
562 }, 384 region: {speak: '$nameOrTextContent'},
563 rootWebArea: { 385 row: {enter: '$node(tableRowHeader)'},
564 enter: '$name', 386 rowHeader: {speak: '$nameOrTextContent $state'},
565 speak: '$if($name, $name, $docUrl)' 387 staticText: {speak: '$name='},
566 },
567 region: {
568 speak: '$nameOrTextContent'
569 },
570 row: {
571 enter: '$node(tableRowHeader)'
572 },
573 rowHeader: {
574 speak: '$nameOrTextContent $state'
575 },
576 staticText: {
577 speak: '$name='
578 },
579 switch: { 388 switch: {
580 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' + 389 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
581 '$if($checked, @describe_switch_on($name), ' + 390 '$if($checked, @describe_switch_on($name), ' +
582 '@describe_switch_off($name)) $description $state' 391 '@describe_switch_off($name)) $description $state'
583 }, 392 },
584 tab: { 393 tab: {
585 speak: '@describe_tab($name) $state $description ' + 394 speak: '@describe_tab($name) $state $description ' +
586 '$if($setSize, @describe_index($posInSet, $setSize))', 395 '$if($setSize, @describe_index($posInSet, $setSize))',
587 }, 396 },
588 table: { 397 table: {
589 enter: '@table_summary($name, ' + 398 enter: '@table_summary($name, ' +
590 '$if($ariaRowCount, $ariaRowCount, $tableRowCount), ' + 399 '$if($ariaRowCount, $ariaRowCount, $tableRowCount), ' +
591 '$if($ariaColumnCount, $ariaColumnCount, $tableColumnCount)) ' + 400 '$if($ariaColumnCount, $ariaColumnCount, $tableColumnCount)) ' +
592 '$node(tableHeader)' 401 '$node(tableHeader)'
593 }, 402 },
594 tableHeaderContainer: { 403 tableHeaderContainer: {speak: '$nameOrTextContent $state $description'},
595 speak: '$nameOrTextContent $state $description'
596 },
597 textField: { 404 textField: {
598 speak: '$name $value $if($multiline, @tag_textarea, $if(' + 405 speak: '$name $value $if($multiline, @tag_textarea, $if(' +
599 '$inputType, $inputType, $role)) $description $state', 406 '$inputType, $inputType, $role)) $description $state',
600 braille: '' 407 braille: ''
601 }, 408 },
602 timer: { 409 timer: {speak: '$nameFromNode $descendants $value $state $description'},
603 speak: '$nameFromNode $descendants $value $state $description'
604 },
605 toggleButton: { 410 toggleButton: {
606 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' + 411 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
607 '$name $role $pressed $description $state' 412 '$name $role $pressed $description $state'
608 }, 413 },
609 toolbar: { 414 toolbar: {enter: '$name $role $description'},
610 enter: '$name $role $description' 415 tree: {enter: '$name $role @@list_with_items($countChildren(treeItem))'},
611 },
612 tree: {
613 enter: '$name $role @@list_with_items($countChildren(treeItem))'
614 },
615 treeItem: { 416 treeItem: {
616 enter: '$role $expanded $collapsed ' + 417 enter: '$role $expanded $collapsed ' +
617 '@describe_index($indexInParent, $parentChildCount) ' + 418 '@describe_index($indexInParent, $parentChildCount) ' +
618 '@describe_depth($hierarchicalLevel)', 419 '@describe_depth($hierarchicalLevel)',
619 speak: '$name ' + 420 speak: '$name ' +
620 '$role $state ' + 421 '$role $state ' +
621 '@describe_index($indexInParent, $parentChildCount) ' + 422 '@describe_index($indexInParent, $parentChildCount) ' +
622 '@describe_depth($hierarchicalLevel)' 423 '@describe_depth($hierarchicalLevel)'
623 }, 424 },
624 window: { 425 window: {
625 enter: '@describe_window($name)', 426 enter: '@describe_window($name)',
626 speak: '@describe_window($name) $earcon(OBJECT_OPEN)' 427 speak: '@describe_window($name) $earcon(OBJECT_OPEN)'
627 } 428 }
628 }, 429 },
629 menuStart: { 430 menuStart:
630 'default': { 431 {'default': {speak: '@chrome_menu_opened($name) $earcon(OBJECT_OPEN)'}},
631 speak: '@chrome_menu_opened($name) $earcon(OBJECT_OPEN)' 432 menuEnd: {'default': {speak: '@chrome_menu_closed $earcon(OBJECT_CLOSE)'}},
632 }
633 },
634 menuEnd: {
635 'default': {
636 speak: '@chrome_menu_closed $earcon(OBJECT_CLOSE)'
637 }
638 },
639 menuListValueChanged: { 433 menuListValueChanged: {
640 'default': { 434 'default': {
641 speak: '$value $name ' + 435 speak: '$value $name ' +
642 '$find({"state": {"selected": true, "invisible": false}}, ' + 436 '$find({"state": {"selected": true, "invisible": false}}, ' +
643 '@describe_index($indexInParent, $parentChildCount)) ' 437 '@describe_index($indexInParent, $parentChildCount)) '
644 } 438 }
645 }, 439 },
646 alert: { 440 alert: {
647 default: { 441 default: {
648 speak: '$earcon(ALERT_NONMODAL) @role_alert ' + 442 speak: '$earcon(ALERT_NONMODAL) @role_alert ' +
649 '$nameOrTextContent $description' 443 '$nameOrTextContent $description'
650 } 444 }
651 } 445 }
652 }; 446 };
653 447
654 /** 448 /**
655 * Used to annotate utterances with speech properties. 449 * Used to annotate utterances with speech properties.
656 * @constructor 450 * @constructor
657 */ 451 */
658 Output.SpeechProperties = function() {}; 452 Output.SpeechProperties = function() {};
659 453
660 /** 454 /**
661 * Custom actions performed while rendering an output string. 455 * Custom actions performed while rendering an output string.
662 * @constructor 456 * @constructor
663 */ 457 */
664 Output.Action = function() { 458 Output.Action = function() {};
665 };
666 459
667 Output.Action.prototype = { 460 Output.Action.prototype = {
668 run: function() { 461 run: function() {}
669 }
670 }; 462 };
671 463
672 /** 464 /**
673 * Action to play an earcon. 465 * Action to play an earcon.
674 * @param {string} earconId 466 * @param {string} earconId
675 * @param {chrome.automation.Rect=} opt_location 467 * @param {chrome.automation.Rect=} opt_location
676 * @constructor 468 * @constructor
677 * @extends {Output.Action} 469 * @extends {Output.Action}
678 */ 470 */
679 Output.EarconAction = function(earconId, opt_location) { 471 Output.EarconAction = function(earconId, opt_location) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 * queueing mode. 527 * queueing mode.
736 * @type {cvox.QueueMode|undefined} 528 * @type {cvox.QueueMode|undefined}
737 * @private 529 * @private
738 */ 530 */
739 Output.forceModeForNextSpeechUtterance_; 531 Output.forceModeForNextSpeechUtterance_;
740 532
741 /** 533 /**
742 * Calling this will make the next speech utterance use |mode| even if it would 534 * Calling this will make the next speech utterance use |mode| even if it would
743 * normally queue or do a category flush. This differs from the |withQueueMode| 535 * normally queue or do a category flush. This differs from the |withQueueMode|
744 * instance method as it can apply to future output. 536 * instance method as it can apply to future output.
745 * @param {cvox.QueueMode} mode 537 * @param {cvox.QueueMode} mode
746 */ 538 */
747 Output.forceModeForNextSpeechUtterance = function(mode) { 539 Output.forceModeForNextSpeechUtterance = function(mode) {
748 Output.forceModeForNextSpeechUtterance_ = mode; 540 Output.forceModeForNextSpeechUtterance_ = mode;
749 }; 541 };
750 542
751 /** 543 /**
752 * For a given automation property, return true if the value 544 * For a given automation property, return true if the value
753 * represents something 'truthy', e.g.: for checked: 545 * represents something 'truthy', e.g.: for checked:
754 * 'true'|'mixed' -> true 546 * 'true'|'mixed' -> true
755 * 'false'|undefined -> false 547 * 'false'|undefined -> false
756 */ 548 */
757 Output.isTruthy = function(node, attrib) { 549 Output.isTruthy = function(node, attrib) {
758 switch(attrib) { 550 switch (attrib) {
759 case 'checked': 551 case 'checked':
760 return node.checked && node.checked !== 'false'; 552 return node.checked && node.checked !== 'false';
761 default: 553 default:
762 return node[attrib] !== undefined || node.state[attrib]; 554 return node[attrib] !== undefined || node.state[attrib];
763 } 555 }
764 }; 556 };
765 557
766 Output.prototype = { 558 Output.prototype = {
767 /** 559 /**
768 * @return {boolean} True if there's any speech that will be output. 560 * @return {boolean} True if there's any speech that will be output.
(...skipping 12 matching lines...) Expand all
781 * @param {cursors.Range} prevRange 573 * @param {cursors.Range} prevRange
782 * @param {EventType|Output.EventType} type 574 * @param {EventType|Output.EventType} type
783 * @return {!Output} 575 * @return {!Output}
784 */ 576 */
785 withSpeech: function(range, prevRange, type) { 577 withSpeech: function(range, prevRange, type) {
786 this.formatOptions_ = {speech: true, braille: false, auralStyle: false}; 578 this.formatOptions_ = {speech: true, braille: false, auralStyle: false};
787 this.render_(range, prevRange, type, this.speechBuffer_); 579 this.render_(range, prevRange, type, this.speechBuffer_);
788 return this; 580 return this;
789 }, 581 },
790 582
791 /** 583 /**
792 * Specify ranges for aurally styled speech. 584 * Specify ranges for aurally styled speech.
793 * @param {!cursors.Range} range 585 * @param {!cursors.Range} range
794 * @param {cursors.Range} prevRange 586 * @param {cursors.Range} prevRange
795 * @param {EventType|Output.EventType} type 587 * @param {EventType|Output.EventType} type
796 * @return {!Output} 588 * @return {!Output}
797 */ 589 */
798 withRichSpeech: function(range, prevRange, type) { 590 withRichSpeech: function(range, prevRange, type) {
799 this.formatOptions_ = {speech: true, braille: false, auralStyle: true}; 591 this.formatOptions_ = {speech: true, braille: false, auralStyle: true};
800 this.render_(range, prevRange, type, this.speechBuffer_); 592 this.render_(range, prevRange, type, this.speechBuffer_);
801 return this; 593 return this;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 * @param {cursors.Range} prevRange 625 * @param {cursors.Range} prevRange
834 * @param {EventType|Output.EventType} type 626 * @param {EventType|Output.EventType} type
835 * @return {!Output} 627 * @return {!Output}
836 */ 628 */
837 withSpeechAndBraille: function(range, prevRange, type) { 629 withSpeechAndBraille: function(range, prevRange, type) {
838 this.withSpeech(range, prevRange, type); 630 this.withSpeech(range, prevRange, type);
839 this.withBraille(range, prevRange, type); 631 this.withBraille(range, prevRange, type);
840 return this; 632 return this;
841 }, 633 },
842 634
843 /** 635 /**
844 * Specify the same ranges for aurally styled speech and braille. 636 * Specify the same ranges for aurally styled speech and braille.
845 * @param {!cursors.Range} range 637 * @param {!cursors.Range} range
846 * @param {cursors.Range} prevRange 638 * @param {cursors.Range} prevRange
847 * @param {EventType|Output.EventType} type 639 * @param {EventType|Output.EventType} type
848 * @return {!Output} 640 * @return {!Output}
849 */ 641 */
850 withRichSpeechAndBraille: function(range, prevRange, type) { 642 withRichSpeechAndBraille: function(range, prevRange, type) {
851 this.withRichSpeech(range, prevRange, type); 643 this.withRichSpeech(range, prevRange, type);
852 this.withBraille(range, prevRange, type); 644 this.withBraille(range, prevRange, type);
853 return this; 645 return this;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 688
897 /** 689 /**
898 * Apply a format string directly to the output buffer. This lets you 690 * Apply a format string directly to the output buffer. This lets you
899 * output a message directly to the buffer using the format syntax. 691 * output a message directly to the buffer using the format syntax.
900 * @param {string} formatStr 692 * @param {string} formatStr
901 * @param {!AutomationNode=} opt_node An optional node to apply the 693 * @param {!AutomationNode=} opt_node An optional node to apply the
902 * formatting to. 694 * formatting to.
903 * @return {!Output} |this| for chaining 695 * @return {!Output} |this| for chaining
904 */ 696 */
905 format: function(formatStr, opt_node) { 697 format: function(formatStr, opt_node) {
906 return this 698 return this.formatForSpeech(formatStr, opt_node)
907 .formatForSpeech(formatStr, opt_node)
908 .formatForBraille(formatStr, opt_node); 699 .formatForBraille(formatStr, opt_node);
909 }, 700 },
910 701
911 /** 702 /**
912 * Apply a format string directly to the speech output buffer. This lets you 703 * Apply a format string directly to the speech output buffer. This lets you
913 * output a message directly to the buffer using the format syntax. 704 * output a message directly to the buffer using the format syntax.
914 * @param {string} formatStr 705 * @param {string} formatStr
915 * @param {!AutomationNode=} opt_node An optional node to apply the 706 * @param {!AutomationNode=} opt_node An optional node to apply the
916 * formatting to. 707 * formatting to.
917 * @return {!Output} |this| for chaining 708 * @return {!Output} |this| for chaining
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 if (Output.forceModeForNextSpeechUtterance_ !== undefined) 754 if (Output.forceModeForNextSpeechUtterance_ !== undefined)
964 queueMode = Output.forceModeForNextSpeechUtterance_; 755 queueMode = Output.forceModeForNextSpeechUtterance_;
965 else if (this.queueMode_ !== undefined) 756 else if (this.queueMode_ !== undefined)
966 queueMode = this.queueMode_; 757 queueMode = this.queueMode_;
967 758
968 if (this.speechBuffer_.length > 0) 759 if (this.speechBuffer_.length > 0)
969 Output.forceModeForNextSpeechUtterance_ = undefined; 760 Output.forceModeForNextSpeechUtterance_ = undefined;
970 761
971 for (var i = 0; i < this.speechBuffer_.length; i++) { 762 for (var i = 0; i < this.speechBuffer_.length; i++) {
972 var buff = this.speechBuffer_[i]; 763 var buff = this.speechBuffer_[i];
973 var speechProps = /** @type {Object} */( 764 var speechProps = /** @type {Object} */ (
974 buff.getSpanInstanceOf(Output.SpeechProperties)) || {}; 765 buff.getSpanInstanceOf(Output.SpeechProperties)) ||
766 {};
975 767
976 speechProps.category = this.speechCategory_; 768 speechProps.category = this.speechCategory_;
977 769
978 (function() { 770 (function() {
979 var scopedBuff = buff; 771 var scopedBuff = buff;
980 speechProps['startCallback'] = function() { 772 speechProps['startCallback'] = function() {
981 var actions = scopedBuff.getSpansInstanceOf(Output.Action); 773 var actions = scopedBuff.getSpansInstanceOf(Output.Action);
982 if (actions) { 774 if (actions) {
983 actions.forEach(function(a) { 775 actions.forEach(function(a) {
984 a.run(); 776 a.run();
985 }); 777 });
986 } 778 }
987 }; 779 };
988 }()); 780 }());
989 781
990 if (i == this.speechBuffer_.length - 1) 782 if (i == this.speechBuffer_.length - 1)
991 speechProps['endCallback'] = this.speechEndCallback_; 783 speechProps['endCallback'] = this.speechEndCallback_;
992 784
993 cvox.ChromeVox.tts.speak( 785 cvox.ChromeVox.tts.speak(buff.toString(), queueMode, speechProps);
994 buff.toString(), queueMode, speechProps);
995 queueMode = cvox.QueueMode.QUEUE; 786 queueMode = cvox.QueueMode.QUEUE;
996 } 787 }
997 788
998 // Braille. 789 // Braille.
999 if (this.brailleBuffer_.length) { 790 if (this.brailleBuffer_.length) {
1000 var buff = this.mergeBraille_(this.brailleBuffer_); 791 var buff = this.mergeBraille_(this.brailleBuffer_);
1001 var selSpan = 792 var selSpan = buff.getSpanInstanceOf(Output.SelectionSpan);
1002 buff.getSpanInstanceOf(Output.SelectionSpan);
1003 var startIndex = -1, endIndex = -1; 793 var startIndex = -1, endIndex = -1;
1004 if (selSpan) { 794 if (selSpan) {
1005 var valueStart = buff.getSpanStart(selSpan); 795 var valueStart = buff.getSpanStart(selSpan);
1006 var valueEnd = buff.getSpanEnd(selSpan); 796 var valueEnd = buff.getSpanEnd(selSpan);
1007 startIndex = valueStart + selSpan.startIndex; 797 startIndex = valueStart + selSpan.startIndex;
1008 endIndex = valueStart + selSpan.endIndex; 798 endIndex = valueStart + selSpan.endIndex;
1009 buff.setSpan(new cvox.ValueSpan(0), valueStart, valueEnd); 799 buff.setSpan(new cvox.ValueSpan(0), valueStart, valueEnd);
1010 buff.setSpan(new cvox.ValueSelectionSpan(), startIndex, endIndex); 800 buff.setSpan(new cvox.ValueSelectionSpan(), startIndex, endIndex);
1011 } 801 }
1012 802
1013 var output = new cvox.NavBraille({ 803 var output = new cvox.NavBraille(
1014 text: buff, 804 {text: buff, startIndex: startIndex, endIndex: endIndex});
1015 startIndex: startIndex,
1016 endIndex: endIndex
1017 });
1018 805
1019 cvox.ChromeVox.braille.write(output); 806 cvox.ChromeVox.braille.write(output);
1020 } 807 }
1021 808
1022 // Display. 809 // Display.
1023 if (this.speechCategory_ != cvox.TtsCategory.LIVE) 810 if (this.speechCategory_ != cvox.TtsCategory.LIVE)
1024 chrome.accessibilityPrivate.setFocusRing(this.locations_); 811 chrome.accessibilityPrivate.setFocusRing(this.locations_);
1025 }, 812 },
1026 813
1027 /** 814 /**
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 // All possible tokens based on prefix. 897 // All possible tokens based on prefix.
1111 if (prefix == '$') { 898 if (prefix == '$') {
1112 if (token == 'value') { 899 if (token == 'value') {
1113 var text = node.value || ''; 900 var text = node.value || '';
1114 if (!node.state[StateType.EDITABLE] && node.name == text) 901 if (!node.state[StateType.EDITABLE] && node.name == text)
1115 return; 902 return;
1116 903
1117 var selectedText = ''; 904 var selectedText = '';
1118 if (node.textSelStart !== undefined) { 905 if (node.textSelStart !== undefined) {
1119 options.annotation.push(new Output.SelectionSpan( 906 options.annotation.push(new Output.SelectionSpan(
1120 node.textSelStart || 0, 907 node.textSelStart || 0, node.textSelEnd || 0));
1121 node.textSelEnd || 0));
1122 908
1123 selectedText = 909 selectedText = node.value.substring(
1124 node.value.substring(node.textSelStart || 0, 910 node.textSelStart || 0, node.textSelEnd || 0);
1125 node.textSelEnd || 0);
1126 } 911 }
1127 options.annotation.push(token); 912 options.annotation.push(token);
1128 if (selectedText && !this.formatOptions_.braille) { 913 if (selectedText && !this.formatOptions_.braille) {
1129 this.append_(buff, selectedText, options); 914 this.append_(buff, selectedText, options);
1130 this.append_(buff, Msgs.getMsg('selected')); 915 this.append_(buff, Msgs.getMsg('selected'));
1131 } else { 916 } else {
1132 this.append_(buff, text, options); 917 this.append_(buff, text, options);
1133 } 918 }
1134 } else if (token == 'name') { 919 } else if (token == 'name') {
1135 options.annotation.push(token); 920 options.annotation.push(token);
(...skipping 10 matching lines...) Expand all
1146 } else if (token == 'urlFilename') { 931 } else if (token == 'urlFilename') {
1147 options.annotation.push('name'); 932 options.annotation.push('name');
1148 var url = node.url || ''; 933 var url = node.url || '';
1149 var filename = ''; 934 var filename = '';
1150 if (url.substring(0, 4) != 'data') { 935 if (url.substring(0, 4) != 'data') {
1151 filename = 936 filename =
1152 url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.')); 937 url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.'));
1153 938
1154 // Hack to not speak the filename if it's ridiculously long. 939 // Hack to not speak the filename if it's ridiculously long.
1155 if (filename.length >= 30) 940 if (filename.length >= 30)
1156 filename = filename.substring(0, 16) + '...'; 941 filename = filename.substring(0, 16) + '...';
1157 } 942 }
1158 this.append_(buff, filename, options); 943 this.append_(buff, filename, options);
1159 } else if (token == 'nameFromNode') { 944 } else if (token == 'nameFromNode') {
1160 if (node.nameFrom == chrome.automation.NameFromType.CONTENTS) 945 if (node.nameFrom == chrome.automation.NameFromType.CONTENTS)
1161 return; 946 return;
1162 947
1163 options.annotation.push('name'); 948 options.annotation.push('name');
1164 this.append_(buff, node.name || '', options); 949 this.append_(buff, node.name || '', options);
1165 } else if (token == 'nameOrDescendants') { 950 } else if (token == 'nameOrDescendants') {
1166 options.annotation.push(token); 951 options.annotation.push(token);
(...skipping 14 matching lines...) Expand all
1181 if (node.role == child.role) 966 if (node.role == child.role)
1182 count++; 967 count++;
1183 if (node === child) 968 if (node === child)
1184 break; 969 break;
1185 } 970 }
1186 this.append_(buff, String(count)); 971 this.append_(buff, String(count));
1187 } 972 }
1188 } else if (token == 'parentChildCount') { 973 } else if (token == 'parentChildCount') {
1189 if (node.parent) { 974 if (node.parent) {
1190 options.annotation.push(token); 975 options.annotation.push(token);
1191 var count = node.parent.children.filter(function(child) { 976 var count = node.parent.children
1192 return node.role == child.role; 977 .filter(function(child) {
1193 }).length; 978 return node.role == child.role;
979 })
980 .length;
1194 this.append_(buff, String(count)); 981 this.append_(buff, String(count));
1195 } 982 }
1196 } else if (token == 'checked') { 983 } else if (token == 'checked') {
1197 var msg = Output.CHECKED_STATE_MAP[node.checked]; 984 var msg = Output.CHECKED_STATE_MAP[node.checked];
1198 if (msg) { 985 if (msg) {
1199 this.format_(node, '@' + msg, buff); 986 this.format_(node, '@' + msg, buff);
1200 } 987 }
1201 } else if (token == 'pressed') { 988 } else if (token == 'pressed') {
1202 var msg = Output.PRESSED_STATE_MAP[node.checked]; 989 var msg = Output.PRESSED_STATE_MAP[node.checked];
1203 if (msg) { 990 if (msg) {
1204 this.format_(node, '@' + msg, buff); 991 this.format_(node, '@' + msg, buff);
1205 } 992 }
1206 } else if (token == 'state') { 993 } else if (token == 'state') {
1207 if (node.state) { 994 if (node.state) {
1208 Object.getOwnPropertyNames(node.state).forEach(function(s) { 995 Object.getOwnPropertyNames(node.state).forEach(function(s) {
1209 var stateInfo = Output.STATE_INFO_[s]; 996 var stateInfo = Output.STATE_INFO_[s];
1210 if (stateInfo && !stateInfo.isRoleSpecific && stateInfo.on) 997 if (stateInfo && !stateInfo.isRoleSpecific && stateInfo.on)
1211 this.format_(node, '@' + stateInfo.on.msgId, buff); 998 this.format_(node, '@' + stateInfo.on.msgId, buff);
1212 }.bind(this)); 999 }.bind(this));
1213 } 1000 }
1214 } else if (token == 'find') { 1001 } else if (token == 'find') {
1215 // Find takes two arguments: JSON query string and format string. 1002 // Find takes two arguments: JSON query string and format string.
1216 if (tree.firstChild) { 1003 if (tree.firstChild) {
1217 var jsonQuery = tree.firstChild.value; 1004 var jsonQuery = tree.firstChild.value;
1218 node = node.find( 1005 node = node.find(
1219 /** @type {chrome.automation.FindParams}*/( 1006 /** @type {chrome.automation.FindParams}*/ (
1220 JSON.parse(jsonQuery))); 1007 JSON.parse(jsonQuery)));
1221 var formatString = tree.firstChild.nextSibling; 1008 var formatString = tree.firstChild.nextSibling;
1222 if (node) 1009 if (node)
1223 this.format_(node, formatString, buff); 1010 this.format_(node, formatString, buff);
1224 } 1011 }
1225 } else if (token == 'descendants') { 1012 } else if (token == 'descendants') {
1226 if (!node || AutomationPredicate.leafOrStaticText(node)) 1013 if (!node || AutomationPredicate.leafOrStaticText(node))
1227 return; 1014 return;
1228 1015
1229 // Construct a range to the leftmost and rightmost leaves. 1016 // Construct a range to the leftmost and rightmost leaves.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 this.append_(buff, msg || '', options); 1056 this.append_(buff, msg || '', options);
1270 } else if (token == 'inputType') { 1057 } else if (token == 'inputType') {
1271 if (!node.inputType) 1058 if (!node.inputType)
1272 return; 1059 return;
1273 options.annotation.push(token); 1060 options.annotation.push(token);
1274 var msgId = Output.INPUT_TYPE_MESSAGE_IDS_[node.inputType] || 1061 var msgId = Output.INPUT_TYPE_MESSAGE_IDS_[node.inputType] ||
1275 'input_type_text'; 1062 'input_type_text';
1276 if (this.formatOptions_.braille) 1063 if (this.formatOptions_.braille)
1277 msgId = msgId + '_brl'; 1064 msgId = msgId + '_brl';
1278 this.append_(buff, Msgs.getMsg(msgId), options); 1065 this.append_(buff, Msgs.getMsg(msgId), options);
1279 } else if (token == 'tableCellRowIndex' || 1066 } else if (
1280 token == 'tableCellColumnIndex') { 1067 token == 'tableCellRowIndex' || token == 'tableCellColumnIndex') {
1281 var value = node[token]; 1068 var value = node[token];
1282 if (value == undefined) 1069 if (value == undefined)
1283 return; 1070 return;
1284 value = String(value + 1); 1071 value = String(value + 1);
1285 options.annotation.push(token); 1072 options.annotation.push(token);
1286 this.append_(buff, value, options); 1073 this.append_(buff, value, options);
1287 } else if (token == 'node') { 1074 } else if (token == 'node') {
1288 if (!tree.firstChild || !node[tree.firstChild.value]) 1075 if (!tree.firstChild || !node[tree.firstChild.value])
1289 return; 1076 return;
1290 var related = node[tree.firstChild.value]; 1077 var related = node[tree.firstChild.value];
1291 this.node_(related, related, Output.EventType.NAVIGATE, buff); 1078 this.node_(related, related, Output.EventType.NAVIGATE, buff);
1292 } else if (token == 'nameOrTextContent') { 1079 } else if (token == 'nameOrTextContent') {
1293 if (node.name) { 1080 if (node.name) {
1294 this.format_(node, '$name', buff); 1081 this.format_(node, '$name', buff);
1295 } else { 1082 } else {
1296 var walker = new AutomationTreeWalker(node, 1083 var walker = new AutomationTreeWalker(node, Dir.FORWARD, {
1297 Dir.FORWARD, 1084 visit: AutomationPredicate.leafOrStaticText,
1298 {visit: AutomationPredicate.leafOrStaticText, 1085 leaf: AutomationPredicate.leafOrStaticText
1299 leaf: AutomationPredicate.leafOrStaticText}); 1086 });
1300 var outputStrings = []; 1087 var outputStrings = [];
1301 while (walker.next().node && 1088 while (walker.next().node &&
1302 walker.phase == AutomationTreeWalkerPhase.DESCENDANT) { 1089 walker.phase == AutomationTreeWalkerPhase.DESCENDANT) {
1303 if (walker.node.name) 1090 if (walker.node.name)
1304 outputStrings.push(walker.node.name); 1091 outputStrings.push(walker.node.name);
1305 } 1092 }
1306 var joinedOutput = outputStrings.join(' '); 1093 var joinedOutput = outputStrings.join(' ');
1307 this.append_(buff, joinedOutput, options); 1094 this.append_(buff, joinedOutput, options);
1308 } 1095 }
1309 } else if (node[token] !== undefined) { 1096 } else if (node[token] !== undefined) {
1310 options.annotation.push(token); 1097 options.annotation.push(token);
1311 var value = node[token]; 1098 var value = node[token];
1312 if (typeof value == 'number') 1099 if (typeof value == 'number')
1313 value = String(value); 1100 value = String(value);
1314 this.append_(buff, value, options); 1101 this.append_(buff, value, options);
1315 } else if (Output.STATE_INFO_[token]) { 1102 } else if (Output.STATE_INFO_[token]) {
1316 options.annotation.push('state'); 1103 options.annotation.push('state');
1317 var stateInfo = Output.STATE_INFO_[token]; 1104 var stateInfo = Output.STATE_INFO_[token];
1318 var resolvedInfo = {}; 1105 var resolvedInfo = {};
1319 resolvedInfo = node.state[token] ? stateInfo.on : stateInfo.off; 1106 resolvedInfo = node.state[token] ? stateInfo.on : stateInfo.off;
1320 if (!resolvedInfo) 1107 if (!resolvedInfo)
1321 return; 1108 return;
1322 if (this.formatOptions_.speech && resolvedInfo.earconId) { 1109 if (this.formatOptions_.speech && resolvedInfo.earconId) {
1323 options.annotation.push( 1110 options.annotation.push(
1324 new Output.EarconAction(resolvedInfo.earconId), 1111 new Output.EarconAction(resolvedInfo.earconId),
1325 node.location || undefined); 1112 node.location || undefined);
1326 } 1113 }
1327 var msgId = 1114 var msgId = this.formatOptions_.braille ?
1328 this.formatOptions_.braille ? resolvedInfo.msgId + '_brl' : 1115 resolvedInfo.msgId + '_brl' :
1329 resolvedInfo.msgId; 1116 resolvedInfo.msgId;
1330 var msg = Msgs.getMsg(msgId); 1117 var msg = Msgs.getMsg(msgId);
1331 this.append_(buff, msg, options); 1118 this.append_(buff, msg, options);
1332 } else if (tree.firstChild) { 1119 } else if (tree.firstChild) {
1333 // Custom functions. 1120 // Custom functions.
1334 if (token == 'if') { 1121 if (token == 'if') {
1335 var cond = tree.firstChild; 1122 var cond = tree.firstChild;
1336 var attrib = cond.value.slice(1); 1123 var attrib = cond.value.slice(1);
1337 if (Output.isTruthy(node, attrib)) 1124 if (Output.isTruthy(node, attrib))
1338 this.format_(node, cond.nextSibling, buff); 1125 this.format_(node, cond.nextSibling, buff);
1339 else 1126 else
1340 this.format_(node, cond.nextSibling.nextSibling, buff); 1127 this.format_(node, cond.nextSibling.nextSibling, buff);
1341 } else if (token == 'earcon') { 1128 } else if (token == 'earcon') {
1342 // Ignore unless we're generating speech output. 1129 // Ignore unless we're generating speech output.
1343 if (!this.formatOptions_.speech) 1130 if (!this.formatOptions_.speech)
1344 return; 1131 return;
1345 1132
1346 options.annotation.push( 1133 options.annotation.push(new Output.EarconAction(
1347 new Output.EarconAction(tree.firstChild.value, 1134 tree.firstChild.value, node.location || undefined));
1348 node.location || undefined));
1349 this.append_(buff, '', options); 1135 this.append_(buff, '', options);
1350 } else if (token == 'countChildren') { 1136 } else if (token == 'countChildren') {
1351 var role = tree.firstChild.value; 1137 var role = tree.firstChild.value;
1352 var count = node.children.filter(function(e) { 1138 var count = node.children
1353 return e.role == role; 1139 .filter(function(e) {
1354 }).length; 1140 return e.role == role;
1141 })
1142 .length;
1355 this.append_(buff, String(count)); 1143 this.append_(buff, String(count));
1356 } 1144 }
1357 } 1145 }
1358 } else if (prefix == '@') { 1146 } else if (prefix == '@') {
1359 if (this.formatOptions_.auralStyle) { 1147 if (this.formatOptions_.auralStyle) {
1360 speechProps = new Output.SpeechProperties(); 1148 speechProps = new Output.SpeechProperties();
1361 speechProps['relativePitch'] = -0.2; 1149 speechProps['relativePitch'] = -0.2;
1362 } 1150 }
1363 var isPluralized = (token[0] == '@'); 1151 var isPluralized = (token[0] == '@');
1364 if (isPluralized) 1152 if (isPluralized)
(...skipping 21 matching lines...) Expand all
1386 if (!msgBuff.length) 1174 if (!msgBuff.length)
1387 msgBuff = ['']; 1175 msgBuff = [''];
1388 msgArgs = msgArgs.concat(msgBuff); 1176 msgArgs = msgArgs.concat(msgBuff);
1389 curArg = curArg.nextSibling; 1177 curArg = curArg.nextSibling;
1390 } 1178 }
1391 } 1179 }
1392 var msg = Msgs.getMsg(msgId, msgArgs); 1180 var msg = Msgs.getMsg(msgId, msgArgs);
1393 try { 1181 try {
1394 if (this.formatOptions_.braille) 1182 if (this.formatOptions_.braille)
1395 msg = Msgs.getMsg(msgId + '_brl', msgArgs) || msg; 1183 msg = Msgs.getMsg(msgId + '_brl', msgArgs) || msg;
1396 } catch(e) {} 1184 } catch (e) {
1185 }
1397 1186
1398 if (!msg) { 1187 if (!msg) {
1399 console.error('Could not get message ' + msgId); 1188 console.error('Could not get message ' + msgId);
1400 return; 1189 return;
1401 } 1190 }
1402 1191
1403 if (isPluralized) { 1192 if (isPluralized) {
1404 var arg = tree.firstChild; 1193 var arg = tree.firstChild;
1405 if (!arg || arg.nextSibling) { 1194 if (!arg || arg.nextSibling) {
1406 console.error('Pluralized messages take exactly one argument'); 1195 console.error('Pluralized messages take exactly one argument');
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1472 this.ancestry_(node, prevNode, type, buff); 1261 this.ancestry_(node, prevNode, type, buff);
1473 this.node_(node, prevNode, type, buff); 1262 this.node_(node, prevNode, type, buff);
1474 if (!this.outputContextFirst_) 1263 if (!this.outputContextFirst_)
1475 this.ancestry_(node, prevNode, type, buff); 1264 this.ancestry_(node, prevNode, type, buff);
1476 if (node.location) 1265 if (node.location)
1477 this.locations_.push(node.location); 1266 this.locations_.push(node.location);
1478 return buff; 1267 return buff;
1479 }.bind(this); 1268 }.bind(this);
1480 1269
1481 var unit = range.isInlineText() ? cursors.Unit.TEXT : cursors.Unit.NODE; 1270 var unit = range.isInlineText() ? cursors.Unit.TEXT : cursors.Unit.NODE;
1482 while (cursor.node && 1271 while (cursor.node && range.end.node &&
1483 range.end.node && 1272 AutomationUtil.getDirection(cursor.node, range.end.node) ==
1484 AutomationUtil.getDirection(cursor.node, range.end.node) == 1273 Dir.FORWARD) {
1485 Dir.FORWARD) {
1486 var node = cursor.node; 1274 var node = cursor.node;
1487 rangeBuff.push.apply(rangeBuff, formatNodeAndAncestors(node, prevNode)); 1275 rangeBuff.push.apply(rangeBuff, formatNodeAndAncestors(node, prevNode));
1488 prevNode = node; 1276 prevNode = node;
1489 cursor = cursor.move(unit, 1277 cursor = cursor.move(unit, cursors.Movement.DIRECTIONAL, Dir.FORWARD);
1490 cursors.Movement.DIRECTIONAL,
1491 Dir.FORWARD);
1492 1278
1493 // Reached a boundary. 1279 // Reached a boundary.
1494 if (cursor.node == prevNode) 1280 if (cursor.node == prevNode)
1495 break; 1281 break;
1496 } 1282 }
1497 }, 1283 },
1498 1284
1499 /** 1285 /**
1500 * @param {!AutomationNode} node 1286 * @param {!AutomationNode} node
1501 * @param {!AutomationNode} prevNode 1287 * @param {!AutomationNode} prevNode
(...skipping 14 matching lines...) Expand all
1516 contextFirst = []; 1302 contextFirst = [];
1517 rest = []; 1303 rest = [];
1518 } 1304 }
1519 if ((Output.ROLE_INFO_[node.role] || {}).outputContextFirst) 1305 if ((Output.ROLE_INFO_[node.role] || {}).outputContextFirst)
1520 contextFirst.push(node); 1306 contextFirst.push(node);
1521 else 1307 else
1522 rest.push(node); 1308 rest.push(node);
1523 } 1309 }
1524 return rest.concat(contextFirst.reverse()); 1310 return rest.concat(contextFirst.reverse());
1525 } 1311 }
1526 var prevUniqueAncestors = byContextFirst(AutomationUtil.getUniqueAncestors( 1312 var prevUniqueAncestors =
1527 node, prevNode)); 1313 byContextFirst(AutomationUtil.getUniqueAncestors(node, prevNode));
1528 var uniqueAncestors = byContextFirst(AutomationUtil.getUniqueAncestors( 1314 var uniqueAncestors =
1529 prevNode, node)); 1315 byContextFirst(AutomationUtil.getUniqueAncestors(prevNode, node));
1530 1316
1531 // First, look up the event type's format block. 1317 // First, look up the event type's format block.
1532 // Navigate is the default event. 1318 // Navigate is the default event.
1533 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; 1319 var eventBlock = Output.RULES[type] || Output.RULES['navigate'];
1534 1320
1535 var getMergedRoleBlock = function(role) { 1321 var getMergedRoleBlock = function(role) {
1536 var parentRole = (Output.ROLE_INFO_[role] || {}).inherits; 1322 var parentRole = (Output.ROLE_INFO_[role] || {}).inherits;
1537 var roleBlock = eventBlock[role] || eventBlock['default']; 1323 var roleBlock = eventBlock[role] || eventBlock['default'];
1538 var parentRoleBlock = parentRole ? eventBlock[parentRole] : {}; 1324 var parentRoleBlock = parentRole ? eventBlock[parentRole] : {};
1539 var mergedRoleBlock = {}; 1325 var mergedRoleBlock = {};
1540 for (var key in parentRoleBlock) 1326 for (var key in parentRoleBlock)
1541 mergedRoleBlock[key] = parentRoleBlock[key]; 1327 mergedRoleBlock[key] = parentRoleBlock[key];
1542 for (var key in roleBlock) 1328 for (var key in roleBlock)
1543 mergedRoleBlock[key] = roleBlock[key]; 1329 mergedRoleBlock[key] = roleBlock[key];
1544 return mergedRoleBlock; 1330 return mergedRoleBlock;
1545 }; 1331 };
1546 1332
1547 // Hash the roles we've entered. 1333 // Hash the roles we've entered.
1548 var enteredRoleSet = {}; 1334 var enteredRoleSet = {};
1549 for (var j = uniqueAncestors.length - 1, hashNode; 1335 for (var j = uniqueAncestors.length - 1, hashNode;
1550 (hashNode = uniqueAncestors[j]); 1336 (hashNode = uniqueAncestors[j]); j--)
1551 j--)
1552 enteredRoleSet[hashNode.role] = true; 1337 enteredRoleSet[hashNode.role] = true;
1553 1338
1554 for (var i = 0, formatPrevNode; 1339 for (var i = 0, formatPrevNode; (formatPrevNode = prevUniqueAncestors[i]);
1555 (formatPrevNode = prevUniqueAncestors[i]);
1556 i++) { 1340 i++) {
1557 // This prevents very repetitive announcements. 1341 // This prevents very repetitive announcements.
1558 if (enteredRoleSet[formatPrevNode.role] || 1342 if (enteredRoleSet[formatPrevNode.role] ||
1559 node.role == formatPrevNode.role || 1343 node.role == formatPrevNode.role ||
1560 localStorage['useVerboseMode'] == 'false') 1344 localStorage['useVerboseMode'] == 'false')
1561 continue; 1345 continue;
1562 1346
1563 var roleBlock = getMergedRoleBlock(formatPrevNode.role); 1347 var roleBlock = getMergedRoleBlock(formatPrevNode.role);
1564 if (roleBlock.leave && localStorage['useVerboseMode'] == 'true') 1348 if (roleBlock.leave && localStorage['useVerboseMode'] == 'true')
1565 this.format_(formatPrevNode, roleBlock.leave, buff, prevNode); 1349 this.format_(formatPrevNode, roleBlock.leave, buff, prevNode);
1566 } 1350 }
1567 1351
1568 // Customize for braille node annotations. 1352 // Customize for braille node annotations.
1569 var originalBuff = buff; 1353 var originalBuff = buff;
1570 var enterRole = {}; 1354 var enterRole = {};
1571 for (var j = uniqueAncestors.length - 1, formatNode; 1355 for (var j = uniqueAncestors.length - 1, formatNode;
1572 (formatNode = uniqueAncestors[j]); 1356 (formatNode = uniqueAncestors[j]); j--) {
1573 j--) {
1574 var roleBlock = getMergedRoleBlock(formatNode.role); 1357 var roleBlock = getMergedRoleBlock(formatNode.role);
1575 if (roleBlock.enter) { 1358 if (roleBlock.enter) {
1576 if (enterRole[formatNode.role]) 1359 if (enterRole[formatNode.role])
1577 continue; 1360 continue;
1578 1361
1579 if (this.formatOptions_.braille) 1362 if (this.formatOptions_.braille)
1580 buff = []; 1363 buff = [];
1581 1364
1582 enterRole[formatNode.role] = true; 1365 enterRole[formatNode.role] = true;
1583 this.format_(formatNode, roleBlock.enter, buff, prevNode); 1366 this.format_(formatNode, roleBlock.enter, buff, prevNode);
(...skipping 18 matching lines...) Expand all
1602 var originalBuff = buff; 1385 var originalBuff = buff;
1603 1386
1604 if (this.formatOptions_.braille) 1387 if (this.formatOptions_.braille)
1605 buff = []; 1388 buff = [];
1606 1389
1607 // Navigate is the default event. 1390 // Navigate is the default event.
1608 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; 1391 var eventBlock = Output.RULES[type] || Output.RULES['navigate'];
1609 var roleBlock = eventBlock[node.role] || {}; 1392 var roleBlock = eventBlock[node.role] || {};
1610 var parentRole = (Output.ROLE_INFO_[node.role] || {}).inherits; 1393 var parentRole = (Output.ROLE_INFO_[node.role] || {}).inherits;
1611 var parentRoleBlock = eventBlock[parentRole || ''] || {}; 1394 var parentRoleBlock = eventBlock[parentRole || ''] || {};
1612 var speakFormat = roleBlock.speak || 1395 var speakFormat =
1613 parentRoleBlock.speak || 1396 roleBlock.speak || parentRoleBlock.speak || eventBlock['default'].speak;
1614 eventBlock['default'].speak;
1615 1397
1616 this.format_(node, speakFormat, buff, prevNode); 1398 this.format_(node, speakFormat, buff, prevNode);
1617 1399
1618 // Restore braille and add an annotation for this node. 1400 // Restore braille and add an annotation for this node.
1619 if (this.formatOptions_.braille) { 1401 if (this.formatOptions_.braille) {
1620 var nodeSpan = this.mergeBraille_(buff); 1402 var nodeSpan = this.mergeBraille_(buff);
1621 nodeSpan.setSpan(new Output.NodeSpan(node), 0, nodeSpan.length); 1403 nodeSpan.setSpan(new Output.NodeSpan(node), 0, nodeSpan.length);
1622 originalBuff.push(nodeSpan); 1404 originalBuff.push(nodeSpan);
1623 } 1405 }
1624 }, 1406 },
(...skipping 15 matching lines...) Expand all
1640 return; 1422 return;
1641 1423
1642 var options = {annotation: ['name'], isUnique: true}; 1424 var options = {annotation: ['name'], isUnique: true};
1643 var rangeStart = range.start.index; 1425 var rangeStart = range.start.index;
1644 var rangeEnd = range.end.index; 1426 var rangeEnd = range.end.index;
1645 if (this.formatOptions_.braille) { 1427 if (this.formatOptions_.braille) {
1646 options.annotation.push(new Output.NodeSpan(node)); 1428 options.annotation.push(new Output.NodeSpan(node));
1647 var selStart = node.textSelStart; 1429 var selStart = node.textSelStart;
1648 var selEnd = node.textSelEnd; 1430 var selEnd = node.textSelEnd;
1649 1431
1650 if (selStart !== undefined && 1432 if (selStart !== undefined && selEnd >= rangeStart &&
1651 selEnd >= rangeStart && selStart <= rangeEnd) { 1433 selStart <= rangeEnd) {
1652 // Editable text selection. 1434 // Editable text selection.
1653 1435
1654 // |rangeStart| and |rangeEnd| are indices set by the caller and are 1436 // |rangeStart| and |rangeEnd| are indices set by the caller and are
1655 // assumed to be inside of the range. In braille, we only ever expect to 1437 // assumed to be inside of the range. In braille, we only ever expect to
1656 // get ranges surrounding a line as anything smaller doesn't make sense. 1438 // get ranges surrounding a line as anything smaller doesn't make sense.
1657 1439
1658 // |selStart| and |selEnd| reflect the editable selection. The relative 1440 // |selStart| and |selEnd| reflect the editable selection. The relative
1659 // selStart and relative selEnd for the current line are then just the 1441 // selStart and relative selEnd for the current line are then just the
1660 // difference between |selStart|, |selEnd| with |rangeStart|. 1442 // difference between |selStart|, |selEnd| with |rangeStart|.
1661 // See editing_test.js for examples. 1443 // See editing_test.js for examples.
(...skipping 21 matching lines...) Expand all
1683 } else { 1465 } else {
1684 // This is output for speech or editable braille. 1466 // This is output for speech or editable braille.
1685 text = range.start.getText().substring(rangeStart, rangeEnd); 1467 text = range.start.getText().substring(rangeStart, rangeEnd);
1686 } 1468 }
1687 1469
1688 this.append_(buff, text, options); 1470 this.append_(buff, text, options);
1689 1471
1690 if (!this.outputContextFirst_) 1472 if (!this.outputContextFirst_)
1691 this.ancestry_(node, prevNode, type, buff); 1473 this.ancestry_(node, prevNode, type, buff);
1692 1474
1693 var loc = 1475 var loc = range.start.node.boundsForRange(rangeStart, rangeEnd);
1694 range.start.node.boundsForRange(rangeStart, rangeEnd);
1695 if (loc) 1476 if (loc)
1696 this.locations_.push(loc); 1477 this.locations_.push(loc);
1697 }, 1478 },
1698 1479
1699 /** 1480 /**
1700 * Appends output to the |buff|. 1481 * Appends output to the |buff|.
1701 * @param {!Array<Spannable>} buff 1482 * @param {!Array<Spannable>} buff
1702 * @param {string|!Spannable} value 1483 * @param {string|!Spannable} value
1703 * @param {{isUnique: (boolean|undefined), 1484 * @param {{isUnique: (boolean|undefined),
1704 * annotation: !Array<*>}=} opt_options 1485 * annotation: !Array<*>}=} opt_options
1705 */ 1486 */
1706 append_: function(buff, value, opt_options) { 1487 append_: function(buff, value, opt_options) {
1707 opt_options = opt_options || {isUnique: false, annotation: []}; 1488 opt_options = opt_options || {isUnique: false, annotation: []};
1708 1489
1709 // Reject empty values without meaningful annotations. 1490 // Reject empty values without meaningful annotations.
1710 if ((!value || value.length == 0) && opt_options.annotation.every( 1491 if ((!value || value.length == 0) &&
1711 function(a) { 1492 opt_options.annotation.every(function(a) {
1712 return !(a instanceof Output.Action) && 1493 return !(a instanceof Output.Action) &&
1713 !(a instanceof Output.SelectionSpan); 1494 !(a instanceof Output.SelectionSpan);
1714 1495
1715 })) 1496 }))
1716 return; 1497 return;
1717 1498
1718 var spannableToAdd = new Spannable(value); 1499 var spannableToAdd = new Spannable(value);
1719 opt_options.annotation.forEach(function(a) { 1500 opt_options.annotation.forEach(function(a) {
1720 spannableToAdd.setSpan(a, 0, spannableToAdd.length); 1501 spannableToAdd.setSpan(a, 0, spannableToAdd.length);
1721 }); 1502 });
1722 1503
1723 // |isUnique| specifies an annotation that cannot be duplicated. 1504 // |isUnique| specifies an annotation that cannot be duplicated.
1724 if (opt_options.isUnique) { 1505 if (opt_options.isUnique) {
1725 var annotationSansNodes = opt_options.annotation.filter( 1506 var annotationSansNodes =
1726 function(annotation) { 1507 opt_options.annotation.filter(function(annotation) {
1727 return !(annotation instanceof Output.NodeSpan); 1508 return !(annotation instanceof Output.NodeSpan);
1728 }); 1509 });
1729 1510
1730 var alreadyAnnotated = buff.some(function(s) { 1511 var alreadyAnnotated = buff.some(function(s) {
1731 return annotationSansNodes.some(function(annotation) { 1512 return annotationSansNodes.some(function(annotation) {
1732 if (!s.hasSpan(annotation)) 1513 if (!s.hasSpan(annotation))
1733 return false; 1514 return false;
1734 var start = s.getSpanStart(annotation); 1515 var start = s.getSpanStart(annotation);
1735 var end = s.getSpanEnd(annotation); 1516 var end = s.getSpanEnd(annotation);
1736 var substr = s.substring(start, end); 1517 var substr = s.substring(start, end);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 // showing the braille cursor. 1588 // showing the braille cursor.
1808 if (cur.length == 0 && hasSelection) { 1589 if (cur.length == 0 && hasSelection) {
1809 result.append(cur); 1590 result.append(cur);
1810 result.append(Output.SPACE); 1591 result.append(Output.SPACE);
1811 separator = ''; 1592 separator = '';
1812 return result; 1593 return result;
1813 } 1594 }
1814 1595
1815 // Keep track of if there's an inline node associated with 1596 // Keep track of if there's an inline node associated with
1816 // |cur|. 1597 // |cur|.
1817 var hasInlineNode = cur.getSpansInstanceOf(Output.NodeSpan) 1598 var hasInlineNode =
1818 .some(function(s) { 1599 cur.getSpansInstanceOf(Output.NodeSpan).some(function(s) {
1819 if (!s.node) 1600 if (!s.node)
1820 return false; 1601 return false;
1821 return s.node.display == 'inline' || 1602 return s.node.display == 'inline' ||
1822 s.node.role == RoleType.INLINE_TEXT_BOX; 1603 s.node.role == RoleType.INLINE_TEXT_BOX;
1823 }); 1604 });
1824 1605
1825 var isName = cur.hasSpan('name'); 1606 var isName = cur.hasSpan('name');
1826 1607
1827 // Now, decide whether we should include separators between the previous 1608 // Now, decide whether we should include separators between the previous
1828 // span and |cur|. 1609 // span and |cur|.
1829 // Never separate chunks without something already there at this point. 1610 // Never separate chunks without something already there at this point.
1830 1611
1831 // The only case where we know for certain that a separator is not needed 1612 // The only case where we know for certain that a separator is not needed
1832 // is when the previous and current values are in-lined and part of the 1613 // is when the previous and current values are in-lined and part of the
1833 // node's name. In all other cases, use the surrounding whitespace to 1614 // node's name. In all other cases, use the surrounding whitespace to
1834 // ensure we only have one separator between the node text. 1615 // ensure we only have one separator between the node text.
1835 if (result.length == 0 || 1616 if (result.length == 0 ||
1836 (hasInlineNode && prevHasInlineNode && isName && prevIsName)) 1617 (hasInlineNode && prevHasInlineNode && isName && prevIsName))
1837 separator = ''; 1618 separator = '';
1838 else if (result.toString()[result.length - 1] == Output.SPACE || 1619 else if (
1620 result.toString()[result.length - 1] == Output.SPACE ||
1839 cur.toString()[0] == Output.SPACE) 1621 cur.toString()[0] == Output.SPACE)
1840 separator = ''; 1622 separator = '';
1841 else 1623 else
1842 separator = Output.SPACE; 1624 separator = Output.SPACE;
1843 1625
1844 prevHasInlineNode = hasInlineNode; 1626 prevHasInlineNode = hasInlineNode;
1845 prevIsName = isName; 1627 prevIsName = isName;
1846 result.append(separator); 1628 result.append(separator);
1847 result.append(cur); 1629 result.append(cur);
1848 return result; 1630 return result;
(...skipping 14 matching lines...) Expand all
1863 var earconFinder = node; 1645 var earconFinder = node;
1864 var ancestors; 1646 var ancestors;
1865 if (opt_prevNode) 1647 if (opt_prevNode)
1866 ancestors = AutomationUtil.getUniqueAncestors(opt_prevNode, node); 1648 ancestors = AutomationUtil.getUniqueAncestors(opt_prevNode, node);
1867 else 1649 else
1868 ancestors = AutomationUtil.getAncestors(node); 1650 ancestors = AutomationUtil.getAncestors(node);
1869 1651
1870 while (earconFinder = ancestors.pop()) { 1652 while (earconFinder = ancestors.pop()) {
1871 var info = Output.ROLE_INFO_[earconFinder.role]; 1653 var info = Output.ROLE_INFO_[earconFinder.role];
1872 if (info && info.earconId) { 1654 if (info && info.earconId) {
1873 return new Output.EarconAction(info.earconId, 1655 return new Output.EarconAction(
1874 node.location || undefined); 1656 info.earconId, node.location || undefined);
1875 break; 1657 break;
1876 } 1658 }
1877 earconFinder = earconFinder.parent; 1659 earconFinder = earconFinder.parent;
1878 } 1660 }
1879 } 1661 }
1880 return null; 1662 return null;
1881 }, 1663 },
1882 1664
1883 /** 1665 /**
1884 * Gets a human friendly string with the contents of output. 1666 * Gets a human friendly string with the contents of output.
(...skipping 25 matching lines...) Expand all
1910 /** 1692 /**
1911 * Gets the output buffer for braille. 1693 * Gets the output buffer for braille.
1912 * @return {!Spannable} 1694 * @return {!Spannable}
1913 */ 1695 */
1914 get brailleOutputForTest() { 1696 get brailleOutputForTest() {
1915 return this.mergeBraille_(this.brailleBuffer_); 1697 return this.mergeBraille_(this.brailleBuffer_);
1916 } 1698 }
1917 }; 1699 };
1918 1700
1919 }); // goog.scope 1701 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698