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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 * The speech queue mode for the generated speech utterance. | 85 * The speech queue mode for the generated speech utterance. |
86 * @type {cvox.QueueMode} | 86 * @type {cvox.QueueMode} |
87 * @private | 87 * @private |
88 */ | 88 */ |
89 this.queueMode_ = cvox.QueueMode.QUEUE; | 89 this.queueMode_ = cvox.QueueMode.QUEUE; |
90 | 90 |
91 /** | 91 /** |
92 * @type {boolean} | 92 * @type {boolean} |
93 * @private | 93 * @private |
94 */ | 94 */ |
95 this.outputContextFirst_ = localStorage['outputContextFirst'] == 'true'; | 95 this.outputContextFirst_ = false; |
96 }; | 96 }; |
97 | 97 |
98 /** | 98 /** |
99 * Delimiter to use between output values. | 99 * Delimiter to use between output values. |
100 * @type {string} | 100 * @type {string} |
101 */ | 101 */ |
102 Output.SPACE = ' '; | 102 Output.SPACE = ' '; |
103 | 103 |
104 /** | 104 /** |
105 * Metadata about supported automation roles. | 105 * Metadata about supported automation roles. |
106 * @const {Object<{msgId: string, | 106 * @const {Object<{msgId: string, |
107 * earconId: (string|undefined), | 107 * earconId: (string|undefined), |
108 * inherits: (string|undefined), | 108 * inherits: (string|undefined), |
109 * ignoreAncestry: (boolean|undefined)}>} | 109 * outputContextFirst: (boolean|undefined)}>} |
110 * msgId: the message id of the role. | 110 * msgId: the message id of the role. |
111 * earconId: an optional earcon to play when encountering the role. | 111 * earconId: an optional earcon to play when encountering the role. |
112 * inherits: inherits rules from this role. | 112 * inherits: inherits rules from this role. |
113 * ignoreAncestry: don't output ancestry changes when encountering this role. | 113 * outputContextFirst: where to place the context output. |
114 * @private | 114 * @private |
115 */ | 115 */ |
116 Output.ROLE_INFO_ = { | 116 Output.ROLE_INFO_ = { |
117 alert: { | 117 alert: { |
118 msgId: 'role_alert', | 118 msgId: 'role_alert', |
119 earconId: 'ALERT_NONMODAL' | 119 earconId: 'ALERT_NONMODAL' |
120 }, | 120 }, |
121 alertDialog: { | 121 alertDialog: { |
122 msgId: 'role_alertdialog' | 122 msgId: 'role_alertdialog' |
123 }, | 123 }, |
(...skipping 18 matching lines...) Expand all Loading... | |
142 earconId: 'BUTTON' | 142 earconId: 'BUTTON' |
143 }, | 143 }, |
144 checkBox: { | 144 checkBox: { |
145 msgId: 'role_checkbox' | 145 msgId: 'role_checkbox' |
146 }, | 146 }, |
147 columnHeader: { | 147 columnHeader: { |
148 msgId: 'role_columnheader', | 148 msgId: 'role_columnheader', |
149 inherits: 'cell' | 149 inherits: 'cell' |
150 }, | 150 }, |
151 comboBox: { | 151 comboBox: { |
152 msgId: 'role_combobox' | 152 msgId: 'role_combobox', |
153 earconId: 'LISTBOX' | |
153 }, | 154 }, |
154 complementary: { | 155 complementary: { |
155 msgId: 'role_complementary', | 156 msgId: 'role_complementary', |
156 inherits: 'abstractContainer' | 157 inherits: 'abstractContainer' |
157 }, | 158 }, |
158 contentInfo: { | 159 contentInfo: { |
159 msgId: 'role_contentinfo', | 160 msgId: 'role_contentinfo', |
160 inherits: 'abstractContainer' | 161 inherits: 'abstractContainer' |
161 }, | 162 }, |
162 date: { | 163 date: { |
163 msgId: 'input_type_date', | 164 msgId: 'input_type_date', |
164 inherits: 'abstractContainer' | 165 inherits: 'abstractContainer' |
165 }, | 166 }, |
166 definition: { | 167 definition: { |
167 msgId: 'role_definition', | 168 msgId: 'role_definition', |
168 inherits: 'abstractContainer' | 169 inherits: 'abstractContainer' |
169 }, | 170 }, |
170 dialog: { | 171 dialog: { |
dmazzoni
2016/10/04 20:00:34
How about outputContextFirst for dialog, alertdial
| |
171 msgId: 'role_dialog' | 172 msgId: 'role_dialog' |
172 }, | 173 }, |
173 directory: { | 174 directory: { |
174 msgId: 'role_directory', | 175 msgId: 'role_directory', |
175 inherits: 'abstractContainer' | 176 inherits: 'abstractContainer' |
176 }, | 177 }, |
177 document: { | 178 document: { |
178 msgId: 'role_document', | 179 msgId: 'role_document', |
179 inherits: 'abstractContainer' | 180 inherits: 'abstractContainer' |
180 }, | 181 }, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 inherits: 'abstractContainer' | 224 inherits: 'abstractContainer' |
224 }, | 225 }, |
225 marquee: { | 226 marquee: { |
226 msgId: 'role_marquee', | 227 msgId: 'role_marquee', |
227 }, | 228 }, |
228 math: { | 229 math: { |
229 msgId: 'role_math', | 230 msgId: 'role_math', |
230 inherits: 'abstractContainer' | 231 inherits: 'abstractContainer' |
231 }, | 232 }, |
232 menu: { | 233 menu: { |
233 msgId: 'role_menu' | 234 msgId: 'role_menu', |
235 outputContextFirst: true | |
234 }, | 236 }, |
235 menuBar: { | 237 menuBar: { |
236 msgId: 'role_menubar', | 238 msgId: 'role_menubar', |
237 }, | 239 }, |
238 menuItem: { | 240 menuItem: { |
239 msgId: 'role_menuitem' | 241 msgId: 'role_menuitem' |
240 }, | 242 }, |
241 menuItemCheckBox: { | 243 menuItemCheckBox: { |
242 msgId: 'role_menuitemcheckbox' | 244 msgId: 'role_menuitemcheckbox' |
243 }, | 245 }, |
(...skipping 17 matching lines...) Expand all Loading... | |
261 popUpButton: { | 263 popUpButton: { |
262 msgId: 'role_button', | 264 msgId: 'role_button', |
263 earconId: 'POP_UP_BUTTON' | 265 earconId: 'POP_UP_BUTTON' |
264 }, | 266 }, |
265 radioButton: { | 267 radioButton: { |
266 msgId: 'role_radio' | 268 msgId: 'role_radio' |
267 }, | 269 }, |
268 radioGroup: { | 270 radioGroup: { |
269 msgId: 'role_radiogroup', | 271 msgId: 'role_radiogroup', |
270 }, | 272 }, |
273 rootWebArea: { | |
274 outputContextFirst: true | |
275 }, | |
271 row: { | 276 row: { |
272 msgId: 'role_row', | 277 msgId: 'role_row', |
273 inherits: 'abstractContainer' | 278 inherits: 'abstractContainer' |
274 }, | 279 }, |
275 rowHeader: { | 280 rowHeader: { |
276 msgId: 'role_rowheader', | 281 msgId: 'role_rowheader', |
277 inherits: 'cell' | 282 inherits: 'cell' |
278 }, | 283 }, |
279 scrollBar: { | 284 scrollBar: { |
280 msgId: 'role_scrollbar', | 285 msgId: 'role_scrollbar', |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 inherits: 'abstractContainer' | 321 inherits: 'abstractContainer' |
317 }, | 322 }, |
318 timer: { | 323 timer: { |
319 msgId: 'role_timer' | 324 msgId: 'role_timer' |
320 }, | 325 }, |
321 toolbar: { | 326 toolbar: { |
322 msgId: 'role_toolbar' | 327 msgId: 'role_toolbar' |
323 }, | 328 }, |
324 toggleButton: { | 329 toggleButton: { |
325 msgId: 'role_button', | 330 msgId: 'role_button', |
326 inherits: 'checkBox' | 331 inherits: 'checkBox', |
332 earconId: 'BUTTON' | |
327 }, | 333 }, |
328 tree: { | 334 tree: { |
329 msgId: 'role_tree' | 335 msgId: 'role_tree' |
330 }, | 336 }, |
331 treeItem: { | 337 treeItem: { |
332 msgId: 'role_treeitem' | 338 msgId: 'role_treeitem' |
333 } | 339 } |
334 }; | 340 }; |
335 | 341 |
336 /** | 342 /** |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
884 callback(); | 890 callback(); |
885 }.bind(this); | 891 }.bind(this); |
886 return this; | 892 return this; |
887 }, | 893 }, |
888 | 894 |
889 /** | 895 /** |
890 * Executes all specified output. | 896 * Executes all specified output. |
891 */ | 897 */ |
892 go: function() { | 898 go: function() { |
893 // Speech. | 899 // Speech. |
894 var queueMode = this.queueMode_; | 900 var queueMode = cvox.QueueMode.FLUSH; |
895 this.speechBuffer_.forEach(function(buff, i, a) { | 901 if (Output.forceModeForNextSpeechUtterance_ !== undefined) |
896 if (Output.forceModeForNextSpeechUtterance_ !== undefined && | 902 queueMode = Output.forceModeForNextSpeechUtterance_; |
897 buff.length > 0) { | 903 else if (this.queueMode_ !== undefined) |
898 queueMode = Output.forceModeForNextSpeechUtterance_; | 904 queueMode = this.queueMode_; |
899 Output.forceModeForNextSpeechUtterance_ = undefined; | |
900 } | |
901 | 905 |
902 var speechProps = {}; | 906 if (this.speechBuffer_.length > 0) |
907 Output.forceModeForNextSpeechUtterance_ = undefined; | |
908 | |
909 for (var i = 0; i < this.speechBuffer_.length; i++) { | |
910 var buff = this.speechBuffer_[i]; | |
911 var speechProps = /** @type {Object} */( | |
912 buff.getSpanInstanceOf(Output.SpeechProperties)) || {}; | |
913 | |
914 speechProps.category = this.speechCategory_; | |
915 | |
903 (function() { | 916 (function() { |
904 var scopedBuff = buff; | 917 var scopedBuff = buff; |
905 speechProps = | |
906 scopedBuff.getSpanInstanceOf(Output.SpeechProperties) || {}; | |
907 speechProps.category = this.speechCategory_; | |
908 | |
909 speechProps['startCallback'] = function() { | 918 speechProps['startCallback'] = function() { |
910 var actions = scopedBuff.getSpansInstanceOf(Output.Action); | 919 var actions = scopedBuff.getSpansInstanceOf(Output.Action); |
911 if (actions) { | 920 if (actions) { |
912 actions.forEach(function(a) { | 921 actions.forEach(function(a) { |
913 a.run(); | 922 a.run(); |
914 }); | 923 }); |
915 } | 924 } |
916 }; | 925 }; |
917 }.bind(this)()); | 926 }()); |
918 | 927 |
919 if (this.speechEndCallback_ && i == a.length - 1) | 928 if (i == this.speechBuffer_.length - 1) |
920 speechProps['endCallback'] = this.speechEndCallback_; | 929 speechProps['endCallback'] = this.speechEndCallback_; |
921 else | 930 |
922 speechProps['endCallback'] = null; | |
923 cvox.ChromeVox.tts.speak( | 931 cvox.ChromeVox.tts.speak( |
924 buff.toString(), queueMode, speechProps); | 932 buff.toString(), queueMode, speechProps); |
925 queueMode = cvox.QueueMode.QUEUE; | 933 queueMode = cvox.QueueMode.QUEUE; |
926 }.bind(this)); | 934 } |
927 | 935 |
928 // Braille. | 936 // Braille. |
929 if (this.brailleBuffer_.length) { | 937 if (this.brailleBuffer_.length) { |
930 var buff = this.createBrailleOutput_(); | 938 var buff = this.createBrailleOutput_(); |
931 var selSpan = | 939 var selSpan = |
932 buff.getSpanInstanceOf(Output.SelectionSpan); | 940 buff.getSpanInstanceOf(Output.SelectionSpan); |
933 var startIndex = -1, endIndex = -1; | 941 var startIndex = -1, endIndex = -1; |
934 if (selSpan) { | 942 if (selSpan) { |
935 var valueStart = buff.getSpanStart(selSpan); | 943 var valueStart = buff.getSpanStart(selSpan); |
936 var valueEnd = buff.getSpanEnd(selSpan); | 944 var valueEnd = buff.getSpanEnd(selSpan); |
(...skipping 23 matching lines...) Expand all Loading... | |
960 * @param {!cursors.Range} range | 968 * @param {!cursors.Range} range |
961 * @param {cursors.Range} prevRange | 969 * @param {cursors.Range} prevRange |
962 * @param {EventType|Output.EventType} type | 970 * @param {EventType|Output.EventType} type |
963 * @param {!Array<Spannable>} buff Buffer to receive rendered output. | 971 * @param {!Array<Spannable>} buff Buffer to receive rendered output. |
964 * @private | 972 * @private |
965 */ | 973 */ |
966 render_: function(range, prevRange, type, buff) { | 974 render_: function(range, prevRange, type, buff) { |
967 if (prevRange && !prevRange.isValid()) | 975 if (prevRange && !prevRange.isValid()) |
968 prevRange = null; | 976 prevRange = null; |
969 | 977 |
978 // Scan ancestors to get the value of |outputContextFirst|. | |
979 var parent = range.start.node; | |
980 while (parent) { | |
981 if (Output.ROLE_INFO_[parent.role] && | |
982 Output.ROLE_INFO_[parent.role].outputContextFirst) { | |
983 this.outputContextFirst_ = true; | |
984 break; | |
985 } | |
986 parent = parent.parent; | |
987 } | |
988 | |
970 if (range.isSubNode()) | 989 if (range.isSubNode()) |
971 this.subNode_(range, prevRange, type, buff); | 990 this.subNode_(range, prevRange, type, buff); |
972 else | 991 else |
973 this.range_(range, prevRange, type, buff); | 992 this.range_(range, prevRange, type, buff); |
974 }, | 993 }, |
975 | 994 |
976 /** | 995 /** |
977 * Format the node given the format specifier. | 996 * Format the node given the format specifier. |
978 * @param {AutomationNode} node | 997 * @param {AutomationNode} node |
979 * @param {string|!Object} format The output format either specified as an | 998 * @param {string|!Object} format The output format either specified as an |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1357 }, | 1376 }, |
1358 | 1377 |
1359 /** | 1378 /** |
1360 * @param {!AutomationNode} node | 1379 * @param {!AutomationNode} node |
1361 * @param {!AutomationNode} prevNode | 1380 * @param {!AutomationNode} prevNode |
1362 * @param {EventType|Output.EventType} type | 1381 * @param {EventType|Output.EventType} type |
1363 * @param {!Array<Spannable>} buff | 1382 * @param {!Array<Spannable>} buff |
1364 * @private | 1383 * @private |
1365 */ | 1384 */ |
1366 ancestry_: function(node, prevNode, type, buff) { | 1385 ancestry_: function(node, prevNode, type, buff) { |
1367 // Check to see if ancestry output is ignored. | |
1368 if (Output.ROLE_INFO_[node.role] && | |
1369 Output.ROLE_INFO_[node.role].ignoreAncestry) | |
1370 return; | |
1371 | |
1372 var prevUniqueAncestors = | 1386 var prevUniqueAncestors = |
1373 AutomationUtil.getUniqueAncestors(node, prevNode); | 1387 AutomationUtil.getUniqueAncestors(node, prevNode); |
1374 var uniqueAncestors = AutomationUtil.getUniqueAncestors(prevNode, node); | 1388 var uniqueAncestors = AutomationUtil.getUniqueAncestors(prevNode, node); |
1375 | 1389 |
1376 // First, look up the event type's format block. | 1390 // First, look up the event type's format block. |
1377 // Navigate is the default event. | 1391 // Navigate is the default event. |
1378 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; | 1392 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; |
1379 | 1393 |
1380 var getMergedRoleBlock = function(role) { | 1394 var getMergedRoleBlock = function(role) { |
1381 var parentRole = (Output.ROLE_INFO_[role] || {}).inherits; | 1395 var parentRole = (Output.ROLE_INFO_[role] || {}).inherits; |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1708 /** | 1722 /** |
1709 * Gets the output buffer for braille. | 1723 * Gets the output buffer for braille. |
1710 * @return {!Spannable} | 1724 * @return {!Spannable} |
1711 */ | 1725 */ |
1712 get brailleOutputForTest() { | 1726 get brailleOutputForTest() { |
1713 return this.createBrailleOutput_(); | 1727 return this.createBrailleOutput_(); |
1714 } | 1728 } |
1715 }; | 1729 }; |
1716 | 1730 |
1717 }); // goog.scope | 1731 }); // goog.scope |
OLD | NEW |