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 |