| 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 |