summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources/chromeos/chromevox/common
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/resources/chromeos/chromevox/common')
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js22
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js6
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js202
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs71
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js723
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js25
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js6
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js8
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js6
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js24
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js60
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js47
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js804
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js6
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js712
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_test.unitjs25
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js15
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js31
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js8
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js12
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js174
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js120
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js16
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js20
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/nav_braille.js121
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js4
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js3
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js30
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js32
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/string_util_test.unitjs32
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js14
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js41
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js74
40 files changed, 1878 insertions, 1630 deletions
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
index 47d2ee96c30..7df05627b2c 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
@@ -34,7 +34,7 @@ cvox.AriaUtil.NO_ROLE_NAME = ' ';
* Note: If you are adding a new mapping, the new message identifier needs a
* corresponding braille message. For example, a message id 'tag_button'
* requires another message 'tag_button_brl' within messages.js.
- * @type {Object.<string, string>}
+ * @type {Object<string, string>}
*/
cvox.AriaUtil.WIDGET_ROLE_TO_NAME = {
'alert' : 'aria_role_alert',
@@ -79,7 +79,7 @@ cvox.AriaUtil.WIDGET_ROLE_TO_NAME = {
* Note: If you are adding a new mapping, the new message identifier needs a
* corresponding braille message. For example, a message id 'tag_button'
* requires another message 'tag_button_brl' within messages.js.
- * @type {Object.<string, string>}
+ * @type {Object<string, string>}
*/
cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME = {
'article' : 'aria_role_article',
@@ -109,7 +109,7 @@ cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME = {
/**
- * @type {Array.<Object>}
+ * @type {Array<Object>}
*/
cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS = [
{ name: 'aria-autocomplete', values:
@@ -381,9 +381,9 @@ cvox.AriaUtil.getStateMsgs = function(targetNode, primary) {
for (var i = 0, attr; attr = cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS[i];
i++) {
var value = targetNode.getAttribute(attr.name);
- var msg_id = attr.values[value];
- if (msg_id) {
- state.push([msg_id]);
+ var msgId = attr.values[value];
+ if (msgId) {
+ state.push([msgId]);
}
}
if (targetNode.getAttribute('role') == 'grid') {
@@ -583,8 +583,8 @@ cvox.AriaUtil.getActiveDescendantId_ = function(targetNode) {
* Returns the list of elements that are one aria-level below.
*
* @param {Node} parentControl The node whose descendants should be analyzed.
- * @param {Array.<string>} role The role(s) of descendant we are looking for.
- * @return {Array.<Node>} The array of matching nodes.
+ * @param {Array<string>} role The role(s) of descendant we are looking for.
+ * @return {Array<Node>} The array of matching nodes.
*/
cvox.AriaUtil.getNextLevel = function(parentControl, role) {
var result = [];
@@ -608,8 +608,8 @@ cvox.AriaUtil.getNextLevel = function(parentControl, role) {
* Recursively finds the first node(s) that match the role.
*
* @param {Element} current The node to start looking at.
- * @param {Array.<string>} role The role(s) to match.
- * @return {Array.<Element>} The array of matching nodes.
+ * @param {Array<string>} role The role(s) to match.
+ * @return {Array<Element>} The array of matching nodes.
*/
cvox.AriaUtil.getNextLevelItems = function(current, role) {
if (current.nodeType != 1) { // If reached a node that is not an element.
@@ -838,7 +838,7 @@ cvox.AriaUtil.getAriaRelevant = function(node, change) {
* node or contain this node.
*
* @param {Node} node The node to be checked.
- * @return {Array.<Element>} All live regions affected by this node changing.
+ * @return {Array<Element>} All live regions affected by this node changing.
*/
cvox.AriaUtil.getLiveRegions = function(node) {
var result = [];
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js
index 568084bccf5..0e8c3b5cf57 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js
@@ -55,7 +55,7 @@ cvox.AuralStyleConverter.identity = function(value) {
* Conversion from an aural style property to Chrome TTS property.
* TODO(dtseng): no-op's below need to be supported by the extension API itself
* or by ChromeVox.
- * @type {Object.<cvox.AuralProperty, string>}
+ * @type {Object<cvox.AuralProperty, string>}
*/
cvox.AuralStyleConverter.propertyTable = {
VOLUME: 'volume',
@@ -86,7 +86,7 @@ cvox.AuralStyleConverter.propertyTable = {
* Conversion from an aural style value to Chrome TTS value.
* TODO(dtseng): Conversion of aural CSS values is incomplete; everything is an
* identity conversion at the moment.
- * @type {Object.<cvox.AuralProperty, function(*)>}
+ * @type {Object<cvox.AuralProperty, function(*)>}
*/
cvox.AuralStyleConverter.valueTable = {
VOLUME: cvox.AuralStyleConverter.identity,
@@ -129,7 +129,7 @@ cvox.AuralStyleConverter.convertRule = function(property, value) {
/**
* Converts an aural CSS style block to a TTS property object.
- * @param {Object.<cvox.AuralProperty, *>} style The style.
+ * @param {Object<cvox.AuralProperty, *>} style The style.
* @return {Object} The tts property object.
*/
cvox.AuralStyleConverter.convertStyle = function(style) {
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js
index 4e2ce623171..bc133b7c5dd 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js
@@ -11,10 +11,13 @@ goog.provide('cvox.BrailleUtil');
goog.require('cvox.ChromeVox');
goog.require('cvox.DomUtil');
+goog.require('cvox.EditableTextAreaShadow');
goog.require('cvox.Focuser');
goog.require('cvox.NavBraille');
goog.require('cvox.NodeStateUtil');
goog.require('cvox.Spannable');
+goog.require('cvox.ValueSelectionSpan');
+goog.require('cvox.ValueSpan');
/**
@@ -30,7 +33,7 @@ cvox.BrailleUtil.ITEM_SEPARATOR = ' ';
* Containers are distinguished from roles by their appearance higher up in the
* DOM tree of a selected node.
* This list should be very short.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.BrailleUtil.CONTAINER = [
'tag_h1_brl',
@@ -51,82 +54,34 @@ cvox.BrailleUtil.CONTAINER = [
* c: replaced with braille container role; this potentially returns whitespace,
* so place at the beginning or end of templates for trimming.
* v: replaced with braille value.
- * @type {Object.<string, string>}
+ * @type {Object<string, string>}
*/
cvox.BrailleUtil.TEMPLATE = {
'base': 'c n v r s',
'aria_role_alert': 'r: n',
- 'aria_role_button': '[n]',
- 'aria_role_textbox': 'n: v r',
- 'input_type_button': '[n]',
- 'input_type_checkbox': 'n (s)',
- 'input_type_email': 'n: v r',
- 'input_type_number': 'n: v r',
- 'input_type_password': 'n: v r',
- 'input_type_search': 'n: v r',
- 'input_type_submit': '[n]',
- 'input_type_text': 'n: v r',
- 'input_type_tel': 'n: v r',
- 'input_type_url': 'n: v r',
- 'tag_button': '[n]',
- 'tag_textarea': 'n: v r'
+ 'aria_role_button': 'n r s',
+ 'aria_role_checkbox': 'n r (s)',
+ 'aria_role_menuitemcheckbox': 'n r (s)',
+ 'aria_role_menuitemradio': 'n r (s)',
+ 'aria_role_radio': 'n r (s)',
+ 'aria_role_textbox': 'n: v r s',
+ 'input_type_button': 'n r s',
+ 'input_type_checkbox': 'n r (s)',
+ 'input_type_email': 'n: v r s',
+ 'input_type_number': 'n: v r s',
+ 'input_type_password': 'n: v r s',
+ 'input_type_radio': 'n r (s)',
+ 'input_type_search': 'n: v r s',
+ 'input_type_submit': 'n r s',
+ 'input_type_text': 'n: v r s',
+ 'input_type_tel': 'n: v r s',
+ 'input_type_url': 'n: v r s',
+ 'tag_button': 'n r s',
+ 'tag_textarea': 'n: v r s'
};
/**
- * Attached to the value region of a braille spannable.
- * @param {number} offset The offset of the span into the value.
- * @constructor
- */
-cvox.BrailleUtil.ValueSpan = function(offset) {
- /**
- * The offset of the span into the value.
- * @type {number}
- */
- this.offset = offset;
-};
-
-
-/**
- * Creates a value span from a json serializable object.
- * @param {!Object} obj The json serializable object to convert.
- * @return {!cvox.BrailleUtil.ValueSpan} The value span.
- */
-cvox.BrailleUtil.ValueSpan.fromJson = function(obj) {
- return new cvox.BrailleUtil.ValueSpan(obj.offset);
-};
-
-
-/**
- * Converts this object to a json serializable object.
- * @return {!Object} The JSON representation.
- */
-cvox.BrailleUtil.ValueSpan.prototype.toJson = function() {
- return this;
-};
-
-
-cvox.Spannable.registerSerializableSpan(
- cvox.BrailleUtil.ValueSpan,
- 'cvox.BrailleUtil.ValueSpan',
- cvox.BrailleUtil.ValueSpan.fromJson,
- cvox.BrailleUtil.ValueSpan.prototype.toJson);
-
-
-/**
- * Attached to the selected text within a value.
- * @constructor
- */
-cvox.BrailleUtil.ValueSelectionSpan = function() {
-};
-
-
-cvox.Spannable.registerStatelessSerializableSpan(
- cvox.BrailleUtil.ValueSelectionSpan,
- 'cvox.BrailleUtil.ValueSelectionSpan');
-
-
-/**
* Gets the braille name for a node.
* See DomUtil for a more precise definition of 'name'.
* Additionally, whitespace is trimmed.
@@ -165,44 +120,29 @@ cvox.BrailleUtil.getRoleMsg = function(node) {
/**
- * Gets the braille role of a node.
- * See DomUtil for a more precise definition of 'role'.
- * @param {Node} node The node.
- * @return {string} The string representation.
- */
-cvox.BrailleUtil.getRole = function(node) {
- if (!node) {
- return '';
- }
- var roleMsg = cvox.BrailleUtil.getRoleMsg(node);
- return roleMsg ? cvox.ChromeVox.msgs.getMsg(roleMsg) : '';
-};
-
-
-/**
- * Gets the braille state of a node.
- * @param {Node} node The node.
+ * Transforms a {@code cvox.NodeState} list of state messages to the
+ * corresponding messages for braille and expands them into a localized
+ * string suitable for output on a braille display.
+ * @param {cvox.NodeState} stateMsgs The states to expand. The content of this
+ * array is modified.
* @return {string} The string representation.
+ * @private
*/
-cvox.BrailleUtil.getState = function(node) {
- if (!node) {
- return '';
- }
- return cvox.NodeStateUtil.expand(
- cvox.DomUtil.getStateMsgs(node, true).map(function(state) {
- // Check to see if a variant of the message with '_brl' exists,
- // and use it if so.
- //
- // Note: many messages are templatized, and if we don't pass any
- // argument to substitute, getMsg might throw an error if the
- // resulting string is empty. To avoid this, we pass a dummy
- // substitution string array here.
- var dummySubs = ['dummy', 'dummy', 'dummy'];
- if (cvox.ChromeVox.msgs.getMsg(state[0] + '_brl', dummySubs)) {
- state[0] += '_brl';
- }
- return state;
- }));
+cvox.BrailleUtil.expandStateMsgs_ = function(stateMsgs) {
+ stateMsgs.forEach(function(state) {
+ // Check to see if a variant of the message with '_brl' exists,
+ // and use it if so.
+ //
+ // Note: many messages are templatized, and if we don't pass any
+ // argument to substitute, getMsg might throw an error if the
+ // resulting string is empty. To avoid this, we pass a dummy
+ // substitution string array here.
+ var dummySubs = ['dummy', 'dummy', 'dummy'];
+ if (cvox.ChromeVox.msgs.getMsg(state[0] + '_brl', dummySubs)) {
+ state[0] += '_brl';
+ }
+ });
+ return cvox.NodeStateUtil.expand(stateMsgs);
};
@@ -228,8 +168,8 @@ cvox.BrailleUtil.getContainer = function(prev, node) {
/**
- * Gets the braille value of a node. A cvox.BrailleUtil.ValueSpan will be
- * attached, along with (possibly) a cvox.BrailleUtil.ValueSelectionSpan.
+ * Gets the braille value of a node. A {@code cvox.ValueSpan} will be
+ * attached, along with (possibly) a {@code cvox.ValueSelectionSpan}.
* @param {Node} node The node.
* @return {!cvox.Spannable} The value spannable.
*/
@@ -237,7 +177,7 @@ cvox.BrailleUtil.getValue = function(node) {
if (!node) {
return new cvox.Spannable();
}
- var valueSpan = new cvox.BrailleUtil.ValueSpan(0 /* offset */);
+ var valueSpan = new cvox.ValueSpan(0 /* offset */);
if (cvox.DomUtil.isInputTypeText(node)) {
var value = node.value;
if (node.type === 'password') {
@@ -250,7 +190,7 @@ cvox.BrailleUtil.getValue = function(node) {
node.selectionStart, 0, spannable.getLength());
var selectionEnd = cvox.BrailleUtil.clamp_(
node.selectionEnd, 0, spannable.getLength());
- spannable.setSpan(new cvox.BrailleUtil.ValueSelectionSpan(),
+ spannable.setSpan(new cvox.ValueSelectionSpan(),
Math.min(selectionStart, selectionEnd),
Math.max(selectionStart, selectionEnd));
}
@@ -269,7 +209,7 @@ cvox.BrailleUtil.getValue = function(node) {
node.selectionStart - lineStart, 0, spannable.getLength());
var selectionEnd = cvox.BrailleUtil.clamp_(
node.selectionEnd - lineStart, 0, spannable.getLength());
- spannable.setSpan(new cvox.BrailleUtil.ValueSelectionSpan(),
+ spannable.setSpan(new cvox.ValueSelectionSpan(),
Math.min(selectionStart, selectionEnd),
Math.max(selectionStart, selectionEnd));
}
@@ -297,14 +237,22 @@ cvox.BrailleUtil.getTemplated = function(prev, node, opt_override) {
opt_override = opt_override ? opt_override : {};
var roleMsg = opt_override.roleMsg ||
(node ? cvox.DomUtil.getRoleMsg(node, cvox.VERBOSITY_VERBOSE) : '');
- var role = opt_override.role;
- if (!role && opt_override.roleMsg) {
- role = cvox.ChromeVox.msgs.getMsg(opt_override.roleMsg + '_brl') ||
- cvox.ChromeVox.msgs.getMsg(opt_override.roleMsg);
- }
- role = role || cvox.BrailleUtil.getRole(node);
var template = cvox.BrailleUtil.TEMPLATE[roleMsg] ||
cvox.BrailleUtil.TEMPLATE['base'];
+ var state = opt_override.state;
+ if (!state) {
+ if (node) {
+ state = cvox.BrailleUtil.expandStateMsgs_(
+ cvox.DomUtil.getStateMsgs(node, true));
+ } else {
+ state = '';
+ }
+ }
+ var role = opt_override.role || '';
+ if (!role && roleMsg) {
+ role = cvox.ChromeVox.msgs.getMsg(roleMsg + '_brl') ||
+ cvox.ChromeVox.msgs.getMsg(roleMsg);
+ }
var templated = new cvox.Spannable();
var mapChar = function(c) {
@@ -314,7 +262,7 @@ cvox.BrailleUtil.getTemplated = function(prev, node, opt_override) {
case 'r':
return role;
case 's':
- return opt_override.state || cvox.BrailleUtil.getState(node);
+ return state;
case 'c':
return opt_override.container ||
cvox.BrailleUtil.getContainer(prev, node);
@@ -327,8 +275,13 @@ cvox.BrailleUtil.getTemplated = function(prev, node, opt_override) {
for (var i = 0; i < template.length; i++) {
var component = mapChar(template[i]);
templated.append(component);
- // Ignore the next whitespace separator if the current component is empty.
- if (!component.toString() && template[i + 1] == ' ') {
+ // Ignore the next whitespace separator if the current component is empty,
+ // unless the empty value has a selection, in which case the cursor
+ // should be placed on the empty space after the empty value.
+ if (!component.toString() && template[i + 1] == ' ' &&
+ (!(component instanceof cvox.Spannable) ||
+ !/**@type {cvox.Spannable}*/(component).getSpanInstanceOf(
+ cvox.ValueSelectionSpan))) {
i++;
}
}
@@ -338,8 +291,8 @@ cvox.BrailleUtil.getTemplated = function(prev, node, opt_override) {
/**
* Creates a braille value from a string and, optionally, a selection range.
- * A cvox.BrailleUtil.ValueSpan will be
- * attached, along with a cvox.BrailleUtil.ValueSelectionSpan if applicable.
+ * A {@code cvox.ValueSpan} will be attached, along with a
+ * {@code cvox.ValueSelectionSpan} if applicable.
* @param {string} text The text to display as the value.
* @param {number=} opt_selStart Selection start.
* @param {number=} opt_selEnd Selection end if different from selection start.
@@ -349,7 +302,7 @@ cvox.BrailleUtil.getTemplated = function(prev, node, opt_override) {
cvox.BrailleUtil.createValue = function(text, opt_selStart, opt_selEnd,
opt_textOffset) {
var spannable = new cvox.Spannable(
- text, new cvox.BrailleUtil.ValueSpan(opt_textOffset || 0));
+ text, new cvox.ValueSpan(opt_textOffset || 0));
if (goog.isDef(opt_selStart)) {
opt_selEnd = goog.isDef(opt_selEnd) ? opt_selEnd : opt_selStart;
// TODO(plundblad): This looses the distinction between the selection
@@ -361,8 +314,7 @@ cvox.BrailleUtil.createValue = function(text, opt_selStart, opt_selEnd,
opt_selEnd = temp;
}
- spannable.setSpan(new cvox.BrailleUtil.ValueSelectionSpan(),
- opt_selStart, opt_selEnd);
+ spannable.setSpan(new cvox.ValueSelectionSpan(), opt_selStart, opt_selEnd);
}
return spannable;
};
@@ -390,7 +342,7 @@ cvox.BrailleUtil.click = function(braille, opt_displayPosition) {
node instanceof HTMLTextAreaElement)) {
var valueSpan = spans.filter(
function(s) {
- return s instanceof cvox.BrailleUtil.ValueSpan;
+ return s instanceof cvox.ValueSpan;
})[0];
if (valueSpan) {
if (document.activeElement !== node) {
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs
index 7e0a8cfa867..a1ee77ff9f4 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs
@@ -60,7 +60,7 @@ CvoxBrailleUtilUnitTest.prototype = {
startIndex: actual.startIndex,
endIndex: actual.endIndex
});
- assertThat(new cvox.NavBraille(expected), eqJSON(actual));
+ assertThat(actual, eqJSON(new cvox.NavBraille(expected)));
}
};
@@ -120,7 +120,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'NameTemplate', function() {
var button = cvox.CursorSelection.fromNode($('1'));
this.assertBrailleEquals(
- {text: '[Submit]',
+ {text: 'Submit btn',
startIndex: 0,
endIndex: 1
}, this.getBraille_(button, button));
@@ -130,13 +130,13 @@ TEST_F('CvoxBrailleUtilUnitTest', 'NameTemplate', function() {
// Note: the cursor appears where text would be typed.
this.assertBrailleEquals(
- {text: 'Search: edtxt',
+ {text: 'Search: ed',
startIndex: 0,
endIndex: 1
}, this.getBraille_(input, input));
inputElement.focus();
this.assertBrailleEquals(
- {text: 'Search: edtxt',
+ {text: 'Search: ed',
startIndex: 8,
endIndex: 8
}, this.getBraille_(input, input));
@@ -157,7 +157,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'TextField', function() {
// Note: the cursor appears where text would be typed.
// The cursor is at the beginning by default.
this.assertBrailleEquals(
- {text: 'Search: larry edtxt',
+ {text: 'Search: larry ed',
startIndex: 0,
endIndex: 1
}, this.getBraille_(input, input));
@@ -165,7 +165,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'TextField', function() {
inputElement.selectionStart = 0;
inputElement.selectionEnd = 5;
this.assertBrailleEquals(
- {text: 'Search: larry edtxt',
+ {text: 'Search: larry ed',
startIndex: 8,
endIndex: 13
}, this.getBraille_(input, input));
@@ -184,13 +184,13 @@ TEST_F('CvoxBrailleUtilUnitTest', 'TextFieldEmpty', function() {
var input = cvox.CursorSelection.fromNode($('1'));
this.assertBrailleEquals(
- {text: ': edtxt',
+ {text: ': ed',
startIndex: 0,
endIndex: 1
}, this.getBraille_(input, input));
inputElement.focus();
this.assertBrailleEquals(
- {text: ': edtxt',
+ {text: ': ed',
startIndex: 2,
endIndex: 2
}, this.getBraille_(input, input));
@@ -213,7 +213,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'TextFieldSelection', function() {
inputElem.selectionStart = 2;
inputElem.selectionEnd = 5;
this.assertBrailleEquals(
- {text: ': strawberry edtxt',
+ {text: ': strawberry ed',
startIndex: 4,
endIndex: 7
}, this.getBraille_(input, input));
@@ -222,7 +222,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'TextFieldSelection', function() {
inputElem.selectionStart = 10;
inputElem.selectionEnd = 10;
this.assertBrailleEquals(
- {text: ': strawberry edtxt',
+ {text: ': strawberry ed',
startIndex: 12,
endIndex: 12
}, this.getBraille_(input, input));
@@ -239,7 +239,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'StateTemplate', function() {
var checkbox = cvox.CursorSelection.fromNode($('1'));
this.assertBrailleEquals(
- {text: 'Save ( )',
+ {text: 'Save chk ( )',
startIndex: 0,
endIndex: 1
}, this.getBraille_(checkbox, checkbox));
@@ -247,7 +247,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'StateTemplate', function() {
$('1').checked = true;
this.assertBrailleEquals(
- {text: 'Save (x)',
+ {text: 'Save chk (x)',
startIndex: 0,
endIndex: 1
}, this.getBraille_(checkbox, checkbox));
@@ -286,7 +286,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'ContainerTemplate', function() {
var navBraille = this.getBraille_(
cvox.CursorSelection.fromBody(), link);
this.assertBrailleEquals(
- {text: 'h1 Skip To Menu int lnk',
+ {text: 'h1 Skip To Menu intlnk',
startIndex: 0,
endIndex: 1
}, navBraille);
@@ -303,14 +303,33 @@ TEST_F('CvoxBrailleUtilUnitTest', 'LinkSpans', function() {
var link2 = $('2');
var navBraille = this.getBraille_(
cvox.CursorSelection.fromBody(), cvox.CursorSelection.fromNode(link1));
- assertEquals('Hello int lnk from ChromeVox lnk',
+ assertEquals('Hello intlnk from ChromeVox lnk',
navBraille.text.toString());
assertEquals(link1, navBraille.text.getSpan(0));
- assertEquals(link1, navBraille.text.getSpan(12));
- assertEquals('undefined', typeof navBraille.text.getSpan(13));
- assertEquals('undefined', typeof navBraille.text.getSpan(18));
- assertEquals(link2, navBraille.text.getSpan(19));
- assertEquals(link2, navBraille.text.getSpan(31));
+ assertEquals(link1, navBraille.text.getSpan(11));
+ assertEquals('undefined', typeof navBraille.text.getSpan(12));
+ assertEquals('undefined', typeof navBraille.text.getSpan(17));
+ assertEquals(link2, navBraille.text.getSpan(18));
+ assertEquals(link2, navBraille.text.getSpan(30));
+});
+
+
+TEST_F('CvoxBrailleUtilUnitTest', 'VisitedLink', function() {
+ this.loadHtml('<p><a id="1" href="http://visited.link">Hello</a> there.');
+ var link = $('1');
+ var navBraille = this.getBraille_(
+ cvox.CursorSelection.fromBody(), cvox.CursorSelection.fromNode(link));
+ this.assertBrailleEquals({text: 'Hello lnk there.',
+ startIndex: 0,
+ endIndex: 1},
+ navBraille);
+ cvox.ChromeVox.visitedUrls[link.href] = true;
+ navBraille = this.getBraille_(
+ cvox.CursorSelection.fromBody(), cvox.CursorSelection.fromNode(link));
+ this.assertBrailleEquals({text: 'Hello vlnk there.',
+ startIndex: 0,
+ endIndex: 1},
+ navBraille);
});
@@ -324,7 +343,7 @@ TEST_F('CvoxBrailleUtilUnitTest', 'NestedElements', function() {
var link = $('batman-link');
var navBraille = this.getBraille_(
cvox.CursorSelection.fromBody(), cvox.CursorSelection.fromNode(h1));
- assertEquals('h1 Larry, Sergey int lnk and Eric',
+ assertEquals('h1 Larry, Sergey intlnk and Eric',
navBraille.text.toString());
this.assertTextNodeChildOf_(h1, navBraille.text.getSpan(0));
this.assertTextNodeChildOf_(h1, navBraille.text.getSpan(5));
@@ -370,32 +389,32 @@ TEST_F('CvoxBrailleUtilUnitTest', 'CreateValue', function() {
// Value without a selection.
s = cvox.BrailleUtil.createValue('value');
assertEquals('value', s.toString());
- assertUndefined(s.getSpanInstanceOf(cvox.BrailleUtil.ValueSelectionSpan));
- valueSpan = s.getSpanInstanceOf(cvox.BrailleUtil.ValueSpan);
+ assertUndefined(s.getSpanInstanceOf(cvox.ValueSelectionSpan));
+ valueSpan = s.getSpanInstanceOf(cvox.ValueSpan);
assertEquals(0, s.getSpanStart(valueSpan));
assertEquals(s.getLength(), s.getSpanEnd(valueSpan));
// Value with a carret at the start of the text.
s = cvox.BrailleUtil.createValue('value', 0);
- selectionSpan = s.getSpanInstanceOf(cvox.BrailleUtil.ValueSelectionSpan);
+ selectionSpan = s.getSpanInstanceOf(cvox.ValueSelectionSpan);
assertEquals(0, s.getSpanStart(selectionSpan));
assertEquals(0, s.getSpanEnd(selectionSpan));
// Value with a carret inside the text.
s = cvox.BrailleUtil.createValue('value', 1);
- selectionSpan = s.getSpanInstanceOf(cvox.BrailleUtil.ValueSelectionSpan);
+ selectionSpan = s.getSpanInstanceOf(cvox.ValueSelectionSpan);
assertEquals(1, s.getSpanStart(selectionSpan));
assertEquals(1, s.getSpanEnd(selectionSpan));
// Value with a carret at the end of the text.
s = cvox.BrailleUtil.createValue('value', 5);
- selectionSpan = s.getSpanInstanceOf(cvox.BrailleUtil.ValueSelectionSpan);
+ selectionSpan = s.getSpanInstanceOf(cvox.ValueSelectionSpan);
assertEquals(5, s.getSpanStart(selectionSpan));
assertEquals(5, s.getSpanEnd(selectionSpan));
// All of the value selected selected with reversed start and end.
s = cvox.BrailleUtil.createValue('value', 5, 0);
- selectionSpan = s.getSpanInstanceOf(cvox.BrailleUtil.ValueSelectionSpan);
+ selectionSpan = s.getSpanInstanceOf(cvox.ValueSelectionSpan);
assertEquals(0, s.getSpanStart(selectionSpan));
assertEquals(5, s.getSpanEnd(selectionSpan));
});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js
index 6f532a96ac2..86fa446e2d9 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js
@@ -37,10 +37,10 @@ chrome.extension.inIncognitoContext;
/**
- * @param {string|Object.<string>=} opt_extensionIdOrConnectInfo Either the
+ * @param {string|Object<string>=} opt_extensionIdOrConnectInfo Either the
* extensionId to connect to, in which case connectInfo params can be
* passed in the next optional argument, or the connectInfo params.
- * @param {Object.<string>=} opt_connectInfo The connectInfo object,
+ * @param {Object<string>=} opt_connectInfo The connectInfo object,
* if arg1 was the extensionId to connect to.
* @return {Port} New port.
*/
@@ -161,7 +161,7 @@ chrome.runtime.Manifest.Oauth2 = function() {};
/** @type {string} */
chrome.runtime.Manifest.Oauth2.prototype.client_id;
-/**@type {!Array.<string>} */
+/**@type {!Array<string>} */
chrome.runtime.Manifest.Oauth2.prototype.scopes;
@@ -181,10 +181,10 @@ chrome.runtime.getManifest = function() {};
chrome.runtime.getURL = function(path) {};
/**
- * @param {string|!Object.<string>=} opt_extensionIdOrConnectInfo Either the
+ * @param {string|!Object<string>=} opt_extensionIdOrConnectInfo Either the
* extensionId to connect to, in which case connectInfo params can be
* passed in the next optional argument, or the connectInfo params.
- * @param {!Object.<string>=} opt_connectInfo The connectInfo object,
+ * @param {!Object<string>=} opt_connectInfo The connectInfo object,
* if arg1 was the extensionId to connect to.
* @return {!Port} New port.
*/
@@ -325,7 +325,7 @@ chrome.tabs.captureVisibleTab = function(windowId, options, callback) {};
/**
* @param {number} tabId Tab Id.
- * @param {Object.<string>=} opt_connectInfo Info Object.
+ * @param {Object<string>=} opt_connectInfo Info Object.
*/
chrome.tabs.connect = function(tabId, opt_connectInfo) {};
@@ -365,7 +365,7 @@ chrome.tabs.get = function(tabId, callback) {};
* the public web pages, but there are still existing usages
*
* @param {number?} windowId Window id.
- * @param {function(Array.<Tab>): void} callback Callback.
+ * @param {function(Array<Tab>): void} callback Callback.
*/
chrome.tabs.getAllInWindow = function(windowId, callback) {};
@@ -387,7 +387,7 @@ chrome.tabs.getSelected = function(windowId, callback) {};
/**
- * @param {Object.<string, (number|Array.<number>)>} highlightInfo
+ * @param {Object<string, (number|Array<number>)>} highlightInfo
* An object with 'windowId' (number) and 'tabs'
* (number or array of numbers) keys.
* @param {function(Window): void} callback Callback function invoked
@@ -407,7 +407,7 @@ chrome.tabs.insertCSS = function(tabId, details, opt_callback) {};
/**
* @param {number} tabId Tab id.
- * @param {Object.<string, number>} moveProperties An object with 'index'
+ * @param {Object<string, number>} moveProperties An object with 'index'
* and optional 'windowId' keys.
* @param {function(Tab): void=} opt_callback Callback.
*/
@@ -415,18 +415,18 @@ chrome.tabs.move = function(tabId, moveProperties, opt_callback) {};
/**
- * @param {Object.<string, (number|string)>} queryInfo An object which may have
+ * @param {Object<string, (number|string)>} queryInfo An object which may have
* 'active', 'pinned', 'highlighted', 'status', 'title', 'url', 'windowId',
* and 'windowType' keys.
- * @param {function(Array.<Tab>): void=} opt_callback Callback.
- * @return {!Array.<Tab>}
+ * @param {function(Array<Tab>): void=} opt_callback Callback.
+ * @return {!Array<Tab>}
*/
chrome.tabs.query = function(queryInfo, opt_callback) {};
/**
* @param {number=} opt_tabId Tab id.
- * @param {Object.<string, boolean>=} opt_reloadProperties An object which
+ * @param {Object<string, boolean>=} opt_reloadProperties An object which
* may have a 'bypassCache' key.
* @param {function(): void=} opt_callback The callback function invoked
* after the tab has been reloaded.
@@ -435,7 +435,7 @@ chrome.tabs.reload = function(opt_tabId, opt_reloadProperties, opt_callback) {};
/**
- * @param {number|Array.<number>} tabIds A tab ID or an array of tab IDs.
+ * @param {number|Array<number>} tabIds A tab ID or an array of tab IDs.
* @param {function(Tab): void=} opt_callback Callback.
*/
chrome.tabs.remove = function(tabIds, opt_callback) {};
@@ -461,7 +461,7 @@ chrome.tabs.sendRequest = function(tabId, request, opt_callback) {};
/**
* @param {number} tabId Tab id.
- * @param {Object.<string, (string|boolean)>} updateProperties An object which
+ * @param {Object<string, (string|boolean)>} updateProperties An object which
* may have 'url' or 'selected' key.
* @param {function(Tab): void=} opt_callback Callback.
*/
@@ -532,7 +532,7 @@ chrome.windows.get = function(id, opt_getInfo, opt_callback) {};
/**
* @param {Object=} opt_getInfo May have 'populate' key. Or the callback.
- * @param {function(!Array.<!ChromeWindow>): void=} opt_callback Callback.
+ * @param {function(!Array<!ChromeWindow>): void=} opt_callback Callback.
*/
chrome.windows.getAll = function(opt_getInfo, opt_callback) {};
@@ -598,7 +598,7 @@ chrome.i18n = {};
/**
- * @param {function(Array.<string>): void} callback The callback function which
+ * @param {function(Array<string>): void} callback The callback function which
* accepts an array of the accept languages of the browser, such as
* 'en-US','en','zh-CN'.
*/
@@ -607,7 +607,7 @@ chrome.i18n.getAcceptLanguages = function(callback) {};
/**
* @param {string} messageName
- * @param {(string|Array.<string>)=} opt_args
+ * @param {(string|Array<string>)=} opt_args
* @return {string}
*/
chrome.i18n.getMessage = function(messageName, opt_args) {};
@@ -664,13 +664,13 @@ TtsVoice.prototype.gender;
TtsVoice.prototype.extensionId;
-/** @type {Array.<string>} */
+/** @type {Array<string>} */
TtsVoice.prototype.eventTypes;
/**
* Gets an array of all available voices.
- * @param {function(Array.<TtsVoice>)=} opt_callback An optional callback
+ * @param {function(Array<TtsVoice>)=} opt_callback An optional callback
* function.
*/
chrome.tts.getVoices = function(opt_callback) {};
@@ -708,7 +708,7 @@ chrome.history = {};
/**
- * @param {Object.<string, string>} details Object with a 'url' key.
+ * @param {Object<string, string>} details Object with a 'url' key.
*/
chrome.history.addUrl = function(details) {};
@@ -720,7 +720,7 @@ chrome.history.deleteAll = function(callback) {};
/**
- * @param {Object.<string, string>} range Object with 'startTime'
+ * @param {Object<string, string>} range Object with 'startTime'
* and 'endTime' keys.
* @param {function(): void} callback Callback function.
*/
@@ -728,25 +728,25 @@ chrome.history.deleteRange = function(range, callback) {};
/**
- * @param {Object.<string, string>} details Object with a 'url' key.
+ * @param {Object<string, string>} details Object with a 'url' key.
*/
chrome.history.deleteUrl = function(details) {};
/**
- * @param {Object.<string, string>} details Object with a 'url' key.
- * @param {function(!Array.<!VisitItem>): void} callback Callback function.
- * @return {!Array.<!VisitItem>}
+ * @param {Object<string, string>} details Object with a 'url' key.
+ * @param {function(!Array<!VisitItem>): void} callback Callback function.
+ * @return {!Array<!VisitItem>}
*/
chrome.history.getVisits = function(details, callback) {};
/**
- * @param {Object.<string, string>} query Object with a 'text' (string)
+ * @param {Object<string, string>} query Object with a 'text' (string)
* key and optional 'startTime' (number), 'endTime' (number) and
* 'maxResults' keys.
- * @param {function(!Array.<!HistoryItem>): void} callback Callback function.
- * @return {!Array.<!HistoryItem>}
+ * @param {function(!Array<!HistoryItem>): void} callback Callback function.
+ * @return {!Array<!HistoryItem>}
*/
chrome.history.search = function(query, callback) {};
@@ -767,8 +767,8 @@ chrome.permissions = {};
/**
* @typedef {{
- * permissions: (Array.<string>|undefined),
- * origins: (Array.<string>|undefined)
+ * permissions: (Array<string>|undefined),
+ * origins: (Array<string>|undefined)
* }}
* @see http://developer.chrome.com/extensions/permissions.html#type-Permissions
*/
@@ -914,7 +914,7 @@ ChromeWindow.prototype.width;
ChromeWindow.prototype.height;
-/** @type {Array.<Tab>} */
+/** @type {Array<Tab>} */
ChromeWindow.prototype.tabs;
@@ -983,7 +983,7 @@ Port.prototype.sender;
/**
- * @param {Object.<string>} obj Message object.
+ * @param {Object<string>} obj Message object.
*/
Port.prototype.postMessage = function(obj) {};
@@ -1053,7 +1053,7 @@ BookmarkTreeNode.prototype.dateAdded;
BookmarkTreeNode.prototype.dateGroupModified;
-/** @type {Array.<BookmarkTreeNode>} */
+/** @type {Array<BookmarkTreeNode>} */
BookmarkTreeNode.prototype.children;
@@ -1211,16 +1211,378 @@ chrome.storage.local.remove = function(keys, opt_callback) {};
chrome.storage.onChanged;
+// Begin auto generated externs; do not edit.
+// The following was generated from:
+//
+// python tools/json_schema_compiler/compiler.py
+// -g externs
+// chrome/common/extensions/api/automation.idl
+
/**
* @const
*/
chrome.automation = {};
/**
+ * @enum {string}
+ */
+chrome.automation.EventType = {
+ activedescendantchanged: 'activedescendantchanged',
+ alert: 'alert',
+ ariaAttributeChanged: 'ariaAttributeChanged',
+ autocorrectionOccured: 'autocorrectionOccured',
+ blur: 'blur',
+ checkedStateChanged: 'checkedStateChanged',
+ childrenChanged: 'childrenChanged',
+ focus: 'focus',
+ hide: 'hide',
+ hover: 'hover',
+ invalidStatusChanged: 'invalidStatusChanged',
+ layoutComplete: 'layoutComplete',
+ liveRegionChanged: 'liveRegionChanged',
+ loadComplete: 'loadComplete',
+ locationChanged: 'locationChanged',
+ menuEnd: 'menuEnd',
+ menuListItemSelected: 'menuListItemSelected',
+ menuListValueChanged: 'menuListValueChanged',
+ menuPopupEnd: 'menuPopupEnd',
+ menuPopupStart: 'menuPopupStart',
+ menuStart: 'menuStart',
+ rowCollapsed: 'rowCollapsed',
+ rowCountChanged: 'rowCountChanged',
+ rowExpanded: 'rowExpanded',
+ scrollPositionChanged: 'scrollPositionChanged',
+ scrolledToAnchor: 'scrolledToAnchor',
+ selectedChildrenChanged: 'selectedChildrenChanged',
+ selection: 'selection',
+ selectionAdd: 'selectionAdd',
+ selectionRemove: 'selectionRemove',
+ show: 'show',
+ textChanged: 'textChanged',
+ textSelectionChanged: 'textSelectionChanged',
+ treeChanged: 'treeChanged',
+ valueChanged: 'valueChanged',
+};
+
+/**
+ * @enum {string}
+ */
+chrome.automation.RoleType = {
+ alertDialog: 'alertDialog',
+ alert: 'alert',
+ annotation: 'annotation',
+ application: 'application',
+ article: 'article',
+ banner: 'banner',
+ blockquote: 'blockquote',
+ busyIndicator: 'busyIndicator',
+ button: 'button',
+ buttonDropDown: 'buttonDropDown',
+ canvas: 'canvas',
+ caption: 'caption',
+ cell: 'cell',
+ checkBox: 'checkBox',
+ client: 'client',
+ colorWell: 'colorWell',
+ columnHeader: 'columnHeader',
+ column: 'column',
+ comboBox: 'comboBox',
+ complementary: 'complementary',
+ contentInfo: 'contentInfo',
+ date: 'date',
+ dateTime: 'dateTime',
+ definition: 'definition',
+ descriptionListDetail: 'descriptionListDetail',
+ descriptionList: 'descriptionList',
+ descriptionListTerm: 'descriptionListTerm',
+ desktop: 'desktop',
+ details: 'details',
+ dialog: 'dialog',
+ directory: 'directory',
+ disclosureTriangle: 'disclosureTriangle',
+ div: 'div',
+ document: 'document',
+ embeddedObject: 'embeddedObject',
+ figcaption: 'figcaption',
+ figure: 'figure',
+ footer: 'footer',
+ form: 'form',
+ grid: 'grid',
+ group: 'group',
+ heading: 'heading',
+ iframe: 'iframe',
+ iframePresentational: 'iframePresentational',
+ ignored: 'ignored',
+ imageMapLink: 'imageMapLink',
+ imageMap: 'imageMap',
+ image: 'image',
+ inlineTextBox: 'inlineTextBox',
+ labelText: 'labelText',
+ legend: 'legend',
+ lineBreak: 'lineBreak',
+ link: 'link',
+ listBoxOption: 'listBoxOption',
+ listBox: 'listBox',
+ listItem: 'listItem',
+ listMarker: 'listMarker',
+ list: 'list',
+ locationBar: 'locationBar',
+ log: 'log',
+ main: 'main',
+ marquee: 'marquee',
+ math: 'math',
+ menuBar: 'menuBar',
+ menuButton: 'menuButton',
+ menuItem: 'menuItem',
+ menuItemCheckBox: 'menuItemCheckBox',
+ menuItemRadio: 'menuItemRadio',
+ menuListOption: 'menuListOption',
+ menuListPopup: 'menuListPopup',
+ menu: 'menu',
+ meter: 'meter',
+ navigation: 'navigation',
+ note: 'note',
+ outline: 'outline',
+ pane: 'pane',
+ paragraph: 'paragraph',
+ popUpButton: 'popUpButton',
+ pre: 'pre',
+ presentational: 'presentational',
+ progressIndicator: 'progressIndicator',
+ radioButton: 'radioButton',
+ radioGroup: 'radioGroup',
+ region: 'region',
+ rootWebArea: 'rootWebArea',
+ rowHeader: 'rowHeader',
+ row: 'row',
+ ruby: 'ruby',
+ ruler: 'ruler',
+ svgRoot: 'svgRoot',
+ scrollArea: 'scrollArea',
+ scrollBar: 'scrollBar',
+ seamlessWebArea: 'seamlessWebArea',
+ search: 'search',
+ searchBox: 'searchBox',
+ slider: 'slider',
+ sliderThumb: 'sliderThumb',
+ spinButtonPart: 'spinButtonPart',
+ spinButton: 'spinButton',
+ splitter: 'splitter',
+ staticText: 'staticText',
+ status: 'status',
+ switch: 'switch',
+ tabGroup: 'tabGroup',
+ tabList: 'tabList',
+ tabPanel: 'tabPanel',
+ tab: 'tab',
+ tableHeaderContainer: 'tableHeaderContainer',
+ table: 'table',
+ textField: 'textField',
+ time: 'time',
+ timer: 'timer',
+ titleBar: 'titleBar',
+ toggleButton: 'toggleButton',
+ toolbar: 'toolbar',
+ treeGrid: 'treeGrid',
+ treeItem: 'treeItem',
+ tree: 'tree',
+ unknown: 'unknown',
+ tooltip: 'tooltip',
+ webArea: 'webArea',
+ webView: 'webView',
+ window: 'window',
+};
+
+/**
+ * @enum {string}
+ */
+chrome.automation.StateType = {
+ busy: 'busy',
+ checked: 'checked',
+ collapsed: 'collapsed',
+ default: 'default',
+ disabled: 'disabled',
+ editable: 'editable',
+ enabled: 'enabled',
+ expanded: 'expanded',
+ focusable: 'focusable',
+ focused: 'focused',
+ haspopup: 'haspopup',
+ horizontal: 'horizontal',
+ hovered: 'hovered',
+ indeterminate: 'indeterminate',
+ invisible: 'invisible',
+ linked: 'linked',
+ multiselectable: 'multiselectable',
+ offscreen: 'offscreen',
+ pressed: 'pressed',
+ protected: 'protected',
+ readOnly: 'readOnly',
+ required: 'required',
+ selectable: 'selectable',
+ selected: 'selected',
+ vertical: 'vertical',
+ visited: 'visited',
+};
+
+/**
+ * @enum {string}
+ */
+chrome.automation.TreeChangeType = {
+ nodeCreated: 'nodeCreated',
+ subtreeCreated: 'subtreeCreated',
+ nodeChanged: 'nodeChanged',
+ nodeRemoved: 'nodeRemoved',
+};
+
+/**
+ * @typedef {{
+ * left: number,
+ * top: number,
+ * width: number,
+ * height: number
+ * }}
+ */
+chrome.automation.Rect;
+
+/**
+ * @typedef {{
+ * role: (!chrome.automation.RoleType|undefined),
+ * state: (Object|undefined),
+ * attributes: (Object|undefined)
+ * }}
+ */
+chrome.automation.FindParams;
+
+/**
+ * @constructor
+ */
+chrome.automation.AutomationEvent = function() {};
+
+/**
+ * @typedef {{
+ * target: chrome.automation.AutomationNode,
+ * type: !chrome.automation.TreeChangeType
+ * }}
+ */
+chrome.automation.TreeChange;
+
+/**
* @constructor
*/
chrome.automation.AutomationNode = function() {};
+/**
+ * @typedef {{
+ * activedescendant: chrome.automation.AutomationNode
+ * }}
+ */
+chrome.automation.ActiveDescendantMixin;
+
+/**
+ * @typedef {{
+ * url: string
+ * }}
+ */
+chrome.automation.LinkMixins;
+
+/**
+ * @typedef {{
+ * docUrl: string,
+ * docTitle: string,
+ * docLoaded: boolean,
+ * docLoadingProgress: number
+ * }}
+ */
+chrome.automation.DocumentMixins;
+
+/**
+ * @typedef {{
+ * scrollX: number,
+ * scrollXMin: number,
+ * scrollXMax: number,
+ * scrollY: number,
+ * scrollYMin: number,
+ * scrollYMax: number
+ * }}
+ */
+chrome.automation.ScrollableMixins;
+
+/**
+ * @typedef {{
+ * textSelStart: number,
+ * textSelEnd: number
+ * }}
+ */
+chrome.automation.EditableTextMixins;
+
+/**
+ * @typedef {{
+ * valueForRange: number,
+ * minValueForRange: number,
+ * maxValueForRange: number
+ * }}
+ */
+chrome.automation.RangeMixins;
+
+/**
+ * @typedef {{
+ * tableRowCount: number,
+ * tableColumnCount: number
+ * }}
+ */
+chrome.automation.TableMixins;
+
+/**
+ * @typedef {{
+ * tableCellColumnIndex: number,
+ * tableCellColumnSpan: number,
+ * tableCellRowIndex: number,
+ * tableCellRowSpan: number
+ * }}
+ */
+chrome.automation.TableCellMixins;
+
+/**
+ * Get the automation tree for the tab with the given tabId, or the current tab
+ * if no tabID is given, enabling automation if necessary. Returns a tree with a
+ * placeholder root node; listen for the "loadComplete" event to get a
+ * notification that the tree has fully loaded (the previous root node reference
+ * will stop working at or before this point).
+ * @param {number} tabId
+ * @param {function(chrome.automation.AutomationNode):void} callback
+ * Called when the <code>AutomationNode</code> for the page is available.
+ */
+chrome.automation.getTree = function(tabId, callback) {};
+
+/**
+ * Get the automation tree for the whole desktop which consists of all on screen
+ * views. Note this API is currently only supported on Chrome OS.
+ * @param {function(chrome.automation.AutomationNode):void} callback
+ * Called when the <code>AutomationNode</code> for the page is available.
+ */
+chrome.automation.getDesktop = function(callback) {};
+
+/**
+ * Add a tree change observer. Tree change observers are static/global,
+ * they listen to tree changes across all trees.
+ * @param {function(chrome.automation.TreeChange):void} observer
+ * A listener for tree changes on the <code>AutomationNode</code> tree.
+ */
+chrome.automation.addTreeChangeObserver = function(observer) {};
+
+/**
+ * Remove a tree change observer.
+ * @param {function(chrome.automation.TreeChange):void} observer
+ * A listener for tree changes on the <code>AutomationNode</code> tree.
+ */
+chrome.automation.removeTreeChangeObserver = function(observer) {};
+
+//
+// End auto generated externs; do not edit.
+//
+
+
/**
* @type {chrome.automation.RoleType}
@@ -1229,11 +1591,26 @@ chrome.automation.AutomationNode.prototype.role;
/**
+ * @type {!Object<chrome.automation.StateType, boolean>}
+ */
+chrome.automation.AutomationNode.prototype.state;
+
+
+/**
+ * @type {number}
+ */
+chrome.automation.AutomationNode.prototype.indexInParent;
+
+
+/**
* @type {{
* name: string,
+ * url: string,
* value: string,
- * wordStarts: Array.<number>,
- * wordEnds: Array.<number>
+ * textSelStart: number,
+ * textSelEnd: number,
+ * wordStarts: Array<number>,
+ * wordEnds: Array<number>
* }}
*/
chrome.automation.AutomationNode.prototype.attributes;
@@ -1246,39 +1623,39 @@ chrome.automation.AutomationNode.prototype.root;
/**
- * @return {chrome.automation.AutomationNode}
+ * @type {chrome.automation.AutomationNode}
*/
-chrome.automation.AutomationNode.prototype.firstChild = function() {};
+chrome.automation.AutomationNode.prototype.firstChild;
/**
- * @return {chrome.automation.AutomationNode}
+ * @type {chrome.automation.AutomationNode}
*/
-chrome.automation.AutomationNode.prototype.lastChild = function() {};
+chrome.automation.AutomationNode.prototype.lastChild;
/**
- * @return {chrome.automation.AutomationNode}
+ * @type {chrome.automation.AutomationNode}
*/
-chrome.automation.AutomationNode.prototype.nextSibling = function() {};
+chrome.automation.AutomationNode.prototype.nextSibling;
/**
- * @return {chrome.automation.AutomationNode}
+ * @type {chrome.automation.AutomationNode}
*/
-chrome.automation.AutomationNode.prototype.previousSibling = function() {};
+chrome.automation.AutomationNode.prototype.previousSibling;
/**
- * @return {chrome.automation.AutomationNode}
+ * @type {chrome.automation.AutomationNode}
*/
-chrome.automation.AutomationNode.prototype.parent = function() {};
+chrome.automation.AutomationNode.prototype.parent;
/**
- * @return {!Array.<chrome.automation.AutomationNode>}
+ * @type {!Array<chrome.automation.AutomationNode>}
*/
-chrome.automation.AutomationNode.prototype.children = function() {};
+chrome.automation.AutomationNode.prototype.children;
/**
@@ -1305,232 +1682,72 @@ chrome.automation.AutomationNode.prototype.removeEventListener =
function(eventType, callback, capture) {};
-chrome.automation.AutomationNode.prototype.focus = function() {};
+/**
+ * @type {chrome.automation.AutomationNode}
+ */
+chrome.automation.TreeChange.prototype.target;
/**
- * @param {function(chrome.automation.AutomationNode)} callback
+ * @type {chrome.automation.TreeChangeType}
*/
-chrome.automation.getDesktop = function(callback) {};
+chrome.automation.TreeChange.prototype.type;
/**
- * @param {function(chrome.automation.AutomationNode)} callback
+ * @param {function(chrome.automation.TreeChange) : void}
+ * callback
*/
-chrome.automation.getTree = function(callback) {};
+chrome.automation.AutomationNode.prototype.addTreeChangeObserver =
+ function(callback) {};
/**
- * @const
+ * @param {function(chrome.automation.TreeChange) : void}
+ * callback
*/
-chrome.commands = {};
+chrome.automation.AutomationNode.prototype.removeTreeChangeObserver =
+ function(callback) {};
+
+
+chrome.automation.AutomationNode.prototype.doDefault = function() {};
+
+
+chrome.automation.AutomationNode.prototype.focus = function() {};
+
+/** @type {string} */
+chrome.automation.AutomationNode.prototype.containerLiveStatus;
+
+/** @type {string} */
+chrome.automation.AutomationNode.prototype.containerLiveRelevant;
+
+/** @type {boolean} */
+chrome.automation.AutomationNode.prototype.containerLiveAtomic;
+
+/** @type {boolean} */
+chrome.automation.AutomationNode.prototype.containerLiveBusy;
/**
- * @type {ChromeEvent}
+ * @param {Object} findParams
*/
-chrome.commands.onCommand;
+chrome.automation.AutomationNode.prototype.find = function(findParams) {};
-// Begin auto generated externs; do not edit.
-// The following was generated from tools/json_schema_compiler/compiler.py.
/**
- * Possible events fired on an $(ref:automation.AutomationNode).
- * @enum {string}
+ * @const
*/
-chrome.automation.EventType = {
- activedescendantchanged: 'activedescendantchanged',
- alert: 'alert',
- ariaAttributeChanged: 'ariaAttributeChanged',
- autocorrectionOccured: 'autocorrectionOccured',
- blur: 'blur',
- checkedStateChanged: 'checkedStateChanged',
- childrenChanged: 'childrenChanged',
- focus: 'focus',
- hide: 'hide',
- hover: 'hover',
- invalidStatusChanged: 'invalidStatusChanged',
- layoutComplete: 'layoutComplete',
- liveRegionChanged: 'liveRegionChanged',
- loadComplete: 'loadComplete',
- locationChanged: 'locationChanged',
- menuEnd: 'menuEnd',
- menuListItemSelected: 'menuListItemSelected',
- menuListValueChanged: 'menuListValueChanged',
- menuPopupEnd: 'menuPopupEnd',
- menuPopupStart: 'menuPopupStart',
- menuStart: 'menuStart',
- rowCollapsed: 'rowCollapsed',
- rowCountChanged: 'rowCountChanged',
- rowExpanded: 'rowExpanded',
- scrollPositionChanged: 'scrollPositionChanged',
- scrolledToAnchor: 'scrolledToAnchor',
- selectedChildrenChanged: 'selectedChildrenChanged',
- selectedTextChanged: 'selectedTextChanged',
- selection: 'selection',
- selectionAdd: 'selectionAdd',
- selectionRemove: 'selectionRemove',
- show: 'show',
- textChanged: 'textChanged',
- textInserted: 'textInserted',
- textRemoved: 'textRemoved',
- textSelectionChanged: 'textSelectionChanged',
- valueChanged: 'valueChanged'
-};
+chrome.commands = {};
+
+
/**
- * Describes the purpose of an $(ref:automation.AutomationNode).
- * @enum {string}
+ * @type {ChromeEvent}
*/
-chrome.automation.RoleType = {
- alertDialog: 'alertDialog',
- alert: 'alert',
- annotation: 'annotation',
- application: 'application',
- article: 'article',
- banner: 'banner',
- browser: 'browser',
- busyIndicator: 'busyIndicator',
- button: 'button',
- buttonDropDown: 'buttonDropDown',
- canvas: 'canvas',
- cell: 'cell',
- checkBox: 'checkBox',
- client: 'client',
- colorWell: 'colorWell',
- columnHeader: 'columnHeader',
- column: 'column',
- comboBox: 'comboBox',
- complementary: 'complementary',
- contentInfo: 'contentInfo',
- definition: 'definition',
- descriptionListDetail: 'descriptionListDetail',
- descriptionListTerm: 'descriptionListTerm',
- desktop: 'desktop',
- dialog: 'dialog',
- directory: 'directory',
- disclosureTriangle: 'disclosureTriangle',
- div: 'div',
- document: 'document',
- drawer: 'drawer',
- editableText: 'editableText',
- embeddedObject: 'embeddedObject',
- footer: 'footer',
- form: 'form',
- grid: 'grid',
- group: 'group',
- growArea: 'growArea',
- heading: 'heading',
- helpTag: 'helpTag',
- horizontalRule: 'horizontalRule',
- iframe: 'iframe',
- ignored: 'ignored',
- imageMapLink: 'imageMapLink',
- imageMap: 'imageMap',
- image: 'image',
- incrementor: 'incrementor',
- inlineTextBox: 'inlineTextBox',
- labelText: 'labelText',
- legend: 'legend',
- link: 'link',
- listBoxOption: 'listBoxOption',
- listBox: 'listBox',
- listItem: 'listItem',
- listMarker: 'listMarker',
- list: 'list',
- locationBar: 'locationBar',
- log: 'log',
- main: 'main',
- marquee: 'marquee',
- mathElement: 'mathElement',
- math: 'math',
- matte: 'matte',
- menuBar: 'menuBar',
- menuButton: 'menuButton',
- menuItem: 'menuItem',
- menuListOption: 'menuListOption',
- menuListPopup: 'menuListPopup',
- menu: 'menu',
- navigation: 'navigation',
- note: 'note',
- outline: 'outline',
- pane: 'pane',
- paragraph: 'paragraph',
- popUpButton: 'popUpButton',
- presentational: 'presentational',
- progressIndicator: 'progressIndicator',
- radioButton: 'radioButton',
- radioGroup: 'radioGroup',
- region: 'region',
- rootWebArea: 'rootWebArea',
- rowHeader: 'rowHeader',
- row: 'row',
- rulerMarker: 'rulerMarker',
- ruler: 'ruler',
- svgRoot: 'svgRoot',
- scrollArea: 'scrollArea',
- scrollBar: 'scrollBar',
- seamlessWebArea: 'seamlessWebArea',
- search: 'search',
- sheet: 'sheet',
- slider: 'slider',
- sliderThumb: 'sliderThumb',
- spinButtonPart: 'spinButtonPart',
- spinButton: 'spinButton',
- splitGroup: 'splitGroup',
- splitter: 'splitter',
- staticText: 'staticText',
- status: 'status',
- systemWide: 'systemWide',
- tabGroup: 'tabGroup',
- tabList: 'tabList',
- tabPanel: 'tabPanel',
- tab: 'tab',
- tableHeaderContainer: 'tableHeaderContainer',
- table: 'table',
- textArea: 'textArea',
- textField: 'textField',
- timer: 'timer',
- titleBar: 'titleBar',
- toggleButton: 'toggleButton',
- toolbar: 'toolbar',
- treeGrid: 'treeGrid',
- treeItem: 'treeItem',
- tree: 'tree',
- unknown: 'unknown',
- tooltip: 'tooltip',
- valueIndicator: 'valueIndicator',
- webArea: 'webArea',
- window: 'window'
-};
+chrome.commands.onCommand;
+
/**
- * Describes characteristics of an $(ref:automation.AutomationNode).
- * @enum {string}
+ * @param {function(Array<{description: string,
+ * name: string,
+ * shortcut: string}>): void} callback
*/
-chrome.automation.StateType = {
- busy: 'busy',
- checked: 'checked',
- collapsed: 'collapsed',
- default: 'default',
- disabled: 'disabled',
- editable: 'editable',
- enabled: 'enabled',
- expanded: 'expanded',
- focusable: 'focusable',
- focused: 'focused',
- haspopup: 'haspopup',
- hovered: 'hovered',
- indeterminate: 'indeterminate',
- invisible: 'invisible',
- linked: 'linked',
- multiselectable: 'multiselectable',
- offscreen: 'offscreen',
- pressed: 'pressed',
- protected: 'protected',
- readOnly: 'readOnly',
- required: 'required',
- selectable: 'selectable',
- selected: 'selected',
- vertical: 'vertical',
- visited: 'visited'
-};
-// End auto generated externs; do not edit.
+chrome.commands.getAll = function(callback) {};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
index c5f9aa6025d..db20382a06a 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
@@ -150,11 +150,11 @@ cvox.ChromeVox.verbosity = cvox.VERBOSITY_VERBOSE;
cvox.ChromeVox.typingEcho = 0;
/**
* Echoing on key press events.
- * @type {Object.<string, boolean>}
+ * @type {Object<string, boolean>}
*/
cvox.ChromeVox.keyEcho = {};
/**
- * @type {Object.<string, {x:number, y:number}>}
+ * @type {Object<string, {x:number, y:number}>}
*/
cvox.ChromeVox.position = {};
/**
@@ -181,10 +181,10 @@ if (cvox.ChromeVox.isChromeOS) {
* where the subsequent independent key downs (while modifier keys are down)
* are a part of the same shortcut. This array is populated in
* cvox.ChromeVoxKbHandler.loadKeyToFunctionsTable().
- * @type {!Array.<cvox.KeySequence>}
+ * @type {!Array<cvox.KeySequence>}
*/
cvox.ChromeVox.sequenceSwitchKeyCodes = [];
-/** @type {Object.<string, boolean>} */
+/** @type {Object<string, boolean>} */
cvox.ChromeVox.visitedUrls = {};
/**
* This function can be called before doing an operation that may trigger
@@ -275,3 +275,20 @@ function $(id) {
* @param {Array} tabs
*/
cvox.ChromeVox.injectChromeVoxIntoTabs = function(tabs) {};
+
+/**
+ * Returns whether the document has focus, taking into account whether
+ * it's hidden and also that if an iframe or webview element has focus,
+ * the focus is really inside that frame and not in this document.
+ * @return {boolean} True if the document has focus.
+ */
+cvox.ChromeVox.documentHasFocus = function() {
+ if (!document.hasFocus() || document.hidden) {
+ return false;
+ }
+ if (document.activeElement.tagName == 'IFRAME' ||
+ document.activeElement.tagName == 'WEBVIEW') {
+ return false;
+ }
+ return true;
+};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js
index ae18d75a726..96c78ca9f31 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js
@@ -15,9 +15,7 @@ goog.provide('cvox.ChromeVoxJSON');
*/
if (!cvox.ChromeVoxJSON) {
- /**
- * @type {Object}
- */
+ /** Placeholder object. */
cvox.ChromeVoxJSON = {};
}
@@ -227,7 +225,7 @@ if (window.JSON && window.JSON.toString() == '[object JSON]') {
if (typeof cvox.ChromeVoxJSON.stringify !== 'function') {
/**
* @param {*} value Input object.
- * @param {(Array.<string>|(function(string, *) : *)|null)=} replacer
+ * @param {(Array<string>|(function(string, *) : *)|null)=} replacer
* Replacer array or function.
* @param {(number|string|null)=} space Whitespace character.
* @return {string} json string which represents jsonObj.
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js
index a50e56547f9..3fdf69e409e 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js
@@ -38,7 +38,7 @@ goog.require('cvox.PlatformFilter');
/**
* Returns all of the categories in the store as an array.
- * @return {Array.<string>} The collection of categories.
+ * @return {Array<string>} The collection of categories.
*/
cvox.CommandStore.categories = function() {
var categorySet = {};
@@ -79,7 +79,7 @@ cvox.CommandStore.categoryForCommand = function(command) {
/**
* Gets all commands for a category.
* @param {string} category The category to query.
- * @return {Array.<string>} The commands, if any.
+ * @return {Array<string>} The commands, if any.
*/
cvox.CommandStore.commandsForCategory = function(category) {
var ret = [];
@@ -95,7 +95,7 @@ cvox.CommandStore.commandsForCategory = function(category) {
/**
* List of commands and their properties
- * @type {Object.<string, {forward: (undefined|boolean),
+ * @type {Object<string, {forward: (undefined|boolean),
* backward: (undefined|boolean),
* announce: boolean,
* category: (undefined|string),
@@ -678,7 +678,7 @@ cvox.CommandStore.CMD_WHITELIST = {
/**
* List of find next commands and their associated data.
- * @type {Object.<string, {predicate: string,
+ * @type {Object<string, {predicate: string,
* forwardError: string,
* backwardError: string}>}
* predicate: The name of the predicate. This must be defined in DomPredicates.
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js
index 1b1cfb0d628..bba28401525 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js
@@ -19,7 +19,7 @@ goog.require('cvox.TtsInterface');
*/
cvox.CompositeTts = function() {
/**
- * @type {Array.<cvox.TtsInterface>}
+ * @type {Array<cvox.TtsInterface>}
* @private
*/
this.ttsEngines_ = [];
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js
index e7f3c4a9cc8..ce0d9415f0d 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js
@@ -40,14 +40,14 @@ cvox.ContentEditableExtractor = function() {
/**
* Map from line index to a data structure containing the start
* and end index within the line.
- * @type {Object.<number, {startIndex: number, endIndex: number}>}
+ * @type {Object<number, {startIndex: number, endIndex: number}>}
* @private
*/
this.lines_ = {};
/**
* Map from 0-based character index to 0-based line index.
- * @type {Array.<number>}
+ * @type {Array<number>}
* @private
*/
this.characterToLineMap_ = [];
@@ -61,7 +61,7 @@ cvox.ContentEditableExtractor.prototype.update = function(element) {
/**
* Map from line index to a data structure containing the start
* and end index within the line.
- * @type {Object.<number, {startIndex: number, endIndex: number}>}
+ * @type {Object<number, {startIndex: number, endIndex: number}>}
*/
var lines = {0: {startIndex: 0, endIndex: 0}};
var startCursor = new cvox.Cursor(element, 0, '');
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js
index 67e161eeda6..0fb55784c3d 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js
@@ -23,7 +23,7 @@ goog.require('cvox.TraverseMath');
/**
* Lists all Node tagName's who's description is derived from its subtree.
- * @type {Object.<string, boolean>}
+ * @type {Object<string, boolean>}
*/
cvox.DescriptionUtil.COLLECTION_NODE_TYPE = {
'H1': true,
@@ -38,7 +38,7 @@ cvox.DescriptionUtil.COLLECTION_NODE_TYPE = {
* Get a control's complete description in the same format as if you
* navigated to the node.
* @param {Element} control A control.
- * @param {Array.<Node>=} opt_changedAncestors The changed ancestors that will
+ * @param {Array<Node>=} opt_changedAncestors The changed ancestors that will
* be used to determine what needs to be spoken. If this is not provided, the
* ancestors used to determine what needs to be spoken will just be the control
* itself and its surrounding control if it has one.
@@ -91,7 +91,7 @@ cvox.DescriptionUtil.getControlDescription =
* ancestor nodes. The ancestors are in order from the highest in the
* tree to the lowest, i.e. ending with the current leaf node.
*
- * @param {Array.<Node>} ancestorsArray An array of ancestor nodes.
+ * @param {Array<Node>} ancestorsArray An array of ancestor nodes.
* @param {boolean} recursive Whether or not the element's subtree should
* be used; true by default.
* @param {number} verbosity The verbosity setting.
@@ -182,7 +182,7 @@ cvox.DescriptionUtil.getDescriptionFromAncestors = function(
* @param {boolean} recursive Whether or not the element's subtree should
* be used; true by default.
* @param {number} verbosity The verbosity setting.
- * @return {!Array.<cvox.NavDescription>} The description of the navigation
+ * @return {!Array<cvox.NavDescription>} The description of the navigation
* action.
*/
cvox.DescriptionUtil.getDescriptionFromNavigation =
@@ -232,7 +232,7 @@ cvox.DescriptionUtil.getDescriptionFromNavigation =
* This is an awkward design, and should be changed in the future.
* @param {!cvox.CursorSelection} prevSel The previous selection.
* @param {!cvox.CursorSelection} sel The selection.
- * @return {!Array.<!cvox.NavDescription>} The descriptions as described above.
+ * @return {!Array<!cvox.NavDescription>} The descriptions as described above.
*/
cvox.DescriptionUtil.getCollectionDescription = function(prevSel, sel) {
var descriptions = cvox.DescriptionUtil.getRawDescriptions_(prevSel, sel);
@@ -253,7 +253,7 @@ cvox.DescriptionUtil.subWalker_ = new cvox.BareObjectWalker();
* Returns the descriptions that would be gotten by an object walker.
* @param {!cvox.CursorSelection} prevSel The previous selection.
* @param {!cvox.CursorSelection} sel The selection.
- * @return {!Array.<!cvox.NavDescription>} The descriptions.
+ * @return {!Array<!cvox.NavDescription>} The descriptions.
* @private
*/
cvox.DescriptionUtil.getRawDescriptions_ = function(prevSel, sel) {
@@ -303,7 +303,7 @@ cvox.DescriptionUtil.getRawDescriptions_ = function(prevSel, sel) {
* object walker.
* @param {?Element} prevnode The previous element if there is one.
* @param {!Element} node The target element.
- * @return {!Array.<!cvox.NavDescription>} The descriptions.
+ * @return {!Array<!cvox.NavDescription>} The descriptions.
*/
cvox.DescriptionUtil.getFullDescriptionsFromChildren =
function(prevnode, node) {
@@ -352,7 +352,7 @@ cvox.DescriptionUtil.getFullDescriptionsFromChildren =
/**
* Modify the descriptions to say that it is a collection.
- * @param {Array.<cvox.NavDescription>} descriptions The descriptions.
+ * @param {Array<cvox.NavDescription>} descriptions The descriptions.
* @private
*/
cvox.DescriptionUtil.insertCollectionDescription_ = function(descriptions) {
@@ -387,8 +387,8 @@ cvox.DescriptionUtil.insertCollectionDescription_ = function(descriptions) {
/**
* Pulls the annotations from a description array.
- * @param {Array.<cvox.NavDescription>} descriptions The descriptions.
- * @return {Array.<string>} The annotations.
+ * @param {Array<cvox.NavDescription>} descriptions The descriptions.
+ * @return {Array<string>} The annotations.
* @private
*/
cvox.DescriptionUtil.getAnnotations_ = function(descriptions) {
@@ -432,7 +432,7 @@ cvox.DescriptionUtil.isAnnotationCollection_ = function(annotation) {
/**
* Determines whether to describe the exit of an ancestor chain.
- * @param {Array.<Node>} ancestors The ancestors exited during navigation.
+ * @param {Array<Node>} ancestors The ancestors exited during navigation.
* @return {boolean} The result.
* @private
*/
@@ -452,7 +452,7 @@ cvox.DescriptionUtil.shouldDescribeExit_ = function(ancestors) {
/**
* Generates a description for a math node.
* @param {!Node} node The given node.
- * @return {!Array.<cvox.NavDescription>} A list of Navigation descriptions.
+ * @return {!Array<cvox.NavDescription>} A list of Navigation descriptions.
*/
cvox.DescriptionUtil.getMathDescription = function(node) {
// TODO (sorge) This function should evantually be removed. Descriptions
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js
index f47833243f0..685a8ecf8f4 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js
@@ -14,7 +14,7 @@ goog.provide('cvox.DomPredicates');
/**
* Checkbox.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a checkbox.
*/
cvox.DomPredicates.checkboxPredicate = function(nodes) {
@@ -31,7 +31,7 @@ cvox.DomPredicates.checkboxPredicate = function(nodes) {
/**
* Radio button.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a radio button.
*/
cvox.DomPredicates.radioPredicate = function(nodes) {
@@ -47,7 +47,7 @@ cvox.DomPredicates.radioPredicate = function(nodes) {
/**
* Slider.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a slider.
*/
cvox.DomPredicates.sliderPredicate = function(nodes) {
@@ -63,7 +63,7 @@ cvox.DomPredicates.sliderPredicate = function(nodes) {
/**
* Graphic.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a graphic.
*/
cvox.DomPredicates.graphicPredicate = function(nodes) {
@@ -79,7 +79,7 @@ cvox.DomPredicates.graphicPredicate = function(nodes) {
/**
* Button.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a button.
*/
cvox.DomPredicates.buttonPredicate = function(nodes) {
@@ -98,7 +98,7 @@ cvox.DomPredicates.buttonPredicate = function(nodes) {
/**
* Combo box.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a combo box.
*/
cvox.DomPredicates.comboBoxPredicate = function(nodes) {
@@ -115,7 +115,7 @@ cvox.DomPredicates.comboBoxPredicate = function(nodes) {
/**
* Editable text field.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is an editable text field.
*/
cvox.DomPredicates.editTextPredicate = function(nodes) {
@@ -134,7 +134,7 @@ cvox.DomPredicates.editTextPredicate = function(nodes) {
/**
* Heading.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading.
*/
cvox.DomPredicates.headingPredicate = function(nodes) {
@@ -159,7 +159,7 @@ cvox.DomPredicates.headingPredicate = function(nodes) {
/**
* Heading level 1.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading level 1.
* TODO: handle ARIA headings with ARIA heading levels?
*/
@@ -170,7 +170,7 @@ cvox.DomPredicates.heading1Predicate = function(nodes) {
/**
* Heading level 2.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading level 2.
*/
cvox.DomPredicates.heading2Predicate = function(nodes) {
@@ -180,7 +180,7 @@ cvox.DomPredicates.heading2Predicate = function(nodes) {
/**
* Heading level 3.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading level 3.
*/
cvox.DomPredicates.heading3Predicate = function(nodes) {
@@ -190,7 +190,7 @@ cvox.DomPredicates.heading3Predicate = function(nodes) {
/**
* Heading level 4.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading level 4.
*/
cvox.DomPredicates.heading4Predicate = function(nodes) {
@@ -200,7 +200,7 @@ cvox.DomPredicates.heading4Predicate = function(nodes) {
/**
* Heading level 5.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading level 5.
*/
cvox.DomPredicates.heading5Predicate = function(nodes) {
@@ -210,7 +210,7 @@ cvox.DomPredicates.heading5Predicate = function(nodes) {
/**
* Heading level 6.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a heading level 6.
*/
cvox.DomPredicates.heading6Predicate = function(nodes) {
@@ -220,7 +220,7 @@ cvox.DomPredicates.heading6Predicate = function(nodes) {
/**
* Link.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a link.
*/
cvox.DomPredicates.linkPredicate = function(nodes) {
@@ -236,7 +236,7 @@ cvox.DomPredicates.linkPredicate = function(nodes) {
/**
* Table.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a data table.
*/
cvox.DomPredicates.tablePredicate = function(nodes) {
@@ -251,7 +251,7 @@ cvox.DomPredicates.tablePredicate = function(nodes) {
/**
* Table Cell.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a table cell.
*/
cvox.DomPredicates.cellPredicate = function(nodes) {
@@ -269,7 +269,7 @@ cvox.DomPredicates.cellPredicate = function(nodes) {
/**
* Visited link.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a visited link.
*/
cvox.DomPredicates.visitedLinkPredicate = function(nodes) {
@@ -284,7 +284,7 @@ cvox.DomPredicates.visitedLinkPredicate = function(nodes) {
/**
* List.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a list.
*/
cvox.DomPredicates.listPredicate = function(nodes) {
@@ -301,7 +301,7 @@ cvox.DomPredicates.listPredicate = function(nodes) {
/**
* List item.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a list item.
*/
cvox.DomPredicates.listItemPredicate = function(nodes) {
@@ -318,7 +318,7 @@ cvox.DomPredicates.listItemPredicate = function(nodes) {
/**
* Blockquote.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a blockquote.
*/
cvox.DomPredicates.blockquotePredicate = function(nodes) {
@@ -328,7 +328,7 @@ cvox.DomPredicates.blockquotePredicate = function(nodes) {
/**
* Form field.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is any type of form field.
*/
cvox.DomPredicates.formFieldPredicate = function(nodes) {
@@ -343,7 +343,7 @@ cvox.DomPredicates.formFieldPredicate = function(nodes) {
/**
* ARIA landmark.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is an ARIA landmark.
*/
cvox.DomPredicates.landmarkPredicate = function(nodes) {
@@ -375,7 +375,7 @@ cvox.DomPredicates.containsTagName_ = function(arr, tagName) {
/**
* MathML expression
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a math expression.
*/
cvox.DomPredicates.mathPredicate = function(nodes) {
@@ -385,7 +385,7 @@ cvox.DomPredicates.mathPredicate = function(nodes) {
/**
* SECTION: A section is anything that indicates a new section. This includes
* headings and landmarks.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is considered a section marker.
*/
cvox.DomPredicates.sectionPredicate = function(nodes) {
@@ -416,7 +416,7 @@ cvox.DomPredicates.sectionPredicate = function(nodes) {
/**
* CONTROL: A control is anything that the user can interact with. This includes
* form fields and links.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is considered a control.
*/
cvox.DomPredicates.controlPredicate = function(nodes) {
@@ -434,7 +434,7 @@ cvox.DomPredicates.controlPredicate = function(nodes) {
/**
* Caption.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a caption.
*/
cvox.DomPredicates.captionPredicate = function(nodes) {
@@ -448,7 +448,7 @@ cvox.DomPredicates.captionPredicate = function(nodes) {
/**
* Article.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a article.
*/
cvox.DomPredicates.articlePredicate = function(nodes) {
@@ -464,7 +464,7 @@ cvox.DomPredicates.articlePredicate = function(nodes) {
/**
* Media.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a media widget (video or audio).
*/
cvox.DomPredicates.mediaPredicate = function(nodes) {
@@ -480,7 +480,7 @@ cvox.DomPredicates.mediaPredicate = function(nodes) {
/**
* Ordered List.
- * @param {Array.<Node>} nodes An array of nodes to check.
+ * @param {Array<Node>} nodes An array of nodes to check.
* @return {?Node} Node in the array that is a ordered list.
*/
cvox.DomPredicates.orderedListPredicate = function(nodes) {
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js
index 6f9ba4add25..f27290da55b 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js
@@ -108,7 +108,7 @@ cvox.DomUtil.TAG_TO_INFORMATION_TABLE_BRIEF_MSG = {
/**
* These tags are treated as text formatters.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
cvox.DomUtil.FORMATTING_TAGS =
['B', 'BIG', 'CITE', 'CODE', 'DFN', 'EM', 'I', 'KBD', 'SAMP', 'SMALL',
@@ -230,6 +230,9 @@ cvox.DomUtil.hasInvisibleAncestor_ = function(node) {
*/
cvox.DomUtil.hasVisibleNodeSubtree_ = function(root, recursive) {
if (!(root instanceof Element)) {
+ if (!root.parentElement) {
+ return false;
+ }
var parentStyle = document.defaultView
.getComputedStyle(root.parentElement, null);
var isVisibleParent = !cvox.DomUtil.isInvisibleStyle(parentStyle);
@@ -946,7 +949,7 @@ cvox.DomUtil.getImageTitle = function(node) {
* the complete set of ids they map to, so that we can skip elements that
* just label other elements and not double-speak them. We cache this
* result and then throw it away at the next event loop.
- * @return {Object.<string, boolean>} Set of all ids that are mapped
+ * @return {Object<string, boolean>} Set of all ids that are mapped
* by aria-labelledby.
*/
cvox.DomUtil.getLabelledByTargets = function() {
@@ -1179,7 +1182,7 @@ cvox.DomUtil.computeHasContent_ = function(node) {
* is the current node.
*
* @param {Node} targetNode The node to get ancestors for.
- * @return {Array.<Node>} An array of ancestors for the targetNode.
+ * @return {Array<Node>} An array of ancestors for the targetNode.
*/
cvox.DomUtil.getAncestors = function(targetNode) {
var ancestors = new Array();
@@ -1231,7 +1234,7 @@ cvox.DomUtil.compareAncestors = function(ancestorsA, ancestorsB) {
* @param {Node} currentNode The current node.
* @param {boolean=} opt_fallback True returns node's ancestors in the case
* where node's ancestors is a subset of previousNode's ancestors.
- * @return {Array.<Node>} An array of unique ancestors for the current node
+ * @return {Array<Node>} An array of unique ancestors for the current node
* (inclusive).
*/
cvox.DomUtil.getUniqueAncestors = function(
@@ -1262,6 +1265,10 @@ cvox.DomUtil.getRoleMsg = function(targetNode, verbosity) {
cvox.DomUtil.isInternalLink(targetNode)) {
info = 'internal_link';
} else if (targetNode.tagName == 'A' &&
+ targetNode.getAttribute('href') &&
+ cvox.ChromeVox.visitedUrls[targetNode.href]) {
+ info = 'visited_link';
+ } else if (targetNode.tagName == 'A' &&
targetNode.getAttribute('name')) {
info = ''; // Don't want to add any role to anchors.
} else if (targetNode.isContentEditable) {
@@ -1393,11 +1400,6 @@ cvox.DomUtil.getStateMsgs = function(targetNode, primary) {
info.push(['aria_disabled_true']);
}
- if (cvox.DomPredicates.linkPredicate([targetNode]) &&
- cvox.ChromeVox.visitedUrls[targetNode.href]) {
- info.push(['visited_url']);
- }
-
if (targetNode.accessKey) {
info.push(['access_key', targetNode.accessKey]);
}
@@ -1969,7 +1971,7 @@ cvox.DomUtil.getContainingTable = function(node, kwargs) {
/**
* Extracts a table node from a list of nodes.
- * @param {Array.<Node>} nodes The list of nodes.
+ * @param {Array<Node>} nodes The list of nodes.
* @param {{allowCaptions: (undefined|boolean)}=} kwargs Optional named args.
* allowCaptions: If true, will return true even if inside a caption. False
* by default.
@@ -2212,7 +2214,7 @@ cvox.DomUtil.countNodes = function(root, p) {
* using a depth first search.
* @param {Node} root The root of the tree to search.
* @param {function(Node) : boolean} p The filter function.
- * @param {Array.<Node>} rv The found nodes are added to this array.
+ * @param {Array<Node>} rv The found nodes are added to this array.
* @param {boolean} findOne If true we exit after the first found node.
* @param {number} maxChildCount The max child count. This is used as a kill
* switch - if there are more nodes than this, terminate the search.
@@ -2260,7 +2262,7 @@ cvox.DomUtil.toArray = function(nodeList) {
/**
* Creates a new element with the same attributes and no children.
* @param {Node|Text} node A node to clone.
- * @param {Object.<string, boolean>} skipattrs Set the attribute to true to
+ * @param {Object<string, boolean>} skipattrs Set the attribute to true to
* skip it during cloning.
* @return {Node|Text} The cloned node.
*/
@@ -2288,7 +2290,7 @@ cvox.DomUtil.shallowChildlessClone = function(node, skipattrs) {
/**
* Creates a new element with the same attributes and clones of children.
* @param {Node|Text} node A node to clone.
- * @param {Object.<string, boolean>} skipattrs Set the attribute to true to
+ * @param {Object<string, boolean>} skipattrs Set the attribute to true to
* skip it during cloning.
* @return {Node|Text} The cloned node.
*/
@@ -2377,7 +2379,7 @@ cvox.DomUtil.getContainingMath = function(node) {
/**
* Extracts a math node from a list of nodes.
- * @param {Array.<Node>} nodes The list of nodes.
+ * @param {Array<Node>} nodes The list of nodes.
* @return {Node} The math node if the list of nodes contains a math node.
* Null if it does not.
*/
@@ -2406,8 +2408,8 @@ cvox.DomUtil.isMath = function(node) {
/**
* Specifies node classes in which we expect maths expressions a alt text.
- * @type {{tex: Array.<string>,
- * asciimath: Array.<string>}}
+ * @type {{tex: Array<string>,
+ * asciimath: Array<string>}}
*/
// These are the classes for which we assume they contain Maths in the ALT or
// TITLE attribute.
@@ -2448,9 +2450,14 @@ cvox.DomUtil.isMathImg = function(node) {
if (node.tagName != 'IMG') {
return false;
}
- var className = node.className.toLowerCase();
- return cvox.DomUtil.ALT_MATH_CLASSES.tex.indexOf(className) != -1 ||
- cvox.DomUtil.ALT_MATH_CLASSES.asciimath.indexOf(className) != -1;
+ for (var i = 0, className; className = node.classList.item(i); i++) {
+ className = className.toLowerCase();
+ if (cvox.DomUtil.ALT_MATH_CLASSES.tex.indexOf(className) != -1 ||
+ cvox.DomUtil.ALT_MATH_CLASSES.asciimath.indexOf(className) != -1) {
+ return true;
+ }
+ }
+ return false;
};
@@ -2536,7 +2543,7 @@ cvox.DomUtil.getNodeTagName = function(node) {
/**
* Cleaning up a list of nodes to remove empty text nodes.
* @param {NodeList} nodes The nodes list.
- * @return {!Array.<Node|string|null>} The cleaned up list of nodes.
+ * @return {!Array<Node|string|null>} The cleaned up list of nodes.
*/
cvox.DomUtil.purgeNodes = function(nodes) {
return cvox.DomUtil.toArray(nodes).
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js
index 5968c61f33e..d336d37f1d5 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js
@@ -3,106 +3,34 @@
// found in the LICENSE file.
goog.provide('cvox.ChromeVoxEditableContentEditable');
+goog.provide('cvox.ChromeVoxEditableElement');
goog.provide('cvox.ChromeVoxEditableHTMLInput');
goog.provide('cvox.ChromeVoxEditableTextArea');
-goog.provide('cvox.ChromeVoxEditableTextBase');
-goog.provide('cvox.TextChangeEvent');
goog.provide('cvox.TextHandlerInterface');
-goog.provide('cvox.TypingEcho');
goog.require('cvox.BrailleTextHandler');
+goog.require('cvox.ChromeVoxEditableTextBase');
goog.require('cvox.ContentEditableExtractor');
goog.require('cvox.DomUtil');
goog.require('cvox.EditableTextAreaShadow');
+goog.require('cvox.TextChangeEvent');
goog.require('cvox.TtsInterface');
-goog.require('goog.i18n.MessageFormat');
/**
- * @fileoverview Gives the user spoken feedback as they type, select text,
- * and move the cursor in editable text controls, including multiline
- * controls.
+ * @fileoverview Gives the user spoken and braille feedback as they type,
+ * select text, and move the cursor in editable HTML text controls, including
+ * multiline controls and contenteditable regions.
*
- * The majority of the code is in ChromeVoxEditableTextBase, a generalized
- * class that takes the current state in the form of a text string, a
- * cursor start location and a cursor end location, and calls a speak
- * method with the resulting text to be spoken. If the control is multiline,
- * information about line breaks (including automatic ones) is also needed.
- *
- * Two subclasses, ChromeVoxEditableHTMLInput and
+ * The two subclasses, ChromeVoxEditableHTMLInput and
* ChromeVoxEditableTextArea, take a HTML input (type=text) or HTML
* textarea node (respectively) in the constructor, and automatically
* handle retrieving the current state of the control, including
* computing line break information for a textarea using an offscreen
- * shadow object. It is still the responsibility of the user of this
- * class to trap key and focus events and call this class's update
- * method.
- *
- */
-
-
-/**
- * A class containing the information needed to speak
- * a text change event to the user.
+ * shadow object. It is the responsibility of the user of these classes to
+ * trap key and focus events and call the update method as needed.
*
- * @constructor
- * @param {string} newValue The new string value of the editable text control.
- * @param {number} newStart The new 0-based start cursor/selection index.
- * @param {number} newEnd The new 0-based end cursor/selection index.
- * @param {boolean} triggeredByUser .
- */
-cvox.TextChangeEvent = function(newValue, newStart, newEnd, triggeredByUser) {
- this.value = newValue;
- this.start = newStart;
- this.end = newEnd;
- this.triggeredByUser = triggeredByUser;
-
- // Adjust offsets to be in left to right order.
- if (this.start > this.end) {
- var tempOffset = this.end;
- this.end = this.start;
- this.start = tempOffset;
- }
-};
-
-
-/**
- * A list of typing echo options.
- * This defines the way typed characters get spoken.
- * CHARACTER: echoes typed characters.
- * WORD: echoes a word once a breaking character is typed (i.e. spacebar).
- * CHARACTER_AND_WORD: combines CHARACTER and WORD behavior.
- * NONE: speaks nothing when typing.
- * COUNT: The number of possible echo levels.
- * @enum
- */
-cvox.TypingEcho = {
- CHARACTER: 0,
- WORD: 1,
- CHARACTER_AND_WORD: 2,
- NONE: 3,
- COUNT: 4
-};
-
-
-/**
- * @param {number} cur Current typing echo.
- * @return {number} Next typing echo.
- */
-cvox.TypingEcho.cycle = function(cur) {
- return (cur + 1) % cvox.TypingEcho.COUNT;
-};
-
-
-/**
- * Return if characters should be spoken given the typing echo option.
- * @param {number} typingEcho Typing echo option.
- * @return {boolean} Whether the character should be spoken.
*/
-cvox.TypingEcho.shouldSpeakChar = function(typingEcho) {
- return typingEcho == cvox.TypingEcho.CHARACTER_AND_WORD ||
- typingEcho == cvox.TypingEcho.CHARACTER;
-};
/**
@@ -120,659 +48,6 @@ cvox.TextHandlerInterface.prototype.changed = function(evt) {};
/**
- * A class representing an abstracted editable text control.
- * @param {string} value The string value of the editable text control.
- * @param {number} start The 0-based start cursor/selection index.
- * @param {number} end The 0-based end cursor/selection index.
- * @param {boolean} isPassword Whether the text control if a password field.
- * @param {cvox.TtsInterface} tts A TTS object.
- * @constructor
- */
-cvox.ChromeVoxEditableTextBase = function(value, start, end, isPassword, tts) {
- /**
- * Current value of the text field.
- * @type {string}
- * @protected
- */
- this.value = value;
-
- /**
- * 0-based selection start index.
- * @type {number}
- * @protected
- */
- this.start = start;
-
- /**
- * 0-based selection end index.
- * @type {number}
- * @protected
- */
- this.end = end;
-
- /**
- * True if this is a password field.
- * @type {boolean}
- * @protected
- */
- this.isPassword = isPassword;
-
- /**
- * Text-to-speech object implementing speak() and stop() methods.
- * @type {cvox.TtsInterface}
- * @protected
- */
- this.tts = tts;
-
- /**
- * Whether or not the text field is multiline.
- * @type {boolean}
- * @protected
- */
- this.multiline = false;
-
- /**
- * An optional handler for braille output.
- * @type {cvox.BrailleTextHandler|undefined}
- * @private
- */
- this.brailleHandler_ = cvox.ChromeVox.braille ?
- new cvox.BrailleTextHandler(cvox.ChromeVox.braille) : undefined;
-};
-
-
-/**
- * Performs setup for this element.
- */
-cvox.ChromeVoxEditableTextBase.prototype.setup = function() {};
-
-
-/**
- * Performs teardown for this element.
- */
-cvox.ChromeVoxEditableTextBase.prototype.teardown = function() {};
-
-
-/**
- * Whether or not moving the cursor from one character to another considers
- * the cursor to be a block (false) or an i-beam (true).
- *
- * If the cursor is a block, then the value of the character to the right
- * of the cursor index is always read when the cursor moves, no matter what
- * the previous cursor location was - this is how PC screenreaders work.
- *
- * If the cursor is an i-beam, moving the cursor by one character reads the
- * character that was crossed over, which may be the character to the left or
- * right of the new cursor index depending on the direction.
- *
- * If the current platform is a Mac, we will use an i-beam cursor. If not,
- * then we will use the block cursor.
- *
- * @type {boolean}
- */
-cvox.ChromeVoxEditableTextBase.useIBeamCursor = cvox.ChromeVox.isMac;
-
-
-/**
- * Switches on or off typing echo based on events. When set, editable text
- * updates for single-character insertions are handled in event watcher's key
- * press handler.
- * @type {boolean}
- */
-cvox.ChromeVoxEditableTextBase.eventTypingEcho = false;
-
-
-/**
- * The maximum number of characters that are short enough to speak in response
- * to an event. For example, if the user selects "Hello", we will speak
- * "Hello, selected", but if the user selects 1000 characters, we will speak
- * "text selected" instead.
- *
- * @type {number}
- */
-cvox.ChromeVoxEditableTextBase.prototype.maxShortPhraseLen = 60;
-
-
-/**
- * Whether or not the text control is a password.
- *
- * @type {boolean}
- */
-cvox.ChromeVoxEditableTextBase.prototype.isPassword = false;
-
-
-/**
- * Whether or not the last update to the text and selection was described.
- *
- * Some consumers of this flag like |ChromeVoxEventWatcher| depend on and
- * react to when this flag is false by generating alternative feedback.
- * @type {boolean}
- */
-cvox.ChromeVoxEditableTextBase.prototype.lastChangeDescribed = false;
-
-
-/**
- * Get the line number corresponding to a particular index.
- * Default implementation that can be overridden by subclasses.
- * @param {number} index The 0-based character index.
- * @return {number} The 0-based line number corresponding to that character.
- */
-cvox.ChromeVoxEditableTextBase.prototype.getLineIndex = function(index) {
- return 0;
-};
-
-
-/**
- * Get the start character index of a line.
- * Default implementation that can be overridden by subclasses.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the first character in this line.
- */
-cvox.ChromeVoxEditableTextBase.prototype.getLineStart = function(index) {
- return 0;
-};
-
-
-/**
- * Get the end character index of a line.
- * Default implementation that can be overridden by subclasses.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the end of this line.
- */
-cvox.ChromeVoxEditableTextBase.prototype.getLineEnd = function(index) {
- return this.value.length;
-};
-
-
-/**
- * Get the full text of the current line.
- * @param {number} index The 0-based line index.
- * @return {string} The text of the line.
- */
-cvox.ChromeVoxEditableTextBase.prototype.getLine = function(index) {
- var lineStart = this.getLineStart(index);
- var lineEnd = this.getLineEnd(index);
- return this.value.substr(lineStart, lineEnd - lineStart);
-};
-
-
-/**
- * @param {string} ch The character to test.
- * @return {boolean} True if a character is whitespace.
- */
-cvox.ChromeVoxEditableTextBase.prototype.isWhitespaceChar = function(ch) {
- return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
-};
-
-
-/**
- * @param {string} ch The character to test.
- * @return {boolean} True if a character breaks a word, used to determine
- * if the previous word should be spoken.
- */
-cvox.ChromeVoxEditableTextBase.prototype.isWordBreakChar = function(ch) {
- return !!ch.match(/^\W$/);
-};
-
-
-/**
- * @param {cvox.TextChangeEvent} evt The new text changed event to test.
- * @return {boolean} True if the event, when compared to the previous text,
- * should trigger description.
- */
-cvox.ChromeVoxEditableTextBase.prototype.shouldDescribeChange = function(evt) {
- if (evt.value == this.value &&
- evt.start == this.start &&
- evt.end == this.end) {
- return false;
- }
- return true;
-};
-
-
-/**
- * Speak text, but if it's a single character, describe the character.
- * @param {string} str The string to speak.
- * @param {boolean=} opt_triggeredByUser True if the speech was triggered by a
- * user action.
- * @param {Object=} opt_personality Personality used to speak text.
- */
-cvox.ChromeVoxEditableTextBase.prototype.speak =
- function(str, opt_triggeredByUser, opt_personality) {
- // If there is a node associated with the editable text object,
- // make sure that node has focus before speaking it.
- if (this.node && (document.activeElement != this.node)) {
- return;
- }
- var queueMode = cvox.QueueMode.QUEUE;
- if (opt_triggeredByUser === true) {
- queueMode = cvox.QueueMode.FLUSH;
- }
- this.tts.speak(str, queueMode, opt_personality || {});
-};
-
-
-/**
- * Update the state of the text and selection and describe any changes as
- * appropriate.
- *
- * @param {cvox.TextChangeEvent} evt The text change event.
- */
-cvox.ChromeVoxEditableTextBase.prototype.changed = function(evt) {
- if (!this.shouldDescribeChange(evt)) {
- this.lastChangeDescribed = false;
- return;
- }
-
- if (evt.value == this.value) {
- this.describeSelectionChanged(evt);
- } else {
- this.describeTextChanged(evt);
- }
- this.lastChangeDescribed = true;
-
- this.value = evt.value;
- this.start = evt.start;
- this.end = evt.end;
-
- if (this.brailleHandler_) {
- var line = this.getLine(this.getLineIndex(evt.start));
- var lineStart = this.getLineStart(this.getLineIndex(evt.start));
- var start = evt.start - lineStart;
- var end = Math.min(evt.end - lineStart, line.length);
- this.brailleHandler_.changed(line, start, end, this.multiline, this.node,
- lineStart);
- }
-};
-
-
-/**
- * Describe a change in the selection or cursor position when the text
- * stays the same.
- * @param {cvox.TextChangeEvent} evt The text change event.
- */
-cvox.ChromeVoxEditableTextBase.prototype.describeSelectionChanged =
- function(evt) {
- // TODO(deboer): Factor this into two function:
- // - one to determine the selection event
- // - one to speak
-
- if (this.isPassword) {
- this.speak((new goog.i18n.MessageFormat(cvox.ChromeVox.msgs.getMsg('dot'))
- .format({'COUNT': 1})), evt.triggeredByUser);
- return;
- }
- if (evt.start == evt.end) {
- // It's currently a cursor.
- if (this.start != this.end) {
- // It was previously a selection, so just announce 'unselected'.
- this.speak(cvox.ChromeVox.msgs.getMsg('Unselected'), evt.triggeredByUser);
- } else if (this.getLineIndex(this.start) !=
- this.getLineIndex(evt.start)) {
- // Moved to a different line; read it.
- var lineValue = this.getLine(this.getLineIndex(evt.start));
- if (lineValue == '') {
- lineValue = cvox.ChromeVox.msgs.getMsg('text_box_blank');
- } else if (/^\s+$/.test(lineValue)) {
- lineValue = cvox.ChromeVox.msgs.getMsg('text_box_whitespace');
- }
- this.speak(lineValue, evt.triggeredByUser);
- } else if (this.start == evt.start + 1 ||
- this.start == evt.start - 1) {
- // Moved by one character; read it.
- if (!cvox.ChromeVoxEditableTextBase.useIBeamCursor) {
- if (evt.start == this.value.length) {
- if (cvox.ChromeVox.verbosity == cvox.VERBOSITY_VERBOSE) {
- this.speak(cvox.ChromeVox.msgs.getMsg('end_of_text_verbose'),
- evt.triggeredByUser);
- } else {
- this.speak(cvox.ChromeVox.msgs.getMsg('end_of_text_brief'),
- evt.triggeredByUser);
- }
- } else {
- this.speak(this.value.substr(evt.start, 1),
- evt.triggeredByUser,
- {'phoneticCharacters': evt.triggeredByUser});
- }
- } else {
- this.speak(this.value.substr(Math.min(this.start, evt.start), 1),
- evt.triggeredByUser,
- {'phoneticCharacters': evt.triggeredByUser});
- }
- } else {
- // Moved by more than one character. Read all characters crossed.
- this.speak(this.value.substr(Math.min(this.start, evt.start),
- Math.abs(this.start - evt.start)), evt.triggeredByUser);
- }
- } else {
- // It's currently a selection.
- if (this.start + 1 == evt.start &&
- this.end == this.value.length &&
- evt.end == this.value.length) {
- // Autocomplete: the user typed one character of autocompleted text.
- this.speak(this.value.substr(this.start, 1), evt.triggeredByUser);
- this.speak(this.value.substr(evt.start));
- } else if (this.start == this.end) {
- // It was previously a cursor.
- this.speak(this.value.substr(evt.start, evt.end - evt.start),
- evt.triggeredByUser);
- this.speak(cvox.ChromeVox.msgs.getMsg('selected'));
- } else if (this.start == evt.start && this.end < evt.end) {
- this.speak(this.value.substr(this.end, evt.end - this.end),
- evt.triggeredByUser);
- this.speak(cvox.ChromeVox.msgs.getMsg('added_to_selection'));
- } else if (this.start == evt.start && this.end > evt.end) {
- this.speak(this.value.substr(evt.end, this.end - evt.end),
- evt.triggeredByUser);
- this.speak(cvox.ChromeVox.msgs.getMsg('removed_from_selection'));
- } else if (this.end == evt.end && this.start > evt.start) {
- this.speak(this.value.substr(evt.start, this.start - evt.start),
- evt.triggeredByUser);
- this.speak(cvox.ChromeVox.msgs.getMsg('added_to_selection'));
- } else if (this.end == evt.end && this.start < evt.start) {
- this.speak(this.value.substr(this.start, evt.start - this.start),
- evt.triggeredByUser);
- this.speak(cvox.ChromeVox.msgs.getMsg('removed_from_selection'));
- } else {
- // The selection changed but it wasn't an obvious extension of
- // a previous selection. Just read the new selection.
- this.speak(this.value.substr(evt.start, evt.end - evt.start),
- evt.triggeredByUser);
- this.speak(cvox.ChromeVox.msgs.getMsg('selected'));
- }
- }
-};
-
-
-/**
- * Describe a change where the text changes.
- * @param {cvox.TextChangeEvent} evt The text change event.
- */
-cvox.ChromeVoxEditableTextBase.prototype.describeTextChanged = function(evt) {
- var personality = {};
- if (evt.value.length < this.value.length) {
- personality = cvox.AbstractTts.PERSONALITY_DELETED;
- }
- if (this.isPassword) {
- this.speak((new goog.i18n.MessageFormat(cvox.ChromeVox.msgs.getMsg('dot'))
- .format({'COUNT': 1})), evt.triggeredByUser, personality);
- return;
- }
-
- var value = this.value;
- var len = value.length;
- var newLen = evt.value.length;
- var autocompleteSuffix = '';
- // Make a copy of evtValue and evtEnd to avoid changing anything in
- // the event itself.
- var evtValue = evt.value;
- var evtEnd = evt.end;
-
- // First, see if there's a selection at the end that might have been
- // added by autocomplete. If so, strip it off into a separate variable.
- if (evt.start < evtEnd && evtEnd == newLen) {
- autocompleteSuffix = evtValue.substr(evt.start);
- evtValue = evtValue.substr(0, evt.start);
- evtEnd = evt.start;
- }
-
- // Now see if the previous selection (if any) was deleted
- // and any new text was inserted at that character position.
- // This would handle pasting and entering text by typing, both from
- // a cursor and from a selection.
- var prefixLen = this.start;
- var suffixLen = len - this.end;
- if (newLen >= prefixLen + suffixLen + (evtEnd - evt.start) &&
- evtValue.substr(0, prefixLen) == value.substr(0, prefixLen) &&
- evtValue.substr(newLen - suffixLen) == value.substr(this.end)) {
- // However, in a dynamic content editable, defer to authoritative events
- // (clipboard, key press) to reduce guess work when observing insertions.
- // Only use this logic when observing deletions (and insertion of word
- // breakers).
- // TODO(dtseng): Think about a more reliable way to do this.
- if (!(this instanceof cvox.ChromeVoxEditableContentEditable) ||
- newLen < len ||
- this.isWordBreakChar(evt.value[newLen - 1] || '')) {
- this.describeTextChangedHelper(
- evt, prefixLen, suffixLen, autocompleteSuffix, personality);
- }
- return;
- }
-
- // Next, see if one or more characters were deleted from the previous
- // cursor position and the new cursor is in the expected place. This
- // handles backspace, forward-delete, and similar shortcuts that delete
- // a word or line.
- prefixLen = evt.start;
- suffixLen = newLen - evtEnd;
- if (this.start == this.end &&
- evt.start == evtEnd &&
- evtValue.substr(0, prefixLen) == value.substr(0, prefixLen) &&
- evtValue.substr(newLen - suffixLen) ==
- value.substr(len - suffixLen)) {
- this.describeTextChangedHelper(
- evt, prefixLen, suffixLen, autocompleteSuffix, personality);
- return;
- }
-
- // If all else fails, we assume the change was not the result of a normal
- // user editing operation, so we'll have to speak feedback based only
- // on the changes to the text, not the cursor position / selection.
- // First, restore the autocomplete text if any.
- evtValue += autocompleteSuffix;
-
- // Try to do a diff between the new and the old text. If it is a one character
- // insertion/deletion at the start or at the end, just speak that character.
- if ((evtValue.length == (value.length + 1)) ||
- ((evtValue.length + 1) == value.length)) {
- // The user added text either to the beginning or the end.
- if (evtValue.length > value.length) {
- if (evtValue.indexOf(value) == 0) {
- this.speak(evtValue[evtValue.length - 1], evt.triggeredByUser,
- personality);
- return;
- } else if (evtValue.indexOf(value) == 1) {
- this.speak(evtValue[0], evt.triggeredByUser, personality);
- return;
- }
- }
- // The user deleted text either from the beginning or the end.
- if (evtValue.length < value.length) {
- if (value.indexOf(evtValue) == 0) {
- this.speak(value[value.length - 1], evt.triggeredByUser, personality);
- return;
- } else if (value.indexOf(evtValue) == 1) {
- this.speak(value[0], evt.triggeredByUser, personality);
- return;
- }
- }
- }
-
- if (this.multiline) {
- // Fall back to announce deleted but omit the text that was deleted.
- if (evt.value.length < this.value.length) {
- this.speak(cvox.ChromeVox.msgs.getMsg('text_deleted'),
- evt.triggeredByUser, personality);
- }
- // The below is a somewhat loose way to deal with non-standard
- // insertions/deletions. Intentionally skip for multiline since deletion
- // announcements are covered above and insertions are non-standard (possibly
- // due to auto complete). Since content editable's often refresh content by
- // removing and inserting entire chunks of text, this type of logic often
- // results in unintended consequences such as reading all text when only one
- // character has been entered.
- return;
- }
-
- // If the text is short, just speak the whole thing.
- if (newLen <= this.maxShortPhraseLen) {
- this.describeTextChangedHelper(evt, 0, 0, '', personality);
- return;
- }
-
- // Otherwise, look for the common prefix and suffix, but back up so
- // that we can speak complete words, to be minimally confusing.
- prefixLen = 0;
- while (prefixLen < len &&
- prefixLen < newLen &&
- value[prefixLen] == evtValue[prefixLen]) {
- prefixLen++;
- }
- while (prefixLen > 0 && !this.isWordBreakChar(value[prefixLen - 1])) {
- prefixLen--;
- }
-
- suffixLen = 0;
- while (suffixLen < (len - prefixLen) &&
- suffixLen < (newLen - prefixLen) &&
- value[len - suffixLen - 1] == evtValue[newLen - suffixLen - 1]) {
- suffixLen++;
- }
- while (suffixLen > 0 && !this.isWordBreakChar(value[len - suffixLen])) {
- suffixLen--;
- }
-
- this.describeTextChangedHelper(evt, prefixLen, suffixLen, '', personality);
-};
-
-
-/**
- * The function called by describeTextChanged after it's figured out
- * what text was deleted, what text was inserted, and what additional
- * autocomplete text was added.
- * @param {cvox.TextChangeEvent} evt The text change event.
- * @param {number} prefixLen The number of characters in the common prefix
- * of this.value and newValue.
- * @param {number} suffixLen The number of characters in the common suffix
- * of this.value and newValue.
- * @param {string} autocompleteSuffix The autocomplete string that was added
- * to the end, if any. It should be spoken at the end of the utterance
- * describing the change.
- * @param {Object=} opt_personality Personality to speak the text.
- */
-cvox.ChromeVoxEditableTextBase.prototype.describeTextChangedHelper = function(
- evt, prefixLen, suffixLen, autocompleteSuffix, opt_personality) {
- var len = this.value.length;
- var newLen = evt.value.length;
- var deletedLen = len - prefixLen - suffixLen;
- var deleted = this.value.substr(prefixLen, deletedLen);
- var insertedLen = newLen - prefixLen - suffixLen;
- var inserted = evt.value.substr(prefixLen, insertedLen);
- var utterance = '';
- var triggeredByUser = evt.triggeredByUser;
-
- if (insertedLen > 1) {
- utterance = inserted;
- } else if (insertedLen == 1) {
- if ((cvox.ChromeVox.typingEcho == cvox.TypingEcho.WORD ||
- cvox.ChromeVox.typingEcho == cvox.TypingEcho.CHARACTER_AND_WORD) &&
- this.isWordBreakChar(inserted) &&
- prefixLen > 0 &&
- !this.isWordBreakChar(evt.value.substr(prefixLen - 1, 1))) {
- // Speak previous word.
- var index = prefixLen;
- while (index > 0 && !this.isWordBreakChar(evt.value[index - 1])) {
- index--;
- }
- if (index < prefixLen) {
- utterance = evt.value.substr(index, prefixLen + 1 - index);
- } else {
- utterance = inserted;
- triggeredByUser = false; // Implies QUEUE_MODE_QUEUE.
- }
- } else if (cvox.ChromeVox.typingEcho == cvox.TypingEcho.CHARACTER ||
- cvox.ChromeVox.typingEcho == cvox.TypingEcho.CHARACTER_AND_WORD) {
- // This particular case is handled in event watcher. See the key press
- // handler for more details.
- utterance = cvox.ChromeVoxEditableTextBase.eventTypingEcho ? '' :
- inserted;
- }
- } else if (deletedLen > 1 && !autocompleteSuffix) {
- utterance = deleted + ', deleted';
- } else if (deletedLen == 1) {
- utterance = deleted;
- }
-
- if (autocompleteSuffix && utterance) {
- utterance += ', ' + autocompleteSuffix;
- } else if (autocompleteSuffix) {
- utterance = autocompleteSuffix;
- }
-
- if (utterance) {
- this.speak(utterance, triggeredByUser, opt_personality);
- }
-};
-
-
-/**
- * Moves the cursor forward by one character.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextCharacter =
- function() { return false; };
-
-
-/**
- * Moves the cursor backward by one character.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousCharacter =
- function() { return false; };
-
-
-/**
- * Moves the cursor forward by one word.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextWord =
- function() { return false; };
-
-
-/**
- * Moves the cursor backward by one word.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousWord =
- function() { return false; };
-
-
-/**
- * Moves the cursor forward by one line.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextLine =
- function() { return false; };
-
-
-/**
- * Moves the cursor backward by one line.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousLine =
- function() { return false; };
-
-
-/**
- * Moves the cursor forward by one paragraph.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextParagraph =
- function() { return false; };
-
-
-/**
- * Moves the cursor backward by one paragraph.
- * @return {boolean} True if the action was handled.
- */
-cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousParagraph =
- function() { return false; };
-
-
-/******************************************/
-
-
-/**
* A subclass of ChromeVoxEditableTextBase a text element that's part of
* the webpage DOM. Contains common code shared by both EditableHTMLInput
* and EditableTextArea, but that might not apply to a non-DOM text box.
@@ -790,6 +65,14 @@ cvox.ChromeVoxEditableElement = function(node, value, start, end, isPassword,
goog.base(this, value, start, end, isPassword, tts);
/**
+ * An optional handler for braille output.
+ * @type {cvox.BrailleTextHandler|undefined}
+ * @private
+ */
+ this.brailleHandler_ = cvox.ChromeVox.braille ?
+ new cvox.BrailleTextHandler(cvox.ChromeVox.braille) : undefined;
+
+ /**
* The DOM node which allows text input.
* @type {Element}
* @protected
@@ -807,12 +90,7 @@ goog.inherits(cvox.ChromeVoxEditableElement,
cvox.ChromeVoxEditableTextBase);
-/**
- * Update the state of the text and selection and describe any changes as
- * appropriate.
- *
- * @param {cvox.TextChangeEvent} evt The text change event.
- */
+/** @override */
cvox.ChromeVoxEditableElement.prototype.changed = function(evt) {
// Ignore changes to the cursor and selection if they happen immediately
// after the description was just spoken. This avoid double-speaking when,
@@ -826,10 +104,24 @@ cvox.ChromeVoxEditableElement.prototype.changed = function(evt) {
this.justSpokeDescription_ = false;
}
goog.base(this, 'changed', evt);
+ if (this.lastChangeDescribed) {
+ this.brailleCurrentLine_();
+ }
};
/** @override */
+cvox.ChromeVoxEditableElement.prototype.speak = function(
+ str, opt_triggeredByUser, opt_personality) {
+ // If there is a node associated with the editable text object,
+ // make sure that node has focus before speaking it.
+ if (this.node && (document.activeElement != this.node)) {
+ return;
+ }
+ goog.base(this, 'speak', str, opt_triggeredByUser, opt_personality);
+};
+
+/** @override */
cvox.ChromeVoxEditableElement.prototype.moveCursorToNextCharacter = function() {
var node = this.node;
node.selectionEnd++;
@@ -916,6 +208,29 @@ cvox.ChromeVoxEditableElement.prototype.moveCursorToPreviousParagraph =
return true;
};
+/**
+ * Shows the current line on the braille display.
+ * @private
+ */
+cvox.ChromeVoxEditableElement.prototype.brailleCurrentLine_ = function() {
+ if (this.brailleHandler_) {
+ var lineIndex = this.getLineIndex(this.start);
+ var line = this.getLine(lineIndex);
+ // Collapsable whitespace inside the contenteditable is represented
+ // as non-breaking spaces. This confuses braille input (which relies on
+ // the text being added to be the same as the text in the input field).
+ // Since the non-breaking spaces are just an artifact of how
+ // contenteditable is implemented, normalize to normal spaces instead.
+ if (this instanceof cvox.ChromeVoxEditableContentEditable) {
+ line = line.replace(/\u00A0/g, ' ');
+ }
+ var lineStart = this.getLineStart(lineIndex);
+ var start = this.start - lineStart;
+ var end = Math.min(this.end - lineStart, line.length);
+ this.brailleHandler_.changed(line, start, end, this.multiline, this.node,
+ lineStart);
+ }
+};
/******************************************/
@@ -1237,9 +552,7 @@ cvox.ChromeVoxEditableContentEditable.prototype.getExtractor = function() {
};
-/**
- * @override
- */
+/** @override */
cvox.ChromeVoxEditableContentEditable.prototype.changed =
function(evt) {
if (!evt.triggeredByUser) {
@@ -1248,6 +561,11 @@ cvox.ChromeVoxEditableContentEditable.prototype.changed =
// Take over here if we can't describe a change; assume it's a blank line.
if (!this.shouldDescribeChange(evt)) {
this.speak(cvox.ChromeVox.msgs.getMsg('text_box_blank'), true);
+ if (this.brailleHandler_) {
+ this.brailleHandler_.changed('' /*line*/, 0 /*start*/, 0 /*end*/,
+ true /*multiline*/, null /*element*/,
+ evt.start /*lineStart*/);
+ }
} else {
goog.base(this, 'changed', evt);
}
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js
index 58940f2626a..bd381156c69 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js
@@ -23,14 +23,14 @@ cvox.EditableTextAreaShadow = function() {
/**
* Map from line index to a data structure containing the start
* and end index within the line.
- * @type {Object.<number, {startIndex: number, endIndex: number}>}
+ * @type {Object<number, {startIndex: number, endIndex: number}>}
* @private
*/
this.lines_ = {};
/**
* Map from 0-based character index to 0-based line index.
- * @type {Array.<number>}
+ * @type {Array<number>}
* @private
*/
this.characterToLineMap_ = [];
@@ -72,7 +72,7 @@ cvox.EditableTextAreaShadow.prototype.update = function(element) {
/**
* Map from line index to a data structure containing the start
* and end index within the line.
- * @type {Object.<number, {startIndex: number, endIndex: number}>}
+ * @type {Object<number, {startIndex: number, endIndex: number}>}
*/
var lines = {0: {startIndex: 0, endIndex: 0}};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js
new file mode 100644
index 00000000000..573123915ba
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js
@@ -0,0 +1,712 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+goog.provide('cvox.ChromeVoxEditableTextBase');
+goog.provide('cvox.TextChangeEvent');
+goog.provide('cvox.TypingEcho');
+
+goog.require('cvox.AbstractTts');
+goog.require('cvox.ChromeVox');
+goog.require('cvox.TtsInterface');
+goog.require('goog.i18n.MessageFormat');
+
+
+/**
+ * @fileoverview Generalized logic for providing spoken feedback when editing
+ * text fields, both single and multiline fields.
+ *
+ * {@code ChromeVoxEditableTextBase} is a generalized class that takes the
+ * current state in the form of a text string, a cursor start location and a
+ * cursor end location, and calls a speak method with the resulting text to
+ * be spoken. This class can be used directly for single line fields or
+ * extended to override methods that extract lines for multiline fields
+ * or to provide other customizations.
+ */
+
+
+/**
+ * A class containing the information needed to speak
+ * a text change event to the user.
+ *
+ * @constructor
+ * @param {string} newValue The new string value of the editable text control.
+ * @param {number} newStart The new 0-based start cursor/selection index.
+ * @param {number} newEnd The new 0-based end cursor/selection index.
+ * @param {boolean} triggeredByUser .
+ */
+cvox.TextChangeEvent = function(newValue, newStart, newEnd, triggeredByUser) {
+ this.value = newValue;
+ this.start = newStart;
+ this.end = newEnd;
+ this.triggeredByUser = triggeredByUser;
+
+ // Adjust offsets to be in left to right order.
+ if (this.start > this.end) {
+ var tempOffset = this.end;
+ this.end = this.start;
+ this.start = tempOffset;
+ }
+};
+
+
+/**
+ * A list of typing echo options.
+ * This defines the way typed characters get spoken.
+ * CHARACTER: echoes typed characters.
+ * WORD: echoes a word once a breaking character is typed (i.e. spacebar).
+ * CHARACTER_AND_WORD: combines CHARACTER and WORD behavior.
+ * NONE: speaks nothing when typing.
+ * COUNT: The number of possible echo levels.
+ * @enum
+ */
+cvox.TypingEcho = {
+ CHARACTER: 0,
+ WORD: 1,
+ CHARACTER_AND_WORD: 2,
+ NONE: 3,
+ COUNT: 4
+};
+
+
+/**
+ * @param {number} cur Current typing echo.
+ * @return {number} Next typing echo.
+ */
+cvox.TypingEcho.cycle = function(cur) {
+ return (cur + 1) % cvox.TypingEcho.COUNT;
+};
+
+
+/**
+ * Return if characters should be spoken given the typing echo option.
+ * @param {number} typingEcho Typing echo option.
+ * @return {boolean} Whether the character should be spoken.
+ */
+cvox.TypingEcho.shouldSpeakChar = function(typingEcho) {
+ return typingEcho == cvox.TypingEcho.CHARACTER_AND_WORD ||
+ typingEcho == cvox.TypingEcho.CHARACTER;
+};
+
+
+/**
+ * A class representing an abstracted editable text control.
+ * @param {string} value The string value of the editable text control.
+ * @param {number} start The 0-based start cursor/selection index.
+ * @param {number} end The 0-based end cursor/selection index.
+ * @param {boolean} isPassword Whether the text control if a password field.
+ * @param {cvox.TtsInterface} tts A TTS object.
+ * @constructor
+ */
+cvox.ChromeVoxEditableTextBase = function(value, start, end, isPassword, tts) {
+ /**
+ * Current value of the text field.
+ * @type {string}
+ * @protected
+ */
+ this.value = value;
+
+ /**
+ * 0-based selection start index.
+ * @type {number}
+ * @protected
+ */
+ this.start = start;
+
+ /**
+ * 0-based selection end index.
+ * @type {number}
+ * @protected
+ */
+ this.end = end;
+
+ /**
+ * True if this is a password field.
+ * @type {boolean}
+ * @protected
+ */
+ this.isPassword = isPassword;
+
+ /**
+ * Text-to-speech object implementing speak() and stop() methods.
+ * @type {cvox.TtsInterface}
+ * @protected
+ */
+ this.tts = tts;
+
+ /**
+ * Whether or not the text field is multiline.
+ * @type {boolean}
+ * @protected
+ */
+ this.multiline = false;
+
+ /**
+ * Whether or not the last update to the text and selection was described.
+ *
+ * Some consumers of this flag like |ChromeVoxEventWatcher| depend on and
+ * react to when this flag is false by generating alternative feedback.
+ * @type {boolean}
+ */
+ this.lastChangeDescribed = false;
+
+};
+
+
+/**
+ * Performs setup for this element.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.setup = function() {};
+
+
+/**
+ * Performs teardown for this element.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.teardown = function() {};
+
+
+/**
+ * Whether or not moving the cursor from one character to another considers
+ * the cursor to be a block (false) or an i-beam (true).
+ *
+ * If the cursor is a block, then the value of the character to the right
+ * of the cursor index is always read when the cursor moves, no matter what
+ * the previous cursor location was - this is how PC screenreaders work.
+ *
+ * If the cursor is an i-beam, moving the cursor by one character reads the
+ * character that was crossed over, which may be the character to the left or
+ * right of the new cursor index depending on the direction.
+ *
+ * If the current platform is a Mac, we will use an i-beam cursor. If not,
+ * then we will use the block cursor.
+ *
+ * @type {boolean}
+ */
+cvox.ChromeVoxEditableTextBase.useIBeamCursor = cvox.ChromeVox.isMac;
+
+
+/**
+ * Switches on or off typing echo based on events. When set, editable text
+ * updates for single-character insertions are handled in event watcher's key
+ * press handler.
+ * @type {boolean}
+ */
+cvox.ChromeVoxEditableTextBase.eventTypingEcho = false;
+
+
+/**
+ * The maximum number of characters that are short enough to speak in response
+ * to an event. For example, if the user selects "Hello", we will speak
+ * "Hello, selected", but if the user selects 1000 characters, we will speak
+ * "text selected" instead.
+ *
+ * @type {number}
+ */
+cvox.ChromeVoxEditableTextBase.prototype.maxShortPhraseLen = 60;
+
+
+/**
+ * Get the line number corresponding to a particular index.
+ * Default implementation that can be overridden by subclasses.
+ * @param {number} index The 0-based character index.
+ * @return {number} The 0-based line number corresponding to that character.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.getLineIndex = function(index) {
+ return 0;
+};
+
+
+/**
+ * Get the start character index of a line.
+ * Default implementation that can be overridden by subclasses.
+ * @param {number} index The 0-based line index.
+ * @return {number} The 0-based index of the first character in this line.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.getLineStart = function(index) {
+ return 0;
+};
+
+
+/**
+ * Get the end character index of a line.
+ * Default implementation that can be overridden by subclasses.
+ * @param {number} index The 0-based line index.
+ * @return {number} The 0-based index of the end of this line.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.getLineEnd = function(index) {
+ return this.value.length;
+};
+
+
+/**
+ * Get the full text of the current line.
+ * @param {number} index The 0-based line index.
+ * @return {string} The text of the line.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.getLine = function(index) {
+ var lineStart = this.getLineStart(index);
+ var lineEnd = this.getLineEnd(index);
+ return this.value.substr(lineStart, lineEnd - lineStart);
+};
+
+
+/**
+ * @param {string} ch The character to test.
+ * @return {boolean} True if a character is whitespace.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.isWhitespaceChar = function(ch) {
+ return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
+};
+
+
+/**
+ * @param {string} ch The character to test.
+ * @return {boolean} True if a character breaks a word, used to determine
+ * if the previous word should be spoken.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.isWordBreakChar = function(ch) {
+ return !!ch.match(/^\W$/);
+};
+
+
+/**
+ * @param {cvox.TextChangeEvent} evt The new text changed event to test.
+ * @return {boolean} True if the event, when compared to the previous text,
+ * should trigger description.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.shouldDescribeChange = function(evt) {
+ if (evt.value == this.value &&
+ evt.start == this.start &&
+ evt.end == this.end) {
+ return false;
+ }
+ return true;
+};
+
+
+/**
+ * Speak text, but if it's a single character, describe the character.
+ * @param {string} str The string to speak.
+ * @param {boolean=} opt_triggeredByUser True if the speech was triggered by a
+ * user action.
+ * @param {Object=} opt_personality Personality used to speak text.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.speak =
+ function(str, opt_triggeredByUser, opt_personality) {
+ var queueMode = cvox.QueueMode.QUEUE;
+ if (opt_triggeredByUser === true) {
+ queueMode = cvox.QueueMode.FLUSH;
+ }
+ this.tts.speak(str, queueMode, opt_personality || {});
+};
+
+
+/**
+ * Update the state of the text and selection and describe any changes as
+ * appropriate.
+ *
+ * @param {cvox.TextChangeEvent} evt The text change event.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.changed = function(evt) {
+ if (!this.shouldDescribeChange(evt)) {
+ this.lastChangeDescribed = false;
+ return;
+ }
+
+ if (evt.value == this.value) {
+ this.describeSelectionChanged(evt);
+ } else {
+ this.describeTextChanged(evt);
+ }
+ this.lastChangeDescribed = true;
+
+ this.value = evt.value;
+ this.start = evt.start;
+ this.end = evt.end;
+};
+
+
+/**
+ * Describe a change in the selection or cursor position when the text
+ * stays the same.
+ * @param {cvox.TextChangeEvent} evt The text change event.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.describeSelectionChanged =
+ function(evt) {
+ // TODO(deboer): Factor this into two function:
+ // - one to determine the selection event
+ // - one to speak
+
+ if (this.isPassword) {
+ this.speak((new goog.i18n.MessageFormat(cvox.ChromeVox.msgs.getMsg('dot'))
+ .format({'COUNT': 1})), evt.triggeredByUser);
+ return;
+ }
+ if (evt.start == evt.end) {
+ // It's currently a cursor.
+ if (this.start != this.end) {
+ // It was previously a selection, so just announce 'unselected'.
+ this.speak(cvox.ChromeVox.msgs.getMsg('Unselected'), evt.triggeredByUser);
+ } else if (this.getLineIndex(this.start) !=
+ this.getLineIndex(evt.start)) {
+ // Moved to a different line; read it.
+ var lineValue = this.getLine(this.getLineIndex(evt.start));
+ if (lineValue == '') {
+ lineValue = cvox.ChromeVox.msgs.getMsg('text_box_blank');
+ } else if (/^\s+$/.test(lineValue)) {
+ lineValue = cvox.ChromeVox.msgs.getMsg('text_box_whitespace');
+ }
+ this.speak(lineValue, evt.triggeredByUser);
+ } else if (this.start == evt.start + 1 ||
+ this.start == evt.start - 1) {
+ // Moved by one character; read it.
+ if (!cvox.ChromeVoxEditableTextBase.useIBeamCursor) {
+ if (evt.start == this.value.length) {
+ if (cvox.ChromeVox.verbosity == cvox.VERBOSITY_VERBOSE) {
+ this.speak(cvox.ChromeVox.msgs.getMsg('end_of_text_verbose'),
+ evt.triggeredByUser);
+ } else {
+ this.speak(cvox.ChromeVox.msgs.getMsg('end_of_text_brief'),
+ evt.triggeredByUser);
+ }
+ } else {
+ this.speak(this.value.substr(evt.start, 1),
+ evt.triggeredByUser,
+ {'phoneticCharacters': evt.triggeredByUser});
+ }
+ } else {
+ this.speak(this.value.substr(Math.min(this.start, evt.start), 1),
+ evt.triggeredByUser,
+ {'phoneticCharacters': evt.triggeredByUser});
+ }
+ } else {
+ // Moved by more than one character. Read all characters crossed.
+ this.speak(this.value.substr(Math.min(this.start, evt.start),
+ Math.abs(this.start - evt.start)), evt.triggeredByUser);
+ }
+ } else {
+ // It's currently a selection.
+ if (this.start + 1 == evt.start &&
+ this.end == this.value.length &&
+ evt.end == this.value.length) {
+ // Autocomplete: the user typed one character of autocompleted text.
+ this.speak(this.value.substr(this.start, 1), evt.triggeredByUser);
+ this.speak(this.value.substr(evt.start));
+ } else if (this.start == this.end) {
+ // It was previously a cursor.
+ this.speak(this.value.substr(evt.start, evt.end - evt.start),
+ evt.triggeredByUser);
+ this.speak(cvox.ChromeVox.msgs.getMsg('selected'));
+ } else if (this.start == evt.start && this.end < evt.end) {
+ this.speak(this.value.substr(this.end, evt.end - this.end),
+ evt.triggeredByUser);
+ this.speak(cvox.ChromeVox.msgs.getMsg('added_to_selection'));
+ } else if (this.start == evt.start && this.end > evt.end) {
+ this.speak(this.value.substr(evt.end, this.end - evt.end),
+ evt.triggeredByUser);
+ this.speak(cvox.ChromeVox.msgs.getMsg('removed_from_selection'));
+ } else if (this.end == evt.end && this.start > evt.start) {
+ this.speak(this.value.substr(evt.start, this.start - evt.start),
+ evt.triggeredByUser);
+ this.speak(cvox.ChromeVox.msgs.getMsg('added_to_selection'));
+ } else if (this.end == evt.end && this.start < evt.start) {
+ this.speak(this.value.substr(this.start, evt.start - this.start),
+ evt.triggeredByUser);
+ this.speak(cvox.ChromeVox.msgs.getMsg('removed_from_selection'));
+ } else {
+ // The selection changed but it wasn't an obvious extension of
+ // a previous selection. Just read the new selection.
+ this.speak(this.value.substr(evt.start, evt.end - evt.start),
+ evt.triggeredByUser);
+ this.speak(cvox.ChromeVox.msgs.getMsg('selected'));
+ }
+ }
+};
+
+
+/**
+ * Describe a change where the text changes.
+ * @param {cvox.TextChangeEvent} evt The text change event.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.describeTextChanged = function(evt) {
+ var personality = {};
+ if (evt.value.length < this.value.length) {
+ personality = cvox.AbstractTts.PERSONALITY_DELETED;
+ }
+ if (this.isPassword) {
+ this.speak((new goog.i18n.MessageFormat(cvox.ChromeVox.msgs.getMsg('dot'))
+ .format({'COUNT': 1})), evt.triggeredByUser, personality);
+ return;
+ }
+
+ var value = this.value;
+ var len = value.length;
+ var newLen = evt.value.length;
+ var autocompleteSuffix = '';
+ // Make a copy of evtValue and evtEnd to avoid changing anything in
+ // the event itself.
+ var evtValue = evt.value;
+ var evtEnd = evt.end;
+
+ // First, see if there's a selection at the end that might have been
+ // added by autocomplete. If so, strip it off into a separate variable.
+ if (evt.start < evtEnd && evtEnd == newLen) {
+ autocompleteSuffix = evtValue.substr(evt.start);
+ evtValue = evtValue.substr(0, evt.start);
+ evtEnd = evt.start;
+ }
+
+ // Now see if the previous selection (if any) was deleted
+ // and any new text was inserted at that character position.
+ // This would handle pasting and entering text by typing, both from
+ // a cursor and from a selection.
+ var prefixLen = this.start;
+ var suffixLen = len - this.end;
+ if (newLen >= prefixLen + suffixLen + (evtEnd - evt.start) &&
+ evtValue.substr(0, prefixLen) == value.substr(0, prefixLen) &&
+ evtValue.substr(newLen - suffixLen) == value.substr(this.end)) {
+ // However, in a dynamic content editable, defer to authoritative events
+ // (clipboard, key press) to reduce guess work when observing insertions.
+ // Only use this logic when observing deletions (and insertion of word
+ // breakers).
+ // TODO(dtseng): Think about a more reliable way to do this.
+ if (!(this instanceof cvox.ChromeVoxEditableContentEditable) ||
+ newLen < len ||
+ this.isWordBreakChar(evt.value[newLen - 1] || '')) {
+ this.describeTextChangedHelper(
+ evt, prefixLen, suffixLen, autocompleteSuffix, personality);
+ }
+ return;
+ }
+
+ // Next, see if one or more characters were deleted from the previous
+ // cursor position and the new cursor is in the expected place. This
+ // handles backspace, forward-delete, and similar shortcuts that delete
+ // a word or line.
+ prefixLen = evt.start;
+ suffixLen = newLen - evtEnd;
+ if (this.start == this.end &&
+ evt.start == evtEnd &&
+ evtValue.substr(0, prefixLen) == value.substr(0, prefixLen) &&
+ evtValue.substr(newLen - suffixLen) ==
+ value.substr(len - suffixLen)) {
+ this.describeTextChangedHelper(
+ evt, prefixLen, suffixLen, autocompleteSuffix, personality);
+ return;
+ }
+
+ // If all else fails, we assume the change was not the result of a normal
+ // user editing operation, so we'll have to speak feedback based only
+ // on the changes to the text, not the cursor position / selection.
+ // First, restore the autocomplete text if any.
+ evtValue += autocompleteSuffix;
+
+ // Try to do a diff between the new and the old text. If it is a one character
+ // insertion/deletion at the start or at the end, just speak that character.
+ if ((evtValue.length == (value.length + 1)) ||
+ ((evtValue.length + 1) == value.length)) {
+ // The user added text either to the beginning or the end.
+ if (evtValue.length > value.length) {
+ if (evtValue.indexOf(value) == 0) {
+ this.speak(evtValue[evtValue.length - 1], evt.triggeredByUser,
+ personality);
+ return;
+ } else if (evtValue.indexOf(value) == 1) {
+ this.speak(evtValue[0], evt.triggeredByUser, personality);
+ return;
+ }
+ }
+ // The user deleted text either from the beginning or the end.
+ if (evtValue.length < value.length) {
+ if (value.indexOf(evtValue) == 0) {
+ this.speak(value[value.length - 1], evt.triggeredByUser, personality);
+ return;
+ } else if (value.indexOf(evtValue) == 1) {
+ this.speak(value[0], evt.triggeredByUser, personality);
+ return;
+ }
+ }
+ }
+
+ if (this.multiline) {
+ // Fall back to announce deleted but omit the text that was deleted.
+ if (evt.value.length < this.value.length) {
+ this.speak(cvox.ChromeVox.msgs.getMsg('text_deleted'),
+ evt.triggeredByUser, personality);
+ }
+ // The below is a somewhat loose way to deal with non-standard
+ // insertions/deletions. Intentionally skip for multiline since deletion
+ // announcements are covered above and insertions are non-standard (possibly
+ // due to auto complete). Since content editable's often refresh content by
+ // removing and inserting entire chunks of text, this type of logic often
+ // results in unintended consequences such as reading all text when only one
+ // character has been entered.
+ return;
+ }
+
+ // If the text is short, just speak the whole thing.
+ if (newLen <= this.maxShortPhraseLen) {
+ this.describeTextChangedHelper(evt, 0, 0, '', personality);
+ return;
+ }
+
+ // Otherwise, look for the common prefix and suffix, but back up so
+ // that we can speak complete words, to be minimally confusing.
+ prefixLen = 0;
+ while (prefixLen < len &&
+ prefixLen < newLen &&
+ value[prefixLen] == evtValue[prefixLen]) {
+ prefixLen++;
+ }
+ while (prefixLen > 0 && !this.isWordBreakChar(value[prefixLen - 1])) {
+ prefixLen--;
+ }
+
+ suffixLen = 0;
+ while (suffixLen < (len - prefixLen) &&
+ suffixLen < (newLen - prefixLen) &&
+ value[len - suffixLen - 1] == evtValue[newLen - suffixLen - 1]) {
+ suffixLen++;
+ }
+ while (suffixLen > 0 && !this.isWordBreakChar(value[len - suffixLen])) {
+ suffixLen--;
+ }
+
+ this.describeTextChangedHelper(evt, prefixLen, suffixLen, '', personality);
+};
+
+
+/**
+ * The function called by describeTextChanged after it's figured out
+ * what text was deleted, what text was inserted, and what additional
+ * autocomplete text was added.
+ * @param {cvox.TextChangeEvent} evt The text change event.
+ * @param {number} prefixLen The number of characters in the common prefix
+ * of this.value and newValue.
+ * @param {number} suffixLen The number of characters in the common suffix
+ * of this.value and newValue.
+ * @param {string} autocompleteSuffix The autocomplete string that was added
+ * to the end, if any. It should be spoken at the end of the utterance
+ * describing the change.
+ * @param {Object=} opt_personality Personality to speak the text.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.describeTextChangedHelper = function(
+ evt, prefixLen, suffixLen, autocompleteSuffix, opt_personality) {
+ var len = this.value.length;
+ var newLen = evt.value.length;
+ var deletedLen = len - prefixLen - suffixLen;
+ var deleted = this.value.substr(prefixLen, deletedLen);
+ var insertedLen = newLen - prefixLen - suffixLen;
+ var inserted = evt.value.substr(prefixLen, insertedLen);
+ var utterance = '';
+ var triggeredByUser = evt.triggeredByUser;
+
+ if (insertedLen > 1) {
+ utterance = inserted;
+ } else if (insertedLen == 1) {
+ if ((cvox.ChromeVox.typingEcho == cvox.TypingEcho.WORD ||
+ cvox.ChromeVox.typingEcho == cvox.TypingEcho.CHARACTER_AND_WORD) &&
+ this.isWordBreakChar(inserted) &&
+ prefixLen > 0 &&
+ !this.isWordBreakChar(evt.value.substr(prefixLen - 1, 1))) {
+ // Speak previous word.
+ var index = prefixLen;
+ while (index > 0 && !this.isWordBreakChar(evt.value[index - 1])) {
+ index--;
+ }
+ if (index < prefixLen) {
+ utterance = evt.value.substr(index, prefixLen + 1 - index);
+ } else {
+ utterance = inserted;
+ triggeredByUser = false; // Implies QUEUE_MODE_QUEUE.
+ }
+ } else if (cvox.ChromeVox.typingEcho == cvox.TypingEcho.CHARACTER ||
+ cvox.ChromeVox.typingEcho == cvox.TypingEcho.CHARACTER_AND_WORD) {
+ // This particular case is handled in event watcher. See the key press
+ // handler for more details.
+ utterance = cvox.ChromeVoxEditableTextBase.eventTypingEcho ? '' :
+ inserted;
+ }
+ } else if (deletedLen > 1 && !autocompleteSuffix) {
+ utterance = deleted + ', deleted';
+ } else if (deletedLen == 1) {
+ utterance = deleted;
+ }
+
+ if (autocompleteSuffix && utterance) {
+ utterance += ', ' + autocompleteSuffix;
+ } else if (autocompleteSuffix) {
+ utterance = autocompleteSuffix;
+ }
+
+ if (utterance) {
+ this.speak(utterance, triggeredByUser, opt_personality);
+ }
+};
+
+
+/**
+ * Moves the cursor forward by one character.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextCharacter =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor backward by one character.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousCharacter =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor forward by one word.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextWord =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor backward by one word.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousWord =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor forward by one line.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextLine =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor backward by one line.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousLine =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor forward by one paragraph.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToNextParagraph =
+ function() { return false; };
+
+
+/**
+ * Moves the cursor backward by one paragraph.
+ * @return {boolean} True if the action was handled.
+ */
+cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousParagraph =
+ function() { return false; };
+
+
+/******************************************/
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_test.unitjs
index 6da825d3163..2df3086d66b 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_test.unitjs
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_test.unitjs
@@ -95,6 +95,7 @@ CvoxEditableTextUnitTest.prototype = {
/** @override */
closureModuleDeps: [
+ 'cvox.ChromeVoxEditableElement',
'cvox.ChromeVoxEditableHTMLInput',
'cvox.ChromeVoxEditableTextBase',
'cvox.ChromeVoxEventWatcher',
@@ -275,7 +276,7 @@ TEST_F('CvoxEditableTextUnitTest', 'Selection', function() {
TEST_F('CvoxEditableTextUnitTest', 'MultiLineText', function() {
var str = 'This string\nspans\nfive lines.\n \n';
var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase(str, 0, 0, false, tts);
+ var obj = new cvox.ChromeVoxEditableElement(null, str, 0, 0, false, tts);
obj.multiline = true;
obj.getLineIndex = function(index) {
if (index >= 33) {
@@ -668,3 +669,25 @@ TEST_F('CvoxEditableTextUnitTest', 'TextChangeEvent', function() {
assertEquals(1, event3.start);
assertEquals(1, event3.end);
});
+
+TEST_F('CvoxEditableTextUnitTest', 'ContentEditableBraille', function() {
+ this.loadDoc(function() {/*!
+ <div id='1' contenteditable='true'>
+ Some &nbsp; text.<br><br>
+ After blank line.
+ </div>
+ */});
+ var element = $('1');
+ element.focus();
+ var editable = new cvox.ChromeVoxEditableContentEditable(
+ element, new TestTts());
+ var firstLine = 'Some text.\n';
+ for (var i = 0; i < firstLine.length; ++i) {
+ editable.update(true);
+ TestBraille.assertContent(firstLine, i, i);
+ window.getSelection().modify('move', 'forward', 'character');
+ }
+ // We should have crossed the line break to the second line which is blank.
+ editable.update(true);
+ TestBraille.assertContent('', 0, 0);
+});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js
index 7d34b6d6fc2..2e2886d4237 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js
@@ -5,18 +5,3 @@
Range.prototype.getBoundingClientRect;
Document.prototype.documentElement.innerWidth;
Document.prototype.documentElement.head;
-
-/** @constructor */
-function WeakMap() {}
-
-/**
- * @param {Object} key
- * @return {*}
- */
-WeakMap.prototype.get = function(key) {};
-
-/**
- * @param {Object} key
- * @param {*} value
- */
-WeakMap.prototype.set = function(key, value) {};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js
index 486d406b6f5..a5ac8a6b371 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js
@@ -24,7 +24,7 @@ cvox.FindUtil.objectWalker_ = new cvox.BareObjectWalker();
* Finds the next selection that matches the predicate function starting from
* sel. Undefined if the nodes in sel are not attached to the document.
* @param {!cvox.CursorSelection} sel The selection from which to start.
- * @param {function(Array.<Node>):Node} predicate A function taking a
+ * @param {function(Array<Node>):Node} predicate A function taking a
* unique ancestor tree and outputting Node if the ancestor tree matches
* the desired node to find.
* @param {boolean=} opt_initialNode Whether to start the search from node
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js
index 5f4b800bf0a..8d7b7fc117f 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js
@@ -41,6 +41,14 @@ cvox.Interframe.IF_MSG_PREFIX = 'cvox.INTERFRAME:';
cvox.Interframe.SET_ID = 'cvox.INTERFRAME_SET_ID';
/**
+ * The message used by a child frame to acknowledge an id was set (sent to its
+ * parent frame.
+ * @type {string}
+ * @const
+ */
+cvox.Interframe.ACK_SET_ID = 'cvox.INTERFRAME_ACK_SET_ID';
+
+/**
* The ID of this window (relative to its parent farme).
* @type {number|string|undefined}
*/
@@ -49,11 +57,19 @@ cvox.Interframe.id;
/**
* Array of functions that have been registered as listeners to interframe
* messages send to this window.
- * @type {Array.<function(Object)>}
+ * @type {Array<function(Object)>}
*/
cvox.Interframe.listeners = [];
/**
+ * Maps an id to a function which gets called when a frame first sends an ack
+ * for a set id msg.
+ @dict {!Object<number|string, function()>}
+ * @private
+ */
+cvox.Interframe.idToCallback_ = {};
+
+/**
* Flag for unit testing. When false, skips over iframe.contentWindow check
* in sendMessageToIframe. This is needed because in the wild, ChromeVox may
* not have access to iframe.contentWindow due to the same-origin security
@@ -74,6 +90,12 @@ cvox.Interframe.init = function() {
cvox.ChromeVoxJSON.parse(suffix));
if (message['command'] == cvox.Interframe.SET_ID) {
cvox.Interframe.id = message['id'];
+ message['command'] = cvox.Interframe.ACK_SET_ID;
+ cvox.Interframe.sendMessageToParentWindow(message);
+ } else if (message['command'] == cvox.Interframe.ACK_SET_ID) {
+ cvox.Interframe.id = message['id'];
+ var callback = cvox.Interframe.idToCallback_[cvox.Interframe.id];
+ callback();
}
for (var i = 0, listener; listener = cvox.Interframe.listeners[i]; i++) {
listener(message);
@@ -196,8 +218,13 @@ cvox.Interframe.sendMessageToParentWindow = function(message) {
* @param {number|string} id The ID you want to receive in replies from
* this iframe.
* @param {HTMLIFrameElement} iframe The iframe to assign.
+ * @param {function()=} opt_callback Called when a ack msg arrives from the
+ *frame.
*/
-cvox.Interframe.sendIdToIFrame = function(id, iframe) {
+cvox.Interframe.sendIdToIFrame = function(id, iframe, opt_callback) {
+ if (opt_callback) {
+ cvox.Interframe.idToCallback_[id] = opt_callback;
+ }
var message = {'command': cvox.Interframe.SET_ID, 'id': id};
cvox.Interframe.sendMessageToIFrame(message, iframe);
};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js
index 5759399cb27..0a6f3d51c01 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js
@@ -11,6 +11,7 @@
goog.provide('cvox.KeySequence');
goog.require('cvox.ChromeVox');
+goog.require('cvox.PlatformFilter');
/**
@@ -47,6 +48,9 @@ cvox.KeySequence = function(
/** @type {boolean} */
this.doubleTap = !!opt_doubleTap;
+ /** @type {cvox.PlatformFilter} */
+ this.platformFilter;
+
if (opt_cvoxModifier == undefined) {
this.cvoxModifier = this.isCVoxModifierActive(originalEvent);
} else {
@@ -96,7 +100,7 @@ cvox.KeySequence = function(
// TODO(dtseng): This is incomplete; pull once we have appropriate libs.
/**
* Maps a keypress keycode to a keydown or keyup keycode.
- * @type {Object.<number, number>}
+ * @type {Object<number, number>}
*/
cvox.KeySequence.KEY_PRESS_CODE = {
39: 222,
@@ -114,7 +118,7 @@ cvox.KeySequence.KEY_PRESS_CODE = {
* A cache of all key sequences that have been set as double-tappable. We need
* this cache because repeated key down computations causes ChromeVox to become
* less responsive. This list is small so we currently use an array.
- * @type {!Array.<cvox.KeySequence>}
+ * @type {!Array<cvox.KeySequence>}
*/
cvox.KeySequence.doubleTapCache = [];
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js
index 9bbf893c5ef..5ff64d01d7a 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js
@@ -9,10 +9,18 @@
goog.provide('cvox.KeyUtil');
+goog.provide('cvox.SimpleKeyEvent');
goog.require('cvox.ChromeVox');
goog.require('cvox.KeySequence');
+/**
+ * @typedef {{ctrlKey: (boolean|undefined),
+ * altKey: (boolean|undefined),
+ * shiftKey: (boolean|undefined),
+ * keyCode: (number|undefined)}}
+ */
+cvox.SimpleKeyEvent;
/**
* Create the namespace
@@ -59,7 +67,7 @@ cvox.KeyUtil.maxSeqLength = 2;
/**
* Convert a key event into a Key Sequence representation.
*
- * @param {Event} keyEvent The keyEvent to convert.
+ * @param {Event|cvox.SimpleKeyEvent} keyEvent The keyEvent to convert.
* @return {cvox.KeySequence} A key sequence representation of the key event.
*/
cvox.KeyUtil.keyEventToKeySequence = function(keyEvent) {
@@ -199,7 +207,7 @@ cvox.KeyUtil.modStringToKeyCode = function(keyString) {
/**
* Returns the key codes of a string respresentation of the ChromeVox modifiers.
*
- * @return {Array.<number>} Array of key codes.
+ * @return {Array<number>} Array of key codes.
*/
cvox.KeyUtil.cvoxModKeyCodes = function() {
var modKeyCombo = cvox.ChromeVox.modKeyStr.split(/\+/g);
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js
index 69b616eab54..55428e861fb 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js
@@ -55,7 +55,7 @@ goog.require('cvox.SemanticUtil');
cvox.SemanticAttr = function() {
// Punctuation Characters.
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.generalPunctuations =
[
@@ -75,28 +75,28 @@ cvox.SemanticAttr = function() {
this.invisibleComma_ = cvox.SemanticUtil.numberToUnicode(0x2063);
this.generalPunctuations.push(this.invisibleComma_);
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.ellipses =
[
'…', '⋮', '⋯', '⋰', '⋱', '︙'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.fullStops =
[
'.', '﹒', '.'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.dashes =
[
'‒', '–', '—', '―', '〜', '︱', '︲', '﹘'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.primes =
[
@@ -108,7 +108,7 @@ cvox.SemanticAttr = function() {
// record pairs of opening/closing and top/bottom fences.
/**
* Mapping opening to closing fences.
- * @type {Object.<string, string>}
+ * @type {Object<string, string>}
*/
this.openClosePairs =
{
@@ -137,7 +137,7 @@ cvox.SemanticAttr = function() {
};
/**
* Mapping top to bottom fences.
- * @type {Object.<string, string>}
+ * @type {Object<string, string>}
*/
this.topBottomPairs =
{
@@ -146,31 +146,31 @@ cvox.SemanticAttr = function() {
'﹃': '﹄', '﹇': '﹈'
};
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.leftFences = cvox.SemanticUtil.objectsToKeys(this.openClosePairs);
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.rightFences = cvox.SemanticUtil.objectsToValues(this.openClosePairs);
this.rightFences.push('〟');
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.topFences = cvox.SemanticUtil.objectsToKeys(this.topBottomPairs);
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.bottomFences = cvox.SemanticUtil.objectsToValues(this.topBottomPairs);
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.neutralFences =
[
'|', '¦', '‖', '❘', '⦀', '⫴', '¦', '|'
];
/** Array of all fences.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.fences = this.neutralFences.concat(
this.leftFences, this.rightFences, this.topFences, this.bottomFences);
@@ -178,7 +178,7 @@ cvox.SemanticAttr = function() {
// Identifiers.
// Latin Alphabets.
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatin =
[
@@ -186,7 +186,7 @@ cvox.SemanticAttr = function() {
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatin =
[
@@ -196,7 +196,7 @@ cvox.SemanticAttr = function() {
'ı', 'ȷ'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinFullWidth =
[
@@ -204,7 +204,7 @@ cvox.SemanticAttr = function() {
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinFullWidth =
[
@@ -212,7 +212,7 @@ cvox.SemanticAttr = function() {
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinBold =
[
@@ -220,7 +220,7 @@ cvox.SemanticAttr = function() {
'𝐍', '𝐎', '𝐏', '𝐐', '𝐑', '𝐒', '𝐓', '𝐔', '𝐕', '𝐖', '𝐗', '𝐘', '𝐙'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinBold =
[
@@ -228,7 +228,7 @@ cvox.SemanticAttr = function() {
'𝐧', '𝐨', '𝐩', '𝐪', '𝐫', '𝐬', '𝐭', '𝐮', '𝐯', '𝐰', '𝐱', '𝐲', '𝐳'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinItalic =
[
@@ -236,7 +236,7 @@ cvox.SemanticAttr = function() {
'𝑁', '𝑂', '𝑃', '𝑄', '𝑅', '𝑆', '𝑇', '𝑈', '𝑉', '𝑊', '𝑋', '𝑌', '𝑍'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinItalic =
[
@@ -246,7 +246,7 @@ cvox.SemanticAttr = function() {
'𝚤', '𝚥'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinScript =
[
@@ -256,7 +256,7 @@ cvox.SemanticAttr = function() {
'℘'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinScript =
[
@@ -266,7 +266,7 @@ cvox.SemanticAttr = function() {
'ℓ'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinBoldScript =
[
@@ -274,7 +274,7 @@ cvox.SemanticAttr = function() {
'𝓝', '𝓞', '𝓟', '𝓠', '𝓡', '𝓢', '𝓣', '𝓤', '𝓥', '𝓦', '𝓧', '𝓨', '𝓩'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinBoldScript =
[
@@ -282,7 +282,7 @@ cvox.SemanticAttr = function() {
'𝓷', '𝓸', '𝓹', '𝓺', '𝓻', '𝓼', '𝓽', '𝓾', '𝓿', '𝔀', '𝔁', '𝔂', '𝔃'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinFraktur =
[
@@ -290,7 +290,7 @@ cvox.SemanticAttr = function() {
'𝔑', '𝔒', '𝔓', '𝔔', 'ℜ', '𝔖', '𝔗', '𝔘', '𝔙', '𝔚', '𝔛', '𝔜', 'ℨ'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinFraktur =
[
@@ -298,7 +298,7 @@ cvox.SemanticAttr = function() {
'𝔫', '𝔬', '𝔭', '𝔮', '𝔯', '𝔰', '𝔱', '𝔲', '𝔳', '𝔴', '𝔵', '𝔶', '𝔷'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinDoubleStruck =
[
@@ -306,7 +306,7 @@ cvox.SemanticAttr = function() {
'ℕ', '𝕆', 'ℙ', 'ℚ', 'ℝ', '𝕊', '𝕋', '𝕌', '𝕍', '𝕎', '𝕏', '𝕐', 'ℤ'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinDoubleStruck =
[
@@ -314,7 +314,7 @@ cvox.SemanticAttr = function() {
'𝕟', '𝕠', '𝕡', '𝕢', '𝕣', '𝕤', '𝕥', '𝕦', '𝕧', '𝕨', '𝕩', '𝕪', '𝕫'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinBoldFraktur =
[
@@ -322,7 +322,7 @@ cvox.SemanticAttr = function() {
'𝕹', '𝕺', '𝕻', '𝕼', '𝕽', '𝕾', '𝕿', '𝖀', '𝖁', '𝖂', '𝖃', '𝖄', '𝖅'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinBoldFraktur =
[
@@ -330,7 +330,7 @@ cvox.SemanticAttr = function() {
'𝖓', '𝖔', '𝖕', '𝖖', '𝖗', '𝖘', '𝖙', '𝖚', '𝖛', '𝖜', '𝖝', '𝖞', '𝖟'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinSansSerif =
[
@@ -338,7 +338,7 @@ cvox.SemanticAttr = function() {
'𝖭', '𝖮', '𝖯', '𝖰', '𝖱', '𝖲', '𝖳', '𝖴', '𝖵', '𝖶', '𝖷', '𝖸', '𝖹'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinSansSerif =
[
@@ -346,7 +346,7 @@ cvox.SemanticAttr = function() {
'𝗇', '𝗈', '𝗉', '𝗊', '𝗋', '𝗌', '𝗍', '𝗎', '𝗏', '𝗐', '𝗑', '𝗒', '𝗓'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinSansSerifBold =
[
@@ -354,7 +354,7 @@ cvox.SemanticAttr = function() {
'𝗡', '𝗢', '𝗣', '𝗤', '𝗥', '𝗦', '𝗧', '𝗨', '𝗩', '𝗪', '𝗫', '𝗬', '𝗭'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinSansSerifBold =
[
@@ -362,7 +362,7 @@ cvox.SemanticAttr = function() {
'𝗻', '𝗼', '𝗽', '𝗾', '𝗿', '𝘀', '𝘁', '𝘂', '𝘃', '𝘄', '𝘅', '𝘆', '𝘇'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinSansSerifItalic =
[
@@ -370,7 +370,7 @@ cvox.SemanticAttr = function() {
'𝘕', '𝘖', '𝘗', '𝘘', '𝘙', '𝘚', '𝘛', '𝘜', '𝘝', '𝘞', '𝘟', '𝘠', '𝘡'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinSansSerifItalic =
[
@@ -378,7 +378,7 @@ cvox.SemanticAttr = function() {
'𝘯', '𝘰', '𝘱', '𝘲', '𝘳', '𝘴', '𝘵', '𝘶', '𝘷', '𝘸', '𝘹', '𝘺', '𝘻'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalLatinMonospace =
[
@@ -386,7 +386,7 @@ cvox.SemanticAttr = function() {
'𝙽', '𝙾', '𝙿', '𝚀', '𝚁', '𝚂', '𝚃', '𝚄', '𝚅', '𝚆', '𝚇', '𝚈', '𝚉'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallLatinMonospace =
[
@@ -394,7 +394,7 @@ cvox.SemanticAttr = function() {
'𝚗', '𝚘', '𝚙', '𝚚', '𝚛', '𝚜', '𝚝', '𝚞', '𝚟', '𝚠', '𝚡', '𝚢', '𝚣'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.latinDoubleStruckItalic =
[
@@ -403,7 +403,7 @@ cvox.SemanticAttr = function() {
// Greek Alphabets
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalGreek =
[
@@ -411,7 +411,7 @@ cvox.SemanticAttr = function() {
'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallGreek =
[
@@ -419,7 +419,7 @@ cvox.SemanticAttr = function() {
'ξ', 'ο', 'π', 'ρ', 'ς', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalGreekBold =
[
@@ -427,7 +427,7 @@ cvox.SemanticAttr = function() {
'𝚵', '𝚶', '𝚷', '𝚸', '𝚺', '𝚻', '𝚼', '𝚽', '𝚾', '𝚿', '𝛀'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallGreekBold =
[
@@ -435,7 +435,7 @@ cvox.SemanticAttr = function() {
'𝛏', '𝛐', '𝛑', '𝛒', '𝛓', '𝛔', '𝛕', '𝛖', '𝛗', '𝛘', '𝛙', '𝛚'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalGreekItalic =
[
@@ -443,7 +443,7 @@ cvox.SemanticAttr = function() {
'𝛯', '𝛰', '𝛱', '𝛲', '𝛴', '𝛵', '𝛶', '𝛷', '𝛸', '𝛹', '𝛺'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallGreekItalic =
[
@@ -451,7 +451,7 @@ cvox.SemanticAttr = function() {
'𝜉', '𝜊', '𝜋', '𝜌', '𝜍', '𝜎', '𝜏', '𝜐', '𝜑', '𝜒', '𝜓', '𝜔'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.capitalGreekSansSerifBold =
[
@@ -459,7 +459,7 @@ cvox.SemanticAttr = function() {
'𝝣', '𝝤', '𝝥', '𝝦', '𝝨', '𝝩', '𝝪', '𝝫', '𝝬', '𝝭', '𝝮'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.smallGreekSansSerifBold =
[
@@ -467,7 +467,7 @@ cvox.SemanticAttr = function() {
'𝝽', '𝝾', '𝝿', '𝞀', '𝞁', '𝞂', '𝞃', '𝞄', '𝞅', '𝞆', '𝞇', '𝞈'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.greekDoubleStruck =
[
@@ -476,7 +476,7 @@ cvox.SemanticAttr = function() {
// Other alphabets.
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.hebrewLetters =
[
@@ -485,7 +485,7 @@ cvox.SemanticAttr = function() {
//Operator symbols
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.additions =
[
@@ -494,7 +494,7 @@ cvox.SemanticAttr = function() {
'◁', '⩞', '⊕'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
/**
* Invisible operator for plus.
@@ -504,7 +504,7 @@ cvox.SemanticAttr = function() {
this.invisiblePlus_ = cvox.SemanticUtil.numberToUnicode(0x2064);
this.additions.push(this.invisiblePlus_);
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.multiplications =
[
@@ -519,7 +519,7 @@ cvox.SemanticAttr = function() {
this.invisibleTimes_ = cvox.SemanticUtil.numberToUnicode(0x2062);
this.multiplications.push(this.invisibleTimes_);
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.subtractions =
[
@@ -527,7 +527,7 @@ cvox.SemanticAttr = function() {
'⨫', '⨬', '⨺', '⩁', '⩬', '﹣', '-', '‐', '‑'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.divisions =
[
@@ -542,7 +542,7 @@ cvox.SemanticAttr = function() {
//Relation symbols
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.equalities =
[
@@ -552,7 +552,7 @@ cvox.SemanticAttr = function() {
'⩴', '⩵', '⩶', '⩷', '⩸', '⋕', '⩭', '⩪', '⩫', '⩬', '﹦', '='
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.inequalities =
[
@@ -569,14 +569,14 @@ cvox.SemanticAttr = function() {
'⫷', '⫸', '⫹', '⫺', '⧀', '⧁', '﹤', '﹥', '<', '>'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.relations =
[
// TODO (sorge): Add all the other relations.
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.arrows =
[
@@ -613,7 +613,7 @@ cvox.SemanticAttr = function() {
//Big operation symbols
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.sumOps =
[
@@ -622,7 +622,7 @@ cvox.SemanticAttr = function() {
'⨆', '⨇', '⨈', '⨉', '⨊', '⨋', '⫼', '⫿'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.intOps =
[
@@ -630,7 +630,7 @@ cvox.SemanticAttr = function() {
'⨐', '⨑', '⨒', '⨓', '⨔', '⨕', '⨖', '⨗', '⨘', '⨙', '⨚', '⨛', '⨜'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.prefixOps =
// TODO (sorge) Insert nabla, differential operators etc.
@@ -638,7 +638,7 @@ cvox.SemanticAttr = function() {
'∀', '∃'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.operatorBits =
// TODO (sorge) What to do if single glyphs of big ops occur on their own.
@@ -652,70 +652,70 @@ cvox.SemanticAttr = function() {
// Numbers.
// Digits.
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsNormal =
[
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsFullWidth =
[
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsBold =
[
'𝟎', '𝟏', '𝟐', '𝟑', '𝟒', '𝟓', '𝟔', '𝟕', '𝟖', '𝟗'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsDoubleStruck =
[
'𝟘', '𝟙', '𝟚', '𝟛', '𝟜', '𝟝', '𝟞', '𝟟', '𝟠', '𝟡'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsSansSerif =
[
'𝟢', '𝟣', '𝟤', '𝟥', '𝟦', '𝟧', '𝟨', '𝟩', '𝟪', '𝟫'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsSansSerifBold =
[
'𝟬', '𝟭', '𝟮', '𝟯', '𝟰', '𝟱', '𝟲', '𝟳', '𝟴', '𝟵'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsMonospace =
[
'𝟶', '𝟷', '𝟸', '𝟹', '𝟺', '𝟻', '𝟼', '𝟽', '𝟾', '𝟿'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsSuperscript =
[
'²', '³', '¹', '⁰', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digitsSubscript =
[
'₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.fractions =
[
@@ -723,7 +723,7 @@ cvox.SemanticAttr = function() {
'⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '↉'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.enclosedNumbers =
// Encircled numbers.
@@ -738,7 +738,7 @@ cvox.SemanticAttr = function() {
'㉙', '㉚', '㉛', '㉜', '㉝', '㉞', '㉟', '㊱', '㊲', '㊳', '㊴',
'㊵', '㊶', '㊷', '㊸', '㊹', '㊺', '㊻', '㊼', '㊽', '㊾', '㊿'];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.fencedNumbers =
// Numbers in Parenthesis.
@@ -747,7 +747,7 @@ cvox.SemanticAttr = function() {
'⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.punctuatedNumbers =
// Numbers with other punctuation.
@@ -756,25 +756,25 @@ cvox.SemanticAttr = function() {
'🄀', '🄁', '🄂', '🄃', '🄄', '🄅', '🄆', '🄇', '🄈', '🄉', '🄊' // comma.
];
/** Array of all single digits.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.digits = this.digitsNormal.concat(
this.digitsFullWidth, this.digitsBold, this.digitsDoubleStruck,
this.digitsSansSerif, this.digitsSansSerifBold, this.digitsMonospace);
/** Array of all non-digit number symbols.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.numbers = this.fractions.concat(
this.digitsSuperscript, this.digitsSubscript,
this.enclosedNumbers, this.fencedNumbers, this.punctuatedNumbers);
/** Array of all number symbols.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.allNumbers = this.digits.concat(this.numbers);
// Functions.
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.trigonometricFunctions =
[
@@ -782,7 +782,7 @@ cvox.SemanticAttr = function() {
'arccsc', 'arcsec', 'arcsin', 'arctan'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.hyperbolicFunctions =
[
@@ -791,21 +791,21 @@ cvox.SemanticAttr = function() {
'arccosh', 'arccoth', 'arccsch', 'arcsech', 'arcsinh', 'arctanh'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.algebraicFunctions =
[
'deg', 'det', 'dim', 'hom', 'ker', 'Tr', 'tr'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.elementaryFunctions =
[
'log', 'ln', 'lg', 'exp', 'expt', 'gcd', 'gcd', 'arg', 'im', 're', 'Pr'
];
/** All predefined prefix functions.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.prefixFunctions = this.trigonometricFunctions.concat(
this.hyperbolicFunctions,
@@ -814,7 +814,7 @@ cvox.SemanticAttr = function() {
);
/** Limit functions are handled separately as they can have lower (and upper)
* limiting expressions.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.limitFunctions =
[
@@ -822,7 +822,7 @@ cvox.SemanticAttr = function() {
'projlim'
];
/**
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.infixFunctions =
[
@@ -830,7 +830,7 @@ cvox.SemanticAttr = function() {
];
/**
* Default assignments of semantic attributes.
- * @type {Array.<{set: Array.<string>,
+ * @type {Array<{set: Array<string>,
* role: cvox.SemanticAttr.Role,
* type: cvox.SemanticAttr.Type,
* font: cvox.SemanticAttr.Font}>} The semantic meaning of the symbol.
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js
index 647aaec6d7f..991ae3244ca 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js
@@ -50,7 +50,7 @@ cvox.SemanticTree.Node = function(id) {
/** @type {number} */
this.id = id;
- /** @type {Array.<Element>} */
+ /** @type {Array<Element>} */
this.mathml = [];
/** @type {cvox.SemanticTree.Node} */
@@ -65,7 +65,7 @@ cvox.SemanticTree.Node = function(id) {
/** @type {cvox.SemanticAttr.Font} */
this.font = cvox.SemanticAttr.Font.UNKNOWN;
- /** @type {!Array.<cvox.SemanticTree.Node>} */
+ /** @type {!Array<cvox.SemanticTree.Node>} */
this.childNodes = [];
/** @type {string} */
@@ -73,7 +73,7 @@ cvox.SemanticTree.Node = function(id) {
/** Branch nodes can store additional nodes that can be useful.
* E.g. a node of type FENCED can have the opening and closing fences here.
- * @type {!Array.<cvox.SemanticTree.Node>}
+ * @type {!Array<cvox.SemanticTree.Node>}
*/
this.contentNodes = [];
};
@@ -83,7 +83,7 @@ cvox.SemanticTree.Node = function(id) {
* Retrieve all subnodes (including the node itself) that satisfy a given
* predicate.
* @param {function(cvox.SemanticTree.Node): boolean} pred The predicate.
- * @return {!Array.<cvox.SemanticTree.Node>} The nodes in the tree for which the
+ * @return {!Array<cvox.SemanticTree.Node>} The nodes in the tree for which the
* predicate holds.
*/
cvox.SemanticTree.Node.prototype.querySelectorAll = function(pred) {
@@ -124,7 +124,7 @@ cvox.SemanticTree.Node.prototype.querySelectorAll = function(pred) {
/**
* Translates a list of nodes into XML representation.
* @param {string} tag Name of the enclosing tag.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes A list of nodes.
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes A list of nodes.
* @return {Node} An XML representation of the node list.
*/
var xmlNodeList = function(tag, nodes) {
@@ -283,7 +283,7 @@ cvox.SemanticTree.Node.prototype.updateContent_ = function(content) {
* Adds MathML nodes to the node's store of MathML nodes if necessary only, as
* we can not necessarily assume that the MathML of the content nodes and
* children are all disjoint.
- * @param {Array.<Node>} mmlNodes List of MathML nodes.
+ * @param {Array<Node>} mmlNodes List of MathML nodes.
* @private
*/
cvox.SemanticTree.Node.prototype.addMathmlNodes_ = function(mmlNodes) {
@@ -297,7 +297,7 @@ cvox.SemanticTree.Node.prototype.addMathmlNodes_ = function(mmlNodes) {
/**
* Removes MathML nodes from the node's store of MathML nodes.
- * @param {Array.<Node>} mmlNodes List of MathML nodes.
+ * @param {Array<Node>} mmlNodes List of MathML nodes.
* @private
*/
cvox.SemanticTree.Node.prototype.removeMathmlNodes_ = function(mmlNodes) {
@@ -493,8 +493,8 @@ cvox.SemanticTree.prototype.parseMathml_ = function(mml) {
/**
* Parse a list of MathML nodes into the semantic tree.
- * @param {Array.<Element>} mmls A list of MathML nodes.
- * @return {!Array.<cvox.SemanticTree.Node>} The list of resulting semantic
+ * @param {Array<Element>} mmls A list of MathML nodes.
+ * @return {!Array<cvox.SemanticTree.Node>} The list of resulting semantic
* node.
* @private
*/
@@ -549,8 +549,8 @@ cvox.SemanticTree.prototype.makeLeafNode_ = function(mml) {
/**
* Create a branching node.
* @param {!cvox.SemanticAttr.Type} type The type of the node.
- * @param {!Array.<cvox.SemanticTree.Node>} children The child nodes.
- * @param {!Array.<cvox.SemanticTree.Node>} contentNodes The content Nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} children The child nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} contentNodes The content Nodes.
* @param {string=} content Content string if there is any.
* @return {!cvox.SemanticTree.Node} The new node.
* @private
@@ -577,7 +577,7 @@ cvox.SemanticTree.prototype.makeBranchNode_ = function(
/**
* Create a branching node for an implicit operation, currently assumed to
* be of multiplicative type.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes The operands.
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes The operands.
* @return {!cvox.SemanticTree.Node} The new branch node.
* @private
*/
@@ -596,7 +596,7 @@ cvox.SemanticTree.prototype.makeImplicitNode_ = function(nodes) {
/**
* Create a branching node for an infix operation.
- * @param {!Array.<cvox.SemanticTree.Node>} children The operands.
+ * @param {!Array<cvox.SemanticTree.Node>} children The operands.
* @param {!cvox.SemanticTree.Node} opNode The operator.
* @return {!cvox.SemanticTree.Node} The new branch node.
* @private
@@ -612,7 +612,7 @@ cvox.SemanticTree.prototype.makeInfixNode_ = function(children, opNode) {
* one content (thereby concatenating the content of each node into a single
* content string) with the inner node as a child.
* @param {!cvox.SemanticTree.Node} inner The inner node.
- * @param {!Array.<cvox.SemanticTree.Node>} nodeList List of nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} nodeList List of nodes.
* @param {!cvox.SemanticAttr.Type} type The new type of the node.
* @return {!cvox.SemanticTree.Node} The new branch node.
* @private
@@ -635,7 +635,7 @@ cvox.SemanticTree.prototype.makeConcatNode_ = function(inner, nodeList, type) {
* Example: + - a becomes (+ (- (a)))
* Input: a [+, -] -> Output: content: '+ -', child: a
* @param {!cvox.SemanticTree.Node} node The inner node.
- * @param {!Array.<cvox.SemanticTree.Node>} prefixes Prefix operators
+ * @param {!Array<cvox.SemanticTree.Node>} prefixes Prefix operators
* from the outermost to the innermost.
* @return {!cvox.SemanticTree.Node} The new branch node.
* @private
@@ -662,7 +662,7 @@ cvox.SemanticTree.prototype.makePrefixNode_ = function(node, prefixes) {
* Example: a - + becomes (((a) -) +)
* Input: a [-, +] -> Output: content: '- +', child: a
* @param {!cvox.SemanticTree.Node} node The inner node.
- * @param {!Array.<cvox.SemanticTree.Node>} postfixes Postfix operators from
+ * @param {!Array<cvox.SemanticTree.Node>} postfixes Postfix operators from
* innermost to outermost.
* @return {!cvox.SemanticTree.Node} The new branch node.
* @private
@@ -683,7 +683,7 @@ cvox.SemanticTree.prototype.makePostfixNode_ = function(node, postfixes) {
*
* This is the main heuristic to rewrite a flat row of terms into a meaningful
* term tree.
- * @param {!Array.<cvox.SemanticTree.Node>} nodes The list of nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} nodes The list of nodes.
* @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
* @private
*/
@@ -702,7 +702,7 @@ cvox.SemanticTree.prototype.processRow_ = function(nodes) {
/**
* Constructs a syntax tree with relation and operator precedence from a list
* of nodes.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes The list of nodes.
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
* @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
* @private
*/
@@ -732,7 +732,7 @@ cvox.SemanticTree.prototype.processRelationsInRow_ = function(nodes) {
/**
* Constructs a syntax tree with operator precedence from a list nodes.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes The list of nodes.
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
* @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
* @private
*/
@@ -762,7 +762,7 @@ cvox.SemanticTree.prototype.processOperationsInRow_ = function(nodes) {
// At this point, we know that split.head is not empty!
var node = this.makePrefixNode_(
this.makeImplicitNode_(
- /** @type {!Array.<!cvox.SemanticTree.Node>} */ (split.head)),
+ /** @type {!Array<!cvox.SemanticTree.Node>} */ (split.head)),
prefix);
if (!split.div) {
return node;
@@ -774,11 +774,11 @@ cvox.SemanticTree.prototype.processOperationsInRow_ = function(nodes) {
/**
* Recursively constructs syntax tree with operator precedence from a list nodes
* given a initial root node.
- * @param {!Array.<cvox.SemanticTree.Node>} nodes The list of nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} nodes The list of nodes.
* @param {!cvox.SemanticTree.Node} root Initial tree.
* @param {!cvox.SemanticTree.Node} lastop Last operator that has not been
* processed yet.
- * @param {Array.<cvox.SemanticTree.Node>=} prefixes Operator nodes that will
+ * @param {Array<cvox.SemanticTree.Node>=} prefixes Operator nodes that will
* become prefix operation (or postfix in case they come after last operand).
* @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
* @private
@@ -918,8 +918,8 @@ cvox.SemanticTree.prototype.appendExistingOperator_ = function(root, op, node) {
* number of matching fences. E.g. || a|b || would be turned into a fenced
* node with fences || and content a|b.
* 4. Any remaining unmatched delimiters are turned into punctuation nodes.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes The list of nodes.
- * @return {!Array.<!cvox.SemanticTree.Node>} The new list of nodes.
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
+ * @return {!Array<!cvox.SemanticTree.Node>} The new list of nodes.
* @private
*/
cvox.SemanticTree.prototype.getFencesInRow_ = function(nodes) {
@@ -934,13 +934,13 @@ cvox.SemanticTree.prototype.getFencesInRow_ = function(nodes) {
* Recursively processes a list of nodes and combines all the fenced expressions
* into single nodes. It also processes singular fences, building expressions
* that are only fenced left or right.
- * @param {!Array.<cvox.SemanticTree.Node>} fences FIFO queue of fence nodes.
- * @param {!Array.<Array.<cvox.SemanticTree.Node>>} content FIFO queue content
+ * @param {!Array<cvox.SemanticTree.Node>} fences FIFO queue of fence nodes.
+ * @param {!Array<Array<cvox.SemanticTree.Node>>} content FIFO queue content
* between fences.
- * @param {!Array.<cvox.SemanticTree.Node>} openStack LIFO stack of open fences.
- * @param {!Array.<!Array.<cvox.SemanticTree.Node>>} contentStack LIFO stack of
+ * @param {!Array<cvox.SemanticTree.Node>} openStack LIFO stack of open fences.
+ * @param {!Array<!Array<cvox.SemanticTree.Node>>} contentStack LIFO stack of
* content between fences yet to be processed.
- * @return {!Array.<cvox.SemanticTree.Node>} A list of nodes with all fenced
+ * @return {!Array<cvox.SemanticTree.Node>} A list of nodes with all fenced
* expressions processed.
* @private
*/
@@ -1057,10 +1057,10 @@ cvox.SemanticTree.prototype.processFences_ = function(
// TODO (sorge) The following could be done with linear programming.
/**
* Trys to combine neutral fences as much as possible.
- * @param {!Array.<!cvox.SemanticTree.Node>} fences A list of neutral fences.
- * @param {!Array.<!Array.<cvox.SemanticTree.Node>>} content Intermediate
+ * @param {!Array<!cvox.SemanticTree.Node>} fences A list of neutral fences.
+ * @param {!Array<!Array<cvox.SemanticTree.Node>>} content Intermediate
* content. Observe that |content| = |fences| - 1
- * @return {!Array.<cvox.SemanticTree.Node>} List of node with fully fenced
+ * @return {!Array<cvox.SemanticTree.Node>} List of node with fully fenced
* nodes.
* @private
*/
@@ -1099,12 +1099,12 @@ cvox.SemanticTree.prototype.processNeutralFences_ = function(fences, content) {
* return: [c1 | c2 | c3 ], c4, ... cn
* @param {!cvox.SemanticTree.Node} leftFence The left fence.
* @param {!cvox.SemanticTree.Node} rightFence The right fence.
- * @param {!Array.<cvox.SemanticTree.Node>} midFences A list of intermediate
+ * @param {!Array<cvox.SemanticTree.Node>} midFences A list of intermediate
* fences.
- * @param {!Array.<!Array.<cvox.SemanticTree.Node>>} content Intermediate
+ * @param {!Array<!Array<cvox.SemanticTree.Node>>} content Intermediate
* content. Observe that |content| = |fences| - 1 + k where k >= 0 is the
* remainder.
- * @return {!Array.<!Array.<cvox.SemanticTree.Node>>} List of content nodes
+ * @return {!Array<!Array<cvox.SemanticTree.Node>>} List of content nodes
* where the first is the fully fenced node wrt. the given left and right
* fence.
* @private
@@ -1163,7 +1163,7 @@ cvox.SemanticTree.fenceToPunct_ = function(fence) {
* Create a fenced node.
* @param {cvox.SemanticTree.Node} ofence Opening fence.
* @param {cvox.SemanticTree.Node} cfence Closing fence.
- * @param {!Array.<cvox.SemanticTree.Node>} content The content
+ * @param {!Array<cvox.SemanticTree.Node>} content The content
* between the fences.
* @return {!cvox.SemanticTree.Node} The new node.
* @private
@@ -1184,8 +1184,8 @@ cvox.SemanticTree.prototype.makeHorizontalFencedNode_ = function(
/**
* Combines sequences of punctuated expressions in a list of nodes.
- * @param {!Array.<cvox.SemanticTree.Node>} nodes The list of nodes.
- * @return {!Array.<cvox.SemanticTree.Node>} The new list of nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} nodes The list of nodes.
+ * @return {!Array<cvox.SemanticTree.Node>} The new list of nodes.
* @private
*/
cvox.SemanticTree.prototype.getPunctuationInRow_ = function(nodes) {
@@ -1219,9 +1219,9 @@ cvox.SemanticTree.prototype.getPunctuationInRow_ = function(nodes) {
/**
* Create a punctuated node.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes List of all nodes separated
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes List of all nodes separated
* by punctuations.
- * @param {!Array.<!cvox.SemanticTree.Node>} punctuations List of all separating
+ * @param {!Array<!cvox.SemanticTree.Node>} punctuations List of all separating
* punctations. Observe that punctations is a subset of nodes.
* @return {!cvox.SemanticTree.Node}
* @private
@@ -1248,7 +1248,7 @@ cvox.SemanticTree.prototype.makePunctuatedNode_ = function(
* Creates a limit node from a sub/superscript or over/under node if the central
* element is a big operator. Otherwise it creates the standard elements.
* @param {string} mmlTag The tag name of the original node.
- * @param {!Array.<!cvox.SemanticTree.Node>} children The children of the
+ * @param {!Array<!cvox.SemanticTree.Node>} children The children of the
* original node.
* @return {!cvox.SemanticTree.Node} The newly created limit node.
* @private
@@ -1331,10 +1331,10 @@ cvox.SemanticTree.prototype.makeLimitNode_ = function(mmlTag, children) {
* symbol. If we have an explicit function application symbol
* following the expression we turn into a prefix function. Otherwise
* we decide heuristically if we could have a function application.
- * @param {!Array.<cvox.SemanticTree.Node>} restNodes The remainder list of
+ * @param {!Array<cvox.SemanticTree.Node>} restNodes The remainder list of
* nodes.
- * @param {!Array.<cvox.SemanticTree.Node>=} result The result node list.
- * @return {!Array.<!cvox.SemanticTree.Node>} The fully processed list.
+ * @param {!Array<cvox.SemanticTree.Node>=} result The result node list.
+ * @return {!Array<!cvox.SemanticTree.Node>} The fully processed list.
* @private
*/
cvox.SemanticTree.prototype.getFunctionsInRow_ = function(restNodes, result) {
@@ -1360,7 +1360,7 @@ cvox.SemanticTree.prototype.getFunctionsInRow_ = function(restNodes, result) {
/**
* Classifies a function wrt. the heuristic that should be applied.
* @param {!cvox.SemanticTree.Node} funcNode The node to be classified.
- * @param {!Array.<cvox.SemanticTree.Node>} restNodes The remainder list of
+ * @param {!Array<cvox.SemanticTree.Node>} restNodes The remainder list of
* nodes. They can useful to look ahead if there is an explicit function
* application. If there is one, it will be destructively removed!
* @return {!string} The string specifying the heuristic.
@@ -1422,10 +1422,10 @@ cvox.SemanticTree.propagatePrefixFunc_ = function(funcNode) {
* Computes the arguments for a function from a list of nodes depending on the
* given heuristic.
* @param {!cvox.SemanticTree.Node} func A function node.
- * @param {!Array.<cvox.SemanticTree.Node>} rest List of nodes to choose
+ * @param {!Array<cvox.SemanticTree.Node>} rest List of nodes to choose
* arguments from.
* @param {string} heuristic The heuristic to follow.
- * @return {!Array.<!cvox.SemanticTree.Node>} The function and the remainder of
+ * @return {!Array<!cvox.SemanticTree.Node>} The function and the remainder of
* the rest list.
* @private
*/
@@ -1482,12 +1482,12 @@ cvox.SemanticTree.prototype.getFunctionArgs_ = function(func, rest, heuristic) {
/**
* Tail recursive function to obtain integral arguments.
- * @param {!Array.<cvox.SemanticTree.Node>} nodes List of nodes to take
+ * @param {!Array<cvox.SemanticTree.Node>} nodes List of nodes to take
* arguments from.
- * @param {Array.<cvox.SemanticTree.Node>=} args List of integral arguments.
- * @return {{integrand: !Array.<cvox.SemanticTree.Node>,
+ * @param {Array<cvox.SemanticTree.Node>=} args List of integral arguments.
+ * @return {{integrand: !Array<cvox.SemanticTree.Node>,
* intvar: cvox.SemanticTree.Node,
- * rest: !Array.<cvox.SemanticTree.Node>}}
+ * rest: !Array<cvox.SemanticTree.Node>}}
* Result split into integrand, integral variable and the remaining
* elements.
* @private
@@ -1664,8 +1664,8 @@ cvox.SemanticTree.generalFunctionBoundary_ = function(node) {
/**
* Rewrites tables into matrices or case statements in a list of nodes.
- * @param {!Array.<cvox.SemanticTree.Node>} nodes List of nodes to rewrite.
- * @return {!Array.<cvox.SemanticTree.Node>} The new list of nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} nodes List of nodes to rewrite.
+ * @return {!Array<cvox.SemanticTree.Node>} The new list of nodes.
* @private
*/
cvox.SemanticTree.prototype.processTablesInRow_ = function(nodes) {
@@ -1745,7 +1745,7 @@ cvox.SemanticTree.prototype.tableToMatrixOrVector_ = function(node) {
* Heuristic to decide if we have a case statement: An expression with a
* singular open fence before it.
* @param {!cvox.SemanticTree.Node} table A table node.
- * @param {!Array.<cvox.SemanticTree.Node>} prevNodes A list of previous nodes.
+ * @param {!Array<cvox.SemanticTree.Node>} prevNodes A list of previous nodes.
* @return {boolean} True if we believe we have a case statement.
* @private
*/
@@ -1852,13 +1852,13 @@ cvox.SemanticTree.assignRoleToRow_ = function(row, role) {
/**
* Splits a list of nodes wrt. to a given predicate.
- * @param {Array.<cvox.SemanticTree.Node>} nodes A list of nodes.
+ * @param {Array<cvox.SemanticTree.Node>} nodes A list of nodes.
* @param {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the
* partitioning relation.
* @param {boolean=} reverse If true slicing is done from the end.
- * @return {{head: !Array.<cvox.SemanticTree.Node>,
+ * @return {{head: !Array<cvox.SemanticTree.Node>,
* div: cvox.SemanticTree.Node,
- * tail: !Array.<cvox.SemanticTree.Node>}} The split list.
+ * tail: !Array<cvox.SemanticTree.Node>}} The split list.
* @private
*/
cvox.SemanticTree.sliceNodes_ = function(nodes, pred, reverse) {
@@ -1889,11 +1889,11 @@ cvox.SemanticTree.sliceNodes_ = function(nodes, pred, reverse) {
/**
* Partitions a list of nodes wrt. to a given predicate. Effectively works like
* a PER on the ordered set of nodes.
- * @param {!Array.<!cvox.SemanticTree.Node>} nodes A list of nodes.
+ * @param {!Array<!cvox.SemanticTree.Node>} nodes A list of nodes.
* @param {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the
* partitioning relation.
- * @return {{rel: !Array.<cvox.SemanticTree.Node>,
- * comp: !Array.<!Array.<cvox.SemanticTree.Node>>}}
+ * @return {{rel: !Array<cvox.SemanticTree.Node>,
+ * comp: !Array<!Array<cvox.SemanticTree.Node>>}}
* The partitioning given in terms of a collection of elements satisfying
* the predicate and a collection of complementary sets lying inbetween the
* related elements. Observe that we always have |comp| = |rel| + 1.
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js
index 525fe4867fc..b444a584bdf 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js
@@ -17,8 +17,8 @@ cvox.SemanticUtil = function() { };
/**
* Merges keys of objects into an array.
- * @param {...Object.<string, string>} objects Optional objects.
- * @return {Array.<string>} Array of all keys of the objects.
+ * @param {...Object<string, string>} objects Optional objects.
+ * @return {Array<string>} Array of all keys of the objects.
*/
cvox.SemanticUtil.objectsToKeys = function(objects) {
objects = Array.prototype.slice.call(arguments, 0);
@@ -29,8 +29,8 @@ cvox.SemanticUtil.objectsToKeys = function(objects) {
/**
* Merges values of objects into an array.
- * @param {...Object.<string, string>} objects Optional objects.
- * @return {Array.<string>} Array of all values of the objects.
+ * @param {...Object<string, string>} objects Optional objects.
+ * @return {Array<string>} Array of all values of the objects.
*/
cvox.SemanticUtil.objectsToValues = function(objects) {
objects = Array.prototype.slice.call(arguments, 0);
@@ -96,7 +96,7 @@ cvox.SemanticUtil.tagName = function(node) {
/**
* List of MathML Tags that are to be ignored.
- * @type {Array.<string>}
+ * @type {Array<string>}
* @const
*/
cvox.SemanticUtil.IGNORETAGS = [
@@ -107,7 +107,7 @@ cvox.SemanticUtil.IGNORETAGS = [
/**
* List of MathML Tags to be ignore if they have no children.
- * @type {Array.<string>}
+ * @type {Array<string>}
* @const
*/
cvox.SemanticUtil.EMPTYTAGS = ['MATH', 'MROW', 'MPADDED', 'MSTYLE'];
@@ -118,8 +118,8 @@ cvox.SemanticUtil.EMPTYTAGS = ['MATH', 'MROW', 'MPADDED', 'MSTYLE'];
* ignored if they have empty children.
* Observe that this is currently not recursive, i.e. will not take care of
* pathological cases, where content is hidden in incorrectly used tags!
- * @param {Array.<Element>} nodes The node list to be cleaned.
- * @return {Array.<Element>} The cleansed list.
+ * @param {Array<Element>} nodes The node list to be cleaned.
+ * @return {Array<Element>} The cleansed list.
*/
cvox.SemanticUtil.purgeNodes = function(nodes) {
var nodeArray = [];
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js
index 34641dedef9..4de27ae3913 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js
@@ -16,7 +16,7 @@ goog.require('cvox.XpathUtil');
* Checks if a node is in a given class of MathML nodes.
* @private
* @param {!Node} node The node to test.
- * @param {Array.<string>} tags List of tag names.
+ * @param {Array<string>} tags List of tag names.
* @return {boolean} True if node has a tag name included in tags.
*/
cvox.MathUtil.isMathmlNodeOfClass_ = function(node, tags) {
@@ -28,7 +28,7 @@ cvox.MathUtil.isMathmlNodeOfClass_ = function(node, tags) {
* Checks if a node is in a given class of MathJax nodes.
* @private
* @param {!Node} node The node to test.
- * @param {Array.<string>} tags List of tag names.
+ * @param {Array<string>} tags List of tag names.
* @return {boolean} True if node has a tag name included in tags.
*/
cvox.MathUtil.isMathjaxNodeOfClass_ = function(node, tags) {
@@ -46,7 +46,7 @@ cvox.MathUtil.isMathjaxNodeOfClass_ = function(node, tags) {
* of MathML or MathJax nodes.
* @private
* @param {!Node} node The node to test.
- * @param {Array.<string>} tags List of tag names.
+ * @param {Array<string>} tags List of tag names.
* @return {boolean} True if node has a tag name included in tags.
*/
cvox.MathUtil.isMathNodeOfClass_ = function(node, tags) {
@@ -58,7 +58,7 @@ cvox.MathUtil.isMathNodeOfClass_ = function(node, tags) {
/**
* Array of MathML Token Elements.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.TOKEN_LIST = ['MI', 'MN', 'MO', 'MTEXT', 'MSPACE', 'MS'];
@@ -82,7 +82,7 @@ cvox.MathUtil.isToken = function(element) {
/**
* Array of MathML Layout Schemata.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.LAYOUT_LIST = ['MROW', 'MFRAC', 'MSQRT', 'MROOT', 'MSTYLE',
'MERROR', 'MPADDED', 'MPHANTOM', 'MFENCED',
@@ -113,7 +113,7 @@ cvox.MathUtil.isLayout = function(element) {
/**
* Array of MathML Script Schemata.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.SCRIPT_LIST = ['MSUB', 'MSUP', 'MSUBSUP', 'MUNDER', 'MOVER',
'MUNDEROVER', 'MMULTISCRIPTS', 'MPRESCRIPTS'];
@@ -143,7 +143,7 @@ cvox.MathUtil.isScript = function(element) {
/**
* Array of MathML Table and Matrix tokens.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.TABLES_LIST = ['MTABLE', 'MLABELEDTR', 'MTR', 'MTD',
'MALIGNGROUP', 'MALIGNMARK'];
@@ -168,7 +168,7 @@ cvox.MathUtil.isTables = function(element) {
/**
* Array of MathML Elementary Layout Schemata.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.ELEMENTARY_LIST = ['MSTACK', 'MLONGDIV', 'MSGROUP', 'MSROW',
'MSCARRIES', 'MSCARRY', 'MSLINE'];
@@ -197,7 +197,7 @@ cvox.MathUtil.isElementary = function(element) {
/**
* Array of all valid tags in a MathML expression.
* This is a union of all other token lists.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.MATHML_TAG_LIST = [cvox.MathUtil.TOKEN_LIST,
cvox.MathUtil.LAYOUT_LIST,
@@ -221,7 +221,7 @@ cvox.MathUtil.isMathmlTag = function(element) {
/**
* Array of MathML Whitespace and Alignment tokens.
* These are elements that can occur in the other token lists.
- * @type {!Array.<string>}
+ * @type {!Array<string>}
*/
cvox.MathUtil.WHITESPACE_LIST = ['MSROW', 'MROW', 'MSPACE',
'MPHANTOM', 'MPADDED'];
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js
index 271722c99e5..227b26f2646 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js
@@ -51,7 +51,7 @@ cvox.Memoize = function() {
* to function result. This variable is null when we're out of scope, and it's
* a map from string to WeakMap to result when we're in scope.
*
- * @type {?Object.<string, WeakMap.<Node, *> >}
+ * @type {?Object<string, WeakMap<Node, *> >}
* @private
*/
cvox.Memoize.nodeMap_ = null;
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_braille.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_braille.js
deleted file mode 100644
index f74b63d5a06..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_braille.js
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A simple container object for the brailling of a
- * navigation from one object to another.
- *
- */
-
-
-goog.provide('cvox.NavBraille');
-
-goog.require('cvox.ChromeVox');
-goog.require('cvox.CursorSelection');
-goog.require('cvox.Spannable');
-
-/**
- * A class capturing the braille for navigation from one object to
- * another.
- * @param {{text: (undefined|string|!cvox.Spannable),
- * startIndex: (undefined|number),
- * endIndex: (undefined|number)}} kwargs The arguments for braille.
- * text The text of the object itself, including text from
- * titles, labels, etc.
- * startIndex The beginning of a selection within text.
- * endIndex The end of a selection within text.
- * @constructor
- */
-cvox.NavBraille = function(kwargs) {
- /**
- * Text, annotated with DOM nodes.
- * @type {!cvox.Spannable}
- */
- this.text = (kwargs.text instanceof cvox.Spannable) ?
- kwargs.text : new cvox.Spannable(kwargs.text);
-
- /**
- * Selection start index.
- * @type {number}
- */
- this.startIndex = goog.isDef(kwargs.startIndex) ? kwargs.startIndex : -1;
-
- /**
- * Selection end index.
- * @type {number}
- */
- this.endIndex = goog.isDef(kwargs.endIndex) ?
- kwargs.endIndex : this.startIndex;
-};
-
-/**
- * Convenience for creating simple braille output.
- * @param {string|!cvox.Spannable} text Text to represent in braille.
- * @return {!cvox.NavBraille} Braille output without a cursor.
- */
-cvox.NavBraille.fromText = function(text) {
- return new cvox.NavBraille({'text': text});
-};
-
-
-/**
- * Creates a NavBraille from its serialized json form as created
- * by toJson().
- * @param {!Object} json the serialized json object.
- * @return {!cvox.NavBraille}
- */
-cvox.NavBraille.fromJson = function(json) {
- if (typeof json.startIndex !== 'number' ||
- typeof json.endIndex !== 'number') {
- throw 'Invalid start or end index in serialized NavBraille: ' + json;
- }
- return new cvox.NavBraille({
- text: cvox.Spannable.fromJson(json.spannable),
- startIndex: json.startIndex,
- endIndex: json.endIndex
- });
-};
-
-
-/**
- * @return {boolean} true if this braille description is empty.
- */
-cvox.NavBraille.prototype.isEmpty = function() {
- return this.text.getLength() == 0;
-};
-
-
-/**
- * @return {string} A string representation of this object.
- */
-cvox.NavBraille.prototype.toString = function() {
- return 'NavBraille(text="' + this.text.toString() + '" ' +
- ' startIndex="' + this.startIndex + '" ' +
- ' endIndex="' + this.endIndex + '")';
-};
-
-
-/**
- * Returns a plain old data object with the same data.
- * Suitable for JSON encoding.
- *
- * @return {{spannable: Object,
- * startIndex: number,
- * endIndex: number}} JSON equivalent.
- */
-cvox.NavBraille.prototype.toJson = function() {
- return {
- spannable: this.text.toJson(),
- startIndex: this.startIndex,
- endIndex: this.endIndex
- };
-};
-
-
-/**
- * Sends braille to the background page.
- */
-cvox.NavBraille.prototype.write = function() {
- cvox.ChromeVox.braille.write(this);
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js
index 1a946467500..e143ca17d1d 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js
@@ -23,7 +23,7 @@ goog.require('cvox.QueueMode');
* text: (string),
* userValue: (undefined|string),
* annotation: (undefined|string),
- * earcons: (undefined|Array.<number>),
+ * earcons: (undefined|Array<number>),
* personality: (undefined|Object),
* hint: (undefined|string),
category: (undefined|string)}} kwargs The arguments for this
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js
index 4e4bdf0ca21..c4023070d6c 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js
@@ -20,7 +20,7 @@ goog.require('cvox.NavDescription');
* text: (string),
* userValue: (undefined|string),
* annotation: (undefined|string),
- * earcons: (undefined|Array.<number>),
+ * earcons: (undefined|Array<number>),
* personality: (undefined|Object),
* hint: (undefined|string),
* category: (undefined|string),
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js
index 4793b3ecfb7..6abc835bd65 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js
@@ -16,7 +16,7 @@ goog.provide('cvox.NodeStateUtil');
* cvox.ChromeVox.getMsg() call. For example [list_position, 3, 5] maps to
* getMsg('list_position', [3, 5]);
*
- * @typedef {!Array.<!Array.<string|number>>}
+ * @typedef {!Array<!Array<string|number>>}
*/
cvox.NodeState;
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js
index 0517c58f1cd..ad39e4a59e3 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js
@@ -37,7 +37,7 @@ cvox.PageSelection = function(sel) {
* @param {!cvox.CursorSelection} prevSel Previous CursorSelection in
* navigation.
* @param {!cvox.CursorSelection} curSel Current CursorSelection in navigation.
- * @return {Array.<cvox.NavDescription>} The new description.
+ * @return {Array<cvox.NavDescription>} The new description.
*/
cvox.PageSelection.prototype.getDescription =
function(navShifter, prevSel, curSel) {
@@ -71,7 +71,7 @@ cvox.PageSelection.prototype.getDescription =
* Use this description when you want to describe the entire selection
* represented by this instance.
*
- * @return {Array.<cvox.NavDescription>} The new description.
+ * @return {Array<cvox.NavDescription>} The new description.
*/
cvox.PageSelection.prototype.getFullDescription = function() {
return [new cvox.NavDescription(
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js
index 74c5cc4b4b0..3057d2efc9b 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js
@@ -207,7 +207,7 @@ cvox.SelectionUtil.isRangeValid = function(range) {
* Returns absolute top and left positions of an element.
*
* @param {!Node} node The element for which to compute the position.
- * @return {Array.<number>} Index 0 is the left; index 1 is the top.
+ * @return {Array<number>} Index 0 is the left; index 1 is the top.
* @private
*/
cvox.SelectionUtil.findPos_ = function(node) {
@@ -588,6 +588,7 @@ cvox.SelectionUtil.getText = function() {
* if you want i18n tests to pass.
*
* @return {string} The text.
+ * @private
*/
cvox.SelectionUtil.getSelectionText_ = function() {
return '' + window.getSelection();
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js
index ea113a8041e..b4773e274a4 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js
@@ -12,7 +12,7 @@ goog.require('goog.object');
/**
* @constructor
- * @param {string=} opt_string Initial value of the spannable.
+ * @param {string|!cvox.Spannable=} opt_string Initial value of the spannable.
* @param {*=} opt_annotation Initial annotation for the entire string.
*/
cvox.Spannable = function(opt_string, opt_annotation) {
@@ -21,15 +21,19 @@ cvox.Spannable = function(opt_string, opt_annotation) {
* @type {string}
* @private
*/
- this.string_ = opt_string || '';
+ this.string_ = opt_string instanceof cvox.Spannable ? '' : opt_string || '';
/**
* Spans (annotations).
- * @type {!Array.<!{ value: *, start: number, end: number }>}
+ * @type {!Array<!{ value: *, start: number, end: number }>}
* @private
*/
this.spans_ = [];
+ // Append the initial spannable.
+ if (opt_string instanceof cvox.Spannable)
+ this.append(opt_string);
+
// Optionally annotate the entire string.
if (goog.isDef(opt_annotation)) {
var len = this.string_.length;
@@ -135,6 +139,22 @@ cvox.Spannable.prototype.getSpanInstanceOf = function(constructor) {
}
};
+/**
+ * Returns all span values which are an instance of a given constructor.
+ * @param {!Function} constructor Constructor.
+ * @return {!Array<Object>} Array of object.
+ */
+cvox.Spannable.prototype.getSpansInstanceOf = function(constructor) {
+ var ret = [];
+ for (var i = 0; i < this.spans_.length; i++) {
+ var span = this.spans_[i];
+ if (span.value instanceof constructor) {
+ ret.push(span.value);
+ }
+ }
+ return ret;
+};
+
/**
* Returns all spans matching a position.
@@ -385,7 +405,7 @@ cvox.Spannable.SerializeInfo_;
/**
* The serialized format of a spannable.
- * @typedef {{string: string, spans: Array.<cvox.Spannable.SerializedSpan_>}}
+ * @typedef {{string: string, spans: Array<cvox.Spannable.SerializedSpan_>}}
* @private
*/
cvox.Spannable.SerializedSpannable_;
@@ -400,7 +420,7 @@ cvox.Spannable.SerializedSpan_;
/**
* Maps type names to serialization info objects.
- * @type {Object.<string, cvox.Spannable.SerializeInfo_>}
+ * @type {Object<string, cvox.Spannable.SerializeInfo_>}
* @private
*/
cvox.Spannable.serializableSpansByName_ = {};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js
new file mode 100644
index 00000000000..5b771c5a774
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Utilities for strings.
+ */
+
+goog.provide('StringUtil');
+
+/**
+ * @constructor
+ */
+StringUtil = function() {};
+
+/**
+ * Returns the length of the longest common prefix of two strings.
+ * @param {string} first The first string.
+ * @param {string} second The second string.
+ * @return {number} The length of the longest common prefix, which may be 0
+ * for an empty common prefix.
+ */
+StringUtil.longestCommonPrefixLength = function(first, second) {
+ var limit = Math.min(first.length, second.length);
+ var i;
+ for (i = 0; i < limit; ++i) {
+ if (first.charAt(i) != second.charAt(i)) {
+ break;
+ }
+ }
+ return i;
+};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util_test.unitjs
new file mode 100644
index 00000000000..efd31a5afdb
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util_test.unitjs
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Include test fixture.
+GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
+
+/**
+ * Test fixture.
+ * @constructor
+ * @extends {ChromeVoxUnitTestBase}
+ */
+function StringUtilUnitTest() {
+ ChromeVoxUnitTestBase.call(this);
+}
+
+StringUtilUnitTest.prototype = {
+ __proto__: ChromeVoxUnitTestBase.prototype,
+
+ /** @override */
+ closureModuleDeps: [
+ 'StringUtil',
+ ],
+};
+
+TEST_F('StringUtilUnitTest', 'longestCommonPrefixLength', function() {
+ var lcpl = StringUtil.longestCommonPrefixLength;
+ assertEquals(0, lcpl('', ''));
+ assertEquals(0, lcpl('', 'hello'));
+ assertEquals(0, lcpl('hello', ''));
+ assertEquals(1, lcpl('hi', 'hello'));
+});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js
index 4df917ef969..4ca1ec4183c 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js
@@ -115,7 +115,7 @@ cvox.TraverseContent.kParagraph = 'paragraph';
/**
* A constant array of all granularities.
- * @type {Array.<string>}
+ * @type {Array<string>}
* @const
*/
cvox.TraverseContent.kAllGrains =
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js
index 83a622035d9..df4814ee58d 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js
@@ -30,14 +30,14 @@ cvox.TraverseMath = function() {
/**
* Dictionary of all LaTeX elements in the page if there are any.
- * @type {!Object.<string, !Node>}
+ * @type {!Object<string, !Node>}
* @private
*/
this.allTexs_ = {};
/**
* Dictionary of all MathJaxs elements in the page if there are any.
- * @type {!Object.<string, !Node>}
+ * @type {!Object<string, !Node>}
* @private
*/
this.allMathjaxs_ = {};
@@ -45,7 +45,7 @@ cvox.TraverseMath = function() {
/**
* Dictionary of all MathJaxs elements that have not yet been translated at
* page load or during MathJax rendering.
- * @type {!Object.<string, !Node>}
+ * @type {!Object<string, !Node>}
* @private
*/
this.todoMathjaxs_ = {};
@@ -65,13 +65,13 @@ cvox.TraverseMath = function() {
/**
* List of domain names.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.allDomains = [];
/**
* List of style names.
- * @type {Array.<string>}
+ * @type {Array<string>}
*/
this.allStyles = [];
@@ -337,8 +337,8 @@ cvox.TraverseMath.prototype.nextParentChild = function(r) {
/**
* Adds a list of domains and styles to the existing one.
- * @param {Array.<string>} domains List of domain names.
- * @param {Array.<string>} styles List of style names.
+ * @param {Array<string>} domains List of domain names.
+ * @param {Array<string>} styles List of style names.
*/
cvox.TraverseMath.prototype.addDomainsAndStyles = function(domains, styles) {
this.allDomains.push.apply(
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js
index 6253fa07f75..8927c1d8846 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js
@@ -22,7 +22,19 @@ goog.require('cvox.TraverseUtil');
* An object that represents an active table cell inside the shadow table.
* @constructor
*/
-function ShadowTableNode() {}
+function ShadowTableNode() {
+ /**
+ * The cells that are row headers of the corresponding active table cell
+ * @type {!Array}
+ */
+ this.rowHeaderCells = [];
+
+ /**
+ * The cells that are column headers of the corresponding active table cell
+ * @type {!Array}
+ */
+ this.colHeaderCells = [];
+}
/**
@@ -68,21 +80,6 @@ ShadowTableNode.prototype.activeCell;
/**
- * The cells that are row headers of the corresponding active table cell
- * @type {!Array}
- */
-ShadowTableNode.prototype.rowHeaderCells = [];
-
-
-/**
- * The cells that are column headers of the corresponding active table cell
- * @type {!Array}
- */
-ShadowTableNode.prototype.colHeaderCells = [];
-
-
-
-/**
* Initializes the traversal with the provided table node.
*
* @constructor
@@ -114,7 +111,7 @@ cvox.TraverseTable = function(tableNode) {
* the (1,3) position, eliminating the need to check for predecessor cells
* with rowspan/colspan every time we traverse the table.
*
- * @type {!Array.<Array.<ShadowTableNode>>}
+ * @type {!Array<Array<ShadowTableNode>>}
* @private
*/
this.shadowTable_ = [];
@@ -125,7 +122,7 @@ cvox.TraverseTable = function(tableNode) {
* initialization and then only recalculated if the table changes.
* This array is used by findHeaderCells() to determine table row headers
* and column headers.
- * @type {Array.<ShadowTableNode>}
+ * @type {Array<ShadowTableNode>}
* @private
*/
this.candidateHeaders_ = [];
@@ -136,7 +133,7 @@ cvox.TraverseTable = function(tableNode) {
* other cells) then the first one will be associated with the ID. This means
* that shadow nodes that have spanned set to true will not be included in
* this array.
- * @type {Array.<ShadowTableNode>}
+ * @type {Array<ShadowTableNode>}
* @private
*/
this.idToShadowNode_ = [];
@@ -265,7 +262,7 @@ cvox.TraverseTable.prototype.initialize = function(tableNode) {
* Finds the cell cursor containing the specified node within the table.
* Returns null if there is no close cell.
* @param {!Node} node The node for which to find the cursor.
- * @return {Array.<number>} The table index for the node.
+ * @return {Array<number>} The table index for the node.
*/
cvox.TraverseTable.prototype.findNearestCursor = function(node) {
// TODO (stoarca): The current structure for representing the
@@ -856,7 +853,7 @@ cvox.TraverseTable.prototype.getCell = function() {
/**
* Gets the cell at the specified location.
- * @param {Array.<number>} index The index <i, j> of the required cell.
+ * @param {Array<number>} index The index <i, j> of the required cell.
* @return {?Node} The cell <TD> or <TH> or role='gridcell' node at the
* specified location. Null if that cell does not exist.
*/
@@ -1220,7 +1217,7 @@ cvox.TraverseTable.prototype.goToCol = function(index) {
/**
* Moves to the cell at the specified index <i, j> in the table. Updates the
* cell cursor.
- * @param {Array.<number>} index The index <i, j> of the required cell.
+ * @param {Array<number>} index The index <i, j> of the required cell.
* @return {boolean} Either:
* 1) True if the index is valid and the update has been made.
* 2) False if the index is not valid (either less than 0, greater than
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js
index 18781e376d6..7ae41862861 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js
@@ -111,8 +111,8 @@ cvox.TraverseUtil.isHidden = function(node) {
* @param {cvox.Cursor} cursor The cursor location where the search should
* start. On exit, the cursor will be immediately to the right of the
* character returned.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* @return {?string} The character found, or null if the bottom of the
* document has been reached.
*/
@@ -205,8 +205,8 @@ cvox.TraverseUtil.forwardsChar = function(
* @param {cvox.Cursor} cursor The cursor location where the search should
* start. On exit, the cursor will be immediately to the left of the
* character returned.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* @return {?string} The previous character, or null if the top of the
* document has been reached.
*/
@@ -310,8 +310,8 @@ cvox.TraverseUtil.backwardsChar = function(
* the char.
* @param {!cvox.Cursor} endCursor The position to start searching for the next
* char. On exit, will point to the position past the char.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* initial and final cursor position will be pushed onto this array.
* @param {boolean} skipWhitespace If true, will keep scanning until a
* non-whitespace character is found.
@@ -373,8 +373,8 @@ cvox.TraverseUtil.getNextChar = function(
* char. On exit, will point to the position before the char.
* @param {!cvox.Cursor} endCursor The position to start searching for the next
* char. On exit, will point to the position past the char.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* initial and final cursor position will be pushed onto this array.
* @param {boolean} skipWhitespace If true, will keep scanning until a
* non-whitespace character is found.
@@ -431,8 +431,8 @@ cvox.TraverseUtil.getPreviousChar = function(
* word returned.
* @param {cvox.Cursor} endCursor The position to start searching for the next
* word. On exit, will point to the end of the word returned.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* @return {?string} The next word, or null if the bottom of the
* document has been reached.
*/
@@ -492,8 +492,8 @@ cvox.TraverseUtil.getNextWord = function(startCursor, endCursor,
* word returned.
* @param {cvox.Cursor} endCursor On exit, will point to the end of the
* word returned.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* @return {?string} The previous word, or null if the bottom of the
* document has been reached.
*/
@@ -546,9 +546,9 @@ cvox.TraverseUtil.getPreviousWord = function(startCursor, endCursor,
/**
* Given elements entered and left, and break tags, returns true if the
* current word should break.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {Object.<string, boolean>} breakTags Associative array of tags
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {Object<string, boolean>} breakTags Associative array of tags
* that should break.
* @return {boolean} True if elementsEntered or elementsLeft include an
* element with one of these tags.
@@ -584,9 +584,9 @@ cvox.TraverseUtil.includesBreakTagOrSkippedNode = function(
* sentence.
* @param {cvox.Cursor} endCursor The position to start searching for the next
* sentence. On exit, will point to the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {Object.<string, boolean>} breakTags Associative array of tags
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {Object<string, boolean>} breakTags Associative array of tags
* that should break the sentence.
* @return {?string} The next sentence, or null if the bottom of the
* document has been reached.
@@ -610,9 +610,9 @@ cvox.TraverseUtil.getNextSentence = function(
* @param {cvox.Cursor} startCursor The position to start searching for the next
* sentence. On exit, will point to the start of the returned string.
* @param {cvox.Cursor} endCursor On exit, the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {Object.<string, boolean>} breakTags Associative array of tags
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {Object<string, boolean>} breakTags Associative array of tags
* that should break the sentence.
* @return {?string} The previous sentence, or null if the bottom of the
* document has been reached.
@@ -636,9 +636,9 @@ cvox.TraverseUtil.getPreviousSentence = function(
* @param {cvox.Cursor} startCursor On exit, marks the beginning of the line.
* @param {cvox.Cursor} endCursor The position to start searching for the next
* line. On exit, will point to the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {Object.<string, boolean>} breakTags Associative array of tags
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {Object<string, boolean>} breakTags Associative array of tags
* that should break the line.
* @return {?string} The next line, or null if the bottom of the
* document has been reached.
@@ -682,9 +682,9 @@ cvox.TraverseUtil.getNextLine = function(
* @param {cvox.Cursor} startCursor The position to start searching for the next
* line. On exit, will point to the start of the returned string.
* @param {cvox.Cursor} endCursor On exit, the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {Object.<string, boolean>} breakTags Associative array of tags
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {Object<string, boolean>} breakTags Associative array of tags
* that should break the line.
* @return {?string} The previous line, or null if the bottom of the
* document has been reached.
@@ -729,8 +729,8 @@ cvox.TraverseUtil.getPreviousLine = function(
* paragraph.
* @param {cvox.Cursor} endCursor The position to start searching for the next
* paragraph. On exit, will point to the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* @return {?string} The next paragraph, or null if the bottom of the
* document has been reached.
*/
@@ -765,8 +765,8 @@ cvox.TraverseUtil.getNextParagraph = function(startCursor, endCursor,
* @param {cvox.Cursor} startCursor The position to start searching for the next
* paragraph. On exit, will point to the start of the returned string.
* @param {cvox.Cursor} endCursor On exit, the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
* @return {?string} The previous paragraph, or null if the bottom of the
* document has been reached.
*/
@@ -815,9 +815,9 @@ cvox.TraverseUtil.getPreviousParagraph = function(
* next string.
* @param {cvox.Cursor} endCursor The position to start searching for the next
* string. On exit, will point to the end of the returned string.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {function(string, string, Array.<Element>, Array.<Element>)}
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {function(string, string, Array<Element>, Array<Element>)}
* breakBefore Function that takes the string so far, next word to be
* added, and elements entered and left, and returns true if the string
* should be ended before adding this word.
@@ -877,9 +877,9 @@ cvox.TraverseUtil.getNextString = function(
* string returned.
* @param {cvox.Cursor} endCursor On exit, will point to the end of the
* string returned.
- * @param {Array.<Element>} elementsEntered Any HTML elements entered.
- * @param {Array.<Element>} elementsLeft Any HTML elements left.
- * @param {function(string, string, Array.<Element>, Array.<Element>)}
+ * @param {Array<Element>} elementsEntered Any HTML elements entered.
+ * @param {Array<Element>} elementsLeft Any HTML elements left.
+ * @param {function(string, string, Array<Element>, Array<Element>)}
* breakBefore Function that takes the string so far, the word to be
* added, and nodes crossed, and returns true if the string should be
* ended before adding this word.