| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 msgId: 'aria_role_alert', | 86 msgId: 'aria_role_alert', |
| 87 earcon: 'ALERT_NONMODAL', | 87 earcon: 'ALERT_NONMODAL', |
| 88 }, | 88 }, |
| 89 button: { | 89 button: { |
| 90 msgId: 'tag_button', | 90 msgId: 'tag_button', |
| 91 earcon: 'BUTTON' | 91 earcon: 'BUTTON' |
| 92 }, | 92 }, |
| 93 checkBox: { | 93 checkBox: { |
| 94 msgId: 'input_type_checkbox' | 94 msgId: 'input_type_checkbox' |
| 95 }, | 95 }, |
| 96 date: { |
| 97 msgId: 'input_type_date' |
| 98 }, |
| 96 dialog: { | 99 dialog: { |
| 97 msgId: 'dialog' | 100 msgId: 'dialog' |
| 98 }, | 101 }, |
| 99 heading: { | 102 heading: { |
| 100 msgId: 'aria_role_heading', | 103 msgId: 'aria_role_heading', |
| 101 }, | 104 }, |
| 102 link: { | 105 link: { |
| 103 msgId: 'tag_link', | 106 msgId: 'tag_link', |
| 104 earcon: 'LINK' | 107 earcon: 'LINK' |
| 105 }, | 108 }, |
| 106 listItem: { | 109 listItem: { |
| 107 msgId: 'ARIA_ROLE_LISTITEM', | 110 msgId: 'ARIA_ROLE_LISTITEM', |
| 108 earcon: 'list_item' | 111 earcon: 'list_item' |
| 109 }, | 112 }, |
| 110 menuListOption: { | 113 menuListOption: { |
| 111 msgId: 'aria_role_menuitem' | 114 msgId: 'aria_role_menuitem' |
| 112 }, | 115 }, |
| 113 popUpButton: { | 116 popUpButton: { |
| 114 msgId: 'tag_button' | 117 msgId: 'tag_button' |
| 115 }, | 118 }, |
| 116 radioButton: { | 119 radioButton: { |
| 117 msgId: 'input_type_radio' | 120 msgId: 'input_type_radio' |
| 118 }, | 121 }, |
| 122 spinButton: { |
| 123 msgId: 'aria_role_combobox', |
| 124 earcon: 'LISTBOX' |
| 125 }, |
| 119 textBox: { | 126 textBox: { |
| 120 msgId: 'input_type_text', | 127 msgId: 'input_type_text', |
| 121 earcon: 'EDITABLE_TEXT' | 128 earcon: 'EDITABLE_TEXT' |
| 122 }, | 129 }, |
| 123 textField: { | 130 textField: { |
| 124 msgId: 'input_type_text', | 131 msgId: 'input_type_text', |
| 125 earcon: 'EDITABLE_TEXT' | 132 earcon: 'EDITABLE_TEXT' |
| 126 }, | 133 }, |
| 134 time: { |
| 135 msgId: 'tag_time' |
| 136 }, |
| 127 toolbar: { | 137 toolbar: { |
| 128 msgId: 'aria_role_toolbar' | 138 msgId: 'aria_role_toolbar' |
| 129 } | 139 } |
| 130 }; | 140 }; |
| 131 | 141 |
| 132 /** | 142 /** |
| 133 * Metadata about supported automation states. | 143 * Metadata about supported automation states. |
| 134 * @const {!Object<string, | 144 * @const {!Object<string, |
| 135 * {on: {msgId: string, earconId: string}, | 145 * {on: {msgId: string, earconId: string}, |
| 136 * off: {msgId: string, earconId: string}}>} | 146 * off: {msgId: string, earconId: string}}>} |
| (...skipping 12 matching lines...) Expand all Loading... |
| 149 } | 159 } |
| 150 }; | 160 }; |
| 151 | 161 |
| 152 /** | 162 /** |
| 153 * Rules specifying format of AutomationNodes for output. | 163 * Rules specifying format of AutomationNodes for output. |
| 154 * @type {!Object<string, Object<string, Object<string, string>>>} | 164 * @type {!Object<string, Object<string, Object<string, string>>>} |
| 155 */ | 165 */ |
| 156 Output.RULES = { | 166 Output.RULES = { |
| 157 navigate: { | 167 navigate: { |
| 158 'default': { | 168 'default': { |
| 159 speak: '$name $value $role', | 169 speak: '$name $value $description $help $role', |
| 160 braille: '' | 170 braille: '' |
| 161 }, | 171 }, |
| 162 alert: { | 172 alert: { |
| 163 speak: '!doNotInterrupt $role $descendants' | 173 speak: '!doNotInterrupt $role $descendants' |
| 164 }, | 174 }, |
| 165 checkBox: { | 175 checkBox: { |
| 166 speak: '$name $role $checked' | 176 speak: '$name $role $checked' |
| 167 }, | 177 }, |
| 178 date: { |
| 179 enter: '$name $role', |
| 180 leave: '@exited_container($role)' |
| 181 }, |
| 168 dialog: { | 182 dialog: { |
| 169 enter: '$name $role' | 183 enter: '$name $role' |
| 170 }, | 184 }, |
| 171 heading: { | 185 heading: { |
| 172 enter: '@tag_h+$hierarchicalLevel', | 186 enter: '@tag_h+$hierarchicalLevel', |
| 173 speak: '@tag_h+$hierarchicalLevel $name=' | 187 speak: '@tag_h+$hierarchicalLevel $name=' |
| 174 }, | 188 }, |
| 175 inlineTextBox: { | 189 inlineTextBox: { |
| 176 speak: '$value=' | 190 speak: '$value=' |
| 177 }, | 191 }, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 200 }, | 214 }, |
| 201 popUpButton: { | 215 popUpButton: { |
| 202 speak: '$value $name $role @aria_has_popup ' + | 216 speak: '$value $name $role @aria_has_popup ' + |
| 203 '$if($collapsed, @aria_expanded_false, @aria_expanded_true)' | 217 '$if($collapsed, @aria_expanded_false, @aria_expanded_true)' |
| 204 }, | 218 }, |
| 205 radioButton: { | 219 radioButton: { |
| 206 speak: '$if($checked, @describe_radio_selected($name), ' + | 220 speak: '$if($checked, @describe_radio_selected($name), ' + |
| 207 '@describe_radio_unselected($name))' | 221 '@describe_radio_unselected($name))' |
| 208 }, | 222 }, |
| 209 slider: { | 223 slider: { |
| 210 speak: '@describe_slider($value, $name)' | 224 speak: '@describe_slider($value, $name) $help' |
| 211 }, | 225 }, |
| 212 staticText: { | 226 staticText: { |
| 213 speak: '$value $name' | 227 speak: '$value $name' |
| 214 }, | 228 }, |
| 215 tab: { | 229 tab: { |
| 216 speak: '@describe_tab($name)' | 230 speak: '@describe_tab($name)' |
| 217 }, | 231 }, |
| 232 textField: { |
| 233 speak: '$name $value $if(' + |
| 234 '$textInputType, @input_type_+$textInputType, @input_type_text) ' + |
| 235 '$earcon(EDITABLE_TEXT)', |
| 236 braille: '' |
| 237 }, |
| 238 time: { |
| 239 enter: '$name $role', |
| 240 leave: '@exited_container($role)' |
| 241 }, |
| 218 toolbar: { | 242 toolbar: { |
| 219 enter: '$name $role' | 243 enter: '$name $role' |
| 220 }, | 244 }, |
| 221 window: { | 245 window: { |
| 222 enter: '$name', | 246 enter: '$name', |
| 223 speak: '@describe_window($name) $earcon(OBJECT_OPEN)' | 247 speak: '@describe_window($name) $earcon(OBJECT_OPEN)' |
| 224 } | 248 } |
| 225 }, | 249 }, |
| 226 menuStart: { | 250 menuStart: { |
| 227 'default': { | 251 'default': { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 * Possible events handled by ChromeVox internally. | 320 * Possible events handled by ChromeVox internally. |
| 297 * @enum {string} | 321 * @enum {string} |
| 298 */ | 322 */ |
| 299 Output.EventType = { | 323 Output.EventType = { |
| 300 NAVIGATE: 'navigate' | 324 NAVIGATE: 'navigate' |
| 301 }; | 325 }; |
| 302 | 326 |
| 303 Output.prototype = { | 327 Output.prototype = { |
| 304 /** | 328 /** |
| 305 * Gets the output buffer for speech. | 329 * Gets the output buffer for speech. |
| 330 * @param {string=} opt_separator Used to join components of the output. |
| 306 * @return {!cvox.Spannable} | 331 * @return {!cvox.Spannable} |
| 307 */ | 332 */ |
| 308 toSpannable: function() { | 333 toSpannable: function(opt_separator) { |
| 334 opt_separator = opt_separator || ''; |
| 309 return this.buffer_.reduce(function(prev, cur) { | 335 return this.buffer_.reduce(function(prev, cur) { |
| 336 if (prev === null) |
| 337 return cur; |
| 338 prev.append(opt_separator); |
| 310 prev.append(cur); | 339 prev.append(cur); |
| 311 return prev; | 340 return prev; |
| 312 }, new cvox.Spannable()); | 341 }, null); |
| 313 }, | 342 }, |
| 314 | 343 |
| 315 /** | 344 /** |
| 345 * Gets the output buffer for speech with separator '|'. |
| 346 * @return {!cvox.Spannable} |
| 347 */ |
| 348 toSpannableForTest: function() { |
| 349 return this.toSpannable('|'); |
| 350 }, |
| 351 |
| 352 /** |
| 316 * Specify ranges for speech. | 353 * Specify ranges for speech. |
| 317 * @param {!cursors.Range} range | 354 * @param {!cursors.Range} range |
| 318 * @param {cursors.Range} prevRange | 355 * @param {cursors.Range} prevRange |
| 319 * @param {chrome.automation.EventType|Output.EventType} type | 356 * @param {chrome.automation.EventType|Output.EventType} type |
| 320 * @return {!Output} | 357 * @return {!Output} |
| 321 */ | 358 */ |
| 322 withSpeech: function(range, prevRange, type) { | 359 withSpeech: function(range, prevRange, type) { |
| 323 this.formatOptions_ = {speech: true, braille: false, location: true}; | 360 this.formatOptions_ = {speech: true, braille: false, location: true}; |
| 324 this.render_(range, prevRange, type, this.buffer_); | 361 this.render_(range, prevRange, type, this.buffer_); |
| 325 return this; | 362 return this; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 node.attributes.textSelEnd)); | 566 node.attributes.textSelEnd)); |
| 530 } | 567 } |
| 531 } | 568 } |
| 532 // Annotate this as a name so we don't duplicate names from ancestors. | 569 // Annotate this as a name so we don't duplicate names from ancestors. |
| 533 if (node.role == chrome.automation.RoleType.inlineTextBox) | 570 if (node.role == chrome.automation.RoleType.inlineTextBox) |
| 534 token = 'name'; | 571 token = 'name'; |
| 535 options.annotation.push(token); | 572 options.annotation.push(token); |
| 536 this.append_(buff, text, options); | 573 this.append_(buff, text, options); |
| 537 } else if (token == 'indexInParent') { | 574 } else if (token == 'indexInParent') { |
| 538 options.annotation.push(token); | 575 options.annotation.push(token); |
| 539 this.append_(buff, node.indexInParent + 1); | 576 this.append_(buff, String(node.indexInParent + 1)); |
| 540 } else if (token == 'parentChildCount') { | 577 } else if (token == 'parentChildCount') { |
| 541 options.annotation.push(token); | 578 options.annotation.push(token); |
| 542 if (node.parent) | 579 if (node.parent) |
| 543 this.append_(buff, node.parent.children.length); | 580 this.append_(buff, String(node.parent.children.length)); |
| 544 } else if (token == 'state') { | 581 } else if (token == 'state') { |
| 545 options.annotation.push(token); | 582 options.annotation.push(token); |
| 546 Object.getOwnPropertyNames(node.state).forEach(function(s) { | 583 Object.getOwnPropertyNames(node.state).forEach(function(s) { |
| 547 this.append_(buff, s, options); | 584 this.append_(buff, s, options); |
| 548 }.bind(this)); | 585 }.bind(this)); |
| 549 } else if (token == 'find') { | 586 } else if (token == 'find') { |
| 550 // Find takes two arguments: JSON query string and format string. | 587 // Find takes two arguments: JSON query string and format string. |
| 551 if (tree.firstChild) { | 588 if (tree.firstChild) { |
| 552 var jsonQuery = tree.firstChild.value; | 589 var jsonQuery = tree.firstChild.value; |
| 553 node = node.find( | 590 node = node.find( |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 } | 904 } |
| 868 | 905 |
| 869 if (currentNode != root) | 906 if (currentNode != root) |
| 870 throw 'Unbalanced parenthesis.'; | 907 throw 'Unbalanced parenthesis.'; |
| 871 | 908 |
| 872 return root; | 909 return root; |
| 873 } | 910 } |
| 874 }; | 911 }; |
| 875 | 912 |
| 876 }); // goog.scope | 913 }); // goog.scope |
| OLD | NEW |