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

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

Issue 2487043002: Refine braille output (Closed)
Patch Set: Simplify Created 4 years, 1 month 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 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 /** @override */ 643 /** @override */
644 run: function() { 644 run: function() {
645 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon[this.earconId]); 645 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon[this.earconId]);
646 } 646 }
647 }; 647 };
648 648
649 /** 649 /**
650 * Annotation for text with a selection inside it. 650 * Annotation for text with a selection inside it.
651 * @param {number} startIndex 651 * @param {number} startIndex
652 * @param {number} endIndex 652 * @param {number} endIndex
653 * @param {number=} opt_offset
654 * @constructor 653 * @constructor
655 */ 654 */
656 Output.SelectionSpan = function(startIndex, endIndex, opt_offset) { 655 Output.SelectionSpan = function(startIndex, endIndex) {
657 // TODO(dtseng): Direction lost below; should preserve for braille panning. 656 // TODO(dtseng): Direction lost below; should preserve for braille panning.
658 this.startIndex = startIndex < endIndex ? startIndex : endIndex; 657 this.startIndex = startIndex < endIndex ? startIndex : endIndex;
659 this.endIndex = endIndex > startIndex ? endIndex : startIndex; 658 this.endIndex = endIndex > startIndex ? endIndex : startIndex;
660 this.offset = opt_offset || 0;
661 }; 659 };
662 660
663 /** 661 /**
664 * Wrapper for automation nodes as annotations. Since the 662 * Wrapper for automation nodes as annotations. Since the
665 * {@code AutomationNode} constructor isn't exposed in the API, this class is 663 * {@code AutomationNode} constructor isn't exposed in the API, this class is
666 * used to allow instanceof checks on these annotations. 664 * used to allow instanceof checks on these annotations.
667 * @param {!AutomationNode} node 665 * @param {!AutomationNode} node
668 * @constructor 666 * @constructor
669 */ 667 */
670 Output.NodeSpan = function(node) { 668 Output.NodeSpan = function(node) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 * @param {string} formatStr 863 * @param {string} formatStr
866 * @param {!AutomationNode=} opt_node An optional node to apply the 864 * @param {!AutomationNode=} opt_node An optional node to apply the
867 * formatting to. 865 * formatting to.
868 * @return {!Output} |this| for chaining 866 * @return {!Output} |this| for chaining
869 */ 867 */
870 formatForBraille: function(formatStr, opt_node) { 868 formatForBraille: function(formatStr, opt_node) {
871 var node = opt_node || null; 869 var node = opt_node || null;
872 870
873 this.formatOptions_ = {speech: false, braille: true, auralStyle: false}; 871 this.formatOptions_ = {speech: false, braille: true, auralStyle: false};
874 this.format_(node, formatStr, this.brailleBuffer_); 872 this.format_(node, formatStr, this.brailleBuffer_);
875
876 return this; 873 return this;
877 }, 874 },
878 875
879 /** 876 /**
880 * Triggers callback for a speech event. 877 * Triggers callback for a speech event.
881 * @param {function()} callback 878 * @param {function()} callback
882 * @return {Output} 879 * @return {Output}
883 */ 880 */
884 onSpeechEnd: function(callback) { 881 onSpeechEnd: function(callback) {
885 this.speechEndCallback_ = function(opt_cleanupOnly) { 882 this.speechEndCallback_ = function(opt_cleanupOnly) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 if (i == this.speechBuffer_.length - 1) 922 if (i == this.speechBuffer_.length - 1)
926 speechProps['endCallback'] = this.speechEndCallback_; 923 speechProps['endCallback'] = this.speechEndCallback_;
927 924
928 cvox.ChromeVox.tts.speak( 925 cvox.ChromeVox.tts.speak(
929 buff.toString(), queueMode, speechProps); 926 buff.toString(), queueMode, speechProps);
930 queueMode = cvox.QueueMode.QUEUE; 927 queueMode = cvox.QueueMode.QUEUE;
931 } 928 }
932 929
933 // Braille. 930 // Braille.
934 if (this.brailleBuffer_.length) { 931 if (this.brailleBuffer_.length) {
935 var buff = this.createBrailleOutput_(); 932 var buff = this.mergeBraille_(this.brailleBuffer_);
936 var selSpan = 933 var selSpan =
937 buff.getSpanInstanceOf(Output.SelectionSpan); 934 buff.getSpanInstanceOf(Output.SelectionSpan);
938 var startIndex = -1, endIndex = -1; 935 var startIndex = -1, endIndex = -1;
939 if (selSpan) { 936 if (selSpan) {
940 var valueStart = buff.getSpanStart(selSpan); 937 var valueStart = buff.getSpanStart(selSpan);
941 var valueEnd = buff.getSpanEnd(selSpan); 938 var valueEnd = buff.getSpanEnd(selSpan);
942 startIndex = valueStart + selSpan.startIndex; 939 startIndex = valueStart + selSpan.startIndex;
943 endIndex = valueStart + selSpan.endIndex; 940 endIndex = valueStart + selSpan.endIndex;
944 buff.setSpan(new cvox.ValueSpan(selSpan.offset), valueStart, valueEnd); 941 buff.setSpan(new cvox.ValueSpan(0), valueStart, valueEnd);
945 buff.setSpan(new cvox.ValueSelectionSpan(), startIndex, endIndex); 942 buff.setSpan(new cvox.ValueSelectionSpan(), startIndex, endIndex);
946 } 943 }
947 944
948 var output = new cvox.NavBraille({ 945 var output = new cvox.NavBraille({
949 text: buff, 946 text: buff,
950 startIndex: startIndex, 947 startIndex: startIndex,
951 endIndex: endIndex 948 endIndex: endIndex
952 }); 949 });
953 950
954 cvox.ChromeVox.braille.write(output); 951 cvox.ChromeVox.braille.write(output);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 // Obtain the operator token. 1028 // Obtain the operator token.
1032 token = tree.value; 1029 token = tree.value;
1033 1030
1034 // Set suffix options. 1031 // Set suffix options.
1035 var options = {}; 1032 var options = {};
1036 options.annotation = []; 1033 options.annotation = [];
1037 options.isUnique = token[token.length - 1] == '='; 1034 options.isUnique = token[token.length - 1] == '=';
1038 if (options.isUnique) 1035 if (options.isUnique)
1039 token = token.substring(0, token.length - 1); 1036 token = token.substring(0, token.length - 1);
1040 1037
1041 // Annotate braille output with the corresponding automation nodes
1042 // to support acting on nodes based on location in the output.
1043 if (node && this.formatOptions_.braille)
1044 options.annotation.push(new Output.NodeSpan(node));
1045
1046 // Process token based on prefix. 1038 // Process token based on prefix.
1047 var prefix = token[0]; 1039 var prefix = token[0];
1048 token = token.slice(1); 1040 token = token.slice(1);
1049 1041
1050 // All possible tokens based on prefix. 1042 // All possible tokens based on prefix.
1051 if (prefix == '$') { 1043 if (prefix == '$') {
1052 if (token == 'value') { 1044 if (token == 'value') {
1053 var text = node.value; 1045 var text = node.value;
1054 if (!node.state.editable && node.name == text) 1046 if (!node.state.editable && node.name == text)
1055 return; 1047 return;
1056 1048
1057 var selectedText = ''; 1049 var selectedText = '';
1058 if (text !== undefined) { 1050 if (text !== undefined) {
1059 if (node.textSelStart !== undefined) { 1051 if (node.textSelStart !== undefined) {
1060 options.annotation.push(new Output.SelectionSpan( 1052 options.annotation.push(new Output.SelectionSpan(
1061 node.textSelStart, 1053 node.textSelStart,
1062 node.textSelEnd)); 1054 node.textSelEnd));
1063 1055
1064 selectedText = 1056 selectedText =
1065 node.value.substring(node.textSelStart, node.textSelEnd); 1057 node.value.substring(node.textSelStart, node.textSelEnd);
1066 } 1058 }
1067 } 1059 }
1068 options.annotation.push(token); 1060 options.annotation.push(token);
1069 if (selectedText) { 1061 if (selectedText) {
1070 this.append_(buff, selectedText, options); 1062 this.append_(buff, selectedText, options);
1071 this.append_(buff, Msgs.getMsg('selected'), options); 1063 this.append_(buff, Msgs.getMsg('selected'));
1072 } else { 1064 } else {
1073 this.append_(buff, text, options); 1065 this.append_(buff, text, options);
1074 } 1066 }
1075 } else if (token == 'name') { 1067 } else if (token == 'name') {
1076 options.annotation.push(token); 1068 options.annotation.push(token);
1077 var earcon = node ? this.findEarcon_(node, opt_prevNode) : null; 1069 var earcon = node ? this.findEarcon_(node, opt_prevNode) : null;
1078 if (earcon) 1070 if (earcon)
1079 options.annotation.push(earcon); 1071 options.annotation.push(earcon);
1080 this.append_(buff, node.name, options); 1072 this.append_(buff, node.name, options);
1081 } else if (token == 'urlFilename') { 1073 } else if (token == 'urlFilename') {
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 if (enteredRoleSet[formatPrevNode.role] || 1483 if (enteredRoleSet[formatPrevNode.role] ||
1492 node.role == formatPrevNode.role || 1484 node.role == formatPrevNode.role ||
1493 localStorage['useVerboseMode'] == 'false') 1485 localStorage['useVerboseMode'] == 'false')
1494 continue; 1486 continue;
1495 1487
1496 var roleBlock = getMergedRoleBlock(formatPrevNode.role); 1488 var roleBlock = getMergedRoleBlock(formatPrevNode.role);
1497 if (roleBlock.leave && localStorage['useVerboseMode'] == 'true') 1489 if (roleBlock.leave && localStorage['useVerboseMode'] == 'true')
1498 this.format_(formatPrevNode, roleBlock.leave, buff, prevNode); 1490 this.format_(formatPrevNode, roleBlock.leave, buff, prevNode);
1499 } 1491 }
1500 1492
1501 var enterOutputs = []; 1493 // Customize for braille node annotations.
1494 var originalBuff = buff;
1502 var enterRole = {}; 1495 var enterRole = {};
1503 for (var j = uniqueAncestors.length - 1, formatNode; 1496 for (var j = uniqueAncestors.length - 1, formatNode;
1504 (formatNode = uniqueAncestors[j]); 1497 (formatNode = uniqueAncestors[j]);
1505 j--) { 1498 j--) {
1506 var roleBlock = getMergedRoleBlock(formatNode.role); 1499 var roleBlock = getMergedRoleBlock(formatNode.role);
1507 if (roleBlock.enter) { 1500 if (roleBlock.enter) {
1508 if (enterRole[formatNode.role]) 1501 if (enterRole[formatNode.role])
1509 continue; 1502 continue;
1503
1504 if (this.formatOptions_.braille)
1505 buff = [];
1506
1510 enterRole[formatNode.role] = true; 1507 enterRole[formatNode.role] = true;
1511 this.format_(formatNode, roleBlock.enter, buff, prevNode); 1508 this.format_(formatNode, roleBlock.enter, buff, prevNode);
1509
1510 if (this.formatOptions_.braille && buff.length) {
1511 var nodeSpan = this.mergeBraille_(buff);
1512 nodeSpan.setSpan(new Output.NodeSpan(formatNode), 0, nodeSpan.length);
1513 originalBuff.push(nodeSpan);
1514 }
1512 } 1515 }
1513 } 1516 }
1514 }, 1517 },
1515 1518
1516 /** 1519 /**
1517 * @param {!AutomationNode} node 1520 * @param {!AutomationNode} node
1518 * @param {!AutomationNode} prevNode 1521 * @param {!AutomationNode} prevNode
1519 * @param {EventType|Output.EventType} type 1522 * @param {EventType|Output.EventType} type
1520 * @param {!Array<Spannable>} buff 1523 * @param {!Array<Spannable>} buff
1521 * @private 1524 * @private
1522 */ 1525 */
1523 node_: function(node, prevNode, type, buff) { 1526 node_: function(node, prevNode, type, buff) {
1527 var originalBuff = buff;
1528
1529 if (this.formatOptions_.braille)
1530 buff = [];
1531
1524 // Navigate is the default event. 1532 // Navigate is the default event.
1525 var eventBlock = Output.RULES[type] || Output.RULES['navigate']; 1533 var eventBlock = Output.RULES[type] || Output.RULES['navigate'];
1526 var roleBlock = eventBlock[node.role] || {}; 1534 var roleBlock = eventBlock[node.role] || {};
1527 var parentRole = (Output.ROLE_INFO_[node.role] || {}).inherits; 1535 var parentRole = (Output.ROLE_INFO_[node.role] || {}).inherits;
1528 var parentRoleBlock = eventBlock[parentRole || ''] || {}; 1536 var parentRoleBlock = eventBlock[parentRole || ''] || {};
1529 var speakFormat = roleBlock.speak || 1537 var speakFormat = roleBlock.speak ||
1530 parentRoleBlock.speak || 1538 parentRoleBlock.speak ||
1531 eventBlock['default'].speak; 1539 eventBlock['default'].speak;
1532 1540
1533 this.format_(node, speakFormat, buff, prevNode); 1541 this.format_(node, speakFormat, buff, prevNode);
1542
1543 // Restore braille and add an annotation for this node.
1544 if (this.formatOptions_.braille) {
1545 var nodeSpan = this.mergeBraille_(buff);
1546 nodeSpan.setSpan(new Output.NodeSpan(node), 0, nodeSpan.length);
1547 originalBuff.push(nodeSpan);
1548 }
1534 }, 1549 },
1535 1550
1536 /** 1551 /**
1537 * @param {!cursors.Range} range 1552 * @param {!cursors.Range} range
1538 * @param {cursors.Range} prevRange 1553 * @param {cursors.Range} prevRange
1539 * @param {EventType|Output.EventType} type 1554 * @param {EventType|Output.EventType} type
1540 * @param {!Array<Spannable>} buff 1555 * @param {!Array<Spannable>} buff
1541 * @private 1556 * @private
1542 */ 1557 */
1543 subNode_: function(range, prevRange, type, buff) { 1558 subNode_: function(range, prevRange, type, buff) {
1544 if (!prevRange) 1559 if (!prevRange)
1545 prevRange = range; 1560 prevRange = range;
1546 var dir = cursors.Range.getDirection(prevRange, range); 1561 var dir = cursors.Range.getDirection(prevRange, range);
1547 var node = range.start.node; 1562 var node = range.start.node;
1548 var prevNode = prevRange.getBound(dir).node; 1563 var prevNode = prevRange.getBound(dir).node;
1549 if (!node || !prevNode) 1564 if (!node || !prevNode)
1550 return; 1565 return;
1551 1566
1552 var options = {annotation: ['name'], isUnique: true}; 1567 var options = {annotation: ['name'], isUnique: true};
1553 var startIndex = range.start.index; 1568 var rangeStart = range.start.index;
1554 var endIndex = range.end.index; 1569 var rangeEnd = range.end.index;
1555 if (this.formatOptions_.braille) { 1570 if (this.formatOptions_.braille) {
1556 options.annotation.push(new Output.NodeSpan(node)); 1571 options.annotation.push(new Output.NodeSpan(node));
1557 var selStart = node.textSelStart; 1572 var selStart = node.textSelStart;
1558 var selEnd = node.textSelEnd; 1573 var selEnd = node.textSelEnd;
1574
1559 if (selStart !== undefined && 1575 if (selStart !== undefined &&
1560 (selEnd >= startIndex && selStart <= endIndex)) { 1576 selEnd >= rangeStart && selStart <= rangeEnd) {
1577 // Editable text selection.
1578
1579 // |rangeStart| and |rangeEnd| are indices set by the caller and are
1580 // assumed to be inside of the range. In braille, we only ever expect to
1581 // get ranges surrounding a line as anything smaller doesn't make sense.
1582
1583 // |selStart| and |selEnd| reflect the editable selection. The relative
1584 // selStart and relative selEnd for the current line are then just the
1585 // difference between |selStart|, |selEnd| with |rangeStart|.
1586 // See editing_test.js for examples.
1561 options.annotation.push(new Output.SelectionSpan( 1587 options.annotation.push(new Output.SelectionSpan(
1562 selStart - startIndex, 1588 selStart - rangeStart, selEnd - rangeStart));
1563 selEnd - startIndex, 1589 } else {
1564 startIndex)); 1590 // Non-editable text selection.
1591 options.annotation.push(new Output.SelectionSpan(rangeStart, rangeEnd));
1565 } 1592 }
1566 } 1593 }
1567 1594
1568 if (this.outputContextFirst_) 1595 if (this.outputContextFirst_)
1569 this.ancestry_(node, prevNode, type, buff); 1596 this.ancestry_(node, prevNode, type, buff);
1570 var earcon = this.findEarcon_(node, prevNode); 1597 var earcon = this.findEarcon_(node, prevNode);
1571 if (earcon) 1598 if (earcon)
1572 options.annotation.push(earcon); 1599 options.annotation.push(earcon);
1573 this.append_(buff, range.start.getText().substring(startIndex, endIndex), 1600 var text = '';
1574 options); 1601
1602 if (this.formatOptions_.braille && !node.state.editable) {
1603 // In braille, we almost always want to show the entire contents and
1604 // simply place the cursor under the SelectionSpan we set above.
1605 text = range.start.getText();
1606 } else {
1607 // This is output for speech or non-editable braille.
dmazzoni 2016/11/10 23:31:29 This appears backwards from your logic. Above, you
David Tseng 2016/11/10 23:54:59 Changed comment. The code is right. In editable br
David Tseng 2016/11/11 02:36:27 Alright, to clarify things, I added a test and con
1608 text = range.start.getText().substring(rangeStart, rangeEnd);
1609 }
1610
1611 this.append_(buff, text, options);
1612
1575 if (!this.outputContextFirst_) 1613 if (!this.outputContextFirst_)
1576 this.ancestry_(node, prevNode, type, buff); 1614 this.ancestry_(node, prevNode, type, buff);
1577 1615
1578 var loc = 1616 var loc =
1579 range.start.node.boundsForRange(startIndex, endIndex); 1617 range.start.node.boundsForRange(rangeStart, rangeEnd);
1580 if (loc) 1618 if (loc)
1581 this.locations_.push(loc); 1619 this.locations_.push(loc);
1582 }, 1620 },
1583 1621
1584 /** 1622 /**
1585 * Appends output to the |buff|. 1623 * Appends output to the |buff|.
1586 * @param {!Array<Spannable>} buff 1624 * @param {!Array<Spannable>} buff
1587 * @param {string|!Spannable} value 1625 * @param {string|!Spannable} value
1588 * @param {{isUnique: (boolean|undefined), 1626 * @param {{isUnique: (boolean|undefined),
1589 * annotation: !Array<*>}=} opt_options 1627 * annotation: !Array<*>}=} opt_options
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1666 index++; 1704 index++;
1667 } 1705 }
1668 1706
1669 if (currentNode != root) 1707 if (currentNode != root)
1670 throw 'Unbalanced parenthesis: ' + inputStr; 1708 throw 'Unbalanced parenthesis: ' + inputStr;
1671 1709
1672 return root; 1710 return root;
1673 }, 1711 },
1674 1712
1675 /** 1713 /**
1676 * Converts the currently rendered braille buffers to a single spannable. 1714 * Converts the braille |spans| buffer to a single spannable.
1715 * @param {!Array<Spannable>} spans
1677 * @return {!Spannable} 1716 * @return {!Spannable}
1678 * @private 1717 * @private
1679 */ 1718 */
1680 createBrailleOutput_: function() { 1719 mergeBraille_: function(spans) {
1681 var result = new Spannable();
1682 var separator = ''; // Changes to space as appropriate. 1720 var separator = ''; // Changes to space as appropriate.
1683 this.brailleBuffer_.forEach(function(cur) { 1721 var prevHasInlineNode = false;
1684 // If this chunk is empty, don't add it since it won't result 1722 return spans.reduce(function(result, cur) {
1685 // in any output on the braille display, but node spans would 1723 // Ignore empty spans except when they contain a selection.
1686 // start before the separator in that case, which is not desired. 1724 var hasSelection = cur.getSpanInstanceOf(Output.SelectionSpan);
1687 // The exception is if this chunk contains a selectionm, in which 1725 if (cur.length == 0 && !hasSelection)
1688 // case it will result in a cursor which has to be preserved. 1726 return result;
1689 // In this case, having separators, potentially both before and after 1727
1690 // the empty string is correct. 1728 // For empty selections, we just add the space separator to account for
1691 if (cur.length == 0 && !cur.getSpanInstanceOf(Output.SelectionSpan)) 1729 // showing the braille cursor.
1692 return; 1730 if (cur.length == 0 && hasSelection) {
1693 var spansToExtend = []; 1731 result.append(cur);
1694 var spansToRemove = []; 1732 result.append(Output.SPACE);
1695 // Nodes that have node spans both on the character to the left 1733 separator = '';
1696 // of the separator and to the right should also cover the separator. 1734 return result;
1697 // We extend the left span to cover both the separator and what the 1735 }
1698 // right span used to cover, removing the right span, mostly for 1736
1699 // ease of writing tests and debug. 1737 // Keep track of if there's an inline node associated with
1700 // Note that getSpan(position) never returns zero length spans 1738 // |cur|.
1701 // (because they don't cover any position). Still, we want to include 1739 var hasInlineNode = cur.getSpansInstanceOf(Output.NodeSpan)
1702 // these because they can be included (the selection span in an empty 1740 .some(function(s) {
1703 // text field is an example), which is why we write the below code 1741 return s.node && s.node.display == 'inline';
1704 // using getSpansInstanceOf and check the endpoints (isntead of doing 1742 });
1705 // the opposite). 1743
1706 result.getSpansInstanceOf(Output.NodeSpan).forEach(function(leftSpan) { 1744 // Now, decide whether we should include separators between the previous
1707 if (result.getSpanEnd(leftSpan) < result.length) 1745 // span and |cur|.
1708 return; 1746 // Never separate chunks without something already there at this point.
1709 var newEnd = result.length; 1747 if (result.length == 0 || hasInlineNode || prevHasInlineNode)
dmazzoni 2016/11/10 23:31:29 I'm not sure we want no separator if either of the
David Tseng 2016/11/11 02:36:27 I found good examples of block <-> inline and inli
1710 cur.getSpansInstanceOf(Output.NodeSpan).forEach(function(rightSpan) { 1748 separator = '';
1711 if (cur.getSpanStart(rightSpan) == 0 && 1749 else
1712 leftSpan.node === rightSpan.node) { 1750 separator = Output.SPACE;
1713 newEnd = Math.max( 1751
1714 newEnd, 1752 prevHasInlineNode = hasInlineNode;
1715 result.length + separator.length +
1716 cur.getSpanEnd(rightSpan));
1717 spansToRemove.push(rightSpan);
1718 }
1719 });
1720 if (newEnd > result.length)
1721 spansToExtend.push({span: leftSpan, end: newEnd});
1722 });
1723 result.append(separator); 1753 result.append(separator);
1724 result.append(cur); 1754 result.append(cur);
1725 spansToExtend.forEach(function(elem) { 1755 return result;
1726 result.setSpan( 1756 }, new Spannable());
1727 elem.span,
1728 result.getSpanStart(elem.span),
1729 elem.end);
1730 });
1731 spansToRemove.forEach(result.removeSpan.bind(result));
1732 separator = Output.SPACE;
1733 });
1734 return result;
1735 }, 1757 },
1736 1758
1737 /** 1759 /**
1738 * Find the earcon for a given node (including ancestry). 1760 * Find the earcon for a given node (including ancestry).
1739 * @param {!AutomationNode} node 1761 * @param {!AutomationNode} node
1740 * @param {!AutomationNode=} opt_prevNode 1762 * @param {!AutomationNode=} opt_prevNode
1741 * @return {Output.Action} 1763 * @return {Output.Action}
1742 */ 1764 */
1743 findEarcon_: function(node, opt_prevNode) { 1765 findEarcon_: function(node, opt_prevNode) {
1744 if (node === opt_prevNode) 1766 if (node === opt_prevNode)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1789 prev.append(cur); 1811 prev.append(cur);
1790 return prev; 1812 return prev;
1791 }, null); 1813 }, null);
1792 }, 1814 },
1793 1815
1794 /** 1816 /**
1795 * Gets the output buffer for braille. 1817 * Gets the output buffer for braille.
1796 * @return {!Spannable} 1818 * @return {!Spannable}
1797 */ 1819 */
1798 get brailleOutputForTest() { 1820 get brailleOutputForTest() {
1799 return this.createBrailleOutput_(); 1821 return this.mergeBraille_(this.brailleBuffer_);
1800 } 1822 }
1801 }; 1823 };
1802 1824
1803 }); // goog.scope 1825 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698