Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js

Issue 1866043004: Add a nameFromNode attrib to link output rule (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 * Rules specifying format of AutomationNodes for output. 389 * Rules specifying format of AutomationNodes for output.
390 * @type {!Object<Object<Object<string>>>} 390 * @type {!Object<Object<Object<string>>>}
391 */ 391 */
392 Output.RULES = { 392 Output.RULES = {
393 navigate: { 393 navigate: {
394 'default': { 394 'default': {
395 speak: '$name $value $role $description', 395 speak: '$name $value $role $description',
396 braille: '' 396 braille: ''
397 }, 397 },
398 abstractContainer: { 398 abstractContainer: {
399 enter: '$name $role $description', 399 enter: '$nameFromNode $role $description',
400 leave: '@exited_container($role)' 400 leave: '@exited_container($role)'
401 }, 401 },
402 alert: { 402 alert: {
403 speak: '!doNotInterrupt $role $descendants' 403 speak: '!doNotInterrupt $role $descendants'
404 }, 404 },
405 alertDialog: { 405 alertDialog: {
406 enter: '$name $role $description $descendants' 406 enter: '$nameFromNode $role $description $descendants'
407 }, 407 },
408 cell: { 408 cell: {
409 enter: '@column_granularity $tableCellColumnIndex' 409 enter: '@column_granularity $tableCellColumnIndex'
410 }, 410 },
411 checkBox: { 411 checkBox: {
412 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' + 412 speak: '$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) ' +
413 '$name $role $checked $description' 413 '$name $role $checked $description'
414 }, 414 },
415 dialog: { 415 dialog: {
416 enter: '$name $role $description' 416 enter: '$nameFromNode $role $description'
417 }, 417 },
418 div: { 418 div: {
419 enter: '$name', 419 enter: '$nameFromNode',
420 speak: '$name $description' 420 speak: '$name $description'
421 }, 421 },
422 grid: { 422 grid: {
423 enter: '$name $role $description' 423 enter: '$nameFromNode $role $description'
424 }, 424 },
425 heading: { 425 heading: {
426 enter: '@tag_h+$hierarchicalLevel', 426 enter: '@tag_h+$hierarchicalLevel',
427 speak: '!relativePitch(hierarchicalLevel)' + 427 speak: '!relativePitch(hierarchicalLevel)' +
428 ' $nameOrDescendants= @tag_h+$hierarchicalLevel' 428 ' $nameOrDescendants= @tag_h+$hierarchicalLevel'
429 }, 429 },
430 inlineTextBox: { 430 inlineTextBox: {
431 speak: '$name=' 431 speak: '$name='
432 }, 432 },
433 link: { 433 link: {
434 enter: '$name= $if($visited, @visited_link, $role)', 434 enter: '$nameFromNode $if($visited, @visited_link, $role)',
435 speak: '$name= $if($visited, @visited_link, $role) $description' 435 speak: '$name= $if($visited, @visited_link, $role) $description'
436 }, 436 },
437 list: { 437 list: {
438 enter: '$role @@list_with_items($countChildren(listItem))' 438 enter: '$role @@list_with_items($countChildren(listItem))'
439 }, 439 },
440 listBox: { 440 listBox: {
441 enter: '$name $role @@list_with_items($countChildren(listBoxOption)) ' + 441 enter: '$nameFromNode' +
442 '$role @@list_with_items($countChildren(listBoxOption)) ' +
442 '$description' 443 '$description'
443 }, 444 },
444 listBoxOption: { 445 listBoxOption: {
445 speak: '$name $role @describe_index($indexInParent, $parentChildCount) ' + 446 speak: '$name $role @describe_index($indexInParent, $parentChildCount) ' +
446 '$description' 447 '$description'
447 }, 448 },
448 listItem: { 449 listItem: {
449 enter: '$role' 450 enter: '$role'
450 }, 451 },
451 menu: { 452 menu: {
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 else 917 else
917 this.range_(range, prevRange, type, buff); 918 this.range_(range, prevRange, type, buff);
918 }, 919 },
919 920
920 /** 921 /**
921 * Format the node given the format specifier. 922 * Format the node given the format specifier.
922 * @param {AutomationNode} node 923 * @param {AutomationNode} node
923 * @param {string|!Object} format The output format either specified as an 924 * @param {string|!Object} format The output format either specified as an
924 * output template string or a parsed output format tree. 925 * output template string or a parsed output format tree.
925 * @param {!Array<Spannable>} buff Buffer to receive rendered output. 926 * @param {!Array<Spannable>} buff Buffer to receive rendered output.
927 * @param {!AutomationNode=} opt_prevNode
926 * @private 928 * @private
927 */ 929 */
928 format_: function(node, format, buff) { 930 format_: function(node, format, buff, opt_prevNode) {
929 var tokens = []; 931 var tokens = [];
930 var args = null; 932 var args = null;
931 933
932 // Hacky way to support args. 934 // Hacky way to support args.
933 if (typeof(format) == 'string') { 935 if (typeof(format) == 'string') {
934 format = format.replace(/([,:])\W/g, '$1'); 936 format = format.replace(/([,:])\W/g, '$1');
935 tokens = format.split(' '); 937 tokens = format.split(' ');
936 } else { 938 } else {
937 tokens = [format]; 939 tokens = [format];
938 } 940 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 if (node.textSelStart !== undefined) { 979 if (node.textSelStart !== undefined) {
978 options.annotation.push(new Output.SelectionSpan( 980 options.annotation.push(new Output.SelectionSpan(
979 node.textSelStart, 981 node.textSelStart,
980 node.textSelEnd)); 982 node.textSelEnd));
981 } 983 }
982 } 984 }
983 options.annotation.push(token); 985 options.annotation.push(token);
984 this.append_(buff, text, options); 986 this.append_(buff, text, options);
985 } else if (token == 'name') { 987 } else if (token == 'name') {
986 options.annotation.push(token); 988 options.annotation.push(token);
987 var earcon = node ? this.findEarcon_(node) : null; 989 var earcon = node ? this.findEarcon_(node, opt_prevNode) : null;
988 if (earcon) 990 if (earcon)
989 options.annotation.push(earcon); 991 options.annotation.push(earcon);
990 this.append_(buff, node.name, options); 992 this.append_(buff, node.name, options);
993 } else if (token == 'nameFromNode') {
994 if (chrome.automation.NameFromType[node.nameFrom] ==
995 'nameFromContents')
996 return;
997
998 options.annotation.push(token);
999 this.append_(buff, node.name, options);
991 } else if (token == 'nameOrDescendants') { 1000 } else if (token == 'nameOrDescendants') {
992 options.annotation.push(token); 1001 options.annotation.push(token);
993 if (node.name) 1002 if (node.name)
994 this.append_(buff, node.name, options); 1003 this.append_(buff, node.name, options);
995 else 1004 else
996 this.format_(node, '$descendants', buff); 1005 this.format_(node, '$descendants', buff);
997 } else if (token == 'indexInParent') { 1006 } else if (token == 'indexInParent') {
998 options.annotation.push(token); 1007 options.annotation.push(token);
999 this.append_(buff, String(node.indexInParent + 1)); 1008 this.append_(buff, String(node.indexInParent + 1));
1000 } else if (token == 'parentChildCount') { 1009 } else if (token == 'parentChildCount') {
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 for (var i = 0, formatPrevNode; 1306 for (var i = 0, formatPrevNode;
1298 (formatPrevNode = prevUniqueAncestors[i]); 1307 (formatPrevNode = prevUniqueAncestors[i]);
1299 i++) { 1308 i++) {
1300 // This prevents very repetitive announcements. 1309 // This prevents very repetitive announcements.
1301 if (enteredRoleSet[formatPrevNode.role] || 1310 if (enteredRoleSet[formatPrevNode.role] ||
1302 localStorage['useVerboseMode'] == 'false') 1311 localStorage['useVerboseMode'] == 'false')
1303 continue; 1312 continue;
1304 1313
1305 var roleBlock = getMergedRoleBlock(formatPrevNode.role); 1314 var roleBlock = getMergedRoleBlock(formatPrevNode.role);
1306 if (roleBlock.leave && localStorage['useVerboseMode'] == 'true') 1315 if (roleBlock.leave && localStorage['useVerboseMode'] == 'true')
1307 this.format_(formatPrevNode, roleBlock.leave, buff); 1316 this.format_(formatPrevNode, roleBlock.leave, buff, prevNode);
1308 } 1317 }
1309 1318
1310 var enterOutputs = []; 1319 var enterOutputs = [];
1311 var enterRole = {}; 1320 var enterRole = {};
1312 for (var j = uniqueAncestors.length - 2, formatNode; 1321 for (var j = uniqueAncestors.length - 2, formatNode;
1313 (formatNode = uniqueAncestors[j]); 1322 (formatNode = uniqueAncestors[j]);
1314 j--) { 1323 j--) {
1315 var roleBlock = getMergedRoleBlock(formatNode.role); 1324 var roleBlock = getMergedRoleBlock(formatNode.role);
1316 if (roleBlock.enter) { 1325 if (roleBlock.enter) {
1317 if (enterRole[formatNode.role]) 1326 if (enterRole[formatNode.role])
1318 continue; 1327 continue;
1319 enterRole[formatNode.role] = true; 1328 enterRole[formatNode.role] = true;
1320 this.format_(formatNode, roleBlock.enter, buff); 1329 this.format_(formatNode, roleBlock.enter, buff, prevNode);
1321 } 1330 }
1322 if (formatNode.role == 'window') 1331 if (formatNode.role == 'window')
1323 break; 1332 break;
1324 } 1333 }
1325 }, 1334 },
1326 1335
1327 /** 1336 /**
1328 * @param {!AutomationNode} node 1337 * @param {!AutomationNode} node
1329 * @param {!AutomationNode} prevNode 1338 * @param {!AutomationNode} prevNode
1330 * @param {EventType|Output.EventType} type 1339 * @param {EventType|Output.EventType} type
1331 * @param {!Array<Spannable>} buff 1340 * @param {!Array<Spannable>} buff
1332 * @private 1341 * @private
1333 */ 1342 */
1334 node_: function(node, prevNode, type, buff) { 1343 node_: function(node, prevNode, type, buff) {
1335 // Navigate is the default event. 1344 // Navigate is the default event.
1336 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; 1345 var eventBlock = Output.RULES[type] || Output.RULES['navigate'];
1337 var roleBlock = eventBlock[node.role] || {}; 1346 var roleBlock = eventBlock[node.role] || {};
1338 var parentRole = (Output.ROLE_INFO_[node.role] || {}).inherits; 1347 var parentRole = (Output.ROLE_INFO_[node.role] || {}).inherits;
1339 var parentRoleBlock = eventBlock[parentRole || ''] || {}; 1348 var parentRoleBlock = eventBlock[parentRole || ''] || {};
1340 var speakFormat = roleBlock.speak || 1349 var speakFormat = roleBlock.speak ||
1341 parentRoleBlock.speak || 1350 parentRoleBlock.speak ||
1342 eventBlock['default'].speak; 1351 eventBlock['default'].speak;
1343 1352
1344 this.format_(node, speakFormat, buff); 1353 this.format_(node, speakFormat, buff, prevNode);
1345 }, 1354 },
1346 1355
1347 /** 1356 /**
1348 * @param {!cursors.Range} range 1357 * @param {!cursors.Range} range
1349 * @param {cursors.Range} prevRange 1358 * @param {cursors.Range} prevRange
1350 * @param {EventType|Output.EventType} type 1359 * @param {EventType|Output.EventType} type
1351 * @param {!Array<Spannable>} buff 1360 * @param {!Array<Spannable>} buff
1352 * @private 1361 * @private
1353 */ 1362 */
1354 subNode_: function(range, prevRange, type, buff) { 1363 subNode_: function(range, prevRange, type, buff) {
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1537 return result; 1546 return result;
1538 }, 1547 },
1539 1548
1540 /** 1549 /**
1541 * Find the earcon for a given node (including ancestry). 1550 * Find the earcon for a given node (including ancestry).
1542 * @param {!AutomationNode} node 1551 * @param {!AutomationNode} node
1543 * @param {!AutomationNode=} opt_prevNode 1552 * @param {!AutomationNode=} opt_prevNode
1544 * @return {Output.Action} 1553 * @return {Output.Action}
1545 */ 1554 */
1546 findEarcon_: function(node, opt_prevNode) { 1555 findEarcon_: function(node, opt_prevNode) {
1556 if (node === opt_prevNode)
1557 return null;
1558
1547 if (this.formatOptions_.speech) { 1559 if (this.formatOptions_.speech) {
1548 var earconFinder = node; 1560 var earconFinder = node;
1549 var ancestors; 1561 var ancestors;
1550 if (opt_prevNode) { 1562 if (opt_prevNode)
1551 // Don't include the node itself.
1552 ancestors = AutomationUtil.getUniqueAncestors(opt_prevNode, node); 1563 ancestors = AutomationUtil.getUniqueAncestors(opt_prevNode, node);
1553 ancestors.pop(); 1564 else
1554 } else {
1555 ancestors = AutomationUtil.getAncestors(node); 1565 ancestors = AutomationUtil.getAncestors(node);
1556 }
1557 1566
1558 while (earconFinder = ancestors.pop()) { 1567 while (earconFinder = ancestors.pop()) {
1559 var info = Output.ROLE_INFO_[earconFinder.role]; 1568 var info = Output.ROLE_INFO_[earconFinder.role];
1560 if (info && info.earconId) { 1569 if (info && info.earconId) {
1561 return new Output.EarconAction(info.earconId); 1570 return new Output.EarconAction(info.earconId);
1562 break; 1571 break;
1563 } 1572 }
1564 earconFinder = earconFinder.parent; 1573 earconFinder = earconFinder.parent;
1565 } 1574 }
1566 } 1575 }
1567 return null; 1576 return null;
1568 } 1577 }
1569 }; 1578 };
1570 1579
1571 }); // goog.scope 1580 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698