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 A utility class for building NavDescriptions from the dom. | 6 * @fileoverview A utility class for building NavDescriptions from the dom. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 goog.provide('cvox.DescriptionUtil'); | 10 goog.provide('cvox.DescriptionUtil'); |
11 | 11 |
12 goog.require('cvox.AriaUtil'); | 12 goog.require('cvox.AriaUtil'); |
13 goog.require('cvox.AuralStyleUtil'); | 13 goog.require('cvox.AuralStyleUtil'); |
14 goog.require('cvox.BareObjectWalker'); | 14 goog.require('cvox.BareObjectWalker'); |
15 goog.require('cvox.CursorSelection'); | 15 goog.require('cvox.CursorSelection'); |
16 goog.require('cvox.DomUtil'); | 16 goog.require('cvox.DomUtil'); |
17 goog.require('cvox.EarconUtil'); | 17 goog.require('cvox.EarconUtil'); |
18 goog.require('cvox.MathmlStore'); | 18 goog.require('cvox.MathmlStore'); |
19 goog.require('cvox.NavDescription'); | 19 goog.require('cvox.NavDescription'); |
20 goog.require('cvox.SpeechRuleEngine'); | 20 goog.require('cvox.SpeechRuleEngine'); |
21 goog.require('cvox.TraverseMath'); | 21 goog.require('cvox.TraverseMath'); |
22 | 22 |
23 | 23 |
24 /** | 24 /** |
25 * Lists all Node tagName's who's description is derived from its subtree. | 25 * Lists all Node tagName's who's description is derived from its subtree. |
26 * @type {Object.<string, boolean>} | 26 * @type {Object<string, boolean>} |
27 */ | 27 */ |
28 cvox.DescriptionUtil.COLLECTION_NODE_TYPE = { | 28 cvox.DescriptionUtil.COLLECTION_NODE_TYPE = { |
29 'H1': true, | 29 'H1': true, |
30 'H2': true, | 30 'H2': true, |
31 'H3': true, | 31 'H3': true, |
32 'H4': true, | 32 'H4': true, |
33 'H5': true, | 33 'H5': true, |
34 'H6': true | 34 'H6': true |
35 }; | 35 }; |
36 | 36 |
37 /** | 37 /** |
38 * Get a control's complete description in the same format as if you | 38 * Get a control's complete description in the same format as if you |
39 * navigated to the node. | 39 * navigated to the node. |
40 * @param {Element} control A control. | 40 * @param {Element} control A control. |
41 * @param {Array.<Node>=} opt_changedAncestors The changed ancestors that will | 41 * @param {Array<Node>=} opt_changedAncestors The changed ancestors that will |
42 * be used to determine what needs to be spoken. If this is not provided, the | 42 * be used to determine what needs to be spoken. If this is not provided, the |
43 * ancestors used to determine what needs to be spoken will just be the control | 43 * ancestors used to determine what needs to be spoken will just be the control |
44 * itself and its surrounding control if it has one. | 44 * itself and its surrounding control if it has one. |
45 * @return {cvox.NavDescription} The description of the control. | 45 * @return {cvox.NavDescription} The description of the control. |
46 */ | 46 */ |
47 cvox.DescriptionUtil.getControlDescription = | 47 cvox.DescriptionUtil.getControlDescription = |
48 function(control, opt_changedAncestors) { | 48 function(control, opt_changedAncestors) { |
49 var ancestors = [control]; | 49 var ancestors = [control]; |
50 if (opt_changedAncestors && (opt_changedAncestors.length > 0)) { | 50 if (opt_changedAncestors && (opt_changedAncestors.length > 0)) { |
51 ancestors = opt_changedAncestors; | 51 ancestors = opt_changedAncestors; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 | 84 |
85 return description; | 85 return description; |
86 }; | 86 }; |
87 | 87 |
88 | 88 |
89 /** | 89 /** |
90 * Returns a description of a navigation from an array of changed | 90 * Returns a description of a navigation from an array of changed |
91 * ancestor nodes. The ancestors are in order from the highest in the | 91 * ancestor nodes. The ancestors are in order from the highest in the |
92 * tree to the lowest, i.e. ending with the current leaf node. | 92 * tree to the lowest, i.e. ending with the current leaf node. |
93 * | 93 * |
94 * @param {Array.<Node>} ancestorsArray An array of ancestor nodes. | 94 * @param {Array<Node>} ancestorsArray An array of ancestor nodes. |
95 * @param {boolean} recursive Whether or not the element's subtree should | 95 * @param {boolean} recursive Whether or not the element's subtree should |
96 * be used; true by default. | 96 * be used; true by default. |
97 * @param {number} verbosity The verbosity setting. | 97 * @param {number} verbosity The verbosity setting. |
98 * @return {cvox.NavDescription} The description of the navigation action. | 98 * @return {cvox.NavDescription} The description of the navigation action. |
99 */ | 99 */ |
100 cvox.DescriptionUtil.getDescriptionFromAncestors = function( | 100 cvox.DescriptionUtil.getDescriptionFromAncestors = function( |
101 ancestorsArray, recursive, verbosity) { | 101 ancestorsArray, recursive, verbosity) { |
102 if (typeof(recursive) === 'undefined') { | 102 if (typeof(recursive) === 'undefined') { |
103 recursive = true; | 103 recursive = true; |
104 } | 104 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 /** | 175 /** |
176 * Returns a description of a navigation from an array of changed | 176 * Returns a description of a navigation from an array of changed |
177 * ancestor nodes. The ancestors are in order from the highest in the | 177 * ancestor nodes. The ancestors are in order from the highest in the |
178 * tree to the lowest, i.e. ending with the current leaf node. | 178 * tree to the lowest, i.e. ending with the current leaf node. |
179 * | 179 * |
180 * @param {Node} prevNode The previous node in navigation. | 180 * @param {Node} prevNode The previous node in navigation. |
181 * @param {Node} node The current node in navigation. | 181 * @param {Node} node The current node in navigation. |
182 * @param {boolean} recursive Whether or not the element's subtree should | 182 * @param {boolean} recursive Whether or not the element's subtree should |
183 * be used; true by default. | 183 * be used; true by default. |
184 * @param {number} verbosity The verbosity setting. | 184 * @param {number} verbosity The verbosity setting. |
185 * @return {!Array.<cvox.NavDescription>} The description of the navigation | 185 * @return {!Array<cvox.NavDescription>} The description of the navigation |
186 * action. | 186 * action. |
187 */ | 187 */ |
188 cvox.DescriptionUtil.getDescriptionFromNavigation = | 188 cvox.DescriptionUtil.getDescriptionFromNavigation = |
189 function(prevNode, node, recursive, verbosity) { | 189 function(prevNode, node, recursive, verbosity) { |
190 if (!prevNode || !node) { | 190 if (!prevNode || !node) { |
191 return []; | 191 return []; |
192 } | 192 } |
193 | 193 |
194 // Specialized math descriptions. | 194 // Specialized math descriptions. |
195 if (cvox.DomUtil.isMath(node) && | 195 if (cvox.DomUtil.isMath(node) && |
(...skipping 29 matching lines...) Expand all Loading... |
225 | 225 |
226 /** | 226 /** |
227 * Returns an array of NavDescriptions that includes everything that would be | 227 * Returns an array of NavDescriptions that includes everything that would be |
228 * spoken by an object walker while traversing from prevSel to sel. | 228 * spoken by an object walker while traversing from prevSel to sel. |
229 * It also includes any necessary annotations and context about the set of | 229 * It also includes any necessary annotations and context about the set of |
230 * descriptions. This function is here because most (currently all) walkers | 230 * descriptions. This function is here because most (currently all) walkers |
231 * that iterate over non-leaf nodes need this sort of description. | 231 * that iterate over non-leaf nodes need this sort of description. |
232 * This is an awkward design, and should be changed in the future. | 232 * This is an awkward design, and should be changed in the future. |
233 * @param {!cvox.CursorSelection} prevSel The previous selection. | 233 * @param {!cvox.CursorSelection} prevSel The previous selection. |
234 * @param {!cvox.CursorSelection} sel The selection. | 234 * @param {!cvox.CursorSelection} sel The selection. |
235 * @return {!Array.<!cvox.NavDescription>} The descriptions as described above. | 235 * @return {!Array<!cvox.NavDescription>} The descriptions as described above. |
236 */ | 236 */ |
237 cvox.DescriptionUtil.getCollectionDescription = function(prevSel, sel) { | 237 cvox.DescriptionUtil.getCollectionDescription = function(prevSel, sel) { |
238 var descriptions = cvox.DescriptionUtil.getRawDescriptions_(prevSel, sel); | 238 var descriptions = cvox.DescriptionUtil.getRawDescriptions_(prevSel, sel); |
239 cvox.DescriptionUtil.insertCollectionDescription_(descriptions); | 239 cvox.DescriptionUtil.insertCollectionDescription_(descriptions); |
240 return descriptions; | 240 return descriptions; |
241 }; | 241 }; |
242 | 242 |
243 | 243 |
244 /** | 244 /** |
245 * Used for getting collection descriptions. | 245 * Used for getting collection descriptions. |
246 * @type {!cvox.BareObjectWalker} | 246 * @type {!cvox.BareObjectWalker} |
247 * @private | 247 * @private |
248 */ | 248 */ |
249 cvox.DescriptionUtil.subWalker_ = new cvox.BareObjectWalker(); | 249 cvox.DescriptionUtil.subWalker_ = new cvox.BareObjectWalker(); |
250 | 250 |
251 | 251 |
252 /** | 252 /** |
253 * Returns the descriptions that would be gotten by an object walker. | 253 * Returns the descriptions that would be gotten by an object walker. |
254 * @param {!cvox.CursorSelection} prevSel The previous selection. | 254 * @param {!cvox.CursorSelection} prevSel The previous selection. |
255 * @param {!cvox.CursorSelection} sel The selection. | 255 * @param {!cvox.CursorSelection} sel The selection. |
256 * @return {!Array.<!cvox.NavDescription>} The descriptions. | 256 * @return {!Array<!cvox.NavDescription>} The descriptions. |
257 * @private | 257 * @private |
258 */ | 258 */ |
259 cvox.DescriptionUtil.getRawDescriptions_ = function(prevSel, sel) { | 259 cvox.DescriptionUtil.getRawDescriptions_ = function(prevSel, sel) { |
260 // Use a object walker in non-smart mode to traverse all of the | 260 // Use a object walker in non-smart mode to traverse all of the |
261 // nodes inside the current smart node and return their annotations. | 261 // nodes inside the current smart node and return their annotations. |
262 var descriptions = []; | 262 var descriptions = []; |
263 | 263 |
264 // We want the descriptions to be in forward order whether or not the | 264 // We want the descriptions to be in forward order whether or not the |
265 // selection is reversed. | 265 // selection is reversed. |
266 sel = sel.clone().setReversed(false); | 266 sel = sel.clone().setReversed(false); |
(...skipping 29 matching lines...) Expand all Loading... |
296 } | 296 } |
297 | 297 |
298 return descriptions; | 298 return descriptions; |
299 }; | 299 }; |
300 | 300 |
301 /** | 301 /** |
302 * Returns the full descriptions of the child nodes that would be gotten by an | 302 * Returns the full descriptions of the child nodes that would be gotten by an |
303 * object walker. | 303 * object walker. |
304 * @param {?Element} prevnode The previous element if there is one. | 304 * @param {?Element} prevnode The previous element if there is one. |
305 * @param {!Element} node The target element. | 305 * @param {!Element} node The target element. |
306 * @return {!Array.<!cvox.NavDescription>} The descriptions. | 306 * @return {!Array<!cvox.NavDescription>} The descriptions. |
307 */ | 307 */ |
308 cvox.DescriptionUtil.getFullDescriptionsFromChildren = | 308 cvox.DescriptionUtil.getFullDescriptionsFromChildren = |
309 function(prevnode, node) { | 309 function(prevnode, node) { |
310 var descriptions = []; | 310 var descriptions = []; |
311 if (!node) { | 311 if (!node) { |
312 return descriptions; | 312 return descriptions; |
313 } | 313 } |
314 var desc; | 314 var desc; |
315 if (cvox.DomUtil.isLeafNode(node)) { | 315 if (cvox.DomUtil.isLeafNode(node)) { |
316 var ancestors; | 316 var ancestors; |
(...skipping 28 matching lines...) Expand all Loading... |
345 curSel = /** @type {!cvox.CursorSelection} */ (curSel); | 345 curSel = /** @type {!cvox.CursorSelection} */ (curSel); |
346 prevnode = node; | 346 prevnode = node; |
347 node = curSel.start.node; | 347 node = curSel.start.node; |
348 } | 348 } |
349 return descriptions; | 349 return descriptions; |
350 }; | 350 }; |
351 | 351 |
352 | 352 |
353 /** | 353 /** |
354 * Modify the descriptions to say that it is a collection. | 354 * Modify the descriptions to say that it is a collection. |
355 * @param {Array.<cvox.NavDescription>} descriptions The descriptions. | 355 * @param {Array<cvox.NavDescription>} descriptions The descriptions. |
356 * @private | 356 * @private |
357 */ | 357 */ |
358 cvox.DescriptionUtil.insertCollectionDescription_ = function(descriptions) { | 358 cvox.DescriptionUtil.insertCollectionDescription_ = function(descriptions) { |
359 var annotations = cvox.DescriptionUtil.getAnnotations_(descriptions); | 359 var annotations = cvox.DescriptionUtil.getAnnotations_(descriptions); |
360 // If all of the items have the same annotation, describe it as a | 360 // If all of the items have the same annotation, describe it as a |
361 // <annotation> collection with <n> items. Currently only enabled | 361 // <annotation> collection with <n> items. Currently only enabled |
362 // for links, but support should be added for any other type that | 362 // for links, but support should be added for any other type that |
363 // makes sense. | 363 // makes sense. |
364 if (descriptions.length >= 3 && | 364 if (descriptions.length >= 3 && |
365 descriptions[0].context.length == 0 && | 365 descriptions[0].context.length == 0 && |
(...skipping 14 matching lines...) Expand all Loading... |
380 'collection', | 380 'collection', |
381 [commonAnnotation, | 381 [commonAnnotation, |
382 cvox.ChromeVox.msgs.getNumber(descriptions.length)]) | 382 cvox.ChromeVox.msgs.getNumber(descriptions.length)]) |
383 })); | 383 })); |
384 } | 384 } |
385 }; | 385 }; |
386 | 386 |
387 | 387 |
388 /** | 388 /** |
389 * Pulls the annotations from a description array. | 389 * Pulls the annotations from a description array. |
390 * @param {Array.<cvox.NavDescription>} descriptions The descriptions. | 390 * @param {Array<cvox.NavDescription>} descriptions The descriptions. |
391 * @return {Array.<string>} The annotations. | 391 * @return {Array<string>} The annotations. |
392 * @private | 392 * @private |
393 */ | 393 */ |
394 cvox.DescriptionUtil.getAnnotations_ = function(descriptions) { | 394 cvox.DescriptionUtil.getAnnotations_ = function(descriptions) { |
395 var annotations = []; | 395 var annotations = []; |
396 for (var i = 0; i < descriptions.length; ++i) { | 396 for (var i = 0; i < descriptions.length; ++i) { |
397 var description = descriptions[i]; | 397 var description = descriptions[i]; |
398 if (annotations.indexOf(description.annotation) == -1) { | 398 if (annotations.indexOf(description.annotation) == -1) { |
399 // If we have an Internal link collection, call it Link collection. | 399 // If we have an Internal link collection, call it Link collection. |
400 // NOTE(deboer): The message comparison is a symptom of a bad design. | 400 // NOTE(deboer): The message comparison is a symptom of a bad design. |
401 // I suspect this code belongs elsewhere but I don't know where, yet. | 401 // I suspect this code belongs elsewhere but I don't know where, yet. |
(...skipping 23 matching lines...) Expand all Loading... |
425 * @param {string} annotation The annotation text. | 425 * @param {string} annotation The annotation text. |
426 * @return {boolean} If this annotation should be a collection. | 426 * @return {boolean} If this annotation should be a collection. |
427 * @private | 427 * @private |
428 */ | 428 */ |
429 cvox.DescriptionUtil.isAnnotationCollection_ = function(annotation) { | 429 cvox.DescriptionUtil.isAnnotationCollection_ = function(annotation) { |
430 return (annotation == cvox.ChromeVox.msgs.getMsg('tag_link')); | 430 return (annotation == cvox.ChromeVox.msgs.getMsg('tag_link')); |
431 }; | 431 }; |
432 | 432 |
433 /** | 433 /** |
434 * Determines whether to describe the exit of an ancestor chain. | 434 * Determines whether to describe the exit of an ancestor chain. |
435 * @param {Array.<Node>} ancestors The ancestors exited during navigation. | 435 * @param {Array<Node>} ancestors The ancestors exited during navigation. |
436 * @return {boolean} The result. | 436 * @return {boolean} The result. |
437 * @private | 437 * @private |
438 */ | 438 */ |
439 cvox.DescriptionUtil.shouldDescribeExit_ = function(ancestors) { | 439 cvox.DescriptionUtil.shouldDescribeExit_ = function(ancestors) { |
440 return ancestors.some(function(node) { | 440 return ancestors.some(function(node) { |
441 switch (node.tagName) { | 441 switch (node.tagName) { |
442 case 'TABLE': | 442 case 'TABLE': |
443 case 'MATH': | 443 case 'MATH': |
444 return true; | 444 return true; |
445 } | 445 } |
446 return cvox.AriaUtil.isLandmark(node); | 446 return cvox.AriaUtil.isLandmark(node); |
447 }); | 447 }); |
448 }; | 448 }; |
449 | 449 |
450 | 450 |
451 // TODO(sorge): Bad naming...this thing returns *multiple* descriptions. | 451 // TODO(sorge): Bad naming...this thing returns *multiple* descriptions. |
452 /** | 452 /** |
453 * Generates a description for a math node. | 453 * Generates a description for a math node. |
454 * @param {!Node} node The given node. | 454 * @param {!Node} node The given node. |
455 * @return {!Array.<cvox.NavDescription>} A list of Navigation descriptions. | 455 * @return {!Array<cvox.NavDescription>} A list of Navigation descriptions. |
456 */ | 456 */ |
457 cvox.DescriptionUtil.getMathDescription = function(node) { | 457 cvox.DescriptionUtil.getMathDescription = function(node) { |
458 // TODO (sorge) This function should evantually be removed. Descriptions | 458 // TODO (sorge) This function should evantually be removed. Descriptions |
459 // should come directly from the speech rule engine, taking information on | 459 // should come directly from the speech rule engine, taking information on |
460 // verbosity etc. into account. | 460 // verbosity etc. into account. |
461 var speechEngine = cvox.SpeechRuleEngine.getInstance(); | 461 var speechEngine = cvox.SpeechRuleEngine.getInstance(); |
462 var traverse = cvox.TraverseMath.getInstance(); | 462 var traverse = cvox.TraverseMath.getInstance(); |
463 speechEngine.parameterize(cvox.MathmlStore.getInstance()); | 463 speechEngine.parameterize(cvox.MathmlStore.getInstance()); |
464 traverse.initialize(node); | 464 traverse.initialize(node); |
465 var ret = speechEngine.evaluateNode(traverse.activeNode); | 465 var ret = speechEngine.evaluateNode(traverse.activeNode); |
466 if (ret == []) { | 466 if (ret == []) { |
467 return [new cvox.NavDescription({'text': 'empty math'})]; | 467 return [new cvox.NavDescription({'text': 'empty math'})]; |
468 } | 468 } |
469 if (cvox.ChromeVox.verbosity == cvox.VERBOSITY_VERBOSE) { | 469 if (cvox.ChromeVox.verbosity == cvox.VERBOSITY_VERBOSE) { |
470 ret[ret.length - 1].annotation = 'math'; | 470 ret[ret.length - 1].annotation = 'math'; |
471 } | 471 } |
472 ret[0].pushEarcon(cvox.AbstractEarcons.SPECIAL_CONTENT); | 472 ret[0].pushEarcon(cvox.AbstractEarcons.SPECIAL_CONTENT); |
473 return ret; | 473 return ret; |
474 }; | 474 }; |
OLD | NEW |