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.js978
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util_test.unitjs142
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js209
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler.js63
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler_test.unitjs70
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js374
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs420
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/buildinfo.js20
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js521
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js290
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js368
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js784
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/command_store_test.unitjs73
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js103
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js235
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor_test.unitjs326
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/cursor.js59
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection.js255
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection_test.unitjs97
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/date_widget.js322
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js474
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js493
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js2608
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util_test.unitjs1578
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/earcon_util.js67
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js649
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js190
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow_test.unitjs67
-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.unitjs693
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js5
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js66
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/find_util_test.unitjs51
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/focus_util.js98
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/focuser.js120
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/group_util.js150
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js240
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js633
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence_test.unitjs445
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js500
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js1529
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js1939
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree_test.unitjs6188
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js135
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js263
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/media_widget.js91
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js133
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/msgs.js161
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js163
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js48
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js52
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js107
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection_test.unitjs143
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/platform_util.js51
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js611
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util_test.unitjs31
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js434
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.unitjs481
-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/table_util.js179
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/time_widget.js221
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js482
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js446
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js1309
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js927
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/common/xpath_util.js152
67 files changed, 0 insertions, 31888 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
deleted file mode 100644
index 09b36bdf1a1..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util.js
+++ /dev/null
@@ -1,978 +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 collection of JavaScript utilities used to simplify working
- * with ARIA (http://www.w3.org/TR/wai-aria).
- */
-
-
-goog.provide('cvox.AriaUtil');
-goog.require('cvox.AbstractEarcons');
-goog.require('cvox.ChromeVox');
-goog.require('cvox.NodeState');
-goog.require('cvox.NodeStateUtil');
-
-
-/**
- * Create the namespace
- * @constructor
- */
-cvox.AriaUtil = function() {
-};
-
-
-/**
- * A mapping from ARIA role names to their message ids.
- * 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>}
- */
-cvox.AriaUtil.WIDGET_ROLE_TO_NAME = {
- 'alert' : 'role_alert',
- 'alertdialog' : 'role_alertdialog',
- 'button' : 'role_button',
- 'checkbox' : 'role_checkbox',
- 'columnheader' : 'role_columnheader',
- 'combobox' : 'role_combobox',
- 'dialog' : 'role_dialog',
- 'grid' : 'role_grid',
- 'gridcell' : 'role_gridcell',
- 'link' : 'role_link',
- 'listbox' : 'role_listbox',
- 'log' : 'role_log',
- 'marquee' : 'role_marquee',
- 'menu' : 'role_menu',
- 'menubar' : 'role_menubar',
- 'menuitem' : 'role_menuitem',
- 'menuitemcheckbox' : 'role_menuitemcheckbox',
- 'menuitemradio' : 'role_menuitemradio',
- 'option' : 'role_option',
- 'progressbar' : 'role_progressbar',
- 'radio' : 'role_radio',
- 'radiogroup' : 'role_radiogroup',
- 'rowheader' : 'role_rowheader',
- 'scrollbar' : 'role_scrollbar',
- 'slider' : 'role_slider',
- 'spinbutton' : 'role_spinbutton',
- 'status' : 'role_status',
- 'tab' : 'role_tab',
- 'tablist' : 'role_tablist',
- 'tabpanel' : 'role_tabpanel',
- 'textbox' : 'role_textbox',
- 'timer' : 'role_timer',
- 'toolbar' : 'role_toolbar',
- 'tooltip' : 'role_tooltip',
- 'treeitem' : 'role_treeitem'
-};
-
-
-/**
- * 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>}
- */
-cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME = {
- 'article' : 'role_article',
- 'application' : 'role_application',
- 'banner' : 'role_banner',
- 'columnheader' : 'role_columnheader',
- 'complementary' : 'role_complementary',
- 'contentinfo' : 'role_contentinfo',
- 'definition' : 'role_definition',
- 'directory' : 'role_directory',
- 'document' : 'role_document',
- 'form' : 'role_form',
- 'group' : 'role_group',
- 'heading' : 'role_heading',
- 'img' : 'role_img',
- 'list' : 'role_list',
- 'listitem' : 'role_listitem',
- 'main' : 'role_main',
- 'math' : 'role_math',
- 'navigation' : 'role_navigation',
- 'note' : 'role_note',
- 'region' : 'role_region',
- 'rowheader' : 'role_rowheader',
- 'search' : 'role_search',
- 'separator' : 'role_separator'
-};
-
-
-/**
- * @type {Array<Object>}
- */
-cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS = [
- { name: 'aria-autocomplete', values:
- {'inline' : 'aria_autocomplete_inline',
- 'list' : 'aria_autocomplete_list',
- 'both' : 'aria_autocomplete_both'} },
- { name: 'aria-checked', values:
- {'true' : 'aria_checked_true',
- 'false' : 'aria_checked_false',
- 'mixed' : 'aria_checked_mixed'} },
- { name: 'aria-disabled', values:
- {'true' : 'aria_disabled_true'} },
- { name: 'aria-expanded', values:
- {'true' : 'aria_expanded_true',
- 'false' : 'aria_expanded_false'} },
- { name: 'aria-invalid', values:
- {'true' : 'aria_invalid_true',
- 'grammar' : 'aria_invalid_grammar',
- 'spelling' : 'aria_invalid_spelling'} },
- { name: 'aria-multiline', values:
- {'true' : 'aria_multiline_true'} },
- { name: 'aria-multiselectable', values:
- {'true' : 'aria_multiselectable_true'} },
- { name: 'aria-pressed', values:
- {'true' : 'aria_pressed_true',
- 'false' : 'aria_pressed_false',
- 'mixed' : 'aria_pressed_mixed'} },
- { name: 'aria-readonly', values:
- {'true' : 'aria_readonly_true'} },
- { name: 'aria-required', values:
- {'true' : 'aria_required_true'} },
- { name: 'aria-selected', values:
- {'true' : 'aria_selected_true',
- 'false' : 'aria_selected_false'} }
-];
-
-
-/**
- * Checks if a node should be treated as a hidden node because of its ARIA
- * markup.
- *
- * @param {Node} targetNode The node to check.
- * @return {boolean} True if the targetNode should be treated as hidden.
- */
-cvox.AriaUtil.isHiddenRecursive = function(targetNode) {
- if (cvox.AriaUtil.isHidden(targetNode)) {
- return true;
- }
- var parent = targetNode.parentElement;
- while (parent) {
- if ((parent.getAttribute('aria-hidden') == 'true') &&
- (parent.getAttribute('chromevoxignoreariahidden') != 'true')) {
- return true;
- }
- parent = parent.parentElement;
- }
- return false;
-};
-
-
-/**
- * Checks if a node should be treated as a hidden node because of its ARIA
- * markup. Does not check parents, so if you need to know if this is a
- * descendant of a hidden node, call isHiddenRecursive.
- *
- * @param {Node} targetNode The node to check.
- * @return {boolean} True if the targetNode should be treated as hidden.
- */
-cvox.AriaUtil.isHidden = function(targetNode) {
- if (!targetNode) {
- return true;
- }
- if (targetNode.getAttribute) {
- if ((targetNode.getAttribute('aria-hidden') == 'true') &&
- (targetNode.getAttribute('chromevoxignoreariahidden') != 'true')) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Checks if a node should be treated as a visible node because of its ARIA
- * markup, regardless of whatever other styling/attributes it may have.
- * It is possible to force a node to be visible by setting aria-hidden to
- * false.
- *
- * @param {Node} targetNode The node to check.
- * @return {boolean} True if the targetNode should be treated as visible.
- */
-cvox.AriaUtil.isForcedVisibleRecursive = function(targetNode) {
- var node = targetNode;
- while (node) {
- if (node.getAttribute) {
- // Stop and return the result based on the closest node that has
- // aria-hidden set.
- if (node.hasAttribute('aria-hidden') &&
- (node.getAttribute('chromevoxignoreariahidden') != 'true')) {
- return node.getAttribute('aria-hidden') == 'false';
- }
- }
- node = node.parentElement;
- }
- return false;
-};
-
-
-/**
- * Checks if a node should be treated as a leaf node because of its ARIA
- * markup. Does not check recursively, and does not check isControlWidget.
- * Note that elements with aria-label are treated as leaf elements. See:
- * http://www.w3.org/TR/wai-aria/roles#textalternativecomputation
- *
- * @param {Element} targetElement The node to check.
- * @return {boolean} True if the targetNode should be treated as a leaf node.
- */
-cvox.AriaUtil.isLeafElement = function(targetElement) {
- var role = targetElement.getAttribute('role');
- var hasArialLabel = targetElement.hasAttribute('aria-label') &&
- (targetElement.getAttribute('aria-label').length > 0);
- return (role == 'img' || role == 'progressbar' || hasArialLabel);
-};
-
-
-/**
- * Determines whether or not a node is or is the descendant of a node
- * with a particular role.
- *
- * @param {Node} node The node to be checked.
- * @param {string} roleName The role to check for.
- * @return {boolean} True if the node or one of its ancestor has the specified
- * role.
- */
-cvox.AriaUtil.isDescendantOfRole = function(node, roleName) {
- while (node) {
- if (roleName && node && (node.getAttribute('role') == roleName)) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
-};
-
-
-/**
- * Helper function to return the role name message identifier for a role.
- * @param {string} role The role.
- * @return {?string} The role name message identifier.
- * @private
- */
-cvox.AriaUtil.getRoleNameMsgForRole_ = function(role) {
- var msgId = cvox.AriaUtil.WIDGET_ROLE_TO_NAME[role];
- if (!msgId) {
- return null;
- }
- return msgId;
-};
-
-/**
- * Returns true is the node is any kind of button.
- *
- * @param {Node} node The node to check.
- * @return {boolean} True if the node is a button.
- */
-cvox.AriaUtil.isButton = function(node) {
- var role = cvox.AriaUtil.getRoleAttribute(node);
- if (role == 'button') {
- return true;
- }
- if (node.tagName == 'BUTTON') {
- return true;
- }
- if (node.tagName == 'INPUT') {
- return (node.type == 'submit' ||
- node.type == 'reset' ||
- node.type == 'button');
- }
- return false;
-};
-
-/**
- * Returns a role message identifier for a node.
- * For a localized string, see cvox.AriaUtil.getRoleName.
- * @param {Node} targetNode The node to get the role name for.
- * @return {string} The role name message identifier for the targetNode.
- */
-cvox.AriaUtil.getRoleNameMsg = function(targetNode) {
- var roleName;
- if (targetNode && targetNode.getAttribute) {
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
-
- // Special case for pop-up buttons.
- if (targetNode.getAttribute('aria-haspopup') == 'true' &&
- cvox.AriaUtil.isButton(targetNode)) {
- return 'role_popup_button';
- }
-
- if (role) {
- roleName = cvox.AriaUtil.getRoleNameMsgForRole_(role);
- if (!roleName) {
- roleName = cvox.AriaUtil.STRUCTURE_ROLE_TO_NAME[role];
- }
- }
-
- // To a user, a menu item within a menu bar is called a "menu";
- // any other menu item is called a "menu item".
- //
- // TODO(deboer): This block feels like a hack. dmazzoni suggests
- // using css-like syntax for names. Investigate further if
- // we need more of these hacks.
- if (role == 'menuitem') {
- var container = targetNode.parentElement;
- while (container) {
- if (container.getAttribute &&
- (cvox.AriaUtil.getRoleAttribute(container) == 'menu' ||
- cvox.AriaUtil.getRoleAttribute(container) == 'menubar')) {
- break;
- }
- container = container.parentElement;
- }
- if (container && cvox.AriaUtil.getRoleAttribute(container) == 'menubar') {
- roleName = cvox.AriaUtil.getRoleNameMsgForRole_('menu');
- } // else roleName is already 'Menu item', no need to change it.
- }
- }
- if (!roleName) {
- roleName = '';
- }
- return roleName;
-};
-
-/**
- * Returns a string to be presented to the user that identifies what the
- * targetNode's role is.
- *
- * @param {Node} targetNode The node to get the role name for.
- * @return {string} The role name for the targetNode.
- */
-cvox.AriaUtil.getRoleName = function(targetNode) {
- var roleMsg = cvox.AriaUtil.getRoleNameMsg(targetNode);
- var roleName = Msgs.getMsg(roleMsg);
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- if ((role == 'heading') && (targetNode.hasAttribute('aria-level'))) {
- roleName += ' ' + targetNode.getAttribute('aria-level');
- }
- return roleName ? roleName : '';
-};
-
-/**
- * Returns a string that gives information about the state of the targetNode.
- *
- * @param {Node} targetNode The node to get the state information for.
- * @param {boolean} primary Whether this is the primary node we're
- * interested in, where we might want extra information - as
- * opposed to an ancestor, where we might be more brief.
- * @return {cvox.NodeState} The status information about the node.
- */
-cvox.AriaUtil.getStateMsgs = function(targetNode, primary) {
- var state = [];
- if (!targetNode || !targetNode.getAttribute) {
- return state;
- }
-
- for (var i = 0, attr; attr = cvox.AriaUtil.ATTRIBUTE_VALUE_TO_STATUS[i];
- i++) {
- var value = targetNode.getAttribute(attr.name);
- var msgId = attr.values[value];
- if (msgId) {
- state.push([msgId]);
- }
- }
- if (targetNode.getAttribute('role') == 'grid') {
- return cvox.AriaUtil.getGridState_(targetNode, targetNode);
- }
-
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- if (targetNode.getAttribute('aria-haspopup') == 'true') {
- if (role == 'menuitem') {
- state.push(['has_submenu']);
- } else if (cvox.AriaUtil.isButton(targetNode)) {
- // Do nothing - the role name will be 'pop-up button'.
- } else {
- state.push(['has_popup']);
- }
- }
-
- var valueText = targetNode.getAttribute('aria-valuetext');
- if (valueText) {
- // If there is a valueText, that always wins.
- state.push(['aria_value_text', valueText]);
- return state;
- }
-
- var valueNow = targetNode.getAttribute('aria-valuenow');
- var valueMin = targetNode.getAttribute('aria-valuemin');
- var valueMax = targetNode.getAttribute('aria-valuemax');
-
- // Scrollbar and progressbar should speak the percentage.
- // http://www.w3.org/TR/wai-aria/roles#scrollbar
- // http://www.w3.org/TR/wai-aria/roles#progressbar
- if ((valueNow != null) && (valueMin != null) && (valueMax != null)) {
- if ((role == 'scrollbar') || (role == 'progressbar')) {
- var percent = Math.round((valueNow / (valueMax - valueMin)) * 100);
- state.push(['state_percent', percent]);
- return state;
- }
- }
-
- // Return as many of the value attributes as possible.
- if (valueNow != null) {
- state.push(['aria_value_now', valueNow]);
- }
- if (valueMin != null) {
- state.push(['aria_value_min', valueMin]);
- }
- if (valueMax != null) {
- state.push(['aria_value_max', valueMax]);
- }
-
- // If this is a composite control or an item within a composite control,
- // get the index and count of the current descendant or active
- // descendant.
- var parentControl = targetNode;
- var currentDescendant = null;
-
- if (cvox.AriaUtil.isCompositeControl(parentControl) && primary) {
- currentDescendant = cvox.AriaUtil.getActiveDescendant(parentControl);
- } else {
- role = cvox.AriaUtil.getRoleAttribute(targetNode);
- if (role == 'option' ||
- role == 'menuitem' ||
- role == 'menuitemcheckbox' ||
- role == 'menuitemradio' ||
- role == 'radio' ||
- role == 'tab' ||
- role == 'treeitem') {
- currentDescendant = targetNode;
- parentControl = targetNode.parentElement;
- while (parentControl &&
- !cvox.AriaUtil.isCompositeControl(parentControl)) {
- parentControl = parentControl.parentElement;
- if (parentControl &&
- cvox.AriaUtil.getRoleAttribute(parentControl) == 'treeitem') {
- break;
- }
- }
- }
- }
-
- if (parentControl &&
- (cvox.AriaUtil.isCompositeControl(parentControl) ||
- cvox.AriaUtil.getRoleAttribute(parentControl) == 'treeitem') &&
- currentDescendant) {
- var parentRole = cvox.AriaUtil.getRoleAttribute(parentControl);
- var descendantRoleList;
- switch (parentRole) {
- case 'combobox':
- case 'listbox':
- descendantRoleList = ['option'];
- break;
- case 'menu':
- descendantRoleList = ['menuitem',
- 'menuitemcheckbox',
- 'menuitemradio'];
- break;
- case 'radiogroup':
- descendantRoleList = ['radio'];
- break;
- case 'tablist':
- descendantRoleList = ['tab'];
- break;
- case 'tree':
- case 'treegrid':
- case 'treeitem':
- descendantRoleList = ['treeitem'];
- break;
- }
-
- if (descendantRoleList) {
- var listLength;
- var currentIndex;
-
- var ariaLength =
- parseInt(currentDescendant.getAttribute('aria-setsize'), 10);
- if (!isNaN(ariaLength)) {
- listLength = ariaLength;
- }
- var ariaIndex =
- parseInt(currentDescendant.getAttribute('aria-posinset'), 10);
- if (!isNaN(ariaIndex)) {
- currentIndex = ariaIndex;
- }
-
- if (listLength == undefined || currentIndex == undefined) {
- var descendants = cvox.AriaUtil.getNextLevel(parentControl,
- descendantRoleList);
- if (listLength == undefined) {
- listLength = descendants.length;
- }
- if (currentIndex == undefined) {
- for (var j = 0; j < descendants.length; j++) {
- if (descendants[j] == currentDescendant) {
- currentIndex = j + 1;
- }
- }
- }
- }
- if (currentIndex && listLength) {
- state.push(['list_position', currentIndex, listLength]);
- }
- }
- }
- return state;
-};
-
-
-/**
- * Returns a string that gives information about the state of the grid node.
- *
- * @param {Node} targetNode The node to get the state information for.
- * @param {Node} parentControl The parent composite control.
- * @return {cvox.NodeState} The status information about the node.
- * @private
- */
-cvox.AriaUtil.getGridState_ = function(targetNode, parentControl) {
- var activeDescendant = cvox.AriaUtil.getActiveDescendant(parentControl);
-
- if (activeDescendant) {
- var descendantSelector = '*[role~="row"]';
- var rows = parentControl.querySelectorAll(descendantSelector);
- var currentIndex = null;
- for (var j = 0; j < rows.length; j++) {
- var gridcells = rows[j].querySelectorAll('*[role~="gridcell"]');
- for (var k = 0; k < gridcells.length; k++) {
- if (gridcells[k] == activeDescendant) {
- return /** @type {cvox.NodeState} */ (
- [['role_gridcell_pos', j + 1, k + 1]]);
- }
- }
- }
- }
- return [];
-};
-
-
-/**
- * Returns the id of a node's active descendant
- * @param {Node} targetNode The node.
- * @return {?string} The id of the active descendant.
- * @private
- */
-cvox.AriaUtil.getActiveDescendantId_ = function(targetNode) {
- if (!targetNode.getAttribute) {
- return null;
- }
-
- var activeId = targetNode.getAttribute('aria-activedescendant');
- if (!activeId) {
- return null;
- }
- return activeId;
-};
-
-
-/**
- * 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.
- */
-cvox.AriaUtil.getNextLevel = function(parentControl, role) {
- var result = [];
- var children = parentControl.childNodes;
- var length = children.length;
- for (var i = 0; i < children.length; i++) {
- if (cvox.AriaUtil.isHidden(children[i]) ||
- !cvox.DomUtil.isVisible(children[i])) {
- continue;
- }
- var nextLevel = cvox.AriaUtil.getNextLevelItems(children[i], role);
- if (nextLevel.length > 0) {
- result = result.concat(nextLevel);
- }
- }
- return result;
-};
-
-
-/**
- * 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.
- */
-cvox.AriaUtil.getNextLevelItems = function(current, role) {
- if (current.nodeType != 1) { // If reached a node that is not an element.
- return [];
- }
- if (role.indexOf(cvox.AriaUtil.getRoleAttribute(current)) != -1) {
- return [current];
- } else {
- var children = current.childNodes;
- var length = children.length;
- if (length == 0) {
- return [];
- } else {
- var resultArray = [];
- for (var i = 0; i < length; i++) {
- var result = cvox.AriaUtil.getNextLevelItems(children[i], role);
- if (result.length > 0) {
- resultArray = resultArray.concat(result);
- }
- }
- return resultArray;
- }
- }
-};
-
-
-/**
- * If the node is an object with an active descendant, returns the
- * descendant node.
- *
- * This function will fully resolve an active descendant chain. If a circular
- * chain is detected, it will return null.
- *
- * @param {Node} targetNode The node to get descendant information for.
- * @return {Node} The descendant node or null if no node exists.
- */
-cvox.AriaUtil.getActiveDescendant = function(targetNode) {
- var seenIds = {};
- var node = targetNode;
-
- while (node) {
- var activeId = cvox.AriaUtil.getActiveDescendantId_(node);
- if (!activeId) {
- break;
- }
- if (activeId in seenIds) {
- // A circlar activeDescendant is an error, so return null.
- return null;
- }
- seenIds[activeId] = true;
- node = document.getElementById(activeId);
- }
-
- if (node == targetNode) {
- return null;
- }
- return node;
-};
-
-
-/**
- * Given a node, returns true if it's an ARIA control widget. Control widgets
- * are treated as leaf nodes.
- *
- * @param {Node} targetNode The node to be checked.
- * @return {boolean} Whether the targetNode is an ARIA control widget.
- */
-cvox.AriaUtil.isControlWidget = function(targetNode) {
- if (targetNode && targetNode.getAttribute) {
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- switch (role) {
- case 'button':
- case 'checkbox':
- case 'combobox':
- case 'listbox':
- case 'menu':
- case 'menuitemcheckbox':
- case 'menuitemradio':
- case 'radio':
- case 'slider':
- case 'progressbar':
- case 'scrollbar':
- case 'spinbutton':
- case 'tab':
- case 'tablist':
- case 'textbox':
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Given a node, returns true if it's an ARIA composite control.
- *
- * @param {Node} targetNode The node to be checked.
- * @return {boolean} Whether the targetNode is an ARIA composite control.
- */
-cvox.AriaUtil.isCompositeControl = function(targetNode) {
- if (targetNode && targetNode.getAttribute) {
- var role = cvox.AriaUtil.getRoleAttribute(targetNode);
- switch (role) {
- case 'combobox':
- case 'grid':
- case 'listbox':
- case 'menu':
- case 'menubar':
- case 'radiogroup':
- case 'tablist':
- case 'tree':
- case 'treegrid':
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Given a node, returns its 'aria-live' value if it's a live region, or
- * null otherwise.
- *
- * @param {Node} node The node to be checked.
- * @return {?string} The live region value, like 'polite' or
- * 'assertive', or null if 'off' or none.
- */
-cvox.AriaUtil.getAriaLive = function(node) {
- if (!node.hasAttribute)
- return null;
- var value = node.getAttribute('aria-live');
- if (value == 'off') {
- return null;
- } else if (value) {
- return value;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'alert':
- return 'assertive';
- case 'log':
- case 'status':
- return 'polite';
- default:
- return null;
- }
-};
-
-
-/**
- * Given a node, returns its 'aria-atomic' value.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} The aria-atomic live region value, either true or false.
- */
-cvox.AriaUtil.getAriaAtomic = function(node) {
- if (!node.hasAttribute)
- return false;
- var value = node.getAttribute('aria-atomic');
- if (value) {
- return (value === 'true');
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- if (role == 'alert') {
- return true;
- }
- return false;
-};
-
-
-/**
- * Given a node, returns its 'aria-busy' value.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} The aria-busy live region value, either true or false.
- */
-cvox.AriaUtil.getAriaBusy = function(node) {
- if (!node.hasAttribute)
- return false;
- var value = node.getAttribute('aria-busy');
- if (value) {
- return (value === 'true');
- }
- return false;
-};
-
-
-/**
- * Given a node, checks its aria-relevant attribute (with proper inheritance)
- * and determines whether the given change (additions, removals, text, all)
- * is relevant and should be announced.
- *
- * @param {Node} node The node to be checked.
- * @param {string} change The name of the change to check - one of
- * 'additions', 'removals', 'text', 'all'.
- * @return {boolean} True if that change is relevant to that node as part of
- * a live region.
- */
-cvox.AriaUtil.getAriaRelevant = function(node, change) {
- if (!node.hasAttribute)
- return false;
- var value;
- if (node.hasAttribute('aria-relevant')) {
- value = node.getAttribute('aria-relevant');
- } else {
- value = 'additions text';
- }
- if (value == 'all') {
- value = 'additions removals text';
- }
-
- var tokens = value.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '').split(' ');
-
- if (change == 'all') {
- return (tokens.indexOf('additions') >= 0 &&
- tokens.indexOf('text') >= 0 &&
- tokens.indexOf('removals') >= 0);
- } else {
- return (tokens.indexOf(change) >= 0);
- }
-};
-
-
-/**
- * Given a node, return all live regions that are either rooted at this
- * node or contain this node.
- *
- * @param {Node} node The node to be checked.
- * @return {Array<Element>} All live regions affected by this node changing.
- */
-cvox.AriaUtil.getLiveRegions = function(node) {
- var result = [];
- if (node.querySelectorAll) {
- var nodes = node.querySelectorAll(
- '[role="alert"], [role="log"], [role="marquee"], ' +
- '[role="status"], [role="timer"], [aria-live]');
- if (nodes) {
- for (var i = 0; i < nodes.length; i++) {
- result.push(nodes[i]);
- }
- }
- }
-
- while (node) {
- if (cvox.AriaUtil.getAriaLive(node)) {
- result.push(node);
- return result;
- }
- node = node.parentElement;
- }
-
- return result;
-};
-
-
-/**
- * Checks to see whether or not a node is an ARIA landmark.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} Whether or not the node is an ARIA landmark.
- */
-cvox.AriaUtil.isLandmark = function(node) {
- if (!node || !node.getAttribute) {
- return false;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'application':
- case 'banner':
- case 'complementary':
- case 'contentinfo':
- case 'form':
- case 'main':
- case 'navigation':
- case 'search':
- return true;
- }
- return false;
-};
-
-
-/**
- * Checks to see whether or not a node is an ARIA grid.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} Whether or not the node is an ARIA grid.
- */
-cvox.AriaUtil.isGrid = function(node) {
- if (!node || !node.getAttribute) {
- return false;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'grid':
- case 'treegrid':
- return true;
- }
- return false;
-};
-
-
-/**
- * Returns the id of an earcon to play along with the description for a node.
- *
- * @param {Node} node The node to get the earcon for.
- * @return {cvox.Earcon?} The earcon id, or null if none applies.
- */
-cvox.AriaUtil.getEarcon = function(node) {
- if (!node || !node.getAttribute) {
- return null;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- switch (role) {
- case 'button':
- return cvox.Earcon.BUTTON;
- case 'checkbox':
- case 'radio':
- case 'menuitemcheckbox':
- case 'menuitemradio':
- var checked = node.getAttribute('aria-checked');
- if (checked == 'true') {
- return cvox.Earcon.CHECK_ON;
- } else {
- return cvox.Earcon.CHECK_OFF;
- }
- case 'combobox':
- case 'listbox':
- return cvox.Earcon.LISTBOX;
- case 'textbox':
- return cvox.Earcon.EDITABLE_TEXT;
- case 'listitem':
- return cvox.Earcon.LIST_ITEM;
- case 'link':
- return cvox.Earcon.LINK;
- }
-
- return null;
-};
-
-
-/**
- * Returns the role of the node.
- *
- * This is equivalent to targetNode.getAttribute('role')
- * except it also takes into account cases where ChromeVox
- * itself has changed the role (ie, adding role="application"
- * to BODY elements for better screen reader compatibility.
- *
- * @param {Node} targetNode The node to get the role for.
- * @return {string} role of the targetNode.
- */
-cvox.AriaUtil.getRoleAttribute = function(targetNode) {
- if (!targetNode.getAttribute) {
- return '';
- }
- var role = targetNode.getAttribute('role');
- if (targetNode.hasAttribute('chromevoxoriginalrole')) {
- role = targetNode.getAttribute('chromevoxoriginalrole');
- }
- return role;
-};
-
-
-/**
- * Checks to see whether or not a node is an ARIA math node.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} Whether or not the node is an ARIA math node.
- */
-cvox.AriaUtil.isMath = function(node) {
- if (!node || !node.getAttribute) {
- return false;
- }
- var role = cvox.AriaUtil.getRoleAttribute(node);
- return role == 'math';
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util_test.unitjs
deleted file mode 100644
index bf13830445b..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/aria_util_test.unitjs
+++ /dev/null
@@ -1,142 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture for aria_util.js.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxAriaUtilUnitTest() {}
-
-CvoxAriaUtilUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.AriaUtil',
- 'cvox.ChromeVox',
- 'cvox.DomUtil',]
-};
-
-TEST_F('CvoxAriaUtilUnitTest', 'GetStateGridWithActiveCell', function() {
- this.loadDoc(function() {/*!
- <div id="grid" role="grid" aria-activedescendant="cell">
- <div role="row">
- <div id="cell" role="gridcell">
- </div>
- </div>
- */});
- assertThat(
- cvox.AriaUtil.getStateMsgs($('grid'), true),
- eqJSON([['role_gridcell_pos', 1, 1]]));
-});
-
-TEST_F('CvoxAriaUtilUnitTest', 'GetActiveDescendant', function() {
- this.loadDoc(function() {/*!
- <div id="top" aria-activedescendant="child">
- <div id="child" />
- </div>
- <div id="top_2" aria-activedescendant="child_2">
- <div id="child_2" aria-activedescendant="grandchild_2">
- <div id="grandchild_2" />
- </div>
- </div>
-
- <h1>The buggy cases.</h1>
- <div id="loop" aria-activedescendant="loop" />
- <div id="circleA" aria-activedescendant="circleB">
- <div id="circleB" aria-activedescendant="circleA" />
- </div>
- */});
-
- // The typical case.
- var topElt = $('top');
- var childElt = $('child');
- assertEquals(childElt, cvox.AriaUtil.getActiveDescendant(topElt));
-
- // childElt has not aria-activedescendant, so return null.
- assertEquals(null, cvox.AriaUtil.getActiveDescendant(childElt));
-
- // The chained case.
- var top2Elt = $('top_2');
- var grandchild2Elt = $('grandchild_2');
- assertEquals(grandchild2Elt, cvox.AriaUtil.getActiveDescendant(top2Elt));
-
- // The buggy cases. These are invalid, so return null as if the
- // aria-activedescendant tags did not exist.
- var loopElt = $('loop');
- assertEquals(null, cvox.AriaUtil.getActiveDescendant(loopElt));
-
- var circleAElt = $('circleA');
- assertEquals(null, cvox.AriaUtil.getActiveDescendant(circleAElt));
-});
-
-TEST_F('CvoxAriaUtilUnitTest', 'ListIndexAndState', function() {
- this.loadDoc(function() {/*!
- <div id="l" role="listbox" tabindex="0" aria-activedescendant="l2">
- <div id="l1" role="option">A</div>
- <div id="l2" role="option">B</div>
- <div id="l3" role="option">C</div>
- </div>
- <div id="a" role="listbox" tabindex="0" aria-activedescendant="a2">
- <div id="a1" role="option" aria-setsize="10" aria-posinset="5">A</div>
- <div id="a2" role="option" aria-setsize="20" aria-posinset="15">B</div>
- <div id="a3" role="option" aria-setsize="30" aria-posinset="25">C</div>
- </div>
- <div id="b" role="listbox" tabindex="0" aria-activedescendant="b2">
- <div id="b1" role="option" aria-posinset="3">A</div>
- <div id="b2" role="option" aria-posinset="2">B</div>
- <div id="b3" role="option" aria-posinset="1">C</div>
- </div>
- */});
-
- var optionElt = $('l2');
- assertThat(
- cvox.AriaUtil.getStateMsgs(optionElt),
- eqJSON([['list_position', 2, 3]]));
-
- var ariaOptionElt = $('a2');
- assertThat(
- cvox.AriaUtil.getStateMsgs(ariaOptionElt),
- eqJSON([['list_position', 15, 20]]));
-
- ariaOptionElt = $('b3');
- assertThat(
- cvox.AriaUtil.getStateMsgs(ariaOptionElt),
- eqJSON([['list_position', 1, 3]]));
-});
-
-TEST_F('CvoxAriaUtilUnitTest', 'GetLiveRegions', function() {
- this.loadDoc(function() {/*!
- <div id="outer">
- <div id="progress" role="progressbar" aria-live="polite" aria-valuenow="1">
- <div id="ptext">
- 1% complete.
- </div>
- </div>
- <div id="progress2" role="progressbar" aria-live="polite" aria-valuenow="1">
- <div id="ptext2">
- 1% complete.
- </div>
- </div>
- </div>
- */});
-
- var progressLiveRegions = cvox.AriaUtil.getLiveRegions(progress);
- assertEquals(1, progressLiveRegions.length);
- assertNotEquals(-1, progressLiveRegions.indexOf(progress));
-
- var outerLiveRegions = cvox.AriaUtil.getLiveRegions(outer);
- assertEquals(2, outerLiveRegions.length);
- assertNotEquals(-1, outerLiveRegions.indexOf(progress));
- assertNotEquals(-1, outerLiveRegions.indexOf(progress2));
-
- // getLiveRegions works walking up the tree as well.
- var ptextLiveRegions = cvox.AriaUtil.getLiveRegions(ptext);
- assertEquals(1, ptextLiveRegions.length);
- assertNotEquals(-1, ptextLiveRegions.indexOf(progress));
-});
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
deleted file mode 100644
index 0e8c3b5cf57..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/aural_style_util.js
+++ /dev/null
@@ -1,209 +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 set of classes to support aural CSS.
- */
-
-
-goog.provide('cvox.AuralProperty');
-goog.provide('cvox.AuralStyleConverter');
-goog.provide('cvox.AuralStyleUtil');
-
-// This seems the only way to lay out an enum and use it as a key.
-/**
- * @enum {string}
- */
-cvox.AuralProperty = {
- VOLUME: 'VOLUME',
- SPEAK: 'SPEAK',
- PAUSE_BEFORE: 'PAUSE_BEFORE',
- PAUSE_AFTER: 'PAUSE_AFTER',
- PAUSE: 'PAUSE',
- CUE_BEFORE: 'CUE_BEFORE',
- CUE_AFTER: 'CUE_AFTER',
- CUE: 'CUE',
- PLAY_DURING: 'PLAY_DURING',
- AZIMUTH: 'AZIMUTH',
- ELEVATION: 'ELEVATION',
- SPEECH_RATE: 'SPEECH_RATE',
- VOICE_FAMILY: 'VOICE_FAMILY',
- PITCH: 'PITCH',
- PITCH_RANGE: 'PITCH_RANGE',
- STRESS: 'STRESS',
- RICHNESS: 'RICHNESS',
- SPEAK_PUNCTUATION: 'SPEAK_PUNCTUATION',
- SPEAK_NUMERIAL: 'SPEAK_NUMERIAL',
- SPEAK_HEADER: 'SPEAK_HEADER',
- NONE: 'NONE'
-};
-
-
-/* A series of conversion functions. */
-/**
- * An identity conversion.
- * @param {number} value The aural CSS value to convert.
- * @return {number} The resulting tts property value.
- */
-cvox.AuralStyleConverter.identity = function(value) {
- return 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>}
- */
-cvox.AuralStyleConverter.propertyTable = {
- VOLUME: 'volume',
- SPEAK: 'no-op',
- PAUSE_BEFORE: 'no-op',
- PAUSE_AFTER: 'no-op',
- PAUSE: 'no-op',
- CUE_BEFORE: 'no-op',
- CUE_AFTER: 'no-op',
- CUE: 'no-op',
- PLAY_DURING: 'no-op',
- AZIMUTH: 'no-op',
- ELEVATION: 'no-op',
- SPEECH_RATE: 'relativeRate',
- VOICE_FAMILY: 'no-op',
- PITCH: 'relativePitch',
- PITCH_RANGE: 'no-op',
- STRESS: 'no-op',
- RICHNESS: 'no-op',
- SPEAK_PUNCTUATION: 'no-op',
- SPEAK_NUMERIAL: 'no-op',
- SPEAK_HEADER: 'no-op',
- NONE: 'no-op'
-};
-
-
-/**
- * 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(*)>}
- */
-cvox.AuralStyleConverter.valueTable = {
- VOLUME: cvox.AuralStyleConverter.identity,
- SPEAK: cvox.AuralStyleConverter.identity,
- PAUSE_BEFORE: cvox.AuralStyleConverter.identity,
- PAUSE_AFTER: cvox.AuralStyleConverter.identity,
- PAUSE: cvox.AuralStyleConverter.identity,
- CUE_BEFORE: cvox.AuralStyleConverter.identity,
- CUE_AFTER: cvox.AuralStyleConverter.identity,
- CUE: cvox.AuralStyleConverter.identity,
- PLAY_DURING: cvox.AuralStyleConverter.identity,
- AZIMUTH: cvox.AuralStyleConverter.identity,
- ELEVATION: cvox.AuralStyleConverter.identity,
- SPEECH_RATE: cvox.AuralStyleConverter.identity,
- VOICE_FAMILY: cvox.AuralStyleConverter.identity,
- PITCH: cvox.AuralStyleConverter.identity,
- PITCH_RANGE: cvox.AuralStyleConverter.identity,
- STRESS: cvox.AuralStyleConverter.identity,
- RICHNESS: cvox.AuralStyleConverter.identity,
- SPEAK_PUNCTUATION: cvox.AuralStyleConverter.identity,
- SPEAK_NUMERIAL: cvox.AuralStyleConverter.identity,
- SPEAK_HEADER: cvox.AuralStyleConverter.identity,
- NONE: cvox.AuralStyleConverter.identity
-};
-
-
-/**
- * Converts a given aural property/value rule to a tts property/value.
- * @param {cvox.AuralProperty} property The property.
- * @param {*} value The CSS-based value.
- * @return {Object} An object holding tts property and value.
- */
-cvox.AuralStyleConverter.convertRule = function(property, value) {
- return {
- property: cvox.AuralStyleConverter.propertyTable[property],
- value: cvox.AuralStyleConverter.valueTable[property](value)
- };
-};
-
-
-/**
- * Converts an aural CSS style block to a TTS property object.
- * @param {Object<cvox.AuralProperty, *>} style The style.
- * @return {Object} The tts property object.
- */
-cvox.AuralStyleConverter.convertStyle = function(style) {
- var ttsProperties = {};
- for (var property in style) {
- var ttsProperty =
- cvox.AuralStyleConverter.convertRule(property, style[property]);
- ttsProperties[ttsProperty.property] = ttsProperty.value;
- }
- return ttsProperties;
-};
-
-
-/**
- * Gets the aural style for a node.
- * @param {Node} node The node.
- * @return {Object} The aural style, converted to tts properties.
-*/
-cvox.AuralStyleUtil.getStyleForNode = function(node) {
- var style = cvox.AuralStyleUtil.defaultStyles[node.tagName];
- if (!style) {
- return null;
- }
- return cvox.AuralStyleConverter.convertStyle(style);
-};
-
-
-/**
- * A list of default aural styles.
- */
-cvox.AuralStyleUtil.defaultStyles = {
- 'ARTICLE': {
- PITCH: -0.1
- },
- 'ASIDE': {
- PITCH: -0.1
- },
- 'FOOTER': {
- PITCH: -0.1
- },
- 'H1': {
- PITCH: -0.3
- },
- 'H2': {
- PITCH: -0.25
- },
- 'H3': {
- PITCH: -0.2
- },
- 'H4': {
- PITCH: -0.15
- },
- 'H5': {
- PITCH: -0.1
- },
- 'H6': {
- PITCH: -0.05
- },
- 'HEADER': {
- PITCH: -0.1
- },
- 'HGROUP': {
- PITCH: -0.1
- },
- 'MARK': {
- PITCH: -0.1
- },
- 'NAV': {
- PITCH: -0.1
- },
- 'SECTION': {
- PITCH: -0.1
- },
- 'TIME': {
- PITCH: -0.1
- }
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler.js
deleted file mode 100644
index 36d3e04cba8..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler.js
+++ /dev/null
@@ -1,63 +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.
-
-goog.provide('cvox.BrailleTextHandler');
-
-goog.require('cvox.BrailleInterface');
-goog.require('cvox.BrailleUtil');
-goog.require('cvox.ChromeVox');
-goog.require('cvox.NavBraille');
-
-/**
- * @fileoverview Updates braille display contents following text changes.
- *
- */
-
-/**
- * Represents an editable text region.
- *
- * @constructor
- * @param {!cvox.BrailleInterface} braille Braille interface.
- */
-cvox.BrailleTextHandler = function(braille) {
- /**
- * Braille interface used to produce output.
- * @type {!cvox.BrailleInterface}
- * @private
- */
- this.braille_ = braille;
-};
-
-
-/**
- * Called by controller class when text changes.
- * @param {string} line The text of the line.
- * @param {number} start The 0-based index starting selection.
- * @param {number} end The 0-based index ending selection.
- * @param {boolean} multiline True if the text comes from a multi line text
- * field.
- * @param {Element} element DOM node which line comes from.
- * @param {number} lineStart Start offset of line (might be > 0 for multiline
- * fields).
- */
-cvox.BrailleTextHandler.prototype.changed = function(
- line, start, end, multiline, element, lineStart) {
- var content;
- if (multiline) {
- var spannable = cvox.BrailleUtil.createValue(line, start, end, lineStart);
- if (element) {
- spannable.setSpan(element, 0, line.length);
- }
- content = new cvox.NavBraille({text: spannable,
- startIndex: start,
- endIndex: end});
- } else {
- if (cvox.ChromeVox.navigationManager) {
- content = cvox.ChromeVox.navigationManager.getBraille();
- }
- }
- if (content) {
- this.braille_.write(content);
- }
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler_test.unitjs
deleted file mode 100644
index 3f53422bd38..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_text_handler_test.unitjs
+++ /dev/null
@@ -1,70 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * @extends {cvox.BrailleInterface}
- * @constructor
- */
-function FakeBraille() {
-}
-
-FakeBraille.prototype = {
- /** @override */
- write: function(content) {
- this.content = content;
- }
-};
-
-/** @constructor */
-function FakeNavigationManager() {
-}
-
-FakeNavigationManager.prototype = {
- getBraille: function() {
- return this.navBraille;
- },
-
- setNavBraille: function(navBraille) {
- this.navBraille = navBraille;
- }
-};
-
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxBrailleTextHandlerUnitTest() {}
-
-CvoxBrailleTextHandlerUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.BrailleInterface',
- 'cvox.BrailleTextHandler',
- 'cvox.NavBraille',
- 'cvox.NavigationManager',
- ],
-
- /** @override */
- setUp: function() {
- this.navigationManager = new FakeNavigationManager();
- this.braille = new FakeBraille();
- cvox.ChromeVox.navigationManager = this.navigationManager;
- this.brailleTextHandler = new cvox.BrailleTextHandler(this.braille);
- }
-};
-
-TEST_F('CvoxBrailleTextHandlerUnitTest', 'UpdateByUser', function() {
- var navBraille = new cvox.NavBraille({ text: 'Hello, world!' });
- this.navigationManager.setNavBraille(navBraille);
-
- this.brailleTextHandler.changed('', 0, 0, false);
- assertEquals(navBraille, this.braille.content);
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js
deleted file mode 100644
index 77ace8dcfc0..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util.js
+++ /dev/null
@@ -1,374 +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 utility class for general braille functionality.
- */
-
-
-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');
-
-
-/**
- * Trimmable whitespace character that appears between consecutive items in
- * braille.
- * @const {string}
- */
-cvox.BrailleUtil.ITEM_SEPARATOR = ' ';
-
-
-/**
- * Messages considered as containers in braille.
- * 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>}
- */
-cvox.BrailleUtil.CONTAINER = [
- 'tag_h1_brl',
- 'tag_h2_brl',
- 'tag_h3_brl',
- 'tag_h4_brl',
- 'tag_h5_brl',
- 'tag_h6_brl'
-];
-
-
-/**
- * Maps a ChromeVox message id to a braille template.
- * The template takes one-character specifiers:
- * n: replaced with braille name.
- * r: replaced with braille role.
- * s: replaced with braille state.
- * 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>}
- */
-cvox.BrailleUtil.TEMPLATE = {
- 'base': 'c n v r s',
- 'role_alert': 'r: n',
- 'role_button': 'n r s',
- 'role_checkbox': 'n r s',
- 'role_menuitemcheckbox': 'n r s',
- 'role_menuitemradio': 'n r s',
- 'role_radio': 'n r s',
- 'role_textbox': 'n: v 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_search': 'n: v r s',
- 'input_type_text': 'n: v r s',
- 'input_type_url': 'n: v r s',
- 'tag_textarea': 'n: v r s'
-};
-
-
-/**
- * Gets the braille name for a node.
- * See DomUtil for a more precise definition of 'name'.
- * Additionally, whitespace is trimmed.
- * @param {Node} node The node.
- * @return {string} The string representation.
- */
-cvox.BrailleUtil.getName = function(node) {
- if (!node) {
- return '';
- }
- return cvox.DomUtil.getName(node).trim();
-};
-
-
-/**
- * Gets the braille role message id for a node.
- * See DomUtil for a more precise definition of 'role'.
- * @param {Node} node The node.
- * @return {string} The string representation.
- */
-cvox.BrailleUtil.getRoleMsg = function(node) {
- if (!node) {
- return '';
- }
- var roleMsg = cvox.DomUtil.getRoleMsg(node, cvox.VERBOSITY_VERBOSE);
- if (roleMsg) {
- roleMsg = cvox.DomUtil.collapseWhitespace(roleMsg);
- }
- if (roleMsg && (roleMsg.length > 0)) {
- if (Msgs.getMsg(roleMsg + '_brl')) {
- roleMsg += '_brl';
- }
- }
- return roleMsg;
-};
-
-
-/**
- * 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.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 (Msgs.getMsg(state[0] + '_brl', dummySubs)) {
- state[0] += '_brl';
- }
- });
- return cvox.NodeStateUtil.expand(stateMsgs);
-};
-
-
-/**
- * Gets the braille container role of a node.
- * @param {Node} prev The previous node in navigation.
- * @param {Node} node The node.
- * @return {string} The string representation.
- */
-cvox.BrailleUtil.getContainer = function(prev, node) {
- if (!prev || !node) {
- return '';
- }
- var ancestors = cvox.DomUtil.getUniqueAncestors(prev, node);
- for (var i = 0, container; container = ancestors[i]; i++) {
- var msg = cvox.BrailleUtil.getRoleMsg(container);
- if (msg && cvox.BrailleUtil.CONTAINER.indexOf(msg) != -1) {
- return Msgs.getMsg(msg);
- }
- }
- return '';
-};
-
-
-/**
- * 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.
- */
-cvox.BrailleUtil.getValue = function(node) {
- if (!node) {
- return new cvox.Spannable();
- }
- var valueSpan = new cvox.ValueSpan(0 /* offset */);
- if (cvox.DomUtil.isInputTypeText(node)) {
- var value = node.value;
- if (node.type === 'password') {
- value = value.replace(/./g, '*');
- }
- var spannable = new cvox.Spannable(value, valueSpan);
- if (node === document.activeElement &&
- cvox.DomUtil.doesInputSupportSelection(node)) {
- var selectionStart = cvox.BrailleUtil.clamp_(
- node.selectionStart, 0, spannable.getLength());
- var selectionEnd = cvox.BrailleUtil.clamp_(
- node.selectionEnd, 0, spannable.getLength());
- spannable.setSpan(new cvox.ValueSelectionSpan(),
- Math.min(selectionStart, selectionEnd),
- Math.max(selectionStart, selectionEnd));
- }
- return spannable;
- } else if (node instanceof HTMLTextAreaElement) {
- var shadow = new cvox.EditableTextAreaShadow();
- shadow.update(node);
- var lineIndex = shadow.getLineIndex(node.selectionEnd);
- var lineStart = shadow.getLineStart(lineIndex);
- var lineEnd = shadow.getLineEnd(lineIndex);
- var lineText = node.value.substring(lineStart, lineEnd);
- valueSpan.offset = lineStart;
- var spannable = new cvox.Spannable(lineText, valueSpan);
- if (node === document.activeElement) {
- var selectionStart = cvox.BrailleUtil.clamp_(
- node.selectionStart - lineStart, 0, spannable.getLength());
- var selectionEnd = cvox.BrailleUtil.clamp_(
- node.selectionEnd - lineStart, 0, spannable.getLength());
- spannable.setSpan(new cvox.ValueSelectionSpan(),
- Math.min(selectionStart, selectionEnd),
- Math.max(selectionStart, selectionEnd));
- }
- return spannable;
- } else {
- return new cvox.Spannable(cvox.DomUtil.getValue(node), valueSpan);
- }
-};
-
-
-/**
- * Gets the templated representation of braille.
- * @param {Node} prev The previous node (during navigation).
- * @param {Node} node The node.
- * @param {{name:(undefined|string),
- * role:(undefined|string),
- * roleMsg:(undefined|string),
- * state:(undefined|string),
- * container:(undefined|string),
- * value:(undefined|cvox.Spannable)}|Object=} opt_override Override a
- * specific property for the given node.
- * @return {!cvox.Spannable} The string representation.
- */
-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 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 = Msgs.getMsg(roleMsg + '_brl') ||
- Msgs.getMsg(roleMsg);
- }
-
- var templated = new cvox.Spannable();
- var mapChar = function(c) {
- switch (c) {
- case 'n':
- return opt_override.name || cvox.BrailleUtil.getName(node);
- case 'r':
- return role;
- case 's':
- return state;
- case 'c':
- return opt_override.container ||
- cvox.BrailleUtil.getContainer(prev, node);
- case 'v':
- return opt_override.value || cvox.BrailleUtil.getValue(node);
- default:
- return c;
- }
- };
- 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,
- // 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++;
- }
- }
- return templated.trimRight();
-};
-
-
-/**
- * Creates a braille value from a string and, optionally, a selection range.
- * 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.
- * @param {number=} opt_textOffset Start offset of text.
- * @return {!cvox.Spannable} The value spannable.
- */
-cvox.BrailleUtil.createValue = function(text, opt_selStart, opt_selEnd,
- opt_textOffset) {
- var spannable = new cvox.Spannable(
- 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
- // anchor (start) and focus (end). We should use that information to
- // decide where to pan the braille display.
- if (opt_selStart > opt_selEnd) {
- var temp = opt_selStart;
- opt_selStart = opt_selEnd;
- opt_selEnd = temp;
- }
-
- spannable.setSpan(new cvox.ValueSelectionSpan(), opt_selStart, opt_selEnd);
- }
- return spannable;
-};
-
-
-/**
- * Activates a position in a nav braille. Moves the caret in text fields
- * and simulates a mouse click on the node at the position.
- *
- * @param {!cvox.NavBraille} braille the nav braille representing the display
- * content that was active when the user issued the key command.
- * The annotations in the spannable are used to decide what
- * node to activate and what part of the node value (if any) to
- * move the caret to.
- * @param {number=} opt_displayPosition position of the display that the user
- * activated, relative to the start of braille.
- */
-cvox.BrailleUtil.click = function(braille, opt_displayPosition) {
- var handled = false;
- var spans = braille.text.getSpans(opt_displayPosition || 0);
- var node = spans.filter(function(n) { return n instanceof Node; })[0];
- if (node) {
- if (goog.isDef(opt_displayPosition) &&
- (cvox.DomUtil.isInputTypeText(node) ||
- node instanceof HTMLTextAreaElement)) {
- var valueSpan = spans.filter(
- function(s) {
- return s instanceof cvox.ValueSpan;
- })[0];
- if (valueSpan) {
- if (document.activeElement !== node) {
- cvox.Focuser.setFocus(node);
- }
- var cursorPosition = opt_displayPosition -
- braille.text.getSpanStart(valueSpan) +
- valueSpan.offset;
- cvox.ChromeVoxEventWatcher.setUpTextHandler();
- node.selectionStart = node.selectionEnd = cursorPosition;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- handled = true;
- }
- }
- }
- if (!handled) {
- cvox.DomUtil.clickElem(
- node || cvox.ChromeVox.navigationManager.getCurrentNode(),
- false, false, false, true);
- }
-};
-
-
-/**
- * Clamps a number so it is within the given boundaries.
- * @param {number} number The number to clamp.
- * @param {number} min The minimum value to return.
- * @param {number} max The maximum value to return.
- * @return {number} {@code number} if it is within the bounds, or the nearest
- * number within the bounds otherwise.
- * @private
- */
-cvox.BrailleUtil.clamp_ = function(number, min, max) {
- return Math.min(Math.max(number, min), max);
-};
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
deleted file mode 100644
index be935d5df48..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/braille_util_test.unitjs
+++ /dev/null
@@ -1,420 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxBrailleUtilUnitTest() {}
-
-CvoxBrailleUtilUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.BrailleUtil',
- 'cvox.CursorSelection',
- 'cvox.NavigationShifter',
- 'TestMsgs',
- ],
-
- /** @override */
- setUp: function() {
- Msgs = TestMsgs;
- },
-
- /**
- * @param {!Node} expectedParent Expected parent node.
- * @param {!Node} node Node to examine.
- * @private
- */
- assertTextNodeChildOf_: function(expectedParent, node) {
- assertEquals(Node.TEXT_NODE, node.nodeType);
- assertEquals(expectedParent, node.parentNode);
- },
-
- /**
- * Helper to retrieve braille for testing.
- * @param {!cvox.CursorSelection} prevSel Previous selection.
- * @param {!cvox.CursorSelection} sel Current selection.
- * @return {!cvox.NavBraille} Resulting braille.
- * @private
- */
- getBraille_: function(prevSel, sel) {
- return (new cvox.NavigationShifter).getBraille(prevSel, sel);
- },
-
- /**
- * Asserts that two NavBraille objects are equal, ignoring spans.
- * @param {Object} expected Expected result, should have no spans.
- * @param {cvox.NavBraille} actual Actual result.
- */
- assertBrailleEquals: function(expected, actual) {
- actual = new cvox.NavBraille({
- text: actual.text.toString(),
- startIndex: actual.startIndex,
- endIndex: actual.endIndex
- });
- assertThat(actual, eqJSON(new cvox.NavBraille(expected)));
- }
-};
-
-TEST_F('CvoxBrailleUtilUnitTest', 'BrailleName', function() {
- this.loadHtml(
- '<div id="navbar">' +
- '<a id="1" href="one.com">one</a>' +
- '<a id="2" href="two.com">two</a>' +
- '<a id="3" href="three.com">three</a>' +
- '</div>');
- var navbar = cvox.CursorSelection.fromNode($('navbar'));
- var braille = this.getBraille_(navbar, navbar);
- this.assertBrailleEquals(
- {text: 'one lnk two lnk three lnk',
- startIndex: 0,
- endIndex: 1
- }, braille);
-
- var one =
- cvox.CursorSelection.fromNode($('1').firstChild);
- braille = this.getBraille_(one, one);
- this.assertBrailleEquals(
- {text: 'one lnk two lnk three lnk',
- startIndex: 0,
- endIndex: 1
- }, braille);
-
- var two =
- cvox.CursorSelection.fromNode($('2').firstChild);
- braille = this.getBraille_(one, two);
- this.assertBrailleEquals(
- {text: 'one lnk two lnk three lnk',
- startIndex: 8,
- endIndex: 9
- }, braille);
-
- var three =
- cvox.CursorSelection.fromNode($('3').firstChild);
- braille = this.getBraille_(two, three);
- this.assertBrailleEquals(
- {text: 'one lnk two lnk three lnk',
- startIndex: 16,
- endIndex: 17
- }, braille);
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'NameTemplate', function() {
- this.loadHtml(
- '<button id="1">Submit</button>' +
- '<input id="2" type="text" aria-label="Search">'
- );
-
- var button = cvox.CursorSelection.fromNode($('1'));
-
- this.assertBrailleEquals(
- {text: 'Submit btn',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(button, button));
-
- var inputElement = $('2');
- var input = cvox.CursorSelection.fromNode(inputElement);
-
- // Note: the cursor appears where text would be typed.
- this.assertBrailleEquals(
- {text: 'Search: ed',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(input, input));
- inputElement.focus();
- this.assertBrailleEquals(
- {text: 'Search: ed',
- startIndex: 8,
- endIndex: 8
- }, this.getBraille_(input, input));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'TextField', function() {
- this.loadHtml(
- '<input id="1" type="text" aria-label="Search" value="larry">'
- );
-
- var inputElement = $('1');
- var input = cvox.CursorSelection.fromNode(inputElement);
-
- // Note: the cursor appears where text would be typed.
- // The cursor is at the beginning by default.
- this.assertBrailleEquals(
- {text: 'Search: larry ed',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(input, input));
- inputElement.focus();
- inputElement.selectionStart = 0;
- inputElement.selectionEnd = 5;
- this.assertBrailleEquals(
- {text: 'Search: larry ed',
- startIndex: 8,
- endIndex: 13
- }, this.getBraille_(input, input));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'TextFieldEmpty', function() {
- this.loadHtml(
- '<input id="1" type="text">'
- );
-
- var inputElement = $('1');
- var input = cvox.CursorSelection.fromNode($('1'));
-
- this.assertBrailleEquals(
- {text: ': ed',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(input, input));
- inputElement.focus();
- this.assertBrailleEquals(
- {text: ': ed',
- startIndex: 2,
- endIndex: 2
- }, this.getBraille_(input, input));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'TextFieldSelection', function() {
- this.loadHtml(
- '<input id="1" type="text" value="strawberry">'
- );
-
- var inputElem = $('1');
- inputElem.focus();
- var input = cvox.CursorSelection.fromNode(inputElem);
-
- // Selection.
- inputElem.selectionStart = 2;
- inputElem.selectionEnd = 5;
- this.assertBrailleEquals(
- {text: ': strawberry ed',
- startIndex: 4,
- endIndex: 7
- }, this.getBraille_(input, input));
-
- // Cursor at end.
- inputElem.selectionStart = 10;
- inputElem.selectionEnd = 10;
- this.assertBrailleEquals(
- {text: ': strawberry ed',
- startIndex: 12,
- endIndex: 12
- }, this.getBraille_(input, input));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'StateTemplate', function() {
- this.loadHtml(
- '<input id="1" type="checkbox" aria-label="Save">');
-
- var checkbox = cvox.CursorSelection.fromNode($('1'));
-
- this.assertBrailleEquals(
- {text: 'Save chk ( )',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(checkbox, checkbox));
-
- $('1').checked = true;
-
- this.assertBrailleEquals(
- {text: 'Save chk (x)',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(checkbox, checkbox));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'AccessKey', function() {
- this.loadHtml(
- '<a href="http://www.google.com" id="1" accesskey="g">Google</a>');
-
- var link = cvox.CursorSelection.fromNode($('1'));
-
- this.assertBrailleEquals(
- {text: 'Google lnk access key:g',
- startIndex: 0,
- endIndex: 1
- }, this.getBraille_(link, link));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'ContainerTemplate', function() {
- this.loadHtml(
- '<h1>' +
- '<a id="1" href="#menu">Skip To Menu</a>' +
- '</h1>'
- );
-
- var link = cvox.CursorSelection.fromNode($('1'));
-
- var navBraille = this.getBraille_(
- cvox.CursorSelection.fromBody(), link);
- this.assertBrailleEquals(
- {text: 'h1 Skip To Menu intlnk',
- startIndex: 0,
- endIndex: 1
- }, navBraille);
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'LinkSpans', function() {
- this.loadHtml('<p><a id="1" href="#1">Hello</a> from' +
- ' <a id="2" href="//www.google.com/">ChromeVox</a>');
- var link1 = $('1');
- var link2 = $('2');
- var navBraille = this.getBraille_(
- cvox.CursorSelection.fromBody(), cvox.CursorSelection.fromNode(link1));
- assertEquals('Hello intlnk from ChromeVox lnk',
- navBraille.text.toString());
- assertEquals(link1, navBraille.text.getSpan(0));
- 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);
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'NestedElements', function() {
- this.loadHtml('<h1 id="test-h1">Larry, ' +
- '<a href="#batman" id="batman-link">Sergey</a> and Eric</h1>');
- var h1 = $('test-h1');
- var link = $('batman-link');
- var navBraille = this.getBraille_(
- cvox.CursorSelection.fromBody(), cvox.CursorSelection.fromNode(h1));
- assertEquals('h1 Larry, Sergey intlnk and Eric',
- navBraille.text.toString());
- this.assertTextNodeChildOf_(h1, navBraille.text.getSpan(0));
- this.assertTextNodeChildOf_(h1, navBraille.text.getSpan(5));
- assertEquals(link, navBraille.text.getSpan(15));
- this.assertTextNodeChildOf_(h1, navBraille.text.getSpan(30));
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'GetTemplatedOverride', function() {
- assertEquals('Menu mnu',
- cvox.BrailleUtil.getTemplated(null, null,
- { 'name': 'Menu',
- 'roleMsg': 'role_menu' }).
- toString());
- assertEquals('alrt: Watch out!',
- cvox.BrailleUtil.getTemplated(null, null,
- { 'name': 'Watch out!',
- 'roleMsg': 'role_alert' }).
- toString());
- // Test all properties. role, if present, overrides roleMsg.
- assertEquals('Name Value Role State',
- cvox.BrailleUtil.getTemplated(null, null,
- { 'name': 'Name',
- 'role': 'Role',
- 'roleMsg': 'excluded',
- 'value': 'Value',
- 'state': 'State'
- }).toString());
-});
-
-
-/**
- * @export
- */
-TEST_F('CvoxBrailleUtilUnitTest', 'CreateValue', function() {
- var s;
- var valueSpan;
- var selectiponSpan;
-
- // Value without a selection.
- s = cvox.BrailleUtil.createValue('value');
- assertEquals('value', s.toString());
- 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.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.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.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.ValueSelectionSpan);
- assertEquals(0, s.getSpanStart(selectionSpan));
- assertEquals(5, s.getSpanEnd(selectionSpan));
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/buildinfo.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/buildinfo.js
deleted file mode 100644
index 47ee49d4581..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/buildinfo.js
+++ /dev/null
@@ -1,20 +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 Build info for ChromeVox.
- *
- * This file may be replaced in package.py for dev builds.
- * For releases, it is updated by hand with meaningful values.
- *
- */
-
-goog.provide('cvox.BuildInfo');
-
-/**
- * An identified for this build.
- * @type {string}
- */
-cvox.BuildInfo.build = 'development build';
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
deleted file mode 100644
index 6ba315b3fcf..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/chrome_extension_externs.js
+++ /dev/null
@@ -1,521 +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 Definitions for the Chromium extensions API used by ChromeVox.
- *
- * @externs
- */
-
-
-// TODO: Move these to //third_party/closure_compiler/externs.
-
-// 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() {};
-
-
-/**
- * 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}
- */
-chrome.automation.AutomationNode.prototype.role;
-
-
-/**
- * @type {!Object<chrome.automation.StateType, boolean>}
- */
-chrome.automation.AutomationNode.prototype.state;
-
-
-/**
- * @type {number}
- */
-chrome.automation.AutomationNode.prototype.indexInParent;
-
-
-/**
- * @type {string}
- */
-chrome.automation.AutomationNode.prototype.name;
-
-/**
- * @type {string}
- */
-chrome.automation.AutomationNode.prototype.description;
-
-
-/**
- * @type {string}
- */
-chrome.automation.AutomationNode.prototype.url;
-
-
-/**
- * @type {string}
- */
-chrome.automation.AutomationNode.prototype.docUrl;
-
-
-/**
- * @type {string}
- */
-chrome.automation.AutomationNode.prototype.value;
-
-
-/**
- * @type {number}
- */
-chrome.automation.AutomationNode.prototype.textSelStart;
-
-
-/**
- * @type {number}
- */
-chrome.automation.AutomationNode.prototype.textSelEnd;
-
-
-/**
- * @type {Array<number>}
- */
-chrome.automation.AutomationNode.prototype.wordStarts;
-
-
-/**
- * @type {Array<number>}
- */
-chrome.automation.AutomationNode.prototype.wordEnds;
-
-
-/**
- * @type {!chrome.automation.AutomationNode}
- */
-chrome.automation.AutomationNode.prototype.root;
-
-
-/**
- * @type {chrome.automation.AutomationNode}
- */
-chrome.automation.AutomationNode.prototype.firstChild;
-
-
-/**
- * @type {chrome.automation.AutomationNode}
- */
-chrome.automation.AutomationNode.prototype.lastChild;
-
-
-/**
- * @type {chrome.automation.AutomationNode}
- */
-chrome.automation.AutomationNode.prototype.nextSibling;
-
-
-/**
- * @type {chrome.automation.AutomationNode}
- */
-chrome.automation.AutomationNode.prototype.previousSibling;
-
-
-/**
- * @type {chrome.automation.AutomationNode}
- */
-chrome.automation.AutomationNode.prototype.parent;
-
-
-/**
- * @type {!Array<chrome.automation.AutomationNode>}
- */
-chrome.automation.AutomationNode.prototype.children;
-
-
-/**
- * @type {{top: number, left: number, height: number, width: number}}
- */
-chrome.automation.AutomationNode.prototype.location;
-
-
-/**
- * @param {chrome.automation.EventType} eventType
- * @param {function(!chrome.automation.AutomationEvent) : void} callback
- * @param {boolean} capture
- */
-chrome.automation.AutomationNode.prototype.addEventListener =
- function(eventType, callback, capture) {};
-
-
-/**
- * @param {chrome.automation.EventType} eventType
- * @param {function(chrome.automation.AutomationNode) : void} callback
- * @param {boolean} capture
- */
-chrome.automation.AutomationNode.prototype.removeEventListener =
- function(eventType, callback, capture) {};
-
-
-/**
- * @type {chrome.automation.AutomationNode}
- */
-chrome.automation.TreeChange.prototype.target;
-
-
-/**
- * @type {chrome.automation.TreeChangeType}
- */
-chrome.automation.TreeChange.prototype.type;
-
-
-/**
- * @param {function(chrome.automation.TreeChange) : void}
- * callback
- */
-chrome.automation.AutomationNode.prototype.addTreeChangeObserver =
- function(callback) {};
-
-
-/**
- * @param {function(chrome.automation.TreeChange) : void}
- * callback
- */
-chrome.automation.AutomationNode.prototype.removeTreeChangeObserver =
- function(callback) {};
-
-
-chrome.automation.AutomationNode.prototype.doDefault = function() {};
-
-
-chrome.automation.AutomationNode.prototype.focus = function() {};
-
-
-chrome.automation.AutomationNode.prototype.showContextMenu = function() {};
-
-
-/**
- * @param {number} start
- * @param {number} end
- */
-chrome.automation.AutomationNode.prototype.setSelection =
- function(start, end) {};
-
-
-/** @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;
-
-
-/**
- * @param {Object} findParams
- */
-chrome.automation.AutomationNode.prototype.find = function(findParams) {};
-
-/**
- * @type {string}
- */
-chrome.automation.AutomationNode.prototype.inputType;
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
deleted file mode 100644
index 88bfbc54a59..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
+++ /dev/null
@@ -1,290 +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 Defines a global object. The initialization of this
- * object happens in init.js.
- *
- */
-
-goog.provide('cvox.ChromeVox');
-
-// Forward declarations.
-// TODO (stoarca): Put these in a separate file and pass that
-// into the build system instead of having it here. This will allow
-// us to group all of the forward declarations for each file without
-// having them overwrite the mapping in deps.js
-goog.addDependency(
- '../host/interface/abstract_host.js',
- ['cvox.AbstractHost'],
- []);
-
-goog.addDependency(
- '../host/interface/tts_interface.js',
- ['cvox.TtsInterface'],
- []);
-
-goog.addDependency(
- '../host/interface/braille_interface.js',
- ['cvox.BrailleInterface'],
- []);
-
-goog.addDependency(
- '../host/interface/mathjax_interface.js',
- ['cvox.MathJaxInterface'],
- []);
-
-goog.addDependency(
- '../chromevox/messages/msgs.js',
- ['Msgs'],
- []);
-
-goog.addDependency(
- '../host/interface/abstract_earcons.js',
- ['cvox.AbstractEarcons'],
- []);
-
-goog.addDependency(
- '../chromevox/common/key_sequence.js',
- ['cvox.KeySequence'],
- []);
-
-goog.addDependency(
- '../chromevox/injected/navigation_manager.js',
- ['cvox.NavigationManager'],
- []);
-
-goog.addDependency(
- '../chromevox/injected/serializer.js',
- ['cvox.Serializer'],
- []);
-
-// Constants
-/**
- * Constant for verbosity setting (cvox.ChromeVox.verbosity).
- * @const
- * @type {number}
- */
-cvox.VERBOSITY_VERBOSE = 0;
-/**
- * Constant for verbosity setting (cvox.ChromeVox.verbosity).
- * @const
- * @type {number}
- */
-cvox.VERBOSITY_BRIEF = 1;
-
-
-/**
- * @constructor
- */
-cvox.ChromeVox = function() {};
-
-/**
- * @type {cvox.AbstractHost}
- */
-cvox.ChromeVox.host = null;
-/**
- * @type {cvox.TtsInterface}
- */
-cvox.ChromeVox.tts;
-/**
- * @type {cvox.BrailleInterface}
- */
-cvox.ChromeVox.braille;
-/**
- * @type {cvox.MathJaxInterface}
- */
-cvox.ChromeVox.mathJax;
-/**
- * @type {boolean}
- */
-cvox.ChromeVox.isActive = true;
-/**
- * @type {?string}
- */
-cvox.ChromeVox.version = null;
-/**
- * @type {cvox.AbstractEarcons}
- */
-cvox.ChromeVox.earcons = null;
-/**
- * @type {cvox.NavigationManager}
- */
-cvox.ChromeVox.navigationManager = null;
-/**
- * @type {cvox.Serializer}
- */
-cvox.ChromeVox.serializer = null;
-/**
- * This indicates whether or not the sticky mode pref is toggled on.
- * Use cvox.ChromeVox.isStickyModeOn() to test if sticky mode is enabled
- * either through the pref or due to being temporarily toggled on.
- * @type {boolean}
- */
-cvox.ChromeVox.isStickyPrefOn = false;
-/**
- * If set to true or false, this value overrides cvox.ChromeVox.isStickyPrefOn
- * temporarily - in order to temporarily enable sticky mode while doing
- * 'read from here' or to temporarily disable it while using a widget.
- * @type {?boolean}
- */
-cvox.ChromeVox.stickyOverride = null;
-/**
- * @type {boolean}
- */
-cvox.ChromeVox.keyPrefixOn = false;
-/**
- * Verbosity setting.
- * See: cvox.VERBOSITY_VERBOSE and cvox.VERBOSITY_BRIEF
- * @type {number}
- */
-cvox.ChromeVox.verbosity = cvox.VERBOSITY_VERBOSE;
-/**
- * @type {number}
- */
-cvox.ChromeVox.typingEcho = 0;
-/**
- * Echoing on key press events.
- * @type {Object<boolean>}
- */
-cvox.ChromeVox.keyEcho = {};
-/**
- * @type {Object<{x:number, y:number}>}
- */
-cvox.ChromeVox.position = {};
-/**
- * @type {boolean}
- */
-cvox.ChromeVox.isChromeOS = navigator.userAgent.indexOf('CrOS') != -1;
-/**
- * @type {boolean}
- */
-cvox.ChromeVox.isMac = navigator.platform.indexOf('Mac') != -1;
-/**
- * @type {string}
- */
-cvox.ChromeVox.modKeyStr;
-if (cvox.ChromeVox.isChromeOS) {
- cvox.ChromeVox.modKeyStr = 'Shift+Search';
-} else if (cvox.ChromeVox.isMac) {
- cvox.ChromeVox.modKeyStr = 'Ctrl+Cmd';
-} else {
- cvox.ChromeVox.modKeyStr = 'Shift+Alt';
-}
-/**
- * If any of these keys is pressed with the modifier key, we go in sequence mode
- * 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>}
- */
-cvox.ChromeVox.sequenceSwitchKeyCodes = [];
-/** @type {Object<boolean>} */
-cvox.ChromeVox.visitedUrls = {};
-/**
- * This function can be called before doing an operation that may trigger
- * focus events and other events that would normally be announced. This
- * tells the event manager that these events should be ignored, they're
- * a result of another command that's already announced them. This is
- * a temporary state that's automatically reverted after a few milliseconds,
- * there's no way to explicitly "un-mark".
- * @type {Function}
- */
-cvox.ChromeVox.markInUserCommand = function() {};
-/**
- * Synchronizes ChromeVox's internal cursor to the targetNode.
- * @param {Node} targetNode The node that ChromeVox should be synced to.
- * @param {boolean=} speakNode If true, speaks out the node.
- * @param {number=} opt_queueMode The queue mode to use for speaking.
- */
-cvox.ChromeVox.syncToNode = function(
- targetNode, speakNode, opt_queueMode) {};
-
-/**
- * Speaks the given node.
- * @param {Node} targetNode The node that ChromeVox should be synced to.
- * @param {number=} queueMode The queue mode to use for speaking.
- * @param {Object=} properties Speech properties to use for this utterance.
- */
-cvox.ChromeVox.speakNode = function(targetNode, queueMode, properties) {};
-
-/**
- * Provide a way for modules that can't depend on cvox.ChromeVoxUserCommands
- * to execute commands.
- *
- * @param {string} commandName The command name as a string.
- */
-cvox.ChromeVox.executeUserCommand = function(commandName) {};
-
-/**
- * True if the document body has aria-hidden='true' when we first load.
- * ChromeVox will disallow any navigation and not eat any keystrokes.
- * @type {boolean}
- */
-cvox.ChromeVox.entireDocumentIsHidden = false;
-
-/**
- * Stores state variables in a provided object.
- *
- * @param {Object} store The object.
- */
-cvox.ChromeVox.storeOn = function(store) {
- store['isStickyPrefOn'] = cvox.ChromeVox.isStickyPrefOn;
- cvox.ChromeVox.navigationManager.storeOn(store);
-};
-
-/**
- * Updates the object with state variables from an earlier storeOn call.
- *
- * @param {Object} store The object.
- */
-cvox.ChromeVox.readFrom = function(store) {
- cvox.ChromeVox.isStickyPrefOn = store['isStickyPrefOn'];
- cvox.ChromeVox.navigationManager.readFrom(store);
-};
-
-/**
- * Returns whether sticky mode is on, taking both the global sticky mode
- * pref and the temporary sticky mode override into account.
- *
- * @return {boolean} Whether sticky mode is on.
- */
-cvox.ChromeVox.isStickyModeOn = function() {
- if (cvox.ChromeVox.stickyOverride !== null) {
- return cvox.ChromeVox.stickyOverride;
- } else {
- return cvox.ChromeVox.isStickyPrefOn;
- }
-};
-
-/**
- * Shortcut for document.getElementById.
- * @param {string} id of the element.
- * @return {HTMLElement} with the id.
- */
-function $(id) {
- return document.getElementById(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
deleted file mode 100644
index 96c78ca9f31..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js
+++ /dev/null
@@ -1,368 +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.
-
-goog.provide('cvox.ChromeVoxJSON');
-
-
-/**
- * @fileoverview A simple wrapper around the JSON APIs.
- * If it is possible to use the browser's built in native JSON, then
- * cvox.ChromeVoxJSON is the same as JSON.
- * If the page has its own version of JSON, cvox.ChromeVoxJSON will use its
- * own implementation (rather than the version of JSON on the page
- * which may be outdated/broken).
- */
-
-if (!cvox.ChromeVoxJSON) {
- /** Placeholder object. */
- cvox.ChromeVoxJSON = {};
-}
-
-if (window.JSON && window.JSON.toString() == '[object JSON]') {
- cvox.ChromeVoxJSON = window.JSON;
-} else {
- /*
- * JSON implementation renamed to cvox.ChromeVoxJSON.
- * This only gets called if the page has its own version of JSON.
- *
- * Based on:
- * http://www.JSON.org/json2.js
- * 2010-03-20
- *
- * Public Domain.
- *
- * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
- *
- * See http://www.JSON.org/js.html
- */
- (function() {
- function f(n) {
- // Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
- }
-
- if (typeof Date.prototype.toJSON !== 'function') {
-
- Date.prototype.toJSON = function(key) {
-
- return isFinite(this.valueOf()) ?
- this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z' : 'null';
- };
-
- String.prototype.toJSON =
- Number.prototype.toJSON =
- Boolean.prototype.toJSON = function(key) {
- return /** @type {string} */ (this.valueOf());
- };
- }
-
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- gap,
- indent,
- meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- },
- rep;
-
-
- function quote(string) {
-
- // If the string contains no control characters, no quote characters, and
- // no backslash characters, then we can safely slap some quotes around it.
- // Otherwise we must also replace the offending characters with safe
- // escape sequences.
-
- escapable.lastIndex = 0;
- return escapable.test(string) ?
- '"' + string.replace(escapable, function(a) {
- var c = meta[a];
- return typeof c === 'string' ? c :
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- }) + '"' :
- '"' + string + '"';
- }
-
-
- function str(key, holder) {
-
- // Produce a string from holder[key].
-
- var i, // The loop counter.
- k, // The member key.
- v, // The member value.
- length,
- mind = gap,
- partial,
- value = holder[key];
-
- // If the value has a toJSON method, call it to obtain a replacement
- // value.
-
- if (value && typeof value === 'object' &&
- typeof value.toJSON === 'function') {
- value = value.toJSON(key);
- }
-
- // If we were called with a replacer function, then call the replacer to
- // obtain a replacement value.
-
- if (typeof rep === 'function') {
- value = rep.call(holder, key, value);
- }
-
- // What happens next depends on the value's type.
-
- switch (typeof value) {
- case 'string':
- return quote(value);
-
- case 'number':
- // JSON numbers must be finite. Encode non-finite numbers as null.
- return isFinite(value) ? String(value) : 'null';
-
- case 'boolean':
- case 'null':
- // If the value is a boolean or null, convert it to a string. Note:
- // typeof null does not produce 'null'. The case is included here in
- // the remote chance that this gets fixed someday.
- return String(value);
-
- // If the type is 'object', we might be dealing with an object or an
- // array or null.
-
- case 'object':
-
- // Due to a specification blunder in ECMAScript, typeof null is
- // 'object', so watch out for that case.
-
- if (!value) {
- return 'null';
- }
-
- // Make an array to hold the partial results of stringifying this
- // object value.
-
- gap += indent;
- partial = [];
-
- // Is the value an array?
-
- if (Object.prototype.toString.apply(value) === '[object Array]') {
-
- // The value is an array. Stringify every element. Use null as a
- // placeholder for non-JSON values.
-
- length = value.length;
- for (i = 0; i < length; i += 1) {
- partial[i] = str(i, value) || 'null';
- }
-
- // Join all of the elements together, separated with commas, and
- // wrap them in brackets.
-
- v = partial.length === 0 ? '[]' :
- gap ? '[\n' + gap +
- partial.join(',\n' + gap) + '\n' +
- mind + ']' :
- '[' + partial.join(',') + ']';
- gap = mind;
- return v;
- }
-
- // If the replacer is an array, use it to select the members to be
- // stringified.
-
- if (rep && typeof rep === 'object') {
- length = rep.length;
- for (i = 0; i < length; i += 1) {
- k = rep[i];
- if (typeof k === 'string') {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- } else {
-
- // Otherwise, iterate through all of the keys in the object.
- for (k in value) {
- if (Object.hasOwnProperty.call(value, k)) {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- }
-
- // Join all of the member texts together, separated with commas,
- // and wrap them in braces.
-
- v = partial.length === 0 ? '{}' :
- gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
- mind + '}' : '{' + partial.join(',') + '}';
- gap = mind;
- return v;
- }
- }
-
- // If the JSON object does not yet have a stringify method, give it one.
-
- if (typeof cvox.ChromeVoxJSON.stringify !== 'function') {
- /**
- * @param {*} value Input object.
- * @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.
- */
- cvox.ChromeVoxJSON.stringify = function(value, replacer, space) {
-
- // The stringify method takes a value and an optional replacer, and an
- // optional space parameter, and returns a JSON text. The replacer can
- // be a function that can replace values, or an array of strings that
- // will select the keys. A default replacer method can be provided. Use
- // of the space parameter can produce text that is more easily readable.
-
- var i;
- gap = '';
- indent = '';
-
- // If the space parameter is a number, make an indent string containing
- // that many spaces.
-
- if (typeof space === 'number') {
- for (i = 0; i < space; i += 1) {
- indent += ' ';
- }
-
- // If the space parameter is a string, it will be used as the indent
- // string.
-
- } else if (typeof space === 'string') {
- indent = space;
- }
-
- // If there is a replacer, it must be a function or an array.
- // Otherwise, throw an error.
-
- rep = replacer;
- if (replacer && typeof replacer !== 'function' &&
- (typeof replacer !== 'object' ||
- typeof replacer.length !== 'number')) {
- throw new Error('JSON.stringify');
- }
-
- // Make a fake root object containing our value under the key of ''.
- // Return the result of stringifying the value.
-
- return str('', {'': value});
- };
- }
-
-
- // If the JSON object does not yet have a parse method, give it one.
-
- if (typeof cvox.ChromeVoxJSON.parse !== 'function') {
- /**
- * @param {string} text The string to parse.
- * @param {(function(string, *) : *|null)=} reviver Reviver function.
- * @return {*} The JSON object.
- */
- cvox.ChromeVoxJSON.parse = function(text, reviver) {
-
- // The parse method takes a text and an optional reviver function, and
- // returns a JavaScript value if the text is a valid JSON text.
-
- var j;
-
- function walk(holder, key) {
-
- // The walk method is used to recursively walk the resulting structure
- // so that modifications can be made.
-
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }
-
-
- // Parsing happens in four stages. In the first stage, we replace
- // certain Unicode characters with escape sequences. JavaScript handles
- // many characters incorrectly, either silently deleting them, or
- // treating them as line endings.
-
- text = String(text);
- cx.lastIndex = 0;
- if (cx.test(text)) {
- text = text.replace(cx, function(a) {
- return '\\u' +
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- });
- }
-
- // In the second stage, we run the text against regular expressions that
- // look for non-JSON patterns. We are especially concerned with '()' and
- // 'new' because they can cause invocation, and '=' because it can cause
- // mutation. But just to be safe, we want to reject all unexpected
- // forms.
- // We split the second stage into 4 regexp operations in order to work
- // around crippling inefficiencies in IE's and Safari's regexp engines.
- // First we replace the JSON backslash pairs with '@' (a non-JSON
- // character). Second, we replace all simple value tokens with ']'
- // characters. Third, we delete all open brackets that follow a colon or
- // comma or that begin the text. Finally, we look to see that the
- // remaining characters are only whitespace or ']' or ',' or ':' or '{'
- // or '}'. If that is so, then the text is safe for eval.
-
- if (/^[\],:{}\s]*$/.
- test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
- replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
- replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
- // In the third stage we use the eval function to compile the text
- // into a JavaScript structure. The '{' operator is subject to a
- // syntactic ambiguity in JavaScript: it can begin a block or an
- // object literal. We wrap the text in parens to eliminate the
- // ambiguity.
-
- j = eval('(' + text + ')');
-
- // In the optional fourth stage, we recursively walk the new
- // structure, passing each name/value pair to a reviver function for
- // possible transformation.
- return typeof reviver === 'function' ? walk({'': j}, '') : j;
- }
-
- // If the text is not JSON parseable, then a SyntaxError is thrown.
-
- throw new SyntaxError('JSON.parse');
- };
- }
- }());
-}
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js
deleted file mode 100644
index 05e02731933..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store.js
+++ /dev/null
@@ -1,784 +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 This class acts as the persistent store for all static data
- * about commands.
- *
- * This store can safely be used within either a content or background script
- * context.
- *
- * If you are looking to add a user command, follow the below steps for best
- * integration with existing components:
- * 1. Add a command below in cvox.CommandStore.CMD_WHITELIST. Pick a
- * programmatic name and fill in each of the relevant JSON keys.
- * Be sure to add a msg id and define it in chromevox/messages/messages.js which
- * describes the command. Please also add a category msg id so that the command
- * will show up in the options page.
- * 2. Add the command's logic to cvox.UserCommands inside of our switch-based
- * dispatch method (doCommand_).
- * 3. Add a key binding in chromevox/background/keymaps/classic_keymap.json and
- * chromevox/background/keymaps/flat_keymap.json.
- *
- * Class description:
- * This class is entirely static and holds a JSON structure that stores
- * commands and their associated metadata.
- *
- * From this metadata, we compute relevant subsets of data such as all present
- * categories.
- */
-
-
-goog.provide('cvox.CommandStore');
-
-goog.require('cvox.PlatformFilter');
-
-
-/**
- * Returns all of the categories in the store as an array.
- * @return {Array<string>} The collection of categories.
- */
-cvox.CommandStore.categories = function() {
- var categorySet = {};
- for (var cmd in cvox.CommandStore.CMD_WHITELIST) {
- var struct = cvox.CommandStore.CMD_WHITELIST[cmd];
- if (struct.category) {
- categorySet[struct.category] = true;
- }
- }
- var ret = [];
- for (var category in categorySet) {
- ret.push(category);
- }
- return ret;
-};
-
-
-/**
- * Gets a message given a command.
- * @param {string} command The command to query.
- * @return {string|undefined} The message id, if any.
- */
-cvox.CommandStore.messageForCommand = function(command) {
- return (cvox.CommandStore.CMD_WHITELIST[command] || {}).msgId;
-};
-
-
-/**
- * Gets a category given a command.
- * @param {string} command The command to query.
- * @return {string|undefined} The command, if any.
- */
-cvox.CommandStore.categoryForCommand = function(command) {
- return (cvox.CommandStore.CMD_WHITELIST[command] || {}).category;
-};
-
-
-/**
- * Gets all commands for a category.
- * @param {string} category The category to query.
- * @return {Array<string>} The commands, if any.
- */
-cvox.CommandStore.commandsForCategory = function(category) {
- var ret = [];
- for (var cmd in cvox.CommandStore.CMD_WHITELIST) {
- var struct = cvox.CommandStore.CMD_WHITELIST[cmd];
- if (category == struct.category) {
- ret.push(cmd);
- }
- }
- return ret;
-};
-
-
-/**
- * List of commands and their properties
- * @type {Object<{forward: (undefined|boolean),
- * backward: (undefined|boolean),
- * announce: boolean,
- * category: (undefined|string),
- * findNext: (undefined|string),
- * doDefault: (undefined|boolean),
- * msgId: (undefined|string),
- * nodeList: (undefined|string),
- * platformFilter: (undefined|cvox.PlatformFilter),
- * skipInput: (undefined|boolean),
- * allowEvents: (undefined|boolean),
- * disallowContinuation: (undefined|boolean)}>}
- * forward: Whether this command points forward.
- * backward: Whether this command points backward. If neither forward or
- * backward are specified, it stays facing in the current direction.
- * announce: Whether to call finishNavCommand and announce the current
- * position after the command is done.
- * findNext: The id from the map above if this command is used for
- * finding next/previous of something.
- * category: The message resource describing the command's category.
- * doDefault: Whether to do the default action. This means that keys will be
- * passed through to the usual DOM capture/bubble phases.
- * msgId: The message resource describing the command.
- * nodeList: The id from the map above if this command is used for
- * showing a list of nodes.
- * platformFilter: Specifies to which platforms this command applies. If left
- * undefined, the command applies to all platforms.
- * skipInput: Explicitly skips this command when text input has focus.
- * Defaults to false.
- * disallowOOBE: Explicitly disallows this command when on chrome://oobe/*.
- * Defaults to false.
- * allowEvents: Allows EventWatcher to continue processing events which can
- * trump TTS.
- * disallowContinuation: Disallows continuous read to proceed. Defaults to
- * false.
- */
-cvox.CommandStore.CMD_WHITELIST = {
- 'toggleStickyMode': {announce: false,
- msgId: 'toggle_sticky_mode',
- 'disallowOOBE': true,
- category: 'modifier_keys'},
- 'toggleKeyPrefix': {announce: false,
- skipInput: true,
- msgId: 'prefix_key',
- 'disallowOOBE': true,
- category: 'modifier_keys'},
- 'passThroughMode': {announce: false,
- msgId: 'pass_through_key_description',
- category: 'modifier_keys'},
-
- 'stopSpeech': {announce: false,
- disallowContinuation: true,
- doDefault: true,
- msgId: 'stop_speech_key',
- category: 'controlling_speech'},
- 'toggleChromeVox': {announce: false,
- platformFilter: cvox.PlatformFilter.WML,
- msgId: 'toggle_chromevox_active',
- category: 'controlling_speech'},
- 'decreaseTtsRate': {announce: false,
- msgId: 'decrease_tts_rate',
- category: 'controlling_speech'},
- 'increaseTtsRate': {announce: false,
- msgId: 'increase_tts_rate',
- category: 'controlling_speech'},
- 'decreaseTtsPitch': {announce: false,
- msgId: 'decrease_tts_pitch',
- category: 'controlling_speech'},
- 'increaseTtsPitch': {announce: false,
- msgId: 'increase_tts_pitch',
- category: 'controlling_speech'},
- 'decreaseTtsVolume': {announce: false,
- msgId: 'decrease_tts_volume',
- category: 'controlling_speech'},
- 'increaseTtsVolume': {announce: false,
- msgId: 'increase_tts_volume',
- category: 'controlling_speech'},
- 'cyclePunctuationEcho': {announce: false,
- msgId: 'cycle_punctuation_echo',
- category: 'controlling_speech'},
- 'cycleTypingEcho': {announce: false,
- msgId: 'cycle_typing_echo',
- category: 'controlling_speech'},
-
-
- 'toggleEarcons': {announce: true,
- msgId: 'toggle_earcons',
- category: 'controlling_speech'},
-
- 'handleTab': {
- allowEvents: true,
- msgId: 'handle_tab_next',
- disallowContinuation: true,
- category: 'navigation'},
- 'handleTabPrev': {
- allowEvents: true,
- msgId: 'handle_tab_prev',
- disallowContinuation: true,
- category: 'navigation'},
- 'forward': {forward: true,
- announce: true,
- msgId: 'forward',
- category: 'navigation'},
- 'backward': {backward: true,
- announce: true,
- msgId: 'backward',
- category: 'navigation'},
- 'right': {forward: true,
- announce: true,
- msgId: 'right',
- category: 'navigation'},
- 'left': {backward: true,
- announce: true,
- msgId: 'left',
- category: 'navigation'},
- 'previousGranularity': {announce: true,
- msgId: 'previous_granularity',
- category: 'navigation'},
- 'nextGranularity': {announce: true,
- msgId: 'next_granularity',
- category: 'navigation'},
-
- 'previousCharacter': {backward: true,
- announce: true,
- msgId: 'previous_character',
- skipInput: true,
- category: 'navigation'},
- 'nextCharacter': {forward: true,
- announce: true,
- msgId: 'next_character',
- skipInput: true,
- category: 'navigation'},
- 'previousWord': {backward: true,
- announce: true,
- msgId: 'previous_word',
- skipInput: true,
- category: 'navigation'},
- 'nextWord': {forward: true,
- announce: true,
- msgId: 'next_word',
- skipInput: true,
- category: 'navigation'},
- 'previousLine': {backward: true,
- announce: true,
- msgId: 'previous_line',
- category: 'navigation'},
- 'nextLine': {forward: true,
- announce: true,
- msgId: 'next_line',
- category: 'navigation'},
- 'previousSentence': {backward: true,
- announce: true,
- msgId: 'previous_sentence',
- skipInput: true,
- category: 'navigation'},
- 'nextSentence': {forward: true,
- announce: true,
- msgId: 'next_sentence',
- skipInput: true,
- category: 'navigation'},
- 'previousObject': {backward: true,
- announce: true,
- msgId: 'previous_object',
- skipInput: true,
- category: 'navigation'},
- 'nextObject': {forward: true,
- announce: true,
- msgId: 'next_object',
- skipInput: true,
- category: 'navigation'},
- 'previousGroup': {backward: true,
- announce: true,
- msgId: 'previous_group',
- skipInput: true,
- category: 'navigation'},
- 'nextGroup': {forward: true,
- announce: true,
- msgId: 'next_group',
- skipInput: true,
- category: 'navigation'},
-
- 'jumpToTop': {forward: true,
- announce: true,
- msgId: 'jump_to_top',
- category: 'navigation'
-},
- 'jumpToBottom': {backward: true,
- announce: true,
- msgId: 'jump_to_bottom',
- category: 'navigation'},
- // Intentionally uncategorized.
- 'moveToStartOfLine': {forward: true, announce: true},
- 'moveToEndOfLine': {backward: true, announce: true},
-
- 'readFromHere': {forward: true,
- announce: false,
- msgId: 'read_from_here',
- category: 'navigation'},
-
- 'performDefaultAction': {disallowContinuation: true,
- msgId: 'perform_default_action',
- doDefault: true,
- skipInput: true,
- category: 'navigation'},
- 'forceClickOnCurrentItem': {announce: true,
- disallowContinuation: true,
- allowEvents: true,
- msgId: 'force_click_on_current_item',
- category: 'navigation'},
- 'forceDoubleClickOnCurrentItem': {announce: true,
- allowEvents: true,
- disallowContinuation: true},
-
- 'readLinkURL': {announce: false,
- msgId: 'read_link_url',
- category: 'information'},
- 'readCurrentTitle': {announce: false,
- msgId: 'read_current_title',
- category: 'information'},
- 'readCurrentURL': {announce: false,
- msgId: 'read_current_url',
- category: 'information'},
-
- 'fullyDescribe': {announce: false,
- msgId: 'fully_describe',
- category: 'information'},
- 'speakTimeAndDate': {announce: false,
- msgId: 'speak_time_and_date',
- category: 'information'},
- 'toggleSelection': {announce: true,
- msgId: 'toggle_selection',
- category: 'information'},
-
- 'toggleSearchWidget': {announce: false,
- disallowContinuation: true,
- msgId: 'toggle_search_widget',
- category: 'information'},
-
- 'toggleKeyboardHelp': {announce: false,
- disallowContinuation: true,
- msgId: 'show_power_key',
- category: 'help_commands'},
- 'help': {announce: false,
- msgId: 'help',
- 'disallowOOBE': true,
- disallowContinuation: true,
- category: 'help_commands'},
- 'contextMenu': {announce: false,
- disallowContinuation: true},
-
- 'showOptionsPage': {announce: false,
- disallowContinuation: true,
- msgId: 'show_options_page',
- 'disallowOOBE': true,
- category: 'help_commands'},
- 'showKbExplorerPage': {announce: false,
- disallowContinuation: true,
- msgId: 'show_kb_explorer_page',
- 'disallowOOBE': true,
- category: 'help_commands'},
-
-
- 'showFormsList': {announce: false,
- disallowContinuation: true,
- nodeList: 'formField',
- msgId: 'show_forms_list',
- category: 'overview'},
- 'showHeadingsList': {announce: false, nodeList: 'heading',
- disallowContinuation: true,
- msgId: 'show_headings_list',
- category: 'overview'},
- 'showLandmarksList': {announce: false, nodeList: 'landmark',
- disallowContinuation: true,
- msgId: 'show_landmarks_list',
- category: 'overview'},
- 'showLinksList': {announce: false, nodeList: 'link',
- disallowContinuation: true,
- msgId: 'show_links_list',
- category: 'overview'},
- 'showTablesList': {announce: false, nodeList: 'table',
- disallowContinuation: true,
- msgId: 'show_tables_list',
- category: 'overview'},
-
- 'nextArticle': {forward: true,
- findNext: 'article'},
-
- 'nextButton': {forward: true,
- findNext: 'button',
- msgId: 'next_button',
- category: 'jump_commands'},
- 'nextCheckbox': {forward: true,
- findNext: 'checkbox',
- msgId: 'next_checkbox',
- category: 'jump_commands'},
- 'nextComboBox': {forward: true,
- findNext: 'combobox',
- msgId: 'next_combo_box',
- category: 'jump_commands'},
- 'nextControl': {forward: true, findNext: 'control'},
- 'nextEditText': {forward: true,
- findNext: 'editText',
- msgId: 'next_edit_text',
- category: 'jump_commands'},
- 'nextFormField': {forward: true,
- findNext: 'formField',
- msgId: 'next_form_field',
- category: 'jump_commands'},
- 'nextGraphic': {forward: true,
- findNext: 'graphic',
- msgId: 'next_graphic',
- category: 'jump_commands'},
- 'nextHeading': {forward: true,
- findNext: 'heading',
- msgId: 'next_heading',
- category: 'jump_commands'},
- 'nextHeading1': {forward: true,
- findNext: 'heading1',
- msgId: 'next_heading1',
- category: 'jump_commands'},
- 'nextHeading2': {forward: true,
- findNext: 'heading2',
- msgId: 'next_heading2',
- category: 'jump_commands'},
- 'nextHeading3': {forward: true,
- findNext: 'heading3',
- msgId: 'next_heading3',
- category: 'jump_commands'},
- 'nextHeading4': {forward: true,
- findNext: 'heading4',
- msgId: 'next_heading4',
- category: 'jump_commands'},
- 'nextHeading5': {forward: true,
- findNext: 'heading5',
- msgId: 'next_heading5',
- category: 'jump_commands'},
- 'nextHeading6': {forward: true,
- findNext: 'heading6',
- msgId: 'next_heading6',
- category: 'jump_commands'},
-
- 'nextLandmark': {forward: true,
- findNext: 'landmark',
- msgId: 'next_landmark',
- category: 'jump_commands'},
- 'nextLink': {forward: true,
- findNext: 'link',
- msgId: 'next_link',
- category: 'jump_commands'},
- 'nextList': {forward: true,
- findNext: 'list',
- msgId: 'next_list',
- category: 'jump_commands'},
- 'nextListItem': {forward: true,
- findNext: 'listItem',
- msgId: 'next_list_item',
- category: 'jump_commands'},
- 'nextMath': {forward: true,
- findNext: 'math',
- msgId: 'next_math',
- category: 'jump_commands'},
- 'nextMedia': {forward: true,
- findNext: 'media',
- msgId: 'next_media',
- category: 'jump_commands'},
- 'nextRadio': {forward: true,
- findNext: 'radio',
- msgId: 'next_radio',
- category: 'jump_commands'},
- 'nextSection': {forward: true, findNext: 'section'},
- 'nextSlider': {forward: true, findNext: 'slider'},
- 'nextTable': {forward: true,
- findNext: 'table',
- msgId: 'next_table',
- category: 'jump_commands'},
- 'nextVisitedLink': {forward: true,
- findNext: 'visitedLink',
- msgId: 'next_visited_link',
- category: 'jump_commands'},
-
-
- 'previousArticle': {backward: true,
- findNext: 'article'},
-
- 'previousButton': {backward: true,
- findNext: 'button',
- msgId: 'previous_button',
- category: 'jump_commands'},
- 'previousCheckbox': {backward: true,
- findNext: 'checkbox',
- msgId: 'previous_checkbox',
- category: 'jump_commands'},
- 'previousComboBox': {backward: true,
- findNext: 'combobox',
- msgId: 'previous_combo_box',
- category: 'jump_commands'},
- 'previousControl': {backward: true, findNext: 'control'},
- 'previousEditText': {backward: true,
- findNext: 'editText',
- msgId: 'previous_edit_text',
- category: 'jump_commands'},
- 'previousFormField': {backward: true,
- findNext: 'formField',
- msgId: 'previous_form_field',
- category: 'jump_commands'},
- 'previousGraphic': {backward: true,
- findNext: 'graphic',
- msgId: 'previous_graphic',
- category: 'jump_commands'},
- 'previousHeading': {backward: true,
- findNext: 'heading',
- msgId: 'previous_heading',
- category: 'jump_commands'},
- 'previousHeading1': {backward: true,
- findNext: 'heading1',
- msgId: 'previous_heading1',
- category: 'jump_commands'},
- 'previousHeading2': {backward: true,
- findNext: 'heading2',
- msgId: 'previous_heading2',
- category: 'jump_commands'},
- 'previousHeading3': {backward: true,
- findNext: 'heading3',
- msgId: 'previous_heading3',
- category: 'jump_commands'},
- 'previousHeading4': {backward: true,
- findNext: 'heading4',
- msgId: 'previous_heading4',
- category: 'jump_commands'},
- 'previousHeading5': {backward: true,
- findNext: 'heading5',
- msgId: 'previous_heading5',
- category: 'jump_commands'},
- 'previousHeading6': {backward: true,
- findNext: 'heading6',
- msgId: 'previous_heading6',
- category: 'jump_commands'},
-
- 'previousLandmark': {backward: true,
- findNext: 'landmark',
- msgId: 'previous_landmark',
- category: 'jump_commands'},
- 'previousLink': {backward: true,
- findNext: 'link',
- msgId: 'previous_link',
- category: 'jump_commands'},
- 'previousList': {backward: true,
- findNext: 'list',
- msgId: 'previous_list',
- category: 'jump_commands'},
- 'previousListItem': {backward: true,
- findNext: 'listItem',
- msgId: 'previous_list_item',
- category: 'jump_commands'},
- 'previousMath': {backward: true,
- findNext: 'math',
- msgId: 'previous_math',
- category: 'jump_commands'},
- 'previousMedia': {backward: true,
- findNext: 'media',
- msgId: 'previous_media',
- category: 'jump_commands'},
- 'previousRadio': {backward: true,
- findNext: 'radio',
- msgId: 'previous_radio',
- category: 'jump_commands'},
- 'previousSection': {backward: true, findNext: 'section'},
- 'previousSlider': {backward: true, findNext: 'slider'},
- 'previousTable': {backward: true,
- findNext: 'table',
- msgId: 'previous_table',
- category: 'jump_commands'},
- 'previousVisitedLink': {backward: true,
- findNext: 'visitedLink',
- msgId: 'previous_visited_link',
- category: 'jump_commands'},
-
-
- // Table Actions.
- 'announceHeaders': {announce: false,
- msgId: 'announce_headers',
- category: 'tables'},
- 'speakTableLocation': {announce: false,
- msgId: 'speak_table_location',
- category: 'tables'},
- 'goToFirstCell': {announce: true,
- msgId: 'skip_to_beginning',
- category: 'tables'},
- 'goToLastCell': {announce: true,
- msgId: 'skip_to_end',
- category: 'tables'},
- 'goToRowFirstCell': {announce: true,
- msgId: 'skip_to_row_beginning',
- category: 'tables'},
- 'goToRowLastCell': {announce: true,
- msgId: 'skip_to_row_end',
- category: 'tables'},
- 'goToColFirstCell': {announce: true,
- msgId: 'skip_to_col_beginning',
- category: 'tables'},
- 'goToColLastCell': {announce: true,
- msgId: 'skip_to_col_end',
- category: 'tables'},
- // These commands are left out of the options page because they involve
- // multiple, non-user configurable modifiers.
- 'previousRow': {backward: true, announce: true, skipInput: true},
- 'previousCol': {backward: true, announce: true, skipInput: true},
- 'nextRow': {forward: true, announce: true, skipInput: true},
- 'nextCol': {forward: true, announce: true, skipInput: true},
-
- // Generic Actions.
- 'enterShifter': {announce: true,
- msgId: 'enter_content',
- category: 'navigation'},
- 'exitShifter': {announce: true,
- msgId: 'exit_content',
- category: 'navigation'},
- 'exitShifterContent': {announce: true},
-
- 'openLongDesc': {announce: false,
- msgId: 'open_long_desc',
- category: 'information'},
-
- 'pauseAllMedia': {announce: false,
- msgId: 'pause_all_media',
- category: 'information'},
-
- // Math specific commands.
- 'toggleSemantics': {announce: false,
- msgId: 'toggle_semantics',
- category: 'information'},
-
- // Braille specific commands.
- 'routing': {announce: false,
- allowEvents: true,
- msgId: 'braille_routing',
- category: 'braille'},
- 'pan_left': {backward: true,
- announce: true,
- msgId: 'braille_pan_left',
- category: 'braille'},
- 'pan_right': {forward: true,
- announce: true,
- msgId: 'braille_pan_right',
- category: 'braille'},
- 'line_up': {backward: true,
- announce: true,
- msgId: 'braille_line_up',
- category: 'braille'},
- 'line_down': {forward: true,
- announce: true,
- msgId: 'braille_line_down',
- category: 'braille'},
- 'top': {forward: true,
- announce: true,
- msgId: 'braille_top',
- category: 'braille'},
- 'bottom': {backward: true,
- announce: true,
- msgId: 'braille_bottom',
- category: 'braille'},
-
- // Developer commands.
- 'enableConsoleTts': {announce: false,
- msgId: 'enable_tts_log',
- category: 'developer'},
- 'toggleBrailleCaptions': {announce: false,
- msgId: 'braille_captions',
- category: 'developer'},
-
- 'startHistoryRecording': {announce: false},
- 'stopHistoryRecording': {announce: false},
- 'autorunner': {announce: false},
-
- 'debug': {announce: false},
-
- 'nop': {announce: false}
-};
-
-
-/**
- * List of find next commands and their associated data.
- * @type {Object<{predicate: string,
- * forwardError: string,
- * backwardError: string}>}
- * predicate: The name of the predicate. This must be defined in DomPredicates.
- * forwardError: The message id of the error string when moving forward.
- * backwardError: The message id of the error string when moving backward.
- */
-cvox.CommandStore.NODE_INFO_MAP = {
- 'checkbox': {predicate: 'checkboxPredicate',
- forwardError: 'no_next_checkbox',
- backwardError: 'no_previous_checkbox',
- typeMsg: 'role_checkbox'},
- 'radio': {predicate: 'radioPredicate',
- forwardError: 'no_next_radio_button',
- backwardError: 'no_previous_radio_button',
- typeMsg: 'role_radio'},
- 'slider': {predicate: 'sliderPredicate',
- forwardError: 'no_next_slider',
- backwardError: 'no_previous_slider',
- typeMsg: 'role_slider'},
- 'graphic': {predicate: 'graphicPredicate',
- forwardError: 'no_next_graphic',
- backwardError: 'no_previous_graphic',
- typeMsg: 'UNUSED'},
- 'article': {predicate: 'articlePredicate',
- forwardError: 'no_next_ARTICLE',
- backwardError: 'no_previous_ARTICLE',
- typeMsg: 'TAG_ARTICLE'},
- 'button': {predicate: 'buttonPredicate',
- forwardError: 'no_next_button',
- backwardError: 'no_previous_button',
- typeMsg: 'role_button'},
- 'combobox': {predicate: 'comboBoxPredicate',
- forwardError: 'no_next_combo_box',
- backwardError: 'no_previous_combo_box',
- typeMsg: 'role_combobox'},
- 'editText': {predicate: 'editTextPredicate',
- forwardError: 'no_next_edit_text',
- backwardError: 'no_previous_edit_text',
- typeMsg: 'input_type_text'},
- 'heading': {predicate: 'headingPredicate',
- forwardError: 'no_next_heading',
- backwardError: 'no_previous_heading',
- typeMsg: 'role_heading'},
- 'heading1': {predicate: 'heading1Predicate',
- forwardError: 'no_next_heading_1',
- backwardError: 'no_previous_heading_1'},
- 'heading2': {predicate: 'heading2Predicate',
- forwardError: 'no_next_heading_2',
- backwardError: 'no_previous_heading_2'},
- 'heading3': {predicate: 'heading3Predicate',
- forwardError: 'no_next_heading_3',
- backwardError: 'no_previous_heading_3'},
- 'heading4': {predicate: 'heading4Predicate',
- forwardError: 'no_next_heading_4',
- backwardError: 'no_previous_heading_4'},
- 'heading5': {predicate: 'heading5Predicate',
- forwardError: 'no_next_heading_5',
- backwardError: 'no_previous_heading_5'},
- 'heading6': {predicate: 'heading6Predicate',
- forwardError: 'no_next_heading_6',
- backwardError: 'no_previous_heading_6'},
-
- 'link': {predicate: 'linkPredicate',
- forwardError: 'no_next_link',
- backwardError: 'no_previous_link',
- typeMsg: 'role_link'},
- 'table': {predicate: 'tablePredicate',
- forwardError: 'no_next_table',
- backwardError: 'no_previous_table',
- typeMsg: 'table_strategy'},
- 'visitedLink': {predicate: 'visitedLinkPredicate',
- forwardError: 'no_next_visited_link',
- backwardError: 'no_previous_visited_link',
- typeMsg: 'role_link'},
- 'list': {predicate: 'listPredicate',
- forwardError: 'no_next_list',
- backwardError: 'no_previous_list',
- typeMsg: 'role_list'},
- 'listItem': {predicate: 'listItemPredicate',
- forwardError: 'no_next_list_item',
- backwardError: 'no_previous_list_item',
- typeMsg: 'role_listitem'},
- 'formField': {predicate: 'formFieldPredicate',
- forwardError: 'no_next_form_field',
- backwardError: 'no_previous_form_field',
- typeMsg: 'role_form'},
- 'landmark': {predicate: 'landmarkPredicate',
- forwardError: 'no_next_landmark',
- backwardError: 'no_previous_landmark',
- typeMsg: 'role_landmark'},
- 'math': {predicate: 'mathPredicate',
- forwardError: 'no_next_math',
- backwardError: 'no_previous_math',
- typeMsg: 'math_expr'},
- 'media': {predicate: 'mediaPredicate',
- forwardError: 'no_next_media_widget',
- backwardError: 'no_previous_media_widget'},
- 'section': {predicate: 'sectionPredicate',
- forwardError: 'no_next_section',
- backwardError: 'no_previous_section'},
- 'control': {predicate: 'controlPredicate',
- forwardError: 'no_next_control',
- backwardError: 'no_previous_control'}
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store_test.unitjs
deleted file mode 100644
index 66ef0081254..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/command_store_test.unitjs
+++ /dev/null
@@ -1,73 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxCommandStoreUnitTest() {}
-
-CvoxCommandStoreUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.ChromeVoxUserCommands',
- 'cvox.CommandStore',
- ]
-};
-
-TEST_F('CvoxCommandStoreUnitTest', 'TableData', function() {
- var categories = cvox.CommandStore.categories();
- assertEquals(10, categories.length);
- assertEquals('modifier_keys', categories[0]);
- assertEquals('controlling_speech', categories[1]);
- assertEquals('navigation', categories[2]);
- assertEquals('information', categories[3]);
- assertEquals('help_commands', categories[4]);
- assertEquals('overview', categories[5]);
- assertEquals('jump_commands', categories[6]);
- assertEquals('tables', categories[7]);
-
- assertEquals('stop_speech_key',
- cvox.CommandStore.messageForCommand('stopSpeech'));
- assertEquals('controlling_speech',
- cvox.CommandStore.categoryForCommand('stopSpeech'));
-
- var controllingSpeechCmds =
- cvox.CommandStore.commandsForCategory('controlling_speech');
- assertEquals(11, controllingSpeechCmds.length);
- assertEquals('stopSpeech', controllingSpeechCmds[0]);
- assertEquals('toggleChromeVox', controllingSpeechCmds[1]);
- assertEquals('decreaseTtsRate', controllingSpeechCmds[2]);
- assertEquals('increaseTtsRate', controllingSpeechCmds[3]);
- assertEquals('decreaseTtsPitch', controllingSpeechCmds[4]);
- assertEquals('increaseTtsPitch', controllingSpeechCmds[5]);
-});
-
-
-/** Tests that undefined is returned for bad queries. */
-TEST_F('CvoxCommandStoreUnitTest', 'InvalidQueries', function() {
- assertThat(cvox.CommandStore.commandsForCategory('foo'), eqJSON([]));
- assertTrue(undefined == cvox.CommandStore.categoryForCommand('foo'));
- assertTrue(undefined == cvox.CommandStore.messageForCommand('foo'));
-});
-
-
-/** Tests the validity of every command. */
-TEST_F('CvoxCommandStoreUnitTest', 'CommandValidity', function() {
- var categories = cvox.CommandStore.categories();
- for (var i = 0; i < categories.length; i++) {
- var commands = cvox.CommandStore.commandsForCategory(categories[i]);
- for (j = 0; j < commands.length; j++) {
- var command = commands[j];
- assertEquals(command + ' function',
- command + ' ' + typeof(cvox.ChromeVoxUserCommands.commands[command]));
- }
- }
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js
deleted file mode 100644
index bba28401525..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/composite_tts.js
+++ /dev/null
@@ -1,103 +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 composite TTS sends allows ChromeVox to use
- * multiple TTS engines at the same time.
- *
- */
-
-goog.provide('cvox.CompositeTts');
-
-goog.require('cvox.TtsInterface');
-
-/**
- * A Composite Tts
- * @constructor
- * @implements {cvox.TtsInterface}
- */
-cvox.CompositeTts = function() {
- /**
- * @type {Array<cvox.TtsInterface>}
- * @private
- */
- this.ttsEngines_ = [];
-};
-
-
-/**
- * Adds a TTS engine to the composite TTS
- * @param {cvox.TtsInterface} tts The TTS to add.
- * @return {cvox.CompositeTts} this.
- */
-cvox.CompositeTts.prototype.add = function(tts) {
- this.ttsEngines_.push(tts);
- return this;
-};
-
-
-/**
- * @override
- */
-cvox.CompositeTts.prototype.speak =
- function(textString, queueMode, properties) {
- this.ttsEngines_.forEach(function(engine) {
- engine.speak(textString, queueMode, properties);
- });
-};
-
-
-/**
- * Returns true if any of the TTSes are still speaking.
- * @override
- */
-cvox.CompositeTts.prototype.isSpeaking = function() {
- return this.ttsEngines_.some(function(engine) {
- return engine.isSpeaking();
- });
-};
-
-
-/**
- * @override
- */
-cvox.CompositeTts.prototype.stop = function() {
- this.ttsEngines_.forEach(function(engine) {
- engine.stop();
- });
-};
-
-
-/**
- * @override
- */
-cvox.CompositeTts.prototype.addCapturingEventListener = function(listener) {
- this.ttsEngines_.forEach(function(engine) {
- engine.addCapturingEventListener(listener);
- });
-};
-
-
-/**
- * @override
- */
-cvox.CompositeTts.prototype.increaseOrDecreaseProperty =
- function(propertyName, increase) {
- this.ttsEngines_.forEach(function(engine) {
- engine.increaseOrDecreaseProperty(propertyName, increase);
- });
-};
-
-
-/**
- * @override
- */
-cvox.CompositeTts.prototype.getDefaultProperty = function(property) {
- for (var i = 0, engine; engine = this.ttsEngines_[i]; i++) {
- var value = engine.getDefaultProperty(property);
- if (value) {
- return value;
- }
- }
-};
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
deleted file mode 100644
index ce0d9415f0d..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor.js
+++ /dev/null
@@ -1,235 +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 Defines the ContentEditableExtractor class.
- */
-
-goog.provide('cvox.ContentEditableExtractor');
-
-goog.require('cvox.Cursor');
-goog.require('cvox.TraverseUtil');
-
-/**
- * Extracts the text and line break information from a contenteditable region.
- * @constructor
- */
-cvox.ContentEditableExtractor = function() {
- /**
- * The extracted, flattened, text.
- * @type {string}
- * @private
- */
- this.text_ = '';
-
- /**
- * The start cursor/selection index.
- * @type {number}
- * @private
- */
- this.start_ = 0;
-
- /**
- * The end cursor/selection index.
- * @type {number}
- * @private
- */
- this.end_ = 0;
-
- /**
- * Map from line index to a data structure containing the start
- * and end index within the line.
- * @type {Object<number, {startIndex: number, endIndex: number}>}
- * @private
- */
- this.lines_ = {};
-
- /**
- * Map from 0-based character index to 0-based line index.
- * @type {Array<number>}
- * @private
- */
- this.characterToLineMap_ = [];
-};
-
-/**
- * Update the metadata.
- * @param {Element} element The DOM element that's contentEditable.
- */
-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}>}
- */
- var lines = {0: {startIndex: 0, endIndex: 0}};
- var startCursor = new cvox.Cursor(element, 0, '');
- var endCursor = startCursor.clone();
- var range = document.createRange();
- var rect;
- var lineIndex = 0;
- var lastBottom = null;
- var text = '';
- var textSize = 0;
- var selectionStartIndex = -1;
- var selectionEndIndex = -1;
- var sel = window.getSelection();
- var selectionStart = new cvox.Cursor(sel.baseNode, sel.baseOffset, '');
- var selectionEnd = new cvox.Cursor(sel.extentNode, sel.extentOffset, '');
- var setStart = false;
- var setEnd = false;
- while (true) {
- var entered = [];
- var left = [];
- var c = cvox.TraverseUtil.forwardsChar(endCursor, entered, left);
- var done = false;
- if (!c) {
- done = true;
- }
- for (var i = 0; i < left.length && !done; i++) {
- if (left[i] == element) {
- done = true;
- }
- }
- if (done) {
- break;
- }
-
- range.setStart(startCursor.node, startCursor.index);
- range.setEnd(endCursor.node, endCursor.index);
- rect = range.getBoundingClientRect();
- if (!rect || rect.width == 0 || rect.height == 0) {
- continue;
- }
-
- if (lastBottom !== null &&
- rect.bottom != lastBottom &&
- textSize > 0 &&
- text.substr(-1).match(/\S/) &&
- c.match(/\S/)) {
- text += '\n';
- textSize++;
- }
-
- if (startCursor.node != endCursor.node && endCursor.index > 0) {
- range.setStart(endCursor.node, endCursor.index - 1);
- rect = range.getBoundingClientRect();
- if (!rect || rect.width == 0 || rect.height == 0) {
- continue;
- }
- }
-
- if (!setStart &&
- selectionStartIndex == -1 &&
- endCursor.node == selectionStart.node &&
- endCursor.index >= selectionStart.index) {
- if (endCursor.index > selectionStart.index) {
- selectionStartIndex = textSize;
- } else {
- setStart = true;
- }
- }
- if (!setEnd &&
- selectionEndIndex == -1 &&
- endCursor.node == selectionEnd.node &&
- endCursor.index >= selectionEnd.index) {
- if (endCursor.index > selectionEnd.index) {
- selectionEndIndex = textSize;
- } else {
- setEnd = true;
- }
- }
-
- if (lastBottom === null) {
- // This is the first character we've successfully measured on this
- // line. Save the vertical position but don't do anything else.
- lastBottom = rect.bottom;
- } else if (rect.bottom != lastBottom) {
- lines[lineIndex].endIndex = textSize;
- lineIndex++;
- lines[lineIndex] = {startIndex: textSize, endIndex: textSize};
- lastBottom = rect.bottom;
- }
- text += c;
- textSize++;
- startCursor = endCursor.clone();
-
- if (setStart) {
- selectionStartIndex = textSize;
- setStart = false;
- }
- if (setEnd) {
- selectionEndIndex = textSize;
- setEnd = false;
- }
- }
-
- // Finish up the last line.
- lines[lineIndex].endIndex = textSize;
-
- // Create a map from character index to line number.
- var characterToLineMap = [];
- for (var i = 0; i <= lineIndex; i++) {
- for (var j = lines[i].startIndex; j <= lines[i].endIndex; j++) {
- characterToLineMap[j] = i;
- }
- }
-
- // Finish updating fields.
- this.text_ = text;
- this.characterToLineMap_ = characterToLineMap;
- this.lines_ = lines;
-
- this.start_ = selectionStartIndex >= 0 ? selectionStartIndex : text.length;
- this.end_ = selectionEndIndex >= 0 ? selectionEndIndex : text.length;
-};
-
-/**
- * Get the text.
- * @return {string} The extracted, flattened, text.
- */
-cvox.ContentEditableExtractor.prototype.getText = function() {
- return this.text_;
-};
-
-/**
- * @return {number} The start cursor/selection index.
- */
-cvox.ContentEditableExtractor.prototype.getStartIndex = function() {
- return this.start_;
-};
-
-/**
- * @return {number} The end cursor/selection index.
- */
-cvox.ContentEditableExtractor.prototype.getEndIndex = function() {
- return this.end_;
-};
-
-/**
- * Get the line number corresponding to a particular index.
- * @param {number} index The 0-based character index.
- * @return {number} The 0-based line number corresponding to that character.
- */
-cvox.ContentEditableExtractor.prototype.getLineIndex = function(index) {
- return this.characterToLineMap_[index];
-};
-
-/**
- * Get the start character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the first character in this line.
- */
-cvox.ContentEditableExtractor.prototype.getLineStart = function(index) {
- return this.lines_[index].startIndex;
-};
-
-/**
- * Get the end character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the end of this line.
- */
-cvox.ContentEditableExtractor.prototype.getLineEnd = function(index) {
- return this.lines_[index].endIndex;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor_test.unitjs
deleted file mode 100644
index c5f0fa3ba57..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/content_editable_extractor_test.unitjs
+++ /dev/null
@@ -1,326 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxContentEditableExtractorUnitTest() {}
-
-CvoxContentEditableExtractorUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.ContentEditableExtractor',
- ]
-};
-
-/**
- * Helper function to set the selection
- * @param {Node} startNode The base/start node of the range.
- * @param {number} startOffset The 0-based character index of the start.
- * @param {Node} endNode The extent/end node of the range.
- * @param {number} endOffset The 0-based character index of the end.
- */
-function setSelection(startNode, startOffset, endNode, endOffset) {
- var r = document.createRange();
- r.setStart(startNode, startOffset);
- r.setEnd(endNode, endOffset);
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(r);
-}
-
-TEST_F('CvoxContentEditableExtractorUnitTest', 'EmptyElement', function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox" contentEditable="true"></div>
- </div>
- */});
-
- var textbox = $('textbox');
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('', extractor.getText());
- assertEquals(0, extractor.getStartIndex());
- assertEquals(0, extractor.getEndIndex(0));
- assertEquals(0, extractor.getLineIndex(0));
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(0, extractor.getLineEnd(0));
-});
-
-/**
- * Test getting text and selections from a single contenteditable node.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'SingleTextNode', function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox" contentEditable="true">Hello</div>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('Hello', extractor.getText());
- assertEquals(0, extractor.getLineIndex(0));
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(5, extractor.getLineEnd(0));
- assertEquals(5, extractor.getStartIndex());
- assertEquals(5, extractor.getEndIndex());
-
- // Test all possible cursor positions.
- for (var i = 0; i <= 5; i++) {
- setSelection(textbox.firstChild, i, textbox.firstChild, i);
- extractor.update(textbox);
- assertEquals(i, extractor.getStartIndex());
- assertEquals(i, extractor.getEndIndex());
- }
-
- // Test all possible ways to select one character.
- for (i = 0; i < 5; i++) {
- setSelection(textbox.firstChild, i, textbox.firstChild, i + 1);
- extractor.update(textbox);
- assertEquals(i, extractor.getStartIndex());
- assertEquals(i + 1, extractor.getEndIndex());
- }
-
- // Test selecting everything.
- setSelection(textbox.firstChild, 0, textbox.firstChild, 5);
- extractor.update(textbox);
- assertEquals(0, extractor.getStartIndex());
- assertEquals(5, extractor.getEndIndex());
-});
-
-/**
- * Test getting text and selections from a contenteditable node with
- * nonprinted whitespace.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'TextWithWhitespace',
- function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox" contentEditable="true"> Hello World </div>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('Hello World', extractor.getText());
- assertEquals(0, extractor.getLineIndex(0));
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(11, extractor.getLineEnd(0));
- assertEquals(11, extractor.getStartIndex());
- assertEquals(11, extractor.getEndIndex());
-
- // Test all *reasonable* indexes of a selection into this text node
- // and the logical index into the text that these should result in.
- var expectedIndexMap = {
- 0: 0,
- 1: 0,
- 2: 1,
- 3: 2,
- 4: 3,
- 5: 4,
- 6: 5,
- // Note: index=7 should never happen
- 8: 6,
- 9: 7,
- 10: 8,
- 11: 9,
- 12: 10,
- 13: 11,
- 14: 11
- };
- for (var srcIndex in expectedIndexMap) {
- var dstIndex = expectedIndexMap[srcIndex];
- setSelection(textbox.firstChild, srcIndex, textbox.firstChild, srcIndex);
- extractor.update(textbox);
- assertEquals(dstIndex, extractor.getStartIndex());
- assertEquals(dstIndex, extractor.getEndIndex());
- }
-});
-
-/**
- * Test getting text and selections from a contenteditable node with
- * preformatted text.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'Preformatted', function() {
- this.loadDoc(function() {/*!
- <div>
- <pre id="textbox" contentEditable="true">aaaaaaaaaa
-bbbbbbbbbb
-cccccccccc</pre>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc', extractor.getText());
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(11, extractor.getLineEnd(0));
- assertEquals(11, extractor.getLineStart(1));
- assertEquals(22, extractor.getLineEnd(1));
- assertEquals(22, extractor.getLineStart(2));
- assertEquals(32, extractor.getLineEnd(2));
-
- // Test all possible cursor positions.
- for (var i = 0; i <= 32; i++) {
- setSelection(textbox.firstChild, i, textbox.firstChild, i);
- extractor.update(textbox);
- assertEquals(i, extractor.getStartIndex());
- assertEquals(i, extractor.getEndIndex());
- }
-});
-
-/**
- * Test getting text and selections from a contenteditable node with
- * wrapping.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'WordWrap', function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox"
- style="width: 1em; word-wrap: normal"
- contentEditable="true">One two three</div>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('One\ntwo\nthree', extractor.getText());
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(4, extractor.getLineEnd(0));
- assertEquals(4, extractor.getLineStart(1));
- assertEquals(8, extractor.getLineEnd(1));
- assertEquals(8, extractor.getLineStart(2));
- assertEquals(13, extractor.getLineEnd(2));
-
- // Test all possible cursor positions.
- for (var i = 0; i <= 13; i++) {
- setSelection(textbox.firstChild, i, textbox.firstChild, i);
- extractor.update(textbox);
- assertEquals(i, extractor.getStartIndex());
- assertEquals(i, extractor.getEndIndex());
- }
-});
-
-/**
- * Test getting text and lines from a contenteditable region
- * containing two paragraphs and an explicit line break.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'TwoParas', function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox" contentEditable="true">
- <p>One</p>
- <p>Two<br>Three</p>
- </div>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('One\nTwo\nThree',
- extractor.getText());
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(4, extractor.getLineEnd(0));
- assertEquals(4, extractor.getLineStart(1));
- assertEquals(8, extractor.getLineEnd(1));
- assertEquals(8, extractor.getLineStart(2));
- assertEquals(13, extractor.getLineEnd(2));
-});
-
-/**
- * Test getting text and lines from a contenteditable region
- * containing two paragraphs, this time with added whitespace.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'TwoParasWithWhitespace',
- function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox" contentEditable="true">
- <p> One </p>
- <p> Two <br> Three </p>
- </div>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('One\nTwo Three',
- extractor.getText());
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(4, extractor.getLineEnd(0));
- assertEquals(4, extractor.getLineStart(1));
- assertEquals(8, extractor.getLineEnd(1));
- assertEquals(8, extractor.getLineStart(2));
- assertEquals(13, extractor.getLineEnd(2));
-});
-
-/**
- * Test getting text and lines from a contenteditable region
- * containing some raw text and then some text in a block-level element.
- */
-TEST_F('CvoxContentEditableExtractorUnitTest', 'NodePlusElement', function() {
- this.loadDoc(function() {/*!
- <div>
- <div id="textbox"
- contentEditable="true">One<div>Two<br>Three</div></div>
- </div>
- */});
- var textbox = $('textbox');
-
- var extractor = new cvox.ContentEditableExtractor();
- extractor.update(textbox);
- assertEquals('One\nTwo\nThree',
- extractor.getText());
- assertEquals(0, extractor.getLineStart(0));
- assertEquals(4, extractor.getLineEnd(0));
- assertEquals(4, extractor.getLineStart(1));
- assertEquals(8, extractor.getLineEnd(1));
- assertEquals(8, extractor.getLineStart(2));
- assertEquals(13, extractor.getLineEnd(2));
-
- var oneTextNode = textbox.firstChild;
- assertEquals('One', oneTextNode.data);
- var twoTextNode = textbox.firstElementChild.firstChild;
- assertEquals('Two', twoTextNode.data);
- var threeTextNode = twoTextNode.nextSibling.nextSibling;
- assertEquals('Three', threeTextNode.data);
-
- // End of first line.
- setSelection(oneTextNode, 3, oneTextNode, 3);
- extractor.update(textbox);
- assertEquals(3, extractor.getStartIndex());
- assertEquals(3, extractor.getEndIndex());
-
- // Beginning of second line.
- setSelection(twoTextNode, 0, twoTextNode, 0);
- extractor.update(textbox);
- assertEquals(4, extractor.getStartIndex());
- assertEquals(4, extractor.getEndIndex());
-
- // End of second line.
- setSelection(twoTextNode, 3, twoTextNode, 3);
- extractor.update(textbox);
- assertEquals(7, extractor.getStartIndex());
- assertEquals(7, extractor.getEndIndex());
-
- // Beginning of third line.
- setSelection(threeTextNode, 0, threeTextNode, 0);
- extractor.update(textbox);
- assertEquals(8, extractor.getStartIndex());
- assertEquals(8, extractor.getEndIndex());
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor.js
deleted file mode 100644
index 1cf59633647..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor.js
+++ /dev/null
@@ -1,59 +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 Simple class to represent a cursor location in the document.
- */
-
-goog.provide('cvox.Cursor');
-
-/**
- * A class to represent a cursor location in the document,
- * like the start position or end position of a selection range.
- *
- * Later this may be extended to support "virtual text" for an object,
- * like the ALT text for an image.
- *
- * Note: we cache the text of a particular node at the time we
- * traverse into it. Later we should add support for dynamically
- * reloading it.
- * NOTE: Undefined behavior if node is null
- * @param {Node} node The DOM node.
- * @param {number} index The index of the character within the node.
- * @param {string} text The cached text contents of the node.
- * @constructor
- */
-cvox.Cursor = function(node, index, text) {
- this.node = node;
- this.index = index;
- this.text = text;
-};
-
-/**
- * @return {!cvox.Cursor} A new cursor pointing to the same location.
- */
-cvox.Cursor.prototype.clone = function() {
- return new cvox.Cursor(this.node, this.index, this.text);
-};
-
-/**
- * Modify this cursor to point to the location that another cursor points to.
- * @param {!cvox.Cursor} otherCursor The cursor to copy from.
- */
-cvox.Cursor.prototype.copyFrom = function(otherCursor) {
- this.node = otherCursor.node;
- this.index = otherCursor.index;
- this.text = otherCursor.text;
-};
-
-/**
- * Check for equality.
- * @param {!cvox.Cursor} rhs The cursor to compare against.
- * @return {boolean} True if equal.
- */
-cvox.Cursor.prototype.equals = function(rhs) {
- return this.node == rhs.node &&
- this.index == rhs.index &&
- this.text == rhs.text;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection.js
deleted file mode 100644
index f04351633c1..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection.js
+++ /dev/null
@@ -1,255 +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 Simple class to represent a cursor selection.
- * A cursor selection is just two cursors; one for the start and one for
- * the end of some interval in the document.
- */
-
-goog.provide('cvox.CursorSelection');
-
-goog.require('cvox.Cursor');
-goog.require('cvox.SelectionUtil');
-goog.require('cvox.TraverseUtil');
-
-
-/**
- * If the start node and end node are the same, and the indexes are the same,
- * the selection is interpreted to be a node. Otherwise, it is interpreted
- * to be a range.
- * @param {!cvox.Cursor} start The starting cursor.
- * @param {!cvox.Cursor} end The ending cursor.
- * @param {boolean=} opt_reverse Whether to make it a reversed selection or
- * not. Default is selection is not reversed. If start and end are in the
- * wrong order, they will be swapped automatically.
- * NOTE: Can't infer automatically whether the selection is reversed because
- * for a selection on a single node, the start and end are equal.
- * @constructor
- */
-cvox.CursorSelection = function(start, end, opt_reverse) {
- this.start = start.clone();
- this.end = end.clone();
-
- if (opt_reverse == undefined) {
- opt_reverse = false;
- }
- /** @private */
- this.isReversed_ = opt_reverse;
-
- if ((this.isReversed_ &&
- this.start.node.compareDocumentPosition(this.end.node) ==
- cvox.CursorSelection.BEFORE) ||
- (!this.isReversed_ &&
- this.end.node.compareDocumentPosition(this.start.node) ==
- cvox.CursorSelection.BEFORE)) {
- var oldStart = this.start;
- this.start = this.end;
- this.end = oldStart;
- }
-};
-
-
-/**
- * From http://www.w3schools.com/jsref/met_node_comparedocumentposition.asp
- */
-cvox.CursorSelection.BEFORE = 4;
-
-
-/**
- * If true, ensures that this selection is reversed. Otherwise, ensures that
- * it is not reversed.
- * @param {boolean} reversed True to reverse. False to nonreverse.
- * @return {!cvox.CursorSelection} For chaining.
- */
-cvox.CursorSelection.prototype.setReversed = function(reversed) {
- if (reversed == this.isReversed_) {
- return this;
- }
- var oldStart = this.start;
- this.start = this.end;
- this.end = oldStart;
- this.isReversed_ = reversed;
- return this;
-};
-
-
-/**
- * Returns true if this selection is a reverse selection.
- * @return {boolean} true if reversed.
- */
-cvox.CursorSelection.prototype.isReversed = function() {
- return this.isReversed_;
-};
-
-
-/**
- * Returns start if not reversed, end if reversed.
- * @return {!cvox.Cursor} start if not reversed, end if reversed.
- */
-cvox.CursorSelection.prototype.absStart = function() {
- return this.isReversed_ ? this.end : this.start;
-};
-
-/**
- * Returns end if not reversed, start if reversed.
- * @return {!cvox.Cursor} end if not reversed, start if reversed.
- */
-cvox.CursorSelection.prototype.absEnd = function() {
- return this.isReversed_ ? this.start : this.end;
-};
-
-
-/**
- * Clones the selection.
- * @return {!cvox.CursorSelection} The cloned selection.
- */
-cvox.CursorSelection.prototype.clone = function() {
- return new cvox.CursorSelection(this.start, this.end, this.isReversed_);
-};
-
-
-/**
- * Places a DOM selection around this CursorSelection.
- */
-cvox.CursorSelection.prototype.select = function() {
- var sel = window.getSelection();
- sel.removeAllRanges();
- this.normalize();
- sel.addRange(this.getRange());
-};
-
-
-/**
- * Creates a new cursor selection that starts and ends at the node.
- * Returns null if node is null.
- * @param {Node} node The node.
- * @return {cvox.CursorSelection} The selection.
- */
-cvox.CursorSelection.fromNode = function(node) {
- if (!node) {
- return null;
- }
- var text = cvox.TraverseUtil.getNodeText(node);
-
- return new cvox.CursorSelection(
- new cvox.Cursor(node, 0, text),
- new cvox.Cursor(node, 0, text));
-};
-
-
-/**
- * Creates a new cursor selection that starts and ends at document.body.
- * @return {!cvox.CursorSelection} The selection.
- */
-cvox.CursorSelection.fromBody = function() {
- return /** @type {!cvox.CursorSelection} */ (
- cvox.CursorSelection.fromNode(document.body));
-};
-
-/**
- * Returns the text that the selection spans.
- * @return {string} Text within the selection. '' if it is a node selection.
- */
-cvox.CursorSelection.prototype.getText = function() {
- if (this.start.equals(this.end)) {
- return cvox.TraverseUtil.getNodeText(this.start.node);
- }
- return cvox.SelectionUtil.getRangeText(this.getRange());
-};
-
-/**
- * Returns a range from the given selection.
- * @return {Range} The range.
- */
-cvox.CursorSelection.prototype.getRange = function() {
- var range = document.createRange();
- if (this.isReversed_) {
- range.setStart(this.end.node, this.end.index);
- range.setEnd(this.start.node, this.start.index);
- } else {
- range.setStart(this.start.node, this.start.index);
- range.setEnd(this.end.node, this.end.index);
- }
- return range;
-};
-
-/**
- * Check for equality.
- * @param {!cvox.CursorSelection} rhs The CursorSelection to compare against.
- * @return {boolean} True if equal.
- */
-cvox.CursorSelection.prototype.equals = function(rhs) {
- return this.start.equals(rhs.start) && this.end.equals(rhs.end);
-};
-
-/**
- * Check for equality regardless of direction.
- * @param {!cvox.CursorSelection} rhs The CursorSelection to compare against.
- * @return {boolean} True if equal.
- */
-cvox.CursorSelection.prototype.absEquals = function(rhs) {
- return ((this.start.equals(rhs.start) && this.end.equals(rhs.end)) ||
- (this.end.equals(rhs.start) && this.start.equals(rhs.end)));
-};
-
-/**
- * Determines if this starts before another CursorSelection in document order.
- * If this is reversed, then a reversed document order is checked.
- * In the case that this and rhs start at the same position, we return true.
- * @param {!cvox.CursorSelection} rhs The selection to compare.
- * @return {boolean} True if this is before rhs.
- */
-cvox.CursorSelection.prototype.directedBefore = function(rhs) {
- var leftToRight = this.start.node.compareDocumentPosition(rhs.start.node) ==
- cvox.CursorSelection.BEFORE;
- return this.start.node == rhs.start.node ||
- (this.isReversed() ? !leftToRight : leftToRight);
-};
-/**
- * Normalizes this selection.
- * Use this routine to adjust CursorSelection's that have been collapsed due to
- * convention such as when a CursorSelection references a node without attention
- * to its endpoints.
- * The result is to surround the node with this cursor.
- * @return {!cvox.CursorSelection} The normalized selection.
- */
-cvox.CursorSelection.prototype.normalize = function() {
- if (this.absEnd().index == 0 && this.absEnd().node) {
- var node = this.absEnd().node;
-
- // DOM ranges use different conventions when surrounding a node. For
- // instance, input nodes endOffset is always 0 while h1's endOffset is 1
- //with both having no children. Use a range to compute the endOffset.
- var testRange = document.createRange();
- testRange.selectNodeContents(node);
- this.absEnd().index = testRange.endOffset;
- }
- return this;
-};
-
-/**
- * Collapses to the directed start of the selection.
- * @return {!cvox.CursorSelection} For chaining.
- */
-cvox.CursorSelection.prototype.collapse = function() {
- // Not a selection.
- if (this.start.equals(this.end)) {
- return this;
- }
- this.end.copyFrom(this.start);
- if (this.start.text.length == 0) {
- return this;
- }
- if (this.isReversed()) {
- if (this.end.index > 0) {
- this.end.index--;
- }
- } else {
- if (this.end.index < this.end.text.length) {
- this.end.index++;
- }
- }
- return this;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection_test.unitjs
deleted file mode 100644
index d4a72beba4a..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/cursor_selection_test.unitjs
+++ /dev/null
@@ -1,97 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxCursorSelectionUnitTest() {}
-
-CvoxCursorSelectionUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.CursorSelection'
- ]
-};
-
-TEST_F('CvoxCursorSelectionUnitTest', 'Reverse', function() {
- this.loadDoc(function() {/*!
- <div>
- <p id="a">a</p>
- <p id="b">b</p>
- </div>
- */});
- var a = new cvox.Cursor($('a'), 0, '');
- var b = new cvox.Cursor($('b'), 0, '');
-
- var aa = new cvox.CursorSelection(a, a);
- assertEquals(false, aa.isReversed());
- aa.setReversed(true);
- assertEquals(true, aa.isReversed());
-
- var ab = new cvox.CursorSelection(a, b);
- assertEquals(false, ab.isReversed());
- ab.setReversed(true);
- assertEquals(true, ab.isReversed());
- assertEquals(true, ab.start.equals(b));
- assertEquals(true, ab.end.equals(a));
- ab.setReversed(false);
- assertEquals(false, ab.isReversed());
- assertEquals(true, ab.start.equals(a));
- assertEquals(true, ab.end.equals(b));
-
- ab = new cvox.CursorSelection(b, a);
- assertEquals(false, ab.isReversed());
- assertEquals(true, ab.start.equals(a));
- assertEquals(true, ab.end.equals(b));
-
- var ba = new cvox.CursorSelection(b, a, true);
- assertEquals(true, ba.isReversed());
- assertEquals(true, ba.start.equals(b));
- assertEquals(true, ba.end.equals(a));
-
- ba = new cvox.CursorSelection(a, b, true);
- assertEquals(true, ba.isReversed());
- assertEquals(true, ba.start.equals(b));
- assertEquals(true, ba.end.equals(a));
-});
-
-
-/** Tests correctness of collapsing selections. */
-TEST_F('CvoxCursorSelectionUnitTest', 'Collapse', function() {
- this.loadDoc(function() {/*!
- <p id='1'>This is a test.</p>
- */});
- var text = $('1').firstChild;
- var a = new cvox.Cursor(text, 0, 'This is a test.');
- var b = new cvox.Cursor(text, 13, 'This is a test.');
- var c = new cvox.Cursor(text, 5, 'This is a test.');
- var d = new cvox.Cursor(text, 8, 'This is a test.');
-
- var aa = new cvox.CursorSelection(a, a).collapse();
- assertEquals(0, aa.start.index);
- assertEquals(0, aa.end.index);
-
- var ab = new cvox.CursorSelection(a, b).collapse();
- assertEquals(0, ab.start.index);
- assertEquals(1, ab.end.index);
-
- var ba = new cvox.CursorSelection(b, a, true).collapse();
- assertEquals(12, ba.absStart().index);
- assertEquals(13, ba.absEnd().index);
-
- var cd = new cvox.CursorSelection(c, d).collapse();
- assertEquals(5, cd.start.index);
- assertEquals(6, cd.end.index);
-
- var dc = new cvox.CursorSelection(d, c, true).collapse();
- assertEquals(7, dc.absStart().index);
- assertEquals(8, dc.absEnd().index);
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/date_widget.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/date_widget.js
deleted file mode 100644
index b494db9282e..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/date_widget.js
+++ /dev/null
@@ -1,322 +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.
-
-goog.provide('cvox.ChromeVoxHTMLDateWidget');
-
-goog.require('Msgs');
-
-/**
- * @fileoverview Gives the user spoken feedback as they interact with the date
- * widget (input type=date).
- *
- */
-
-/**
- * A class containing the information needed to speak
- * a text change event to the user.
- *
- * @constructor
- * @param {Element} dateElem The time widget element.
- * @param {cvox.TtsInterface} tts The TTS object from ChromeVox.
- */
-cvox.ChromeVoxHTMLDateWidget = function(dateElem, tts) {
- var self = this;
- /**
- * Currently selected field in the widget.
- * @type {number}
- * @private
- */
- this.pos_ = 0;
- var maxpos = 2;
- if (dateElem.type == 'month' || dateElem.type == 'week') {
- maxpos = 1;
- }
- /**
- * The maximum number of fields in the widget.
- * @type {number}
- * @private
- */
- this.maxPos_ = maxpos;
- /**
- * The HTML node of the widget.
- * @type {Node}
- * @private
- */
- this.dateElem_ = dateElem;
- /**
- * A handle to the ChromeVox TTS object.
- * @type {Object}
- * @private
- */
- this.dateTts_ = tts;
- /**
- * The previous value of the year field.
- * @type {number}
- * @private
- */
- this.pYear_ = -1;
- /**
- * The previous value of the month field.
- * @type {number}
- * @private
- */
- this.pMonth_ = -1;
- /**
- * The previous value of the week field.
- * @type {number}
- * @private
- */
- this.pWeek_ = -1;
- /**
- * The previous value of the day field.
- * @type {number}
- * @private
- */
- this.pDay_ = -1;
-
- // Use listeners to make this work when running tests inside of ChromeVox.
- this.keyListener_ = function(evt) {
- self.eventHandler_(evt);
- };
- this.blurListener_ = function(evt) {
- self.shutdown();
- };
-
- // Ensure we have a reasonable value to start with.
- if (this.dateElem_.value.length == 0) {
- this.forceInitTime_();
- }
-
- // Move the cursor to the first position so that we are guaranteed to start
- // off at the hours position.
- for (var i = 0; i < this.maxPos_; i++) {
- var evt = document.createEvent('KeyboardEvent');
- evt.initKeyboardEvent(
- 'keydown', true, true, window, 'Left', 0, false, false, false, false);
- this.dateElem_.dispatchEvent(evt);
- evt = document.createEvent('KeyboardEvent');
- evt.initKeyboardEvent(
- 'keyup', true, true, window, 'Left', 0, false, false, false, false);
- this.dateElem_.dispatchEvent(evt);
- }
-
- this.dateElem_.addEventListener('keydown', this.keyListener_, false);
- this.dateElem_.addEventListener('keyup', this.keyListener_, false);
- this.dateElem_.addEventListener('blur', this.blurListener_, false);
- this.update_(true);
-};
-
-/**
- * Removes the key listeners for the time widget.
- *
- */
-cvox.ChromeVoxHTMLDateWidget.prototype.shutdown = function() {
- this.dateElem_.removeEventListener('blur', this.blurListener_, false);
- this.dateElem_.removeEventListener('keydown', this.keyListener_, false);
- this.dateElem_.removeEventListener('keyup', this.keyListener_, false);
-};
-
-/**
- * Forces a sensible default value so that there is something there that can
- * be inspected with JS.
- * @private
- */
-cvox.ChromeVoxHTMLDateWidget.prototype.forceInitTime_ = function() {
- var currentDate = new Date();
- var valueString = '';
- var yearString = currentDate.getFullYear() + '';
- // Date.getMonth starts at 0, but the value for the HTML5 date widget needs to
- // start at 1.
- var monthString = currentDate.getMonth() + 1 + '';
- if (monthString.length < 2) {
- monthString = '0' + monthString; // Month format is MM.
- }
- var dayString = currentDate.getDate() + '';
-
- switch (this.dateElem_.type) {
- case 'month':
- valueString = yearString + '-' + monthString;
- break;
- case 'week':
- // Based on info from: http://www.merlyn.demon.co.uk/weekcalc.htm#WNR
- currentDate.setHours(0, 0, 0);
- // Set to nearest Thursday: current date + 4 - current day number
- // Make Sunday's day number 7
- currentDate.setDate(
- currentDate.getDate() + 4 - (currentDate.getDay() || 7));
- // Get first day of year
- var yearStart = new Date(currentDate.getFullYear(), 0, 1);
- // Calculate full weeks to nearest Thursday
- var weekString =
- Math.ceil((((currentDate - yearStart) / 86400000) + 1) / 7) + '';
- if (weekString.length < 2) {
- weekString = '0' + weekString; // Week format is WXX.
- }
- weekString = 'W' + weekString;
- valueString = yearString + '-' + weekString;
- break;
- default:
- valueString = yearString + '-' + monthString + '-' + dayString;
- break;
- }
- this.dateElem_.setAttribute('value', valueString);
-};
-
-/**
- * Ensure that the position stays within bounds.
- * @private
- */
-cvox.ChromeVoxHTMLDateWidget.prototype.handlePosChange_ = function() {
- this.pos_ = Math.max(this.pos_, 0);
- this.pos_ = Math.min(this.pos_, this.maxPos_);
- // TODO (clchen, dtseng): Make this logic i18n once there is a way to
- // determine what the date format actually is. For now, assume that:
- // date == mm/dd/yyyy
- // week == ww/yyyy
- // month == mm/yyyy.
- switch (this.pos_) {
- case 0:
- if (this.dateElem_.type == 'week') {
- this.pWeek_ = -1;
- } else {
- this.pMonth_ = -1;
- }
- break;
- case 1:
- if (this.dateElem_.type == 'date') {
- this.pDay_ = -1;
- } else {
- this.pYear_ = -1;
- }
- break;
- case 2:
- this.pYear_ = -1;
- break;
- }
-};
-
-/**
- * Speaks any changes to the control.
- * @private
- * @param {boolean} shouldSpeakLabel Whether or not to speak the label.
- */
-cvox.ChromeVoxHTMLDateWidget.prototype.update_ = function(shouldSpeakLabel) {
- var splitDate = this.dateElem_.value.split('-');
- if (splitDate.length < 1) {
- this.forceInitTime_();
- return;
- }
-
- var year = -1;
- var month = -1;
- var week = -1;
- var day = -1;
-
- year = parseInt(splitDate[0], 10);
-
- if (this.dateElem_.type == 'week') {
- week = parseInt(splitDate[1].replace('W', ''), 10);
- } else if (this.dateElem_.type == 'date') {
- month = parseInt(splitDate[1], 10);
- day = parseInt(splitDate[2], 10);
- } else {
- month = parseInt(splitDate[1], 10);
- }
-
- var changeMessage = '';
-
- if (shouldSpeakLabel) {
- changeMessage = cvox.DomUtil.getName(this.dateElem_, true, true) + '\n';
- }
-
- if (week != this.pWeek_) {
- changeMessage = changeMessage +
- Msgs.getMsg('datewidget_week') + week + '\n';
- this.pWeek_ = week;
- }
-
- if (month != this.pMonth_) {
- var monthName = '';
- switch (month) {
- case 1:
- monthName = Msgs.getMsg('datewidget_january');
- break;
- case 2:
- monthName = Msgs.getMsg('datewidget_february');
- break;
- case 3:
- monthName = Msgs.getMsg('datewidget_march');
- break;
- case 4:
- monthName = Msgs.getMsg('datewidget_april');
- break;
- case 5:
- monthName = Msgs.getMsg('datewidget_may');
- break;
- case 6:
- monthName = Msgs.getMsg('datewidget_june');
- break;
- case 7:
- monthName = Msgs.getMsg('datewidget_july');
- break;
- case 8:
- monthName = Msgs.getMsg('datewidget_august');
- break;
- case 9:
- monthName = Msgs.getMsg('datewidget_september');
- break;
- case 10:
- monthName = Msgs.getMsg('datewidget_october');
- break;
- case 11:
- monthName = Msgs.getMsg('datewidget_november');
- break;
- case 12:
- monthName = Msgs.getMsg('datewidget_december');
- break;
- }
- changeMessage = changeMessage + monthName + '\n';
- this.pMonth_ = month;
- }
-
- if (day != this.pDay_) {
- changeMessage = changeMessage + day + '\n';
- this.pDay_ = day;
- }
-
- if (year != this.pYear_) {
- changeMessage = changeMessage + year + '\n';
- this.pYear_ = year;
- }
-
- if (changeMessage.length > 0) {
- this.dateTts_.speak(changeMessage, 0, null);
- }
-};
-
-/**
- * Handles user key events.
- * @private
- * @param {Event} evt The event to be handled.
- */
-cvox.ChromeVoxHTMLDateWidget.prototype.eventHandler_ = function(evt) {
- var shouldSpeakLabel = false;
- if (evt.type == 'keydown') {
- // Handle tab/right arrow
- if (((evt.keyCode == 9) && !evt.shiftKey) || (evt.keyCode == 39)) {
- this.pos_++;
- this.handlePosChange_();
- shouldSpeakLabel = true;
- }
- // Handle shift+tab/left arrow
- if (((evt.keyCode == 9) && evt.shiftKey) || (evt.keyCode == 37)) {
- this.pos_--;
- this.handlePosChange_();
- shouldSpeakLabel = true;
- }
- // For all other cases, fall through and let update_ decide if there are any
- // changes that need to be spoken.
- }
- this.update_(shouldSpeakLabel);
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js
deleted file mode 100644
index d7bece47b98..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/description_util.js
+++ /dev/null
@@ -1,474 +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 utility class for building NavDescriptions from the dom.
- */
-
-
-goog.provide('cvox.DescriptionUtil');
-
-goog.require('cvox.AriaUtil');
-goog.require('cvox.AuralStyleUtil');
-goog.require('cvox.BareObjectWalker');
-goog.require('cvox.CursorSelection');
-goog.require('cvox.DomUtil');
-goog.require('cvox.EarconUtil');
-goog.require('cvox.MathmlStore');
-goog.require('cvox.NavDescription');
-goog.require('cvox.SpeechRuleEngine');
-goog.require('cvox.TraverseMath');
-
-
-/**
- * Lists all Node tagName's who's description is derived from its subtree.
- * @type {Object<boolean>}
- */
-cvox.DescriptionUtil.COLLECTION_NODE_TYPE = {
- 'H1': true,
- 'H2': true,
- 'H3': true,
- 'H4': true,
- 'H5': true,
- 'H6': true
-};
-
-/**
- * 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
- * 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.
- * @return {cvox.NavDescription} The description of the control.
- */
-cvox.DescriptionUtil.getControlDescription =
- function(control, opt_changedAncestors) {
- var ancestors = [control];
- if (opt_changedAncestors && (opt_changedAncestors.length > 0)) {
- ancestors = opt_changedAncestors;
- } else {
- var surroundingControl = cvox.DomUtil.getSurroundingControl(control);
- if (surroundingControl) {
- ancestors = [surroundingControl, control];
- }
- }
-
- var description = cvox.DescriptionUtil.getDescriptionFromAncestors(
- ancestors, true, cvox.VERBOSITY_VERBOSE);
-
- // Use heuristics if the control doesn't otherwise have a name.
- if (surroundingControl) {
- var name = cvox.DomUtil.getName(surroundingControl);
- if (name.length == 0) {
- name = cvox.DomUtil.getControlLabelHeuristics(surroundingControl);
- if (name.length > 0) {
- description.context = name + ' ' + description.context;
- }
- }
- } else {
- var name = cvox.DomUtil.getName(control);
- if (name.length == 0) {
- name = cvox.DomUtil.getControlLabelHeuristics(control);
- if (name.length > 0) {
- description.text = cvox.DomUtil.collapseWhitespace(name);
- }
- }
- var value = cvox.DomUtil.getValue(control);
- if (value.length > 0) {
- description.userValue = cvox.DomUtil.collapseWhitespace(value);
- }
- }
-
- return description;
-};
-
-
-/**
- * Returns a description of a navigation from an array of changed
- * 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 {boolean} recursive Whether or not the element's subtree should
- * be used; true by default.
- * @param {number} verbosity The verbosity setting.
- * @return {cvox.NavDescription} The description of the navigation action.
- */
-cvox.DescriptionUtil.getDescriptionFromAncestors = function(
- ancestorsArray, recursive, verbosity) {
- if (typeof(recursive) === 'undefined') {
- recursive = true;
- }
- var len = ancestorsArray.length;
- var context = '';
- var text = '';
- var userValue = '';
- var annotation = '';
- var earcons = [];
- var personality = null;
- var hint = '';
-
- if (len > 0) {
- text = cvox.DomUtil.getName(ancestorsArray[len - 1], recursive);
-
- userValue = cvox.DomUtil.getValue(ancestorsArray[len - 1]);
- }
- for (var i = len - 1; i >= 0; i--) {
- var node = ancestorsArray[i];
-
- hint = cvox.DomUtil.getHint(node);
-
- // Don't speak dialogs here, they're spoken when events occur.
- var role = node.getAttribute ? node.getAttribute('role') : null;
- if (role == 'alertdialog') {
- continue;
- }
-
- var roleText = cvox.DomUtil.getRole(node, verbosity);
-
- // Use the ancestor closest to the target to be the personality.
- if (!personality) {
- personality = cvox.AuralStyleUtil.getStyleForNode(node);
- }
- // TODO(dtseng): Is this needed?
- if (i < len - 1 && node.hasAttribute('role')) {
- var name = cvox.DomUtil.getName(node, false);
- if (name) {
- roleText = name + ' ' + roleText;
- }
- }
- if (roleText.length > 0) {
- // Since we prioritize reading of context in reading order, only populate
- // it for larger ancestry changes.
- if (context.length > 0 ||
- (annotation.length > 0 && node.childElementCount > 1)) {
- context = roleText + ' ' + cvox.DomUtil.getState(node, false) +
- ' ' + context;
- } else {
- if (annotation.length > 0) {
- annotation +=
- ' ' + roleText + ' ' + cvox.DomUtil.getState(node, true);
- } else {
- annotation = roleText + ' ' + cvox.DomUtil.getState(node, true);
- }
- }
- }
- var earcon = cvox.EarconUtil.getEarcon(node);
- if (earcon != null && earcons.indexOf(earcon) == -1) {
- earcons.push(earcon);
- }
- }
- return new cvox.NavDescription({
- context: cvox.DomUtil.collapseWhitespace(context),
- text: cvox.DomUtil.collapseWhitespace(text),
- userValue: cvox.DomUtil.collapseWhitespace(userValue),
- annotation: cvox.DomUtil.collapseWhitespace(annotation),
- earcons: earcons,
- personality: personality,
- hint: cvox.DomUtil.collapseWhitespace(hint)
- });
-};
-
-/**
- * Returns a description of a navigation from an array of changed
- * 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 {Node} prevNode The previous node in navigation.
- * @param {Node} node The current node in navigation.
- * @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
- * action.
- */
-cvox.DescriptionUtil.getDescriptionFromNavigation =
- function(prevNode, node, recursive, verbosity) {
- if (!prevNode || !node) {
- return [];
- }
-
- // Specialized math descriptions.
- if (cvox.DomUtil.isMath(node) &&
- !cvox.AriaUtil.isMath(node)) {
- return cvox.DescriptionUtil.getMathDescription(node);
- }
-
- // Next, check to see if the current node is a collection type.
- if (cvox.DescriptionUtil.COLLECTION_NODE_TYPE[node.tagName]) {
- return cvox.DescriptionUtil.getCollectionDescription(
- /** @type {!cvox.CursorSelection} */(
- cvox.CursorSelection.fromNode(prevNode)),
- /** @type {!cvox.CursorSelection} */(
- cvox.CursorSelection.fromNode(node)));
- }
-
- // Now, generate a description for all other elements.
- var ancestors = cvox.DomUtil.getUniqueAncestors(prevNode, node, true);
- var desc = cvox.DescriptionUtil.getDescriptionFromAncestors(
- ancestors, recursive, verbosity);
- var prevAncestors = cvox.DomUtil.getUniqueAncestors(node, prevNode);
- if (cvox.DescriptionUtil.shouldDescribeExit_(prevAncestors)) {
- var prevDesc = cvox.DescriptionUtil.getDescriptionFromAncestors(
- prevAncestors, recursive, verbosity);
- if (prevDesc.context && !desc.context) {
- desc.context =
- Msgs.getMsg('exited_container', [prevDesc.context]);
- }
- }
- return [desc];
-};
-
-
-/**
- * Returns an array of NavDescriptions that includes everything that would be
- * spoken by an object walker while traversing from prevSel to sel.
- * It also includes any necessary annotations and context about the set of
- * descriptions. This function is here because most (currently all) walkers
- * that iterate over non-leaf nodes need this sort of description.
- * 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.
- */
-cvox.DescriptionUtil.getCollectionDescription = function(prevSel, sel) {
- var descriptions = cvox.DescriptionUtil.getRawDescriptions_(prevSel, sel);
- cvox.DescriptionUtil.insertCollectionDescription_(descriptions);
- return descriptions;
-};
-
-
-/**
- * Used for getting collection descriptions.
- * @type {!cvox.BareObjectWalker}
- * @private
- */
-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.
- * @private
- */
-cvox.DescriptionUtil.getRawDescriptions_ = function(prevSel, sel) {
- // Use a object walker in non-smart mode to traverse all of the
- // nodes inside the current smart node and return their annotations.
- var descriptions = [];
-
- // We want the descriptions to be in forward order whether or not the
- // selection is reversed.
- sel = sel.clone().setReversed(false);
- var node = cvox.DescriptionUtil.subWalker_.sync(sel).start.node;
-
- var prevNode = prevSel.end.node;
- var curSel = cvox.CursorSelection.fromNode(node);
-
- if (!curSel) {
- return [];
- }
-
- while (cvox.DomUtil.isDescendantOfNode(node, sel.start.node)) {
- var ancestors = cvox.DomUtil.getUniqueAncestors(prevNode, node);
- // Specialized math descriptions.
- if (cvox.DomUtil.isMath(node) &&
- !cvox.AriaUtil.isMath(node)) {
- descriptions =
- descriptions.concat(cvox.DescriptionUtil.getMathDescription(node));
- } else {
- var description = cvox.DescriptionUtil.getDescriptionFromAncestors(
- ancestors, true, cvox.ChromeVox.verbosity);
- descriptions.push(description);
- }
- curSel = cvox.DescriptionUtil.subWalker_.next(curSel);
- if (!curSel) {
- break;
- }
-
- curSel = /** @type {!cvox.CursorSelection} */ (curSel);
- prevNode = node;
- node = curSel.start.node;
- }
-
- return descriptions;
-};
-
-/**
- * Returns the full descriptions of the child nodes that would be gotten by an
- * object walker.
- * @param {?Element} prevnode The previous element if there is one.
- * @param {!Element} node The target element.
- * @return {!Array<!cvox.NavDescription>} The descriptions.
- */
-cvox.DescriptionUtil.getFullDescriptionsFromChildren =
- function(prevnode, node) {
- var descriptions = [];
- if (!node) {
- return descriptions;
- }
- var desc;
- if (cvox.DomUtil.isLeafNode(node)) {
- var ancestors;
- if (prevnode) {
- ancestors = cvox.DomUtil.getUniqueAncestors(prevnode, node);
- } else {
- ancestors = new Array();
- ancestors.push(node);
- }
- desc = cvox.DescriptionUtil.getDescriptionFromAncestors(
- ancestors, true, cvox.ChromeVox.verbosity);
- descriptions.push(desc);
- return descriptions;
- }
- var originalNode = node;
- var curSel = cvox.CursorSelection.fromNode(node);
- if (!curSel) {
- return descriptions;
- }
- node = cvox.DescriptionUtil.subWalker_.sync(curSel).start.node;
- curSel = cvox.CursorSelection.fromNode(node);
- if (!curSel) {
- return descriptions;
- }
- while (cvox.DomUtil.isDescendantOfNode(node, originalNode)) {
- descriptions = descriptions.concat(
- cvox.DescriptionUtil.getFullDescriptionsFromChildren(prevnode, node));
- curSel = cvox.DescriptionUtil.subWalker_.next(curSel);
- if (!curSel) {
- break;
- }
- curSel = /** @type {!cvox.CursorSelection} */ (curSel);
- prevnode = node;
- node = curSel.start.node;
- }
- return descriptions;
-};
-
-
-/**
- * Modify the descriptions to say that it is a collection.
- * @param {Array<cvox.NavDescription>} descriptions The descriptions.
- * @private
- */
-cvox.DescriptionUtil.insertCollectionDescription_ = function(descriptions) {
- var annotations = cvox.DescriptionUtil.getAnnotations_(descriptions);
- // If all of the items have the same annotation, describe it as a
- // <annotation> collection with <n> items. Currently only enabled
- // for links, but support should be added for any other type that
- // makes sense.
- if (descriptions.length >= 3 &&
- descriptions[0].context.length == 0 &&
- annotations.length == 1 &&
- annotations[0].length > 0 &&
- cvox.DescriptionUtil.isAnnotationCollection_(annotations[0])) {
- var commonAnnotation = annotations[0];
- var firstContext = descriptions[0].context;
- descriptions[0].context = '';
- for (var i = 0; i < descriptions.length; i++) {
- descriptions[i].annotation = '';
- }
-
- descriptions.splice(0, 0, new cvox.NavDescription({
- context: firstContext,
- text: '',
- annotation: Msgs.getMsg(
- 'collection',
- [commonAnnotation,
- Msgs.getNumber(descriptions.length)])
- }));
- }
-};
-
-
-/**
- * Pulls the annotations from a description array.
- * @param {Array<cvox.NavDescription>} descriptions The descriptions.
- * @return {Array<string>} The annotations.
- * @private
- */
-cvox.DescriptionUtil.getAnnotations_ = function(descriptions) {
- var annotations = [];
- for (var i = 0; i < descriptions.length; ++i) {
- var description = descriptions[i];
- if (annotations.indexOf(description.annotation) == -1) {
- // If we have an Internal link collection, call it Link collection.
- // NOTE(deboer): The message comparison is a symptom of a bad design.
- // I suspect this code belongs elsewhere but I don't know where, yet.
- var linkMsg = Msgs.getMsg('role_link');
- if (description.annotation.toLowerCase().indexOf(linkMsg.toLowerCase()) !=
- -1) {
- if (annotations.indexOf(linkMsg) == -1) {
- annotations.push(linkMsg);
- }
- } else {
- annotations.push(description.annotation);
- }
- }
- }
- return annotations;
-};
-
-
-/**
- * Returns true if this annotation should be grouped as a collection,
- * meaning that instead of repeating the annotation for each item, we
- * just announce <annotation> collection with <n> items at the front.
- *
- * Currently enabled for links, but could be extended to support other
- * roles that make sense.
- *
- * @param {string} annotation The annotation text.
- * @return {boolean} If this annotation should be a collection.
- * @private
- */
-cvox.DescriptionUtil.isAnnotationCollection_ = function(annotation) {
- return (annotation == Msgs.getMsg('role_link'));
-};
-
-/**
- * Determines whether to describe the exit of an ancestor chain.
- * @param {Array<Node>} ancestors The ancestors exited during navigation.
- * @return {boolean} The result.
- * @private
- */
-cvox.DescriptionUtil.shouldDescribeExit_ = function(ancestors) {
- return ancestors.some(function(node) {
- switch (node.tagName) {
- case 'TABLE':
- case 'MATH':
- return true;
- }
- return cvox.AriaUtil.isLandmark(node);
- });
-};
-
-
-// TODO(sorge): Bad naming...this thing returns *multiple* descriptions.
-/**
- * Generates a description for a math node.
- * @param {!Node} node The given node.
- * @return {!Array<cvox.NavDescription>} A list of Navigation descriptions.
- */
-cvox.DescriptionUtil.getMathDescription = function(node) {
- // TODO (sorge) This function should evantually be removed. Descriptions
- // should come directly from the speech rule engine, taking information on
- // verbosity etc. into account.
- var speechEngine = cvox.SpeechRuleEngine.getInstance();
- var traverse = cvox.TraverseMath.getInstance();
- speechEngine.parameterize(cvox.MathmlStore.getInstance());
- traverse.initialize(node);
- var ret = speechEngine.evaluateNode(traverse.activeNode);
- if (ret == []) {
- return [new cvox.NavDescription({'text': 'empty math'})];
- }
- if (cvox.ChromeVox.verbosity == cvox.VERBOSITY_VERBOSE) {
- ret[ret.length - 1].annotation = 'math';
- }
- ret[0].pushEarcon(cvox.Earcon.MATH);
- return ret;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js
deleted file mode 100644
index 685a8ecf8f4..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_predicates.js
+++ /dev/null
@@ -1,493 +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 bunch of predicates that take as input an array of
- * nodes with the unique ancestors of a node. They output true if a
- * certain category of node has been found.
- *
- */
-
-goog.provide('cvox.DomPredicates');
-
-
-/**
- * Checkbox.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute &&
- nodes[i].getAttribute('role') == 'checkbox') ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'checkbox')) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Radio button.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'radio') ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'radio')) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Slider.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'slider') ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'range')) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Graphic.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (nodes[i].tagName == 'IMG' ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'img')) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Button.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'button') ||
- nodes[i].tagName == 'BUTTON' ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'submit') ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'button') ||
- (nodes[i].tagName == 'INPUT' && nodes[i].type == 'reset')) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Combo box.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute &&
- nodes[i].getAttribute('role') == 'combobox') ||
- nodes[i].tagName == 'SELECT') {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Editable text field.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'textbox') ||
- nodes[i].tagName == 'TEXTAREA' ||
- nodes[i].isContentEditable ||
- (nodes[i].tagName == 'INPUT' &&
- cvox.DomUtil.isInputTypeText(nodes[i]))) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Heading.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (nodes[i].getAttribute &&
- nodes[i].getAttribute('role') == 'heading') {
- return nodes[i];
- }
- switch (nodes[i].tagName) {
- case 'H1':
- case 'H2':
- case 'H3':
- case 'H4':
- case 'H5':
- case 'H6':
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Heading level 1.
- * @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?
- */
-cvox.DomPredicates.heading1Predicate = function(nodes) {
- return cvox.DomPredicates.containsTagName_(nodes, 'H1');
-};
-
-
-/**
- * Heading level 2.
- * @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) {
- return cvox.DomPredicates.containsTagName_(nodes, 'H2');
-};
-
-
-/**
- * Heading level 3.
- * @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) {
- return cvox.DomPredicates.containsTagName_(nodes, 'H3');
-};
-
-
-/**
- * Heading level 4.
- * @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) {
- return cvox.DomPredicates.containsTagName_(nodes, 'H4');
-};
-
-
-/**
- * Heading level 5.
- * @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) {
- return cvox.DomPredicates.containsTagName_(nodes, 'H5');
-};
-
-
-/**
- * Heading level 6.
- * @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) {
- return cvox.DomPredicates.containsTagName_(nodes, 'H6');
-};
-
-
-/**
- * Link.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'link') ||
- (nodes[i].tagName == 'A' && nodes[i].href)) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Table.
- * @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) {
- // TODO(stoarca): Captions should always be allowed!!
- var node = cvox.DomUtil.findTableNodeInList(nodes, {allowCaptions: true});
- if (node && !cvox.DomUtil.isLayoutTable(node)) {
- return node;
- } else {
- return null;
- }
-};
-
-/**
- * Table Cell.
- * @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) {
- for (var i = nodes.length - 1; i >= 0; --i) {
- var node = nodes[i];
- if (node.tagName == 'TD' ||
- node.tagName == 'TH' ||
- (node.getAttribute && node.getAttribute('role') == 'gridcell')) {
- return node;
- }
- }
- return null;
-};
-
-
-/**
- * Visited link.
- * @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) {
- for (var i = nodes.length - 1; i >= 0; --i) {
- if (cvox.DomPredicates.linkPredicate([nodes[i]]) &&
- cvox.ChromeVox.visitedUrls[nodes[i].href]) {
- return nodes[i];
- }
- }
-};
-
-
-/**
- * List.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'list') ||
- nodes[i].tagName == 'UL' ||
- nodes[i].tagName == 'OL') {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * List item.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute &&
- nodes[i].getAttribute('role') == 'listitem') ||
- nodes[i].tagName == 'LI') {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Blockquote.
- * @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) {
- return cvox.DomPredicates.containsTagName_(nodes, 'BLOCKQUOTE');
-};
-
-
-/**
- * Form field.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (cvox.DomUtil.isControl(nodes[i])) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * ARIA landmark.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (cvox.AriaUtil.isLandmark(nodes[i])) {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * @param {Array} arr Array of nodes.
- * @param {string} tagName The name of the tag.
- * @return {?Node} Node if obj is in the array.
- * @private
- */
-cvox.DomPredicates.containsTagName_ = function(arr, tagName) {
- var i = arr.length;
- while (i--) {
- if (arr[i].tagName == tagName) {
- return arr[i];
- }
- }
- return null;
-};
-
-
-/**
- * MathML expression
- * @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) {
- return cvox.DomUtil.findMathNodeInList(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.
- * @return {?Node} Node in the array that is considered a section marker.
- */
-cvox.DomPredicates.sectionPredicate = function(nodes) {
- for (var i = 0; i < nodes.length; i++) {
- if (cvox.DomUtil.isSemanticElt(nodes[i])) {
- return nodes[i];
- }
- if (cvox.AriaUtil.isLandmark(nodes[i])) {
- return nodes[i];
- }
- if (nodes[i].getAttribute &&
- nodes[i].getAttribute('role') == 'heading') {
- return nodes[i];
- }
- switch (nodes[i].tagName) {
- case 'H1':
- case 'H2':
- case 'H3':
- case 'H4':
- case 'H5':
- case 'H6':
- return nodes[i];
- }
- }
- return null;
-};
-
-/**
- * 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.
- * @return {?Node} Node in the array that is considered a control.
- */
-cvox.DomPredicates.controlPredicate = function(nodes) {
- for (var i = 0; i < nodes.length; i++) {
- if (cvox.DomUtil.isControl(nodes[i])) {
- return nodes[i];
- }
- if ((nodes[i].getAttribute && nodes[i].getAttribute('role') == 'link') ||
- (nodes[i].tagName == 'A' && nodes[i].href)) {
- return nodes[i];
- }
- }
- return null;
-};
-
-/**
- * Caption.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (nodes[i].tagName == 'CAPTION') {
- return nodes[i];
- }
- }
- return null;
-};
-
-/**
- * Article.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if ((nodes[i].getAttribute &&
- nodes[i].getAttribute('role') == 'article') ||
- nodes[i].tagName == 'ARTICLE') {
- return nodes[i];
- }
- }
- return null;
-};
-
-/**
- * Media.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (nodes[i].tagName == 'AUDIO' ||
- nodes[i].tagName == 'VIDEO') {
- return nodes[i];
- }
- }
- return null;
-};
-
-
-/**
- * Ordered List.
- * @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) {
- for (var i = 0; i < nodes.length; i++) {
- if (nodes[i].tagName == 'OL') {
- return nodes[i];
- }
- }
- return null;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js
deleted file mode 100644
index cea00b5f612..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util.js
+++ /dev/null
@@ -1,2608 +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 collection of JavaScript utilities used to simplify working
- * with the DOM.
- */
-
-
-goog.provide('cvox.DomUtil');
-
-goog.require('cvox.AbstractTts');
-goog.require('cvox.AriaUtil');
-goog.require('cvox.ChromeVox');
-goog.require('cvox.DomPredicates');
-goog.require('cvox.Memoize');
-goog.require('cvox.NodeState');
-goog.require('cvox.XpathUtil');
-
-
-
-/**
- * Create the namespace
- * @constructor
- */
-cvox.DomUtil = function() {
-};
-
-
-/**
- * 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}
- */
-cvox.DomUtil.INPUT_TYPE_TO_INFORMATION_TABLE_MSG = {
- 'button' : 'role_button',
- 'checkbox' : 'role_checkbox',
- 'color' : 'input_type_color',
- 'datetime' : 'input_type_datetime',
- 'datetime-local' : 'input_type_datetime_local',
- 'date' : 'input_type_date',
- 'email' : 'input_type_email',
- 'file' : 'input_type_file',
- 'image' : 'role_button',
- 'month' : 'input_type_month',
- 'number' : 'input_type_number',
- 'password' : 'input_type_password',
- 'radio' : 'role_radio',
- 'range' : 'role_slider',
- 'reset' : 'input_type_reset',
- 'search' : 'input_type_search',
- 'submit' : 'role_button',
- 'tel' : 'input_type_number',
- 'text' : 'input_type_text',
- 'url' : 'input_type_url',
- 'week' : 'input_type_week'
-};
-
-
-/**
- * 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}
- */
-cvox.DomUtil.TAG_TO_INFORMATION_TABLE_VERBOSE_MSG = {
- 'A' : 'role_link',
- 'ARTICLE' : 'tag_article',
- 'ASIDE' : 'tag_aside',
- 'AUDIO' : 'tag_audio',
- 'BUTTON' : 'role_button',
- 'FOOTER' : 'tag_footer',
- 'H1' : 'tag_h1',
- 'H2' : 'tag_h2',
- 'H3' : 'tag_h3',
- 'H4' : 'tag_h4',
- 'H5' : 'tag_h5',
- 'H6' : 'tag_h6',
- 'HEADER' : 'tag_header',
- 'HGROUP' : 'tag_hgroup',
- 'LI' : 'tag_li',
- 'MARK' : 'tag_mark',
- 'NAV' : 'tag_nav',
- 'OL' : 'tag_ol',
- 'SECTION' : 'tag_section',
- 'SELECT' : 'tag_select',
- 'TABLE' : 'tag_table',
- 'TEXTAREA' : 'tag_textarea',
- 'TIME' : 'tag_time',
- 'UL' : 'tag_ul',
- 'VIDEO' : 'tag_video'
-};
-
-/**
- * ChromeVox does not speak the omitted tags.
- * @type {Object}
- */
-cvox.DomUtil.TAG_TO_INFORMATION_TABLE_BRIEF_MSG = {
- 'AUDIO' : 'tag_audio',
- 'BUTTON' : 'role_button',
- 'SELECT' : 'tag_select',
- 'TABLE' : 'tag_table',
- 'TEXTAREA' : 'tag_textarea',
- 'VIDEO' : 'tag_video'
-};
-
-/**
- * These tags are treated as text formatters.
- * @type {Array<string>}
- */
-cvox.DomUtil.FORMATTING_TAGS =
- ['B', 'BIG', 'CITE', 'CODE', 'DFN', 'EM', 'I', 'KBD', 'SAMP', 'SMALL',
- 'SPAN', 'STRIKE', 'STRONG', 'SUB', 'SUP', 'U', 'VAR'];
-
-/**
- * Determine if the given node is visible on the page. This does not check if
- * it is inside the document view-port as some sites try to communicate with
- * screen readers with such elements.
- * @param {Node} node The node to determine as visible or not.
- * @param {{checkAncestors: (boolean|undefined),
- checkDescendants: (boolean|undefined)}=} opt_options
- * In certain cases, we already have information
- * on the context of the node. To improve performance and avoid redundant
- * operations, you may wish to turn certain visibility checks off by
- * passing in an options object. The following properties are configurable:
- * checkAncestors: {boolean=} True if we should check the ancestor chain
- * for forced invisibility traits of descendants. True by default.
- * checkDescendants: {boolean=} True if we should consider descendants of
- * the given node for visible elements. True by default.
- * @return {boolean} True if the node is visible.
- */
-cvox.DomUtil.isVisible = function(node, opt_options) {
- var checkAncestors = true;
- var checkDescendants = true;
- if (opt_options) {
- if (opt_options.checkAncestors !== undefined) {
- checkAncestors = opt_options.checkAncestors;
- }
- if (opt_options.checkDescendants !== undefined) {
- checkDescendants = opt_options.checkDescendants;
- }
- }
-
- // Generate a unique function name based on the arguments, and
- // memoize the result of the internal visibility computation so that
- // within the same call stack, we don't need to recompute the visibility
- // of the same node.
- var fname = 'isVisible-' + checkAncestors + '-' + checkDescendants;
- return /** @type {boolean} */ (cvox.Memoize.memoize(
- cvox.DomUtil.computeIsVisible_.bind(
- this, node, checkAncestors, checkDescendants), fname, node));
-};
-
-/**
- * Implementation of |cvox.DomUtil.isVisible|.
- * @param {Node} node The node to determine as visible or not.
- * @param {boolean} checkAncestors True if we should check the ancestor chain
- * for forced invisibility traits of descendants.
- * @param {boolean} checkDescendants True if we should consider descendants of
- * the given node for visible elements.
- * @return {boolean} True if the node is visible.
- * @private
- */
-cvox.DomUtil.computeIsVisible_ = function(
- node, checkAncestors, checkDescendants) {
- // If the node is an iframe that we can never inject into, consider it hidden.
- if (node.tagName == 'IFRAME' && !node.src) {
- return false;
- }
-
- // If the node is being forced visible by ARIA, ARIA wins.
- if (cvox.AriaUtil.isForcedVisibleRecursive(node)) {
- return true;
- }
-
- // Confirm that no subtree containing node is invisible.
- if (checkAncestors &&
- cvox.DomUtil.hasInvisibleAncestor_(node)) {
- return false;
- }
-
- // If the node's subtree has a visible node, we declare it as visible.
- if (cvox.DomUtil.hasVisibleNodeSubtree_(node, checkDescendants)) {
- return true;
- }
-
- return false;
-};
-
-
-/**
- * Checks the ancestor chain for the given node for invisibility. If an
- * ancestor is invisible and this cannot be overriden by a descendant,
- * we return true. If the element is not a descendant of the document
- * element it will return true (invisible).
- * @param {Node} node The node to check the ancestor chain for.
- * @return {boolean} True if a descendant is invisible.
- * @private
- */
-cvox.DomUtil.hasInvisibleAncestor_ = function(node) {
- var ancestor = node;
- while (ancestor = ancestor.parentElement) {
- var style = document.defaultView.getComputedStyle(ancestor, null);
- if (cvox.DomUtil.isInvisibleStyle(style, true)) {
- return true;
- }
- // Once we reach the document element and we haven't found anything
- // invisible yet, we're done. If we exit the while loop and never found
- // the document element, the element wasn't part of the DOM and thus it's
- // invisible.
- if (ancestor == document.documentElement) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Checks for a visible node in the subtree defined by root.
- * @param {Node} root The root of the subtree to check.
- * @param {boolean} recursive Whether or not to check beyond the root of the
- * subtree for visible nodes. This option exists for performance tuning.
- * Sometimes we already have information about the descendants, and we do
- * not need to check them again.
- * @return {boolean} True if the subtree contains a visible node.
- * @private
- */
-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);
- return isVisibleParent;
- }
-
- var rootStyle = document.defaultView.getComputedStyle(root, null);
- var isRootVisible = !cvox.DomUtil.isInvisibleStyle(rootStyle);
- if (isRootVisible) {
- return true;
- }
- var isSubtreeInvisible = cvox.DomUtil.isInvisibleStyle(rootStyle, true);
- if (!recursive || isSubtreeInvisible) {
- return false;
- }
-
- // Carry on with a recursive check of the descendants.
- var children = root.childNodes;
- for (var i = 0; i < children.length; i++) {
- var child = children[i];
- if (cvox.DomUtil.hasVisibleNodeSubtree_(child, recursive)) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Determines whether or a node is not visible according to any CSS criteria
- * that can hide it.
- * @param {CSSStyleDeclaration} style The style of the node to determine as
- * invsible or not.
- * @param {boolean=} opt_strict If set to true, we do not check the visibility
- * style attribute. False by default.
- * CAUTION: Checking the visibility style attribute can result in returning
- * true (invisible) even when an element has have visible descendants. This
- * is because an element with visibility:hidden can have descendants that
- * are visible.
- * @return {boolean} True if the node is invisible.
- */
-cvox.DomUtil.isInvisibleStyle = function(style, opt_strict) {
- if (!style) {
- return false;
- }
- if (style.display == 'none') {
- return true;
- }
- // Opacity values range from 0.0 (transparent) to 1.0 (fully opaque).
- if (parseFloat(style.opacity) == 0) {
- return true;
- }
- // Visibility style tests for non-strict checking.
- if (!opt_strict &&
- (style.visibility == 'hidden' || style.visibility == 'collapse')) {
- return true;
- }
- return false;
-};
-
-
-/**
- * Determines whether a control should be announced as disabled.
- *
- * @param {Node} node The node to be examined.
- * @return {boolean} Whether or not the node is disabled.
- */
-cvox.DomUtil.isDisabled = function(node) {
- if (node.disabled) {
- return true;
- }
- var ancestor = node;
- while (ancestor = ancestor.parentElement) {
- if (ancestor.tagName == 'FIELDSET' && ancestor.disabled) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Determines whether a node is an HTML5 semantic element
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} True if the node is an HTML5 semantic element.
- */
-cvox.DomUtil.isSemanticElt = function(node) {
- if (node.tagName) {
- var tag = node.tagName;
- if ((tag == 'SECTION') || (tag == 'NAV') || (tag == 'ARTICLE') ||
- (tag == 'ASIDE') || (tag == 'HGROUP') || (tag == 'HEADER') ||
- (tag == 'FOOTER') || (tag == 'TIME') || (tag == 'MARK')) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Determines whether or not a node is a leaf node.
- * TODO (adu): This function is doing a lot more than just checking for the
- * presence of descendants. We should be more precise in the documentation
- * about what we mean by leaf node.
- *
- * @param {Node} node The node to be checked.
- * @param {boolean=} opt_allowHidden Allows hidden nodes during descent.
- * @return {boolean} True if the node is a leaf node.
- */
-cvox.DomUtil.isLeafNode = function(node, opt_allowHidden) {
- // If it's not an Element, then it's a leaf if it has no first child.
- if (!(node instanceof Element)) {
- return (node.firstChild == null);
- }
-
- // Now we know for sure it's an element.
- var element = /** @type {Element} */(node);
- if (!opt_allowHidden &&
- !cvox.DomUtil.isVisible(element, {checkAncestors: false})) {
- return true;
- }
- if (!opt_allowHidden && cvox.AriaUtil.isHidden(element)) {
- return true;
- }
- if (cvox.AriaUtil.isLeafElement(element)) {
- return true;
- }
- switch (element.tagName) {
- case 'OBJECT':
- case 'EMBED':
- case 'VIDEO':
- case 'AUDIO':
- case 'IFRAME':
- case 'FRAME':
- return true;
- }
-
- if (!!cvox.DomPredicates.linkPredicate([element])) {
- return !cvox.DomUtil.findNode(element, function(node) {
- return !!cvox.DomPredicates.headingPredicate([node]);
- });
- }
- if (cvox.DomUtil.isLeafLevelControl(element)) {
- return true;
- }
- if (!element.firstChild) {
- return true;
- }
- if (cvox.DomUtil.isMath(element)) {
- return true;
- }
- if (cvox.DomPredicates.headingPredicate([element])) {
- return !cvox.DomUtil.findNode(element, function(n) {
- return !!cvox.DomPredicates.controlPredicate([n]);
- });
- }
- return false;
-};
-
-
-/**
- * Determines whether or not a node is or is the descendant of a node
- * with a particular tag or class name.
- *
- * @param {Node} node The node to be checked.
- * @param {?string} tagName The tag to check for, or null if the tag
- * doesn't matter.
- * @param {?string=} className The class to check for, or null if the class
- * doesn't matter.
- * @return {boolean} True if the node or one of its ancestor has the specified
- * tag.
- */
-cvox.DomUtil.isDescendantOf = function(node, tagName, className) {
- while (node) {
-
- if (tagName && className &&
- (node.tagName && (node.tagName == tagName)) &&
- (node.className && (node.className == className))) {
- return true;
- } else if (tagName && !className &&
- (node.tagName && (node.tagName == tagName))) {
- return true;
- } else if (!tagName && className &&
- (node.className && (node.className == className))) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
-};
-
-
-/**
- * Determines whether or not a node is or is the descendant of another node.
- *
- * @param {Object} node The node to be checked.
- * @param {Object} ancestor The node to see if it's a descendant of.
- * @return {boolean} True if the node is ancestor or is a descendant of it.
- */
-cvox.DomUtil.isDescendantOfNode = function(node, ancestor) {
- while (node && ancestor) {
- if (node.isSameNode(ancestor)) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
-};
-
-
-/**
- * Remove all whitespace from the beginning and end, and collapse all
- * inner strings of whitespace to a single space.
- * @param {string} str The input string.
- * @return {string} The string with whitespace collapsed.
- */
-cvox.DomUtil.collapseWhitespace = function(str) {
- return str.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '');
-};
-
-/**
- * Gets the base label of a node. I don't know exactly what this is.
- *
- * @param {Node} node The node to get the label from.
- * @param {boolean=} recursive Whether or not the element's subtree
- * should be used; true by default.
- * @param {boolean=} includeControls Whether or not controls in the subtree
- * should be included; true by default.
- * @return {string} The base label of the node.
- * @private
- */
-cvox.DomUtil.getBaseLabel_ = function(node, recursive, includeControls) {
- var label = '';
- if (node.hasAttribute) {
- if (node.hasAttribute('aria-labelledby')) {
- var labelNodeIds = node.getAttribute('aria-labelledby').split(' ');
- for (var labelNodeId, i = 0; labelNodeId = labelNodeIds[i]; i++) {
- var labelNode = document.getElementById(labelNodeId);
- if (labelNode) {
- label += ' ' + cvox.DomUtil.getName(
- labelNode, true, includeControls, true);
- }
- }
- } else if (node.hasAttribute('aria-label')) {
- label = node.getAttribute('aria-label');
- } else if (node.constructor == HTMLImageElement) {
- label = cvox.DomUtil.getImageTitle(node);
- } else if (node.tagName == 'FIELDSET') {
- // Other labels will trump fieldset legend with this implementation.
- // Depending on how this works out on the web, we may later switch this
- // to appending the fieldset legend to any existing label.
- var legends = node.getElementsByTagName('LEGEND');
- label = '';
- for (var legend, i = 0; legend = legends[i]; i++) {
- label += ' ' + cvox.DomUtil.getName(legend, true, includeControls);
- }
- }
-
- if (label.length == 0 && node && node.id) {
- var labelFor = document.querySelector('label[for="' + node.id + '"]');
- if (labelFor) {
- label = cvox.DomUtil.getName(labelFor, recursive, includeControls);
- }
- }
- }
- return cvox.DomUtil.collapseWhitespace(label);
-};
-
-/**
- * Gets the nearest label in the ancestor chain, if one exists.
- * @param {Node} node The node to start from.
- * @return {string} The label.
- * @private
- */
-cvox.DomUtil.getNearestAncestorLabel_ = function(node) {
- var label = '';
- var enclosingLabel = node;
- while (enclosingLabel && enclosingLabel.tagName != 'LABEL') {
- enclosingLabel = enclosingLabel.parentElement;
- }
- if (enclosingLabel && !enclosingLabel.hasAttribute('for')) {
- // Get all text from the label but don't include any controls.
- label = cvox.DomUtil.getName(enclosingLabel, true, false);
- }
- return label;
-};
-
-
-/**
- * Gets the name for an input element.
- * @param {Node} node The node.
- * @return {string} The name.
- * @private
- */
-cvox.DomUtil.getInputName_ = function(node) {
- var label = '';
- if (node.type == 'image') {
- label = cvox.DomUtil.getImageTitle(node);
- } else if (node.type == 'submit') {
- if (node.hasAttribute('value')) {
- label = node.getAttribute('value');
- } else {
- label = 'Submit';
- }
- } else if (node.type == 'reset') {
- if (node.hasAttribute('value')) {
- label = node.getAttribute('value');
- } else {
- label = 'Reset';
- }
- } else if (node.type == 'button') {
- if (node.hasAttribute('value')) {
- label = node.getAttribute('value');
- }
- }
- return label;
-};
-
-/**
- * Wraps getName_ with marking and unmarking nodes so that infinite loops
- * don't occur. This is the ugly way to solve this; getName should not ever
- * do a recursive call somewhere above it in the tree.
- * @param {Node} node See getName_.
- * @param {boolean=} recursive See getName_.
- * @param {boolean=} includeControls See getName_.
- * @param {boolean=} opt_allowHidden Allows hidden nodes in name computation.
- * @return {string} See getName_.
- */
-cvox.DomUtil.getName = function(
- node, recursive, includeControls, opt_allowHidden) {
- if (!node || node.cvoxGetNameMarked == true) {
- return '';
- }
- node.cvoxGetNameMarked = true;
- var ret =
- cvox.DomUtil.getName_(node, recursive, includeControls, opt_allowHidden);
- node.cvoxGetNameMarked = false;
- var prefix = cvox.DomUtil.getPrefixText(node);
- return prefix + ret;
-};
-
-// TODO(dtseng): Seems like this list should be longer...
-/**
- * Determines if a node has a name obtained from concatinating the names of its
- * children.
- * @param {!Node} node The node under consideration.
- * @param {boolean=} opt_allowHidden Allows hidden nodes in name computation.
- * @return {boolean} True if node has name based on children.
- * @private
- */
-cvox.DomUtil.hasChildrenBasedName_ = function(node, opt_allowHidden) {
- if (!!cvox.DomPredicates.linkPredicate([node]) ||
- !!cvox.DomPredicates.headingPredicate([node]) ||
- node.tagName == 'BUTTON' ||
- cvox.AriaUtil.isControlWidget(node) ||
- !cvox.DomUtil.isLeafNode(node, opt_allowHidden)) {
- return true;
- } else {
- return false;
- }
-};
-
-/**
- * Get the name of a node: this includes all static text content and any
- * HTML-author-specified label, title, alt text, aria-label, etc. - but
- * does not include:
- * - the user-generated control value (use getValue)
- * - the current state (use getState)
- * - the role (use getRole)
- *
- * Order of precedence:
- * Text content if it's a text node.
- * aria-labelledby
- * aria-label
- * alt (for an image)
- * title
- * label (for a control)
- * placeholder (for an input element)
- * recursive calls to getName on all children
- *
- * @param {Node} node The node to get the name from.
- * @param {boolean=} recursive Whether or not the element's subtree should
- * be used; true by default.
- * @param {boolean=} includeControls Whether or not controls in the subtree
- * should be included; true by default.
- * @param {boolean=} opt_allowHidden Allows hidden nodes in name computation.
- * @return {string} The name of the node.
- * @private
- */
-cvox.DomUtil.getName_ = function(
- node, recursive, includeControls, opt_allowHidden) {
- if (typeof(recursive) === 'undefined') {
- recursive = true;
- }
- if (typeof(includeControls) === 'undefined') {
- includeControls = true;
- }
-
- if (node.constructor == Text) {
- return node.data;
- }
-
- var label = cvox.DomUtil.getBaseLabel_(node, recursive, includeControls);
-
- if (label.length == 0 && cvox.DomUtil.isControl(node)) {
- label = cvox.DomUtil.getNearestAncestorLabel_(node);
- }
-
- if (label.length == 0 && node.constructor == HTMLInputElement) {
- label = cvox.DomUtil.getInputName_(node);
- }
-
- if (cvox.DomUtil.isInputTypeText(node) && node.hasAttribute('placeholder')) {
- var placeholder = node.getAttribute('placeholder');
- if (label.length > 0) {
- if (cvox.DomUtil.getValue(node).length > 0) {
- return label;
- } else {
- return label + ' with hint ' + placeholder;
- }
- } else {
- return placeholder;
- }
- }
-
- if (label.length > 0) {
- return label;
- }
-
- // Fall back to naming via title only if there is no text content.
- if (cvox.DomUtil.collapseWhitespace(node.textContent).length == 0 &&
- node.hasAttribute &&
- node.hasAttribute('title')) {
- return node.getAttribute('title');
- }
-
- if (!recursive) {
- return '';
- }
-
- if (cvox.AriaUtil.isCompositeControl(node)) {
- return '';
- }
- if (cvox.DomUtil.hasChildrenBasedName_(node, opt_allowHidden)) {
- return cvox.DomUtil.getNameFromChildren(
- node, includeControls, opt_allowHidden);
- }
- return '';
-};
-
-
-/**
- * Get the name from the children of a node, not including the node itself.
- *
- * @param {Node} node The node to get the name from.
- * @param {boolean=} includeControls Whether or not controls in the subtree
- * should be included; true by default.
- * @param {boolean=} opt_allowHidden Allow hidden nodes in name computation.
- * @return {string} The concatenated text of all child nodes.
- */
-cvox.DomUtil.getNameFromChildren = function(
- node, includeControls, opt_allowHidden) {
- if (includeControls == undefined) {
- includeControls = true;
- }
- var name = '';
- var delimiter = '';
- for (var i = 0; i < node.childNodes.length; i++) {
- var child = node.childNodes[i];
- var prevChild = node.childNodes[i - 1] || child;
- if (!includeControls && cvox.DomUtil.isControl(child)) {
- continue;
- }
- var isVisible = cvox.DomUtil.isVisible(child, {checkAncestors: false});
- if (opt_allowHidden || (isVisible && !cvox.AriaUtil.isHidden(child))) {
- delimiter = (prevChild.tagName == 'SPAN' ||
- child.tagName == 'SPAN' ||
- child.parentNode.tagName == 'SPAN') ?
- '' : ' ';
- name += delimiter + cvox.DomUtil.getName(child, true, includeControls);
- }
- }
-
- return name;
-};
-
-/**
- * Get any prefix text for the given node.
- * This includes list style text for the leftmost leaf node under a listitem.
- * @param {Node} node Compute prefix for this node.
- * @param {number=} opt_index Starting offset into the given node's text.
- * @return {string} Prefix text, if any.
- */
-cvox.DomUtil.getPrefixText = function(node, opt_index) {
- opt_index = opt_index || 0;
-
- // Generate list style text.
- var ancestors = cvox.DomUtil.getAncestors(node);
- var prefix = '';
- var firstListitem = cvox.DomPredicates.listItemPredicate(ancestors);
-
- var leftmost = firstListitem;
- while (leftmost && leftmost.firstChild) {
- leftmost = leftmost.firstChild;
- }
-
- // Do nothing if we're not at the leftmost leaf.
- if (firstListitem &&
- firstListitem.parentNode &&
- opt_index == 0 &&
- firstListitem.parentNode.tagName == 'OL' &&
- node == leftmost &&
- document.defaultView.getComputedStyle(firstListitem.parentNode)
- .listStyleType != 'none') {
- var items = cvox.DomUtil.toArray(firstListitem.parentNode.children).filter(
- function(li) { return li.tagName == 'LI'; });
- var position = items.indexOf(firstListitem) + 1;
- // TODO(dtseng): Support all list style types.
- if (document.defaultView.getComputedStyle(
- firstListitem.parentNode).listStyleType.indexOf('latin') != -1) {
- position--;
- prefix = String.fromCharCode('A'.charCodeAt(0) + position % 26);
- } else {
- prefix = position;
- }
- prefix += '. ';
- }
- return prefix;
-};
-
-
-/**
- * Use heuristics to guess at the label of a control, to be used if one
- * is not explicitly set in the DOM. This is useful when a control
- * field gets focus, but probably not useful when browsing the page
- * element at a time.
- * @param {Node} node The node to get the label from.
- * @return {string} The name of the control, using heuristics.
- */
-cvox.DomUtil.getControlLabelHeuristics = function(node) {
- // If the node explicitly has aria-label or title set to '',
- // treat it the same way as alt='' and do not guess - just assume
- // the web developer knew what they were doing and wanted
- // no title/label for that control.
- if (node.hasAttribute &&
- ((node.hasAttribute('aria-label') &&
- (node.getAttribute('aria-label') == '')) ||
- (node.hasAttribute('aria-title') &&
- (node.getAttribute('aria-title') == '')))) {
- return '';
- }
-
- // TODO (clchen, rshearer): Implement heuristics for getting the label
- // information from the table headers once the code for getting table
- // headers quickly is implemented.
-
- // If no description has been found yet and heuristics are enabled,
- // then try getting the content from the closest node.
- var prevNode = cvox.DomUtil.previousLeafNode(node);
- var prevTraversalCount = 0;
- while (prevNode && (!cvox.DomUtil.hasContent(prevNode) ||
- cvox.DomUtil.isControl(prevNode))) {
- prevNode = cvox.DomUtil.previousLeafNode(prevNode);
- prevTraversalCount++;
- }
- var nextNode = cvox.DomUtil.directedNextLeafNode(node);
- var nextTraversalCount = 0;
- while (nextNode && (!cvox.DomUtil.hasContent(nextNode) ||
- cvox.DomUtil.isControl(nextNode))) {
- nextNode = cvox.DomUtil.directedNextLeafNode(nextNode);
- nextTraversalCount++;
- }
- var guessedLabelNode;
- if (prevNode && nextNode) {
- var parentNode = node;
- // Count the number of parent nodes until there is a shared parent; the
- // label is most likely in the same branch of the DOM as the control.
- // TODO (chaitanyag): Try to generalize this algorithm and move it to
- // its own function in DOM Utils.
- var prevCount = 0;
- while (parentNode) {
- if (cvox.DomUtil.isDescendantOfNode(prevNode, parentNode)) {
- break;
- }
- parentNode = parentNode.parentNode;
- prevCount++;
- }
- parentNode = node;
- var nextCount = 0;
- while (parentNode) {
- if (cvox.DomUtil.isDescendantOfNode(nextNode, parentNode)) {
- break;
- }
- parentNode = parentNode.parentNode;
- nextCount++;
- }
- guessedLabelNode = nextCount < prevCount ? nextNode : prevNode;
- } else {
- guessedLabelNode = prevNode || nextNode;
- }
- if (guessedLabelNode) {
- return cvox.DomUtil.collapseWhitespace(
- cvox.DomUtil.getValue(guessedLabelNode) + ' ' +
- cvox.DomUtil.getName(guessedLabelNode));
- }
-
- return '';
-};
-
-
-/**
- * Get the text value of a node: the selected value of a select control or the
- * current text of a text control. Does not return the state of a checkbox
- * or radio button.
- *
- * Not recursive.
- *
- * @param {Node} node The node to get the value from.
- * @return {string} The value of the node.
- */
-cvox.DomUtil.getValue = function(node) {
- var activeDescendant = cvox.AriaUtil.getActiveDescendant(node);
- if (activeDescendant) {
- return cvox.DomUtil.collapseWhitespace(
- cvox.DomUtil.getValue(activeDescendant) + ' ' +
- cvox.DomUtil.getName(activeDescendant));
- }
-
- if (node.constructor == HTMLSelectElement) {
- node = /** @type {HTMLSelectElement} */(node);
- var value = '';
- var start = node.selectedOptions ? node.selectedOptions[0] : null;
- var end = node.selectedOptions ?
- node.selectedOptions[node.selectedOptions.length - 1] : null;
- // TODO(dtseng): Keeping this stateless means we describe the start and end
- // of the selection only since we don't know which was added or
- // removed. Once we keep the previous selection, we can read the diff.
- if (start && end && start != end) {
- value = Msgs.getMsg(
- 'selected_options_value', [start.text, end.text]);
- } else if (start) {
- value = start.text + '';
- }
- return value;
- }
-
- if (node.constructor == HTMLTextAreaElement) {
- return node.value;
- }
-
- if (node.constructor == HTMLInputElement) {
- switch (node.type) {
- // Returning '' for inputs that are covered by getName.
- case 'hidden':
- case 'image':
- case 'submit':
- case 'reset':
- case 'button':
- case 'checkbox':
- case 'radio':
- return '';
- case 'password':
- return node.value.replace(/./g, 'dot ');
- default:
- return node.value;
- }
- }
-
- if (node.isContentEditable) {
- return cvox.DomUtil.getNameFromChildren(node, true);
- }
-
- return '';
-};
-
-
-/**
- * Given an image node, return its title as a string. The preferred title
- * is always the alt text, and if that's not available, then the title
- * attribute. If neither of those are available, it attempts to construct
- * a title from the filename, and if all else fails returns the word Image.
- * @param {Node} node The image node.
- * @return {string} The title of the image.
- */
-cvox.DomUtil.getImageTitle = function(node) {
- var text;
- if (node.hasAttribute('alt')) {
- text = node.alt;
- } else if (node.hasAttribute('title')) {
- text = node.title;
- } else {
- var url = node.src;
- if (url.substring(0, 4) != 'data') {
- var filename = url.substring(
- url.lastIndexOf('/') + 1, url.lastIndexOf('.'));
-
- // Hack to not speak the filename if it's ridiculously long.
- if (filename.length >= 1 && filename.length <= 16) {
- text = filename + ' Image';
- } else {
- text = 'Image';
- }
- } else {
- text = 'Image';
- }
- }
- return text;
-};
-
-
-/**
- * Search the whole page for any aria-labelledby attributes and collect
- * 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<boolean>} Set of all ids that are mapped by aria-labelledby.
- */
-cvox.DomUtil.getLabelledByTargets = function() {
- if (cvox.labelledByTargets) {
- return cvox.labelledByTargets;
- }
-
- // Start by getting all elements with
- // aria-labelledby on the page since that's probably a short list,
- // then see if any of those ids overlap with an id in this element's
- // ancestor chain.
- var labelledByElements = document.querySelectorAll('[aria-labelledby]');
- var labelledByTargets = {};
- for (var i = 0; i < labelledByElements.length; ++i) {
- var element = labelledByElements[i];
- var attrValue = element.getAttribute('aria-labelledby');
- var ids = attrValue.split(/ +/);
- for (var j = 0; j < ids.length; j++) {
- labelledByTargets[ids[j]] = true;
- }
- }
- cvox.labelledByTargets = labelledByTargets;
-
- window.setTimeout(function() {
- cvox.labelledByTargets = null;
- }, 0);
-
- return labelledByTargets;
-};
-
-
-/**
- * Determines whether or not a node has content.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} True if the node has content.
- */
-cvox.DomUtil.hasContent = function(node) {
- // Memoize the result of the internal content computation so that
- // within the same call stack, we don't need to redo the computation
- // on the same node twice.
- return /** @type {boolean} */ (cvox.Memoize.memoize(
- cvox.DomUtil.computeHasContent_.bind(this), 'hasContent', node));
-};
-
-/**
- * Internal implementation of |cvox.DomUtil.hasContent|.
- *
- * @param {Node} node The node to be checked.
- * @return {boolean} True if the node has content.
- * @private
- */
-cvox.DomUtil.computeHasContent_ = function(node) {
- // nodeType:8 == COMMENT_NODE
- if (node.nodeType == 8) {
- return false;
- }
-
- // Exclude anything in the head
- if (cvox.DomUtil.isDescendantOf(node, 'HEAD')) {
- return false;
- }
-
- // Exclude script nodes
- if (cvox.DomUtil.isDescendantOf(node, 'SCRIPT')) {
- return false;
- }
-
- // Exclude noscript nodes
- if (cvox.DomUtil.isDescendantOf(node, 'NOSCRIPT')) {
- return false;
- }
-
- // Exclude noembed nodes since NOEMBED is deprecated. We treat
- // noembed as having not content rather than try to get its content since
- // Chrome will return raw HTML content rather than a valid DOM subtree.
- if (cvox.DomUtil.isDescendantOf(node, 'NOEMBED')) {
- return false;
- }
-
- // Exclude style nodes that have been dumped into the body.
- if (cvox.DomUtil.isDescendantOf(node, 'STYLE')) {
- return false;
- }
-
- // Check the style to exclude undisplayed/hidden nodes.
- if (!cvox.DomUtil.isVisible(node)) {
- return false;
- }
-
- // Ignore anything that is hidden by ARIA.
- if (cvox.AriaUtil.isHidden(node)) {
- return false;
- }
-
- // We need to speak controls, including those with no value entered. We
- // therefore treat visible controls as if they had content, and return true
- // below.
- if (cvox.DomUtil.isControl(node)) {
- return true;
- }
-
- // Videos are always considered to have content so that we can navigate to
- // and use the controls of the video widget.
- if (cvox.DomUtil.isDescendantOf(node, 'VIDEO')) {
- return true;
- }
- // Audio elements are always considered to have content so that we can
- // navigate to and use the controls of the audio widget.
- if (cvox.DomUtil.isDescendantOf(node, 'AUDIO')) {
- return true;
- }
-
- // We want to try to jump into an iframe iff it has a src attribute.
- // For right now, we will avoid iframes without any content in their src since
- // ChromeVox is not being injected in those cases and will cause the user to
- // get stuck.
- // TODO (clchen, dmazzoni): Manually inject ChromeVox for iframes without src.
- if ((node.tagName == 'IFRAME') && (node.src) &&
- (node.src.indexOf('javascript:') != 0)) {
- return true;
- }
-
- var controlQuery = 'button,input,select,textarea';
-
- // Skip any non-control content inside of a label if the label is
- // correctly associated with a control, the label text will get spoken
- // when the control is reached.
- var enclosingLabel = node.parentElement;
- while (enclosingLabel && enclosingLabel.tagName != 'LABEL') {
- enclosingLabel = enclosingLabel.parentElement;
- }
- if (enclosingLabel) {
- var embeddedControl = enclosingLabel.querySelector(controlQuery);
- if (enclosingLabel.hasAttribute('for')) {
- var targetId = enclosingLabel.getAttribute('for');
- var targetNode = document.getElementById(targetId);
- if (targetNode &&
- cvox.DomUtil.isControl(targetNode) &&
- !embeddedControl) {
- return false;
- }
- } else if (embeddedControl) {
- return false;
- }
- }
-
- // Skip any non-control content inside of a legend if the legend is correctly
- // nested within a fieldset. The legend text will get spoken when the fieldset
- // is reached.
- var enclosingLegend = node.parentElement;
- while (enclosingLegend && enclosingLegend.tagName != 'LEGEND') {
- enclosingLegend = enclosingLegend.parentElement;
- }
- if (enclosingLegend) {
- var legendAncestor = enclosingLegend.parentElement;
- while (legendAncestor && legendAncestor.tagName != 'FIELDSET') {
- legendAncestor = legendAncestor.parentElement;
- }
- var embeddedControl =
- legendAncestor && legendAncestor.querySelector(controlQuery);
- if (legendAncestor && !embeddedControl) {
- return false;
- }
- }
-
- if (!!cvox.DomPredicates.linkPredicate([node])) {
- return true;
- }
-
- // At this point, any non-layout tables are considered to have content.
- // For layout tables, it is safe to consider them as without content since the
- // sync operation would select a descendant of a layout table if possible. The
- // only instance where |hasContent| gets called on a layout table is if no
- // descendants have content (see |AbstractNodeWalker.next|).
- if (node.tagName == 'TABLE' && !cvox.DomUtil.isLayoutTable(node)) {
- return true;
- }
-
- // Math is always considered to have content.
- if (cvox.DomUtil.isMath(node)) {
- return true;
- }
-
- if (cvox.DomPredicates.headingPredicate([node])) {
- return true;
- }
-
- if (cvox.DomUtil.isFocusable(node)) {
- return true;
- }
-
- // Skip anything referenced by another element on the page
- // via aria-labelledby.
- var labelledByTargets = cvox.DomUtil.getLabelledByTargets();
- var enclosingNodeWithId = node;
- while (enclosingNodeWithId) {
- if (enclosingNodeWithId.id &&
- labelledByTargets[enclosingNodeWithId.id]) {
- // If we got here, some element on this page has an aria-labelledby
- // attribute listing this node as its id. As long as that "some" element
- // is not this element, we should return false, indicating this element
- // should be skipped.
- var attrValue = enclosingNodeWithId.getAttribute('aria-labelledby');
- if (attrValue) {
- var ids = attrValue.split(/ +/);
- if (ids.indexOf(enclosingNodeWithId.id) == -1) {
- return false;
- }
- } else {
- return false;
- }
- }
- enclosingNodeWithId = enclosingNodeWithId.parentElement;
- }
-
- var text = cvox.DomUtil.getValue(node) + ' ' + cvox.DomUtil.getName(node);
- var state = cvox.DomUtil.getState(node, true);
- if (text.match(/^\s+$/) && state === '') {
- // Text only contains whitespace
- return false;
- }
-
- return true;
-};
-
-
-/**
- * Returns a list of all the ancestors of a given node. The last element
- * is the current node.
- *
- * @param {Node} targetNode The node to get ancestors for.
- * @return {Array<Node>} An array of ancestors for the targetNode.
- */
-cvox.DomUtil.getAncestors = function(targetNode) {
- var ancestors = new Array();
- while (targetNode) {
- ancestors.push(targetNode);
- targetNode = targetNode.parentNode;
- }
- ancestors.reverse();
- while (ancestors.length && !ancestors[0].tagName && !ancestors[0].nodeValue) {
- ancestors.shift();
- }
- return ancestors;
-};
-
-
-/**
- * Compares Ancestors of A with Ancestors of B and returns
- * the index value in B at which B diverges from A.
- * If there is no divergence, the result will be -1.
- * Note that if B is the same as A except B has more nodes
- * even after A has ended, that is considered a divergence.
- * The first node that B has which A does not have will
- * be treated as the divergence point.
- *
- * @param {Object} ancestorsA The array of ancestors for Node A.
- * @param {Object} ancestorsB The array of ancestors for Node B.
- * @return {number} The index of the divergence point (the first node that B has
- * which A does not have in B's list of ancestors).
- */
-cvox.DomUtil.compareAncestors = function(ancestorsA, ancestorsB) {
- var i = 0;
- while (ancestorsA[i] && ancestorsB[i] && (ancestorsA[i] == ancestorsB[i])) {
- i++;
- }
- if (!ancestorsA[i] && !ancestorsB[i]) {
- i = -1;
- }
- return i;
-};
-
-
-/**
- * Returns an array of ancestors that are unique for the currentNode when
- * compared to the previousNode. Having such an array is useful in generating
- * the node information (identifying when interesting node boundaries have been
- * crossed, etc.).
- *
- * @param {Node} previousNode The previous node.
- * @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
- * (inclusive).
- */
-cvox.DomUtil.getUniqueAncestors = function(
- previousNode, currentNode, opt_fallback) {
- var prevAncestors = cvox.DomUtil.getAncestors(previousNode);
- var currentAncestors = cvox.DomUtil.getAncestors(currentNode);
- var divergence = cvox.DomUtil.compareAncestors(prevAncestors,
- currentAncestors);
- var diff = currentAncestors.slice(divergence);
- return (diff.length == 0 && opt_fallback) ? currentAncestors : diff;
-};
-
-
-/**
- * Returns a role message identifier for a node.
- * For a localized string, see cvox.DomUtil.getRole.
- * @param {Node} targetNode The node to get the role name for.
- * @param {number} verbosity The verbosity setting to use.
- * @return {string} The role message identifier for the targetNode.
- */
-cvox.DomUtil.getRoleMsg = function(targetNode, verbosity) {
- var info;
- info = cvox.AriaUtil.getRoleNameMsg(targetNode);
- if (!info) {
- if (targetNode.tagName == 'INPUT') {
- info = cvox.DomUtil.INPUT_TYPE_TO_INFORMATION_TABLE_MSG[targetNode.type];
- } else if (targetNode.tagName == 'A' &&
- 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) {
- info = 'input_type_text';
- } else if (cvox.DomUtil.isMath(targetNode)) {
- info = 'math_expr';
- } else if (targetNode.tagName == 'TABLE' &&
- cvox.DomUtil.isLayoutTable(targetNode)) {
- info = '';
- } else {
- if (verbosity == cvox.VERBOSITY_BRIEF) {
- info =
- cvox.DomUtil.TAG_TO_INFORMATION_TABLE_BRIEF_MSG[targetNode.tagName];
- } else {
- info = cvox.DomUtil.TAG_TO_INFORMATION_TABLE_VERBOSE_MSG[
- targetNode.tagName];
-
- if (cvox.DomUtil.hasLongDesc(targetNode)) {
- info = 'image_with_long_desc';
- }
-
- if (!info && targetNode.onclick) {
- info = 'clickable';
- }
- }
- }
- }
-
- return info;
-};
-
-
-/**
- * Returns a string to be presented to the user that identifies what the
- * targetNode's role is.
- * ARIA roles are given priority; if there is no ARIA role set, the role
- * will be determined by the HTML tag for the node.
- *
- * @param {Node} targetNode The node to get the role name for.
- * @param {number} verbosity The verbosity setting to use.
- * @return {string} The role name for the targetNode.
- */
-cvox.DomUtil.getRole = function(targetNode, verbosity) {
- var roleMsg = cvox.DomUtil.getRoleMsg(targetNode, verbosity) || '';
- var role = roleMsg && roleMsg != ' ' ?
- Msgs.getMsg(roleMsg) : '';
- return role ? role : roleMsg;
-};
-
-
-/**
- * Count the number of items in a list node.
- *
- * @param {Node} targetNode The list node.
- * @return {number} The number of items in the list.
- */
-cvox.DomUtil.getListLength = function(targetNode) {
- var count = 0;
- for (var node = targetNode.firstChild;
- node;
- node = node.nextSibling) {
- if (cvox.DomUtil.isVisible(node) &&
- (node.tagName == 'LI' ||
- (node.getAttribute && node.getAttribute('role') == 'listitem'))) {
- if (node.hasAttribute('aria-setsize')) {
- var ariaLength = parseInt(node.getAttribute('aria-setsize'), 10);
- if (!isNaN(ariaLength)) {
- return ariaLength;
- }
- }
- count++;
- }
- }
- return count;
-};
-
-
-/**
- * Returns a NodeState that gives information about the state of the targetNode.
- *
- * @param {Node} targetNode The node to get the state information for.
- * @param {boolean} primary Whether this is the primary node we're
- * interested in, where we might want extra information - as
- * opposed to an ancestor, where we might be more brief.
- * @return {cvox.NodeState} The status information about the node.
- */
-cvox.DomUtil.getStateMsgs = function(targetNode, primary) {
- var activeDescendant = cvox.AriaUtil.getActiveDescendant(targetNode);
- if (activeDescendant) {
- return cvox.DomUtil.getStateMsgs(activeDescendant, primary);
- }
- var info = [];
- var role = targetNode.getAttribute ? targetNode.getAttribute('role') : '';
- info = cvox.AriaUtil.getStateMsgs(targetNode, primary);
- if (!info) {
- info = [];
- }
-
- if (targetNode.tagName == 'INPUT') {
- if (!targetNode.hasAttribute('aria-checked')) {
- var INPUT_MSGS = {
- 'checkbox-true': 'checkbox_checked_state',
- 'checkbox-false': 'checkbox_unchecked_state',
- 'radio-true': 'radio_selected_state',
- 'radio-false': 'radio_unselected_state' };
- var msgId = INPUT_MSGS[targetNode.type + '-' + !!targetNode.checked];
- if (msgId) {
- info.push([msgId]);
- }
- }
- } else if (targetNode.tagName == 'SELECT') {
- if (targetNode.selectedOptions && targetNode.selectedOptions.length <= 1) {
- info.push(['list_position',
- Msgs.getNumber(targetNode.selectedIndex + 1),
- Msgs.getNumber(targetNode.options.length)]);
- } else {
- info.push(['selected_options_state',
- Msgs.getNumber(targetNode.selectedOptions.length)]);
- }
- } else if (targetNode.tagName == 'UL' ||
- targetNode.tagName == 'OL' ||
- role == 'list') {
- info.push(['list_with_items_not_pluralized',
- Msgs.getNumber(
- cvox.DomUtil.getListLength(targetNode))]);
- }
-
- if (cvox.DomUtil.isDisabled(targetNode)) {
- info.push(['aria_disabled_true']);
- }
-
- if (targetNode.accessKey) {
- info.push(['access_key', targetNode.accessKey]);
- }
-
- return info;
-};
-
-
-/**
- * Returns a string that gives information about the state of the targetNode.
- *
- * @param {Node} targetNode The node to get the state information for.
- * @param {boolean} primary Whether this is the primary node we're
- * interested in, where we might want extra information - as
- * opposed to an ancestor, where we might be more brief.
- * @return {string} The status information about the node.
- */
-cvox.DomUtil.getState = function(targetNode, primary) {
- return cvox.NodeStateUtil.expand(
- cvox.DomUtil.getStateMsgs(targetNode, primary));
-};
-
-
-/**
- * Return whether a node is focusable. This includes nodes whose tabindex
- * attribute is set to "-1" explicitly - these nodes are not in the tab
- * order, but they should still be focused if the user navigates to them
- * using linear or smart DOM navigation.
- *
- * Note that when the tabIndex property of an Element is -1, that doesn't
- * tell us whether the tabIndex attribute is missing or set to "-1" explicitly,
- * so we have to check the attribute.
- *
- * @param {Object} targetNode The node to check if it's focusable.
- * @return {boolean} True if the node is focusable.
- */
-cvox.DomUtil.isFocusable = function(targetNode) {
- if (!targetNode || typeof(targetNode.tabIndex) != 'number') {
- return false;
- }
-
- // Workaround for http://code.google.com/p/chromium/issues/detail?id=153904
- if ((targetNode.tagName == 'A') && !targetNode.hasAttribute('href') &&
- !targetNode.hasAttribute('tabindex')) {
- return false;
- }
-
- if (targetNode.tabIndex >= 0) {
- return true;
- }
-
- if (targetNode.hasAttribute &&
- targetNode.hasAttribute('tabindex') &&
- targetNode.getAttribute('tabindex') == '-1') {
- return true;
- }
-
- return false;
-};
-
-
-/**
- * Find a focusable descendant of a given node. This includes nodes whose
- * tabindex attribute is set to "-1" explicitly - these nodes are not in the
- * tab order, but they should still be focused if the user navigates to them
- * using linear or smart DOM navigation.
- *
- * @param {Node} targetNode The node whose descendants to check if focusable.
- * @return {Node} The focusable descendant node. Null if no descendant node
- * was found.
- */
-cvox.DomUtil.findFocusableDescendant = function(targetNode) {
- // Search down the descendants chain until a focusable node is found
- if (targetNode) {
- var focusableNode =
- cvox.DomUtil.findNode(targetNode, cvox.DomUtil.isFocusable);
- if (focusableNode) {
- return focusableNode;
- }
- }
- return null;
-};
-
-
-/**
- * Returns the number of focusable nodes in root's subtree. The count does not
- * include root.
- *
- * @param {Node} targetNode The node whose descendants to check are focusable.
- * @return {number} The number of focusable descendants.
- */
-cvox.DomUtil.countFocusableDescendants = function(targetNode) {
- return targetNode ?
- cvox.DomUtil.countNodes(targetNode, cvox.DomUtil.isFocusable) : 0;
-};
-
-
-/**
- * Checks if the targetNode is still attached to the document.
- * A node can become detached because of AJAX changes.
- *
- * @param {Object} targetNode The node to check.
- * @return {boolean} True if the targetNode is still attached.
- */
-cvox.DomUtil.isAttachedToDocument = function(targetNode) {
- while (targetNode) {
- if (targetNode.tagName && (targetNode.tagName == 'HTML')) {
- return true;
- }
- targetNode = targetNode.parentNode;
- }
- return false;
-};
-
-
-/**
- * Dispatches a left click event on the element that is the targetNode.
- * Clicks go in the sequence of mousedown, mouseup, and click.
- * @param {Node} targetNode The target node of this operation.
- * @param {boolean} shiftKey Specifies if shift is held down.
- * @param {boolean} callOnClickDirectly Specifies whether or not to directly
- * invoke the onclick method if there is one.
- * @param {boolean=} opt_double True to issue a double click.
- * @param {boolean=} opt_handleOwnEvents Whether to handle the generated
- * events through the normal event processing.
- */
-cvox.DomUtil.clickElem = function(
- targetNode, shiftKey, callOnClickDirectly, opt_double,
- opt_handleOwnEvents) {
- // If there is an activeDescendant of the targetNode, then that is where the
- // click should actually be targeted.
- var activeDescendant = cvox.AriaUtil.getActiveDescendant(targetNode);
- if (activeDescendant) {
- targetNode = activeDescendant;
- }
- if (callOnClickDirectly) {
- var onClickFunction = null;
- if (targetNode.onclick) {
- onClickFunction = targetNode.onclick;
- }
- if (!onClickFunction && (targetNode.nodeType != 1) &&
- targetNode.parentNode && targetNode.parentNode.onclick) {
- onClickFunction = targetNode.parentNode.onclick;
- }
- var keepGoing = true;
- if (onClickFunction) {
- try {
- keepGoing = onClickFunction();
- } catch (exception) {
- // Something went very wrong with the onclick method; we'll ignore it
- // and just dispatch a click event normally.
- }
- }
- if (!keepGoing) {
- // The onclick method ran successfully and returned false, meaning the
- // event should not bubble up, so we will return here.
- return;
- }
- }
-
- // Send a mousedown (or simply a double click if requested).
- var evt = document.createEvent('MouseEvents');
- var evtType = opt_double ? 'dblclick' : 'mousedown';
- evt.initMouseEvent(evtType, true, true, document.defaultView,
- 1, 0, 0, 0, 0, false, false, shiftKey, false, 0, null);
- // Unless asked not to, Mark any events we generate so we don't try to
- // process our own events.
- evt.fromCvox = !opt_handleOwnEvents;
- try {
- targetNode.dispatchEvent(evt);
- } catch (e) {}
- //Send a mouse up
- evt = document.createEvent('MouseEvents');
- evt.initMouseEvent('mouseup', true, true, document.defaultView,
- 1, 0, 0, 0, 0, false, false, shiftKey, false, 0, null);
- evt.fromCvox = !opt_handleOwnEvents;
- try {
- targetNode.dispatchEvent(evt);
- } catch (e) {}
- //Send a click
- evt = document.createEvent('MouseEvents');
- evt.initMouseEvent('click', true, true, document.defaultView,
- 1, 0, 0, 0, 0, false, false, shiftKey, false, 0, null);
- evt.fromCvox = !opt_handleOwnEvents;
- try {
- targetNode.dispatchEvent(evt);
- } catch (e) {}
-
- if (cvox.DomUtil.isInternalLink(targetNode)) {
- cvox.DomUtil.syncInternalLink(targetNode);
- }
-};
-
-
-/**
- * Syncs to an internal link.
- * @param {Node} node A link whose href's target we want to sync.
- */
-cvox.DomUtil.syncInternalLink = function(node) {
- var targetNode;
- var targetId = node.href.split('#')[1];
- targetNode = document.getElementById(targetId);
- if (!targetNode) {
- var nodes = document.getElementsByName(targetId);
- if (nodes.length > 0) {
- targetNode = nodes[0];
- }
- }
- if (targetNode) {
- // Insert a dummy node to adjust next Tab focus location.
- var parent = targetNode.parentNode;
- var dummyNode = document.createElement('div');
- dummyNode.setAttribute('tabindex', '-1');
- parent.insertBefore(dummyNode, targetNode);
- dummyNode.setAttribute('chromevoxignoreariahidden', 1);
- dummyNode.focus();
- cvox.ChromeVox.syncToNode(targetNode, false);
- }
-};
-
-
-/**
- * Given an HTMLInputElement, returns true if it's an editable text type.
- * This includes input type='text' and input type='password' and a few
- * others.
- *
- * @param {Node} node The node to check.
- * @return {boolean} True if the node is an INPUT with an editable text type.
- */
-cvox.DomUtil.isInputTypeText = function(node) {
- if (!node || node.constructor != HTMLInputElement) {
- return false;
- }
-
- switch (node.type) {
- case 'email':
- case 'number':
- case 'password':
- case 'search':
- case 'text':
- case 'tel':
- case 'url':
- case '':
- return true;
- default:
- return false;
- }
-};
-
-
-/**
- * Given a node, returns true if it's a control. Controls are *not necessarily*
- * leaf-level given that some composite controls may have focusable children
- * if they are managing focus with tabindex:
- * ( http://www.w3.org/TR/2010/WD-wai-aria-practices-20100916/#visualfocus ).
- *
- * @param {Node} node The node to check.
- * @return {boolean} True if the node is a control.
- */
-cvox.DomUtil.isControl = function(node) {
- if (cvox.AriaUtil.isControlWidget(node) &&
- cvox.DomUtil.isFocusable(node)) {
- return true;
- }
- if (node.tagName) {
- switch (node.tagName) {
- case 'BUTTON':
- case 'TEXTAREA':
- case 'SELECT':
- return true;
- case 'INPUT':
- return node.type != 'hidden';
- }
- }
- if (node.isContentEditable) {
- return true;
- }
- return false;
-};
-
-
-/**
- * Given a node, returns true if it's a leaf-level control. This includes
- * composite controls thare are managing focus for children with
- * activedescendant, but not composite controls with focusable children:
- * ( http://www.w3.org/TR/2010/WD-wai-aria-practices-20100916/#visualfocus ).
- *
- * @param {Node} node The node to check.
- * @return {boolean} True if the node is a leaf-level control.
- */
-cvox.DomUtil.isLeafLevelControl = function(node) {
- if (cvox.DomUtil.isControl(node)) {
- return !(cvox.AriaUtil.isCompositeControl(node) &&
- cvox.DomUtil.findFocusableDescendant(node));
- }
- return false;
-};
-
-
-/**
- * Given a node that might be inside of a composite control like a listbox,
- * return the surrounding control.
- * @param {Node} node The node from which to start looking.
- * @return {Node} The surrounding composite control node, or null if none.
- */
-cvox.DomUtil.getSurroundingControl = function(node) {
- var surroundingControl = null;
- if (!cvox.DomUtil.isControl(node) && node.hasAttribute &&
- node.hasAttribute('role')) {
- surroundingControl = node.parentElement;
- while (surroundingControl &&
- !cvox.AriaUtil.isCompositeControl(surroundingControl)) {
- surroundingControl = surroundingControl.parentElement;
- }
- }
- return surroundingControl;
-};
-
-
-/**
- * Given a node and a function for determining when to stop
- * descent, return the next leaf-like node.
- *
- * @param {!Node} node The node from which to start looking,
- * this node *must not* be above document.body.
- * @param {boolean} r True if reversed. False by default.
- * @param {function(!Node):boolean} isLeaf A function that
- * returns true if we should stop descending.
- * @return {Node} The next leaf-like node or null if there is no next
- * leaf-like node. This function will always return a node below
- * document.body and never document.body itself.
- */
-cvox.DomUtil.directedNextLeafLikeNode = function(node, r, isLeaf) {
- if (node != document.body) {
- // if not at the top of the tree, we want to find the next possible
- // branch forward in the dom, so we climb up the parents until we find a
- // node that has a nextSibling
- while (!cvox.DomUtil.directedNextSibling(node, r)) {
- if (!node) {
- return null;
- }
- // since node is never above document.body, it always has a parent.
- // so node.parentNode will never be null.
- node = /** @type {!Node} */(node.parentNode);
- if (node == document.body) {
- // we've readed the end of the document.
- return null;
- }
- }
- if (cvox.DomUtil.directedNextSibling(node, r)) {
- // we just checked that next sibling is non-null.
- node = /** @type {!Node} */(cvox.DomUtil.directedNextSibling(node, r));
- }
- }
- // once we're at our next sibling, we want to descend down into it as
- // far as the child class will allow
- while (cvox.DomUtil.directedFirstChild(node, r) && !isLeaf(node)) {
- node = /** @type {!Node} */(cvox.DomUtil.directedFirstChild(node, r));
- }
-
- // after we've done all that, if we are still at document.body, this must
- // be an empty document.
- if (node == document.body) {
- return null;
- }
- return node;
-};
-
-
-/**
- * Given a node, returns the next leaf node.
- *
- * @param {!Node} node The node from which to start looking
- * for the next leaf node.
- * @param {boolean=} reverse True if reversed. False by default.
- * @return {Node} The next leaf node.
- * Null if there is no next leaf node.
- */
-cvox.DomUtil.directedNextLeafNode = function(node, reverse) {
- reverse = !!reverse;
- return cvox.DomUtil.directedNextLeafLikeNode(
- node, reverse, cvox.DomUtil.isLeafNode);
-};
-
-
-/**
- * Given a node, returns the previous leaf node.
- *
- * @param {!Node} node The node from which to start looking
- * for the previous leaf node.
- * @return {Node} The previous leaf node.
- * Null if there is no previous leaf node.
- */
-cvox.DomUtil.previousLeafNode = function(node) {
- return cvox.DomUtil.directedNextLeafNode(node, true);
-};
-
-
-/**
- * Computes the outer most leaf node of a given node, depending on value
- * of the reverse flag r.
- * @param {!Node} node in the DOM.
- * @param {boolean} r True if reversed. False by default.
- * @param {function(!Node):boolean} pred Predicate to decide
- * what we consider a leaf.
- * @return {Node} The outer most leaf node of that node.
- */
-cvox.DomUtil.directedFindFirstNode = function(node, r, pred) {
- var child = cvox.DomUtil.directedFirstChild(node, r);
- while (child) {
- if (pred(child)) {
- return child;
- } else {
- var leaf = cvox.DomUtil.directedFindFirstNode(child, r, pred);
- if (leaf) {
- return leaf;
- }
- }
- child = cvox.DomUtil.directedNextSibling(child, r);
- }
- return null;
-};
-
-
-/**
- * Moves to the deepest node satisfying a given predicate under the given node.
- * @param {!Node} node in the DOM.
- * @param {boolean} r True if reversed. False by default.
- * @param {function(!Node):boolean} pred Predicate deciding what a leaf is.
- * @return {Node} The deepest node satisfying pred.
- */
-cvox.DomUtil.directedFindDeepestNode = function(node, r, pred) {
- var next = cvox.DomUtil.directedFindFirstNode(node, r, pred);
- if (!next) {
- if (pred(node)) {
- return node;
- } else {
- return null;
- }
- } else {
- return cvox.DomUtil.directedFindDeepestNode(next, r, pred);
- }
-};
-
-
-/**
- * Computes the next node wrt. a predicate that is a descendant of ancestor.
- * @param {!Node} node in the DOM.
- * @param {!Node} ancestor of the given node.
- * @param {boolean} r True if reversed. False by default.
- * @param {function(!Node):boolean} pred Predicate to decide
- * what we consider a leaf.
- * @param {boolean=} above True if the next node can live in the subtree
- * directly above the start node. False by default.
- * @param {boolean=} deep True if we are looking for the next node that is
- * deepest in the tree. Otherwise the next shallow node is returned.
- * False by default.
- * @return {Node} The next node in the DOM that satisfies the predicate.
- */
-cvox.DomUtil.directedFindNextNode = function(
- node, ancestor, r, pred, above, deep) {
- above = !!above;
- deep = !!deep;
- if (!cvox.DomUtil.isDescendantOfNode(node, ancestor) || node == ancestor) {
- return null;
- }
- var next = cvox.DomUtil.directedNextSibling(node, r);
- while (next) {
- if (!deep && pred(next)) {
- return next;
- }
- var leaf = (deep ?
- cvox.DomUtil.directedFindDeepestNode :
- cvox.DomUtil.directedFindFirstNode)(next, r, pred);
- if (leaf) {
- return leaf;
- }
- if (deep && pred(next)) {
- return next;
- }
- next = cvox.DomUtil.directedNextSibling(next, r);
- }
- var parent = /** @type {!Node} */(node.parentNode);
- if (above && pred(parent)) {
- return parent;
- }
- return cvox.DomUtil.directedFindNextNode(
- parent, ancestor, r, pred, above, deep);
-};
-
-
-/**
- * Get a string representing a control's value and state, i.e. the part
- * that changes while interacting with the control
- * @param {Element} control A control.
- * @return {string} The value and state string.
- */
-cvox.DomUtil.getControlValueAndStateString = function(control) {
- var parentControl = cvox.DomUtil.getSurroundingControl(control);
- if (parentControl) {
- return cvox.DomUtil.collapseWhitespace(
- cvox.DomUtil.getValue(control) + ' ' +
- cvox.DomUtil.getName(control) + ' ' +
- cvox.DomUtil.getState(control, true));
- } else {
- return cvox.DomUtil.collapseWhitespace(
- cvox.DomUtil.getValue(control) + ' ' +
- cvox.DomUtil.getState(control, true));
- }
-};
-
-
-/**
- * Determine whether the given node is an internal link.
- * @param {Node} node The node to be examined.
- * @return {boolean} True if the node is an internal link, false otherwise.
- */
-cvox.DomUtil.isInternalLink = function(node) {
- if (node.nodeType == 1) { // Element nodes only.
- var href = node.getAttribute('href');
- if (href && href.indexOf('#') != -1) {
- var path = href.split('#')[0];
- return path == '' || path == window.location.pathname;
- }
- }
- return false;
-};
-
-
-/**
- * Get a string containing the currently selected link's URL.
- * @param {Node} node The link from which URL needs to be extracted.
- * @return {string} The value of the URL.
- */
-cvox.DomUtil.getLinkURL = function(node) {
- if (node.tagName == 'A') {
- if (node.getAttribute('href')) {
- if (cvox.DomUtil.isInternalLink(node)) {
- return Msgs.getMsg('internal_link');
- } else {
- return node.getAttribute('href');
- }
- } else {
- return '';
- }
- } else if (cvox.AriaUtil.getRoleName(node) ==
- Msgs.getMsg('role_link')) {
- return Msgs.getMsg('unknown_link');
- }
-
- return '';
-};
-
-
-/**
- * Checks if a given node is inside a table and returns the table node if it is
- * @param {Node} node The node.
- * @param {{allowCaptions: (undefined|boolean)}=} kwargs Optional named args.
- * allowCaptions: If true, will return true even if inside a caption. False
- * by default.
- * @return {Node} If the node is inside a table, the table node. Null if it
- * is not.
- */
-cvox.DomUtil.getContainingTable = function(node, kwargs) {
- var ancestors = cvox.DomUtil.getAncestors(node);
- return cvox.DomUtil.findTableNodeInList(ancestors, kwargs);
-};
-
-
-/**
- * Extracts a table node from a 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.
- * @return {Node} The table node if the list of nodes contains a table node.
- * Null if it does not.
- */
-cvox.DomUtil.findTableNodeInList = function(nodes, kwargs) {
- kwargs = kwargs || {allowCaptions: false};
- // Don't include the caption node because it is actually rendered outside
- // of the table.
- for (var i = nodes.length - 1, node; node = nodes[i]; i--) {
- if (node.constructor != Text) {
- if (!kwargs.allowCaptions && node.tagName == 'CAPTION') {
- return null;
- }
- if ((node.tagName == 'TABLE') || cvox.AriaUtil.isGrid(node)) {
- return node;
- }
- }
- }
- return null;
-};
-
-
-/**
- * Determines whether a given table is a data table or a layout table
- * @param {Node} tableNode The table node.
- * @return {boolean} If the table is a layout table, returns true. False
- * otherwise.
- */
-cvox.DomUtil.isLayoutTable = function(tableNode) {
- // TODO(stoarca): Why are we returning based on this inaccurate heuristic
- // instead of first trying the better heuristics below?
- if (tableNode.rows && (tableNode.rows.length <= 1 ||
- (tableNode.rows[0].childElementCount == 1))) {
- // This table has either 0 or one rows, or only "one" column.
- // This is a quick check for column count and may not be accurate. See
- // TraverseTable.getW3CColCount_ for a more accurate
- // (but more complicated) way to determine column count.
- return true;
- }
-
- // These heuristics are adapted from the Firefox data and layout table.
- // heuristics: http://asurkov.blogspot.com/2011/10/data-vs-layout-table.html
- if (cvox.AriaUtil.isGrid(tableNode)) {
- // This table has an ARIA role identifying it as a grid.
- // Not a layout table.
- return false;
- }
- if (cvox.AriaUtil.isLandmark(tableNode)) {
- // This table has an ARIA landmark role - not a layout table.
- return false;
- }
-
- if (tableNode.caption || tableNode.summary) {
- // This table has a caption or a summary - not a layout table.
- return false;
- }
-
- if ((cvox.XpathUtil.evalXPath('tbody/tr/th', tableNode).length > 0) &&
- (cvox.XpathUtil.evalXPath('tbody/tr/td', tableNode).length > 0)) {
- // This table at least one column and at least one column header.
- // Not a layout table.
- return false;
- }
-
- if (cvox.XpathUtil.evalXPath('colgroup', tableNode).length > 0) {
- // This table specifies column groups - not a layout table.
- return false;
- }
-
- if ((cvox.XpathUtil.evalXPath('thead', tableNode).length > 0) ||
- (cvox.XpathUtil.evalXPath('tfoot', tableNode).length > 0)) {
- // This table has header or footer rows - not a layout table.
- return false;
- }
-
- if ((cvox.XpathUtil.evalXPath('tbody/tr/td/embed', tableNode).length > 0) ||
- (cvox.XpathUtil.evalXPath('tbody/tr/td/object', tableNode).length > 0) ||
- (cvox.XpathUtil.evalXPath('tbody/tr/td/iframe', tableNode).length > 0) ||
- (cvox.XpathUtil.evalXPath('tbody/tr/td/applet', tableNode).length > 0)) {
- // This table contains embed, object, applet, or iframe elements. It is
- // a layout table.
- return true;
- }
-
- // These heuristics are loosely based on Okada and Miura's "Detection of
- // Layout-Purpose TABLE Tags Based on Machine Learning" (2007).
- // http://books.google.com/books?id=kUbmdqasONwC&lpg=PA116&ots=Lb3HJ7dISZ&lr&pg=PA116
-
- // Increase the points for each heuristic. If there are 3 or more points,
- // this is probably a layout table.
- var points = 0;
-
- if (! cvox.DomUtil.hasBorder(tableNode)) {
- // This table has no border.
- points++;
- }
-
- if (tableNode.rows.length <= 6) {
- // This table has a limited number of rows.
- points++;
- }
-
- if (cvox.DomUtil.countPreviousTags(tableNode) <= 12) {
- // This table has a limited number of previous tags.
- points++;
- }
-
- if (cvox.XpathUtil.evalXPath('tbody/tr/td/table', tableNode).length > 0) {
- // This table has nested tables.
- points++;
- }
- return (points >= 3);
-};
-
-
-/**
- * Count previous tags, which we dfine as the number of HTML tags that
- * appear before the given node.
- * @param {Node} node The given node.
- * @return {number} The number of previous tags.
- */
-cvox.DomUtil.countPreviousTags = function(node) {
- var ancestors = cvox.DomUtil.getAncestors(node);
- return ancestors.length + cvox.DomUtil.countPreviousSiblings(node);
-};
-
-
-/**
- * Counts previous siblings, not including text nodes.
- * @param {Node} node The given node.
- * @return {number} The number of previous siblings.
- */
-cvox.DomUtil.countPreviousSiblings = function(node) {
- var count = 0;
- var prev = node.previousSibling;
- while (prev != null) {
- if (prev.constructor != Text) {
- count++;
- }
- prev = prev.previousSibling;
- }
- return count;
-};
-
-
-/**
- * Whether a given table has a border or not.
- * @param {Node} tableNode The table node.
- * @return {boolean} If the table has a border, return true. False otherwise.
- */
-cvox.DomUtil.hasBorder = function(tableNode) {
- // If .frame contains "void" there is no border.
- if (tableNode.frame) {
- return (tableNode.frame.indexOf('void') == -1);
- }
-
- // If .border is defined and == "0" then there is no border.
- if (tableNode.border) {
- if (tableNode.border.length == 1) {
- return (tableNode.border != '0');
- } else {
- return (tableNode.border.slice(0, -2) != 0);
- }
- }
-
- // If .style.border-style is 'none' there is no border.
- if (tableNode.style.borderStyle && tableNode.style.borderStyle == 'none') {
- return false;
- }
-
- // If .style.border-width is specified in units of length
- // ( https://developer.mozilla.org/en/CSS/border-width ) then we need
- // to check if .style.border-width starts with 0[px,em,etc]
- if (tableNode.style.borderWidth) {
- return (tableNode.style.borderWidth.slice(0, -2) != 0);
- }
-
- // If .style.border-color is defined, then there is a border
- if (tableNode.style.borderColor) {
- return true;
- }
- return false;
-};
-
-
-/**
- * Return the first leaf node, starting at the top of the document.
- * @return {Node?} The first leaf node in the document, if found.
- */
-cvox.DomUtil.getFirstLeafNode = function() {
- var node = document.body;
- while (node && node.firstChild) {
- node = node.firstChild;
- }
- while (node && !cvox.DomUtil.hasContent(node)) {
- node = cvox.DomUtil.directedNextLeafNode(node);
- }
- return node;
-};
-
-
-/**
- * Finds the first descendant node that matches the filter function, using
- * a depth first search. This function offers the most general purpose way
- * of finding a matching element. You may also wish to consider
- * {@code goog.dom.query} which can express many matching criteria using
- * CSS selector expressions. These expressions often result in a more
- * compact representation of the desired result.
- * This is the findNode function from goog.dom:
- * http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/dom/dom.js
- *
- * @param {Node} root The root of the tree to search.
- * @param {function(Node) : boolean} p The filter function.
- * @return {Node|undefined} The found node or undefined if none is found.
- */
-cvox.DomUtil.findNode = function(root, p) {
- var rv = [];
- var found = cvox.DomUtil.findNodes_(root, p, rv, true, 10000);
- return found ? rv[0] : undefined;
-};
-
-
-/**
- * Finds the number of nodes matching the filter.
- * @param {Node} root The root of the tree to search.
- * @param {function(Node) : boolean} p The filter function.
- * @return {number} The number of nodes selected by filter.
- */
-cvox.DomUtil.countNodes = function(root, p) {
- var rv = [];
- cvox.DomUtil.findNodes_(root, p, rv, false, 10000);
- return rv.length;
-};
-
-
-/**
- * Finds the first or all the descendant nodes that match the filter function,
- * 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 {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.
- * @return {boolean} Whether the search is complete or not. True in case
- * findOne is true and the node is found. False otherwise. This is the
- * findNodes_ function from goog.dom:
- * http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/dom/dom.js.
- * @private
- */
-cvox.DomUtil.findNodes_ = function(root, p, rv, findOne, maxChildCount) {
- if ((root != null) || (maxChildCount == 0)) {
- var child = root.firstChild;
- while (child) {
- if (p(child)) {
- rv.push(child);
- if (findOne) {
- return true;
- }
- }
- maxChildCount = maxChildCount - 1;
- if (cvox.DomUtil.findNodes_(child, p, rv, findOne, maxChildCount)) {
- return true;
- }
- child = child.nextSibling;
- }
- }
- return false;
-};
-
-
-/**
- * Converts a NodeList into an array
- * @param {NodeList} nodeList The nodeList.
- * @return {Array} The array of nodes in the nodeList.
- */
-cvox.DomUtil.toArray = function(nodeList) {
- var nodeArray = [];
- for (var i = 0; i < nodeList.length; i++) {
- nodeArray.push(nodeList[i]);
- }
- return nodeArray;
-};
-
-
-/**
- * Creates a new element with the same attributes and no children.
- * @param {Node|Text} node A node to clone.
- * @param {Object<boolean>} skipattrs Set the attribute to true to skip it
- * during cloning.
- * @return {Node|Text} The cloned node.
- */
-cvox.DomUtil.shallowChildlessClone = function(node, skipattrs) {
- if (node.nodeName == '#text') {
- return document.createTextNode(node.nodeValue);
- }
-
- if (node.nodeName == '#comment') {
- return document.createComment(node.nodeValue);
- }
-
- var ret = document.createElement(node.nodeName);
- for (var i = 0; i < node.attributes.length; ++i) {
- var attr = node.attributes[i];
- if (skipattrs && skipattrs[attr.nodeName]) {
- continue;
- }
- ret.setAttribute(attr.nodeName, attr.nodeValue);
- }
- return ret;
-};
-
-
-/**
- * Creates a new element with the same attributes and clones of children.
- * @param {Node|Text} node A node to clone.
- * @param {Object<boolean>} skipattrs Set the attribute to true to skip it
- * during cloning.
- * @return {Node|Text} The cloned node.
- */
-cvox.DomUtil.deepClone = function(node, skipattrs) {
- var ret = cvox.DomUtil.shallowChildlessClone(node, skipattrs);
- for (var i = 0; i < node.childNodes.length; ++i) {
- ret.appendChild(cvox.DomUtil.deepClone(node.childNodes[i], skipattrs));
- }
- return ret;
-};
-
-
-/**
- * Returns either node.firstChild or node.lastChild, depending on direction.
- * @param {Node|Text} node The node.
- * @param {boolean} reverse If reversed.
- * @return {Node|Text} The directed first child or null if the node has
- * no children.
- */
-cvox.DomUtil.directedFirstChild = function(node, reverse) {
- if (reverse) {
- return node.lastChild;
- }
- return node.firstChild;
-};
-
-/**
- * Returns either node.nextSibling or node.previousSibling, depending on
- * direction.
- * @param {Node|Text} node The node.
- * @param {boolean=} reverse If reversed.
- * @return {Node|Text} The directed next sibling or null if there are
- * no more siblings in that direction.
- */
-cvox.DomUtil.directedNextSibling = function(node, reverse) {
- if (!node) {
- return null;
- }
- if (reverse) {
- return node.previousSibling;
- }
- return node.nextSibling;
-};
-
-/**
- * Creates a function that sends a click. This is because loop closures
- * are dangerous.
- * See: http://joust.kano.net/weblog/archive/2005/08/08/
- * a-huge-gotcha-with-javascript-closures/
- * @param {Node} targetNode The target node to click on.
- * @return {function()} A function that will click on the given targetNode.
- */
-cvox.DomUtil.createSimpleClickFunction = function(targetNode) {
- var target = targetNode.cloneNode(true);
- return function() { cvox.DomUtil.clickElem(target, false, false); };
-};
-
-/**
- * Adds a node to document.head if that node has not already been added.
- * If document.head does not exist, this will add the node to the body.
- * @param {Node} node The node to add.
- * @param {string=} opt_id The id of the node to ensure the node is only
- * added once.
- */
-cvox.DomUtil.addNodeToHead = function(node, opt_id) {
- if (opt_id && document.getElementById(opt_id)) {
- return;
- }
- var p = document.head || document.body;
- p.appendChild(node);
-};
-
-
-/**
- * Checks if a given node is inside a math expressions and
- * returns the math node if one exists.
- * @param {Node} node The node.
- * @return {Node} The math node, if the node is inside a math expression.
- * Null if it is not.
- */
-cvox.DomUtil.getContainingMath = function(node) {
- var ancestors = cvox.DomUtil.getAncestors(node);
- return cvox.DomUtil.findMathNodeInList(ancestors);
-};
-
-
-/**
- * Extracts a math node from a 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.
- */
-cvox.DomUtil.findMathNodeInList = function(nodes) {
- for (var i = 0, node; node = nodes[i]; i++) {
- if (cvox.DomUtil.isMath(node)) {
- return node;
- }
- }
- return null;
-};
-
-
-/**
- * Checks to see wether a node is a math node.
- * @param {Node} node The node to be tested.
- * @return {boolean} Whether or not a node is a math node.
- */
-cvox.DomUtil.isMath = function(node) {
- return cvox.DomUtil.isMathml(node) ||
- cvox.DomUtil.isMathJax(node) ||
- cvox.DomUtil.isMathImg(node) ||
- cvox.AriaUtil.isMath(node);
-};
-
-
-/**
- * Specifies node classes in which we expect maths expressions a alt text.
- * @type {{tex: Array<string>,
- * asciimath: Array<string>}}
- */
-// These are the classes for which we assume they contain Maths in the ALT or
-// TITLE attribute.
-// tex: Wikipedia;
-// latex: Wordpress;
-// numberedequation, inlineformula, displayformula: MathWorld;
-cvox.DomUtil.ALT_MATH_CLASSES = {
- tex: ['tex', 'latex'],
- asciimath: ['numberedequation', 'inlineformula', 'displayformula']
-};
-
-
-/**
- * Composes a query selector string for image nodes with alt math content by
- * type of content.
- * @param {string} contentType The content type, e.g., tex, asciimath.
- * @return {!string} The query elector string.
- */
-cvox.DomUtil.altMathQuerySelector = function(contentType) {
- var classes = cvox.DomUtil.ALT_MATH_CLASSES[contentType];
- if (classes) {
- return classes.map(function(x) {return 'img.' + x;}).join(', ');
- }
- return '';
-};
-
-
-/**
- * Check if a given node is potentially a math image with alternative text in
- * LaTeX.
- * @param {Node} node The node to be tested.
- * @return {boolean} Whether or not a node has an image with class TeX or LaTeX.
- */
-cvox.DomUtil.isMathImg = function(node) {
- if (!node || !node.tagName || !node.className) {
- return false;
- }
- if (node.tagName != 'IMG') {
- return false;
- }
- 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;
-};
-
-
-/**
- * Checks to see whether a node is a MathML node.
- * !! This is necessary as Chrome currently does not upperCase Math tags !!
- * @param {Node} node The node to be tested.
- * @return {boolean} Whether or not a node is a MathML node.
- */
-cvox.DomUtil.isMathml = function(node) {
- if (!node || !node.tagName) {
- return false;
- }
- return node.tagName.toLowerCase() == 'math';
-};
-
-
-/**
- * Checks to see wether a node is a MathJax node.
- * @param {Node} node The node to be tested.
- * @return {boolean} Whether or not a node is a MathJax node.
- */
-cvox.DomUtil.isMathJax = function(node) {
- if (!node || !node.tagName || !node.className) {
- return false;
- }
-
- function isSpanWithClass(n, cl) {
- return (n.tagName == 'SPAN' &&
- n.className.split(' ').some(function(x) {
- return x.toLowerCase() == cl;}));
- };
- if (isSpanWithClass(node, 'math')) {
- var ancestors = cvox.DomUtil.getAncestors(node);
- return ancestors.some(function(x) {return isSpanWithClass(x, 'mathjax');});
- }
- return false;
-};
-
-
-/**
- * Computes the id of the math span in a MathJax DOM element.
- * @param {string} jaxId The id of the MathJax node.
- * @return {string} The id of the span node.
- */
-cvox.DomUtil.getMathSpanId = function(jaxId) {
- var node = document.getElementById(jaxId + '-Frame');
- if (node) {
- var span = node.querySelector('span.math');
- if (span) {
- return span.id;
- }
- }
-};
-
-
-/**
- * Returns true if the node has a longDesc.
- * @param {Node} node The node to be tested.
- * @return {boolean} Whether or not a node has a longDesc.
- */
-cvox.DomUtil.hasLongDesc = function(node) {
- if (node && node.longDesc) {
- return true;
- }
- return false;
-};
-
-
-/**
- * Returns tag name of a node if it has one.
- * @param {Node} node A node.
- * @return {string} A the tag name of the node.
- */
-cvox.DomUtil.getNodeTagName = function(node) {
- if (node.nodeType == Node.ELEMENT_NODE) {
- return node.tagName;
- }
- return '';
-};
-
-
-/**
- * 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.
- */
-cvox.DomUtil.purgeNodes = function(nodes) {
- return cvox.DomUtil.toArray(nodes).
- filter(function(node) {
- return node.nodeType != Node.TEXT_NODE ||
- !node.textContent.match(/^\s+$/);});
-};
-
-
-/**
- * Calculates a hit point for a given node.
- * @return {{x:(number), y:(number)}} The position.
- */
-cvox.DomUtil.elementToPoint = function(node) {
- if (!node) {
- return {x: 0, y: 0};
- }
- if (node.constructor == Text) {
- node = node.parentNode;
- }
- var r = node.getBoundingClientRect();
- return {
- x: r.left + (r.width / 2),
- y: r.top + (r.height / 2)
- };
-};
-
-
-/**
- * Checks if an input node supports HTML5 selection.
- * If the node is not an input element, returns false.
- * @param {Node} node The node to check.
- * @return {boolean} True if HTML5 selection supported.
- */
-cvox.DomUtil.doesInputSupportSelection = function(node) {
- return goog.isDef(node) &&
- node.tagName == 'INPUT' &&
- node.type != 'email' &&
- node.type != 'number';
-};
-
-
-/**
- * Gets the hint text for a given element.
- * @param {Node} node The target node.
- * @return {string} The hint text.
- */
-cvox.DomUtil.getHint = function(node) {
- var desc = '';
- if (node.hasAttribute) {
- if (node.hasAttribute('aria-describedby')) {
- var describedByIds = node.getAttribute('aria-describedby').split(' ');
- for (var describedById, i = 0; describedById = describedByIds[i]; i++) {
- var describedNode = document.getElementById(describedById);
- if (describedNode) {
- desc += ' ' + cvox.DomUtil.getName(
- describedNode, true, true, true);
- }
- }
- }
- }
- return desc;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util_test.unitjs
deleted file mode 100644
index b77b36676fa..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/dom_util_test.unitjs
+++ /dev/null
@@ -1,1578 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxDomUtilUnitTest() {}
-
-CvoxDomUtilUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.ChromeVox',
- 'cvox.DescriptionUtil',
- 'cvox.DomUtil',
- 'TestMsgs',
- ],
-
- /** @override */
- setUp: function() {
- Msgs = TestMsgs;
- },
-
- asText_: function(node) {
- var temp = document.createElement('div');
- temp.appendChild(node);
- return temp.innerHTML;
- },
-
- assertEqualsAsText_: function(node1, node2) {
- assertEquals(this.asText_(node1), this.asText_(node2));
- },
-
- loadDomUtilTestDoc_: function() {
- this.loadDoc(function() {/*!
- <style type="text/css">
- #display_none { display: none; }
- #visibility_hidden { visibility: hidden; }
- #forced_visible { visibility: hidden; }
- #visibility_collapse { visibility: collapse; }
- #opacity_zero { opacity: 0; }
- #opacity_partial { opacity: 0.5; }
- #opacity_undefined { }
- #nested_visibility_hide { visibility: hidden; }
- #nested_visibility_show { visibility: visible; }
- #nested_display_none { display: none; }
- #nested_display_block { display: block; }
- </style>
- <form action="">
-
- <div id="normal_node">1</div>
- <div id="display_none">2</div>
- <div id="visibility_hidden">3</div>
- <div id="visibility_collapse">3b</div>
- <div id="opacity_zero">4</div>
- <div id="opacity_partial">4b</div>
- <div id="opacity_undefined">5</div>
- <select id="select_node"><option>5</option></select>
- <textarea id="textarea">6</textarea>
- <div id="forced_visible" aria-hidden="false">7</div>
- <p id="normal_para">----</p>
- <p id="presentation" role="presentation">----</p>
- <p id="aria_hidden" aria-hidden="true">----</p>
- <p id="only_spaces"> </p>
- <p id="only_tabs"> </p>
- <p id="only_newlines">
-
- </p>
- <p id="only_nbsp">&nbsp;</p>
- <p id="other_entity">&amp;</p>
- <img id="img">
- <img id="img_alt" alt="tree">
- <img id="img_blankalt" alt="">
-
- <input id="check" type="checkbox">
- <input id="check_checked" type="checkbox" checked>
-
- <span><p id="a">a</p></span>
- <span><p id="b">b</p><p id="c">c</p></span>
- </form>
-
- <a id="special_link1" href="http://google.com"><span id="empty_span"></span>
- </a>
- <a id="special_link2" href="http://google.com"><span>Text content</span></a>
- <a id="special_link3"><span></span></a>
-
- <div id="nested_visibility_hide">
- hide<div id="nested_visibility_show">show</div>me
- </div>
- <div id="nested_display_none">
- nothing<div id="nested_display_block">will</div>show
- </div>
- */});
- },
-};
-
-TEST_F('CvoxDomUtilUnitTest', 'IsVisible', function() {
- this.loadDomUtilTestDoc_();
-
- // Simple tests.
- var node = $('normal_node');
- assertEquals(true, cvox.DomUtil.isVisible(node));
- node = $('display_none');
- assertEquals(false, cvox.DomUtil.isVisible(node));
- node = $('visibility_hidden');
- assertEquals(false, cvox.DomUtil.isVisible(node));
- node = $('visibility_collapse');
- assertEquals(false, cvox.DomUtil.isVisible(node));
- node = $('opacity_zero');
- assertEquals(false, cvox.DomUtil.isVisible(node));
- node = $('opacity_partial');
- assertEquals(true, cvox.DomUtil.isVisible(node));
- node = $('opacity_undefined');
- assertEquals(true, cvox.DomUtil.isVisible(node));
- node = $('forced_visible');
- assertEquals(true, cvox.DomUtil.isVisible(node));
-
- // Nested visibility tests.
- node = $('nested_visibility_hide');
- assertEquals(true, cvox.DomUtil.isVisible(node)); // Has visible child.
- node = $('nested_visibility_hide').childNodes[0];
- assertEquals(false, cvox.DomUtil.isVisible(node)); // TextNode is invisible.
- node = $('nested_visibility_show');
- assertEquals(true, cvox.DomUtil.isVisible(node));
- node = $('nested_visibility_show').childNodes[0];
- assertEquals(true, cvox.DomUtil.isVisible(node)); // TextNode is visible.
- node = $('nested_display_block');
- assertEquals(false, cvox.DomUtil.isVisible(node));
-
- // Options tests (for performance).
- node = $('nested_display_block');
- assertEquals(true,
- cvox.DomUtil.isVisible(node, {checkAncestors: false}));
- node = $('nested_visibility_hide');
- assertEquals(false,
- cvox.DomUtil.isVisible(node, {checkDescendants: false}));
-
- // Test that an element not part of the DOM is treated as invisible.
- var div = document.createElement('div');
- assertEquals(false, cvox.DomUtil.isVisible(div));
- document.body.appendChild(div);
- assertEquals(true, cvox.DomUtil.isVisible(div));
-});
-
-/** Test determining if a node is a leaf node or not. @export */
-TEST_F('CvoxDomUtilUnitTest', 'IsLeafNode', function() {
- this.loadDomUtilTestDoc_();
-
- var node = $('normal_node');
- assertEquals(false, cvox.DomUtil.isLeafNode(node));
- node = $('display_none');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('visibility_hidden');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('opacity_zero');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('select_node');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('textarea');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('normal_para');
- assertEquals(false, cvox.DomUtil.isLeafNode(node));
- node = $('aria_hidden');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('special_link1');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('special_link2');
- assertEquals(true, cvox.DomUtil.isLeafNode(node));
- node = $('special_link3');
- assertEquals(false, cvox.DomUtil.isLeafNode(node));
- node = $('nested_visibility_hide');
- assertEquals(false, cvox.DomUtil.isLeafNode(node));
-});
-
-/** Test determining if a node has content or not. @export */
-TEST_F('CvoxDomUtilUnitTest', 'HasContent', function() {
- this.loadDomUtilTestDoc_();
-
- var node = $('normal_node');
- cvox.DomUtil.hasContent(node);
- assertEquals(true, cvox.DomUtil.hasContent(node));
- node = $('display_none');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('visibility_hidden');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('opacity_zero');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('select_node');
- assertEquals(true, cvox.DomUtil.hasContent(node));
- node = $('textarea');
- assertEquals(true, cvox.DomUtil.hasContent(node));
- node = $('normal_para');
- assertEquals(true, cvox.DomUtil.hasContent(node));
- // TODO (adu): This test fails. Will inspect.
- // node = $('presentation');
- // assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('aria_hidden');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('only_spaces');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('only_tabs');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('only_newlines');
- assertEquals(false, cvox.DomUtil.hasContent(node));
- node = $('other_entity');
- assertEquals(true, cvox.DomUtil.hasContent(node));
- node = $('img');
- assertEquals(true, cvox.DomUtil.hasContent(node));
- node = $('img_alt');
- assertEquals(true, cvox.DomUtil.hasContent(node));
- node = $('img_blankalt');
- assertEquals(false, cvox.DomUtil.hasContent(node));
-});
-
-/** Test getting a node's state. @export */
-TEST_F('CvoxDomUtilUnitTest', 'NodeState', function() {
- this.loadDomUtilTestDoc_();
- this.appendDoc(function() {/*!
- <input id="state1_enabled">
- <input id="state1_disabled" disabled>
- <button id="state2_enabled">Button</button>
- <button id="state2_disabled" disabled>Button</button>
- <textarea id="state3_enabled">Textarea</textarea>
- <textarea id="state3_disabled" disabled>Textarea</textarea>
- <select id="state4_enabled"><option>Select</option></select>
- <select id="state4_disabled" disabled><option>Select</option></select>
- <div role="button" id="state5_enabled" tabindex="0">ARIAButton</div>
- <div role="button" id="state5_disabled" tabindex="0" disabled>ARIAButton</div>
- <fieldset>
- <input id="state6_enabled">
- </fieldset>
- <fieldset disabled>
- <input id="state6_disabled">
- </fieldset>
- */});
- var node = $('check');
- assertEquals('not checked', cvox.DomUtil.getState(node, true));
- node = $('check_checked');
- assertEquals('checked', cvox.DomUtil.getState(node, true));
- node = $('state1_enabled');
- assertEquals('', cvox.DomUtil.getState(node, true));
- node = $('state1_disabled');
- assertEquals('Disabled', cvox.DomUtil.getState(node, true));
- node = $('state2_enabled');
- assertEquals('', cvox.DomUtil.getState(node, true));
- node = $('state2_disabled');
- assertEquals('Disabled', cvox.DomUtil.getState(node, true));
- node = $('state3_enabled');
- assertEquals('', cvox.DomUtil.getState(node, true));
- node = $('state3_disabled');
- assertEquals('Disabled', cvox.DomUtil.getState(node, true));
- node = $('state4_enabled');
- assertEquals('1 of 1', cvox.DomUtil.getState(node, true));
- node = $('state4_disabled');
- assertEquals('1 of 1 Disabled', cvox.DomUtil.getState(node, true));
- node = $('state5_enabled');
- assertEquals('', cvox.DomUtil.getState(node, true));
- node = $('state5_disabled');
- assertEquals('', cvox.DomUtil.getState(node, true));
- node = $('state6_enabled');
- assertEquals('', cvox.DomUtil.getState(node, true));
- node = $('state6_disabled');
- assertEquals('Disabled', cvox.DomUtil.getState(node, true));
-});
-
-/** Test finding the next/previous leaf node. @export */
-TEST_F('CvoxDomUtilUnitTest', 'LeafNodeTraversal', function() {
- this.loadDomUtilTestDoc_();
-
- var node = $('a');
- node = cvox.DomUtil.directedNextLeafNode(node);
- assertEquals('\n ', node.textContent);
- node = cvox.DomUtil.directedNextLeafNode(node);
- assertEquals('b', node.textContent);
- node = cvox.DomUtil.directedNextLeafNode(node);
- assertEquals('c', node.textContent);
- node = cvox.DomUtil.previousLeafNode(node);
- assertEquals('b', node.textContent);
- node = cvox.DomUtil.previousLeafNode(node);
- assertEquals('\n ', node.textContent);
- node = cvox.DomUtil.previousLeafNode(node);
- assertEquals('a', node.textContent);
-});
-
-/** Test finding the label for controls. @export */
-TEST_F('CvoxDomUtilUnitTest', 'GetLabel', function() {
- this.loadDoc(function() {/*!
- <fieldset id="Fieldset">
- <legend>This is a legend inside a fieldset</legend>
- <div align="right">
- <span>
- Username:
- </span>
- </div>
- <input name="Email" id="Email" size="18" value="" type="text">
- <span>
- Password:
- </span>
- <input name="Passwd" id="Passwd" size="18" type="password">
- <input name="PersistentCookie" id="PersistentCookie" type="checkbox">
- <label for="PersistentCookie" id="PersistentCookieLabel">
- Stay signed in
- </label>
- <input name="signIn" id="signIn" value="Sign in" type="submit">
- <input id="dummyA" size="18" value="" type="text" title="">
- <input id="dummyB" size="18" value="" type="text" aria-label="">
- </fieldset>
- */});
-
- function getControlText(control) {
- var description = cvox.DescriptionUtil.getControlDescription(control);
- return cvox.DomUtil.collapseWhitespace(
- description.context + ' ' +
- description.text + ' ' +
- description.userValue + ' ' +
- description.annotation);
- }
-
- var fieldsetElement = $('Fieldset');
- assertEquals('This is a legend inside a fieldset',
- cvox.DomUtil.getName(fieldsetElement, false, false));
-
- var usernameField = $('Email');
- assertEquals('', cvox.DomUtil.getValue(usernameField));
- assertEquals('Username:',
- cvox.DomUtil.getControlLabelHeuristics(usernameField));
- assertEquals('Username: Edit text', getControlText(usernameField));
- var passwordField = $('Passwd');
- assertEquals('', cvox.DomUtil.getValue(passwordField));
- assertEquals('Password:',
- cvox.DomUtil.getControlLabelHeuristics(passwordField));
- assertEquals('Password: Password edit text', getControlText(passwordField));
- var cookieCheckbox = $('PersistentCookie');
- assertEquals('Stay signed in', cvox.DomUtil.getName(cookieCheckbox));
- assertEquals('Stay signed in Check box not checked',
- getControlText(cookieCheckbox));
- var signinButton = $('signIn');
- assertEquals('Sign in', cvox.DomUtil.getName(signinButton));
- assertEquals('Sign in Button', getControlText(signinButton));
- var dummyInputA = $('dummyA');
- assertEquals('', cvox.DomUtil.getName(dummyInputA));
- var dummyInputB = $('dummyB');
- assertEquals('', cvox.DomUtil.getName(dummyInputB));
-
- // The heuristic no longer returns 'Stay signed in' as the label for
- // the signIn button because 'Stay signed in' is in a label that's
- // explicitly associated with another control.
- //assertEquals('Stay signed in ',
- // cvox.DomUtil.getControlLabelHeuristics(signinButton));
-});
-
-/** Test finding the label for controls with a more complex setup. @export */
-TEST_F('CvoxDomUtilUnitTest', 'GetLabelComplex', function() {
- this.loadDoc(function() {/*!
- <table class="bug-report-table">
- <tbody><tr>
- <td class="bug-report-fieldlabel">
- <input id="page-url-checkbox" type="checkbox">
- <span id="page-url-label" i18n-content="page-url">Include this URL:</span>
- </td>
- <td>
- <input id="page-url-text" class="bug-report-field" maxlength="200">
- </td>
- </tr>
- </tbody></table>
- <table id="user-email-table" class="bug-report-table">
- <tbody><tr>
- <td class="bug-report-fieldlabel">
- <input id="user-email-checkbox" checked="checked" type="checkbox">
- <span id="user-email-label">Include this email:</span>
- </td>
- <td>
- <label id="user-email-text" class="bug-report-field"></label>
- </td>
- </tr>
- </tbody></table>
- <table class="bug-report-table">
- <tbody><tr>
- <td class="bug-report-fieldlabel">
- <input id="sys-info-checkbox" checked="checked" type="checkbox">
- <span id="sysinfo-label">
- <a id="sysinfo-url" href="#">Send system information</a>
- </span>
- </td>
- </tr>
- </tbody></table>
- <table class="bug-report-table">
- <tbody><tr>
- <td class="bug-report-fieldlabel">
- <input id="screenshot-checkbox" type="checkbox">
- <span id="screenshot-label-current">Include the current screenshot:</span>
- </td>
- </tr>
- </tbody></table>
- */});
- var urlCheckbox = $('page-url-checkbox');
- assertEquals('Include this URL:',
- cvox.DomUtil.getControlLabelHeuristics(urlCheckbox));
- var emailCheckbox = $('user-email-checkbox');
- assertEquals('Include this email:',
- cvox.DomUtil.getControlLabelHeuristics(emailCheckbox));
- var sysCheckbox = $('sys-info-checkbox');
- assertEquals('Send system information',
- cvox.DomUtil.getControlLabelHeuristics(sysCheckbox));
-});
-
-/**************************************************************/
-
-TEST_F('CvoxDomUtilUnitTest', 'EscapedNames', function() {
- this.loadDoc(function() {/*!
- <p id="en-title" title="&lt;&gt;"></p>
- <p id="en-arialabel" aria-label="&lt;&gt;"></p>
- <img id="en-img" title="&lt;&gt;"></img>
- <p id="en-double" title="&amp;lt;&amp;gt;"></p>
- */});
- assertEquals('<>', cvox.DomUtil.getName(
- $('en-title')));
- assertEquals('<>', cvox.DomUtil.getName(
- $('en-arialabel')));
- assertEquals('<>', cvox.DomUtil.getName(
- $('en-img')));
- assertEquals('&lt;&gt;', cvox.DomUtil.getName(
- $('en-double')));
-});
-
-/** Test a paragraph with plain text. @export */
-TEST_F('CvoxDomUtilUnitTest', 'SimplePara', function() {
- this.loadDoc(function() {/*!
- <p id="simplepara">This is a simple paragraph.</p>
- */});
- var node = $('simplepara');
- var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node));
- assertEquals('This is a simple paragraph.', text);
-});
-
-/** Test a paragraph with nested tags. @export */
-TEST_F('CvoxDomUtilUnitTest', 'NestedPara', function() {
- this.loadDoc(function() {/*!
- <p id="nestedpara">This is a <b>paragraph</b> with <i>nested</i> tags.</p>
- */});
- var node = $('nestedpara');
- var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node));
- assertEquals('This is a paragraph with nested tags.', text);
-});
-
-/**
- * Test a paragraph with nested tags and varying visibility.
- * @export
- */
-TEST_F('CvoxDomUtilUnitTest', 'NestedVisibilityPara', function() {
- this.loadDoc(function() {/*!
- <style type="text/css">
- #nested_visibility_paragraph { }
- #nested_visibility_paragraph .hide { visibility: hidden; }
- #nested_visibility_paragraph .show { visibility: visible; }
- </style>
- <p id="nested_visibility_paragraph">
- This is
- <span class="hide">
- not
- <span class="show"> a sentence.</span>
- </span>
- </p>
- */});
- var node = $('nested_visibility_paragraph');
- var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node));
- assertEquals('This is a sentence.', text);
-});
-
-/** Test getting text from an IMG node. @export */
-TEST_F('CvoxDomUtilUnitTest', 'Image', function() {
- this.loadDoc(function() {/*!
- <img id="img">
- <img id="img_noalt" src="rose.png">
- <img id="img_alt" alt="flower" src="rose.png">
- <img id="img_title" title="a Flower" src="rose.png">
- <img id="img_noalt_long"
- src="777777777777777777777777777777777.png">
- */});
-
- var node = $('img');
- assertEquals('Image', cvox.DomUtil.getName(node));
- node = $('img_noalt');
- assertEquals('rose Image', cvox.DomUtil.getName(node));
- node = $('img_alt');
- assertEquals('flower', cvox.DomUtil.getName(node));
- node = $('img_title');
- assertEquals('a Flower', cvox.DomUtil.getName(node));
- node = $('img_noalt_long');
- assertEquals('Image', cvox.DomUtil.getName(node));
-});
-
-/** Test getting text from a select box. @export */
-TEST_F('CvoxDomUtilUnitTest', 'Select', function() {
- this.loadDoc(function() {/*!
- <select id="select_noneselected">
- <option>Apple</option>
- <option>Banana</option>
- <option>Pear</option>
- </select>
- <select id="select_bananaselected">
- <option>Apple</option>
- <option selected>Banana</option>
- <option>Pear</option>
- </select>
- */});
-
- $('select_noneselected').selectedIndex = -1;
- var node = $('select_noneselected');
- assertEquals('', cvox.DomUtil.getValue(node));
- node = $('select_bananaselected');
- assertEquals('Banana', cvox.DomUtil.getValue(node));
-});
-
-/** Test whether funky html causes getName to go into infinite loop. */
-TEST_F('CvoxDomUtilUnitTest', 'GetNameInfiniteLoop', function() {
- this.loadDoc(function() {/*!
- <div>
- <label for="a">
- <p id="a">asdf</p>
- </label>
- </div>
- */});
- // intentionally no asserts; if there is an infinite (recursive) loop,
- // the stack will blow up
- var node = $('a');
- var label = cvox.DomUtil.getName(node);
-});
-
-/** Test getting text from an INPUT control. @export */
-TEST_F('CvoxDomUtilUnitTest', 'Input', function() {
- this.loadDoc(function() {/*!
- <form action="">
- <input id="hidden" type="hidden" value="hidden1">
- <input id="input_img" type="image" src="rose.png">
- <input id="input_img_alt" type="image" alt="flower" src="rose.png">
- <input id="submit" type="submit">
- <input id="submit_withvalue" type="submit" value="Go">
- <input id="reset" type="reset">
- <input id="reset_withvalue" type="reset" value="Stop">
- <input id="button" type="button" value="Button">
- <input id="checkbox" type="checkbox" value="ignore1">
- <input id="checkbox_title" type="checkbox" value="ignore1" title="toggle">
- <input id="radio" type="radio" value="ignore2">
- <input id="password" type="password" value="dragon">
- <input id="text" value="my text">
- <input id="placeholder0" placeholder="Phone number">
- <input id="placeholder1" title="Phone number">
- <input id="placeholder2" title="Phone number" placeholder="xxx-yyy-zzzz">
- <input id="placeholder3" title="Phone number" placeholder="xxx-yyy-zzzz"
- value="310-555-1212">
- </form>
- */});
-
- var node = $('hidden');
- assertEquals('', cvox.DomUtil.getName(node));
- node = $('input_img');
- assertEquals('rose Image', cvox.DomUtil.getName(node));
- node = $('input_img_alt');
- assertEquals('flower', cvox.DomUtil.getName(node));
- node = $('submit');
- assertEquals('Submit', cvox.DomUtil.getName(node));
- node = $('submit_withvalue');
- assertEquals('Go', cvox.DomUtil.getName(node));
- node = $('reset');
- assertEquals('Reset', cvox.DomUtil.getName(node));
- node = $('reset_withvalue');
- assertEquals('Stop', cvox.DomUtil.getName(node));
- node = $('button');
- assertEquals('Button', cvox.DomUtil.getName(node));
- node = $('checkbox');
- assertEquals('', cvox.DomUtil.getName(node));
- node = $('checkbox_title');
- assertEquals('toggle', cvox.DomUtil.getName(node));
- node = $('radio');
- assertEquals('', cvox.DomUtil.getName(node));
- node = $('password');
- assertEquals('dot dot dot dot dot dot ', cvox.DomUtil.getValue(node));
- node = $('text');
- assertEquals('my text', cvox.DomUtil.getValue(node));
- node = $('placeholder0');
- assertEquals('Phone number', cvox.DomUtil.getName(node));
- node = $('placeholder1');
- assertEquals('Phone number', cvox.DomUtil.getName(node));
- node = $('placeholder2');
- assertEquals('xxx-yyy-zzzz',
- cvox.DomUtil.getName(node));
- node = $('placeholder3');
- assertEquals('310-555-1212 xxx-yyy-zzzz',
- cvox.DomUtil.getValue(node) + ' ' + cvox.DomUtil.getName(node));
-});
-
-
-/** Test checking if something is a control. @export */
-TEST_F('CvoxDomUtilUnitTest', 'IsControl', function() {
- this.loadDoc(function() {/*!
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td>&nbsp;</td>
-
- <td nowrap="nowrap">
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td bgcolor="#3366CC"><img alt="" width="1" height="1"></td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td bgcolor="#E5ECF9" nowrap="nowrap"><font color="#000000"
- face="arial,sans-serif" size="+1"><b>&nbsp;Preferences</b>
- </font></td>
-
- <td align="right" bgcolor="#E5ECF9" nowrap="nowrap">
- <font color="#000000" face="arial,sans-serif" size="-1">
- <a href="http://www.google.com/accounts/ManageAccount">Google
- Account settings</a> | <a href="http://www.google.com/">
- Preferences Help</a> | <a href="/about.html">About
- Google</a>&nbsp;</font></td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="2" cellspacing="0">
- <tbody>
- <tr bgcolor="#E5ECF9">
- <td><font face="arial,sans-serif" size="-1"><b>Save</b> your
- preferences when finished and <b>return to search</b>.</font></td>
-
- <td align="right"><font face="arial,sans-serif" size="-1">
- <input value="Save Preferences " name="submit2" type="submit">
- </font></td>
- </tr>
- </tbody>
- </table>
-
- <h1>Global Preferences</h1><font size="-1">(changes apply to all Google
- services)</font><br>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td bgcolor="#CBDCED"><img alt="" width="1" height="2"></td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td>
-
- <td valign="top" width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
-
- <h2>Interface Language</h2>
- </td>
-
- <td colspan="2"><br>
- <font face="arial,sans-serif" size="-1">Display Google tips and
- messages in: <select name="hl">
- <option value="af">
- Afrikaans
- </option>
-
- <option value="ak">
- Akan
- </option>
-
- <option value="sq">
- Albanian
- </option>
-
- <option value="am">
- Amharic
- </option>
-
- <option value="ar">
- Arabic
- </option>
- </select><br>
- If you do not find your native language in the pulldown above, you
- can<br>
- help Google create it through our
- <a href="http://services.google.com/">Google in Your Language
- program</a>.<br>
- &nbsp;</font></td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td>
- </tr>
-
- <tr>
- <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td>
-
- <td valign="top" width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
-
- <h2>Search Language</h2>
- </td>
-
- <td>
- &nbsp;<br>
- <font face="arial,sans-serif" size="-1">Prefer pages written in these
- language(s):</font><br>
-
- <table border="0" cellpadding="5" cellspacing="10">
- <tbody>
- <tr>
- <td valign="top" nowrap="nowrap"><font face="arial,sans-serif"
- size="-1"><label><input name="lr" value="lang_af"
- onclick="tick()" id="paf" type="checkbox">
- <span id="taf">Afrikaans</span></label><br>
- <label><input name="lr" value="lang_ar" onclick="tick()"
- id="par" type="checkbox"> <span id="tar">Arabic</span></label>
- <br>
- <label><input name="lr" value="lang_hy" onclick="tick()"
- id="phy" type="checkbox"> <span id="thy">Armenian</span>
- </label><br>
- <label><input name="lr" value="lang_be" onclick="tick()"
- id="pbe" type="checkbox"> <span id="tbe">Belarusian</span>
- </label><br>
- <label><input name="lr" value="lang_bg" onclick="tick()"
- id="pbg" type="checkbox"> <span id="tbg">Bulgarian</span>
- </label><br>
- <label><input name="lr" value="lang_ca" onclick="tick()"
- id="pca" type="checkbox"> <span id="tca">Catalan</span>
- </label><br>
- <label><input name="lr" value="lang_zh-CN" onclick="tick()"
- id="pzh-CN" type="checkbox"> <span id="tzh-CN">
- Chinese&nbsp;(Simplified)</span></label><br>
- <label><input name="lr" value="lang_zh-TW" onclick="tick()"
- id="pzh-TW" type="checkbox"> <span id="tzh-TW">
- Chinese&nbsp;(Traditional)</span></label><br>
- <label><input name="lr" value="lang_hr" onclick="tick()"
- id="phr" type="checkbox"> <span id="thr">Croatian</span>
- </label><br>
- <label><input name="lr" value="lang_cs" onclick="tick()"
- id="pcs" type="checkbox"> <span id="tcs">Czech</span>
- </label><br>
- <label><input name="lr" value="lang_da" onclick="tick()"
- id="pda" type="checkbox"> <span id="tda">Danish</span>
- </label><br>
- <label><input name="lr" value="lang_nl" onclick="tick()"
- id="pnl" type="checkbox"> <span id="tnl">Dutch</span>
- </label></font></td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- </tbody>
- </table><a name="loc" id="loc"></a>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td>
- </tr>
-
- <tr>
- <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td>
-
- <td valign="top" width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
-
- <h2>Location</h2>
- </td>
-
- <td>
- <br>
-
- <div style="color: rgb(204, 0, 0); display: none;" id="locerr">
- <span id="lem"><font face="arial,sans-serif" size="-1">The location
- <b>X</b> was not recognized.</font></span>
- <font face="arial,sans-serif" size="-1"><br>
- <br>
- Suggestions:<br></font>
-
- <ul>
- <li><font face="arial,sans-serif" size="-1">Make sure all street
- and city names are spelled correctly.</font></li>
-
- <li><font face="arial,sans-serif" size="-1">Make sure the address
- included a city and state.</font></li>
-
- <li><font face="arial,sans-serif" size="-1">Try entering a Zip
- code.</font></li>
- </ul>
- </div>
-
- <div style="color: rgb(204, 0, 0); display: none;" id="locterr">
- <font face="arial,sans-serif" size="-1">Please enter a valid US
- city or zip code<br>
- <br></font>
- </div>
-
- <div style="color: rgb(204, 0, 0); display: none;" id="locserr">
- <font face="arial,sans-serif" size="-1">Server error. Please try
- again.<br>
- <br></font>
- </div><font face="arial,sans-serif" size="-1">Use as the default
- location in Google Maps, customized search results, and other Google
- products:<br>
- <input name="uulo" value="1" type="hidden"><input name="muul"
- value="4_20" type="hidden"><input name="luul" size="60" value=""
- type="text"><br>
- This location is saved on this computer.
- <a href="/support/websearch/bin/answer.py?answer=35892&amp;hl=en">
- Learn more</a><br>
- <br></font>
- </td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td>
- </tr>
-
- <tr>
- <td rowspan="2" width="1" bgcolor="#CBDCED">
- <img alt="" width="2" height="1"></td>
-
- <td width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
- <h2>SafeSearch Filtering</h2>
- </td>
- <td><br>
- <font face="arial,sans-serif" size="-1">
- <a href="http://www.google.com/">
- Google's SafeSearch</a> blocks web pages containing explicit sexual
- content from appearing in search results.</font></td>
- </tr>
- <tr valign="top">
- <td width="175" nowrap="nowrap">&nbsp;</td>
- <td>
- <div style="margin-bottom: 1.2em; font: smaller arial,sans-serif;">
- <input id="stf" name="safeui" value="on" type="radio">
- <label for="stf">Use strict filtering&nbsp;(Filter both explicit
- text and explicit images)</label><br>
- <input id="modf" name="safeui" value="images" checked="checked"
- type="radio"><label for="modf">Use moderate
- filtering&nbsp;(Filter explicit images only - default
- behavior)</label><br>
- <input id="nof" name="safeui" value="off" type="radio">
- <label for="nof">Do not filter my search results</label>
- </div>
- <p style="margin-bottom: 1.2em; font-size: smaller;">This will apply
- strict filtering to all searches from this computer using Firefox.
- <a href="http://www.google.com/">Learn more</a></p>
- </td>
- </tr>
- </tbody>
- </table>
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td>
- </tr>
-
- <tr>
- <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td>
-
- <td valign="top" width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
-
- <h2>Number of Results</h2>
- </td>
-
- <td>&nbsp;<br>
- <font face="arial,sans-serif" size="-1">Google's default (10 results)
- provides the fastest results.<br>
- Display <select name="num">
- <option value="10" selected="selected">
- 10
- </option>
-
- <option value="20">
- 20
- </option>
-
- <option value="30">
- 30
- </option>
-
- <option value="50">
- 50
- </option>
-
- <option value="100">
- 100
- </option>
- </select> results per page.<br>
- &nbsp;</font></td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td>
- </tr>
-
- <tr>
- <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td>
-
- <td valign="top" width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
-
- <h2>Results Window</h2><a name="safeui" id="safeui">&nbsp;</a>
- </td>
-
- <td>&nbsp;<br>
- <font face="arial,sans-serif" size="-1"><input id="nwc" name="newwindow"
- value="1" type="checkbox">&nbsp; <label for="nwc">Open
- search results in a new browser window.</label></font><br>
- &nbsp;</td>
- </tr>
- </tbody>
- </table>
-
- <table width="100%" border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td>
- </tr>
-
- <tr>
- <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td>
-
- <td valign="top" width="175" nowrap="nowrap">
- &nbsp;<br>
- &nbsp;
-
- <h2>Google Instant</h2>
- </td>
-
- <td>&nbsp;<br>
- <font face="arial,sans-serif" size="-1"><input id="suggon" name="suggon"
- value="1" checked="checked" type="radio"><label for="suggon">Use Google
- Instant predictions and results appear while typing</label><br>
- <input id="suggmid" name="suggon" value="2" type="radio">
- <label for="suggmid">Do not use Google Instant</label><br>
- <br>
- Signed-in users can remove personalized predictions from their
- <a href="/history">Web History</a>. <a href="http://www.google.com/">
- Learn more</a><br>
- <br>
- &nbsp;</font></td>
- </tr>
-
- <tr>
- <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="2"></td>
- </tr>
- </tbody>
- </table><br>
- */});
- var submitButton = document.getElementsByName('submit2')[0];
- assertEquals(true, cvox.DomUtil.isControl(submitButton));
- var selectControl = document.getElementsByName('hl')[0];
- assertEquals(true, cvox.DomUtil.isControl(selectControl));
- var checkbox = $('paf');
- assertEquals(true, cvox.DomUtil.isControl(checkbox));
- var textInput = document.getElementsByName('luul')[0];
- assertEquals(true, cvox.DomUtil.isControl(textInput));
- var radioButton = $('suggmid');
- assertEquals(true, cvox.DomUtil.isControl(radioButton));
- var h1Elem = document.getElementsByTagName('h1');
- assertEquals(false, cvox.DomUtil.isControl(h1Elem));
-});
-
-/** Test if something is an ARIA control. @export */
-TEST_F('CvoxDomUtilUnitTest', 'IsAriaControl', function() {
- this.loadDoc(function() {/*!
- <li id="cb1" role="checkbox" tabindex="0" aria-checked="false"
- aria-describedby="cond desc1">
- Lettuce
- </li>
- <li id="larger1" role="button" tabindex="0" aria-pressed="false"
- aria-labelledby="larger_label">+</li>
- <li id="r1" role="radio" tabindex="-1" aria-checked="false">Thai</li>
- <li id="treeitem1" role="treeitem" tabindex="-1">Oranges</li>
- */});
- var checkbox = $('cb1');
- assertEquals(true, cvox.DomUtil.isControl(checkbox));
- var button = $('larger1');
- assertEquals(true, cvox.DomUtil.isControl(button));
- var radio = $('r1');
- assertEquals(true, cvox.DomUtil.isControl(radio));
- var treeitem = $('treeitem1');
- assertEquals(false, cvox.DomUtil.isControl(treeitem));
-});
-
-/** Test if something is an focusable. @export */
-TEST_F('CvoxDomUtilUnitTest', 'IsFocusable', function() {
- this.loadDoc(function() {/*!
- <a id="focus_link" href="#">Link</a>
- <a id="focus_anchor">Unfocusable anchor</a>
- <input id="focus_input" value="Input" />
- <select id="focus_select"><option>Select</option></select>
- <button id="focus_button1">Button</button>
- <button id="focus_button2" tabindex="-1">Button 2</button>
- <button id="focus_button3" tabindex="0">Button 3</button>
- <button id="focus_button4" tabindex="1">Button 4</button>
- <div id="focus_div1">Div</div>
- <div id="focus_div2" tabindex="-1">Div 2</div>
- <div id="focus_div3" tabindex="0">Div 3</div>
- <div id="focus_div4" tabindex="1">Div 4</div>
- */});
- var node;
- node = $('focus_link');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_anchor');
- assertEquals(false, cvox.DomUtil.isFocusable(node));
- node = $('focus_input');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_select');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_button1');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_button2');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_button3');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_button4');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_div1');
- assertEquals(false, cvox.DomUtil.isFocusable(node));
- node = $('focus_div2');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_div3');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
- node = $('focus_div4');
- assertEquals(true, cvox.DomUtil.isFocusable(node));
-
- // Test it with null.
- assertEquals(false, cvox.DomUtil.isFocusable(null));
-
- // Test it with something that's not an element.
- assertEquals(false, cvox.DomUtil.isFocusable(new Object()));
-
- // Test it with a Text node.
- node = $('focus_button1').firstChild;
- assertEquals(false, cvox.DomUtil.isFocusable(node));
-});
-
-/** Some additional tests for getName function. */
-TEST_F('CvoxDomUtilUnitTest', 'GetName', function() {
- this.loadDoc(function() {/*!
- <span id="test-span" aria-labelledby="fake-id">Some text</span>
- <label id="label1">One</label>
- <label id="label3">Label</label>
- <div id="test-div" aria-labelledby="label1 label2 label3"></div>
- */});
- var node = $('test-span');
- // Makes sure we can deal with invalid ids in aria-labelledby.
- var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node));
- assertEquals('Some text', text);
- node = $('test-div');
- text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node));
- assertEquals('One Label', cvox.DomUtil.getName(node));
-});
-
-/** Test for getLinkURL. */
-TEST_F('CvoxDomUtilUnitTest', 'GetLinkURL', function() {
- this.loadDoc(function() {/*!
- <a id="l1" name="nohref">Anchor</a>
- <a id="l2" href="">Empty link</a>
- <a id="l3" href="#">Link to self</a>
- <a id="l4" href="http://google.com">Google</a>
- <span id="l5" role="link" onClick="javascript:alert('?')">Something</span>
- <div id="l6" role="link">Div with link role</a>
- */});
- var node = $('l1');
- assertEquals('', cvox.DomUtil.getLinkURL(node));
- node = $('l2');
- assertEquals('', cvox.DomUtil.getLinkURL(node));
- node = $('l3');
- assertEquals('Internal link', cvox.DomUtil.getLinkURL(node));
- node = $('l4');
- assertEquals('http://google.com', cvox.DomUtil.getLinkURL(node));
- node = $('l5');
- assertEquals('Unknown link', cvox.DomUtil.getLinkURL(node));
- node = $('l6');
- assertEquals('Unknown link', cvox.DomUtil.getLinkURL(node));
-});
-
-/** Test for isDisabled. */
-TEST_F('CvoxDomUtilUnitTest', 'IsDisabled', function() {
- this.loadDoc(function() {/*!
- <input id="button1" type="button" value="Press me!"/>
- <input id="button2" type="button" value="Don't touch me!" disabled/>
- */});
- var node = $('button1');
- assertEquals(false, cvox.DomUtil.isDisabled(node));
- node = $('button2');
- assertEquals(true, cvox.DomUtil.isDisabled(node));
-});
-
-/** Test for a tree with aria-expanded attribute. */
-TEST_F('CvoxDomUtilUnitTest', 'Tree', function() {
- this.loadDoc(function() {/*!
- <div id=":0" role="tree" aria-selected="false" aria-expanded="true"
- aria-level="0" aria-labelledby=":0.label" tabindex="0"
- aria-activedescendant=":1">
- <span id=":0.label">Countries</span>
- <div class="goog-tree-item" id=":1" role="treeitem" aria-selected="true"
- aria-expanded="false" aria-labelledby=":1.label" aria-level="1">
- <span id=":1.label">A</span>
- </div>
- <div class="goog-tree-item" id=":2" role="treeitem" aria-selected="false"
- aria-expanded="false" aria-labelledby=":2.label" aria-level="1">
- <span id=":2.label">B<span>
- </div>
- <div class="goog-tree-item" id=":3" role="treeitem" aria-selected="false"
- aria-expanded="true" aria-labelledby=":3.label" aria-level="1">
- <span id=":3.label">C</span>
- <div class="goog-tree-children" role="group">
- <div class="goog-tree-item" id=":3a" role="treeitem"
- aria-selected="false" aria-expanded="false"
- aria-labelledby=":3a.label" aria-level="2">
- <span id=":3a.label">Chile</span>
- </div>
- <div class="goog-tree-item" id=":3b" role="treeitem"
- aria-selected="false" aria-expanded="false"
- aria-labelledby=":3b.label" aria-level="2">
- <span id=":3b.label">China</span>
- </div>
- <div class="goog-tree-item" id=":3c" role="treeitem"
- aria-selected="false" aria-expanded="false"
- aria-labelledby=":3c.label" aria-level="2">
- <span id=":3c.label">Christmas Island</span>
- </div>
- <div class="goog-tree-item" id=":3d" role="treeitem"
- aria-selected="false" aria-expanded="false"
- aria-labelledby=":3d.label" aria-level="2">
- <span id=":3d.label">Cocos (Keeling) Islands</span>
- </div>
- </div>
- </div>
- </div>
- */});
- var node = $(':0');
- assertEquals('A Collapsed Selected 1 of 3',
- cvox.DomUtil.getControlValueAndStateString(node));
- node = $(':1');
- assertEquals('A Collapsed Selected 1 of 3',
- cvox.DomUtil.getControlValueAndStateString(node));
- node = $(':2');
- assertEquals('B Collapsed Not selected 2 of 3',
- cvox.DomUtil.getControlValueAndStateString(node));
- node = $(':3');
- assertEquals('C Expanded Not selected 3 of 3',
- cvox.DomUtil.getControlValueAndStateString(node));
- node = $(':3b');
- assertEquals('China Collapsed Not selected 2 of 4',
- cvox.DomUtil.getControlValueAndStateString(node));
-});
-
-/** Test for tables with different border specifications */
-TEST_F('CvoxDomUtilUnitTest', 'TableBorders', function() {
- this.loadDoc(function() {/*!
- <table id=":0" border="1">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":1" border="0">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":2" border="0px">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":3" frame="box">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":4" frame="void">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":5" style="border-width: medium">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":6" style="border-width: medium; border-style: none">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":7" style="border-color: red">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":8" style="border-style: dotted; border-width: 0px">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":9" style="border-width: 0px">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":10" style="border: 0px">
- <tr>
- <td>A</td>
- </tr>
- </table>
- <table id=":11" style="border: 0">
- <tr>
- <td>A</td>
- </tr>
- </table>
- */});
- var node = $(':0');
- assertTrue(cvox.DomUtil.hasBorder(node));
-
- node = $(':1');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':2');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':3');
- assertTrue(cvox.DomUtil.hasBorder(node));
-
- node = $(':4');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':5');
- assertTrue(cvox.DomUtil.hasBorder(node));
-
- node = $(':6');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':7');
- assertTrue(cvox.DomUtil.hasBorder(node));
-
- node = $(':8');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':9');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':10');
- assertFalse(cvox.DomUtil.hasBorder(node));
-
- node = $(':11');
- assertFalse(cvox.DomUtil.hasBorder(node));
-});
-
-/** Tests for shallowChildlessClone */
-TEST_F('CvoxDomUtilUnitTest', 'ShallowChildlessClone', function() {
- this.loadDoc(function() {/*!
- <div id='simple'>asdf</div>
- <div id='expectedSimpleClone'>asdf</div>
- <div id='oneLevel'><div>asdf</div></div>
- <div id='expectedOneLevelClone'><div></div></div>
- <div id='withAttrs'><div class="asdf">asdf</div></div>
- <div id='expectedWithAttrsClone'><div class="asdf"></div></div>
- */});
-
- var simple = $('simple').firstChild;
- var expectedSimpleClone = $('expectedSimpleClone').firstChild;
- var oneLevel = $('oneLevel').firstChild;
- var expectedOneLevelClone = $('expectedOneLevelClone').firstChild;
- var withAttrs = $('withAttrs').firstChild;
- var expectedWithAttrsClone = $('expectedWithAttrsClone').firstChild;
-
- var simpleClone = cvox.DomUtil.shallowChildlessClone(simple);
- this.assertEqualsAsText_(simpleClone, expectedSimpleClone);
-
- var oneLevelClone = cvox.DomUtil.shallowChildlessClone(oneLevel);
- this.assertEqualsAsText_(oneLevelClone, expectedOneLevelClone);
-
- var withAttrsClone = cvox.DomUtil.shallowChildlessClone(withAttrs);
- this.assertEqualsAsText_(withAttrsClone, expectedWithAttrsClone);
-});
-
-/** Tests for deepClone */
-TEST_F('CvoxDomUtilUnitTest', 'DeepClone', function() {
- this.loadDoc(function() {/*!
- <div id='simple'>asdf</div>
- */});
- var simpleClone = cvox.DomUtil.deepClone($('simple'));
- this.assertEqualsAsText_(simpleClone, $('simple'));
-
- this.loadDoc(function() {/*!
- <div id="withAttrs" class="asdf">asdf</div>
- */});
- var withAttrsClone = cvox.DomUtil.deepClone($('withAttrs'));
- this.assertEqualsAsText_(withAttrsClone, $('withAttrs'));
-});
-
-/** Tests for findNode */
-TEST_F('CvoxDomUtilUnitTest', 'FindNode', function() {
- this.loadDoc(function() {/*!
- <div id="root">
- <p id="a">a</p>
- <a href="#" id="b">b</a>
- </div>
- */});
- var f = cvox.DomUtil.findNode;
- var node = f($('root'), function(n) {return n.id == 'b';});
- assertEquals('b', node.id);
-});
-
-/** Tests for getState for a list */
-TEST_F('CvoxDomUtilUnitTest', 'ListLength', function() {
- this.loadDoc(function() {/*!
- <ul id="ul1">
- <li>A
- <li>B
- <li>C
- </ul>
- <ul id="ul2">
- <li aria-setsize="10">A
- <li aria-setsize="10">B
- <li aria-setsize="10">C
- </ul>
- */});
- var ul1 = $('ul1');
- assertEquals('with 3 items',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getState(ul1)));
-
- var ul2 = $('ul2');
- assertEquals('with 10 items',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getState(ul2)));
-});
-
-/** Tests for hasLongDesc */
-TEST_F('CvoxDomUtilUnitTest', 'HasLongDesc', function() {
- this.loadDoc(function() {/*!
- <img id="img0" longdesc="desc.html" src="img0.jpg"></img>
- <img id="img1" src="img1.jpg"></img>
- */});
- var img0 = $('img0');
- assertEquals(true, cvox.DomUtil.hasLongDesc(img0));
-
- var img1 = $('img1');
- assertEquals(false, cvox.DomUtil.hasLongDesc(img1));
-});
-
-/** Tests for various link leaf types. */
-TEST_F('CvoxDomUtilUnitTest', 'LinkLeaf', function() {
- this.loadDoc(function() {/*!
- <a id='leaf' href='google.com'><strong>Click</strong><div>here</div></a>
- <a id='non-leaf' href='google.com'>Click <h2>here</h2></a>
- */});
- var leaf = $('leaf');
- var nonLeaf = $('non-leaf');
- assertTrue(cvox.DomUtil.isLeafNode(leaf));
- assertFalse(cvox.DomUtil.isLeafNode(nonLeaf));
-});
-
-
-/** Test the value and state of a multiple select. */
-TEST_F('CvoxDomUtilUnitTest', 'MultipleSelectValue', function() {
- this.loadDoc(function() {/*!
- <select id='cars' multiple>
- <option value="volvo">Volvo</option>
- <option value="saab">Saab</option>
- <option value="opel" selected>Opel</option>
- <option value="audi" selected>Audi</option>
- </select>
- */});
- var cars = $('cars');
- assertEquals('Opel to Audi', cvox.DomUtil.getValue(cars));
- assertEquals('selected 2 items', cvox.DomUtil.getState(cars));
-});
-
-
-/**
- * Test correctness of elementToPoint.
- *
- * Absolute positioning of the container is used to avoid the window of the
- * browser being too small to contain the test elements.
- */
-TEST_F('CvoxDomUtilUnitTest', 'ElementToPoint', function() {
- this.loadDoc(function() {/*!
- <div style="position: absolute; top: 0; left: 0">
- <a id='one' href='#a'>First</a>
- <p id='two'>Some text</p>
- <ul><li id='three'>LI</li><li>LI2</li></ul>
- </div>
- */});
- var one = $('one');
- var two = $('two');
- var three = $('three');
-
- var oneHitPoint = cvox.DomUtil.elementToPoint(one);
- var twoHitPoint = cvox.DomUtil.elementToPoint(two);
- var threeHitPoint = cvox.DomUtil.elementToPoint(three);
-
- assertEquals(one, document.elementFromPoint(oneHitPoint.x, oneHitPoint.y));
- assertEquals(two, document.elementFromPoint(twoHitPoint.x, twoHitPoint.y));
- assertEquals(three,
- document.elementFromPoint(threeHitPoint.x, threeHitPoint.y));
-});
-
-/** Tests we compute the correct name for hidden aria labelledby nodes. */
-TEST_F('CvoxDomUtilUnitTest', 'HiddenAriaLabelledby', function() {
- this.loadDoc(function() {/*!
- <span id="acc_name" style="display: none">
- hello world!
- </span>
- <button id="button" aria-labelledby="acc_name">
- */});
- assertEquals('hello world!',
- cvox.DomUtil.getName($('button')));
-});
-
-/** Tests that we compute the correct state for accesskeys. */
-TEST_F('CvoxDomUtilUnitTest', 'AccessKey', function() {
- this.loadDoc(function() {/*!
- <a id='accessKey' href="#f" title="Next page" accesskey="n">Next page</a>
- */});
- var a = $('accessKey');
- assertEquals('has access key, n', cvox.DomUtil.getState(a));
-});
-
-
-/** Tests that we compute the correct name for ordered listitems. */
-TEST_F('CvoxDomUtilUnitTest', 'OrderedListitem', function() {
- this.loadDoc(function() {/*!
- <ol id="fruits_ol">
- <li id='ol_li1'>apple
- <li id='ol_li2'>orange
- <li id='ol_li3'>strawberry
- <li id='ol_li4'>banana
- </ol>
- */});
- var li1 = $('ol_li1');
- var li2 = $('ol_li2');
- var li3 = $('ol_li3');
- var li4 = $('ol_li4');
- // Note that whitespace processing happens at a higher layer
- // (DescriptionUtil).
- assertEquals('1. apple',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li1)));
- assertEquals('2. orange',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li2)));
- assertEquals('3. strawberry',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li3)));
- assertEquals('4. banana',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li4)));
-
- $('fruits_ol').style.listStyleType = 'lower-latin';
-
- assertEquals('A. apple',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li1)));
- assertEquals('B. orange',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li2)));
- assertEquals('C. strawberry',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li3)));
- assertEquals('D. banana',
- cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li4)));
-});
-
-/** Tests a node with title, and textContent containing only whitespace. */
-TEST_F('CvoxDomUtilUnitTest', 'TitleOverridesInnerWhitespace', function() {
- this.loadDoc(function() {/*!
- <button id="btn1" title="Remove from Chrome">
- <span class="lid"></span>
- <span class="can"></span>
- </button>
- */});
- var btn1 = $('btn1');
- assertEquals('Remove from Chrome', cvox.DomUtil.getName(btn1));
-});
-
-/** Test memoization. **/
-TEST_F('CvoxDomUtilUnitTest', 'Memoization', function() {
- this.loadDoc(function() {/*!
- <div id="container">
- </div>
- */});
-
- // Nest divs 100 levels deep.
- var container = $('container');
- var outer = container;
- for (var i = 0; i < 100; i++) {
- var inner = document.createElement('div');
- outer.appendChild(inner);
- outer = inner;
- }
- var target = document.createElement('p');
- target.innerHTML = 'Text';
- outer.appendChild(target);
-
- var iterations = 200;
-
- function logTime(msg, fn) {
- var t0 = new Date();
- fn();
- console.log(msg + ' elapsed time: ' + (new Date() - t0) + ' ms');
- }
-
- // First, test without memoization.
- logTime('No memoization', function() {
- container.style.visibility = 'hidden';
- for (var i = 0; i < iterations; i++) {
- assertFalse(cvox.DomUtil.isVisible(target));
- }
- container.style.visibility = 'visible';
- for (var i = 0; i < iterations; i++) {
- assertTrue(cvox.DomUtil.isVisible(target));
- }
- });
-
- // Now test with memoization enabled.
- logTime('With memoization', function() {
- cvox.Memoize.scope(function() {
- container.style.visibility = 'hidden';
- for (var i = 0; i < iterations; i++) {
- assertFalse(cvox.DomUtil.isVisible(target));
- }
- });
- cvox.Memoize.scope(function() {
- container.style.visibility = 'visible';
- for (var i = 0; i < iterations; i++) {
- assertTrue(cvox.DomUtil.isVisible(target));
- }
- });
- });
-
- // Finally as a sanity check that things are being memoized, turn on
- // memoization and show that we get the wrong result if we change the
- // DOM and call isVisible again.
- cvox.Memoize.scope(function() {
- container.style.visibility = 'hidden';
- assertFalse(cvox.DomUtil.isVisible(target));
-
- container.style.visibility = 'visible';
- // This should be true! It will return the wrong answer because
- // we're deliberately leaving memoization on while modifying the DOM.
- assertFalse(cvox.DomUtil.isVisible(target));
- });
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/earcon_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/earcon_util.js
deleted file mode 100644
index 51679ab007e..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/earcon_util.js
+++ /dev/null
@@ -1,67 +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 Earcon utils.
- */
-
-goog.provide('cvox.EarconUtil');
-
-goog.require('cvox.AbstractEarcons');
-goog.require('cvox.AriaUtil');
-goog.require('cvox.DomUtil');
-
-/**
- * Returns the id of an earcon to play along with the description for a node.
- *
- * @param {Node} node The node to get the earcon for.
- * @return {cvox.Earcon?} The earcon id, or null if none applies.
- */
-cvox.EarconUtil.getEarcon = function(node) {
- var earcon = cvox.AriaUtil.getEarcon(node);
- if (earcon != null) {
- return earcon;
- }
-
- switch (node.tagName) {
- case 'BUTTON':
- return cvox.Earcon.BUTTON;
- case 'A':
- if (node.hasAttribute('href')) {
- return cvox.Earcon.LINK;
- }
- break;
- case 'IMG':
- if (cvox.DomUtil.hasLongDesc(node)) {
- return cvox.Earcon.LONG_DESC;
- }
- break;
- case 'LI':
- return cvox.Earcon.LIST_ITEM;
- case 'SELECT':
- return cvox.Earcon.LISTBOX;
- case 'TEXTAREA':
- return cvox.Earcon.EDITABLE_TEXT;
- case 'INPUT':
- switch (node.type) {
- case 'button':
- case 'submit':
- case 'reset':
- return cvox.Earcon.BUTTON;
- case 'checkbox':
- case 'radio':
- if (node.checked) {
- return cvox.Earcon.CHECK_ON;
- } else {
- return cvox.Earcon.CHECK_OFF;
- }
- default:
- if (cvox.DomUtil.isInputTypeText(node)) {
- // 'text', 'password', etc.
- return cvox.Earcon.EDITABLE_TEXT;
- }
- }
- }
- return null;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js
deleted file mode 100644
index 9d116d24ed4..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text.js
+++ /dev/null
@@ -1,649 +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.
-
-goog.provide('cvox.ChromeVoxEditableContentEditable');
-goog.provide('cvox.ChromeVoxEditableElement');
-goog.provide('cvox.ChromeVoxEditableHTMLInput');
-goog.provide('cvox.ChromeVoxEditableTextArea');
-goog.provide('cvox.TextHandlerInterface');
-
-
-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');
-
-/**
- * @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 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 the responsibility of the user of these classes to
- * trap key and focus events and call the update method as needed.
- *
- */
-
-
-/**
- * An interface for being notified when the text changes.
- * @interface
- */
-cvox.TextHandlerInterface = function() {};
-
-
-/**
- * Called when text changes.
- * @param {cvox.TextChangeEvent} evt The text change event.
- */
-cvox.TextHandlerInterface.prototype.changed = function(evt) {};
-
-
-/**
- * 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.
- * @param {Element} node A DOM node which allows text input.
- * @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.
- * @extends {cvox.ChromeVoxEditableTextBase}
- * @constructor
- */
-cvox.ChromeVoxEditableElement = function(node, value, start, end, isPassword,
- tts) {
- 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
- */
- this.node = node;
-
- /**
- * True if the description was just spoken.
- * @type {boolean}
- * @private
- */
- this.justSpokeDescription_ = false;
-};
-goog.inherits(cvox.ChromeVoxEditableElement,
- cvox.ChromeVoxEditableTextBase);
-
-
-/** @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,
- // for example, a text field is focused and then a moment later the
- // contents are selected. If the value changes, though, this change will
- // not be ignored.
- if (this.justSpokeDescription_ && this.value == evt.value) {
- this.value = evt.value;
- this.start = evt.start;
- this.end = evt.end;
- 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++;
- node.selectionStart = node.selectionEnd;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableElement.prototype.moveCursorToPreviousCharacter =
- function() {
- var node = this.node;
- node.selectionStart--;
- node.selectionEnd = node.selectionStart;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableElement.prototype.moveCursorToNextWord = function() {
- var node = this.node;
- var length = node.value.length;
- var re = /\W+/gm;
- var substring = node.value.substring(node.selectionEnd);
- var match = re.exec(substring);
- if (match !== null && match.index == 0) {
- // Ignore word-breaking sequences right next to the cursor.
- match = re.exec(substring);
- }
- var index = (match === null) ? length : match.index + node.selectionEnd;
- node.selectionStart = node.selectionEnd = index;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableElement.prototype.moveCursorToPreviousWord = function() {
- var node = this.node;
- var length = node.value.length;
- var re = /\W+/gm;
- var substring = node.value.substring(0, node.selectionStart);
- var index = 0;
- while (re.exec(substring) !== null) {
- if (re.lastIndex < node.selectionStart) {
- index = re.lastIndex;
- }
- }
- node.selectionStart = node.selectionEnd = index;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableElement.prototype.moveCursorToNextParagraph =
- function() {
- var node = this.node;
- var length = node.value.length;
- var index = node.selectionEnd >= length ? length :
- node.value.indexOf('\n', node.selectionEnd);
- if (index < 0) {
- index = length;
- }
- node.selectionStart = node.selectionEnd = index + 1;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableElement.prototype.moveCursorToPreviousParagraph =
- function() {
- var node = this.node;
- var index = node.selectionStart <= 0 ? 0 :
- node.value.lastIndexOf('\n', node.selectionStart - 2) + 1;
- if (index < 0) {
- index = 0;
- }
- node.selectionStart = node.selectionEnd = index;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- 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);
- }
-};
-
-/******************************************/
-
-
-/**
- * A subclass of ChromeVoxEditableElement for an HTMLInputElement.
- * @param {HTMLInputElement} node The HTMLInputElement node.
- * @param {cvox.TtsInterface} tts A TTS object.
- * @extends {cvox.ChromeVoxEditableElement}
- * @implements {cvox.TextHandlerInterface}
- * @constructor
- */
-cvox.ChromeVoxEditableHTMLInput = function(node, tts) {
- this.node = node;
- this.setup();
- goog.base(this,
- node,
- node.value,
- node.selectionStart,
- node.selectionEnd,
- node.type === 'password',
- tts);
-};
-goog.inherits(cvox.ChromeVoxEditableHTMLInput,
- cvox.ChromeVoxEditableElement);
-
-
-/**
- * Performs setup for this input node.
- * This accounts for exception-throwing behavior introduced by crbug.com/324360.
- * @override
- */
-cvox.ChromeVoxEditableHTMLInput.prototype.setup = function() {
- if (!this.node) {
- return;
- }
- if (!cvox.DomUtil.doesInputSupportSelection(this.node)) {
- this.originalType = this.node.type;
- this.node.type = 'text';
- }
-};
-
-
-/**
- * Performs teardown for this input node.
- * This accounts for exception-throwing behavior introduced by crbug.com/324360.
- * @override
- */
-cvox.ChromeVoxEditableHTMLInput.prototype.teardown = function() {
- if (this.node && this.originalType) {
- this.node.type = this.originalType;
- }
-};
-
-
-/**
- * Update the state of the text and selection and describe any changes as
- * appropriate.
- *
- * @param {boolean} triggeredByUser True if this was triggered by a user action.
- */
-cvox.ChromeVoxEditableHTMLInput.prototype.update = function(triggeredByUser) {
- var newValue = this.node.value;
- var textChangeEvent = new cvox.TextChangeEvent(newValue,
- this.node.selectionStart,
- this.node.selectionEnd,
- triggeredByUser);
- this.changed(textChangeEvent);
-};
-
-
-/******************************************/
-
-
-/**
- * A subclass of ChromeVoxEditableElement for an HTMLTextAreaElement.
- * @param {HTMLTextAreaElement} node The HTMLTextAreaElement node.
- * @param {cvox.TtsInterface} tts A TTS object.
- * @extends {cvox.ChromeVoxEditableElement}
- * @implements {cvox.TextHandlerInterface}
- * @constructor
- */
-cvox.ChromeVoxEditableTextArea = function(node, tts) {
- goog.base(this, node, node.value, node.selectionStart, node.selectionEnd,
- false /* isPassword */, tts);
- this.multiline = true;
-
- /**
- * True if the shadow is up-to-date with the current value of this text area.
- * @type {boolean}
- * @private
- */
- this.shadowIsCurrent_ = false;
-};
-goog.inherits(cvox.ChromeVoxEditableTextArea,
- cvox.ChromeVoxEditableElement);
-
-
-/**
- * An offscreen div used to compute the line numbers. A single div is
- * shared by all instances of the class.
- * @type {!cvox.EditableTextAreaShadow|undefined}
- * @private
- */
-cvox.ChromeVoxEditableTextArea.shadow_;
-
-
-/**
- * Update the state of the text and selection and describe any changes as
- * appropriate.
- *
- * @param {boolean} triggeredByUser True if this was triggered by a user action.
- */
-cvox.ChromeVoxEditableTextArea.prototype.update = function(triggeredByUser) {
- if (this.node.value != this.value) {
- this.shadowIsCurrent_ = false;
- }
- var textChangeEvent = new cvox.TextChangeEvent(this.node.value,
- this.node.selectionStart, this.node.selectionEnd, triggeredByUser);
- this.changed(textChangeEvent);
-};
-
-
-/**
- * Get the line number corresponding to a particular index.
- * @param {number} index The 0-based character index.
- * @return {number} The 0-based line number corresponding to that character.
- */
-cvox.ChromeVoxEditableTextArea.prototype.getLineIndex = function(index) {
- return this.getShadow().getLineIndex(index);
-};
-
-
-/**
- * Get the start character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the first character in this line.
- */
-cvox.ChromeVoxEditableTextArea.prototype.getLineStart = function(index) {
- return this.getShadow().getLineStart(index);
-};
-
-
-/**
- * Get the end character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the end of this line.
- */
-cvox.ChromeVoxEditableTextArea.prototype.getLineEnd = function(index) {
- return this.getShadow().getLineEnd(index);
-};
-
-
-/**
- * Update the shadow object, an offscreen div used to compute line numbers.
- * @return {!cvox.EditableTextAreaShadow} The shadow object.
- */
-cvox.ChromeVoxEditableTextArea.prototype.getShadow = function() {
- var shadow = cvox.ChromeVoxEditableTextArea.shadow_;
- if (!shadow) {
- shadow = cvox.ChromeVoxEditableTextArea.shadow_ =
- new cvox.EditableTextAreaShadow();
- }
- if (!this.shadowIsCurrent_) {
- shadow.update(this.node);
- this.shadowIsCurrent_ = true;
- }
- return shadow;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableTextArea.prototype.moveCursorToNextLine = function() {
- var node = this.node;
- var length = node.value.length;
- if (node.selectionEnd >= length) {
- return false;
- }
- var shadow = this.getShadow();
- var lineIndex = shadow.getLineIndex(node.selectionEnd);
- var lineStart = shadow.getLineStart(lineIndex);
- var offset = node.selectionEnd - lineStart;
- var lastLine = (length == 0) ? 0 : shadow.getLineIndex(length - 1);
- var newCursorPosition = (lineIndex >= lastLine) ? length :
- Math.min(shadow.getLineStart(lineIndex + 1) + offset,
- shadow.getLineEnd(lineIndex + 1));
- node.selectionStart = node.selectionEnd = newCursorPosition;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableTextArea.prototype.moveCursorToPreviousLine = function() {
- var node = this.node;
- if (node.selectionStart <= 0) {
- return false;
- }
- var shadow = this.getShadow();
- var lineIndex = shadow.getLineIndex(node.selectionStart);
- var lineStart = shadow.getLineStart(lineIndex);
- var offset = node.selectionStart - lineStart;
- var newCursorPosition = (lineIndex <= 0) ? 0 :
- Math.min(shadow.getLineStart(lineIndex - 1) + offset,
- shadow.getLineEnd(lineIndex - 1));
- node.selectionStart = node.selectionEnd = newCursorPosition;
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/******************************************/
-
-
-/**
- * A subclass of ChromeVoxEditableElement for elements that are contentEditable.
- * This is also used for a region of HTML with the ARIA role of "textbox",
- * so that an author can create a pure-JavaScript editable text object - this
- * will work the same as contentEditable as long as the DOM selection is
- * updated properly within the textbox when it has focus.
- * @param {Element} node The root contentEditable node.
- * @param {cvox.TtsInterface} tts A TTS object.
- * @extends {cvox.ChromeVoxEditableElement}
- * @implements {cvox.TextHandlerInterface}
- * @constructor
- */
-cvox.ChromeVoxEditableContentEditable = function(node, tts) {
- goog.base(this, node, '', 0, 0, false /* isPassword */, tts);
-
-
- /**
- * True if the ContentEditableExtractor is current with this field's data.
- * @type {boolean}
- * @private
- */
- this.extractorIsCurrent_ = false;
-
- var extractor = this.getExtractor();
- this.value = extractor.getText();
- this.start = extractor.getStartIndex();
- this.end = extractor.getEndIndex();
- this.multiline = true;
-};
-goog.inherits(cvox.ChromeVoxEditableContentEditable,
- cvox.ChromeVoxEditableElement);
-
-/**
- * A helper used to compute the line numbers. A single object is
- * shared by all instances of the class.
- * @type {!cvox.ContentEditableExtractor|undefined}
- * @private
- */
-cvox.ChromeVoxEditableContentEditable.extractor_;
-
-
-/**
- * Update the state of the text and selection and describe any changes as
- * appropriate.
- *
- * @param {boolean} triggeredByUser True if this was triggered by a user action.
- */
-cvox.ChromeVoxEditableContentEditable.prototype.update =
- function(triggeredByUser) {
- this.extractorIsCurrent_ = false;
- var textChangeEvent = new cvox.TextChangeEvent(
- this.getExtractor().getText(),
- this.getExtractor().getStartIndex(),
- this.getExtractor().getEndIndex(),
- triggeredByUser);
- this.changed(textChangeEvent);
-};
-
-
-/**
- * Get the line number corresponding to a particular index.
- * @param {number} index The 0-based character index.
- * @return {number} The 0-based line number corresponding to that character.
- */
-cvox.ChromeVoxEditableContentEditable.prototype.getLineIndex = function(index) {
- return this.getExtractor().getLineIndex(index);
-};
-
-
-/**
- * Get the start character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the first character in this line.
- */
-cvox.ChromeVoxEditableContentEditable.prototype.getLineStart = function(index) {
- return this.getExtractor().getLineStart(index);
-};
-
-
-/**
- * Get the end character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the end of this line.
- */
-cvox.ChromeVoxEditableContentEditable.prototype.getLineEnd = function(index) {
- return this.getExtractor().getLineEnd(index);
-};
-
-
-/**
- * Update the extractor object, an offscreen div used to compute line numbers.
- * @return {!cvox.ContentEditableExtractor} The extractor object.
- */
-cvox.ChromeVoxEditableContentEditable.prototype.getExtractor = function() {
- var extractor = cvox.ChromeVoxEditableContentEditable.extractor_;
- if (!extractor) {
- extractor = cvox.ChromeVoxEditableContentEditable.extractor_ =
- new cvox.ContentEditableExtractor();
- }
- if (!this.extractorIsCurrent_) {
- extractor.update(this.node);
- this.extractorIsCurrent_ = true;
- }
- return extractor;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableContentEditable.prototype.changed =
- function(evt) {
- if (!evt.triggeredByUser) {
- return;
- }
- // Take over here if we can't describe a change; assume it's a blank line.
- if (!this.shouldDescribeChange(evt)) {
- this.speak(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);
- }
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableContentEditable.prototype.moveCursorToNextCharacter =
- function() {
- window.getSelection().modify('move', 'forward', 'character');
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableContentEditable.prototype.moveCursorToPreviousCharacter =
- function() {
- window.getSelection().modify('move', 'backward', 'character');
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/** @override */
-cvox.ChromeVoxEditableContentEditable.prototype.moveCursorToNextParagraph =
- function() {
- window.getSelection().modify('move', 'forward', 'paragraph');
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-/** @override */
-cvox.ChromeVoxEditableContentEditable.prototype.moveCursorToPreviousParagraph =
- function() {
- window.getSelection().modify('move', 'backward', 'paragraph');
- cvox.ChromeVoxEventWatcher.handleTextChanged(true);
- return true;
-};
-
-
-/**
- * @override
- */
-cvox.ChromeVoxEditableContentEditable.prototype.shouldDescribeChange =
- function(evt) {
- var sel = window.getSelection();
- var cursor = new cvox.Cursor(sel.baseNode, sel.baseOffset, '');
-
- // This is a very specific work around because of our buggy content editable
- // support. Blank new lines are not captured in the line indexing data
- // structures.
- // Scenario: given a piece of text like:
- //
- // Some Title
- //
- // Description
- // Footer
- //
- // The new lines after Title are not traversed to by TraverseUtil. A root fix
- // would make changes there. However, considering the fickle nature of that
- // code, we specifically detect for new lines here.
- if (Math.abs(this.start - evt.start) != 1 &&
- this.start == this.end &&
- evt.start == evt.end &&
- sel.baseNode == sel.extentNode &&
- sel.baseOffset == sel.extentOffset &&
- sel.baseNode.nodeType == Node.ELEMENT_NODE &&
- sel.baseNode.querySelector('BR') &&
- cvox.TraverseUtil.forwardsChar(cursor, [], [])) {
- // This case detects if the range selection surrounds a new line,
- // but there is still content after the new line (like the example
- // above after "Title"). In these cases, we "pretend" we're the
- // last character so we speak "blank".
- return false;
- }
-
- // Otherwise, we should never speak "blank" no matter what (even if
- // we're at the end of a content editable).
- return true;
-};
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
deleted file mode 100644
index bd381156c69..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow.js
+++ /dev/null
@@ -1,190 +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 Defines the EditableTextAreaShadow class.
- */
-
-goog.provide('cvox.EditableTextAreaShadow');
-
-/**
- * Creates a shadow element for an editable text area used to compute line
- * numbers.
- * @constructor
- */
-cvox.EditableTextAreaShadow = function() {
- /**
- * @type {Element}
- * @private
- */
- this.shadowElement_ = document.createElement('div');
-
- /**
- * Map from line index to a data structure containing the start
- * and end index within the line.
- * @type {Object<number, {startIndex: number, endIndex: number}>}
- * @private
- */
- this.lines_ = {};
-
- /**
- * Map from 0-based character index to 0-based line index.
- * @type {Array<number>}
- * @private
- */
- this.characterToLineMap_ = [];
-};
-
-/**
- * Update the shadow element.
- * @param {Element} element The textarea element.
- */
-cvox.EditableTextAreaShadow.prototype.update = function(element) {
- document.body.appendChild(this.shadowElement_);
-
- while (this.shadowElement_.childNodes.length) {
- this.shadowElement_.removeChild(this.shadowElement_.childNodes[0]);
- }
- this.shadowElement_.style.cssText =
- window.getComputedStyle(element, null).cssText;
- this.shadowElement_.style.position = 'absolute';
- this.shadowElement_.style.top = -9999;
- this.shadowElement_.style.left = -9999;
- this.shadowElement_.setAttribute('aria-hidden', 'true');
-
- // Add the text to the shadow element, but with an extra character to the
- // end so that we can get the bounding box of the last line - we can't
- // measure blank lines otherwise.
- var text = element.value;
- var textNode = document.createTextNode(text + '.');
- this.shadowElement_.appendChild(textNode);
-
- /**
- * For extra speed, try to skip this many characters at a time - if
- * none of the characters are newlines and they're all at the same
- * vertical position, we don't have to examine each one. If not,
- * fall back to moving by one character at a time.
- * @const
- */
- var SKIP = 8;
-
- /**
- * Map from line index to a data structure containing the start
- * and end index within the line.
- * @type {Object<number, {startIndex: number, endIndex: number}>}
- */
- var lines = {0: {startIndex: 0, endIndex: 0}};
-
- var range = document.createRange();
- var offset = 0;
- var lastGoodOffset = 0;
- var lineIndex = 0;
- var lastBottom = null;
- var nearNewline = false;
- var rect;
- while (offset <= text.length) {
- range.setStart(textNode, offset);
-
- // If we're near the end or if there's an explicit newline character,
- // don't even try to skip.
- if (offset + SKIP > text.length ||
- text.substr(offset, SKIP).indexOf('\n') >= 0) {
- nearNewline = true;
- }
-
- if (nearNewline) {
- // Move by one character.
- offset++;
- range.setEnd(textNode, offset);
- rect = range.getBoundingClientRect();
- } else {
- // Try to move by |SKIP| characters.
- range.setEnd(textNode, offset + SKIP);
- rect = range.getBoundingClientRect();
- if (rect.bottom == lastBottom) {
- // Great, they all seem to be on the same line.
- offset += SKIP;
- } else {
- // Nope, there might be a newline, better go one at a time to be safe.
- if (rect && lastBottom !== null) {
- nearNewline = true;
- }
- offset++;
- range.setEnd(textNode, offset);
- rect = range.getBoundingClientRect();
- }
- }
-
- if (offset > 0 && text[offset - 1] == '\n') {
- // Handle an explicit newline character - that always results in
- // a new line.
- lines[lineIndex].endIndex = offset - 1;
- lineIndex++;
- lines[lineIndex] = {startIndex: offset, endIndex: offset};
- lastBottom = null;
- nearNewline = false;
- lastGoodOffset = offset;
- } else if (rect && (lastBottom === null)) {
- // This is the first character we've successfully measured on this
- // line. Save the vertical position but don't do anything else.
- lastBottom = rect.bottom;
- } else if (rect && rect.bottom != lastBottom) {
- // This character is at a different vertical position, so place an
- // implicit newline immediately after the *previous* good character
- // we found (which we now know was the last character of the previous
- // line).
- lines[lineIndex].endIndex = lastGoodOffset;
- lineIndex++;
- lines[lineIndex] = {startIndex: lastGoodOffset, endIndex: lastGoodOffset};
- lastBottom = rect ? rect.bottom : null;
- nearNewline = false;
- }
-
- if (rect) {
- lastGoodOffset = offset;
- }
- }
- // Finish up the last line.
- lines[lineIndex].endIndex = text.length;
-
- // Create a map from character index to line number.
- var characterToLineMap = [];
- for (var i = 0; i <= lineIndex; i++) {
- for (var j = lines[i].startIndex; j <= lines[i].endIndex; j++) {
- characterToLineMap[j] = i;
- }
- }
-
- // Finish updating fields and remove the shadow element.
- this.characterToLineMap_ = characterToLineMap;
- this.lines_ = lines;
- document.body.removeChild(this.shadowElement_);
-};
-
-/**
- * Get the line number corresponding to a particular index.
- * @param {number} index The 0-based character index.
- * @return {number} The 0-based line number corresponding to that character.
- */
-cvox.EditableTextAreaShadow.prototype.getLineIndex = function(index) {
- return this.characterToLineMap_[index];
-};
-
-/**
- * Get the start character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the first character in this line.
- */
-cvox.EditableTextAreaShadow.prototype.getLineStart = function(index) {
- return this.lines_[index].startIndex;
-};
-
-/**
- * Get the end character index of a line.
- * @param {number} index The 0-based line index.
- * @return {number} The 0-based index of the end of this line.
- */
-cvox.EditableTextAreaShadow.prototype.getLineEnd = function(index) {
- return this.lines_[index].endIndex;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow_test.unitjs
deleted file mode 100644
index ce874225246..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_area_shadow_test.unitjs
+++ /dev/null
@@ -1,67 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxShadowUnitTest() {}
-
-CvoxShadowUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.EditableTextAreaShadow'
- ]
-};
-
-TEST_F('CvoxShadowUnitTest', 'MultilineLines', function() {
- this.loadDoc(function() {/*!
- <div><textarea id="area">
-one
-
-two
-
-three
-</textarea></div> */});
-
- var area = $('area');
-
- var shadow = new cvox.EditableTextAreaShadow();
- shadow.update(area);
- assertEquals(0, shadow.getLineIndex(0));
- assertEquals(0, shadow.getLineIndex(3));
- assertEquals(1, shadow.getLineIndex(4));
- assertEquals(2, shadow.getLineIndex(5));
- assertEquals(2, shadow.getLineIndex(8));
- assertEquals(3, shadow.getLineIndex(9));
- assertEquals(4, shadow.getLineIndex(10));
- assertEquals(4, shadow.getLineIndex(14));
-});
-
-/**
- * Test the get line of a multiline textarea with wrapping instead of
- * explicit newlines.
- * Test disabled due to not being reliable if font size changes.
- * See https://codereview.chromium.org/549303004/
- */
-TEST_F('CvoxShadowUnitTest', 'DISABLED_MultilineWrap', function() {
- this.loadDoc(function() {/*!
- <div><textarea id="area"
- cols=4 rows=20>One two thr fou fiv six sev eig</textarea>
- </div> */});
-
- var area = $('area');
-
- var shadow = new cvox.EditableTextAreaShadow();
- shadow.update(area);
- for (var i = 0; i < 32; i++) {
- assertEquals(Math.floor(i / 4), shadow.getLineIndex(i));
- }
-});
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
deleted file mode 100644
index e1f3c27ba38..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js
+++ /dev/null
@@ -1,712 +0,0 @@
-// 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(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(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 = Msgs.getMsg('text_box_blank');
- } else if (/^\s+$/.test(lineValue)) {
- lineValue = 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(Msgs.getMsg('end_of_text_verbose'),
- evt.triggeredByUser);
- } else {
- this.speak(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(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(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(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(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(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(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(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(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
deleted file mode 100644
index a122d096cb8..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/editable_text_test.unitjs
+++ /dev/null
@@ -1,693 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * A TTS class implementing speak and stop methods intended only for testing.
- * @constructor
- * @implements cvox.TtsInterface
- */
-function TestTts() {
- this.strings = [];
-}
-
-/**
- * The strings that were spoken since the last call to get().
- * @type {Array<string>}
- */
-TestTts.prototype.strings;
-
-/**
- * Returns the list of strings spoken since the last time this method was
- * called, and then clears the list.
- * @return {Array<string>} The list of strings.
- */
-TestTts.prototype.get = function() {
- var result = this.strings;
- this.strings = [];
- return result;
-};
-
-/** @override */
-TestTts.prototype.speak = function(text, queueMode, properties) {
- this.strings.push(text);
-};
-
-/** @override */
-TestTts.prototype.isSpeaking = function() {
- return false;
-};
-
-/** @override */
-TestTts.prototype.stop = function() {
- // Do nothing.
-};
-
-/** @override */
-TestTts.prototype.increaseOrDecreaseProperty =
- function(propertyName, increase) {
- // Do nothing.
-};
-
-/**
- * Stores the last braille content.
- * @constructor
- * @implements cvox.BrailleInterface
- */
-function TestBraille() {
- this.content = null;
-}
-
-/** @override */
-TestBraille.prototype.write = function(params) {
- this.content = params;
-};
-
-/**
- * Asserts the current braille content.
- *
- * @param {string} text Braille text.
- * @param {number=} opt_start Selection start.
- * @param {number=} opt_end Selection end.
- */
-TestBraille.assertContent = function(text, opt_start, opt_end) {
- var c = cvox.ChromeVox.braille.content;
- assertTrue(c != null);
- opt_start = opt_start !== undefined ? opt_start : -1;
- opt_end = opt_end !== undefined ? opt_end : opt_start;
- assertEquals(text, c.text.toString());
- assertEquals(opt_start, c.startIndex);
- assertEquals(opt_end, c.endIndex);
-};
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxEditableTextUnitTest() {}
-
-CvoxEditableTextUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.ChromeVoxEditableElement',
- 'cvox.ChromeVoxEditableHTMLInput',
- 'cvox.ChromeVoxEditableTextBase',
- 'cvox.ChromeVoxEventWatcher',
- 'cvox.TextChangeEvent',
- 'cvox.TtsInterface',
- 'cvox.TypingEcho',
- ],
-
- /** @override */
- setUp: function() {
- // TODO: These tests are all assuming we used the IBeam cursor.
- // We need to add coverage for block cursor.
- cvox.ChromeVoxEditableTextBase.useIBeamCursor = true;
- cvox.ChromeVox.typingEcho = cvox.TypingEcho.CHARACTER_AND_WORD;
- cvox.ChromeVoxEditableTextBase.eventTypingEcho = false;
- cvox.ChromeVox.braille = new TestBraille();
-
- /** Simple mock. */
- Msgs = {};
-
- /**
- * Simply return the message id.
- * @param {string} msg Message id.
- * @return {string} Message id.
- */
- Msgs.getMsg = function(msg) {
- return msg;
- };
- },
-
- /**
- * Sets up for a cursor movement test.
- * @param {string} tagName Desired tag name, "input" or "textarea".
- * @return {Object} object containing the editable element, and functions
- * to prepare, run the test, and tear down.
- * @private
- */
- setUpForCursorTest_: function(tagName) {
- var element, editable;
- switch (tagName) {
- case 'input':
- element = document.createElement('input');
- editable = new cvox.ChromeVoxEditableHTMLInput(element, new TestTts());
- break;
- case 'textarea':
- element = document.createElement('textarea');
- editable = new cvox.ChromeVoxEditableTextArea(element, new TestTts());
- break;
- default:
- throw 'invalid tagName in setUpForCursorTest_';
- }
- document.body.appendChild(element);
- element.focus();
-
- var expect = function(str) {
- assertEquals(element.selectionStart, element.selectionEnd);
- assertEquals(str, element.value.substring(0, element.selectionStart) +
- '|' + element.value.substring(element.selectionEnd));
- };
- return {
- editable: editable,
- expect: expect,
- prepare: function(str) {
- var position = str.indexOf('|');
- var value = str.substring(0, position) + str.substring(position + 1);
- element.value = value;
- element.selectionStart = element.selectionEnd = position;
- editable.update(true /* triggeredByUser */);
- expect(str);
- },
- tearDown: function() {
- document.body.removeChild(element);
- }
- };
- }
-};
-
-TEST_F('CvoxEditableTextUnitTest', 'CursorNavigation', function() {
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('Hello', 0, 0, false, tts);
-
- obj.changed(new cvox.TextChangeEvent('Hello', 1, 1));
- obj.changed(new cvox.TextChangeEvent('Hello', 2, 2));
- obj.changed(new cvox.TextChangeEvent('Hello', 3, 3));
- obj.changed(new cvox.TextChangeEvent('Hello', 4, 4));
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- obj.changed(new cvox.TextChangeEvent('Hello', 4, 4));
- obj.changed(new cvox.TextChangeEvent('Hello', 3, 3));
- assertEqualStringArrays(['H', 'e', 'l', 'l', 'o',
- 'o', 'l'], tts.get());
- obj.changed(new cvox.TextChangeEvent('Hello', 0, 0));
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- assertEqualStringArrays(['Hel', 'Hello'], tts.get());
-});
-
-/** Test typing words. */
-TEST_F('CvoxEditableTextUnitTest', 'TypingWords', function() {
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
- obj.changed(new cvox.TextChangeEvent('H', 1, 1));
- obj.changed(new cvox.TextChangeEvent('He', 2, 2));
- obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
- obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
- obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
- obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
- obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
- obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
- obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
- assertEqualStringArrays(['H', 'e', 'l', 'l', 'o', 'Hello,',
- ' ',
- 'W', 'o', 'r', 'l', 'd', 'World.'],
- tts.get());
-
- // Backspace
- obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
- obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
- assertEqualStringArrays(['.', 'd', 'l'], tts.get());
-
- // Forward-delete
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 9, 9));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 8, 8));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, or', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, r', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
- assertEqualStringArrays(['r', 'o', 'W', 'W', 'o', 'r'], tts.get());
-
- // Clear all
- obj.changed(new cvox.TextChangeEvent('', 0, 0));
- assertEqualStringArrays(['Hello, , deleted'], tts.get());
-
- // Paste / insert a whole word
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- assertEqualStringArrays(['Hello'], tts.get());
- obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
- assertEqualStringArrays([', World'], tts.get());
-});
-
-/** Test selection. */
-TEST_F('CvoxEditableTextUnitTest', 'Selection', function() {
- var tts = new TestTts();
- var obj =
- new cvox.ChromeVoxEditableTextBase('Hello, world.', 0, 0, false, tts);
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 1));
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 2));
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 3));
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 4));
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 5));
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 6));
- assertEqualStringArrays(['H', 'selected',
- 'e', 'added_to_selection',
- 'l', 'added_to_selection',
- 'l', 'added_to_selection',
- 'o', 'added_to_selection',
- ',', 'added_to_selection'],
- tts.get());
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 12));
- assertEqualStringArrays([' world', 'added_to_selection'],
- tts.get());
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 1, 12));
- assertEqualStringArrays(['H', 'removed_from_selection'],
- tts.get());
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 2, 5));
- assertEqualStringArrays(['llo', 'selected'],
- tts.get());
- obj.changed(new cvox.TextChangeEvent('Hello, world.', 2, 2));
- assertEqualStringArrays(['Unselected'],
- tts.get());
-});
-
-
-/** Test multi-line text. */
-TEST_F('CvoxEditableTextUnitTest', 'MultiLineText', function() {
- var str = 'This string\nspans\nfive lines.\n \n';
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableElement(null, str, 0, 0, false, tts);
- obj.multiline = true;
- obj.getLineIndex = function(index) {
- if (index >= 33) {
- return 4;
- } else if (index >= 30) {
- return 3;
- } else if (index >= 18) {
- return 2;
- } else if (index >= 12) {
- return 1;
- } else {
- return 0;
- }
- };
- obj.getLineStart = function(index) {
- return [0, 12, 18, 30, 33][index];
- };
- obj.getLineEnd = function(index) {
- return [11, 17, 29, 32, 33][index];
- };
- assertEquals('This string', obj.getLine(0));
- obj.changed(new cvox.TextChangeEvent(str, 12, 12));
- assertEqualStringArrays(['spans'], tts.get());
- TestBraille.assertContent('spans', 0);
- obj.changed(new cvox.TextChangeEvent(str, 18, 18));
- assertEqualStringArrays(['five lines.'], tts.get());
- TestBraille.assertContent('five lines.', 0);
- obj.changed(new cvox.TextChangeEvent(str, 30, 30));
- assertEqualStringArrays(['text_box_whitespace'], tts.get());
- TestBraille.assertContent(' ', 0);
- obj.changed(new cvox.TextChangeEvent(str, 33, 33));
- assertEqualStringArrays(['text_box_blank'], tts.get());
- TestBraille.assertContent('', 0);
- obj.changed(new cvox.TextChangeEvent(str, 0, 1));
- assertEqualStringArrays(['T', 'selected'], tts.get());
- TestBraille.assertContent('This string', 0, 1);
- obj.changed(new cvox.TextChangeEvent(str, 0, 12));
- assertEqualStringArrays(['his string\n', 'added_to_selection'],
- tts.get());
- // Newline stripped, thus 11, not 12.
- TestBraille.assertContent('This string', 0, 11);
- obj.changed(new cvox.TextChangeEvent(str, 0, str.length));
- assertEqualStringArrays([str.substr(12), 'added_to_selection'],
- tts.get());
- TestBraille.assertContent('This string', 0, 11);
- obj.changed(new cvox.TextChangeEvent(str, 12, 19));
- assertEqualStringArrays(['spans\nf', 'selected'], tts.get());
- TestBraille.assertContent('spans', 0, 5);
-});
-
-
-/**
- * Test autocomplete; suppose a user is typing "google.com/firefox" into an
- * address bar, and it's being autocompleted. Sometimes it's autocompleted
- * as they type, sometimes there's a short delay.
- */
-TEST_F('CvoxEditableTextUnitTest', 'Autocomplete', function() {
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
-
- // User types 'g'
- obj.changed(new cvox.TextChangeEvent('g', 1, 1));
- assertEqualStringArrays(['g'], tts.get());
-
- // The rest of 'google.com' is autocompleted and automatically selected.
- obj.changed(new cvox.TextChangeEvent('google.com', 1, 10));
- assertEqualStringArrays(['oogle.com, oogle.com'], tts.get());
-
- // The user doesn't realize it and types a few more characters of 'google.com'
- // and this changes the selection (unselecting) as the user types them.
- obj.changed(new cvox.TextChangeEvent('google.com', 2, 10));
- assertEqualStringArrays(['o', 'ogle.com'], tts.get());
- obj.changed(new cvox.TextChangeEvent('google.com', 3, 10));
- assertEqualStringArrays(['o', 'gle.com'], tts.get());
- obj.changed(new cvox.TextChangeEvent('google.com', 4, 10));
- assertEqualStringArrays(['g', 'le.com'], tts.get());
-
- // The user presses right-arrow, which fully unselects the remaining text.
- obj.changed(new cvox.TextChangeEvent('google.com', 10, 10));
- assertEqualStringArrays(['Unselected'], tts.get());
-
- // The user types '/'
- obj.changed(new cvox.TextChangeEvent('google.com/', 11, 11));
- assertEqualStringArrays(['com/'], tts.get());
-
- // The user types 'f', and 'finance' is autocompleted
- obj.changed(new cvox.TextChangeEvent('google.com/finance', 12, 18));
- assertEqualStringArrays(['finance, inance'], tts.get());
-
- // The user types 'i'
- obj.changed(new cvox.TextChangeEvent('google.com/finance', 13, 18));
- assertEqualStringArrays(['i', 'nance'], tts.get());
-
- // The user types 'r', now 'firefox' is autocompleted
- obj.changed(new cvox.TextChangeEvent('google.com/firefox', 14, 18));
- assertEqualStringArrays(['refox, efox'], tts.get());
-
- // The user presses right-arrow to accept the completion.
- obj.changed(new cvox.TextChangeEvent('google.com/firefox', 18, 18));
- assertEqualStringArrays(['Unselected'], tts.get());
-});
-
-
-/**
- * Test a few common scenarios where text is replaced.
- */
-TEST_F('CvoxEditableTextUnitTest', 'ReplacingText', function() {
- // Initial value is Alabama.
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('Alabama', 0, 0, false, tts);
-
- // Entire text replaced with Alaska.
- obj.changed(new cvox.TextChangeEvent('Alaska', 0, 0));
- assertEqualStringArrays(['Alaska'], tts.get());
-
- // Entire text selected.
- obj.changed(new cvox.TextChangeEvent('Alaska', 0, 6));
- assertEqualStringArrays(['Alaska', 'selected'], tts.get());
-
- // Entire text replaced with Arizona.
- obj.changed(new cvox.TextChangeEvent('Arizona', 7, 7));
- assertEqualStringArrays(['Arizona'], tts.get());
-
- // Entire text selected.
- obj.changed(new cvox.TextChangeEvent('Arizona', 0, 7));
- assertEqualStringArrays(['Arizona', 'selected'], tts.get());
-
- // Click between 'r' and 'i'.
- obj.changed(new cvox.TextChangeEvent('Arizona', 2, 2));
- assertEqualStringArrays(['Unselected'], tts.get());
-
- // Next character removed from selection.
- obj.changed(new cvox.TextChangeEvent('Arizona', 2, 7));
- assertEqualStringArrays(['izona', 'selected'], tts.get());
-
- // Selection replaced with "kansas" to make Arkansas. This time it
- // says "kansas" because the deleted text was selected.
- obj.changed(new cvox.TextChangeEvent('Arkansas', 8, 8));
- assertEqualStringArrays(['kansas'], tts.get());
-});
-
-
-/**
- * Test feedback when text changes in a long sentence.
- */
-TEST_F('CvoxEditableTextUnitTest', 'ReplacingLongText', function() {
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase(
- 'I love deadlines. I like the whooshing sound they make as they fly by.',
- 0, 0, false, tts);
-
- // Change the whole sentence without moving the cursor. It should speak
- // only the part that changed, but it should speak whole words.
- obj.changed(new cvox.TextChangeEvent(
- 'I love deadlines. I love the whooshing sounds they make as they fly by.',
- 0, 0));
- assertEqualStringArrays(['love the whooshing sounds'], tts.get());
-});
-
-/** Tests character echo. */
-TEST_F('CvoxEditableTextUnitTest', 'CharacterEcho', function() {
- cvox.ChromeVox.typingEcho = cvox.TypingEcho.CHARACTER;
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
- obj.changed(new cvox.TextChangeEvent('H', 1, 1));
- obj.changed(new cvox.TextChangeEvent('He', 2, 2));
- obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
- obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
- obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
- obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
- obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
- obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
- obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
- assertEqualStringArrays(
- ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '.'],
- tts.get());
-});
-
-
-/** Tests word echo. */
-TEST_F('CvoxEditableTextUnitTest', 'WordEcho', function() {
- cvox.ChromeVox.typingEcho = cvox.TypingEcho.WORD;
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
- obj.changed(new cvox.TextChangeEvent('H', 1, 1));
- obj.changed(new cvox.TextChangeEvent('He', 2, 2));
- obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
- obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
- obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
- obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
- obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
- obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
- obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
- assertEqualStringArrays(
- ['Hello,', 'World.'],
- tts.get());
-});
-
-
-/** Tests no echo. */
-TEST_F('CvoxEditableTextUnitTest', 'NoEcho', function() {
- cvox.ChromeVox.typingEcho = cvox.TypingEcho.NONE;
- var tts = new TestTts();
- var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
- obj.changed(new cvox.TextChangeEvent('H', 1, 1));
- obj.changed(new cvox.TextChangeEvent('He', 2, 2));
- obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
- obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
- obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
- obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
- obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
- obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
- obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
- obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
- obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
- obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
- obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
- assertEqualStringArrays(
- [],
- tts.get());
-});
-
-/** Tests cursor movement in an input field by character. */
-TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByCharacter', function() {
- var test = this.setUpForCursorTest_('input');
- var editable = test.editable, prepare = test.prepare, expect = test.expect;
- try {
- // Moving near the beginning of the text.
- prepare('|"Hello," says Sally.');
- editable.moveCursorToPreviousCharacter();
- expect('|"Hello," says Sally.');
- editable.moveCursorToNextCharacter();
- expect('"|Hello," says Sally.');
- editable.moveCursorToNextCharacter();
- expect('"H|ello," says Sally.');
-
- // Moving near the end of the text.
- prepare('"Hello," says Sally|.');
- editable.moveCursorToPreviousCharacter();
- expect('"Hello," says Sall|y.');
- editable.moveCursorToNextCharacter();
- expect('"Hello," says Sally|.');
- editable.moveCursorToNextCharacter();
- expect('"Hello," says Sally.|');
- editable.moveCursorToNextCharacter();
- expect('"Hello," says Sally.|');
- } finally {
- test.tearDown();
- }
-});
-
-/** Tests cursor movement in an input field by word. */
-TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByWord', function() {
- var test = this.setUpForCursorTest_('input');
- var editable = test.editable, prepare = test.prepare, expect = test.expect;
- try {
- // Moving forward.
- prepare('"He|llo," says Sally.');
- editable.moveCursorToNextWord();
- expect('"Hello|," says Sally.');
- editable.moveCursorToNextWord();
- expect('"Hello," says| Sally.');
- editable.moveCursorToNextWord();
- expect('"Hello," says Sally|.');
- editable.moveCursorToNextWord();
- expect('"Hello," says Sally.|');
- editable.moveCursorToNextWord();
- expect('"Hello," says Sally.|');
-
- // Moving backward.
- prepare('"Hello," says S|ally.');
- editable.moveCursorToPreviousWord();
- expect('"Hello," says |Sally.');
- editable.moveCursorToPreviousWord();
- expect('"Hello," |says Sally.');
- editable.moveCursorToPreviousWord();
- expect('"|Hello," says Sally.');
- editable.moveCursorToPreviousWord();
- expect('|"Hello," says Sally.');
- editable.moveCursorToPreviousWord();
- expect('|"Hello," says Sally.');
- } finally {
- test.tearDown();
- }
-});
-
-/** Tests that character and word movement still work in <textarea>. */
-TEST_F('CvoxEditableTextUnitTest', 'CursorMovementTextArea', function() {
- var test = this.setUpForCursorTest_('textarea');
- var editable = test.editable, prepare = test.prepare, expect = test.expect;
- try {
- prepare('|Hello, Larry.\nHello, Sergey.');
- editable.moveCursorToNextCharacter();
- expect('H|ello, Larry.\nHello, Sergey.');
- editable.moveCursorToNextWord();
- expect('Hello|, Larry.\nHello, Sergey.');
- editable.moveCursorToNextWord();
- expect('Hello, Larry|.\nHello, Sergey.');
- editable.moveCursorToNextWord();
- expect('Hello, Larry.\nHello|, Sergey.');
- editable.moveCursorToNextCharacter();
- expect('Hello, Larry.\nHello,| Sergey.');
- editable.moveCursorToPreviousWord();
- expect('Hello, Larry.\n|Hello, Sergey.');
- editable.moveCursorToPreviousCharacter();
- expect('Hello, Larry.|\nHello, Sergey.');
- } finally {
- test.tearDown();
- }
-});
-
-/** Tests that line navigation works. */
-TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByLine', function() {
- var test = this.setUpForCursorTest_('textarea');
- var editable = test.editable, prepare = test.prepare, expect = test.expect;
- try {
- prepare('123\n1234\n1234|5\n\nHi');
- editable.moveCursorToPreviousLine();
- expect('123\n1234|\n12345\n\nHi');
- editable.moveCursorToPreviousLine();
- expect('123|\n1234\n12345\n\nHi');
- editable.moveCursorToNextLine();
- expect('123\n123|4\n12345\n\nHi');
- editable.moveCursorToNextLine();
- expect('123\n1234\n123|45\n\nHi');
- editable.moveCursorToNextLine();
- expect('123\n1234\n12345\n|\nHi');
- editable.moveCursorToNextLine();
- expect('123\n1234\n12345\n\n|Hi');
- editable.moveCursorToNextLine();
- expect('123\n1234\n12345\n\nHi|');
-
- prepare('foo|bar');
- editable.moveCursorToPreviousLine();
- expect('|foobar');
- editable.moveCursorToPreviousLine();
- expect('|foobar');
- editable.moveCursorToNextLine();
- expect('foobar|');
- editable.moveCursorToNextLine();
- expect('foobar|');
- } finally {
- test.tearDown();
- }
-});
-
-/** Tests that paragraph navigation works. */
-TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByParagraph', function() {
- var test = this.setUpForCursorTest_('textarea');
- var editable = test.editable, prepare = test.prepare, expect = test.expect;
- try {
- prepare('Para|graph 1\nParagraph 2\nParagraph 3');
- editable.moveCursorToNextParagraph();
- expect('Paragraph 1\n|Paragraph 2\nParagraph 3');
- editable.moveCursorToNextParagraph();
- expect('Paragraph 1\nParagraph 2\n|Paragraph 3');
- editable.moveCursorToNextParagraph();
- expect('Paragraph 1\nParagraph 2\nParagraph 3|');
- editable.moveCursorToPreviousParagraph();
- expect('Paragraph 1\nParagraph 2\n|Paragraph 3');
- editable.moveCursorToPreviousParagraph();
- expect('Paragraph 1\n|Paragraph 2\nParagraph 3');
- editable.moveCursorToPreviousParagraph();
- expect('|Paragraph 1\nParagraph 2\nParagraph 3');
- } finally {
- test.tearDown();
- }
-});
-
-/** Tests normalization of TextChangeEvent's */
-TEST_F('CvoxEditableTextUnitTest', 'TextChangeEvent', function() {
- var event1 = new cvox.TextChangeEvent('foo', 0, 1, true);
- var event2 = new cvox.TextChangeEvent('foo', 1, 0, true);
- var event3 = new cvox.TextChangeEvent('foo', 1, 1, true);
-
- assertEquals(0, event1.start);
- assertEquals(1, event1.end);
-
- assertEquals(0, event2.start);
- assertEquals(1, event2.end);
-
- 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
deleted file mode 100644
index 6ae51f423b0..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/externs.js
+++ /dev/null
@@ -1,5 +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.
-
-Document.prototype.documentElement.innerWidth;
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js
deleted file mode 100644
index a5ac8a6b371..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util.js
+++ /dev/null
@@ -1,66 +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 Utilities for finding DOM nodes and CursorSelection's.
- */
-
-
-goog.provide('cvox.FindUtil');
-
-goog.require('cvox.BareObjectWalker');
-goog.require('cvox.CursorSelection');
-
-
-/**
- * @type {!cvox.BareObjectWalker}
- * @private
- */
-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
- * 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
- * (true), or the next node (false); defaults to false.
- * @return {cvox.CursorSelection} The selection that was found.
- * null if end of document reached.
- */
-cvox.FindUtil.findNext = function(sel, predicate, opt_initialNode) {
- var r = sel.isReversed();
- var cur = new cvox.CursorSelection(sel.absStart(), sel.absStart())
- .setReversed(r);
-
- // We may have been sync'ed into a subtree of the current predicate match.
- // Find our ancestor that matches the predicate.
- var ancestor;
- if (ancestor = predicate(cvox.DomUtil.getAncestors(cur.start.node))) {
- cur = cvox.CursorSelection.fromNode(ancestor).setReversed(r);
- if (opt_initialNode) {
- return cur;
- }
- }
-
- while (cur) {
- // Use ObjectWalker's traversal which guarantees us a stable iteration of
- // the DOM including returning null at page bounds.
- cur = cvox.FindUtil.objectWalker_.next(cur);
- var retNode = null;
- if (!cur ||
- (retNode = predicate(cvox.DomUtil.getAncestors(cur.start.node)))) {
- return retNode ? cvox.CursorSelection.fromNode(retNode) : null;
- }
-
- // Iframes require inter-frame messaging.
- if (cur.start.node.tagName == 'IFRAME') {
- return cur;
- }
- }
- return null;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util_test.unitjs
deleted file mode 100644
index 707fdcb331e..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/find_util_test.unitjs
+++ /dev/null
@@ -1,51 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxFindUtilUnitTest() {}
-
-CvoxFindUtilUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.FindUtil',
- ]
-};
-
-TEST_F('CvoxFindUtilUnitTest', 'Links', function() {
- this.loadDoc(function() {/*!
- <div>
- <p id="before">Before</p>
- <h2>Chapter 1</h2>
- <h2>Chapter 2</h2>
- <a href="#c3" id="c3" name="chapter_3"></a>
- <h2 id="c3_2">Chapter 3</h2>
- <h2 id="c4">Chapter 4</h2>
- <h2>Chapter 5</h2>
- <h2>Chapter 6</h2>
- <a href='#c7' id="c7" name="chapter_7"><h2 id="c7_2">Chapter 7</h2></a>
- <h2 id="c8">Chapter 8</h2>
- <p id="after">After</p>
- </div>
- */});
-
- var sel = cvox.CursorSelection.fromNode($('before'));
-
- var ret = cvox.FindUtil.findNext(sel, cvox.DomPredicates.linkPredicate);
- assertEquals('c3', ret.start.node.id);
- ret = cvox.FindUtil.findNext(ret, cvox.DomPredicates.linkPredicate);
- assertEquals('c7', ret.start.node.id);
-
- ret.setReversed(true);
- ret = cvox.FindUtil.findNext(ret, cvox.DomPredicates.linkPredicate);
- assertEquals('c3', ret.start.node.id);
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/focus_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/focus_util.js
deleted file mode 100644
index 4c00595a954..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/focus_util.js
+++ /dev/null
@@ -1,98 +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 collection of JavaScript utilities used to manage focus
- * within a document.
- */
-
-
-goog.provide('cvox.FocusUtil');
-
-
-/**
- * Utilities for managing focus.
- * @constructor
- */
-cvox.FocusUtil = function() {
-};
-
-/**
- * Maps whether an input element of specified type accepts text selection or
- * not. True if the element does accept text selection, false if it does not.
- * This can be used to determine whether a visitor to that element should
- * provide interactive text editing to the user.
- * From the W3C table of possible type keywords:
- * http://www.w3.org/TR/html5/the-input-element.html#attr-input-type
- *
- * TODO(dmazzoni): merge this with cvox.DomUtil.isInputTypeText
- *
- * @type {Object}
- */
-cvox.FocusUtil.INPUT_TYPE_ACCEPTS_SELECTION_TABLE = {
- 'hidden' : false,
- 'text' : true,
- 'search' : true,
- 'tel' : true,
- 'url' : true,
- 'email' : true,
- 'password' : true,
- 'datetime' : false,
- 'date' : false,
- 'month' : false,
- 'week' : false,
- 'time' : false,
- 'datetime-local' : false,
- 'number' : false,
- 'range' : false,
- 'color' : false,
- 'checkbox' : false,
- 'radio' : false,
- 'file' : false,
- 'submit' : false,
- 'image' : false,
- 'reset' : false,
- 'button' : false
-};
-
-/**
- * Checks if the currently focused element is a field that accepts text input
- * (This can include text fields and selectors)
- *
- * @return {boolean} True if the currently focused element accepts text input.
- */
-cvox.FocusUtil.isFocusInTextInputField = function() {
- var activeElement = document.activeElement;
-
- if (!activeElement) {
- return false;
- }
-
- if (activeElement.isContentEditable) {
- return true;
- }
-
- if (activeElement.getAttribute('role') == 'textbox') {
- return true;
- }
-
- if (activeElement.getAttribute('readOnly') == 'true') {
- return false;
- }
-
- if (activeElement.tagName === 'TEXTAREA' ||
- activeElement.tagName === 'SELECT') {
- return true;
- }
-
- if (activeElement.tagName === 'INPUT') {
- if (!activeElement.hasAttribute('type')) {
- return true;
- } else {
- var activeType = activeElement.getAttribute('type').toLowerCase();
- return cvox.FocusUtil.INPUT_TYPE_ACCEPTS_SELECTION_TABLE[activeType];
- }
- }
- return false;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/focuser.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/focuser.js
deleted file mode 100644
index f0a29d87c43..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/focuser.js
+++ /dev/null
@@ -1,120 +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 Implements the setFocus function.
- */
-
-goog.provide('cvox.Focuser');
-
-goog.require('cvox.ChromeVoxEventSuspender');
-goog.require('cvox.DomUtil');
-
-
-/**
- * Sets the browser focus to the targetNode or its closest ancestor that is
- * focusable.
- *
- * @param {Node} targetNode The node to move the browser focus to.
- * @param {boolean=} opt_focusDescendants Whether or not we check descendants
- * of the target node to see if they are focusable. If true, sets focus on the
- * first focusable descendant. If false, only sets focus on the targetNode or
- * its closest ancestor. Default is false.
- */
-cvox.Focuser.setFocus = function(targetNode, opt_focusDescendants) {
- // Save the selection because Chrome will lose it if there's a focus or blur.
- var sel = window.getSelection();
- var range;
- if (sel.rangeCount > 0) {
- range = sel.getRangeAt(0);
- }
- // Blur the currently-focused element if the target node is not a descendant.
- if (document.activeElement &&
- !cvox.DomUtil.isDescendantOfNode(targetNode, document.activeElement)) {
- document.activeElement.blur();
- }
-
- // Video elements should always be focusable.
- if (targetNode && (targetNode.constructor == HTMLVideoElement)) {
- if (!cvox.DomUtil.isFocusable(targetNode)) {
- targetNode.setAttribute('tabIndex', 0);
- }
- }
-
- if (opt_focusDescendants && !cvox.DomUtil.isFocusable(targetNode)) {
- var focusableDescendant = cvox.DomUtil.findFocusableDescendant(targetNode);
- if (focusableDescendant) {
- targetNode = focusableDescendant;
- }
- } else {
- // Search up the parent chain until a focusable node is found.
- while (targetNode && !cvox.DomUtil.isFocusable(targetNode)) {
- targetNode = targetNode.parentNode;
- }
- }
-
- // If we found something focusable, focus it - otherwise, blur it.
- if (cvox.DomUtil.isFocusable(targetNode)) {
- // Don't let the instance of ChromeVox in the parent focus iframe children
- // - instead, let the instance of ChromeVox in the iframe focus itself to
- // avoid getting trapped in iframes that have no ChromeVox in them.
- // This self focusing is performed by calling window.focus() in
- // cvox.NavigationManager.prototype.addInterframeListener_
- if (targetNode.tagName != 'IFRAME') {
- // setTimeout must be used because there's a bug (in Chrome, I think)
- // with .focus() which causes the page to be redrawn incorrectly if
- // not in setTimeout.
- if (cvox.ChromeVoxEventSuspender.areEventsSuspended()) {
- if (cvox.Focuser.shouldEnterSuspendEvents_(targetNode)) {
- cvox.ChromeVoxEventSuspender.enterSuspendEvents();
- }
- window.setTimeout(function() {
- targetNode.focus();
- cvox.ChromeVoxEventSuspender.exitSuspendEvents();
- }, 0);
- }
- else {
- window.setTimeout(function() {
- targetNode.focus();
- }, 0);
- }
- }
- } else if (document.activeElement &&
- document.activeElement.tagName != 'BODY') {
- document.activeElement.blur();
- }
-
- // Restore the selection, unless the focused item is a text box.
- if (cvox.DomUtil.isInputTypeText(targetNode)) {
- targetNode.select();
- } else if (range) {
- sel.removeAllRanges();
- sel.addRange(range);
- }
-};
-
-/**
- * Rules for whether or not enterSuspendEvents should be called.
- * In general, we should not enterSuspendEvents if the targetNode will get some
- * special handlers attached when a focus event is received for it; otherwise,
- * the special handlers will not get attached.
- *
- * @param {Node} targetNode The node that is being focused.
- * @return {boolean} True if enterSuspendEvents should be called.
- */
-cvox.Focuser.shouldEnterSuspendEvents_ = function(targetNode){
- if (targetNode.constructor && targetNode.constructor == HTMLVideoElement) {
- return false;
- }
- if (targetNode.hasAttribute) {
- switch (targetNode.getAttribute('type')) {
- case 'time':
- case 'date':
- case 'week':
- case 'month':
- return false;
- }
- }
- return true;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/group_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/group_util.js
deleted file mode 100644
index d2a8ff1959b..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/group_util.js
+++ /dev/null
@@ -1,150 +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 Some utilities for defining what groups are.
- */
-
-
-goog.provide('cvox.GroupUtil');
-
-goog.require('cvox.AriaUtil');
-goog.require('cvox.DomUtil');
-
-
-/**
- * If a node contains more characters than this, it should not be treated
- * as a leaf node by the smart navigation algorithm.
- *
- * This number was determined by looking at the average number of
- * characters in a paragraph:
- * http://www.fullondesign.co.uk/design/usability/
- * 285-how-many-characters-per-a-page-is-normal.htm
- * and then trying it out on a few popular websites (CNN, BBC,
- * Google Search, etc.) and making sure it made sense.
- * @type {number}
- * @private
- * @const
- */
-cvox.GroupUtil.MAX_CHARCOUNT_ = 1500;
-
-
-/**
- * If a node contains any of these elements, it should not be treated
- * as a leaf node by the smart navigation algorithm.
- * @type {string}
- * @private
- * @const
- */
-cvox.GroupUtil.BREAKOUT_SELECTOR_ = 'blockquote,' +
- 'button,' +
- 'code,' +
- 'form,' +
- 'frame,' +
- 'h1,' +
- 'h2,' +
- 'h3,' +
- 'h4,' +
- 'h5,' +
- 'h6,' +
- 'hr,' +
- 'iframe,' +
- 'input,' +
- 'object,' +
- 'ol,' +
- 'p,' +
- 'pre,' +
- 'select,' +
- 'table,' +
- 'tr,' +
- 'ul,' +
- 'math,' +
- // This takes care of MathJax expressions.
- 'span.math,' +
-// TODO (sorge) Do we want to group all math or only display math?
-// '[mode="display"],' +
- // Aria widget roles
- '[role~="alert ' +
- 'alertdialog ' +
- 'button ' +
- 'checkbox ' +
- 'combobox ' +
- 'dialog ' +
- 'log ' +
- 'marquee ' +
- 'menubar ' +
- 'progressbar ' +
- 'radio ' +
- 'radiogroup ' +
- 'scrollbar ' +
- 'slider ' +
- 'spinbutton ' +
- 'status ' +
- 'tab ' +
- 'tabpanel ' +
- 'textbox ' +
- 'toolbar ' +
- 'tooltip ' +
- 'treeitem ' +
- // Aria structure roles
- 'article ' +
- 'document ' +
- 'group ' +
- 'heading ' +
- 'img ' +
- 'list ' +
- 'math ' +
- 'region ' +
- 'row ' +
- 'separator"]';
-
-
-/**
- * Returns true if this is a leaf node for groups.
- * true for a node => true for all child nodes
- * true if node has no children
- * @param {!Node} node The node to check.
- * @return {boolean} true if this is at the "leaf node" level or lower
- * for this granularity.
- */
-cvox.GroupUtil.isLeafNode = function(node) {
- // TODO (stoarca): Write test to make sure that this function satisfies
- // the restriction given above.
- if (node.tagName == 'LABEL') {
- return cvox.DomUtil.isLeafNode(node);
- }
- if (cvox.DomUtil.isLeafNode(node)) {
- return true;
- }
-
- if (!cvox.DomUtil.isSemanticElt(node)) {
- var breakingNodes = node.querySelectorAll(
- cvox.GroupUtil.BREAKOUT_SELECTOR_);
-
- for (var i = 0; i < breakingNodes.length; ++i) {
- if (cvox.DomUtil.hasContent(breakingNodes[i])) {
- return false;
- }
- }
- }
-
- if (cvox.AriaUtil.isCompositeControl(node) &&
- !cvox.DomUtil.isFocusable(node)) {
- return false;
- }
-
- var content = cvox.DomUtil.collapseWhitespace(
- cvox.DomUtil.getValue(node) + ' ' +
- cvox.DomUtil.getName(node));
- if (content.length > cvox.GroupUtil.MAX_CHARCOUNT_) {
- return false;
- }
-
- if (content.replace(/\s/g, '') === '') {
- // Text only contains whitespace
- return false;
- }
-
- return true;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js
deleted file mode 100644
index 8d7b7fc117f..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/interframe.js
+++ /dev/null
@@ -1,240 +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 Tools for interframe communication. To use this class, every
- * window that wants to communicate with its child iframes should enumerate
- * them using document.getElementsByTagName('iframe'), create an ID to
- * associate with that iframe, then call cvox.Interframe.sendIdToIFrame
- * on each of them. Then use cvox.Interframe.sendMessageToIFrame to send
- * messages to that iframe and cvox.Interframe.addListener to receive
- * replies. When a reply is received, it will automatically contain the ID of
- * that iframe as a parameter.
- *
- */
-
-goog.provide('cvox.Interframe');
-
-goog.require('cvox.ChromeVoxJSON');
-goog.require('cvox.DomUtil');
-
-/**
- * @constructor
- */
-cvox.Interframe = function() {
-};
-
-/**
- * The prefix of all interframe messages.
- * @type {string}
- * @const
- */
-cvox.Interframe.IF_MSG_PREFIX = 'cvox.INTERFRAME:';
-
-/**
- * The message used to set the ID of a child frame so that it can send replies
- * to its parent frame.
- * @type {string}
- * @const
- */
-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}
- */
-cvox.Interframe.id;
-
-/**
- * Array of functions that have been registered as listeners to interframe
- * messages send to this window.
- * @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
- * policy. There is no reason to set this outside of a test.
- * @type {boolean}
- */
-cvox.Interframe.allowAccessToIframeContentWindow = true;
-
-/**
- * Initializes the cvox.Interframe module. (This is called automatically.)
- */
-cvox.Interframe.init = function() {
- cvox.Interframe.messageListener = function(event) {
- if (typeof event.data === 'string' &&
- event.data.indexOf(cvox.Interframe.IF_MSG_PREFIX) == 0) {
- var suffix = event.data.substr(cvox.Interframe.IF_MSG_PREFIX.length);
- var message = /** @type {Object} */ (
- 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);
- }
- }
- return false;
- };
- window.addEventListener('message', cvox.Interframe.messageListener, true);
-};
-
-/**
- * Unregister the main window event listener. Intended for clean unit testing;
- * normally there's no reason to call this outside of a test.
- */
-cvox.Interframe.shutdown = function() {
- window.removeEventListener('message', cvox.Interframe.messageListener, true);
-};
-
-/**
- * Register a function to listen to all interframe communication messages.
- * Messages from a child frame will have a parameter 'id' that you assigned
- * when you called cvox.Interframe.sendIdToIFrame.
- * @param {function(Object)} listener The listener function.
- */
-cvox.Interframe.addListener = function(listener) {
- cvox.Interframe.listeners.push(listener);
-};
-
-/**
- * Send a message to another window.
- * @param {Object} message The message to send.
- * @param {Window} window The window to receive the message.
- */
-cvox.Interframe.sendMessageToWindow = function(message, window) {
- var encodedMessage = cvox.Interframe.IF_MSG_PREFIX +
- cvox.ChromeVoxJSON.stringify(message, null, null);
- window.postMessage(encodedMessage, '*');
-};
-
-/**
- * Send a message to another iframe.
- * @param {Object} message The message to send. The message must have an 'id'
- * parameter in order to be sent.
- * @param {HTMLIFrameElement} iframe The iframe to send the message to.
- */
-cvox.Interframe.sendMessageToIFrame = function(message, iframe) {
- if (cvox.Interframe.allowAccessToIframeContentWindow &&
- iframe.contentWindow) {
- cvox.Interframe.sendMessageToWindow(message, iframe.contentWindow);
- return;
- }
-
- // A content script can't access window.parent, but the page can, so
- // inject a tiny bit of javascript into the page.
- var encodedMessage = cvox.Interframe.IF_MSG_PREFIX +
- cvox.ChromeVoxJSON.stringify(message, null, null);
- var script = document.createElement('script');
- script.type = 'text/javascript';
-
- // TODO: Make this logic more like makeNodeReference_ inside api.js
- // (line 126) so we can use an attribute instead of a classname
- if (iframe.hasAttribute('id') &&
- document.getElementById(iframe.id) == iframe) {
- // Ideally, try to send it based on the iframe's existing id.
- script.innerHTML =
- 'document.getElementById(decodeURI(\'' +
- encodeURI(iframe.id) + '\')).contentWindow.postMessage(decodeURI(\'' +
- encodeURI(encodedMessage) + '\'), \'*\');';
- } else {
- // If not, add a style name and send it based on that.
- var styleName = 'cvox_iframe' + message['id'];
- if (iframe.className === '') {
- iframe.className = styleName;
- } else if (iframe.className.indexOf(styleName) == -1) {
- iframe.className += ' ' + styleName;
- }
-
- script.innerHTML =
- 'document.getElementsByClassName(decodeURI(\'' +
- encodeURI(styleName) +
- '\'))[0].contentWindow.postMessage(decodeURI(\'' +
- encodeURI(encodedMessage) + '\'), \'*\');';
- }
-
- // Remove the script so we don't leave any clutter.
- document.head.appendChild(script);
- window.setTimeout(function() {
- document.head.removeChild(script);
- }, 1000);
-};
-
-/**
- * Send a message to the parent window of this window, if any. If the parent
- * assigned this window an ID, sends back the ID in the reply automatically.
- * @param {Object} message The message to send.
- */
-cvox.Interframe.sendMessageToParentWindow = function(message) {
- if (!cvox.Interframe.isIframe()) {
- return;
- }
-
- message['sourceId'] = cvox.Interframe.id;
- if (window.parent) {
- cvox.Interframe.sendMessageToWindow(message, window.parent);
- return;
- }
-
- // A content script can't access window.parent, but the page can, so
- // use window.location.href to execute a simple line of javascript in
- // the page context.
- var encodedMessage = cvox.Interframe.IF_MSG_PREFIX +
- cvox.ChromeVoxJSON.stringify(message, null, null);
- window.location.href =
- 'javascript:window.parent.postMessage(\'' +
- encodeURI(encodedMessage) + '\', \'*\');';
-};
-
-/**
- * Send the given ID to a child iframe.
- * @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, 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);
-};
-
-/**
- * Returns true if inside iframe
- * @return {boolean} true if inside iframe.
- */
-cvox.Interframe.isIframe = function() {
- return (window != window.parent);
-};
-
-cvox.Interframe.init();
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js
deleted file mode 100644
index 0a6f3d51c01..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence.js
+++ /dev/null
@@ -1,633 +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 JavaScript class that represents a sequence of keys entered
- * by the user.
- */
-
-
-goog.provide('cvox.KeySequence');
-
-goog.require('cvox.ChromeVox');
-goog.require('cvox.PlatformFilter');
-
-
-/**
- * A class to represent a sequence of keys entered by a user or affiliated with
- * a ChromeVox command.
- * This class can represent the data from both types of key sequences:
- *
- * COMMAND KEYS SPECIFIED IN A KEYMAP:
- * - Two discrete keys (at most): [Down arrow], [A, A] or [O, W] etc. Can
- * specify one or both.
- * - Modifiers (like ctrl, alt, meta, etc)
- * - Whether or not the ChromeVox modifier key is required with the command.
- *
- * USER INPUT:
- * - Two discrete keys (at most): [Down arrow], [A, A] or [O, W] etc.
- * - Modifiers (like ctlr, alt, meta, etc)
- * - Whether or not the ChromeVox modifier key was active when the keys were
- * entered.
- * - Whether or not a prefix key was entered before the discrete keys.
- * - Whether sticky mode was active.
- * @param {Event|Object} originalEvent The original key event entered by a user.
- * The originalEvent may or may not have parameters stickyMode and keyPrefix
- * specified. We will also accept an event-shaped object.
- * @param {boolean=} opt_cvoxModifier Whether or not the ChromeVox modifier key
- * is active. If not specified, we will try to determine whether the modifier
- * was active by looking at the originalEvent.
- * @param {boolean=} opt_skipStripping Skips stripping of ChromeVox modifiers
- * from key events when the cvox modifiers are set. Defaults to false.
- * @param {boolean=} opt_doubleTap Whether this is triggered via double tap.
- * @constructor
- */
-cvox.KeySequence = function(
- originalEvent, opt_cvoxModifier, opt_skipStripping, opt_doubleTap) {
- /** @type {boolean} */
- this.doubleTap = !!opt_doubleTap;
-
- /** @type {cvox.PlatformFilter} */
- this.platformFilter;
-
- if (opt_cvoxModifier == undefined) {
- this.cvoxModifier = this.isCVoxModifierActive(originalEvent);
- } else {
- this.cvoxModifier = opt_cvoxModifier;
- }
- this.stickyMode = !!originalEvent['stickyMode'];
- this.prefixKey = !!originalEvent['keyPrefix'];
- this.skipStripping = !!opt_skipStripping;
-
- if (this.stickyMode && this.prefixKey) {
- throw 'Prefix key and sticky mode cannot both be enabled: ' + originalEvent;
- }
-
- var event = this.resolveChromeOSSpecialKeys_(originalEvent);
-
- // TODO (rshearer): We should take the user out of sticky mode if they
- // try to use the CVox modifier or prefix key.
-
- /**
- * Stores the key codes and modifiers for the keys in the key sequence.
- * TODO(rshearer): Consider making this structure an array of minimal
- * keyEvent-like objects instead so we don't have to worry about what happens
- * when ctrlKey.length is different from altKey.length.
- *
- * NOTE: If a modifier key is pressed by itself, we will store the keyCode
- * *and* set the appropriate modKey to be true. This mirrors the way key
- * events are created on Mac and Windows. For example, if the Meta key was
- * pressed by itself, the keys object will have:
- * {metaKey: [true], keyCode:[91]}
- *
- * @type {Object}
- */
- this.keys = {
- ctrlKey: [],
- searchKeyHeld: [],
- altKey: [],
- altGraphKey: [],
- shiftKey: [],
- metaKey: [],
- keyCode: []
- };
-
- this.extractKey_(event);
-};
-
-
-// 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>}
- */
-cvox.KeySequence.KEY_PRESS_CODE = {
- 39: 222,
- 44: 188,
- 45: 189,
- 46: 190,
- 47: 191,
- 59: 186,
- 91: 219,
- 92: 220,
- 93: 221
-};
-
-/**
- * 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>}
- */
-cvox.KeySequence.doubleTapCache = [];
-
-
-/**
- * Adds an additional key onto the original sequence, for use when the user
- * is entering two shortcut keys. This happens when the user presses a key,
- * releases it, and then presses a second key. Those two keys together are
- * considered part of the sequence.
- * @param {Event|Object} additionalKeyEvent The additional key to be added to
- * the original event. Should be an event or an event-shaped object.
- * @return {boolean} Whether or not we were able to add a key. Returns false
- * if there are already two keys attached to this event.
- */
-cvox.KeySequence.prototype.addKeyEvent = function(additionalKeyEvent) {
- if (this.keys.keyCode.length > 1) {
- return false;
- }
- this.extractKey_(additionalKeyEvent);
- return true;
-};
-
-
-/**
- * Check for equality. Commands are matched based on the actual key codes
- * involved and on whether or not they both require a ChromeVox modifier key.
- *
- * If sticky mode or a prefix is active on one of the commands but not on
- * the other, then we try and match based on key code first.
- * - If both commands have the same key code and neither of them have the
- * ChromeVox modifier active then we have a match.
- * - Next we try and match with the ChromeVox modifier. If both commands have
- * the same key code, and one of them has the ChromeVox modifier and the other
- * has sticky mode or an active prefix, then we also have a match.
- * @param {!cvox.KeySequence} rhs The key sequence to compare against.
- * @return {boolean} True if equal.
- */
-cvox.KeySequence.prototype.equals = function(rhs) {
- // Check to make sure the same keys with the same modifiers were pressed.
- if (!this.checkKeyEquality_(rhs)) {
- return false;
- }
-
- if (this.doubleTap != rhs.doubleTap) {
- return false;
- }
-
- // So now we know the actual keys are the same.
- // If they both have the ChromeVox modifier, or they both don't have the
- // ChromeVox modifier, then they are considered equal.
- if (this.cvoxModifier === rhs.cvoxModifier) {
- return true;
- }
-
- // So only one of them has the ChromeVox modifier. If the one that doesn't
- // have the ChromeVox modifier has sticky mode or the prefix key then the
- // keys are still considered equal.
- var unmodified = this.cvoxModifier ? rhs : this;
- return unmodified.stickyMode || unmodified.prefixKey;
-};
-
-
-/**
- * Utility method that extracts the key code and any modifiers from a given
- * event and adds them to the object map.
- * @param {Event|Object} keyEvent The keyEvent or event-shaped object to extract
- * from.
- * @private
- */
-cvox.KeySequence.prototype.extractKey_ = function(keyEvent) {
- for (var prop in this.keys) {
- if (prop == 'keyCode') {
- var keyCode;
- // TODO (rshearer): This is temporary until we find a library that can
- // convert between ASCII charcodes and keycodes.
- if (keyEvent.type == 'keypress' && keyEvent[prop] >= 97 &&
- keyEvent[prop] <= 122) {
- // Alphabetic keypress. Convert to the upper case ASCII code.
- keyCode = keyEvent[prop] - 32;
- } else if (keyEvent.type == 'keypress') {
- keyCode = cvox.KeySequence.KEY_PRESS_CODE[keyEvent[prop]];
- }
- this.keys[prop].push(keyCode || keyEvent[prop]);
- } else {
- if (this.isKeyModifierActive(keyEvent, prop)) {
- this.keys[prop].push(true);
- } else {
- this.keys[prop].push(false);
- }
- }
- }
- if (this.cvoxModifier) {
- this.rationalizeKeys_();
- }
-};
-
-
-/**
- * Rationalizes the key codes and the ChromeVox modifier for this keySequence.
- * This means we strip out the key codes and key modifiers stored for this
- * KeySequence that are also present in the ChromeVox modifier. For example, if
- * the ChromeVox modifier keys are Ctrl+Alt, and we've determined that the
- * ChromeVox modifier is active (meaning the user has pressed Ctrl+Alt), we
- * don't want this.keys.ctrlKey = true also because that implies that this
- * KeySequence involves the ChromeVox modifier and the ctrl key being held down
- * together, which doesn't make any sense.
- * @private
- */
-cvox.KeySequence.prototype.rationalizeKeys_ = function() {
- if (this.skipStripping) {
- return;
- }
-
- // TODO (rshearer): This is a hack. When the modifier key becomes customizable
- // then we will not have to deal with strings here.
- var modifierKeyCombo = cvox.ChromeVox.modKeyStr.split(/\+/g);
-
- var index = this.keys.keyCode.length - 1;
- // For each modifier that is part of the CVox modifier, remove it from keys.
- if (modifierKeyCombo.indexOf('Ctrl') != -1) {
- this.keys.ctrlKey[index] = false;
- }
- if (modifierKeyCombo.indexOf('Alt') != -1) {
- this.keys.altKey[index] = false;
- }
- if (modifierKeyCombo.indexOf('Shift') != -1) {
- this.keys.shiftKey[index] = false;
- }
- var metaKeyName = this.getMetaKeyName_();
- if (modifierKeyCombo.indexOf(metaKeyName) != -1) {
- if (metaKeyName == 'Search') {
- this.keys.searchKeyHeld[index] = false;
- // TODO(dmazzoni): http://crbug.com/404763 Get rid of the code that
- // tracks the search key and just use meta everywhere.
- this.keys.metaKey[index] = false;
- } else if (metaKeyName == 'Cmd' || metaKeyName == 'Win') {
- this.keys.metaKey[index] = false;
- }
- }
-};
-
-
-/**
- * Get the user-facing name for the meta key (keyCode = 91), which varies
- * depending on the platform.
- * @return {string} The user-facing string name for the meta key.
- * @private
- */
-cvox.KeySequence.prototype.getMetaKeyName_ = function() {
- if (cvox.ChromeVox.isChromeOS) {
- return 'Search';
- } else if (cvox.ChromeVox.isMac) {
- return 'Cmd';
- } else {
- return 'Win';
- }
-};
-
-
-/**
- * Utility method that checks for equality of the modifiers (like shift and alt)
- * and the equality of key codes.
- * @param {!cvox.KeySequence} rhs The key sequence to compare against.
- * @return {boolean} True if the modifiers and key codes in the key sequence are
- * the same.
- * @private
- */
-cvox.KeySequence.prototype.checkKeyEquality_ = function(rhs) {
- for (var i in this.keys) {
- for (var j = this.keys[i].length; j--;) {
- if (this.keys[i][j] !== rhs.keys[i][j])
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Gets first key code
- * @return {number} The first key code.
- */
-cvox.KeySequence.prototype.getFirstKeyCode = function() {
- return this.keys.keyCode[0];
-};
-
-
-/**
- * Gets the number of keys in the sequence. Should be 1 or 2.
- * @return {number} The number of keys in the sequence.
- */
-cvox.KeySequence.prototype.length = function() {
- return this.keys.keyCode.length;
-};
-
-
-
-/**
- * Checks if the specified key code represents a modifier key, i.e. Ctrl, Alt,
- * Shift, Search (on ChromeOS) or Meta.
- *
- * @param {number} keyCode key code.
- * @return {boolean} true if it is a modifier keycode, false otherwise.
- */
-cvox.KeySequence.prototype.isModifierKey = function(keyCode) {
- // Shift, Ctrl, Alt, Search/LWin
- return keyCode == 16 || keyCode == 17 || keyCode == 18 || keyCode == 91 ||
- keyCode == 93;
-};
-
-
-/**
- * Determines whether the Cvox modifier key is active during the keyEvent.
- * @param {Event|Object} keyEvent The keyEvent or event-shaped object to check.
- * @return {boolean} Whether or not the modifier key was active during the
- * keyEvent.
- */
-cvox.KeySequence.prototype.isCVoxModifierActive = function(keyEvent) {
- // TODO (rshearer): Update this when the modifier key becomes customizable
- var modifierKeyCombo = cvox.ChromeVox.modKeyStr.split(/\+/g);
-
- // For each modifier that is held down, remove it from the combo.
- // If the combo string becomes empty, then the user has activated the combo.
- if (this.isKeyModifierActive(keyEvent, 'ctrlKey')) {
- modifierKeyCombo = modifierKeyCombo.filter(function(modifier) {
- return modifier != 'Ctrl';
- });
- }
- if (this.isKeyModifierActive(keyEvent, 'altKey')) {
- modifierKeyCombo = modifierKeyCombo.filter(function(modifier) {
- return modifier != 'Alt';
- });
- }
- if (this.isKeyModifierActive(keyEvent, 'shiftKey')) {
- modifierKeyCombo = modifierKeyCombo.filter(function(modifier) {
- return modifier != 'Shift';
- });
- }
- if (this.isKeyModifierActive(keyEvent, 'metaKey') ||
- this.isKeyModifierActive(keyEvent, 'searchKeyHeld')) {
- var metaKeyName = this.getMetaKeyName_();
- modifierKeyCombo = modifierKeyCombo.filter(function(modifier) {
- return modifier != metaKeyName;
- });
- }
- return (modifierKeyCombo.length == 0);
-};
-
-
-/**
- * Determines whether a particular key modifier (for example, ctrl or alt) is
- * active during the keyEvent.
- * @param {Event|Object} keyEvent The keyEvent or Event-shaped object to check.
- * @param {string} modifier The modifier to check.
- * @return {boolean} Whether or not the modifier key was active during the
- * keyEvent.
- */
-cvox.KeySequence.prototype.isKeyModifierActive = function(keyEvent, modifier) {
- // We need to check the key event modifier and the keyCode because Linux will
- // not set the keyEvent.modKey property if it is the modKey by itself.
- // This bug filed as crbug.com/74044
- switch (modifier) {
- case 'ctrlKey':
- return (keyEvent.ctrlKey || keyEvent.keyCode == 17);
- break;
- case 'altKey':
- return (keyEvent.altKey || (keyEvent.keyCode == 18));
- break;
- case 'shiftKey':
- return (keyEvent.shiftKey || (keyEvent.keyCode == 16));
- break;
- case 'metaKey':
- return (keyEvent.metaKey || (keyEvent.keyCode == 91));
- break;
- case 'searchKeyHeld':
- return ((cvox.ChromeVox.isChromeOS && keyEvent.keyCode == 91) ||
- keyEvent['searchKeyHeld']);
- break;
- }
- return false;
-};
-
-/**
- * Returns if any modifier is active in this sequence.
- * @return {boolean} The result.
- */
-cvox.KeySequence.prototype.isAnyModifierActive = function() {
- for (var modifierType in this.keys) {
- for (var i = 0; i < this.length(); i++) {
- if (this.keys[modifierType][i] && modifierType != 'keyCode') {
- return true;
- }
- }
- }
- return false;
-};
-
-
-/**
- * Creates a KeySequence event from a generic object.
- * @param {Object} sequenceObject The object.
- * @return {cvox.KeySequence} The created KeySequence object.
- */
-cvox.KeySequence.deserialize = function(sequenceObject) {
- var firstSequenceEvent = {};
-
- firstSequenceEvent['stickyMode'] = (sequenceObject.stickyMode == undefined) ?
- false : sequenceObject.stickyMode;
- firstSequenceEvent['prefixKey'] = (sequenceObject.prefixKey == undefined) ?
- false : sequenceObject.prefixKey;
-
-
- var secondKeyPressed = sequenceObject.keys.keyCode.length > 1;
- var secondSequenceEvent = {};
-
- for (var keyPressed in sequenceObject.keys) {
- firstSequenceEvent[keyPressed] = sequenceObject.keys[keyPressed][0];
- if (secondKeyPressed) {
- secondSequenceEvent[keyPressed] = sequenceObject.keys[keyPressed][1];
- }
- }
-
- var keySeq = new cvox.KeySequence(firstSequenceEvent,
- sequenceObject.cvoxModifier, true, sequenceObject.doubleTap);
- if (secondKeyPressed) {
- cvox.ChromeVox.sequenceSwitchKeyCodes.push(
- new cvox.KeySequence(firstSequenceEvent, sequenceObject.cvoxModifier));
- keySeq.addKeyEvent(secondSequenceEvent);
- }
-
- if (sequenceObject.doubleTap) {
- cvox.KeySequence.doubleTapCache.push(keySeq);
- }
-
- return keySeq;
-};
-
-
-/**
- * Creates a KeySequence event from a given string. The string should be in the
- * standard key sequence format described in keyUtil.keySequenceToString and
- * used in the key map JSON files.
- * @param {string} keyStr The string representation of a key sequence.
- * @return {!cvox.KeySequence} The created KeySequence object.
- */
-cvox.KeySequence.fromStr = function(keyStr) {
- var sequenceEvent = {};
- var secondSequenceEvent = {};
-
- var secondKeyPressed;
- if (keyStr.indexOf('>') == -1) {
- secondKeyPressed = false;
- } else {
- secondKeyPressed = true;
- }
-
- var cvoxPressed = false;
- sequenceEvent['stickyMode'] = false;
- sequenceEvent['prefixKey'] = false;
-
- var tokens = keyStr.split('+');
- for (var i = 0; i < tokens.length; i++) {
- var seqs = tokens[i].split('>');
- for (var j = 0; j < seqs.length; j++) {
- if (seqs[j].charAt(0) == '#') {
- var keyCode = parseInt(seqs[j].substr(1), 10);
- if (j > 0) {
- secondSequenceEvent['keyCode'] = keyCode;
- } else {
- sequenceEvent['keyCode'] = keyCode;
- }
- }
- var keyName = seqs[j];
- if (seqs[j].length == 1) {
- // Key is A/B/C...1/2/3 and we don't need to worry about setting
- // modifiers.
- if (j > 0) {
- secondSequenceEvent['keyCode'] = seqs[j].charCodeAt(0);
- } else {
- sequenceEvent['keyCode'] = seqs[j].charCodeAt(0);
- }
- } else {
- // Key is a modifier key
- if (j > 0) {
- cvox.KeySequence.setModifiersOnEvent_(keyName, secondSequenceEvent);
- if (keyName == 'Cvox') {
- cvoxPressed = true;
- }
- } else {
- cvox.KeySequence.setModifiersOnEvent_(keyName, sequenceEvent);
- if (keyName == 'Cvox') {
- cvoxPressed = true;
- }
- }
- }
- }
- }
- var keySeq = new cvox.KeySequence(sequenceEvent, cvoxPressed);
- if (secondKeyPressed) {
- keySeq.addKeyEvent(secondSequenceEvent);
- }
- return keySeq;
-};
-
-
-/**
- * Utility method for populating the modifiers on an event object that will be
- * used to create a KeySequence.
- * @param {string} keyName A particular modifier key name (such as 'Ctrl').
- * @param {Object} seqEvent The event to populate.
- * @private
- */
-cvox.KeySequence.setModifiersOnEvent_ = function(keyName, seqEvent) {
- if (keyName == 'Ctrl') {
- seqEvent['ctrlKey'] = true;
- seqEvent['keyCode'] = 17;
- } else if (keyName == 'Alt') {
- seqEvent['altKey'] = true;
- seqEvent['keyCode'] = 18;
- } else if (keyName == 'Shift') {
- seqEvent['shiftKey'] = true;
- seqEvent['keyCode'] = 16;
- } else if (keyName == 'Search') {
- seqEvent['searchKeyHeld'] = true;
- seqEvent['keyCode'] = 91;
- } else if (keyName == 'Cmd') {
- seqEvent['metaKey'] = true;
- seqEvent['keyCode'] = 91;
- } else if (keyName == 'Win') {
- seqEvent['metaKey'] = true;
- seqEvent['keyCode'] = 91;
- } else if (keyName == 'Insert') {
- seqEvent['keyCode'] = 45;
- }
-};
-
-
-/**
- * Used to resolve special ChromeOS keys (see link for more detail).
- * http://crbug.com/162268
- * @param {Object} originalEvent The event.
- * @return {Object} The resolved event.
- * @private
- */
-cvox.KeySequence.prototype.resolveChromeOSSpecialKeys_ =
- function(originalEvent) {
- if (!this.cvoxModifier || this.stickyMode || this.prefixKey ||
- !cvox.ChromeVox.isChromeOS) {
- return originalEvent;
- }
- var evt = {};
- for (var key in originalEvent) {
- evt[key] = originalEvent[key];
- }
- switch (evt['keyCode']) {
- case 33: // Page up.
- evt['keyCode'] = 38; // Up arrow.
- break;
- case 34: // Page down.
- evt['keyCode'] = 40; // Down arrow.
- break;
- case 35: // End.
- evt['keyCode'] = 39; // Right arrow.
- break;
- case 36: // Home.
- evt['keyCode'] = 37; // Left arrow.
- break;
- case 45: // Insert.
- evt['keyCode'] = 190; // Period.
- break;
- case 46: // Delete.
- evt['keyCode'] = 8; // Backspace.
- break;
- case 112: // F1.
- evt['keyCode'] = 49; // 1.
- break;
- case 113: // F2.
- evt['keyCode'] = 50; // 2.
- break;
- case 114: // F3.
- evt['keyCode'] = 51; // 3.
- break;
- case 115: // F4.
- evt['keyCode'] = 52; // 4.
- break;
- case 116: // F5.
- evt['keyCode'] = 53; // 5.
- break;
- case 117: // F6.
- evt['keyCode'] = 54; // 6.
- break;
- case 118: // F7.
- evt['keyCode'] = 55; // 7.
- break;
- case 119: // F8.
- evt['keyCode'] = 56; // 8.
- break;
- case 120: // F9.
- evt['keyCode'] = 57; // 9.
- break;
- case 121: // F10.
- evt['keyCode'] = 48; // 0.
- break;
- case 122: // F11
- evt['keyCode'] = 189; // Hyphen.
- break;
- case 123: // F12
- evt['keyCode'] = 187; // Equals.
- break;
- }
- return evt;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence_test.unitjs
deleted file mode 100644
index 14419b5595c..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_sequence_test.unitjs
+++ /dev/null
@@ -1,445 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxKeySequenceUnitTest() {}
-
-CvoxKeySequenceUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.ChromeVox',
- 'cvox.KeySequence',
- ],
-
- /**
- * Create mock event object.
- * @param {number} keyCode The event key code (i.e. 13 for Enter).
- * @param {{altGraphKey: boolean=,
- * altKey: boolean=,
- * ctrlKey: boolean=,
- * metaKey: boolean=,
- * searchKeyHeld: boolean=,
- * shiftKey: boolean=,
- * stickyMode: boolean=,
- * prefixKey: boolean=}} eventParams The parameters on the event.
- * altGraphKey: Whether or not the altGraph key was held down.
- * altKey: Whether or not the alt key was held down.
- * ctrlKey: Whether or not the ctrl key was held down.
- * metaKey: Whether or not the meta key was held down.
- * searchKeyHeld: Whether or not the search key was held down.
- * shiftKey: Whether or not the shift key was held down.
- * stickyMode: Whether or not sticky mode is enabled.
- * prefixKey: Whether or not the prefix key was entered.
- * @return {Object} The mock event.
- */
- createMockEvent: function(keyCode, eventParams) {
- var mockEvent = {};
- mockEvent.keyCode = keyCode;
-
- if (eventParams == null) {
- return mockEvent;
- }
- if (eventParams.hasOwnProperty('altGraphKey')) {
- mockEvent.altGraphKey = eventParams.altGraphKey;
- }
- if (eventParams.hasOwnProperty('altKey')) {
- mockEvent.altKey = eventParams.altKey;
- }
- if (eventParams.hasOwnProperty('ctrlKey')) {
- mockEvent.ctrlKey = eventParams.ctrlKey;
- }
- if (eventParams.hasOwnProperty('metaKey')) {
- mockEvent.metaKey = eventParams.metaKey;
- }
- if (eventParams.hasOwnProperty('shiftKey')) {
- mockEvent.shiftKey = eventParams.shiftKey;
- }
-
- if (eventParams.hasOwnProperty('searchKeyHeld')) {
- mockEvent.searchKeyHeld = eventParams.searchKeyHeld;
- }
- if (eventParams.hasOwnProperty('stickyMode')) {
- mockEvent.stickyMode = eventParams.stickyMode;
- }
- if (eventParams.hasOwnProperty('prefixKey')) {
- mockEvent.keyPrefix = eventParams.prefixKey;
- }
-
- return mockEvent;
- },
-
- /** @override */
- setUp: function() {
- // Set up mock ChromeVox modifier
- cvox.ChromeVox.modKeyStr = 'Alt';
-
- // Use these mock events in the tests:
-
- // Down arrow, no modifiers
- this.downArrowEvent = this.createMockEvent(40);
-
- // Down arrow key with alt held down. We specified 'Alt' as the
- // mock ChromeVox modifier string, so this means that KeySequence
- // should interpret this as the ChromeVox modifier being active.
- this.altDownArrowEvent = this.createMockEvent(40, {altKey: true});
-
- // Right arrow, no modifiers
- this.rightArrowEvent = this.createMockEvent(39);
-
- // Ctrl key, no modifiers
- this.ctrlEvent = this.createMockEvent(17);
-
- // Ctrl key with sticky mode
- this.ctrlStickyEvent = this.createMockEvent(17, {stickyMode: true});
-
- // Ctrl key with prefix mode
- this.ctrlPrefixEvent = this.createMockEvent(17, {prefixKey: true});
-
- // 'a' key, no modifiers
- this.aEvent = this.createMockEvent(65);
-
- // 'a' key with ctrl held down
- this.ctrlAEvent = this.createMockEvent(65, {ctrlKey: true});
-
- // 'a' key with meta held down
- this.metaAEvent = this.createMockEvent(65, {metaKey: true});
-
- // 'a' key with shift held down
- this.shiftAEvent = this.createMockEvent(65, {shiftKey: true});
-
- // 'a' key with alt (which is the mock ChromeVox modifier) and shift held
- // down.
- this.altShiftAEvent = this.createMockEvent(65, {altKey: true,
- shiftKey: true});
-
- // 'a' key with shift and prefix held down
- this.shiftAPrefixEvent = this.createMockEvent(65, {shiftKey: true,
- prefixKey: true});
-
- // 'a' key with shift and sticky mode
- this.shiftAStickyEvent = this.createMockEvent(65, {shiftKey: true,
- stickyMode: true});
-
- // 'a' key with sticky mode
- this.aEventSticky = this.createMockEvent(65, {stickyMode: true});
-
- // 'a' key with prefix key
- this.aEventPrefix = this.createMockEvent(65, {prefixKey: true});
-
- // 'a' key with alt (which is the mock ChromeVox modifier) held down
- this.altAEvent = this.createMockEvent(65, {altKey: true});
-
- // 'b' key, no modifiers
- this.bEvent = this.createMockEvent(66);
-
- // 'b' key, with ctrl held down
- this.ctrlBEvent = this.createMockEvent(66, {ctrlKey: true});
-
- // 'c' key, no modifiers
- this.cEvent = this.createMockEvent(67);
-
- // Shift key with ctrl held down
- this.ctrlShiftEvent = this.createMockEvent(60, {ctrlKey: true});
-
- // Ctrl key with shift held down
- this.shiftCtrlEvent = this.createMockEvent(17, {shiftKey: true});
- }
-};
-
-TEST_F('CvoxKeySequenceUnitTest', 'SimpleSequenceNoModifier', function() {
- var downKey = new cvox.KeySequence(this.downArrowEvent, false);
-
- assertEqualsJSON([40], downKey.keys.keyCode);
- assertFalse(downKey.stickyMode);
- assertFalse(downKey.prefixKey);
- assertFalse(downKey.cvoxModifier);
-
- assertEqualsJSON([false], downKey.keys.altGraphKey);
- assertEqualsJSON([false], downKey.keys.altKey);
- assertEqualsJSON([false], downKey.keys.ctrlKey);
- assertEqualsJSON([false], downKey.keys.metaKey);
- assertEqualsJSON([false], downKey.keys.searchKeyHeld);
- assertEqualsJSON([false], downKey.keys.shiftKey);
-
- assertEquals(1, downKey.length());
-});
-
-
-/** Test another key sequence, this time with the modifier */
-TEST_F('CvoxKeySequenceUnitTest', 'SimpleSequenceWithModifier', function() {
- var downKey = new cvox.KeySequence(this.downArrowEvent, true);
-
- assertEqualsJSON([40], downKey.keys.keyCode);
- assertFalse(downKey.stickyMode);
- assertFalse(downKey.prefixKey);
- assertTrue(downKey.cvoxModifier);
-
- assertEqualsJSON([false], downKey.keys.altGraphKey);
- assertEqualsJSON([false], downKey.keys.altKey);
- assertEqualsJSON([false], downKey.keys.ctrlKey);
- assertEqualsJSON([false], downKey.keys.metaKey);
- assertEqualsJSON([false], downKey.keys.searchKeyHeld);
- assertEqualsJSON([false], downKey.keys.shiftKey);
-
- assertEquals(1, downKey.length());
-});
-
-
-/** Test a key sequence that includes the modifier */
-TEST_F('CvoxKeySequenceUnitTest', 'ModifiedSequence', function() {
- var cvoxDownKey = new cvox.KeySequence(this.altDownArrowEvent, true);
-
- assertEqualsJSON([40], cvoxDownKey.keys.keyCode);
- assertFalse(cvoxDownKey.stickyMode);
- assertFalse(cvoxDownKey.prefixKey);
- assertTrue(cvoxDownKey.cvoxModifier);
-
- assertEqualsJSON([false], cvoxDownKey.keys.altGraphKey);
- assertEqualsJSON([false], cvoxDownKey.keys.altKey);
- assertEqualsJSON([false], cvoxDownKey.keys.ctrlKey);
- assertEqualsJSON([false], cvoxDownKey.keys.metaKey);
- assertEqualsJSON([false], cvoxDownKey.keys.searchKeyHeld);
- assertEqualsJSON([false], cvoxDownKey.keys.shiftKey);
-
- assertEquals(1, cvoxDownKey.length());
-});
-
-
-/**
- * Test equality - Ctrl key vs. Ctrl key with sticky mode on
- * These should be equal because Ctrl should still function even with
- * sticky mode on.
-*/
-TEST_F('CvoxKeySequenceUnitTest', 'StickyEquality', function() {
- var ctrlKey = new cvox.KeySequence(this.ctrlEvent, false);
- var ctrlSticky = new cvox.KeySequence(this.ctrlStickyEvent, false);
-
- assertTrue(ctrlKey.equals(ctrlSticky));
-});
-
-
-/**
- * Test equality - 'a' key with Shift modifier vs. 'a' key without Shift
- * modifier.
- * These should not be equal because they do not have the same modifiers.
-*/
-TEST_F('CvoxKeySequenceUnitTest', 'ShiftEquality', function() {
- var aKey = new cvox.KeySequence(this.aEvent, false);
- var shiftA = new cvox.KeySequence(this.shiftAEvent, false);
-
- assertFalse(aKey.equals(shiftA));
-});
-
-
-/**
- * Test equality - 'a' with ChromeVox modifier specified, 'a' with sticky mode
- * on, 'a' with prefix key, and 'a' with ChromeVox modifier held down. These
- * should all be equal to each other.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'FourWayEquality', function() {
- var commandSequence = new cvox.KeySequence(this.aEvent, true);
- var stickySequence = new cvox.KeySequence(this.aEventSticky, false);
- var prefixSequence = new cvox.KeySequence(this.aEventPrefix, false);
- var cvoxModifierSequence = new cvox.KeySequence(this.altAEvent);
-
- assertTrue(commandSequence.equals(stickySequence));
- assertTrue(commandSequence.equals(prefixSequence));
- assertTrue(commandSequence.equals(cvoxModifierSequence));
-
- assertTrue(stickySequence.equals(commandSequence));
- assertTrue(stickySequence.equals(prefixSequence));
- assertTrue(stickySequence.equals(cvoxModifierSequence));
-
- assertTrue(prefixSequence.equals(commandSequence));
- assertTrue(prefixSequence.equals(stickySequence));
- assertTrue(prefixSequence.equals(cvoxModifierSequence));
-
- assertTrue(cvoxModifierSequence.equals(commandSequence));
- assertTrue(cvoxModifierSequence.equals(stickySequence));
- assertTrue(cvoxModifierSequence.equals(prefixSequence));
-});
-
-
-/**
- * Test equality - 'a' key with Shift modifier and prefix vs. 'a' key with Shift
- * modifier and sticky mode vs. 'a' key with Shift modifier and ChromeVox
- * modifier specified vs. 'a' key with ChromeVox modifier held down.
- * These should all be equal to each other..
-*/
-TEST_F('CvoxKeySequenceUnitTest', 'ShiftPrefixEquality', function() {
- var shiftAWithModifier = new cvox.KeySequence(this.shiftAEvent, true);
- var shiftAWithPrefix = new cvox.KeySequence(this.shiftAPrefixEvent, false);
- var shiftASticky = new cvox.KeySequence(this.shiftAStickyEvent, false);
- var cvoxShiftA = new cvox.KeySequence(this.altShiftAEvent);
-
- assertTrue(shiftAWithModifier.equals(shiftAWithPrefix));
- assertTrue(shiftAWithModifier.equals(shiftASticky));
- assertTrue(shiftAWithModifier.equals(cvoxShiftA));
-
- assertTrue(shiftAWithPrefix.equals(shiftAWithModifier));
- assertTrue(shiftAWithPrefix.equals(shiftASticky));
- assertTrue(shiftAWithPrefix.equals(cvoxShiftA));
-
- assertTrue(shiftASticky.equals(shiftAWithPrefix));
- assertTrue(shiftASticky.equals(shiftAWithModifier));
- assertTrue(shiftASticky.equals(cvoxShiftA));
-
- assertTrue(cvoxShiftA.equals(shiftAWithModifier));
- assertTrue(cvoxShiftA.equals(shiftAWithPrefix));
- assertTrue(cvoxShiftA.equals(shiftASticky));
-});
-
-
-/**
- * Test inequality - 'a' with modifier key vs. 'a' without modifier key.
- * These should not be equal.
-*/
-TEST_F('CvoxKeySequenceUnitTest', 'Inequality', function() {
- var aNoModifier = new cvox.KeySequence(this.aEvent, false);
- var aWithModifier = new cvox.KeySequence(this.aEvent, true);
-
- assertFalse(aNoModifier.equals(aWithModifier));
- assertFalse(aWithModifier.equals(aNoModifier));
-});
-
-
-/**
- * Test equality - adding an additional key onto a sequence.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'CvoxCtrl', function() {
- var cvoxCtrlSequence = new cvox.KeySequence(this.ctrlEvent, true);
- assertTrue(cvoxCtrlSequence.addKeyEvent(this.rightArrowEvent));
-
- assertEquals(2, cvoxCtrlSequence.length());
-
- // Can't add more than two key events.
- assertFalse(cvoxCtrlSequence.addKeyEvent(this.rightArrowEvent));
-
- var cvoxCtrlStickySequence = new cvox.KeySequence(this.ctrlStickyEvent,
- false);
- assertTrue(cvoxCtrlStickySequence.addKeyEvent(this.rightArrowEvent));
-
- var mockCtrlPrefixSequence = new cvox.KeySequence(this.ctrlPrefixEvent,
- false);
- assertTrue(mockCtrlPrefixSequence.addKeyEvent(this.rightArrowEvent));
-
- assertTrue(cvoxCtrlSequence.equals(cvoxCtrlStickySequence));
- assertTrue(cvoxCtrlStickySequence.equals(cvoxCtrlSequence));
-
- assertTrue(cvoxCtrlSequence.equals(mockCtrlPrefixSequence));
- assertTrue(mockCtrlPrefixSequence.equals(cvoxCtrlSequence));
-
- assertTrue(cvoxCtrlStickySequence.equals(mockCtrlPrefixSequence));
- assertTrue(mockCtrlPrefixSequence.equals(cvoxCtrlStickySequence));
-});
-
-
-/**
- * Test for inequality - key sequences in different orders.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'DifferentSequences', function() {
- var cvoxBSequence = new cvox.KeySequence(this.bEvent, true);
- assertTrue(cvoxBSequence.addKeyEvent(this.cEvent));
-
- var cvoxCSequence = new cvox.KeySequence(this.cEvent, false);
- assertTrue(cvoxCSequence.addKeyEvent(this.bEvent));
-
- assertFalse(cvoxBSequence.equals(cvoxCSequence));
- assertFalse(cvoxCSequence.equals(cvoxBSequence));
-});
-
-
-/**
- * Tests modifiers (ctrl, alt, etc) - if two sequences have different modifiers
- * held down then they aren't equal.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'MoreModifiers', function() {
- var ctrlASequence = new cvox.KeySequence(this.ctrlAEvent, false);
- var ctrlModifierKeyASequence = new cvox.KeySequence(this.ctrlAEvent, true);
-
- var ctrlBSequence = new cvox.KeySequence(this.ctrlBEvent, false);
-
- var metaASequence = new cvox.KeySequence(this.metaAEvent, false);
-
- assertFalse(ctrlASequence.equals(metaASequence));
- assertFalse(ctrlASequence.equals(ctrlModifierKeyASequence));
- assertFalse(ctrlASequence.equals(ctrlBSequence));
-});
-
-
-/**
- * Tests modifier (ctrl, alt, etc) order - if two sequences have the same
- * modifiers but held down in a different order then they aren't equal.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'ModifierOrder', function() {
- var ctrlShiftSequence = new cvox.KeySequence(this.ctrlShiftEvent, false);
- var shiftCtrlSequence = new cvox.KeySequence(this.shiftCtrlEvent, true);
-
- assertFalse(ctrlShiftSequence.equals(shiftCtrlSequence));
-});
-
-
-/**
- * Tests converting from a string to a KeySequence object.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'FromStr', function() {
- var ctrlString = cvox.KeySequence.fromStr('Ctrl');
- assertEqualsJSON(ctrlString.keys.ctrlKey, [true]);
- assertEqualsJSON(ctrlString.keys.keyCode, [17]);
-
- var modifiedLetterString = cvox.KeySequence.fromStr('Ctrl+Z');
- assertEqualsJSON(modifiedLetterString.keys.ctrlKey, [true]);
- assertEqualsJSON(modifiedLetterString.keys.keyCode, [90]);
-
- var keyCodeString = cvox.KeySequence.fromStr('#9');
- assertEqualsJSON(keyCodeString.keys.keyCode, [9]);
-
- var modifiedKeyCodeString = cvox.KeySequence.fromStr('Shift+#9');
- assertEqualsJSON(modifiedKeyCodeString.keys.shiftKey, [true]);
- assertEqualsJSON(modifiedKeyCodeString.keys.keyCode, [9]);
-
- var cvoxLetterString = cvox.KeySequence.fromStr('Cvox+U');
- assertTrue(cvoxLetterString.cvoxModifier);
- assertEqualsJSON(cvoxLetterString.keys.keyCode, [85]);
-
- var cvoxSequenceString = cvox.KeySequence.fromStr('Cvox+C>T');
- assertTrue(cvoxSequenceString.cvoxModifier);
- assertEqualsJSON(cvoxSequenceString.keys.keyCode, [67, 84]);
-
- var cvoxSequenceKeyCodeString = cvox.KeySequence.fromStr('Cvox+L>#186');
- assertTrue(cvoxSequenceKeyCodeString.cvoxModifier);
- assertEqualsJSON(cvoxSequenceKeyCodeString.keys.keyCode, [76, 186]);
-
- var stickyString = cvox.KeySequence.fromStr('Insert>Insert+');
- assertEqualsJSON(stickyString.keys.keyCode, [45, 45]);
-});
-
-
-/**
- * Tests converting from a JSON string to a KeySequence object.
- */
-TEST_F('CvoxKeySequenceUnitTest', 'Deserialize', function() {
- var forwardSequence = cvox.KeySequence.deserialize({'cvoxModifier': true,
- 'stickyMode': false, 'prefixKey': false, 'keys': {'ctrlKey': [false],
- 'searchKeyHeld': [false], 'altKey': [false], 'altGraphKey': [false],
- 'shiftKey': [false], 'metaKey': [false], 'keyCode': [40]}});
- assertTrue(forwardSequence.cvoxModifier);
- assertEqualsJSON(forwardSequence.keys.keyCode, [40]);
-
- var ctrlSequence = cvox.KeySequence.deserialize({'cvoxModifier': false,
- 'stickyMode': true, 'prefixKey': false, 'keys': {'ctrlKey': [true],
- 'searchKeyHeld': [false], 'altKey': [false], 'altGraphKey': [false],
- 'shiftKey': [false], 'metaKey': [false], 'keyCode': [17]}});
- assertEqualsJSON(ctrlSequence.keys.ctrlKey, [true]);
- assertEqualsJSON(ctrlSequence.keys.keyCode, [17]);
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js
deleted file mode 100644
index 5ff64d01d7a..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/key_util.js
+++ /dev/null
@@ -1,500 +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 collection of JavaScript utilities used to simplify working
- * with keyboard events.
- */
-
-
-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
- * @constructor
- */
-cvox.KeyUtil = function() {
-};
-
-/**
- * The time in ms at which the ChromeVox Sticky Mode key was pressed.
- * @type {number}
- */
-cvox.KeyUtil.modeKeyPressTime = 0;
-
-/**
- * Indicates if sequencing is currently active for building a keyboard shortcut.
- * @type {boolean}
- */
-cvox.KeyUtil.sequencing = false;
-
-/**
- * The previous KeySequence when sequencing is ON.
- * @type {cvox.KeySequence}
- */
-cvox.KeyUtil.prevKeySequence = null;
-
-
-/**
- * The sticky key sequence.
- * @type {cvox.KeySequence}
- */
-cvox.KeyUtil.stickyKeySequence = null;
-
-/**
- * Maximum number of key codes the sequence buffer may hold. This is the max
- * length of a sequential keyboard shortcut, i.e. the number of key that can be
- * pressed one after the other while modifier keys (Cros+Shift) are held down.
- * @const
- * @type {number}
- */
-cvox.KeyUtil.maxSeqLength = 2;
-
-
-/**
- * Convert a key event into a Key Sequence representation.
- *
- * @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) {
- var util = cvox.KeyUtil;
- if (util.prevKeySequence &&
- (util.maxSeqLength == util.prevKeySequence.length())) {
- // Reset the sequence buffer if max sequence length is reached.
- util.sequencing = false;
- util.prevKeySequence = null;
- }
- // Either we are in the middle of a key sequence (N > H), or the key prefix
- // was pressed before (Ctrl+Z), or sticky mode is enabled
- var keyIsPrefixed = util.sequencing || keyEvent['keyPrefix'] ||
- keyEvent['stickyMode'];
-
- // Create key sequence.
- var keySequence = new cvox.KeySequence(keyEvent);
-
- // Check if the Cvox key should be considered as pressed because the
- // modifier key combination is active.
- var keyWasCvox = keySequence.cvoxModifier;
-
- if (keyIsPrefixed || keyWasCvox) {
- if (!util.sequencing && util.isSequenceSwitchKeyCode(keySequence)) {
- // If this is the beginning of a sequence.
- util.sequencing = true;
- util.prevKeySequence = keySequence;
- return keySequence;
- } else if (util.sequencing) {
- if (util.prevKeySequence.addKeyEvent(keyEvent)) {
- keySequence = util.prevKeySequence;
- util.prevKeySequence = null;
- util.sequencing = false;
- return keySequence;
- } else {
- throw 'Think sequencing is enabled, yet util.prevKeySequence already' +
- 'has two key codes' + util.prevKeySequence;
- }
- }
- } else {
- util.sequencing = false;
- }
-
- // Repeated keys pressed.
- var currTime = new Date().getTime();
- if (cvox.KeyUtil.isDoubleTapKey(keySequence) &&
- util.prevKeySequence &&
- keySequence.equals(util.prevKeySequence)) {
- var prevTime = util.modeKeyPressTime;
- if (prevTime > 0 && currTime - prevTime < 300) { // Double tap
- keySequence = util.prevKeySequence;
- keySequence.doubleTap = true;
- util.prevKeySequence = null;
- util.sequencing = false;
- // Resets the search key state tracked for ChromeOS because in OOBE,
- // we never get a key up for the key down (keyCode 91).
- if (cvox.ChromeVox.isChromeOS &&
- keyEvent.keyCode == cvox.KeyUtil.getStickyKeyCode()) {
- cvox.ChromeVox.searchKeyHeld = false;
- }
- return keySequence;
- }
- // The user double tapped the sticky key but didn't do it within the
- // required time. It's possible they will try again, so keep track of the
- // time the sticky key was pressed and keep track of the corresponding
- // key sequence.
- }
- util.prevKeySequence = keySequence;
- util.modeKeyPressTime = currTime;
- return keySequence;
-};
-
-/**
- * Returns the string representation of the specified key code.
- *
- * @param {number} keyCode key code.
- * @return {string} A string representation of the key event.
- */
-cvox.KeyUtil.keyCodeToString = function(keyCode) {
- if (keyCode == 17) {
- return 'Ctrl';
- }
- if (keyCode == 18) {
- return 'Alt';
- }
- if (keyCode == 16) {
- return 'Shift';
- }
- if ((keyCode == 91) || (keyCode == 93)) {
- if (cvox.ChromeVox.isChromeOS) {
- return 'Search';
- } else if (cvox.ChromeVox.isMac) {
- return 'Cmd';
- } else {
- return 'Win';
- }
- }
- // TODO(rshearer): This is a hack to work around the special casing of the
- // sticky mode string that used to happen in keyEventToString. We won't need
- // it once we move away from strings completely.
- if (keyCode == 45) {
- return 'Insert';
- }
- if (keyCode >= 65 && keyCode <= 90) {
- // A - Z
- return String.fromCharCode(keyCode);
- } else if (keyCode >= 48 && keyCode <= 57) {
- // 0 - 9
- return String.fromCharCode(keyCode);
- } else {
- // Anything else
- return '#' + keyCode;
- }
-};
-
-/**
- * Returns the keycode of a string representation of the specified modifier.
- *
- * @param {string} keyString Modifier key.
- * @return {number} Key code.
- */
-cvox.KeyUtil.modStringToKeyCode = function(keyString) {
- switch (keyString) {
- case 'Ctrl':
- return 17;
- case 'Alt':
- return 18;
- case 'Shift':
- return 16;
- case 'Cmd':
- case 'Win':
- return 91;
- }
- return -1;
-};
-
-/**
- * Returns the key codes of a string respresentation of the ChromeVox modifiers.
- *
- * @return {Array<number>} Array of key codes.
- */
-cvox.KeyUtil.cvoxModKeyCodes = function() {
- var modKeyCombo = cvox.ChromeVox.modKeyStr.split(/\+/g);
- var modKeyCodes = modKeyCombo.map(function(keyString) {
- return cvox.KeyUtil.modStringToKeyCode(keyString);
- });
- return modKeyCodes;
-};
-
-/**
- * Checks if the specified key code is a key used for switching into a sequence
- * mode. Sequence switch keys are specified in
- * cvox.KeyUtil.sequenceSwitchKeyCodes
- *
- * @param {!cvox.KeySequence} rhKeySeq The key sequence to check.
- * @return {boolean} true if it is a sequence switch keycode, false otherwise.
- */
-cvox.KeyUtil.isSequenceSwitchKeyCode = function(rhKeySeq) {
- for (var i = 0; i < cvox.ChromeVox.sequenceSwitchKeyCodes.length; i++) {
- var lhKeySeq = cvox.ChromeVox.sequenceSwitchKeyCodes[i];
- if (lhKeySeq.equals(rhKeySeq)) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Get readable string description of the specified keycode.
- *
- * @param {number} keyCode The key code.
- * @return {string} Returns a string description.
- */
-cvox.KeyUtil.getReadableNameForKeyCode = function(keyCode) {
- if (keyCode == 0) {
- return 'Power button';
- } else if (keyCode == 17) {
- return 'Control';
- } else if (keyCode == 18) {
- return 'Alt';
- } else if (keyCode == 16) {
- return 'Shift';
- } else if (keyCode == 9) {
- return 'Tab';
- } else if ((keyCode == 91) || (keyCode == 93)) {
- if (cvox.ChromeVox.isChromeOS) {
- return 'Search';
- } else if (cvox.ChromeVox.isMac) {
- return 'Cmd';
- } else {
- return 'Win';
- }
- } else if (keyCode == 8) {
- return 'Backspace';
- } else if (keyCode == 32) {
- return 'Space';
- } else if (keyCode == 35) {
- return'end';
- } else if (keyCode == 36) {
- return 'home';
- } else if (keyCode == 37) {
- return 'Left arrow';
- } else if (keyCode == 38) {
- return 'Up arrow';
- } else if (keyCode == 39) {
- return 'Right arrow';
- } else if (keyCode == 40) {
- return 'Down arrow';
- } else if (keyCode == 45) {
- return 'Insert';
- } else if (keyCode == 13) {
- return 'Enter';
- } else if (keyCode == 27) {
- return 'Escape';
- } else if (keyCode == 112) {
- return cvox.ChromeVox.isChromeOS ? 'Back' : 'F1';
- } else if (keyCode == 113) {
- return cvox.ChromeVox.isChromeOS ? 'Forward' : 'F2';
- } else if (keyCode == 114) {
- return cvox.ChromeVox.isChromeOS ? 'Refresh' : 'F3';
- } else if (keyCode == 115) {
- return cvox.ChromeVox.isChromeOS ? 'Toggle full screen' : 'F4';
- } else if (keyCode == 116) {
- return 'F5';
- } else if (keyCode == 117) {
- return 'F6';
- } else if (keyCode == 118) {
- return 'F7';
- } else if (keyCode == 119) {
- return 'F8';
- } else if (keyCode == 120) {
- return 'F9';
- } else if (keyCode == 121) {
- return 'F10';
- } else if (keyCode == 122) {
- return 'F11';
- } else if (keyCode == 123) {
- return 'F12';
- } else if (keyCode == 186) {
- return 'Semicolon';
- } else if (keyCode == 187) {
- return 'Equal sign';
- } else if (keyCode == 188) {
- return 'Comma';
- } else if (keyCode == 189) {
- return 'Dash';
- } else if (keyCode == 190) {
- return 'Period';
- } else if (keyCode == 191) {
- return 'Forward slash';
- } else if (keyCode == 192) {
- return 'Grave accent';
- } else if (keyCode == 219) {
- return 'Open bracket';
- } else if (keyCode == 220) {
- return 'Back slash';
- } else if (keyCode == 221) {
- return 'Close bracket';
- } else if (keyCode == 222) {
- return 'Single quote';
- } else if (keyCode == 115) {
- return 'Toggle full screen';
- } else if (keyCode >= 48 && keyCode <= 90) {
- return String.fromCharCode(keyCode);
- }
-};
-
-/**
- * Get the platform specific sticky key keycode.
- *
- * @return {number} The platform specific sticky key keycode.
- */
-cvox.KeyUtil.getStickyKeyCode = function() {
- // TODO (rshearer): This should not be hard-coded here.
- var stickyKeyCode = 45; // Insert for Linux and Windows
- if (cvox.ChromeVox.isChromeOS || cvox.ChromeVox.isMac) {
- stickyKeyCode = 91; // GUI key (Search/Cmd) for ChromeOs and Mac
- }
- return stickyKeyCode;
-};
-
-
-/**
- * Get readable string description for an internal string representation of a
- * key or a keyboard shortcut.
- *
- * @param {string} keyStr The internal string repsentation of a key or
- * a keyboard shortcut.
- * @return {?string} Readable string representation of the input.
- */
-cvox.KeyUtil.getReadableNameForStr = function(keyStr) {
- // TODO (clchen): Refactor this function away since it is no longer used.
- return null;
-};
-
-
-/**
- * Creates a string representation of a KeySequence.
- * A KeySequence with a keyCode of 76 ('L') and the control and alt keys down
- * would return the string 'Ctrl+Alt+L', for example. A key code that doesn't
- * correspond to a letter or number will typically return a string with a
- * pound and then its keyCode, like '#39' for Right Arrow. However,
- * if the opt_readableKeyCode option is specified, the key code will return a
- * readable string description like 'Right Arrow' instead of '#39'.
- *
- * The modifiers always come in this order:
- *
- * Ctrl
- * Alt
- * Shift
- * Meta
- *
- * @param {cvox.KeySequence} keySequence The KeySequence object.
- * @param {boolean=} opt_readableKeyCode Whether or not to return a readable
- * string description instead of a string with a pound symbol and a keycode.
- * Default is false.
- * @param {boolean=} opt_modifiers Restrict printout to only modifiers. Defaults
- * to false.
- * @return {string} Readable string representation of the KeySequence object.
- */
-cvox.KeyUtil.keySequenceToString = function(
- keySequence, opt_readableKeyCode, opt_modifiers) {
- // TODO(rshearer): Move this method and the getReadableNameForKeyCode and the
- // method to KeySequence after we refactor isModifierActive (when the modifie
- // key becomes customizable and isn't stored as a string). We can't do it
- // earlier because isModifierActive uses KeyUtil.getReadableNameForKeyCode,
- // and I don't want KeySequence to depend on KeyUtil.
- var str = '';
-
- var numKeys = keySequence.length();
-
- for (var index = 0; index < numKeys; index++) {
- if (str != '' && !opt_modifiers) {
- str += '>';
- } else if (str != '') {
- str += '+';
- }
-
- // This iterates through the sequence. Either we're on the first key
- // pressed or the second
- var tempStr = '';
- for (var keyPressed in keySequence.keys) {
- // This iterates through the actual key, taking into account any
- // modifiers.
- if (!keySequence.keys[keyPressed][index]) {
- continue;
- }
- var modifier = '';
- switch (keyPressed) {
- case 'ctrlKey':
- // TODO(rshearer): This is a hack to work around the special casing
- // of the Ctrl key that used to happen in keyEventToString. We won't
- // need it once we move away from strings completely.
- modifier = 'Ctrl';
- break;
- case 'searchKeyHeld':
- var searchKey = cvox.KeyUtil.getReadableNameForKeyCode(91);
- modifier = searchKey;
- break;
- case 'altKey':
- modifier = 'Alt';
- break;
- case 'altGraphKey':
- modifier = 'AltGraph';
- break;
- case 'shiftKey':
- modifier = 'Shift';
- break;
- case 'metaKey':
- var metaKey = cvox.KeyUtil.getReadableNameForKeyCode(91);
- modifier = metaKey;
- break;
- case 'keyCode':
- var keyCode = keySequence.keys[keyPressed][index];
- // We make sure the keyCode isn't for a modifier key. If it is, then
- // we've already added that into the string above.
- if (!keySequence.isModifierKey(keyCode) && !opt_modifiers) {
- if (opt_readableKeyCode) {
- tempStr += cvox.KeyUtil.getReadableNameForKeyCode(keyCode);
- } else {
- tempStr += cvox.KeyUtil.keyCodeToString(keyCode);
- }
- }
- }
- if (str.indexOf(modifier) == -1) {
- tempStr += modifier + '+';
- }
- }
- str += tempStr;
-
- // Strip trailing +.
- if (str[str.length - 1] == '+') {
- str = str.slice(0, -1);
- }
- }
-
- if (keySequence.cvoxModifier || keySequence.prefixKey) {
- if (str != '') {
- str = 'Cvox+' + str;
- } else {
- str = 'Cvox';
- }
- } else if (keySequence.stickyMode) {
- if (str[str.length - 1] == '>') {
- str = str.slice(0, -1);
- }
- str = str + '+' + str;
- }
- return str;
-};
-
-/**
- * Looks up if the given key sequence is triggered via double tap.
- * @param {cvox.KeySequence} key The key.
- * @return {boolean} True if key is triggered via double tap.
- */
-cvox.KeyUtil.isDoubleTapKey = function(key) {
- var isSet = false;
- var originalState = key.doubleTap;
- key.doubleTap = true;
- for (var i = 0, keySeq; keySeq = cvox.KeySequence.doubleTapCache[i]; i++) {
- if (keySeq.equals(key)) {
- isSet = true;
- break;
- }
- }
- key.doubleTap = originalState;
- return isSet;
-};
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
deleted file mode 100644
index 940121dc852..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_attr.js
+++ /dev/null
@@ -1,1529 +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 Semantic attributes of Math symbols and expressions.
- *
- * This file contains the basic functionality to lookup and assign semantic
- * attributes for mathematical expressions. Since there is no such thing as a
- * well-defined semantics for all of mathematics we compute a default semantics
- * that closely models mathematical expressions found in K-12 mathematics as
- * well as in general undergraduate curriculum (i.e., calculus, linear algebra,
- * etc).
- *
- * Currently semantic attributes of symbols consist of the following two parts:
- *
- * type -- An unmutable property of an expression, regardless of its position in
- * the math expression. For example, the letter 'f' will always have the
- * type identifier, regardless of its use in context, e.g. as function
- * symbol or variable.
- *
- * role -- A mutable description of the role an expression plays in the context
- * of the overall mathematical expression. For instance, the symbol '|'
- * is of type punctuation, but depending on context it has the role of a
- * neutral fence or of a single vertical bar.
- *
- * In addition for some symbols we record the font as a further attribute.
- *
- * When a semantically interpreted expression is transformed into a XML
- * representation, types become tag names, while role, font, etc. are added as
- * attributes.
- *
- * This file is part of the content script as we do not want to call out to the
- * background page every time we need to look up the semantic of a symbol.
- *
- * TODO (sorge) Move semantic tree translation into the background page
- * alongside MathJax.
- *
- */
-
-goog.provide('cvox.SemanticAttr');
-
-goog.require('cvox.SemanticUtil');
-
-
-/**
- * Contains the basic mappings of characters/symbols and functions to semantic
- * attributes.
- *
- * Observe that all characters are given as hex code number in order to ease the
- * comparison with those in the JSON files that define speech rules per
- * character.
- * @constructor
- */
-cvox.SemanticAttr = function() {
- // Punctuation Characters.
- /**
- * @type {Array<string>}
- */
- this.generalPunctuations =
- [
- '!', '"', '#', '%', '&', '\'', '*', ',', ':', ';', '?', '@', '\\',
- '¡', '§', '¶', '·', '¿', '‗', '†', '‡', '•', '‣', '․', '‥', '‧',
- '‰', '‱', '‸', '※', '‼', '‽', '‾', '⁁', '⁂', '⁃', '⁇', '⁈', '⁉',
- '⁋', '⁌', '⁍', '⁎', '⁏', '⁐', '⁑', '⁓', '⁕', '⁖', '⁘', '⁙', '⁚',
- '⁛', '⁜', '⁝', '⁞', '︐', '︓', '︔', '︕', '︖', '︰', '﹅', '﹆',
- '﹉', '﹊', '﹋', '﹌', '﹐', '﹔', '﹕', '﹖', '﹗', '﹟', '﹠', '﹡', '﹨',
- '﹪', '﹫', '!', '"', '#', '%', '&', ''', '*', ',', '/', ':',
- ';', '?', '@', '\'
- ];
- /**
- * @type {string}
- * @private
- */
- this.invisibleComma_ = cvox.SemanticUtil.numberToUnicode(0x2063);
- this.generalPunctuations.push(this.invisibleComma_);
- /**
- * @type {Array<string>}
- */
- this.ellipses =
- [
- '…', '⋮', '⋯', '⋰', '⋱', '︙'
- ];
- /**
- * @type {Array<string>}
- */
- this.fullStops =
- [
- '.', '﹒', '.'
- ];
- /**
- * @type {Array<string>}
- */
- this.dashes =
- [
- '‒', '–', '—', '―', '〜', '︱', '︲', '﹘'
- ];
- /**
- * @type {Array<string>}
- */
- this.primes =
- [
- '′', '″', '‴', '‵', '‶', '‷', '⁗'
- ];
-
- // Fences.
- // Fences are treated slightly differently from other symbols as we want to
- // record pairs of opening/closing and top/bottom fences.
- /**
- * Mapping opening to closing fences.
- * @type {Object<string>}
- */
- this.openClosePairs =
- {
- // Unicode categories Ps and Pe.
- // Observe that left quotation 301D could also be matched to 301F,
- // but is currently matched to 301E.
- '(': ')', '[': ']', '{': '}', '⁅': '⁆', '〈': '〉', '❨': '❩',
- '❪': '❫', '❬': '❭', '❮': '❯', '❰': '❱', '❲': '❳', '❴': '❵',
- '⟅': '⟆', '⟦': '⟧', '⟨': '⟩', '⟪': '⟫', '⟬': '⟭', '⟮': '⟯',
- '⦃': '⦄', '⦅': '⦆', '⦇': '⦈', '⦉': '⦊', '⦋': '⦌', '⦍': '⦎',
- '⦏': '⦐', '⦑': '⦒', '⦓': '⦔', '⦕': '⦖', '⦗': '⦘', '⧘': '⧙',
- '⧚': '⧛', '⧼': '⧽', '⸢': '⸣', '⸤': '⸥', '⸦': '⸧', '⸨': '⸩',
- '〈': '〉', '《': '》', '「': '」', '『': '』', '【': '】',
- '〔': '〕', '〖': '〗', '〘': '〙', '〚': '〛', '〝': '〞',
- '﴾': '﴿', '︗': '︘', '﹙': '﹚', '﹛': '﹜', '﹝': '﹞', '(': ')',
- '[': ']', '{': '}', '⦅': '⦆', '「': '」',
- // Unicode categories Sm and So.
- '⌈': '⌉', '⌊': '⌋', '⌌': '⌍', '⌎': '⌏', '⌜': '⌝', '⌞': '⌟',
- // Extender fences.
- // Parenthesis.
- '⎛': '⎞', '⎜': '⎟', '⎝': '⎠',
- // Square bracket.
- '⎡': '⎤', '⎢': '⎥', '⎣': '⎦',
- // Curly bracket.
- '⎧': '⎫', '⎨': '⎬', '⎩': '⎭', '⎰': '⎱', '⎸': '⎹'
- };
- /**
- * Mapping top to bottom fences.
- * @type {Object<string>}
- */
- this.topBottomPairs =
- {
- '⎴': '⎵', '⏜': '⏝', '⏞': '⏟', '⏠': '⏡', '︵': '︶', '︷': '︸',
- '︹': '︺', '︻': '︼', '︽': '︾', '︿': '﹀', '﹁': '﹂',
- '﹃': '﹄', '﹇': '﹈'
- };
- /**
- * @type {Array<string>}
- */
- this.leftFences = cvox.SemanticUtil.objectsToKeys(this.openClosePairs);
- /**
- * @type {Array<string>}
- */
- this.rightFences = cvox.SemanticUtil.objectsToValues(this.openClosePairs);
- this.rightFences.push('〟');
- /**
- * @type {Array<string>}
- */
- this.topFences = cvox.SemanticUtil.objectsToKeys(this.topBottomPairs);
- /**
- * @type {Array<string>}
- */
- this.bottomFences = cvox.SemanticUtil.objectsToValues(this.topBottomPairs);
- /**
- * @type {Array<string>}
- */
- this.neutralFences =
- [
- '|', '¦', '‖', '❘', '⦀', '⫴', '¦', '|'
- ];
- /** Array of all fences.
- * @type {Array<string>}
- */
- this.fences = this.neutralFences.concat(
- this.leftFences, this.rightFences, this.topFences, this.bottomFences);
-
- // Identifiers.
- // Latin Alphabets.
- /**
- * @type {Array<string>}
- */
- this.capitalLatin =
- [
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatin =
- [
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- // dotless i and j.
- 'ı', 'ȷ'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinFullWidth =
- [
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinFullWidth =
- [
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinBold =
- [
- '𝐀', '𝐁', '𝐂', '𝐃', '𝐄', '𝐅', '𝐆', '𝐇', '𝐈', '𝐉', '𝐊', '𝐋', '𝐌',
- '𝐍', '𝐎', '𝐏', '𝐐', '𝐑', '𝐒', '𝐓', '𝐔', '𝐕', '𝐖', '𝐗', '𝐘', '𝐙'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinBold =
- [
- '𝐚', '𝐛', '𝐜', '𝐝', '𝐞', '𝐟', '𝐠', '𝐡', '𝐢', '𝐣', '𝐤', '𝐥', '𝐦',
- '𝐧', '𝐨', '𝐩', '𝐪', '𝐫', '𝐬', '𝐭', '𝐮', '𝐯', '𝐰', '𝐱', '𝐲', '𝐳'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinItalic =
- [
- '𝐴', '𝐵', '𝐶', '𝐷', '𝐸', '𝐹', '𝐺', '𝐻', '𝐼', '𝐽', '𝐾', '𝐿', '𝑀',
- '𝑁', '𝑂', '𝑃', '𝑄', '𝑅', '𝑆', '𝑇', '𝑈', '𝑉', '𝑊', '𝑋', '𝑌', '𝑍'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinItalic =
- [
- '𝑎', '𝑏', '𝑐', '𝑑', '𝑒', '𝑓', '𝑔', 'ℎ', '𝑖', '𝑗', '𝑘', '𝑙', '𝑚',
- '𝑛', '𝑜', '𝑝', '𝑞', '𝑟', '𝑠', '𝑡', '𝑢', '𝑣', '𝑤', '𝑥', '𝑦', '𝑧',
- // dotless i and j.
- '𝚤', '𝚥'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinScript =
- [
- '𝒜', 'ℬ', '𝒞', '𝒟', 'ℰ', 'ℱ', '𝒢', 'ℋ', 'ℐ', '𝒥', '𝒦', 'ℒ', 'ℳ',
- '𝒩', '𝒪', '𝒫', '𝒬', 'ℛ', '𝒮', '𝒯', '𝒰', '𝒱', '𝒲', '𝒳', '𝒴', '𝒵',
- // Powerset Cap P.
- '℘'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinScript =
- [
- '𝒶', '𝒷', '𝒸', '𝒹', 'ℯ', '𝒻', 'ℊ', '𝒽', '𝒾', '𝒿', '𝓀', '𝓁', '𝓂',
- '𝓃', 'ℴ', '𝓅', '𝓆', '𝓇', '𝓈', '𝓉', '𝓊', '𝓋', '𝓌', '𝓍', '𝓎', '𝓏',
- // script small l
- 'ℓ'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinBoldScript =
- [
- '𝓐', '𝓑', '𝓒', '𝓓', '𝓔', '𝓕', '𝓖', '𝓗', '𝓘', '𝓙', '𝓚', '𝓛', '𝓜',
- '𝓝', '𝓞', '𝓟', '𝓠', '𝓡', '𝓢', '𝓣', '𝓤', '𝓥', '𝓦', '𝓧', '𝓨', '𝓩'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinBoldScript =
- [
- '𝓪', '𝓫', '𝓬', '𝓭', '𝓮', '𝓯', '𝓰', '𝓱', '𝓲', '𝓳', '𝓴', '𝓵', '𝓶',
- '𝓷', '𝓸', '𝓹', '𝓺', '𝓻', '𝓼', '𝓽', '𝓾', '𝓿', '𝔀', '𝔁', '𝔂', '𝔃'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinFraktur =
- [
- '𝔄', '𝔅', 'ℭ', '𝔇', '𝔈', '𝔉', '𝔊', 'ℌ', 'ℑ', '𝔍', '𝔎', '𝔏', '𝔐',
- '𝔑', '𝔒', '𝔓', '𝔔', 'ℜ', '𝔖', '𝔗', '𝔘', '𝔙', '𝔚', '𝔛', '𝔜', 'ℨ'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinFraktur =
- [
- '𝔞', '𝔟', '𝔠', '𝔡', '𝔢', '𝔣', '𝔤', '𝔥', '𝔦', '𝔧', '𝔨', '𝔩', '𝔪',
- '𝔫', '𝔬', '𝔭', '𝔮', '𝔯', '𝔰', '𝔱', '𝔲', '𝔳', '𝔴', '𝔵', '𝔶', '𝔷'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinDoubleStruck =
- [
- '𝔸', '𝔹', 'ℂ', '𝔻', '𝔼', '𝔽', '𝔾', 'ℍ', '𝕀', '𝕁', '𝕂', '𝕃', '𝕄',
- 'ℕ', '𝕆', 'ℙ', 'ℚ', 'ℝ', '𝕊', '𝕋', '𝕌', '𝕍', '𝕎', '𝕏', '𝕐', 'ℤ'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinDoubleStruck =
- [
- '𝕒', '𝕓', '𝕔', '𝕕', '𝕖', '𝕗', '𝕘', '𝕙', '𝕚', '𝕛', '𝕜', '𝕝', '𝕞',
- '𝕟', '𝕠', '𝕡', '𝕢', '𝕣', '𝕤', '𝕥', '𝕦', '𝕧', '𝕨', '𝕩', '𝕪', '𝕫'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinBoldFraktur =
- [
- '𝕬', '𝕭', '𝕮', '𝕯', '𝕰', '𝕱', '𝕲', '𝕳', '𝕴', '𝕵', '𝕶', '𝕷', '𝕸',
- '𝕹', '𝕺', '𝕻', '𝕼', '𝕽', '𝕾', '𝕿', '𝖀', '𝖁', '𝖂', '𝖃', '𝖄', '𝖅'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinBoldFraktur =
- [
- '𝖆', '𝖇', '𝖈', '𝖉', '𝖊', '𝖋', '𝖌', '𝖍', '𝖎', '𝖏', '𝖐', '𝖑', '𝖒',
- '𝖓', '𝖔', '𝖕', '𝖖', '𝖗', '𝖘', '𝖙', '𝖚', '𝖛', '𝖜', '𝖝', '𝖞', '𝖟'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinSansSerif =
- [
- '𝖠', '𝖡', '𝖢', '𝖣', '𝖤', '𝖥', '𝖦', '𝖧', '𝖨', '𝖩', '𝖪', '𝖫', '𝖬',
- '𝖭', '𝖮', '𝖯', '𝖰', '𝖱', '𝖲', '𝖳', '𝖴', '𝖵', '𝖶', '𝖷', '𝖸', '𝖹'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinSansSerif =
- [
- '𝖺', '𝖻', '𝖼', '𝖽', '𝖾', '𝖿', '𝗀', '𝗁', '𝗂', '𝗃', '𝗄', '𝗅', '𝗆',
- '𝗇', '𝗈', '𝗉', '𝗊', '𝗋', '𝗌', '𝗍', '𝗎', '𝗏', '𝗐', '𝗑', '𝗒', '𝗓'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinSansSerifBold =
- [
- '𝗔', '𝗕', '𝗖', '𝗗', '𝗘', '𝗙', '𝗚', '𝗛', '𝗜', '𝗝', '𝗞', '𝗟', '𝗠',
- '𝗡', '𝗢', '𝗣', '𝗤', '𝗥', '𝗦', '𝗧', '𝗨', '𝗩', '𝗪', '𝗫', '𝗬', '𝗭'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinSansSerifBold =
- [
- '𝗮', '𝗯', '𝗰', '𝗱', '𝗲', '𝗳', '𝗴', '𝗵', '𝗶', '𝗷', '𝗸', '𝗹', '𝗺',
- '𝗻', '𝗼', '𝗽', '𝗾', '𝗿', '𝘀', '𝘁', '𝘂', '𝘃', '𝘄', '𝘅', '𝘆', '𝘇'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinSansSerifItalic =
- [
- '𝘈', '𝘉', '𝘊', '𝘋', '𝘌', '𝘍', '𝘎', '𝘏', '𝘐', '𝘑', '𝘒', '𝘓', '𝘔',
- '𝘕', '𝘖', '𝘗', '𝘘', '𝘙', '𝘚', '𝘛', '𝘜', '𝘝', '𝘞', '𝘟', '𝘠', '𝘡'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinSansSerifItalic =
- [
- '𝘢', '𝘣', '𝘤', '𝘥', '𝘦', '𝘧', '𝘨', '𝘩', '𝘪', '𝘫', '𝘬', '𝘭', '𝘮',
- '𝘯', '𝘰', '𝘱', '𝘲', '𝘳', '𝘴', '𝘵', '𝘶', '𝘷', '𝘸', '𝘹', '𝘺', '𝘻'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalLatinMonospace =
- [
- '𝙰', '𝙱', '𝙲', '𝙳', '𝙴', '𝙵', '𝙶', '𝙷', '𝙸', '𝙹', '𝙺', '𝙻', '𝙼',
- '𝙽', '𝙾', '𝙿', '𝚀', '𝚁', '𝚂', '𝚃', '𝚄', '𝚅', '𝚆', '𝚇', '𝚈', '𝚉'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallLatinMonospace =
- [
- '𝚊', '𝚋', '𝚌', '𝚍', '𝚎', '𝚏', '𝚐', '𝚑', '𝚒', '𝚓', '𝚔', '𝚕', '𝚖',
- '𝚗', '𝚘', '𝚙', '𝚚', '𝚛', '𝚜', '𝚝', '𝚞', '𝚟', '𝚠', '𝚡', '𝚢', '𝚣'
- ];
- /**
- * @type {Array<string>}
- */
- this.latinDoubleStruckItalic =
- [
- 'ⅅ', 'ⅆ', 'ⅇ', 'ⅈ', 'ⅉ'
- ];
-
- // Greek Alphabets
- /**
- * @type {Array<string>}
- */
- this.capitalGreek =
- [
- 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν',
- 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallGreek =
- [
- 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν',
- 'ξ', 'ο', 'π', 'ρ', 'ς', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalGreekBold =
- [
- '𝚨', '𝚩', '𝚪', '𝚫', '𝚬', '𝚭', '𝚮', '𝚯', '𝚰', '𝚱', '𝚲', '𝚳', '𝚴',
- '𝚵', '𝚶', '𝚷', '𝚸', '𝚺', '𝚻', '𝚼', '𝚽', '𝚾', '𝚿', '𝛀'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallGreekBold =
- [
- '𝛂', '𝛃', '𝛄', '𝛅', '𝛆', '𝛇', '𝛈', '𝛉', '𝛊', '𝛋', '𝛌', '𝛍', '𝛎',
- '𝛏', '𝛐', '𝛑', '𝛒', '𝛓', '𝛔', '𝛕', '𝛖', '𝛗', '𝛘', '𝛙', '𝛚'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalGreekItalic =
- [
- '𝛢', '𝛣', '𝛤', '𝛥', '𝛦', '𝛧', '𝛨', '𝛩', '𝛪', '𝛫', '𝛬', '𝛭', '𝛮',
- '𝛯', '𝛰', '𝛱', '𝛲', '𝛴', '𝛵', '𝛶', '𝛷', '𝛸', '𝛹', '𝛺'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallGreekItalic =
- [
- '𝛼', '𝛽', '𝛾', '𝛿', '𝜀', '𝜁', '𝜂', '𝜃', '𝜄', '𝜅', '𝜆', '𝜇', '𝜈',
- '𝜉', '𝜊', '𝜋', '𝜌', '𝜍', '𝜎', '𝜏', '𝜐', '𝜑', '𝜒', '𝜓', '𝜔'
- ];
- /**
- * @type {Array<string>}
- */
- this.capitalGreekSansSerifBold =
- [
- '𝝖', '𝝗', '𝝘', '𝝙', '𝝚', '𝝛', '𝝜', '𝝝', '𝝞', '𝝟', '𝝠', '𝝡', '𝝢',
- '𝝣', '𝝤', '𝝥', '𝝦', '𝝨', '𝝩', '𝝪', '𝝫', '𝝬', '𝝭', '𝝮'
- ];
- /**
- * @type {Array<string>}
- */
- this.smallGreekSansSerifBold =
- [
- '𝝰', '𝝱', '𝝲', '𝝳', '𝝴', '𝝵', '𝝶', '𝝷', '𝝸', '𝝹', '𝝺', '𝝻', '𝝼',
- '𝝽', '𝝾', '𝝿', '𝞀', '𝞁', '𝞂', '𝞃', '𝞄', '𝞅', '𝞆', '𝞇', '𝞈'
- ];
- /**
- * @type {Array<string>}
- */
- this.greekDoubleStruck =
- [
- 'ℼ', 'ℽ', 'ℾ', 'ℿ'
- ];
-
- // Other alphabets.
- /**
- * @type {Array<string>}
- */
- this.hebrewLetters =
- [
- 'ℵ', 'ℶ', 'ℷ', 'ℸ'
- ];
-
- //Operator symbols
- /**
- * @type {Array<string>}
- */
- this.additions =
- [
- '+', '±', '∓', '∔', '∧', '∨', '∩', '∪', '⊌', '⊓', '⊔', '⊝', '⊞',
- '⊤', '⊥', '⊺', '⊻', '⊼', '⋄', '⋎', '⋏', '⋒', '⋓', '△', '▷', '▽',
- '◁', '⩞', '⊕'
- ];
- /**
- * @type {Array<string>}
- */
- /**
- * Invisible operator for plus.
- * @type {string}
- * @private
- */
- this.invisiblePlus_ = cvox.SemanticUtil.numberToUnicode(0x2064);
- this.additions.push(this.invisiblePlus_);
- /**
- * @type {Array<string>}
- */
- this.multiplications =
- [
- '†', '‡', '∐', '∗', '∘', '∙', '≀', '⊚', '⊛', '⊠', '⊡', '⋅', '⋆', '⋇',
- '⋉', '⋊', '⋋', '⋌', '○'
- ];
- /**
- * Invisible operator for multiplication.
- * @type {string}
- * @private
- */
- this.invisibleTimes_ = cvox.SemanticUtil.numberToUnicode(0x2062);
- this.multiplications.push(this.invisibleTimes_);
- /**
- * @type {Array<string>}
- */
- this.subtractions =
- [
- '-', '⁒', '⁻', '₋', '−', '∖', '∸', '≂', '⊖', '⊟', '➖', '⨩', '⨪',
- '⨫', '⨬', '⨺', '⩁', '⩬', '﹣', '-', '‐', '‑'
- ];
- /**
- * @type {Array<string>}
- */
- this.divisions =
- [
- '/', '÷', '⁄', '∕', '⊘', '⟌', '⦼', '⨸'
- ];
- /**
- * Invisible operator for function application.
- * @type {string}
- * @private
- */
- this.functionApplication_ = cvox.SemanticUtil.numberToUnicode(0x2061);
-
- //Relation symbols
- /**
- * @type {Array<string>}
- */
- this.equalities =
- [
- '=', '~', '⁼', '₌', '∼', '∽', '≃', '≅', '≈', '≊', '≋', '≌', '≍',
- '≎', '≑', '≒', '≓', '≔', '≕', '≖', '≗', '≘', '≙', '≚', '≛', '≜',
- '≝', '≞', '≟', '≡', '≣', '⧤', '⩦', '⩮', '⩯', '⩰', '⩱', '⩲', '⩳',
- '⩴', '⩵', '⩶', '⩷', '⩸', '⋕', '⩭', '⩪', '⩫', '⩬', '﹦', '='
- ];
- /**
- * @type {Array<string>}
- */
- this.inequalities =
- [
- '<', '>', '≁', '≂', '≄', '≆', '≇', '≉', '≏', '≐', '≠', '≢', '≤',
- '≥', '≦', '≧', '≨', '≩', '≪', '≫', '≬', '≭', '≮', '≯', '≰', '≱',
- '≲', '≳', '≴', '≵', '≶', '≷', '≸', '≹', '≺', '≻', '≼', '≽', '≾',
- '≿', '⊀', '⊁', '⋖', '⋗', '⋘', '⋙', '⋚', '⋛', '⋜', '⋝', '⋞', '⋟',
- '⋠', '⋡', '⋢', '⋣', '⋤', '⋥', '⋦', '⋧', '⋨', '⋩', '⩹', '⩺', '⩻',
- '⩼', '⩽', '⩾', '⩿', '⪀', '⪁', '⪂', '⪃', '⪄', '⪅', '⪆', '⪇', '⪈',
- '⪉', '⪊', '⪋', '⪌', '⪍', '⪎', '⪏', '⪐', '⪑', '⪒', '⪓', '⪔', '⪕',
- '⪖', '⪗', '⪘', '⪙', '⪚', '⪛', '⪜', '⪝', '⪞', '⪟', '⪠', '⪡', '⪢',
- '⪣', '⪤', '⪥', '⪦', '⪧', '⪨', '⪩', '⪪', '⪫', '⪬', '⪭', '⪮', '⪯',
- '⪰', '⪱', '⪲', '⪳', '⪴', '⪵', '⪶', '⪷', '⪸', '⪹', '⪺', '⪻', '⪼',
- '⫷', '⫸', '⫹', '⫺', '⧀', '⧁', '﹤', '﹥', '<', '>'
- ];
- /**
- * @type {Array<string>}
- */
- this.relations =
- [
- // TODO (sorge): Add all the other relations.
- ];
- /**
- * @type {Array<string>}
- */
- this.arrows =
- [
- '←', '↑', '→', '↓', '↔', '↕', '↖', '↗', '↘', '↙', '↚', '↛', '↜',
- '↝', '↞', '↟', '↠', '↡', '↢', '↣', '↤', '↥', '↦', '↧', '↨', '↩',
- '↪', '↫', '↬', '↭', '↮', '↯', '↰', '↱', '↲', '↳', '↴', '↵', '↶',
- '↷', '↸', '↹', '↺', '↻', '⇄', '⇅', '⇆', '⇇', '⇈', '⇉', '⇊', '⇍',
- '⇎', '⇏', '⇐', '⇑', '⇒', '⇓', '⇔', '⇕', '⇖', '⇗', '⇘', '⇙', '⇚',
- '⇛', '⇜', '⇝', '⇞', '⇟', '⇠', '⇡', '⇢', '⇣', '⇤', '⇥', '⇦', '⇧',
- '⇨', '⇩', '⇪', '⇫', '⇬', '⇭', '⇮', '⇯', '⇰', '⇱', '⇲', '⇳', '⇴',
- '⇵', '⇶', '⇷', '⇸', '⇹', '⇺', '⇻', '⇼', '⇽', '⇾', '⇿', '⌁', '⌃',
- '⌄', '⌤', '⎋', '➔', '➘', '➙', '➚', '➛', '➜', '➝', '➞', '➟', '➠',
- '➡', '➢', '➣', '➤', '➥', '➦', '➧', '➨', '➩', '➪', '➫', '➬', '➭',
- '➮', '➯', '➱', '➲', '➳', '➴', '➵', '➶', '➷', '➸', '➹', '➺', '➻',
- '➼', '➽', '➾', '⟰', '⟱', '⟲', '⟳', '⟴', '⟵', '⟶', '⟷', '⟸', '⟹',
- '⟺', '⟻', '⟼', '⟽', '⟾', '⟿', '⤀', '⤁', '⤂', '⤃', '⤄', '⤅', '⤆',
- '⤇', '⤈', '⤉', '⤊', '⤋', '⤌', '⤍', '⤎', '⤏', '⤐', '⤑', '⤒', '⤓',
- '⤔', '⤕', '⤖', '⤗', '⤘', '⤙', '⤚', '⤛', '⤜', '⤝', '⤞', '⤟', '⤠',
- '⤡', '⤢', '⤣', '⤤', '⤥', '⤦', '⤧', '⤨', '⤩', '⤪', '⤭', '⤮', '⤯',
- '⤰', '⤱', '⤲', '⤳', '⤴', '⤵', '⤶', '⤷', '⤸', '⤹', '⤺', '⤻', '⤼',
- '⤽', '⤾', '⤿', '⥀', '⥁', '⥂', '⥃', '⥄', '⥅', '⥆', '⥇', '⥈', '⥉',
- '⥰', '⥱', '⥲', '⥳', '⥴', '⥵', '⥶', '⥷', '⥸', '⥹', '⥺', '⥻', '⦳',
- '⦴', '⦽', '⧪', '⧬', '⧭', '⨗', '⬀', '⬁', '⬂', '⬃', '⬄', '⬅', '⬆',
- '⬇', '⬈', '⬉', '⬊', '⬋', '⬌', '⬍', '⬎', '⬏', '⬐', '⬑', '⬰', '⬱',
- '⬲', '⬳', '⬴', '⬵', '⬶', '⬷', '⬸', '⬹', '⬺', '⬻', '⬼', '⬽', '⬾',
- '⬿', '⭀', '⭁', '⭂', '⭃', '⭄', '⭅', '⭆', '⭇', '⭈', '⭉', '⭊', '⭋',
- '⭌', '←', '↑', '→', '↓',
- // Harpoons
- '↼', '↽', '↾', '↿', '⇀', '⇁', '⇂', '⇃', '⇋', '⇌', '⥊', '⥋', '⥌',
- '⥍', '⥎', '⥏', '⥐', '⥑', '⥒', '⥓', '⥔', '⥕', '⥖', '⥗', '⥘', '⥙',
- '⥚', '⥛', '⥜', '⥝', '⥞', '⥟', '⥠', '⥡', '⥢', '⥣', '⥤', '⥥', '⥦',
- '⥧', '⥨', '⥩', '⥪', '⥫', '⥬', '⥭', '⥮', '⥯', '⥼', '⥽', '⥾', '⥿'
- ];
-
- //Big operation symbols
- /**
- * @type {Array<string>}
- */
- this.sumOps =
- [
- '⅀', // double struck
- '∏', '∐', '∑', '⋀', '⋁', '⋂', '⋃', '⨀', '⨁', '⨂', '⨃', '⨄', '⨅',
- '⨆', '⨇', '⨈', '⨉', '⨊', '⨋', '⫼', '⫿'
- ];
- /**
- * @type {Array<string>}
- */
- this.intOps =
- [
- '∫', '∬', '∭', '∮', '∯', '∰', '∱', '∲', '∳', '⨌', '⨍', '⨎', '⨏',
- '⨐', '⨑', '⨒', '⨓', '⨔', '⨕', '⨖', '⨗', '⨘', '⨙', '⨚', '⨛', '⨜'
- ];
- /**
- * @type {Array<string>}
- */
- this.prefixOps =
- // TODO (sorge) Insert nabla, differential operators etc.
- [
- '∀', '∃'
- ];
- /**
- * @type {Array<string>}
- */
- this.operatorBits =
- // TODO (sorge) What to do if single glyphs of big ops occur on their own.
- [
- '⌠', '⌡', '⎶', '⎪', '⎮', '⎯', '⎲', '⎳', '⎷'
- ];
-
- // Accents.
- // TODO (sorge) Add accented characters.
-
- // Numbers.
- // Digits.
- /**
- * @type {Array<string>}
- */
- this.digitsNormal =
- [
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsFullWidth =
- [
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsBold =
- [
- '𝟎', '𝟏', '𝟐', '𝟑', '𝟒', '𝟓', '𝟔', '𝟕', '𝟖', '𝟗'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsDoubleStruck =
- [
- '𝟘', '𝟙', '𝟚', '𝟛', '𝟜', '𝟝', '𝟞', '𝟟', '𝟠', '𝟡'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsSansSerif =
- [
- '𝟢', '𝟣', '𝟤', '𝟥', '𝟦', '𝟧', '𝟨', '𝟩', '𝟪', '𝟫'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsSansSerifBold =
- [
- '𝟬', '𝟭', '𝟮', '𝟯', '𝟰', '𝟱', '𝟲', '𝟳', '𝟴', '𝟵'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsMonospace =
- [
- '𝟶', '𝟷', '𝟸', '𝟹', '𝟺', '𝟻', '𝟼', '𝟽', '𝟾', '𝟿'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsSuperscript =
- [
- '²', '³', '¹', '⁰', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'
- ];
- /**
- * @type {Array<string>}
- */
- this.digitsSubscript =
- [
- '₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'
- ];
- /**
- * @type {Array<string>}
- */
- this.fractions =
- [
- '¼', '½', '¾', '⅐', '⅑', '⅒', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙',
- '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '↉'
- ];
- /**
- * @type {Array<string>}
- */
- this.enclosedNumbers =
- // Encircled numbers.
- [
- '①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬',
- '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳', '⓪', '⓫', '⓬', '⓭', '⓮', '⓯',
- '⓰', '⓱', '⓲', '⓳', '⓴', '⓵', '⓶', '⓷', '⓸', '⓹', '⓺', '⓻', '⓼',
- '⓽', '⓾', '⓿', '❶', '❷', '❸', '❹', '❺', '❻', '❼', '❽', '❾', '❿',
- '➀', '➁', '➂', '➃', '➄', '➅', '➆', '➇', '➈', '➉', '➊', '➋', '➌',
- '➍', '➎', '➏', '➐', '➑', '➒', '➓', '㉈', '㉉', '㉊', '㉋', '㉌',
- '㉍', '㉎', '㉏', '㉑', '㉒', '㉓', '㉔', '㉕', '㉖', '㉗', '㉘',
- '㉙', '㉚', '㉛', '㉜', '㉝', '㉞', '㉟', '㊱', '㊲', '㊳', '㊴',
- '㊵', '㊶', '㊷', '㊸', '㊹', '㊺', '㊻', '㊼', '㊽', '㊾', '㊿'];
- /**
- * @type {Array<string>}
- */
- this.fencedNumbers =
- // Numbers in Parenthesis.
- [
- '⑴', '⑵', '⑶', '⑷', '⑸', '⑹', '⑺', '⑻', '⑼', '⑽', '⑾', '⑿', '⒀',
- '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇'
- ];
- /**
- * @type {Array<string>}
- */
- this.punctuatedNumbers =
- // Numbers with other punctuation.
- ['⒈', '⒉', '⒊', '⒋', '⒌', '⒍', '⒎', '⒏', '⒐', '⒑', '⒒', '⒓', '⒔',
- '⒕', '⒖', '⒗', '⒘', '⒙', '⒚', '⒛', // full stop.
- '🄀', '🄁', '🄂', '🄃', '🄄', '🄅', '🄆', '🄇', '🄈', '🄉', '🄊' // comma.
- ];
- /** Array of all single digits.
- * @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>}
- */
- this.numbers = this.fractions.concat(
- this.digitsSuperscript, this.digitsSubscript,
- this.enclosedNumbers, this.fencedNumbers, this.punctuatedNumbers);
- /** Array of all number symbols.
- * @type {Array<string>}
- */
- this.allNumbers = this.digits.concat(this.numbers);
-
- // Functions.
- /**
- * @type {Array<string>}
- */
- this.trigonometricFunctions =
- [
- 'cos', 'cot', 'csc', 'sec', 'sin', 'tan', 'arccos', 'arccot',
- 'arccsc', 'arcsec', 'arcsin', 'arctan'
- ];
- /**
- * @type {Array<string>}
- */
- this.hyperbolicFunctions =
- [
- 'cosh', 'coth', 'csch', 'sech', 'sinh', 'tanh',
- 'arcosh', 'arcoth', 'arcsch', 'arsech', 'arsinh', 'artanh',
- 'arccosh', 'arccoth', 'arccsch', 'arcsech', 'arcsinh', 'arctanh'
- ];
- /**
- * @type {Array<string>}
- */
- this.algebraicFunctions =
- [
- 'deg', 'det', 'dim', 'hom', 'ker', 'Tr', 'tr'
- ];
- /**
- * @type {Array<string>}
- */
- this.elementaryFunctions =
- [
- 'log', 'ln', 'lg', 'exp', 'expt', 'gcd', 'gcd', 'arg', 'im', 're', 'Pr'
- ];
- /** All predefined prefix functions.
- * @type {Array<string>}
- */
- this.prefixFunctions = this.trigonometricFunctions.concat(
- this.hyperbolicFunctions,
- this.algebraicFunctions,
- this.elementaryFunctions
- );
- /** Limit functions are handled separately as they can have lower (and upper)
- * limiting expressions.
- * @type {Array<string>}
- */
- this.limitFunctions =
- [
- 'inf', 'lim', 'liminf', 'limsup', 'max', 'min', 'sup', 'injlim',
- 'projlim'
- ];
- /**
- * @type {Array<string>}
- */
- this.infixFunctions =
- [
- 'mod', 'rem'
- ];
- /**
- * Default assignments of semantic attributes.
- * @type {Array<{set: Array<string>,
- * role: cvox.SemanticAttr.Role,
- * type: cvox.SemanticAttr.Type,
- * font: cvox.SemanticAttr.Font}>} The semantic meaning of the symbol.
- * @private
- */
- this.symbolSetToSemantic_ = [
- // Punctuation
- {set: this.generalPunctuations,
- type: cvox.SemanticAttr.Type.PUNCTUATION,
- role: cvox.SemanticAttr.Role.UNKNOWN
- },
- {set: this.ellipses,
- type: cvox.SemanticAttr.Type.PUNCTUATION,
- role: cvox.SemanticAttr.Role.ELLIPSIS
- },
- {set: this.fullStops,
- type: cvox.SemanticAttr.Type.PUNCTUATION,
- role: cvox.SemanticAttr.Role.FULLSTOP
- },
- {set: this.dashes,
- type: cvox.SemanticAttr.Type.PUNCTUATION,
- role: cvox.SemanticAttr.Role.DASH
- },
- {set: this.primes,
- type: cvox.SemanticAttr.Type.PUNCTUATION,
- role: cvox.SemanticAttr.Role.PRIME
- },
- // Fences
- {set: this.leftFences,
- type: cvox.SemanticAttr.Type.FENCE,
- role: cvox.SemanticAttr.Role.OPEN
- },
- {set: this.rightFences,
- type: cvox.SemanticAttr.Type.FENCE,
- role: cvox.SemanticAttr.Role.CLOSE
- },
- {set: this.topFences,
- type: cvox.SemanticAttr.Type.FENCE,
- role: cvox.SemanticAttr.Role.TOP
- },
- {set: this.bottomFences,
- type: cvox.SemanticAttr.Type.FENCE,
- role: cvox.SemanticAttr.Role.BOTTOM
- },
- {set: this.neutralFences,
- type: cvox.SemanticAttr.Type.FENCE,
- role: cvox.SemanticAttr.Role.NEUTRAL
- },
- // Single characters.
- // Latin alphabets.
- {set: this.smallLatin,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.capitalLatin,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.smallLatinFullWidth,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.capitalLatinFullWidth,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.smallLatinBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.BOLD
- },
- {set: this.capitalLatinBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.BOLD
- },
- {set: this.smallLatinItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.ITALIC
- },
- {set: this.capitalLatinItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.ITALIC
- },
- {set: this.smallLatinScript,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SCRIPT
- },
- {set: this.capitalLatinScript,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SCRIPT
- },
- {set: this.smallLatinBoldScript,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.BOLDSCRIPT
- },
- {set: this.capitalLatinBoldScript,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.BOLDSCRIPT
- },
- {set: this.smallLatinFraktur,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.FRAKTUR
- },
- {set: this.capitalLatinFraktur,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.FRAKTUR
- },
- {set: this.smallLatinDoubleStruck,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.DOUBLESTRUCK
- },
- {set: this.capitalLatinDoubleStruck,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.DOUBLESTRUCK
- },
- {set: this.smallLatinBoldFraktur,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.BOLDFRAKTUR
- },
- {set: this.capitalLatinBoldFraktur,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.BOLDFRAKTUR
- },
- {set: this.smallLatinSansSerif,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIF
- },
- {set: this.capitalLatinSansSerif,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIF
- },
- {set: this.smallLatinSansSerifBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIFBOLD
- },
- {set: this.capitalLatinSansSerifBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIFBOLD
- },
- {set: this.smallLatinSansSerifItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIFITALIC
- },
- {set: this.capitalLatinSansSerifItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIFITALIC
- },
- {set: this.smallLatinMonospace,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.MONOSPACE
- },
- {set: this.capitalLatinMonospace,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.MONOSPACE
- },
- {set: this.latinDoubleStruckItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.LATINLETTER,
- font: cvox.SemanticAttr.Font.DOUBLESTRUCKITALIC
- },
- // Greek alphabets.
- {set: this.smallGreek,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.capitalGreek,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.smallGreekBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.BOLD
- },
- {set: this.capitalGreekBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.BOLD
- },
- {set: this.smallGreekItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.ITALIC
- },
- {set: this.capitalGreekItalic,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.ITALIC
- },
- {set: this.smallGreekSansSerifBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIFBOLD
- },
- {set: this.capitalGreekSansSerifBold,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.SANSSERIFBOLD
- },
- {set: this.greekDoubleStruck,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.GREEKLETTER,
- font: cvox.SemanticAttr.Font.DOUBLESTRUCK
- },
- // Other alphabets.
- {set: this.hebrewLetters,
- type: cvox.SemanticAttr.Type.IDENTIFIER,
- role: cvox.SemanticAttr.Role.OTHERLETTER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- // Numbers.
- {set: this.digitsNormal,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.digitsFullWidth,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.NORMAL
- },
- {set: this.digitsBold,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.BOLD
- },
- {set: this.digitsDoubleStruck,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.DOUBLESTRUCK
- },
- {set: this.digitsSansSerif,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.SANSSERIF
- },
- {set: this.digitsSansSerifBold,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.SANSSERIFBOLD
- },
- {set: this.digitsMonospace,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER,
- font: cvox.SemanticAttr.Font.MONOSPACE
- },
- {set: this.numbers,
- type: cvox.SemanticAttr.Type.NUMBER,
- role: cvox.SemanticAttr.Role.INTEGER
- },
- // Operators.
- {set: this.additions,
- type: cvox.SemanticAttr.Type.OPERATOR,
- role: cvox.SemanticAttr.Role.ADDITION
- },
- {set: this.multiplications,
- type: cvox.SemanticAttr.Type.OPERATOR,
- role: cvox.SemanticAttr.Role.MULTIPLICATION
- },
- {set: this.subtractions,
- type: cvox.SemanticAttr.Type.OPERATOR,
- role: cvox.SemanticAttr.Role.SUBTRACTION
- },
- {set: this.divisions,
- type: cvox.SemanticAttr.Type.OPERATOR,
- role: cvox.SemanticAttr.Role.DIVISION
- },
- {set: this.prefixOps,
- type: cvox.SemanticAttr.Type.PREFIXOP,
- role: cvox.SemanticAttr.Role.PREFIXFUNC
- },
- // Relations
- {set: this.equalities,
- type: cvox.SemanticAttr.Type.RELATION,
- role: cvox.SemanticAttr.Role.EQUALITY
- },
- {set: this.inequalities,
- type: cvox.SemanticAttr.Type.RELATION,
- role: cvox.SemanticAttr.Role.INEQUALITY
- },
- {set: this.relations,
- type: cvox.SemanticAttr.Type.RELATION,
- role: cvox.SemanticAttr.Role.UNKNOWN
- },
- {set: this.arrows,
- type: cvox.SemanticAttr.Type.RELATION,
- role: cvox.SemanticAttr.Role.ARROW
- },
- // Large operators
- {set: this.sumOps,
- type: cvox.SemanticAttr.Type.LARGEOP,
- role: cvox.SemanticAttr.Role.SUM},
- {set: this.intOps,
- type: cvox.SemanticAttr.Type.LARGEOP,
- role: cvox.SemanticAttr.Role.INTEGRAL},
- // Functions
- {set: this.limitFunctions,
- type: cvox.SemanticAttr.Type.FUNCTION,
- role: cvox.SemanticAttr.Role.LIMFUNC},
- {set: this.prefixFunctions,
- type: cvox.SemanticAttr.Type.FUNCTION,
- role: cvox.SemanticAttr.Role.PREFIXFUNC},
- {set: this.infixFunctions,
- type: cvox.SemanticAttr.Type.OPERATOR,
- role: cvox.SemanticAttr.Role.MULTIPLICATION
- }
- // TODO (sorge) Add some of the remaining elements.
- ];
-};
-goog.addSingletonGetter(cvox.SemanticAttr);
-
-
-/**
- * Union type of semantic attributes.
- * @typedef {cvox.SemanticAttr.Type|cvox.SemanticAttr.Role}
- */
-cvox.SemanticAttr.Attr;
-
-
-/**
- * Mapping for types of elements.
- * @enum {string}
- */
-cvox.SemanticAttr.Type = {
- // Leafs.
- // Punctuation like comma, dot, ellipses.
- PUNCTUATION: 'punctuation',
- // Fence symbol.
- FENCE: 'fence',
- // One or several digits, plus some punctuation.
- NUMBER: 'number',
- // Single or multiple letters.
- IDENTIFIER: 'identifier',
- // Regular text in a math expression.
- TEXT: 'text',
- // e.g. +, *.
- OPERATOR: 'operator',
- // Relation symbol, e.g. equals.
- RELATION: 'relation',
- // e.g. Sum, product, integral.
- LARGEOP: 'largeop',
- // Some named function.
- FUNCTION: 'function',
-
- // Branches.
- // Compound Symbols.
- ACCENT: 'accent',
- FENCED: 'fenced',
- FRACTION: 'fraction',
- PUNCTUATED: 'punctuated',
-
- // Relations.
- // Relation sequence of a single relation.
- RELSEQ: 'relseq',
- // Relation sequence containing at least two different relations.
- MULTIREL: 'multirel',
- // Operations.
- INFIXOP: 'infixop',
- PREFIXOP: 'prefixop',
- POSTFIXOP: 'postfixop',
-
- // Function and Bigop Application.
- APPL: 'appl',
- INTEGRAL: 'integral',
- BIGOP: 'bigop',
-
- SQRT: 'sqrt',
- ROOT: 'root',
- // These are bigops or functions with limits.
- LIMUPPER: 'limupper',
- LIMLOWER: 'limlower',
- LIMBOTH: 'limboth',
- SUBSCRIPT: 'subscript',
- SUPERSCRIPT: 'superscript',
- UNDERSCORE: 'underscore',
- OVERSCORE: 'overscore',
-
- // Tables and their elements.
- TABLE: 'table',
- MULTILINE: 'multiline',
- MATRIX: 'matrix',
- VECTOR: 'vector',
- CASES: 'cases',
- ROW: 'row',
- // Lines are effectively single cell rows.
- LINE: 'line',
- CELL: 'cell',
-
- // General.
- UNKNOWN: 'unknown',
- EMPTY: 'empty'
-};
-
-
-/**
- * Mapping for roles of nodes.
- * Roles are more specific than types.
- * @enum {string}
- */
-cvox.SemanticAttr.Role = {
- // Punctuation.
- ELLIPSIS: 'ellipsis',
- FULLSTOP: 'fullstop',
- DASH: 'dash',
- PRIME: 'prime', // Superscript.
- VBAR: 'vbar', // A vertical bar.
- OPENFENCE: 'openfence',
- CLOSEFENCE: 'closefence',
- APPLICATION: 'application', // Function Application.
-
- // Fences.
- OPEN: 'open',
- CLOSE: 'close',
- TOP: 'top',
- BOTTOM: 'bottom',
- NEUTRAL: 'neutral',
-
- // Letters.
- LATINLETTER: 'latinletter',
- GREEKLETTER: 'greekletter',
- OTHERLETTER: 'otherletter',
-
- // Numbers.
- INTEGER: 'integer',
- FLOAT: 'float',
- OTHERNUMBER: 'othernumber',
-
- // Accents.
- MULTIACCENT: 'multiaccent',
- OVERACCENT: 'overaccent',
- UNDERACCENT: 'underaccent',
-
- // Fenced.
- LEFTRIGHT: 'leftright',
- ABOVEBELOW: 'abovebelow',
-
- // Punctuated elements.
- SEQUENCE: 'sequence',
- ENDPUNCT: 'endpunct',
- STARTPUNCT: 'startpunct',
-
- // Operators.
- NEGATIVE: 'negative',
- NEGATION: 'negation',
- MULTIOP: 'multiop',
-
- // Functions.
- LIMFUNC: 'limit function',
- INFIXFUNC: 'infix function',
- PREFIXFUNC: 'prefix function',
- POSTFIXFUNC: 'postfix function',
-
- // Large operators.
- SUM: 'sum',
- INTEGRAL: 'integral',
-
- // Binary operations.
- ADDITION: 'addition',
- MULTIPLICATION: 'multiplication',
- DIVISION: 'division',
- SUBTRACTION: 'subtraction',
- IMPLICIT: 'implicit',
-
- // Relations.
- EQUALITY: 'equality',
- INEQUALITY: 'inequality',
- ELEMENT: 'element',
- BINREL: 'binrel',
- ARROW: 'arrow',
-
- // Roles of rows, lines, cells.
- // They mirror the different types for tables.
- MULTILINE: 'multiline',
- MATRIX: 'matrix',
- VECTOR: 'vector',
- CASES: 'cases',
- TABLE: 'table',
-
- // General
- UNKNOWN: 'unknown'
-};
-
-
-/**
- * Mapping for font annotations. (Taken from MathML2 section 3.2.2, with the
- * exception of double-struck-italic.)
- * @enum {string}
- */
-cvox.SemanticAttr.Font = {
- BOLD: 'bold',
- BOLDFRAKTUR: 'bold-fraktur',
- BOLDITALIC: 'bold-italic',
- BOLDSCRIPT: 'bold-script',
- DOUBLESTRUCK: 'double-struck',
- DOUBLESTRUCKITALIC: 'double-struck-italic',
- FRAKTUR: 'fraktur',
- ITALIC: 'italic',
- MONOSPACE: 'monospace',
- NORMAL: 'normal',
- SCRIPT: 'script',
- SANSSERIF: 'sans-serif',
- SANSSERIFITALIC: 'sans-serif-italic',
- SANSSERIFBOLD: 'sans-serif-bold',
- SANSSERIFBOLDITALIC: 'sans-serif-bold-italic',
- UNKNOWN: 'unknown'
-};
-
-
-/**
- * Lookup the semantic type of a symbol.
- * @param {string} symbol The symbol to which we want to determine the type.
- * @return {cvox.SemanticAttr.Type} The semantic type of the symbol.
- */
-cvox.SemanticAttr.prototype.lookupType = function(symbol) {
- return cvox.SemanticAttr.Type.UNKNOWN;
-};
-
-
-/**
- * Lookup the semantic role of a symbol.
- * @param {string} symbol The symbol to which we want to determine the role.
- * @return {cvox.SemanticAttr.Role} The semantic role of the symbol.
- */
-cvox.SemanticAttr.prototype.lookupRole = function(symbol) {
- return cvox.SemanticAttr.Role.UNKNOWN;
-};
-
-
-/**
- * Lookup the semantic meaning of a symbol in terms of type and role.
- * @param {string} symbol The symbol to which we want to determine the meaning.
- * @return {{role: cvox.SemanticAttr.Role,
- * type: cvox.SemanticAttr.Type}} The semantic meaning of the symbol.
- */
-cvox.SemanticAttr.lookupMeaning = function(symbol) {
- return cvox.SemanticAttr.getInstance().lookupMeaning_(symbol);
-};
-
-
-/**
- * String representation of the invisible times unicode character.
- * @return {string} The invisible times character.
- */
-cvox.SemanticAttr.invisibleTimes = function() {
- return cvox.SemanticAttr.getInstance().invisibleTimes_;
-};
-
-
-/**
- * String representation of the invisible comma unicode character.
- * @return {string} The invisible comma character.
- */
-cvox.SemanticAttr.invisibleComma = function() {
- return cvox.SemanticAttr.getInstance().invisibleComma_;
-};
-
-
-/**
- * String representation of the function application character.
- * @return {string} The invisible function application character.
- */
-cvox.SemanticAttr.functionApplication = function() {
- return cvox.SemanticAttr.getInstance().functionApplication_;
-};
-
-
-/**
- * Decide when two fences match. Currently we match any right to left
- * or bottom to top fence and neutral to neutral.
- * @param {cvox.SemanticAttr.Role} open Opening fence.
- * @param {cvox.SemanticAttr.Role} close Closing fence.
- * @return {boolean} True if the fences are matching.
- */
-cvox.SemanticAttr.isMatchingFenceRole = function(open, close) {
- return (open == cvox.SemanticAttr.Role.OPEN &&
- close == cvox.SemanticAttr.Role.CLOSE) ||
- (open == cvox.SemanticAttr.Role.NEUTRAL &&
- close == cvox.SemanticAttr.Role.NEUTRAL) ||
- (open == cvox.SemanticAttr.Role.TOP &&
- close == cvox.SemanticAttr.Role.BOTTOM);
-};
-
-
-/**
- * Decide when opening and closing fences match. For neutral fences they have to
- * be the same.
- * @param {string} open Opening fence.
- * @param {string} close Closing fence.
- * @return {boolean} True if the fences are matching.
- */
-cvox.SemanticAttr.isMatchingFence = function(open, close) {
- return cvox.SemanticAttr.getInstance().isMatchingFence_(open, close);
-};
-
-
-/**
- * Determines if a fence is an opening fence.
- * @param {cvox.SemanticAttr.Role} fence Opening fence.
- * @return {boolean} True if the fence is open or neutral.
- */
-cvox.SemanticAttr.isOpeningFence = function(fence) {
- return (fence == cvox.SemanticAttr.Role.OPEN ||
- fence == cvox.SemanticAttr.Role.NEUTRAL);
-};
-
-
-/**
- * Determines if a fence is a closing fence.
- * @param {cvox.SemanticAttr.Role} fence Closing fence.
- * @return {boolean} True if the fence is close or neutral.
- */
-cvox.SemanticAttr.isClosingFence = function(fence) {
- return (fence == cvox.SemanticAttr.Role.CLOSE ||
- fence == cvox.SemanticAttr.Role.NEUTRAL);
-};
-
-
-// TODO (sorge) Make this depended on position in the alphabets.
-/**
- * Check if a character is a small 'd' in some font.
- * @param {!string} chr The character string.
- * @return {boolean} True if the character is indeed a single small d.
- */
-cvox.SemanticAttr.isCharacterD = function(chr) {
- var Ds = ['d', 'ⅆ', 'd', '𝐝', '𝑑', '𝒹', '𝓭', '𝔡',
- '𝕕', '𝖉', '𝖽', '𝗱', '𝘥', '𝚍'];
- return Ds.indexOf(chr) != -1;
-};
-
-
-/**
- * Decide when opening and closing fences match. For neutral fences they have to
- * be the same.
- * @param {!string} open Opening fence.
- * @param {!string} close Closing fence.
- * @return {boolean} True if the fences are matching.
- * @private
- */
-cvox.SemanticAttr.prototype.isMatchingFence_ = function(open, close) {
- if (this.neutralFences.indexOf(open) != -1) {
- return open == close;
- }
- return this.openClosePairs[open] == close ||
- this.topBottomPairs[open] == close;
-};
-
-
-/**
- * Lookup the semantic meaning of a symbol in terms of type and role.
- * @param {!string} symbol The symbol to which we want to determine the meaning.
- * @return {{role: cvox.SemanticAttr.Role,
- * type: cvox.SemanticAttr.Type,
- * font: cvox.SemanticAttr.Font}} The semantic meaning of the symbol.
- * @private
- */
-cvox.SemanticAttr.prototype.lookupMeaning_ = function(symbol) {
- for (var i = 0, set; set = this.symbolSetToSemantic_[i]; i++) {
- if (set.set.indexOf(symbol) != -1) {
- return {role: set.role || cvox.SemanticAttr.Role.UNKNOWN,
- type: set.type || cvox.SemanticAttr.Type.UNKNOWN,
- font: set.font || cvox.SemanticAttr.Font.UNKNOWN
- };
- }
- }
- return {role: cvox.SemanticAttr.Role.UNKNOWN,
- type: cvox.SemanticAttr.Type.UNKNOWN,
- font: cvox.SemanticAttr.Font.UNKNOWN
- };
-};
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
deleted file mode 100644
index 991ae3244ca..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js
+++ /dev/null
@@ -1,1939 +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 semantic tree for MathML expressions.
- *
- * This file contains functionality to compute a semantic interpretation from a
- * given MathML expression. This is a very heuristic approach that assumes a
- * fairly simple default semantic which is suitable for K-12 and simple UG
- * mathematics.
- *
- */
-
-goog.provide('cvox.SemanticTree');
-goog.provide('cvox.SemanticTree.Node');
-
-goog.require('cvox.DomUtil');
-goog.require('cvox.SemanticAttr');
-goog.require('cvox.SemanticUtil');
-
-
-/**
- * Create an initial semantic tree.
- * @param {!Element} mml The original MathML node.
- * @constructor
- */
-cvox.SemanticTree = function(mml) {
- /** ID counter.
- * @type {number}
- * @private
- */
- this.idCounter_ = 0;
-
- /** Original MathML tree.
- * @type {Node}
- */
- this.mathml = mml;
-
- /** @type {cvox.SemanticTree.Node} */
- this.root = this.parseMathml_(mml);
-};
-
-
-/**
- * @param {number} id Node id.
- * @constructor
- */
-cvox.SemanticTree.Node = function(id) {
- /** @type {number} */
- this.id = id;
-
- /** @type {Array<Element>} */
- this.mathml = [];
-
- /** @type {cvox.SemanticTree.Node} */
- this.parent = null;
-
- /** @type {cvox.SemanticAttr.Type} */
- this.type = cvox.SemanticAttr.Type.UNKNOWN;
-
- /** @type {cvox.SemanticAttr.Role} */
- this.role = cvox.SemanticAttr.Role.UNKNOWN;
-
- /** @type {cvox.SemanticAttr.Font} */
- this.font = cvox.SemanticAttr.Font.UNKNOWN;
-
- /** @type {!Array<cvox.SemanticTree.Node>} */
- this.childNodes = [];
-
- /** @type {string} */
- this.textContent = '';
-
- /** 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>}
- */
- this.contentNodes = [];
-};
-
-
-/**
- * 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
- * predicate holds.
- */
-cvox.SemanticTree.Node.prototype.querySelectorAll = function(pred) {
- var result = [];
- for (var i = 0, child; child = this.childNodes[i]; i++) {
- result = result.concat(child.querySelectorAll(pred));
- }
- if (pred(this)) {
- result.unshift(this);
- }
- return result;
-};
-
-
- /**
- * Returns an XML representation of the tree.
- * @param {boolean=} brief If set attributes are omitted.
- * @return {Node} The XML representation of the tree.
- */
- cvox.SemanticTree.prototype.xml = function(brief) {
- var dp = new DOMParser();
- var xml = dp.parseFromString('<stree></stree>', 'text/xml');
-
- var xmlRoot = this.root.xml(xml, brief);
- xml.childNodes[0].appendChild(xmlRoot);
-
- return xml.childNodes[0];
- };
-
-
- /**
- * An XML tree representation of the current node.
- * @param {Document} xml The XML document.
- * @param {boolean=} brief If set attributes are omitted.
- * @return {Node} The XML representation of the node.
- */
- cvox.SemanticTree.Node.prototype.xml = function(xml, brief) {
- /**
- * 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.
- * @return {Node} An XML representation of the node list.
- */
- var xmlNodeList = function(tag, nodes) {
- var xmlNodes = nodes.map(function(x) {return x.xml(xml, brief);});
- var tagNode = xml.createElement(tag);
- for (var i = 0, child; child = xmlNodes[i]; i++) {
- tagNode.appendChild(child);
- }
- return tagNode;
- };
- var node = xml.createElement(this.type);
- if (!brief) {
- this.xmlAttributes_(node);
- }
- node.textContent = this.textContent;
- if (this.contentNodes.length > 0) {
- node.appendChild(xmlNodeList('content', this.contentNodes));
- }
- if (this.childNodes.length > 0) {
- node.appendChild(xmlNodeList('children', this.childNodes));
- }
- return node;
- };
-
-
-/**
- * Serializes the XML representation of the tree.
- * @param {boolean=} brief If set attributes are omitted.
- * @return {string} Serialized string.
- */
-cvox.SemanticTree.prototype.toString = function(brief) {
- var xmls = new XMLSerializer();
- return xmls.serializeToString(this.xml(brief));
-};
-
-
-/**
- * Pretty print the XML representation of the tree.
- * @param {boolean=} brief If set attributes are omitted.
- * @return {string} The formatted string.
- */
-cvox.SemanticTree.prototype.formatXml = function(brief) {
- var xml = this.toString(brief);
- return cvox.SemanticTree.formatXml(xml);
-};
-
-
-/**
- * Pretty prints an XML representation.
- * @param {string} xml The serialised XML string.
- * @return {string} The formatted string.
- */
-cvox.SemanticTree.formatXml = function(xml) {
- var reg = /(>)(<)(\/*)/g;
- xml = xml.replace(reg, '$1\r\n$2$3');
- reg = /(>)(.+)(<c)/g;
- xml = xml.replace(reg, '$1\r\n$2\r\n$3');
- var formatted = '';
- var padding = '';
- xml.split('\r\n')
- .forEach(function(node) {
- if (node.match(/.+<\/\w[^>]*>$/)) {
- // Node with content.
- formatted += padding + node + '\r\n';
- } else if (node.match(/^<\/\w/)) {
- if (padding) {
- // Closing tag
- padding = padding.slice(2);
- formatted += padding + node + '\r\n';
- }
- } else if (node.match(/^<\w[^>]*[^\/]>.*$/)) {
- // Opening tag
- formatted += padding + node + '\r\n';
- padding += ' ';
- } else {
- // Empty tag
- formatted += padding + node + '\r\n';
- }
- });
- return formatted;
-};
-
-
-/**
- * Serializes the XML representation of a node.
- * @param {boolean=} brief If attributes are to be omitted.
- * @return {string} Serialized string.
- */
-cvox.SemanticTree.Node.prototype.toString = function(brief) {
- var xmls = new XMLSerializer();
- var dp = new DOMParser();
- var xml = dp.parseFromString('', 'text/xml');
- return xmls.serializeToString(this.xml(xml, brief));
-};
-
-
-/**
- * Adds attributes to the XML representation of the current node.
- * @param {Node} node The XML node.
- * @private
- */
-cvox.SemanticTree.Node.prototype.xmlAttributes_ = function(node) {
- node.setAttribute('role', this.role);
- if (this.font != cvox.SemanticAttr.Font.UNKNOWN) {
- node.setAttribute('font', this.font);
- }
- node.setAttribute('id', this.id);
-};
-
-
-/** Creates a new node object.
- * @return {cvox.SemanticTree.Node} The newly created node.
- * @private
- */
-cvox.SemanticTree.prototype.createNode_ = function() {
- return new cvox.SemanticTree.Node(this.idCounter_++);
-};
-
-
-/**
- * Replaces a node in the tree. Updates the root node if necessary.
- * @param {!cvox.SemanticTree.Node} oldNode The node to be replaced.
- * @param {!cvox.SemanticTree.Node} newNode The new node.
- * @private
- */
-cvox.SemanticTree.prototype.replaceNode_ = function(oldNode, newNode) {
- var parent = oldNode.parent;
- if (!parent) {
- this.root = newNode;
- return;
- }
- parent.replaceChild_(oldNode, newNode);
-};
-
-
-/**
- * Updates the content of the node thereby possibly changing type and role.
- * @param {string} content The new content string.
- * @private
- */
-cvox.SemanticTree.Node.prototype.updateContent_ = function(content) {
- // Remove superfluous whitespace!
- content = content.trim();
- if (this.textContent == content) {
- return;
- }
- var meaning = cvox.SemanticAttr.lookupMeaning(content);
- this.textContent = content;
- this.role = meaning.role;
- this.type = meaning.type;
- this.font = meaning.font;
-};
-
-
-/**
- * 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.
- * @private
- */
-cvox.SemanticTree.Node.prototype.addMathmlNodes_ = function(mmlNodes) {
- for (var i = 0, mml; mml = mmlNodes[i]; i++) {
- if (this.mathml.indexOf(mml) == -1) {
- this.mathml.push(mml);
- }
- }
-};
-
-
-/**
- * Removes MathML nodes from the node's store of MathML nodes.
- * @param {Array<Node>} mmlNodes List of MathML nodes.
- * @private
- */
-cvox.SemanticTree.Node.prototype.removeMathmlNodes_ = function(mmlNodes) {
- var mmlList = this.mathml;
- for (var i = 0, mml; mml = mmlNodes[i]; i++) {
- var index = mmlList.indexOf(mml);
- if (index != -1) {
- mmlList.splice(index, 1);
- }
- }
- this.mathml = mmlList;
-};
-
-
-/**
- * Appends a child to the node.
- * @param {cvox.SemanticTree.Node} child The new child.
- * @private
- */
-cvox.SemanticTree.Node.prototype.appendChild_ = function(child) {
- this.childNodes.push(child);
- this.addMathmlNodes_(child.mathml);
- child.parent = this;
-};
-
-
-/**
- * Replaces a child node of the node.
- * @param {!cvox.SemanticTree.Node} oldNode The node to be replaced.
- * @param {!cvox.SemanticTree.Node} newNode The new node.
- * @private
- */
-cvox.SemanticTree.Node.prototype.replaceChild_ = function(oldNode, newNode) {
- var index = this.childNodes.indexOf(oldNode);
- if (index == -1) {
- return;
- }
- newNode.parent = this;
- oldNode.parent = null;
- this.childNodes[index] = newNode;
- // To not mess up the order of MathML elements more than necessary, we only
- // remove and add difference lists. The hope is that we might end up with
- // little change.
- var removeMathml = oldNode.mathml.filter(
- function(x) {return newNode.mathml.indexOf(x) == -1;});
- var addMathml = newNode.mathml.filter(
- function(x) {return oldNode.mathml.indexOf(x) == -1;});
- this.removeMathmlNodes_(removeMathml);
- this.addMathmlNodes_(addMathml);
-};
-
-
-/**
- * Appends a content node to the node.
- * @param {cvox.SemanticTree.Node} node The new content node.
- * @private
- */
-cvox.SemanticTree.Node.prototype.appendContentNode_ = function(node) {
- if (node) {
- this.contentNodes.push(node);
- this.addMathmlNodes_(node.mathml);
- node.parent = this;
- }
-};
-
-
-/**
- * Removes a content node from the node.
- * @param {cvox.SemanticTree.Node} node The content node to be removed.
- * @private
- */
-cvox.SemanticTree.Node.prototype.removeContentNode_ = function(node) {
- if (node) {
- var index = this.contentNodes.indexOf(node);
- if (index != -1) {
- this.contentNodes.splice(index, 1);
- }
- }
-};
-
-
-/**
- * This is the main function that creates the semantic tree by recursively
- * parsing the initial MathML tree and bottom up assembling the tree.
- * @param {!Element} mml The MathML tree.
- * @return {!cvox.SemanticTree.Node} The root of the new tree.
- * @private
- */
-cvox.SemanticTree.prototype.parseMathml_ = function(mml) {
- var children = cvox.DomUtil.toArray(mml.children);
- switch (cvox.SemanticUtil.tagName(mml)) {
- case 'MATH':
- case 'MROW':
- case 'MPADDED':
- case 'MSTYLE':
- children = cvox.SemanticUtil.purgeNodes(children);
- // Single child node, i.e. the row is meaningless.
- if (children.length == 1) {
- return this.parseMathml_(/** @type {!Element} */(children[0]));
- }
- // Case of a 'meaningful' row, even if they are empty.
- return this.processRow_(this.parseMathmlChildren_(children));
- break;
- case 'MFRAC':
- var newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.FRACTION,
- [this.parseMathml_(children[0]), this.parseMathml_(children[1])],
- []);
- newNode.role = cvox.SemanticAttr.Role.DIVISION;
- return newNode;
- break;
- case 'MSUB':
- case 'MSUP':
- case 'MSUBSUP':
- case 'MOVER':
- case 'MUNDER':
- case 'MUNDEROVER':
- return this.makeLimitNode_(cvox.SemanticUtil.tagName(mml),
- this.parseMathmlChildren_(children));
- break;
- case 'MROOT':
- return this.makeBranchNode_(
- cvox.SemanticAttr.Type.ROOT,
- [this.parseMathml_(children[0]), this.parseMathml_(children[1])],
- []);
- break;
- case 'MSQRT':
- children = this.parseMathmlChildren_(
- cvox.SemanticUtil.purgeNodes(children));
- return this.makeBranchNode_(
- cvox.SemanticAttr.Type.SQRT, [this.processRow_(children)], []);
- break;
- case 'MTABLE':
- newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.TABLE,
- this.parseMathmlChildren_(children), []);
- if (cvox.SemanticTree.tableIsMultiline_(newNode)) {
- this.tableToMultiline_(newNode);
- }
- return newNode;
- break;
- case 'MTR':
- newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.ROW,
- this.parseMathmlChildren_(children), []);
- newNode.role = cvox.SemanticAttr.Role.TABLE;
- return newNode;
- break;
- case 'MTD':
- children = this.parseMathmlChildren_(
- cvox.SemanticUtil.purgeNodes(children));
- newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.CELL, [this.processRow_(children)], []);
- newNode.role = cvox.SemanticAttr.Role.TABLE;
- return newNode;
- break;
- case 'MTEXT':
- var leaf = this.makeLeafNode_(mml);
- leaf.type = cvox.SemanticAttr.Type.TEXT;
- return leaf;
- break;
- // TODO (sorge) Role and font of multi-character and digits unicode strings.
- // TODO (sorge) Reclassify wrongly tagged numbers or identifiers.
- // TODO (sorge) Put this all in a single clean reclassification method.
- case 'MI':
- leaf = this.makeLeafNode_(mml);
- if (leaf.type == cvox.SemanticAttr.Type.UNKNOWN) {
- leaf.type = cvox.SemanticAttr.Type.IDENTIFIER;
- }
- return leaf;
- break;
- case 'MN':
- leaf = this.makeLeafNode_(mml);
- if (leaf.type == cvox.SemanticAttr.Type.UNKNOWN) {
- leaf.type = cvox.SemanticAttr.Type.NUMBER;
- }
- return leaf;
- break;
- case 'MO':
- leaf = this.makeLeafNode_(mml);
- if (leaf.type == cvox.SemanticAttr.Type.UNKNOWN) {
- leaf.type = cvox.SemanticAttr.Type.OPERATOR;
- }
- return leaf;
- break;
- // TODO (sorge) Do something useful with error and phantom symbols.
- default:
- // Ordinarilly at this point we should not get any other tag.
- return this.makeUnprocessed_(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
- * node.
- * @private
- */
-cvox.SemanticTree.prototype.parseMathmlChildren_ = function(mmls) {
- var result = [];
- for (var i = 0, mml; mml = mmls[i]; i++) {
- result.push(this.parseMathml_(mml));
- }
- return result;
-};
-
-/**
- * Create a node that is to be processed at a later point in time.
- * @param {Node} mml The MathML tree.
- * @return {!cvox.SemanticTree.Node} The new node.
- * @private
- */
-cvox.SemanticTree.prototype.makeUnprocessed_ = function(mml) {
- var node = this.createNode_();
- node.mathml = [mml];
- return node;
-};
-
-
-/**
- * Create an empty leaf node.
- * @return {!cvox.SemanticTree.Node} The new node.
- * @private
- */
-cvox.SemanticTree.prototype.makeEmptyNode_ = function() {
- var node = this.createNode_();
- node.type = cvox.SemanticAttr.Type.EMPTY;
- return node;
-};
-
-
-/**
- * Create a leaf node.
- * @param {Node} mml The MathML tree.
- * @return {!cvox.SemanticTree.Node} The new node.
- * @private
- */
-cvox.SemanticTree.prototype.makeLeafNode_ = function(mml) {
- var node = this.createNode_();
- node.mathml = [mml];
- node.updateContent_(mml.textContent);
- node.font = mml.getAttribute('mathvariant') || node.font;
- return node;
-};
-
-
-/**
- * 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 {string=} content Content string if there is any.
- * @return {!cvox.SemanticTree.Node} The new node.
- * @private
- */
-cvox.SemanticTree.prototype.makeBranchNode_ = function(
- type, children, contentNodes, content) {
- var node = this.createNode_();
- if (content) {
- node.updateContent_(content);
- }
- node.type = type;
- node.childNodes = children;
- node.contentNodes = contentNodes;
- children.concat(contentNodes)
- .forEach(
- function(x) {
- x.parent = node;
- node.addMathmlNodes_(x.mathml);
- });
- return node;
-};
-
-
-/**
- * Create a branching node for an implicit operation, currently assumed to
- * be of multiplicative type.
- * @param {!Array<!cvox.SemanticTree.Node>} nodes The operands.
- * @return {!cvox.SemanticTree.Node} The new branch node.
- * @private
- */
-cvox.SemanticTree.prototype.makeImplicitNode_ = function(nodes) {
- if (nodes.length == 1) {
- return nodes[0];
- }
- var operator = this.createNode_();
- // For now we assume this is a multiplication using invisible times.
- operator.updateContent_(cvox.SemanticAttr.invisibleTimes());
- var newNode = this.makeInfixNode_(nodes, operator);
- newNode.role = cvox.SemanticAttr.Role.IMPLICIT;
- return newNode;
-};
-
-
-/**
- * Create a branching node for an infix operation.
- * @param {!Array<cvox.SemanticTree.Node>} children The operands.
- * @param {!cvox.SemanticTree.Node} opNode The operator.
- * @return {!cvox.SemanticTree.Node} The new branch node.
- * @private
- */
-cvox.SemanticTree.prototype.makeInfixNode_ = function(children, opNode) {
- return this.makeBranchNode_(
- cvox.SemanticAttr.Type.INFIXOP, children, [opNode], opNode.textContent);
-};
-
-
-/**
- * Creates a node of the specified type by collapsing the given node list into
- * 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 {!cvox.SemanticAttr.Type} type The new type of the node.
- * @return {!cvox.SemanticTree.Node} The new branch node.
- * @private
- */
-cvox.SemanticTree.prototype.makeConcatNode_ = function(inner, nodeList, type) {
- if (nodeList.length == 0) {
- return inner;
- }
- var content = nodeList.map(function(x) {return x.textContent;}).join(' ');
- var newNode = this.makeBranchNode_(type, [inner], nodeList, content);
- if (nodeList.length > 0) {
- newNode.role = cvox.SemanticAttr.Role.MULTIOP;
- }
- return newNode;
-};
-
-
-/**
- * Wraps a node into prefix operators.
- * 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
- * from the outermost to the innermost.
- * @return {!cvox.SemanticTree.Node} The new branch node.
- * @private
- */
-cvox.SemanticTree.prototype.makePrefixNode_ = function(node, prefixes) {
- var negatives = cvox.SemanticTree.partitionNodes_(
- prefixes, cvox.SemanticTree.attrPred_('role', 'SUBTRACTION'));
- var newNode = this.makeConcatNode_(
- node, negatives.comp.pop(), cvox.SemanticAttr.Type.PREFIXOP);
-
- while (negatives.rel.length > 0) {
- newNode = this.makeConcatNode_(
- newNode, [negatives.rel.pop()], cvox.SemanticAttr.Type.PREFIXOP);
- newNode.role = cvox.SemanticAttr.Role.NEGATIVE;
- newNode = this.makeConcatNode_(
- newNode, negatives.comp.pop(), cvox.SemanticAttr.Type.PREFIXOP);
- }
- return newNode;
-};
-
-
-/**
- * Wraps a node into postfix operators.
- * 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
- * innermost to outermost.
- * @return {!cvox.SemanticTree.Node} The new branch node.
- * @private
- */
-cvox.SemanticTree.prototype.makePostfixNode_ = function(node, postfixes) {
- return this.makeConcatNode_(
- node, postfixes, cvox.SemanticAttr.Type.POSTFIXOP);
-};
-
-
-// TODO (sorge) Separate out interspersed text before the relations in row
-// heuristic otherwise we get them as implicit operations!
-// Currently we handle that later in the rules, which is rather messy.
-/**
- * Processes a list of nodes, combining expressions by delimiters, tables,
- * punctuation sequences, function/big operator/integral applications to
- * generate a syntax tree with relation and operator precedence.
- *
- * 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.
- * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
- * @private
- */
-cvox.SemanticTree.prototype.processRow_ = function(nodes) {
- if (nodes.length == 0) {
- return this.makeEmptyNode_();
- }
- nodes = this.getFencesInRow_(nodes);
- nodes = this.processTablesInRow_(nodes);
- nodes = this.getPunctuationInRow_(nodes);
- nodes = this.getFunctionsInRow_(nodes);
- return this.processRelationsInRow_(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.
- * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
- * @private
- */
-cvox.SemanticTree.prototype.processRelationsInRow_ = function(nodes) {
- var partition = cvox.SemanticTree.partitionNodes_(
- nodes, cvox.SemanticTree.attrPred_('type', 'RELATION'));
- var firstRel = partition.rel[0];
-
- if (!firstRel) {
- return this.processOperationsInRow_(nodes);
- }
- if (nodes.length == 1) {
- return nodes[0];
- }
- var children = partition.comp.map(
- goog.bind(this.processOperationsInRow_, this));
- if (partition.rel.every(
- function(x) {return x.textContent == firstRel.textContent;})) {
- return this.makeBranchNode_(
- cvox.SemanticAttr.Type.RELSEQ, children, partition.rel,
- firstRel.textContent);
- }
- return this.makeBranchNode_(
- cvox.SemanticAttr.Type.MULTIREL, children, partition.rel);
-};
-
-
-/**
- * Constructs a syntax tree with operator precedence from a list nodes.
- * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
- * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
- * @private
- */
-cvox.SemanticTree.prototype.processOperationsInRow_ = function(nodes) {
- if (nodes.length == 0) {
- return this.makeEmptyNode_();
- }
- if (nodes.length == 1) {
- return nodes[0];
- }
-
- var prefix = [];
- while (nodes.length > 0 &&
- nodes[0].type == cvox.SemanticAttr.Type.OPERATOR) {
- prefix.push(nodes.shift());
- }
- // Pathological case: only operators in row.
- if (nodes.length == 0) {
- return this.makePrefixNode_(prefix.pop(), prefix);
- }
- if (nodes.length == 1) {
- return this.makePrefixNode_(nodes[0], prefix);
- }
-
- var split = cvox.SemanticTree.sliceNodes_(
- nodes, cvox.SemanticTree.attrPred_('type', 'OPERATOR'));
- // At this point, we know that split.head is not empty!
- var node = this.makePrefixNode_(
- this.makeImplicitNode_(
- /** @type {!Array<!cvox.SemanticTree.Node>} */ (split.head)),
- prefix);
- if (!split.div) {
- return node;
- }
- return this.makeOperationsTree_(split.tail, node, split.div);
-};
-
-
-/**
- * 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 {!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
- * become prefix operation (or postfix in case they come after last operand).
- * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
- * @private
- */
-cvox.SemanticTree.prototype.makeOperationsTree_ = function(
- nodes, root, lastop, prefixes) {
- prefixes = prefixes || [];
-
- if (nodes.length == 0) {
- // Left over prefixes become postfixes.
- prefixes.unshift(lastop);
- if (root.type == cvox.SemanticAttr.Type.INFIXOP) {
- // We assume prefixes bind stronger than postfixes.
- var node = this.makePostfixNode_(
- // Here we know that the childNodes are not empty!
- /** @type {!cvox.SemanticTree.Node} */ (root.childNodes.pop()),
- prefixes);
- root.appendChild_(node);
- return root;
- }
- return this.makePostfixNode_(root, prefixes);
- }
-
- var split = cvox.SemanticTree.sliceNodes_(
- nodes, cvox.SemanticTree.attrPred_('type', 'OPERATOR'));
-
- if (split.head.length == 0) {
- prefixes.push(split.div);
- return this.makeOperationsTree_(split.tail, root, lastop, prefixes);
- }
-
- var node = this.makePrefixNode_(
- this.makeImplicitNode_(split.head), prefixes);
- var newNode = this.appendOperand_(root, lastop, node);
- if (!split.div) {
- return newNode;
- }
-
- return this.makeOperationsTree_(split.tail, newNode, split.div, []);
-};
-
-// TODO (sorge) The following four functions could be combined into
-// a single one. Currently it is clearer the way it is, though.
-/**
- * Appends an operand at the right place in an operator tree.
- * @param {!cvox.SemanticTree.Node} root The operator tree.
- * @param {!cvox.SemanticTree.Node} op The operator node.
- * @param {!cvox.SemanticTree.Node} node The node to be added.
- * @return {!cvox.SemanticTree.Node} The modified root node.
- * @private
- */
-cvox.SemanticTree.prototype.appendOperand_ = function(root, op, node) {
- // In general our operator tree will have the form that additions and
- // subtractions are stacked, while multiplications are subordinate.
- if (root.type != cvox.SemanticAttr.Type.INFIXOP) {
- return this.makeInfixNode_([root, node], op);
- }
- if (this.appendExistingOperator_(root, op, node)) {
- return root;
- }
- return op.role == cvox.SemanticAttr.Role.MULTIPLICATION ?
- this.appendMultiplicativeOp_(root, op, node) :
- this.appendAdditiveOp_(root, op, node);
-};
-
-
-/**
- * Appends a multiplicative operator and operand.
- * @param {!cvox.SemanticTree.Node} root The root node.
- * @param {!cvox.SemanticTree.Node} op The operator node.
- * @param {!cvox.SemanticTree.Node} node The operand node to be added.
- * @return {!cvox.SemanticTree.Node} The modified root node.
- * @private
- */
-cvox.SemanticTree.prototype.appendMultiplicativeOp_ = function(root, op, node) {
- var lastRoot = root;
- var lastChild = root.childNodes[root.childNodes.length - 1];
- while (lastChild && lastChild.type == cvox.SemanticAttr.Type.INFIXOP) {
- lastRoot = lastChild;
- lastChild = lastRoot.childNodes[root.childNodes.length - 1];
- }
- var newNode = this.makeInfixNode_([lastRoot.childNodes.pop(), node], op);
- lastRoot.appendChild_(newNode);
- return root;
-};
-
-
-/**
- * Appends an additive/substractive operator and operand.
- * @param {!cvox.SemanticTree.Node} root The old root node.
- * @param {!cvox.SemanticTree.Node} op The operator node.
- * @param {!cvox.SemanticTree.Node} node The operand node to be added.
- * @return {!cvox.SemanticTree.Node} The new root node.
- * @private
- */
-cvox.SemanticTree.prototype.appendAdditiveOp_ = function(root, op, node) {
- return this.makeInfixNode_([root, node], op);
-};
-
-
-/**
- * Adds an operand to an operator node if it is the continuation of an existing
- * operation.
- * @param {!cvox.SemanticTree.Node} root The root node.
- * @param {!cvox.SemanticTree.Node} op The operator node.
- * @param {!cvox.SemanticTree.Node} node The operand node to be added.
- * @return {boolean} True if operator was successfully appended.
- * @private
- */
-cvox.SemanticTree.prototype.appendExistingOperator_ = function(root, op, node) {
- if (!root || root.type != cvox.SemanticAttr.Type.INFIXOP) {
- return false;
- }
- if (root.textContent == op.textContent) {
- root.appendContentNode_(op);
- root.appendChild_(node);
- return true;
- }
- this.appendExistingOperator_(
- // Again, if this is an INFIXOP node, we know it has a child!
- /** @type {!cvox.SemanticTree.Node} */
- (root.childNodes[root.childNodes.length - 1]),
- op, node);
-};
-
-
-// TODO (sorge) The following procedure needs a rational reconstruction. It
-// contains a number of similar cases which should be combined.
-/**
- * Combines delimited expressions in a list of nodes.
- *
- * The basic idea of the heuristic is as follows:
- * 1. Opening and closing delimiters are matched regardless of the actual shape
- * of the fence. These are turned into fenced nodes.
- * 2. Neutral fences are matched only with neutral fences of the same shape.
- * 3. For a collection of unmatched neutral fences we try to get a maximum
- * 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.
- * @private
- */
-cvox.SemanticTree.prototype.getFencesInRow_ = function(nodes) {
- var partition = cvox.SemanticTree.partitionNodes_(
- nodes, cvox.SemanticTree.attrPred_('type', 'FENCE'));
- var felem = partition.comp.shift();
- return this.processFences_(partition.rel, partition.comp, [], [felem]);
-};
-
-
-/**
- * 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
- * between fences.
- * @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
- * expressions processed.
- * @private
- */
-cvox.SemanticTree.prototype.processFences_ = function(
- fences, content, openStack, contentStack) {
- // Base case 1: Everything is used up.
- if (fences.length == 0 && openStack.length == 0) {
- return contentStack[0];
- }
- var openPred = cvox.SemanticTree.attrPred_('role', 'OPEN');
- // Base case 2: Only open and neutral fences are left on the stack.
- if (fences.length == 0) {
- // Basic idea:
- // - make punctuation nodes from open fences
- // - combine as many neutral fences as possible, if the are not separated by
- // open fences.
- // The idea is to allow for things like case statements etc. and not bury
- // them inside a neutral fenced expression.
- //
- // 0. We process the list from left to right. Hence the first element on the
- // content stack are actually left most elements in the expression.
- // 1. Slice at open fence.
- // 2. On tail optimize for neutral fences.
- // 3. Repeat until fence stack is exhausted.
- // Push rightmost elements onto the result.
- var result = contentStack.shift();
- while (openStack.length > 0) {
- if (openPred(openStack[0])) {
- var firstOpen = openStack.shift();
- cvox.SemanticTree.fenceToPunct_(firstOpen);
- result.push(firstOpen);
- } else {
- var split = cvox.SemanticTree.sliceNodes_(openStack, openPred);
- var cutLength = split.head.length - 1;
- var innerNodes = this.processNeutralFences_(
- split.head, contentStack.slice(0, cutLength));
- contentStack = contentStack.slice(cutLength);
- //var rightContent = contentStack.shift();
- result.push.apply(result, innerNodes);
- //result.push.apply(result, rightContent);
- if (split.div) {
- split.tail.unshift(split.div);
- }
- openStack = split.tail;
- }
- result.push.apply(result, contentStack.shift());
- }
- return result;
- }
- var lastOpen = openStack[openStack.length - 1];
- var firstRole = fences[0].role;
- // General opening case.
- // Either we have an open fence.
- if (firstRole == cvox.SemanticAttr.Role.OPEN ||
- // Or we have a neutral fence that does not have a counter part.
- (firstRole == cvox.SemanticAttr.Role.NEUTRAL &&
- (!lastOpen ||
- fences[0].textContent != lastOpen.textContent))) {
- openStack.push(fences.shift());
- contentStack.push(content.shift());
- return this.processFences_(fences, content, openStack, contentStack);
- }
- // General closing case.
- if (lastOpen && (
- // Closing fence for some opening fence.
- (firstRole == cvox.SemanticAttr.Role.CLOSE &&
- lastOpen.role == cvox.SemanticAttr.Role.OPEN) ||
- // Netural fence with exact counter part.
- (firstRole == cvox.SemanticAttr.Role.NEUTRAL &&
- fences[0].textContent == lastOpen.textContent))) {
- var fenced = this.makeHorizontalFencedNode_(
- openStack.pop(), fences.shift(), contentStack.pop());
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return this.processFences_(fences, content, openStack, contentStack);
- }
- // Closing with a neutral fence on the stack.
- if (lastOpen && firstRole == cvox.SemanticAttr.Role.CLOSE &&
- lastOpen.role == cvox.SemanticAttr.Role.NEUTRAL &&
- openStack.some(openPred)) {
- // Steps of the algorithm:
- // 1. Split list at right most opening bracket.
- // 2. Cut content list at corresponding length.
- // 3. Optimise the neutral fences.
- // 4. Make fenced node.
- //
- // Careful, this reverses openStack!
- var split = cvox.SemanticTree.sliceNodes_(openStack, openPred, true);
- // We know that
- // (a) div & tail exist,
- // (b) all are combined in this step into a single fenced node,
- // (c) head is the new openStack,
- // (d) the new contentStack is remainder of contentStack + new fenced node +
- // shift of content.
- var rightContent = contentStack.pop();
- var cutLength = contentStack.length - split.tail.length + 1;
- var innerNodes = this.processNeutralFences_(
- split.tail, contentStack.slice(cutLength));
- contentStack = contentStack.slice(0, cutLength);
- var fenced = this.makeHorizontalFencedNode_(
- split.div, fences.shift(),
- contentStack.pop().concat(innerNodes, rightContent));
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return this.processFences_(fences, content, split.head, contentStack);
- }
- // Final Case: A singular closing fence.
- // We turn the fence into a punctuation.
- var fenced = fences.shift();
- cvox.SemanticTree.fenceToPunct_(fenced);
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return this.processFences_(fences, content, openStack, contentStack);
-};
-
-
-// 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
- * content. Observe that |content| = |fences| - 1
- * @return {!Array<cvox.SemanticTree.Node>} List of node with fully fenced
- * nodes.
- * @private
- */
-cvox.SemanticTree.prototype.processNeutralFences_ = function(fences, content) {
- if (fences.length == 0) {
- return fences;
- }
- if (fences.length == 1) {
- cvox.SemanticTree.fenceToPunct_(fences[0]);
- return fences;
- }
- var firstFence = fences.shift();
- var split = cvox.SemanticTree.sliceNodes_(
- fences, function(x) {return x.textContent == firstFence.textContent;});
- if (!split.div) {
- cvox.SemanticTree.fenceToPunct_(firstFence);
- var restContent = content.shift();
- restContent.unshift(firstFence);
- return restContent.concat(this.processNeutralFences_(fences, content));
- }
- var newContent = this.combineFencedContent_(
- firstFence, split.div, split.head, content);
- if (split.tail.length > 0) {
- var leftContent = newContent.shift();
- var result = this.processNeutralFences_(split.tail, newContent);
- return leftContent.concat(result);
- }
- return newContent[0];
-};
-
-
-/**
- * Combines nodes framed by two matching fences using the given content.
- * Example: leftFence: [, rightFence: ], midFences: |, |
- * content: c1, c2, c3, c4, ... cn
- * 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
- * fences.
- * @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
- * where the first is the fully fenced node wrt. the given left and right
- * fence.
- * @private
- */
-cvox.SemanticTree.prototype.combineFencedContent_ = function(
- leftFence, rightFence, midFences, content) {
-
- if (midFences.length == 0) {
- var fenced = this.makeHorizontalFencedNode_(
- leftFence, rightFence, content.shift());
- content.unshift(fenced);
- return content;
- }
-
- var leftContent = content.shift();
- var cutLength = midFences.length - 1;
- var midContent = content.slice(0, cutLength);
- content = content.slice(cutLength);
- var rightContent = content.shift();
- var innerNodes = this.processNeutralFences_(midFences, midContent);
- leftContent.push.apply(leftContent, innerNodes);
- leftContent.push.apply(leftContent, rightContent);
- var fenced = this.makeHorizontalFencedNode_(
- leftFence, rightFence, leftContent);
- if (content.length > 0) {
- content[0].unshift(fenced);
- } else {
- content = [[fenced]];
- }
- return content;
- };
-
-
-/**
- * Rewrite fences into punctuation. This is done with any "leftover" fence.
- * @param {cvox.SemanticTree.Node} fence Fence.
- * @private
- */
-cvox.SemanticTree.fenceToPunct_ = function(fence) {
- fence.type = cvox.SemanticAttr.Type.PUNCTUATION;
- switch (fence.role) {
- case cvox.SemanticAttr.Role.NEUTRAL:
- fence.role = cvox.SemanticAttr.Role.VBAR;
- break;
- case cvox.SemanticAttr.Role.OPEN:
- fence.role = cvox.SemanticAttr.Role.OPENFENCE;
- break;
- case cvox.SemanticAttr.Role.CLOSE:
- fence.role = cvox.SemanticAttr.Role.CLOSEFENCE;
- break;
- }
-};
-
-
-/**
- * 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
- * between the fences.
- * @return {!cvox.SemanticTree.Node} The new node.
- * @private
- */
-cvox.SemanticTree.prototype.makeHorizontalFencedNode_ = function(
- ofence, cfence, content) {
- var childNode = this.processRow_(content);
- var newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.FENCED, [childNode], [ofence, cfence]);
- if (ofence.role == cvox.SemanticAttr.Role.OPEN) {
- newNode.role = cvox.SemanticAttr.Role.LEFTRIGHT;
- } else {
- newNode.role = ofence.role;
- }
- return newNode;
-};
-
-
-/**
- * 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.
- * @private
- */
-cvox.SemanticTree.prototype.getPunctuationInRow_ = function(nodes) {
- // For now we just make a punctuation node with a particular role. This is
- // similar to an mrow. The only exception are ellipses, which we assume to be
- // in lieu of identifiers.
- // In addition we keep the single punctuation nodes as content.
- var partition = cvox.SemanticTree.partitionNodes_(
- nodes, function(x) {
- return cvox.SemanticTree.attrPred_('type', 'PUNCTUATION')(x) &&
- !cvox.SemanticTree.attrPred_('role', 'ELLIPSIS')(x);});
- if (partition.rel.length == 0) {
- return nodes;
- }
- var newNodes = [];
- var firstComp = partition.comp.shift();
- if (firstComp.length > 0) {
- newNodes.push(this.processRow_(firstComp));
- }
- var relCounter = 0;
- while (partition.comp.length > 0) {
- newNodes.push(partition.rel[relCounter++]);
- firstComp = partition.comp.shift();
- if (firstComp.length > 0) {
- newNodes.push(this.processRow_(firstComp));
- }
- }
- return [this.makePunctuatedNode_(newNodes, partition.rel)];
-};
-
-
-/**
- * Create a punctuated node.
- * @param {!Array<!cvox.SemanticTree.Node>} nodes List of all nodes separated
- * by punctuations.
- * @param {!Array<!cvox.SemanticTree.Node>} punctuations List of all separating
- * punctations. Observe that punctations is a subset of nodes.
- * @return {!cvox.SemanticTree.Node}
- * @private
- */
-cvox.SemanticTree.prototype.makePunctuatedNode_ = function(
- nodes, punctuations) {
- var newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.PUNCTUATED, nodes, punctuations);
-
- if (punctuations.length == 1 &&
- nodes[0].type == cvox.SemanticAttr.Type.PUNCTUATION) {
- newNode.role = cvox.SemanticAttr.Role.STARTPUNCT;
- } else if (punctuations.length == 1 &&
- nodes[nodes.length - 1].type == cvox.SemanticAttr.Type.PUNCTUATION) {
- newNode.role = cvox.SemanticAttr.Role.ENDPUNCT;
- } else {
- newNode.role = cvox.SemanticAttr.Role.SEQUENCE;
- }
- return newNode;
-};
-
-
-/**
- * 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
- * original node.
- * @return {!cvox.SemanticTree.Node} The newly created limit node.
- * @private
- */
-cvox.SemanticTree.prototype.makeLimitNode_ = function(mmlTag, children) {
- var center = children[0];
- var isFunction = cvox.SemanticTree.attrPred_('type', 'FUNCTION')(center);
- // TODO (sorge) Put this into a single function.
- var isLimit = cvox.SemanticTree.attrPred_('type', 'LARGEOP')(center) ||
- cvox.SemanticTree.attrPred_('type', 'LIMBOTH')(center) ||
- cvox.SemanticTree.attrPred_('type', 'LIMLOWER')(center) ||
- cvox.SemanticTree.attrPred_('type', 'LIMUPPER')(center) ||
- (isFunction && cvox.SemanticTree.attrPred_('role', 'LIMFUNC')(center));
- var type = cvox.SemanticAttr.Type.UNKNOWN;
- // TODO (sorge) Make use of the difference in information on sub vs under etc.
- if (isLimit) {
- switch (mmlTag) {
- case 'MSUB':
- case 'MUNDER':
- type = cvox.SemanticAttr.Type.LIMLOWER;
- break;
- case 'MSUP':
- case 'MOVER':
- type = cvox.SemanticAttr.Type.LIMUPPER;
- break;
- case 'MSUBSUP':
- case 'MUNDEROVER':
- type = cvox.SemanticAttr.Type.LIMBOTH;
- break;
- }
- } else {
- switch (mmlTag) {
- case 'MSUB':
- type = cvox.SemanticAttr.Type.SUBSCRIPT;
- break;
- case 'MSUP':
- type = cvox.SemanticAttr.Type.SUPERSCRIPT;
- break;
- case 'MSUBSUP':
- var innerNode = this.makeBranchNode_(cvox.SemanticAttr.Type.SUBSCRIPT,
- [center, children[1]], []);
- innerNode.role = center.role;
- children = [innerNode, children[2]];
- type = cvox.SemanticAttr.Type.SUPERSCRIPT;
- break;
- case 'MOVER':
- type = cvox.SemanticAttr.Type.OVERSCORE;
- break;
- case 'MUNDER':
- type = cvox.SemanticAttr.Type.UNDERSCORE;
- break;
- case 'MUNDEROVER':
- default:
- var innerNode = this.makeBranchNode_(cvox.SemanticAttr.Type.UNDERSCORE,
- [center, children[1]], []);
- innerNode.role = center.role;
- children = [innerNode, children[2]];
- type = cvox.SemanticAttr.Type.OVERSCORE;
- break;
- }
- }
- var newNode = this.makeBranchNode_(type, children, []);
- newNode.role = center.role;
- return newNode;
-};
-
-
-/**
- * Recursive method to accumulate function expressions.
- *
- * The idea is to process functions in a row from left to right combining them
- * with there arguments. Thereby we take the notion of a function rather broadly
- * as a functional expressions that consists of a prefix and some arguments.
- * In particular we distinguish four types of functional expressions:
- * - integral: Integral expression.
- * - bigop: A big operator expression like a sum.
- * - prefix: A well defined prefix function such as sin, cos or a limit
- * functions like lim, max.
- * - simple: An expression consisting of letters that are potentially a function
- * 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
- * nodes.
- * @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) {
- result = result || [];
- // Base case.
- if (restNodes.length == 0) {
- return result;
- }
- var firstNode = /** @type {!cvox.SemanticTree.Node} */ (restNodes.shift());
- var heuristic = cvox.SemanticTree.classifyFunction_(firstNode, restNodes);
- // First node is not a function node.
- if (!heuristic) {
- result.push(firstNode);
- return this.getFunctionsInRow_(restNodes, result);
- }
- // Combine functions in the rest of the row.
- var processedRest = this.getFunctionsInRow_(restNodes, []);
- var newRest = this.getFunctionArgs_(firstNode, processedRest, heuristic);
- return result.concat(newRest);
-};
-
-
-/**
- * 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
- * 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.
- * @private
- */
-cvox.SemanticTree.classifyFunction_ = function(funcNode, restNodes) {
- // We do not allow double function application. This is not lambda calculus!
- if (funcNode.type == cvox.SemanticAttr.Type.APPL ||
- funcNode.type == cvox.SemanticAttr.Type.BIGOP ||
- funcNode.type == cvox.SemanticAttr.Type.INTEGRAL) {
- return '';
- }
- // Find and remove explicit function applications.
- // We now treat funcNode as a prefix function, regardless of what its actual
- // content is.
- if (restNodes[0] &&
- restNodes[0].textContent == cvox.SemanticAttr.functionApplication()) {
- // Remove explicit function application. This is destructive on the
- // underlying list.
- restNodes.shift();
- cvox.SemanticTree.propagatePrefixFunc_(funcNode);
- return 'prefix';
- }
- switch (funcNode.role) {
- case cvox.SemanticAttr.Role.INTEGRAL:
- return 'integral';
- break;
- case cvox.SemanticAttr.Role.SUM:
- return 'bigop';
- break;
- case cvox.SemanticAttr.Role.PREFIXFUNC:
- case cvox.SemanticAttr.Role.LIMFUNC:
- return 'prefix';
- break;
- default:
- if (funcNode.type == cvox.SemanticAttr.Type.IDENTIFIER) {
- return 'simple';
- }
- }
- return '';
-};
-
-
-/**
- * Propagates a prefix function role in a node.
- * @param {cvox.SemanticTree.Node} funcNode The node whose role is to be
- * rewritten.
- * @private
- */
-cvox.SemanticTree.propagatePrefixFunc_ = function(funcNode) {
- if (funcNode) {
- funcNode.role = cvox.SemanticAttr.Role.PREFIXFUNC;
- cvox.SemanticTree.propagatePrefixFunc_(funcNode.childNodes[0]);
- }
-};
-
-
-/**
- * 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
- * arguments from.
- * @param {string} heuristic The heuristic to follow.
- * @return {!Array<!cvox.SemanticTree.Node>} The function and the remainder of
- * the rest list.
- * @private
- */
-cvox.SemanticTree.prototype.getFunctionArgs_ = function(func, rest, heuristic) {
- switch (heuristic) {
- case 'integral':
- var components = this.getIntegralArgs_(rest);
- var integrand = this.processRow_(components.integrand);
- var funcNode = this.makeIntegralNode_(func, integrand, components.intvar);
- components.rest.unshift(funcNode);
- return components.rest;
- break;
- case 'prefix':
- if (rest[0] && rest[0].type == cvox.SemanticAttr.Type.FENCED) {
- funcNode = this.makeFunctionNode_(
- func, /** @type {!cvox.SemanticTree.Node} */ (rest.shift()));
- rest.unshift(funcNode);
- return rest;
- }
- case 'bigop':
- var partition = cvox.SemanticTree.sliceNodes_(
- rest, cvox.SemanticTree.prefixFunctionBoundary_);
- var arg = this.processRow_(partition.head);
- if (heuristic == 'prefix') {
- funcNode = this.makeFunctionNode_(func, arg);
- } else {
- funcNode = this.makeBigOpNode_(func, arg);
- }
- if (partition.div) {
- partition.tail.unshift(partition.div);
- }
- partition.tail.unshift(funcNode);
- return partition.tail;
- break;
- case 'simple':
- if (rest.length == 0) {
- return [func];
- }
- var firstArg = rest[0];
- if (firstArg.type == cvox.SemanticAttr.Type.FENCED &&
- firstArg.role != cvox.SemanticAttr.Role.NEUTRAL &&
- this.simpleFunctionHeuristic_(firstArg)) {
- funcNode = this.makeFunctionNode_(
- func, /** @type {!cvox.SemanticTree.Node} */ (rest.shift()));
- rest.unshift(funcNode);
- return rest;
- }
- rest.unshift(func);
- return rest;
- break;
- }
-};
-
-
-/**
- * Tail recursive function to obtain integral arguments.
- * @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>,
- * intvar: cvox.SemanticTree.Node,
- * rest: !Array<cvox.SemanticTree.Node>}}
- * Result split into integrand, integral variable and the remaining
- * elements.
- * @private
- */
-cvox.SemanticTree.prototype.getIntegralArgs_ = function(nodes, args) {
- args = args || [];
- if (nodes.length == 0) {
- return {integrand: args, intvar: null, rest: nodes};
- }
- var firstNode = nodes[0];
- if (cvox.SemanticTree.generalFunctionBoundary_(firstNode)) {
- return {integrand: args, intvar: null, rest: nodes};
- }
- if (cvox.SemanticTree.integralDxBoundarySingle_(firstNode)) {
- return {integrand: args, intvar: firstNode, rest: nodes.slice(1)};
- }
- if (nodes[1] && cvox.SemanticTree.integralDxBoundary_(firstNode, nodes[1])) {
- var comma = this.createNode_();
- comma.updateContent_(cvox.SemanticAttr.invisibleComma());
- var intvar = this.makePunctuatedNode_(
- [firstNode, comma, nodes[1]], [comma]);
- intvar.role = cvox.SemanticAttr.Role.INTEGRAL;
- return {integrand: args, intvar: intvar, rest: nodes.slice(2)};
- }
- args.push(nodes.shift());
- return this.getIntegralArgs_(nodes, args);
-};
-
-
-/**
- * Create a function node.
- * @param {!cvox.SemanticTree.Node} func The function operator.
- * @param {!cvox.SemanticTree.Node} arg The argument.
- * @return {!cvox.SemanticTree.Node} The new function node.
- * @private
- */
-cvox.SemanticTree.prototype.makeFunctionNode_ = function(func, arg) {
- var applNode = this.createNode_();
- applNode.updateContent_(cvox.SemanticAttr.functionApplication());
- applNode.type = cvox.SemanticAttr.Type.PUNCTUATION;
- applNode.role = cvox.SemanticAttr.Role.APPLICATION;
- var newNode = this.makeBranchNode_(cvox.SemanticAttr.Type.APPL, [func, arg],
- [applNode]);
- newNode.role = func.role;
- return newNode;
-};
-
-
-/**
- * Create a big operator node.
- * @param {!cvox.SemanticTree.Node} bigOp The big operator.
- * @param {!cvox.SemanticTree.Node} arg The argument.
- * @return {!cvox.SemanticTree.Node} The new big operator node.
- * @private
- */
-cvox.SemanticTree.prototype.makeBigOpNode_ = function(bigOp, arg) {
- var newNode = this.makeBranchNode_(
- cvox.SemanticAttr.Type.BIGOP, [bigOp, arg], []);
- newNode.role = bigOp.role;
- return newNode;
-};
-
-
-/**
- * Create an integral node. It has three children: integral, integrand and
- * integration variable. The latter two can be omitted.
- * @param {!cvox.SemanticTree.Node} integral The integral operator.
- * @param {cvox.SemanticTree.Node} integrand The integrand.
- * @param {cvox.SemanticTree.Node} intvar The integral variable.
- * @return {!cvox.SemanticTree.Node} The new integral node.
- * @private
- */
-cvox.SemanticTree.prototype.makeIntegralNode_ = function(
- integral, integrand, intvar) {
- integrand = integrand || this.makeEmptyNode_();
- intvar = intvar || this.makeEmptyNode_();
- var newNode = this.makeBranchNode_(cvox.SemanticAttr.Type.INTEGRAL,
- [integral, integrand, intvar], []);
- newNode.role = integral.role;
- return newNode;
-};
-
-
-/**
- * Predicate implementing the boundary criteria for simple functions:
- *
- * @param {!cvox.SemanticTree.Node} node A semantic node of type fenced.
- * @return {boolean} True if the node meets the boundary criteria.
- * @private
- */
-cvox.SemanticTree.prototype.simpleFunctionHeuristic_ = function(node) {
- var children = node.childNodes;
- if (children.length == 0) {
- return true;
- }
- if (children.length > 1) {
- return false;
- }
- var child = children[0];
- if (child.type == cvox.SemanticAttr.Type.INFIXOP) {
- if (child.role != cvox.SemanticAttr.Role.IMPLICIT) {
- return false;
- }
- if (child.childNodes.some(cvox.SemanticTree.attrPred_('type', 'INFIXOP'))) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Predicate implementing the boundary criteria for prefix functions and big
- * operators:
- * 1. an explicit operator,
- * 2. a relation symbol, or
- * 3. some punctuation.
- * @param {cvox.SemanticTree.Node} node A semantic node.
- * @return {boolean} True if the node meets the boundary criteria.
- * @private
- */
-cvox.SemanticTree.prefixFunctionBoundary_ = function(node) {
- return cvox.SemanticTree.attrPred_('type', 'OPERATOR')(node) ||
- cvox.SemanticTree.generalFunctionBoundary_(node);
-};
-
-
-/**
- * Predicate implementing the boundary criteria for integrals dx on two nodes.
- * @param {cvox.SemanticTree.Node} firstNode A semantic node.
- * @param {cvox.SemanticTree.Node} secondNode The direct neighbour of first
- * Node.
- * @return {boolean} True if the second node exists and the first node is a 'd'.
- * @private
- */
-cvox.SemanticTree.integralDxBoundary_ = function(
- firstNode, secondNode) {
- return !!secondNode &&
- cvox.SemanticTree.attrPred_('type', 'IDENTIFIER')(secondNode) &&
- cvox.SemanticAttr.isCharacterD(firstNode.textContent);
-};
-
-
-/**
- * Predicate implementing the boundary criteria for integrals dx on a single
- * node.
- * @param {cvox.SemanticTree.Node} node A semantic node.
- * @return {boolean} True if the node meets the boundary criteria.
- * @private
- */
-cvox.SemanticTree.integralDxBoundarySingle_ = function(node) {
- if (cvox.SemanticTree.attrPred_('type', 'IDENTIFIER')(node)) {
- var firstChar = node.textContent[0];
- return firstChar && node.textContent[1] &&
- cvox.SemanticAttr.isCharacterD(firstChar);
- }
- return false;
-};
-
-
-/**
- * Predicate implementing the general boundary criteria for function operators:
- * 1. a relation symbol,
- * 2. some punctuation.
- * @param {cvox.SemanticTree.Node} node A semantic node.
- * @return {boolean} True if the node meets the boundary criteria.
- * @private
- */
-cvox.SemanticTree.generalFunctionBoundary_ = function(node) {
- return cvox.SemanticTree.attrPred_('type', 'RELATION')(node) ||
- cvox.SemanticTree.attrPred_('type', 'PUNCTUATION')(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.
- * @private
- */
-cvox.SemanticTree.prototype.processTablesInRow_ = function(nodes) {
- // First we process all matrices:
- var partition = cvox.SemanticTree.partitionNodes_(
- nodes, cvox.SemanticTree.tableIsMatrixOrVector_);
- var result = [];
- for (var i = 0, matrix; matrix = partition.rel[i]; i++) {
- result = result.concat(partition.comp.shift());
- result.push(this.tableToMatrixOrVector_(matrix));
- }
- result = result.concat(partition.comp.shift());
- // Process the remaining tables for cases.
- partition = cvox.SemanticTree.partitionNodes_(
- result, cvox.SemanticTree.isTableOrMultiline_);
- result = [];
- for (var i = 0, table; table = partition.rel[i]; i++) {
- var prevNodes = partition.comp.shift();
- if (cvox.SemanticTree.tableIsCases_(table, prevNodes)) {
- this.tableToCases_(
- table, /** @type {!cvox.SemanticTree.Node} */ (prevNodes.pop()));
- }
- result = result.concat(prevNodes);
- result.push(table);
- }
- return result.concat(partition.comp.shift());
-};
-
-
-/**
- * Decides if a node is a table or multiline element.
- * @param {cvox.SemanticTree.Node} node A node.
- * @return {boolean} True if node is either table or multiline.
- * @private
- */
-cvox.SemanticTree.isTableOrMultiline_ = function(node) {
- return !!node && (cvox.SemanticTree.attrPred_('type', 'TABLE')(node) ||
- cvox.SemanticTree.attrPred_('type', 'MULTILINE')(node));
-};
-
-
-/**
- * Heuristic to decide if we have a matrix: An expression fenced on both sides
- * without any other content is considered a fenced node.
- * @param {cvox.SemanticTree.Node} node A node.
- * @return {boolean} True if we believe we have a matrix.
- * @private
- */
-cvox.SemanticTree.tableIsMatrixOrVector_ = function(node) {
- return !!node && cvox.SemanticTree.attrPred_('type', 'FENCED')(node) &&
- cvox.SemanticTree.attrPred_('role', 'LEFTRIGHT')(node) &&
- node.childNodes.length == 1 &&
- cvox.SemanticTree.isTableOrMultiline_(node.childNodes[0]);
-};
-
-
-/**
- * Replaces a fenced node by a matrix or vector node.
- * @param {!cvox.SemanticTree.Node} node The fenced node to be rewritten.
- * @return {!cvox.SemanticTree.Node} The matrix or vector node.
- * @private
- */
-cvox.SemanticTree.prototype.tableToMatrixOrVector_ = function(node) {
- var matrix = node.childNodes[0];
- var type = cvox.SemanticTree.attrPred_('type', 'MULTILINE')(matrix) ?
- 'VECTOR' : 'MATRIX';
- matrix.type = cvox.SemanticAttr.Type[type];
- node.contentNodes.forEach(goog.bind(matrix.appendContentNode_, matrix));
- for (var i = 0, row; row = matrix.childNodes[i]; i++) {
- cvox.SemanticTree.assignRoleToRow_(row, cvox.SemanticAttr.Role[type]);
- }
- return matrix;
-};
-
-
-/**
- * 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.
- * @return {boolean} True if we believe we have a case statement.
- * @private
- */
-cvox.SemanticTree.tableIsCases_ = function(table, prevNodes) {
- return prevNodes.length > 0 &&
- cvox.SemanticTree.attrPred_('role', 'OPENFENCE')(
- prevNodes[prevNodes.length - 1]);
-};
-
-
-/**
- * Makes case node out of a table and a fence.
- * @param {!cvox.SemanticTree.Node} table The table containing the cases.
- * @param {!cvox.SemanticTree.Node} openFence The left delimiter of the case
- * statement.
- * @return {!cvox.SemanticTree.Node} The cases node.
- * @private
- */
-cvox.SemanticTree.prototype.tableToCases_ = function(table, openFence) {
- for (var i = 0, row; row = table.childNodes[i]; i++) {
- cvox.SemanticTree.assignRoleToRow_(row, cvox.SemanticAttr.Role.CASES);
- // }
- }
- table.type = cvox.SemanticAttr.Type.CASES;
- table.appendContentNode_(openFence);
- return table;
-};
-
-
-// TODO (sorge) This heuristic is very primitive. We could start reworking
-// multilines, by combining all cells, semantically rewriting the entire line
-// and see if there are any similarities. Alternatively, we could look for
-// similarities in columns (e.g., single relation symbols, like equalities or
-// inequalities in the same column could indicate an equation array).
-/**
- * Heuristic to decide if we have a multiline formula. A table is considered a
- * multiline formula if it does not have any separate cells.
- * @param {!cvox.SemanticTree.Node} table A table node.
- * @return {boolean} True if we believe we have a mulitline formula.
- * @private
- */
-cvox.SemanticTree.tableIsMultiline_ = function(table) {
- return table.childNodes.every(
- function(row) {
- var length = row.childNodes.length;
- return length <= 1;});
-};
-
-
-/**
- * Rewrites a table to multiline structure, simplifying it by getting rid of the
- * cell hierarchy level.
- * @param {!cvox.SemanticTree.Node} table The node to be rewritten a multiline.
- * @private
- */
-cvox.SemanticTree.prototype.tableToMultiline_ = function(table) {
- table.type = cvox.SemanticAttr.Type.MULTILINE;
- for (var i = 0, row; row = table.childNodes[i]; i++) {
- cvox.SemanticTree.rowToLine_(row, cvox.SemanticAttr.Role.MULTILINE);
- }
-};
-
-
-/**
- * Converts a row that only contains one cell into a single line.
- * @param {!cvox.SemanticTree.Node} row The row to convert.
- * @param {cvox.SemanticAttr.Role=} role The new role for the line.
- * @private
- */
-cvox.SemanticTree.rowToLine_ = function(row, role) {
- role = role || cvox.SemanticAttr.Role.UNKNOWN;
- if (cvox.SemanticTree.attrPred_('type', 'ROW')(row) &&
- row.childNodes.length == 1 &&
- cvox.SemanticTree.attrPred_('type', 'CELL')(row.childNodes[0])) {
- row.type = cvox.SemanticAttr.Type.LINE;
- row.role = role;
- row.childNodes = row.childNodes[0].childNodes;
- }
-};
-
-
-/**
- * Assign a row and its contained cells a new role value.
- * @param {!cvox.SemanticTree.Node} row The row to be updated.
- * @param {!cvox.SemanticAttr.Role} role The new role for the row and its cells.
- * @private
- */
-cvox.SemanticTree.assignRoleToRow_ = function(row, role) {
- if (cvox.SemanticTree.attrPred_('type', 'LINE')(row)) {
- row.role = role;
- return;
- }
- if (cvox.SemanticTree.attrPred_('type', 'ROW')(row)) {
- row.role = role;
- var cellPred = cvox.SemanticTree.attrPred_('type', 'CELL');
- row.childNodes.forEach(function(cell) {
- if (cellPred(cell)) {
- cell.role = role;
- }
- });
- }
-};
-
-
-/**
- * Splits a list of nodes wrt. to a given predicate.
- * @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>,
- * div: cvox.SemanticTree.Node,
- * tail: !Array<cvox.SemanticTree.Node>}} The split list.
- * @private
- */
-cvox.SemanticTree.sliceNodes_ = function(nodes, pred, reverse) {
- if (reverse) {
- nodes.reverse();
- }
- var head = [];
- for (var i = 0, node; node = nodes[i]; i++) {
- if (pred(node)) {
- if (reverse) {
- return {head: nodes.slice(i + 1).reverse(),
- div: node,
- tail: head.reverse()};
- }
- return {head: head,
- div: node,
- tail: nodes.slice(i + 1)};
- }
- head.push(node);
- }
- if (reverse) {
- return {head: [], div: null, tail: head.reverse()};
- }
- return {head: head, div: null, tail: []};
-};
-
-
-/**
- * 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 {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the
- * partitioning relation.
- * @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.
- *
- * Example: On input [a, r_1, b, c, r_2, d, e, r_3] where P(r_i) holds, we
- * get as output: {rel: [r_1, r_2, r_3], comp: [[a], [b, c], [d, e], []].
- * @private
- */
-cvox.SemanticTree.partitionNodes_ = function(nodes, pred) {
- var restNodes = nodes;
- var rel = [];
- var comp = [];
-
- do {
- var result = cvox.SemanticTree.sliceNodes_(restNodes, pred);
- comp.push(result.head);
- rel.push(result.div);
- restNodes = result.tail;
- } while (result.div);
- rel.pop();
- return {rel: rel, comp: comp};
-};
-
-
-/**
- * Constructs a predicate to check the semantic attribute of a node.
- * @param {!string} prop The property of a node.
- * @param {!string} attr The attribute.
- * @return {function(cvox.SemanticTree.Node): boolean} The predicate.
- * @private
- */
-
-cvox.SemanticTree.attrPred_ = function(prop, attr) {
- var getAttr = function(prop) {
- switch (prop) {
- case 'type': return cvox.SemanticAttr.Type[attr];
- case 'role': return cvox.SemanticAttr.Role[attr];
- case 'font': return cvox.SemanticAttr.Font[attr];
- }
- };
-
- return function(node) {return node[prop] == getAttr(prop);};
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree_test.unitjs
deleted file mode 100644
index d6948aebd65..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree_test.unitjs
+++ /dev/null
@@ -1,6188 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxSemanticTreeUnitTest() {}
-
-CvoxSemanticTreeUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.SemanticAttr',
- 'cvox.SemanticTree',
- 'cvox.SemanticUtil',
- 'cvox.XpathUtil'
- ],
-
- /** @override */
- setUp: function() {
- this.nodeCounter = 0;
- this.xpathBlacklist = [];
- this.brief = true;
- this.setupAttributes();
- },
-
- /**
- * Adds some unicode characters via hex code to the right category.
- *
- * This method is necessary as the test framework can not handle code
- * containing utf-8 encoded characters.
- */
- setupAttributes: function() {
- var attr = cvox.SemanticAttr.getInstance();
- attr.neutralFences.unshift(cvox.SemanticUtil.numberToUnicode(0x00A6));
- attr.dashes.unshift(cvox.SemanticUtil.numberToUnicode(0x2015));
- attr.neutralFences.unshift(cvox.SemanticUtil.numberToUnicode(0x2016));
- attr.arrows.unshift(cvox.SemanticUtil.numberToUnicode(0x2192));
- attr.sumOps.unshift(cvox.SemanticUtil.numberToUnicode(0x2211));
- attr.additions.unshift(cvox.SemanticUtil.numberToUnicode(0x2213));
- attr.multiplications.unshift(cvox.SemanticUtil.numberToUnicode(0x2218));
- attr.intOps.unshift(cvox.SemanticUtil.numberToUnicode(0x222B));
- attr.inequalities.unshift(cvox.SemanticUtil.numberToUnicode(0x2264));
- attr.additions.unshift(cvox.SemanticUtil.numberToUnicode(0x2295));
- var open = cvox.SemanticUtil.numberToUnicode(0x3008);
- var close = cvox.SemanticUtil.numberToUnicode(0x3009);
- attr.openClosePairs[open] = close;
- attr.leftFences.unshift(open);
- attr.rightFences.unshift(close);
- },
-
- /**
- * Removes XML nodes according to the XPath elements in the blacklist.
- * @param {Node} xml Xml representation of the semantic node.
- */
- customizeXml: function(xml) {
- this.xpathBlacklist.forEach(
- function(xpath) {
- var removes = cvox.XpathUtil.evalXPath(xpath, xml);
- removes.forEach(
- function(node) {
- node.parentNode.removeChild(node);
- });
- });
- },
-
- /**
- * Tests if for a given mathml snippet results in a particular semantic tree.
- * @param {string} mml MathML expression.
- * @param {string} sml XML snippet for the semantic tree.
- */
- executeTreeTest: function(mml, sml) {
- var mathMl = '<math id=' + this.nodeCounter + '>' + mml + '';
- this.loadHtml(mathMl);
- var node = document.getElementById((this.nodeCounter++).toString());
- var stree = new cvox.SemanticTree(/** @type {!Element} */(node));
- var sxml = stree.xml(this.brief);
- this.customizeXml(sxml);
- var dp = new DOMParser();
- var xml = dp.parseFromString('<stree>' + sml + '</stree>', 'text/xml');
- var xmls = new XMLSerializer();
- assertEquals(xmls.serializeToString(xml),
- xmls.serializeToString(sxml));
- }
-};
-
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeRelations', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mo>=</mo>',
- '<relation>=</relation>');
- this.executeTreeTest(
- '<mi>a</mi><mo>=</mo><mi>b</mi>',
- '<relseq>=' +
- '<content><relation>=</relation></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
- this.executeTreeTest(
- '<mi>a</mi><mo>=</mo><mi>b</mi><mo>=</mo><mi>c</mi>',
- '<relseq>=' +
- '<content><relation>=</relation><relation>=</relation></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</relseq>');
- this.executeTreeTest(
- '<mi>a</mi><mo>=</mo><mi>b</mi><mo>=</mo><mi>c</mi>' +
- '<mo>\u2264</mo><mi>d</mi>',
- '<multirel>' +
- '<content><relation>=</relation><relation>=</relation>' +
- '<relation>\u2264</relation></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</multirel>');
-});
-
-
-// Operators.
-/**
- * Test operator trees with pre- and postfixes.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrePostfixOperators', function() {
- this.brief = true;
- // Pathological operator only case.
- this.executeTreeTest(
- '<mo>+</mo><mo>-</mo><mo>+</mo>',
- '<prefixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<prefixop>-' +
- '<content><operator>-</operator></content>' +
- '<children>' +
- '<operator>+</operator>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</prefixop>');
- // Single identifier with prefixes.
- this.executeTreeTest(
- '<mo>+</mo><mo>+</mo><mi>a</mi>',
- '<prefixop>+ +' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</prefixop>');
- // Single identifier with prefix and negative.
- this.executeTreeTest(
- '<mo>+</mo><mo>-</mo><mi>a</mi>',
- '<prefixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<prefixop>-' +
- '<content><operator>-</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</prefixop>');
- // Single identifier with postfixes.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mo>-</mo>',
- '<postfixop>+ -' +
- '<content><operator>+</operator><operator>-</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</postfixop>');
- // Single identifier with pre- and postfixes.
- this.executeTreeTest(
- '<mo>+</mo><mo>+</mo><mi>a</mi><mo>+</mo><mo>+</mo>',
- '<postfixop>+ +' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<prefixop>+ +' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</postfixop>');
- // Single identifier with mixed pre- and postfixes.
- this.executeTreeTest(
- '<mo>\u2213</mo><mo>+</mo><mi>a</mi><mo>\u2213</mo><mo>+</mo>',
- '<postfixop>\u2213 +' +
- '<content>' +
- '<operator>\u2213</operator><operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<prefixop>\u2213 +' +
- '<content>' +
- '<operator>\u2213</operator><operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</postfixop>');
- // Two identifiers with pre- and postfixes.
- this.executeTreeTest(
- '<mo>+</mo><mo>+</mo><mi>a</mi><mo>\u2213</mo><mo>+</mo>' +
- '<mi>b</mi><mo>+</mo>',
- '<infixop>\u2213' +
- '<content><operator>\u2213</operator></content>' +
- '<children>' +
- '<prefixop>+ +' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</prefixop>' +
- '<postfixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<prefixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</postfixop>' +
- '</children>' +
- '</infixop>');
- // Three identifiers with pre- and postfixes.
- this.executeTreeTest(
- '<mo>+</mo><mo>+</mo><mi>a</mi><mo>\u2213</mo><mo>+</mo>' +
- '<mi>b</mi><mo>+</mo><mo>\u2213</mo><mi>c</mi><mo>+</mo>',
- '<infixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<infixop>\u2213' +
- '<content><operator>\u2213</operator></content>' +
- '<children>' +
- '<prefixop>+ +' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</prefixop>' +
- '<prefixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</infixop>' +
- '<postfixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<prefixop>\u2213' +
- '<content><operator>\u2213</operator></content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</postfixop>' +
- '</children>' +
- '</infixop>');
-});
-
-
-/**
- * Test operator trees with single operator.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeSingleOperators', function() {
- this.brief = true;
- // Single identifier.
- this.executeTreeTest(
- '<mi>a</mi>',
- '<identifier>a</identifier>');
- // Single implicit node.
- this.executeTreeTest(
- '<mi>a</mi><mi>b</mi>',
- '<infixop>\u2062' +
- '<content><operator>\u2062</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
- // Implicit multi node.
- this.executeTreeTest(
- '<mi>a</mi><mi>b</mi><mi>c</mi>',
- '<infixop>\u2062' +
- '<content><operator>\u2062</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>');
- // Single addition.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi>',
- '<infixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
- // Multi addition.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mo>+</mo><mi>c</mi>',
- '<infixop>+' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>');
- // Multi addition with implicit node.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mi>c</mi><mo>+</mo><mi>d</mi>',
- '<infixop>+' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<infixop>\u2062' +
- '<content><operator>\u2062</operator></content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>');
-});
-
-
-/**
- * Test operator trees with multiple operators.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeMultipleOperators', function() {
- this.brief = true;
- // Addition and subtraction.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mo>-</mo><mi>c</mi><mo>+</mo><mi>d</mi>',
- '<infixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<infixop>-' +
- '<content><operator>-</operator></content>' +
- '<children>' +
- '<infixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>');
- // Addition and subtraction.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mo>+</mo><mi>c</mi><mo>-</mo>' +
- '<mi>d</mi><mo>-</mo><mi>e</mi>',
- '<infixop>-' +
- '<content><operator>-</operator><operator>-</operator></content>' +
- '<children>' +
- '<infixop>+' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>d</identifier>' +
- '<identifier>e</identifier>' +
- '</children>' +
- '</infixop>');
- // Addition and explicit multiplication.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mo>\u2218</mo><mi>c</mi><mo>+</mo>' +
- '<mi>d</mi>',
- '<infixop>+' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<infixop>\u2218' +
- '<content><operator>\u2218</operator></content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>');
- // Addition with explicit and implicit multiplication.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mo>\u2218</mo><mi>c</mi><mi>d</mi>' +
- '<mo>+</mo><mi>e</mi><mo>\u2218</mo><mi>f</mi>',
- '<infixop>+' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<infixop>\u2218' +
- '<content><operator>\u2218</operator></content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<infixop>\u2062' +
- '<content><operator>\u2062</operator></content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</infixop>' +
- '<infixop>\u2218' +
- '<content><operator>\u2218</operator></content>' +
- '<children>' +
- '<identifier>e</identifier>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</infixop>');
- // Two Additions, subtraction plus explicit and implicit multiplication,
- // one prefix and one postfix.
- this.executeTreeTest(
- '<mi>a</mi><mo>+</mo><mi>b</mi><mo>+</mo><mi>c</mi><mi>d</mi>' +
- '<mo>+</mo><mi>e</mi><mo>\u2218</mo><mi>f</mi><mo>-</mo><mi>g</mi>' +
- '<mo>+</mo><mo>+</mo><mi>h</mi><mo>\u2295</mo><mi>i</mi>' +
- '<mo>\u2295</mo><mi>j</mi><mo>+</mo><mo>+</mo>',
- '<infixop>\u2295' +
- '<content><operator>\u2295</operator>' +
- '<operator>\u2295</operator></content>' +
- '<children>' +
- '<infixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<infixop>-' +
- '<content><operator>-</operator></content>' +
- '<children>' +
- '<infixop>+' +
- '<content><operator>+</operator>' +
- '<operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<infixop>\u2062' +
- '<content><operator>\u2062</operator></content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '<infixop>\u2218' +
- '<content><operator>\u2218</operator></content>' +
- '<children>' +
- '<identifier>e</identifier>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</infixop>' +
- '<identifier>g</identifier>' +
- '</children>' +
- '</infixop>' +
- '<prefixop>+' +
- '<content><operator>+</operator></content>' +
- '<children>' +
- '<identifier>h</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</infixop>' +
- '<identifier>i</identifier>' +
- '<postfixop>+ +' +
- '<content><operator>+</operator><operator>+</operator></content>' +
- '<children>' +
- '<identifier>j</identifier>' +
- '</children>' +
- '</postfixop>' +
- '</children>' +
- '</infixop>');
-});
-
-
-// Fences.
-/**
- * Test regular directed fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeRegularFences', function() {
- this.brief = true;
- // No fence.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
- // Empty parentheses.
- this.executeTreeTest(
- '<mrow><mo>(</mo><mo>)</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<empty/>' +
- '</children>' +
- '</fenced>');
- // Single Fenced Expression.
- this.executeTreeTest(
- '<mrow><mo>(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>)</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>');
- // Single Fenced Expression and operators.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>+</mo><mo>(</mo><mi>b</mi><mo>+</mo><mi>c</mi>' +
- '<mo>)</mo><mo>+</mo><mi>d</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>');
- // Parallel Parenthesis.
- this.executeTreeTest(
- '<mrow><mo>(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>)</mo><mo>(</mo>' +
- '<mi>c</mi><mo>+</mo><mi>d</mi><mo>)</mo></mrow>',
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>');
- // Nested Parenthesis.
- this.executeTreeTest(
- '<mrow><mo>(</mo><mo>(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>)</mo>' +
- '<mo>(</mo><mi>c</mi><mo>+</mo><mi>d</mi><mo>)</mo><mo>)</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>');
- // Nested parenthesis and brackets.
- this.executeTreeTest(
- '<mrow><mo>(</mo><mo>[</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>+</mo>' +
- '<mi>c</mi><mo>]</mo><mo>+</mo><mi>d</mi><mo>)</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>');
- // Nested parenthesis, brackets, braces and superscript operator.
- this.executeTreeTest(
- '<mrow><mo>(</mo><msup><mi>a</mi><mrow><mn>2</mn><mo>[</mo><mi>i</mi>' +
- '<mo>+</mo><mi>n</mi><mo>]</mo></mrow></msup><mo>+</mo><mi>b</mi>' +
- '<mo>)</mo><mo>+</mo><mo>{</mo><mi>c</mi><mi>d</mi><mo>-</mo><mo>[</mo>' +
- '<mi>e</mi><mo>+</mo><mi>f</mi><mo>]</mo><mo>}</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<number>2</number>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>i</identifier>' +
- '<identifier>n</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</superscript>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<fenced>' +
- '<content>' +
- '<fence>{</fence>' +
- '<fence>}</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>-' +
- '<content>' +
- '<operator>-</operator>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>e</identifier>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>');
-});
-
-
-/**
- * Test neutral fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeNeutralFences', function() {
- this.brief = true;
- // Empty bars.
- this.executeTreeTest(
- '<mrow><mo>|</mo><mo>|</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<empty/>' +
- '</children>' +
- '</fenced>');
- // Simple bar fence.
- this.executeTreeTest(
- '<mrow><mo>|</mo><mi>a</mi><mo>|</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</fenced>');
- // Parallel bar fences.
- this.executeTreeTest(
- '<mrow><mo>|</mo><mi>a</mi><mo>|</mo><mi>b</mi><mo>+</mo>' +
- '<mo>\u00A6</mo><mi>c</mi><mo>\u00A6</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</fenced>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u00A6</fence>' +
- '<fence>\u00A6</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>');
- // Nested bar fences.
- this.executeTreeTest(
- '<mrow><mo>\u00A6</mo><mo>|</mo><mi>a</mi><mo>|</mo><mi>b</mi>' +
- '<mo>+</mo><mi>c</mi><mo>\u00A6</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>\u00A6</fence>' +
- '<fence>\u00A6</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</fenced>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>');
-});
-
-
-/**
- * Mixed neutral and regular fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeMixedFences', function() {
- this.brief = true;
- // Empty parenthsis inside bars.
- this.executeTreeTest(
- '<mrow><mo>|</mo><mo>(</mo><mo>)</mo><mo>|</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<empty/>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</fenced>');
- // Bars inside parentheses.
- this.executeTreeTest(
- '<mrow><mo>(</mo><mo>|</mo><mi>a</mi><mo>|</mo><mi>b</mi>' +
- '<mo>&#x00A6;</mo><mi>c</mi><mo>&#x00A6;</mo><mi>d</mi>' +
- '<mo>)</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '</children>' +
- '</fenced>' +
- '<identifier>b</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u00A6</fence>' +
- '<fence>\u00A6</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</fenced>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>');
- // Parentheses inside bards.
- this.executeTreeTest(
- '<mrow><mo>|</mo><mo>(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>)</mo>' +
- '<mo>&#x00A6;</mo><mi>c</mi><mo>&#x00A6;</mo><mi>d</mi><mo>|</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u00A6</fence>' +
- '<fence>\u00A6</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</fenced>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>');
- // Parentheses inside bards.
- this.executeTreeTest(
- '<mrow><mo>[</mo><mo>|</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>|</mo>' +
- '<mo>+</mo><mi>c</mi><mo>]</mo><mo>+</mo><mo>\u00A6</mo><mi>d</mi>' +
- '<mo>+</mo><mo>(</mo><mi>e</mi><mo>+</mo><mi>f</mi><mo>)</mo>' +
- '<mo>\u00A6</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u00A6</fence>' +
- '<fence>\u00A6</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>d</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>e</identifier>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>');
-});
-
-
-/**
- * Mixed with isolated bars.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeMixedFencesWithBars', function() {
- this.brief = true;
- this.xpathBlacklist = ['descendant::punctuated/content'];
- // Set notation.
- this.executeTreeTest(
- '<mrow><mo>{</mo><mo>(</mo><mi>x</mi><mo>,</mo><mi>y</mi><mo>,</mo>' +
- '<mi>z</mi><mo>)</mo><mo>|</mo><mi>x</mi><mi>y</mi><mo>=</mo>' +
- '<mo>z</mo><mo>}</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>{</fence>' +
- '<fence>}</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<punctuation>,</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>,</punctuation>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>');
- // Disjunction of bracketed parallel statements.
- this.executeTreeTest(
- '<mrow><mo>[</mo><mi>a</mi><mo>&#x2016;</mo><mi>b</mi><mo>]</mo>' +
- '<mo>|</mo><mo>[</mo><mi>x</mi><mo>&#x2016;</mo><mi>y</mi><mo>]</mo>' +
- '</mrow>',
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</punctuated>'
- );
- // Metric over the above.
- this.executeTreeTest(
- '<mrow><mo>&#x2016;</mo><mo>[</mo><mi>a</mi><mo>&#x2016;</mo>' +
- '<mi>b</mi><mo>]</mo><mo>|</mo><mo>[</mo><mi>x</mi><mo>&#x2016;</mo>' +
- '<mi>y</mi><mo>]</mo><mo>&#x2016;</mo></mrow>',
- '<fenced>' +
- '<content>' +
- '<fence>\u2016</fence>' +
- '<fence>\u2016</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>');
- // Mix of metrics and bracketed expression and single bars.
- this.executeTreeTest(
- '<mrow><mo>&#x2016;</mo><mo>[</mo><mi>a</mi><mo>&#x2016;</mo><mi>b</mi>' +
- '<mo>]</mo><mo>|</mo><mo>[</mo><mi>c</mi><mo>&#x2016;</mo>' +
- '<mo>&#x00A6;</mo><mi>d</mi><mo>]</mo><mo>&#x2016;</mo><mo>[</mo>' +
- '<mi>u</mi><mo>&#x2016;</mo><mi>v</mi><mo>]</mo><mo>|</mo><mi>x</mi>' +
- '<mo>&#x2016;</mo><mi>y</mi><mo>&#x00A6;</mo><mi>z</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u2016</fence>' +
- '<fence>\u2016</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>u</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>v</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '<punctuation>|</punctuation>' +
- '<identifier>x</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</punctuated>');
- this.xpathBlacklist = [];
-});
-
-
-/**
- * Pathological cases with only opening fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeOpeningFencesOnly', function() {
- this.brief = true;
- this.xpathBlacklist = ['descendant::punctuated/content'];
- // Single.
- this.executeTreeTest(
- '<mrow><mo>[</mo></mrow>',
- '<fence>[</fence>');
- // Single right.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>[</mo></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>[</punctuation>' +
- '</children>' +
- '</punctuated>');
- // Single middle.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>[</mo><mi>b</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>[</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>');
- // Single left.
- this.executeTreeTest(
- '<mrow><mo>[</mo><mi>b</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<punctuation>[</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>[</mo><mi>b</mi><mi>c</mi><mo>(</mo><mi>d</mi>' +
- '<mo>{</mo><mi>e</mi><mo>&#x3008;</mo><mi>f</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>[</punctuation>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '<punctuation>(</punctuation>' +
- '<identifier>d</identifier>' +
- '<punctuation>{</punctuation>' +
- '<identifier>e</identifier>' +
- '<punctuation>\u3008</punctuation>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple plus inner fenced.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>[</mo><mi>b</mi><mo>[</mo><mo>(</mo><mo>(</mo>' +
- '<mi>c</mi><mo>)</mo><mi>d</mi><mo>{</mo><mi>e</mi><mo>&#x3008;</mo>' +
- '<mi>f</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>[</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>[</punctuation>' +
- '<punctuation>(</punctuation>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</fenced>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</infixop>' +
- '<punctuation>{</punctuation>' +
- '<identifier>e</identifier>' +
- '<punctuation>\u3008</punctuation>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</punctuated>');
- this.xpathBlacklist = [];
-});
-
-
-/**
- * Pathological cases with only closing fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeClosingFencesOnly', function() {
- this.brief = true;
- this.xpathBlacklist = ['descendant::punctuated/content'];
- // Single.
- this.executeTreeTest(
- '<mrow><mo>]</mo></mrow>',
- '<fence>]</fence>');
- // Single right.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>]</mo></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>]</punctuation>' +
- '</children>' +
- '</punctuated>');
- // Single middle.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>]</mo><mi>b</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>]</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>');
- // Single left.
- this.executeTreeTest(
- '<mrow><mo>]</mo><mi>b</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<punctuation>]</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>]</mo><mi>b</mi><mi>c</mi><mo>)</mo><mi>d</mi>' +
- '<mo>}</mo><mi>e</mi><mo>&#x3009;</mo><mi>f</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>]</punctuation>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</infixop>' +
- '<punctuation>)</punctuation>' +
- '<identifier>d</identifier>' +
- '<punctuation>}</punctuation>' +
- '<identifier>e</identifier>' +
- '<punctuation>\u3009</punctuation>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple plus inner fenced.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>]</mo><mi>b</mi><mo>]</mo><mo>(</mo><mi>c</mi>' +
- '<mo>)</mo><mo>)</mo><mi>d</mi><mo>}</mo><mi>e</mi><mo>&#x3009;</mo>' +
- '<mi>f</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>]</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>]</punctuation>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>)</punctuation>' +
- '<identifier>d</identifier>' +
- '<punctuation>}</punctuation>' +
- '<identifier>e</identifier>' +
- '<punctuation>\u3009</punctuation>' +
- '<identifier>f</identifier>' +
- '</children>' +
- '</punctuated>');
- this.xpathBlacklist = [];
-});
-
-
-/**
- * Pathological cases with only neutral fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeNeutralFencesOnly', function() {
- this.brief = true;
- this.xpathBlacklist = ['descendant::punctuated/content'];
- // Single.
- this.executeTreeTest(
- '<mrow><mo>|</mo></mrow>',
- '<fence>|</fence>');
- // Single right.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>|</mo></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>|</punctuation>' +
- '</children>' +
- '</punctuated>');
- // Single middle.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>|</mo><mi>b</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>|</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>');
- // Single left.
- this.executeTreeTest(
- '<mrow><mo>|</mo><mi>b</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<punctuation>|</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>');
- // Two different bars.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>|</mo><mi>b</mi><mo>&#x00A6;</mo><mi>c</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>|</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</punctuated>');
- // Three different bars.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>&#x2016;</mo><mi>b</mi><mo>|</mo><mi>c</mi>' +
- '<mo>&#x00A6;</mo><mi>d</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>|</punctuation>' +
- '<identifier>c</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple plus inner fenced.
- this.executeTreeTest(
- '<mrow><mo>&#x2016;</mo><mo>[</mo><mi>a</mi><mo>&#x2016;</mo><mi>b</mi>' +
- '<mo>]</mo><mo>&#x2016;</mo><mo>|</mo><mi>x</mi><mo>&#x2016;</mo>' +
- '<mi>y</mi><mo>&#x00A6;</mo><mi>z</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u2016</fence>' +
- '<fence>\u2016</fence>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<identifier>x</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</punctuated>');
- this.xpathBlacklist = [];
-});
-
-
-/**
- * Pathological cases with mixed fences.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeMixedUnmatchedFences', function() {
- this.brief = true;
- this.xpathBlacklist = ['descendant::punctuated/content'];
- // Close, neutral, open.
- this.executeTreeTest(
- '<mrow><mo>]</mo><mo>&#x2016;</mo><mi>b</mi><mo>|</mo><mi>c</mi>' +
- '<mo>(</mo></mrow>',
- '<punctuated>' +
- '<children>' +
- '<punctuation>]</punctuation>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>|</punctuation>' +
- '<identifier>c</identifier>' +
- '<punctuation>(</punctuation>' +
- '</children>' +
- '</punctuated>');
- // Neutrals and close.
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>&#x2016;</mo><mi>b</mi><mo>|</mo><mi>c</mi>' +
- '<mo>&#x00A6;</mo><mi>d</mi><mo>]</mo><mi>e</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>|</punctuation>' +
- '<identifier>c</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>d</identifier>' +
- '<punctuation>]</punctuation>' +
- '<identifier>e</identifier>' +
- '</children>' +
- '</punctuated>');
- // Neutrals and open.
- this.executeTreeTest(
- '<mrow><mo>[</mo><mi>a</mi><mo>&#x2016;</mo><mi>b</mi><mo>|</mo>' +
- '<mi>c</mi><mo>&#x00A6;</mo><mi>d</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<punctuation>[</punctuation>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '<punctuation>|</punctuation>' +
- '<identifier>c</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple fences, fenced and operations
- this.executeTreeTest(
- '<mrow><mo>&#x2016;</mo><mo>[</mo><mi>a</mi><mo>&#x2016;</mo><mi>b</mi>' +
- '<mo>]</mo><mo>|</mo><mo>[</mo><mi>c</mi><mo>&#x2016;</mo>' +
- '<mo>&#x00A6;</mo><mi>d</mi><mo>]</mo><mo>&#x2016;</mo><mo>|</mo>' +
- '<mi>x</mi><mo>&#x2016;</mo><mi>y</mi><mo>&#x00A6;</mo><mi>z</mi>' +
- '<mo>]</mo></mrow>',
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u2016</fence>' +
- '<fence>\u2016</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>c</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>d</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>|</punctuation>' +
- '<identifier>x</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>z</identifier>' +
- '<punctuation>]</punctuation>' +
- '</children>' +
- '</punctuated>');
- // Multiple fences, fenced and operations
- this.executeTreeTest(
- '<mrow><mo>&#x2016;</mo><mo>]</mo><mo>&#x00A6;</mo><mo>&#x2016;</mo>' +
- '<mo>[</mo><mo>|</mo><mo>[</mo><mi>a</mi><mo>&#x2016;</mo><mi>b</mi>' +
- '<mo>]</mo><mo>&#x2016;</mo><mo>|</mo><mi>[</mi><mo>&#x2016;</mo>' +
- '<mi>y</mi><mo>&#x00A6;</mo><mi>z</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>\u2016</fence>' +
- '<fence>\u2016</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<punctuation>]</punctuation>' +
- '<punctuation>\u00A6</punctuation>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>[</punctuation>' +
- '<fenced>' +
- '<content>' +
- '<fence>|</fence>' +
- '<fence>|</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>\u2016</punctuation>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '<punctuation>[</punctuation>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</punctuated>');
- // Multiple fences, fenced and operations
- this.executeTreeTest(
- '<mrow><mo>&#x2016;</mo><mo>[</mo><mi>a</mi><mo>&#x00A6;</mo>' +
- '<mo>&#x2016;</mo><mo>[</mo><mo>+</mo><mo>[</mo><mi>b</mi>' +
- '<mo>&#x2016;</mo><mi>c</mi><mo>]</mo><mo>+</mo><mo>&#x2016;</mo>' +
- '<mo>|</mo><mi>d</mi><mo>+</mo><mi>e</mi><mi>[</mi><mo>&#x2016;</mo>' +
- '<mi>y</mi><mo>&#x00A6;</mo><mo>+</mo><mi>z</mi></mrow>',
- '<punctuated>' +
- '<children>' +
- '<punctuation>\u2016</punctuation>' +
- '<punctuation>[</punctuation>' +
- '<identifier>a</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<punctuation>\u2016</punctuation>' +
- '<punctuation>[</punctuation>' +
- '<postfixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<prefixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<children>' +
- '<identifier>b</identifier>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>c</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</postfixop>' +
- '<punctuation>\u2016</punctuation>' +
- '<punctuation>|</punctuation>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>d</identifier>' +
- '<identifier>e</identifier>' +
- '</children>' +
- '</infixop>' +
- '<punctuation>[</punctuation>' +
- '<punctuation>\u2016</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>\u00A6</punctuation>' +
- '<prefixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</prefixop>' +
- '</children>' +
- '</punctuated>');
- this.xpathBlacklist = [];
-});
-
-
-/**
- * Simple function applications
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeSimpleFuncsSingle', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>f</mi></mrow>',
- '<identifier>f</identifier>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mi>y</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>,</mo><mi>y</mi>' +
- '<mo>,</mo><mi>z</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<punctuated>' +
- '<content>' +
- '<punctuation>,</punctuation>' +
- '<punctuation>,</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<punctuation>,</punctuation>' +
- '<identifier>y</identifier>' +
- '<punctuation>,</punctuation>' +
- '<identifier>z</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><msup><mi>x</mi><mn>2</mn></msup>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><msub><mi>x</mi><mn>2</mn></msub>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><msubsup><mi>x</mi><mn>2</mn>' +
- '<mn>1</mn></msubsup><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '<number>1</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mover><mi>x</mi><mn>2</mn></mover>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<overscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</overscore>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><munder><mi>x</mi><mn>2</mn></munder>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<underscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</underscore>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><munderover><mi>x</mi><mn>2</mn>' +
- '<mn>1</mn></munderover><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<overscore>' +
- '<children>' +
- '<underscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</underscore>' +
- '<number>1</number>' +
- '</children>' +
- '</overscore>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mfrac><mn>1</mn><mn>2</mn></mfrac>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<fraction>' +
- '<children>' +
- '<number>1</number>' +
- '<number>2</number>' +
- '</children>' +
- '</fraction>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>+</mo><mi>y</mi>' +
- '<mo>)</mo></mrow>',
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>');
-});
-
-
-/**
- * Simple functions with surrounding operators.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeSimpleFuncsWithOps', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mn>1</mn><mo>+</mo><mi>f</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<number>1</number>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo>' +
- '<mn>2</mn></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<number>2</number>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mn>1</mn><mo>+</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>+</mo><mn>2</mn></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<number>1</number>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<number>2</number>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>+</mo><mi>f</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo>' +
- '<mo>b</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>+</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>+</mo><mo>b</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>=</mo><mi>f</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo>' +
- '<mo>b</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>=</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>=</mo><mo>b</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Multiple simple functions.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeSimpleFuncsMulti', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo><mi>g</mi>' +
- '<mo>(</mo><mi>x</mi><mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>g</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo><mi>g</mi>' +
- '<mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mi>h</mi><mo>(</mo>' +
- '<mi>x</mi><mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>g</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>h</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo><mi>g</mi>' +
- '<mo>(</mo><mi>y</mi><mo>)</mo><mo>=</mo><mi>h</mi><mo>(</mo>' +
- '<mi>x</mi><mi>y</mi><mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>g</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>h</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Nested simple functions.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeSimpleFuncsNested', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>g</mi><mo>(</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>g</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>h</mi><mo>(</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mi>g</mi><mo>(</mo><mi>y</mi><mo>)</mo><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>h</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>g</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>h</mi><mo>(</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>+</mo><mi>g</mi><mo>(</mo><mi>y</mi><mo>)</mo><mo>)</mo></mrow>',
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>h</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>g</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mi>P</mi><mo>[</mo><mi>x</mi><mo>=</mo><mn>2</mn><mo>]</mo>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>P</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>[</fence>' +
- '<fence>]</fence>' +
- '</content>' +
- '<children>' +
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-});
-
-
-/**
- * Simple functions with explicit function application.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeSimpleFuncsExplicitApp', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mi>f</mi><mo>\u2061</mo><mo>(</mo><mi>x</mi><mo>+</mo><mi>y</mi>' +
- '<mo>)</mo>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mi>f</mi><mo>\u2061</mo><mo>(</mo><mi>x</mi><mo>+</mo><mi>y</mi>' +
- '<mo>)</mo><mo>+</mo><mi>f</mi><mo>(</mo><mi>x</mi><mo>+</mo>' +
- '<mi>y</mi><mo>)</mo>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<msub><mi>f</mi><mn>1</mn></msub><mo>\u2061</mo><mo>(</mo><mi>x</mi>' +
- '<mo>+</mo><mi>y</mi><mo>)</mo>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<number>1</number>' +
- '</children>' +
- '</subscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<msup><msub><mi>f</mi><mn>n</mn></msub><mn>2</mn></msup>' +
- '<mo>\u2061</mo><mo>(</mo><mi>x</mi><mo>+</mo><mi>y</mi><mo>)</mo>' +
- '<mo>+</mo><msup><msub><mi>f</mi><mn>m</mn></msub><mn>2</mn></msup>' +
- '<mo>(</mo><mi>x</mi><mo>+</mo><mi>y</mi><mo>)</mo>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<identifier>n</identifier>' +
- '</children>' +
- '</subscript>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>f</identifier>' +
- '<identifier>m</identifier>' +
- '</children>' +
- '</subscript>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</infixop>');
-});
-
-
-/**
- * Prefix function applications
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsSingle', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mi>y</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><msup><mi>x</mi><mn>2</mn></msup>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><msub><mi>x</mi><mn>2</mn></msub>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><msubsup><mi>x</mi><mn>2</mn>' +
- '<mn>1</mn></msubsup><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '<number>1</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mover><mi>x</mi><mn>2</mn></mover>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<overscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</overscore>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><munder><mi>x</mi><mn>2</mn></munder>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<underscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</underscore>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><munderover><mi>x</mi><mn>2</mn>' +
- '<mn>1</mn></munderover><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<overscore>' +
- '<children>' +
- '<underscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</underscore>' +
- '<number>1</number>' +
- '</children>' +
- '</overscore>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mfrac><mn>1</mn><mn>2</mn></mfrac>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<fraction>' +
- '<children>' +
- '<number>1</number>' +
- '<number>2</number>' +
- '</children>' +
- '</fraction>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>+</mo><mi>y</mi>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-});
-
-
-/**
- * Prefix functions applications with surrounding operators.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsWithOps', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mn>1</mn><mo>+</mo><mi>sin</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<number>1</number>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo>' +
- '<mn>2</mn></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<number>2</number>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mn>1</mn><mo>+</mo><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>+</mo><mn>2</mn></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<number>1</number>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<number>2</number>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>+</mo><mi>sin</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo>' +
- '<mo>b</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>+</mo><mi>sin</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo><mo>+</mo><mo>b</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>=</mo><mi>sin</mi><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo>' +
- '<mo>b</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>=</mo><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>=</mo><mo>b</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Multiple prefix function applications.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsMulti', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo><mi>cos</mi>' +
- '<mo>(</mo><mi>x</mi><mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo><mi>cos</mi>' +
- '<mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mi>tan</mi><mo>(</mo>' +
- '<mi>x</mi><mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>tan</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>+</mo><mi>cos</mi>' +
- '<mo>(</mo><mi>y</mi><mo>)</mo><mo>=</mo><mi>tan</mi><mo>(</mo>' +
- '<mi>x</mi><mi>y</mi><mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>tan</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Prefix function applications with sub- and superscripts.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsScripts', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><msup><mi>sin</mi><mn>2</mn></msup><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><msub><mi>sin</mi><mn>1</mn></msub><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>1</number>' +
- '</children>' +
- '</subscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><msubsup><mi>sin</mi><mn>2</mn><mn>1</mn></msubsup><mo>(</mo>' +
- '<mi>x</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '<number>1</number>' +
- '</children>' +
- '</superscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><msup><mi>sin</mi><mn>2</mn></msup><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo><mo>+</mo><msup><mi>cos</mi><mn>2</mn></msup><mo>(</mo>' +
- '<mi>y</mi><mo>)</mo><mo>=</mo><mn>1</mn></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>cos</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<number>1</number>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Prefix function applications with unfenced arguments.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsUnfenced', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mi>y</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><msup><mi>x</mi><mn>2</mn></msup></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<superscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><msub><mi>x</mi><mn>2</mn></msub></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<subscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><msubsup><mi>x</mi><mn>2</mn><mn>1</mn>' +
- '</msubsup></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '<number>1</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mover><mi>x</mi><mn>2</mn></mover></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<overscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</overscore>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><munder><mi>x</mi><mn>2</mn></munder></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<underscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</underscore>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><munderover><mi>x</mi><mn>2</mn><mn>1</mn>' +
- '</munderover></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<overscore>' +
- '<children>' +
- '<underscore>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</underscore>' +
- '<number>1</number>' +
- '</children>' +
- '</overscore>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mfrac><mn>1</mn><mn>2</mn></mfrac></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fraction>' +
- '<children>' +
- '<number>1</number>' +
- '<number>2</number>' +
- '</children>' +
- '</fraction>' +
- '</children>' +
- '</appl>');
-});
-
-
-/**
- * Prefix function applications with unfenced arguments in an operator
- * expression.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsUnfencedOps', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mn>1</mn><mo>+</mo><mi>sin</mi><mi>x</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<number>1</number>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mo>+</mo><mn>2</mn></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<number>2</number>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mn>1</mn><mo>+</mo><mi>sin</mi><mi>x</mi><mo>+</mo>' +
- '<mn>2</mn></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<number>1</number>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<number>2</number>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>+</mo><mi>sin</mi><mi>x</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mo>+</mo><mo>b</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>+</mo><mi>sin</mi><mi>x</mi><mo>+</mo>' +
- '<mo>b</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>=</mo><mi>sin</mi><mi>x</mi></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mo>=</mo><mo>b</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mo>a</mo><mo>=</mo><mi>sin</mi><mi>x</mi><mo>=</mo>' +
- '<mo>b</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Multiple prefix function applications with unfenced arguments.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsMultiUnfenced', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mo>+</mo><mi>cos</mi><mi>x</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mo>+</mo><mi>cos</mi><mi>x</mi><mo>=</mo>' +
- '<mi>tan</mi><mi>x</mi></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>tan</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mi>x</mi><mo>+</mo><mi>cos</mi><mi>y</mi><mo>=</mo>' +
- '<mi>tan</mi><mi>x</mi><mi>y</mi></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>tan</function>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Prefix function applications with sub- and superscripts and unfenced
- * arguments.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsScriptUnfenced',
- function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><msup><mi>sin</mi><mn>2</mn></msup><mi>x</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><msub><mi>sin</mi><mn>1</mn></msub><mi>x</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>1</number>' +
- '</children>' +
- '</subscript>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><msubsup><mi>sin</mi><mn>2</mn><mn>1</mn></msubsup>' +
- '<mi>x</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '<number>1</number>' +
- '</children>' +
- '</superscript>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><msup><mi>sin</mi><mn>2</mn></msup><mi>x</mi><mo>+</mo><msup>' +
- '<mi>cos</mi><mn>2</mn></msup><mi>y</mi><mo>=</mo><mn>1</mn></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>cos</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<number>1</number>' +
- '</children>' +
- '</relseq>');
- this.executeTreeTest(
- '<mrow><msubsup><msubsup><mi>sin</mi><mn>2</mn><mn>1</mn>' +
- '</msubsup><mi>n</mi><mi>m</mi></msubsup><mi>x</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<subscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</subscript>' +
- '<number>1</number>' +
- '</children>' +
- '</superscript>' +
- '<identifier>n</identifier>' +
- '</children>' +
- '</subscript>' +
- '<identifier>m</identifier>' +
- '</children>' +
- '</superscript>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>');
-});
-
-
-/**
- * Prefix functions without arguments.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsNoArgs', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mi>sin</mi>',
- '<function>sin</function>');
-
- this.executeTreeTest(
- '<msup><mi>sin</mi><mn>2</mn></msup>',
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>');
-
- this.executeTreeTest(
- '<msup><mi>sin</mi><mn>2</mn></msup><mo>+</mo><msup><mi>cos</mi>' +
- '<mn>2</mn></msup>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>cos</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><msup><mi>sin</mi><mn>2</mn></msup><mo>+</mo>' +
- '<msup><mi>cos</mi><mn>2</mn></msup><mo>=</mo><mn>1</mn></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>sin</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<superscript>' +
- '<children>' +
- '<function>cos</function>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<number>1</number>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mi>sin</mi><mo>=</mo><mfrac><mn>1</mn>' +
- '<mi>csc</mi></mfrac></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '<fraction>' +
- '<children>' +
- '<number>1</number>' +
- '<function>csc</function>' +
- '</children>' +
- '</fraction>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Nested prefix function applications, both with and without fenced arguments.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreePrefixFuncsNested', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><mi>log</mi><mi>cos</mi><mi>x</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>log</function>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>ln</mi><mo>' +
- '(</mo><mi>sin</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>ln</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>log</mi><mi>cos</mi><mi>x</mi><mo>=' +
- '</mo><mi>ln</mi><mo>(</mo><mi>sin</mi><mo>' +
- '(</mo><mi>x</mi><mo>)</mo><mo>)</mo></mrow>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>log</function>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>cos</function>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>ln</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>sin</function>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Variations of tables representing matrices, vectors, case statements,
- * multiline equations and regular tables.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeTables', function() {
- this.brief = false;
- this.executeTreeTest(
- '<mrow class="MJX-TeXAtom-ORD"><mi mathvariant="bold">A</mi>' +
- '<mo>=</mo><mo>[</mo><mtable rowspacing="4pt" columnspacing="1em">' +
- '<mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd>' +
- '<mn>2</mn></mtd><mtd><mn>3</mn></mtd></mtr></mtable><mo>]</mo>' +
- '</mrow>',
- '<relseq role="equality" id="16">=' +
- '<content>' +
- '<relation role="equality" id="1">=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="bold" id="0">A</identifier>' +
- '<matrix role="unknown" id="13">' +
- '<content>' +
- '<fence role="open" id="2">[</fence>' +
- '<fence role="close" id="14">]</fence>' +
- '</content>' +
- '<children>' +
- '<row role="matrix" id="7">' +
- '<children>' +
- '<cell role="matrix" id="4">' +
- '<children>' +
- '<number role="integer" font="normal" id="3">0</number>' +
- '</children>' +
- '</cell>' +
- '<cell role="matrix" id="6">' +
- '<children>' +
- '<number role="integer" font="normal" id="5">1</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="matrix" id="12">' +
- '<children>' +
- '<cell role="matrix" id="9">' +
- '<children>' +
- '<number role="integer" font="normal" id="8">2</number>' +
- '</children>' +
- '</cell>' +
- '<cell role="matrix" id="11">' +
- '<children>' +
- '<number role="integer" font="normal" id="10">3</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</matrix>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mo>[</mo><mtable rowspacing="4pt" columnspacing="1em"><mtr>' +
- '<mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd>' +
- '<mn>2</mn></mtd><mtd><mn>3</mn></mtd></mtr></mtable>' +
- '<mo>]</mo>',
- '<matrix role="unknown" id="11">' +
- '<content>' +
- '<fence role="open" id="0">[</fence>' +
- '<fence role="close" id="12">]</fence>' +
- '</content>' +
- '<children>' +
- '<row role="matrix" id="5">' +
- '<children>' +
- '<cell role="matrix" id="2">' +
- '<children>' +
- '<number role="integer" font="normal" id="1">0</number>' +
- '</children>' +
- '</cell>' +
- '<cell role="matrix" id="4">' +
- '<children>' +
- '<number role="integer" font="normal" id="3">1</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="matrix" id="10">' +
- '<children>' +
- '<cell role="matrix" id="7">' +
- '<children>' +
- '<number role="integer" font="normal" id="6">2</number>' +
- '</children>' +
- '</cell>' +
- '<cell role="matrix" id="9">' +
- '<children>' +
- '<number role="integer" font="normal" id="8">3</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</matrix>');
-
- this.executeTreeTest(
- '<mrow class="MJX-TeXAtom-ORD"><mi mathvariant="bold">V</mi>' +
- '<mo>=</mo><mo>[</mo><mtable rowspacing="4pt" columnspacing="1em">' +
- '<mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>2</mn></mtd></mtr>' +
- '<mtr><mtd><mn>3</mn></mtd></mtr></mtable><mo>]</mo></mrow>',
- '<relseq role="equality" id="15">=' +
- '<content>' +
- '<relation role="equality" id="1">=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="bold" id="0">V</identifier>' +
- '<vector role="unknown" id="12">' +
- '<content>' +
- '<fence role="open" id="2">[</fence>' +
- '<fence role="close" id="13">]</fence>' +
- '</content>' +
- '<children>' +
- '<line role="vector" id="5">' +
- '<children>' +
- '<number role="integer" font="normal" id="3">1</number>' +
- '</children>' +
- '</line>' +
- '<line role="vector" id="8">' +
- '<children>' +
- '<number role="integer" font="normal" id="6">2</number>' +
- '</children>' +
- '</line>' +
- '<line role="vector" id="11">' +
- '<children>' +
- '<number role="integer" font="normal" id="9">3</number>' +
- '</children>' +
- '</line>' +
- '</children>' +
- '</vector>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mo>[</mo><mtable rowspacing="4pt" columnspacing="1em">' +
- '<mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>2</mn></mtd></mtr>' +
- '<mtr><mtd><mn>3</mn></mtd></mtr></mtable><mo>]</mo>',
- '<vector role="unknown" id="10">' +
- '<content>' +
- '<fence role="open" id="0">[</fence>' +
- '<fence role="close" id="11">]</fence>' +
- '</content>' +
- '<children>' +
- '<line role="vector" id="3">' +
- '<children>' +
- '<number role="integer" font="normal" id="1">1</number>' +
- '</children>' +
- '</line>' +
- '<line role="vector" id="6">' +
- '<children>' +
- '<number role="integer" font="normal" id="4">2</number>' +
- '</children>' +
- '</line>' +
- '<line role="vector" id="9">' +
- '<children>' +
- '<number role="integer" font="normal" id="7">3</number>' +
- '</children>' +
- '</line>' +
- '</children>' +
- '</vector>');
-
-
- this.executeTreeTest(
- '<mrow><mo>{</mo><mtable><mtr><mtd><mi>a</mi></mtd><mtd>' +
- '<mtext>often</mtext></mtd></mtr><mtr><mtd><mi>b</mi></mtd>' +
- '<mtd><mtext>sometimes</mtext></mtd></mtr></mtable></mrow>',
- '<cases role="unknown" id="11">' +
- '<content>' +
- '<punctuation role="openfence" id="0">{</punctuation>' +
- '</content>' +
- '<children>' +
- '<row role="cases" id="5">' +
- '<children>' +
- '<cell role="cases" id="2">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="1">a</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="4">' +
- '<children>' +
- '<text role="unknown" id="3">often</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="cases" id="10">' +
- '<children>' +
- '<cell role="cases" id="7">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="6">b</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="9">' +
- '<children>' +
- '<text role="unknown" id="8">sometimes</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</cases>');
-
- this.executeTreeTest(
- '<mrow><mi mathvariant="bold">A</mi><mo>=</mo><mo>{</mo><mtable>' +
- '<mtr><mtd><mi>a</mi></mtd><mtd><mtext>often</mtext></mtd></mtr>' +
- '<mtr><mtd><mi>b</mi></mtd><mtd><mtext>sometimes</mtext></mtd></mtr>' +
- '</mtable></mrow>',
- '<relseq role="equality" id="14">=' +
- '<content>' +
- '<relation role="equality" id="1">=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="bold" id="0">A</identifier>' +
- '<cases role="unknown" id="13">' +
- '<content>' +
- '<punctuation role="openfence" id="2">{</punctuation>' +
- '</content>' +
- '<children>' +
- '<row role="cases" id="7">' +
- '<children>' +
- '<cell role="cases" id="4">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="3">a</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="6">' +
- '<children>' +
- '<text role="unknown" id="5">often</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="cases" id="12">' +
- '<children>' +
- '<cell role="cases" id="9">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="8">b</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="11">' +
- '<children>' +
- '<text role="unknown" id="10">sometimes</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</cases>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mrow><mo>{</mo><mtable><mtr><mtd><mi>a</mi></mtd><mtd>' +
- '<mtext>often</mtext></mtd></mtr><mtr><mtd><mi>b</mi></mtd><mtd>' +
- '<mtext>sometimes</mtext></mtd></mtr></mtable><mo>.</mo></mrow>',
- '<punctuated role="endpunct" id="13">' +
- '<content>' +
- '<punctuation role="fullstop" id="12">.</punctuation>' +
- '</content>' +
- '<children>' +
- '<cases role="unknown" id="11">' +
- '<content>' +
- '<punctuation role="openfence" id="0">{</punctuation>' +
- '</content>' +
- '<children>' +
- '<row role="cases" id="5">' +
- '<children>' +
- '<cell role="cases" id="2">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="1">a</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="4">' +
- '<children>' +
- '<text role="unknown" id="3">often</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="cases" id="10">' +
- '<children>' +
- '<cell role="cases" id="7">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="6">b</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="9">' +
- '<children>' +
- '<text role="unknown" id="8">sometimes</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</cases>' +
- '<punctuation role="fullstop" id="12">.</punctuation>' +
- '</children>' +
- '</punctuated>');
-
- this.executeTreeTest(
- '<mrow><mo>{</mo><mtable><mtr><mtd><mi>a</mi></mtd>' +
- '<mtd><mtext>often</mtext></mtd></mtr><mtr><mtd><mi>b</mi></mtd>' +
- '<mtd><mtext>sometimes</mtext></mtd></mtr></mtable>' +
- '<mo>,</mo><mi>b</mi><mo>,</mo><mi>c</mi><mo>.</mo></mrow>',
- '<punctuated role="sequence" id="17">' +
- '<content>' +
- '<punctuation role="unknown" id="12">,</punctuation>' +
- '<punctuation role="unknown" id="14">,</punctuation>' +
- '<punctuation role="fullstop" id="16">.</punctuation>' +
- '</content>' +
- '<children>' +
- '<cases role="unknown" id="11">' +
- '<content>' +
- '<punctuation role="openfence" id="0">{</punctuation>' +
- '</content>' +
- '<children>' +
- '<row role="cases" id="5">' +
- '<children>' +
- '<cell role="cases" id="2">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="1">a</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="4">' +
- '<children>' +
- '<text role="unknown" id="3">often</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="cases" id="10">' +
- '<children>' +
- '<cell role="cases" id="7">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="6">b</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="cases" id="9">' +
- '<children>' +
- '<text role="unknown" id="8">sometimes</text>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</cases>' +
- '<punctuation role="unknown" id="12">,</punctuation>' +
- '<identifier role="latinletter" font="normal" id="13">b</identifier>' +
- '<punctuation role="unknown" id="14">,</punctuation>' +
- '<identifier role="latinletter" font="normal" id="15">c</identifier>' +
- '<punctuation role="fullstop" id="16">.</punctuation>' +
- '</children>' +
- '</punctuated>');
-
- this.executeTreeTest(
- '<mrow><mo>{</mo><mtable><mtr><mtd><mi>a</mi><mo>,</mo>' +
- '<mtext>often</mtext></mtd></mtr><mtr><mtd><mi>b</mi><mo>,</mo>' +
- '<mtext>sometimes</mtext></mtd></mtr></mtable><mo>,</mo><mi>b</mi>' +
- '<mo>,</mo><mi>c</mi><mo>.</mo></mrow>',
- '<punctuated role="sequence" id="19">' +
- '<content>' +
- '<punctuation role="unknown" id="14">,</punctuation>' +
- '<punctuation role="unknown" id="16">,</punctuation>' +
- '<punctuation role="fullstop" id="18">.</punctuation>' +
- '</content>' +
- '<children>' +
- '<cases role="unknown" id="13">' +
- '<content>' +
- '<punctuation role="openfence" id="0">{</punctuation>' +
- '</content>' +
- '<children>' +
- '<line role="cases" id="6">' +
- '<children>' +
- '<punctuated role="sequence" id="4">' +
- '<content>' +
- '<punctuation role="unknown" id="2">,</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="1">a</identifier>' +
- '<punctuation role="unknown" id="2">,</punctuation>' +
- '<text role="unknown" id="3">often</text>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</line>' +
- '<line role="cases" id="12">' +
- '<children>' +
- '<punctuated role="sequence" id="10">' +
- '<content>' +
- '<punctuation role="unknown" id="8">,</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="7">b</identifier>' +
- '<punctuation role="unknown" id="8">,</punctuation>' +
- '<text role="unknown" id="9">sometimes</text>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</line>' +
- '</children>' +
- '</cases>' +
- '<punctuation role="unknown" id="14">,</punctuation>' +
- '<identifier role="latinletter" font="normal" id="15">b</identifier>' +
- '<punctuation role="unknown" id="16">,</punctuation>' +
- '<identifier role="latinletter" font="normal" id="17">c</identifier>' +
- '<punctuation role="fullstop" id="18">.</punctuation>' +
- '</children>' +
- '</punctuated>');
-
- this.executeTreeTest(
- '<mtable><mtr><mtd><mi>x</mi><maligngroup/><mo>=</mo><mn>4</mn>' +
- '</mtd></mtr><mtr><mtd><mi>y</mi><maligngroup/><mo>=</mo><mn>2</mn>' +
- '</mtd></mtr><mtr><mtd><mi>x</mi><mi>y</mi><maligngroup/><mo>=</mo>' +
- '<mn>6</mn></mtd></mtr></mtable>',
- '<multiline role="unknown" id="21">' +
- '<children>' +
- '<line role="multiline" id="5">' +
- '<children>' +
- '<relseq role="equality" id="3">=' +
- '<content>' +
- '<relation role="equality" id="1">=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="0">x</identifier>' +
- '<number role="integer" font="normal" id="2">4</number>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</line>' +
- '<line role="multiline" id="11">' +
- '<children>' +
- '<relseq role="equality" id="9">=' +
- '<content>' +
- '<relation role="equality" id="7">=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="6">y</identifier>' +
- '<number role="integer" font="normal" id="8">2</number>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</line>' +
- '<line role="multiline" id="20">' +
- '<children>' +
- '<relseq role="equality" id="18">=' +
- '<content>' +
- '<relation role="equality" id="14">=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop role="implicit" id="17">\u2062' +
- '<content>' +
- '<operator role="multiplication" id="16">\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="12">x</identifier>' +
- '<identifier role="latinletter" font="normal" id="13">y</identifier>' +
- '</children>' +
- '</infixop>' +
- '<number role="integer" font="normal" id="15">6</number>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</line>' +
- '</children>' +
- '</multiline>');
-
- this.executeTreeTest(
- '<mtable><mtr><mtd><mi>x</mi></mtd><mtd><mo>=</mo></mtd><mtd><mn>4</mn>' +
- '</mtd></mtr><mtr><mtd><mi>y</mi></mtd><mtd><mo>=</mo></mtd><mtd>' +
- '<mn>2</mn></mtd></mtr><mtr><mtd><mi>x</mi><mi>y</mi></mtd><mtd>' +
- '<mo>=</mo></mtd><mtd><mn>6</mn></mtd></mtr></mtable>',
- '<table role="unknown" id="24">' +
- '<children>' +
- '<row role="table" id="6">' +
- '<children>' +
- '<cell role="table" id="1">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="0">x</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="table" id="3">' +
- '<children>' +
- '<relation role="equality" id="2">=</relation>' +
- '</children>' +
- '</cell>' +
- '<cell role="table" id="5">' +
- '<children>' +
- '<number role="integer" font="normal" id="4">4</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="table" id="13">' +
- '<children>' +
- '<cell role="table" id="8">' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="7">y</identifier>' +
- '</children>' +
- '</cell>' +
- '<cell role="table" id="10">' +
- '<children>' +
- '<relation role="equality" id="9">=</relation>' +
- '</children>' +
- '</cell>' +
- '<cell role="table" id="12">' +
- '<children>' +
- '<number role="integer" font="normal" id="11">2</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '<row role="table" id="23">' +
- '<children>' +
- '<cell role="table" id="18">' +
- '<children>' +
- '<infixop role="implicit" id="17">\u2062' +
- '<content>' +
- '<operator role="multiplication" id="16">\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<identifier role="latinletter" font="normal" id="14">x</identifier>' +
- '<identifier role="latinletter" font="normal" id="15">y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</cell>' +
- '<cell role="table" id="20">' +
- '<children>' +
- '<relation role="equality" id="19">=</relation>' +
- '</children>' +
- '</cell>' +
- '<cell role="table" id="22">' +
- '<children>' +
- '<number role="integer" font="normal" id="21">6</number>' +
- '</children>' +
- '</cell>' +
- '</children>' +
- '</row>' +
- '</children>' +
- '</table>');
-});
-
-
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeLimitFunctions', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><munder><mi>lim</mi><mrow><mi>x</mi><mo>\u2192</mo>' +
- '<mi>\u221E</mi></mrow></munder><mo>(</mo><mi>x</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>lim</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>+</mo><munder><mi>lim</mi><mrow><mi>x</mi>' +
- '<mo>\u2192</mo><mi>\u221E</mi></mrow></munder><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo><mo>+</mo><mi>b</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>lim</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><msup><munder><mi>lim</mi><mrow><mi>x</mi><mo>\u2192</mo>' +
- '<mi>\u221E</mi></mrow></munder><mo>+</mo></msup><mo>(</mo><mi>x</mi>' +
- '<mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limupper>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>lim</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<operator>+</operator>' +
- '</children>' +
- '</limupper>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><munderover><mi>lim</mi><mo>\u2015</mo><mrow><mi>x</mi>' +
- '<mo>\u2192</mo><mi>\u221E</mi></mrow></munderover><mo>(</mo>' +
- '<mi>x</mi><mo>)</mo></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<function>lim</function>' +
- '<punctuation>\u2015</punctuation>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limboth>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mrow><munder><mi>liminf</mi><mrow><mi>x</mi><mo>\u2192</mo>' +
- '<mi>\u221E</mi></mrow></munder><mo>(</mo><mi>x</mi><mo>)</mo>' +
- '<mo>+</mo><munder><mi>limsup</mi><mrow><mi>y</mi><mo>\u2192</mo>' +
- '<mi>\u221E</mi></mrow></munder><mo>(</mo><mi>y</mi><mo>)</mo></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>liminf</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>limsup</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<fenced>' +
- '<content>' +
- '<fence>(</fence>' +
- '<fence>)</fence>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</fenced>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><mi>a</mi><mo>+</mo><munder><mi>lim</mi><mrow><mi>x</mi>' +
- '<mo>\u2192</mo><mi>\u221E</mi></mrow></munder><mi>x</mi><mo>+</mo>' +
- '<mi>b</mi></mrow>',
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>a</identifier>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>lim</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</appl>' +
- '<identifier>b</identifier>' +
- '</children>' +
- '</infixop>');
-
- this.executeTreeTest(
- '<mrow><munder><mi>lim</mi><mrow><mi>x</mi><mo>\u2192</mo><mi>\u221E</mi>' +
- '</mrow></munder><mi>lim</mi><munder><mrow><mi>y</mi><mo>\u2192</mo>' +
- '<mi>\u221E</mi></mrow></munder><mi>x</mi><mi>y</mi></mrow>',
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<function>lim</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>lim</function>' +
- '<infixop>\u2062' +
- '<content>' +
- '<operator>\u2062</operator>' +
- '</content>' +
- '<children>' +
- '<underscore>' +
- '<children>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>y</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</underscore>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</appl>');
-
- this.executeTreeTest(
- '<mi>liminf</mi>',
- '<function>liminf</function>');
-
- this.executeTreeTest(
- '<munder><mi>lim</mi><mrow><mi>x</mi><mo>\u2192</mo><mi>\u221E</mi>' +
- '</mrow></munder>',
- '<limlower>' +
- '<children>' +
- '<function>lim</function>' +
- '<relseq>\u2192' +
- '<content>' +
- '<relation>\u2192</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>');
-
- this.executeTreeTest(
- '<mi>liminf</mi><mo>+</mo><mi>limsup</mi><mo>=</mo><mi>lim</mi>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>liminf</function>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>limsup</function>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</infixop>' +
- '<appl>' +
- '<content>' +
- '<punctuation>\u2061</punctuation>' +
- '</content>' +
- '<children>' +
- '<function>lim</function>' +
- '<empty/>' +
- '</children>' +
- '</appl>' +
- '</children>' +
- '</relseq>');
-});
-
-
-/**
- * Variations of big operators.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeBigOps', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mrow><munderover><mi>\u2211</mi><mrow><mi>n</mi><mo>=</mo><mn>0</mn>' +
- '</mrow><mi>\u221E</mi></munderover><msup><mi>n</mi><mn>2</mn>' +
- '</msup></mrow>',
- '<bigop>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u2211</largeop>' +
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>n</identifier>' +
- '<number>0</number>' +
- '</children>' +
- '</relseq>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</limboth>' +
- '<superscript>' +
- '<children>' +
- '<identifier>n</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</bigop>');
-
- this.executeTreeTest(
- '<mrow><munderover><mi>\u2211</mi><mrow><mi>n</mi><mo>=</mo><mn>0</mn>' +
- '</mrow><mi>\u221E</mi></munderover><munderover><mi>\u2211</mi><mrow>' +
- '<mi>m</mi><mo>=</mo><mn>0</mn></mrow><mi>\u221E</mi></munderover><msup>' +
- '<mi>n</mi><mn>m</mn></msup></mrow>',
- '<bigop>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u2211</largeop>' +
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>n</identifier>' +
- '<number>0</number>' +
- '</children>' +
- '</relseq>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</limboth>' +
- '<bigop>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u2211</largeop>' +
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>m</identifier>' +
- '<number>0</number>' +
- '</children>' +
- '</relseq>' +
- '<identifier>\u221E</identifier>' +
- '</children>' +
- '</limboth>' +
- '<superscript>' +
- '<children>' +
- '<identifier>n</identifier>' +
- '<identifier>m</identifier>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</bigop>' +
- '</children>' +
- '</bigop>');
-
- this.executeTreeTest(
- '<mrow><munder><mi>\u2211</mi><mrow><mi>n</mi><mo>=</mo><mn>0</mn></mrow>' +
- '</munder><msup><mi>n</mi><mn>2</mn></msup></mrow>',
- '<bigop>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<largeop>\u2211</largeop>' +
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<identifier>n</identifier>' +
- '<number>0</number>' +
- '</children>' +
- '</relseq>' +
- '</children>' +
- '</limlower>' +
- '<superscript>' +
- '<children>' +
- '<identifier>n</identifier>' +
- '<number>2</number>' +
- '</children>' +
- '</superscript>' +
- '</children>' +
- '</bigop>');
-});
-
-
-
-/**
- * Variations of integrals.
- */
-TEST_F('CvoxSemanticTreeUnitTest', 'StreeIntegrals', function() {
- this.brief = true;
- this.executeTreeTest(
- '<mi>\u222B</mi>',
- '<largeop>\u222B</largeop>');
-
- this.executeTreeTest(
- '<mi>\u222B</mi><mi>dx</mi>',
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<empty/>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>');
-
- this.executeTreeTest(
- '<mrow><mi>\u222B</mi><mi>x</mi><mi>dx</mi></mrow>',
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<identifier>x</identifier>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>');
-
- this.executeTreeTest(
- '<mrow><mi>\u222B</mi><mi>x</mi><mi>d</mi><mi>x</mi></mrow>',
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<identifier>x</identifier>' +
- '<punctuated>' +
- '<content>' +
- '<punctuation>\u2063</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>d</identifier>' +
- '<punctuation>\u2063</punctuation>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</integral>');
-
- this.executeTreeTest(
- '<mrow><mi>\u222B</mi><mi>x</mi><mo>+' +
- '</mo><mi>y</mi><mi>d</mi><mi>x</mi></mrow>',
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<identifier>x</identifier>' +
- '<identifier>y</identifier>' +
- '</children>' +
- '</infixop>' +
- '<punctuated>' +
- '<content>' +
- '<punctuation>\u2063</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>d</identifier>' +
- '<punctuation>\u2063</punctuation>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</integral>');
-
- this.executeTreeTest(
- '<munderover><mi>\u222B</mi><mn>0</mn><mn>10</mn></munderover>',
- '<limboth>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<number>0</number>' +
- '<number>10</number>' +
- '</children>' +
- '</limboth>');
-
- this.executeTreeTest(
- '<munder><mi>\u222B</mi><mn>X</mn></munder>',
- '<limlower>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<identifier>X</identifier>' +
- '</children>' +
- '</limlower>');
-
- this.executeTreeTest(
- '<munderover><mi>\u222B</mi><mn>0</mn><mn>10</mn></munderover><mi>x</mi>' +
- '<mi>d</mi><mi>x</mi>',
- '<integral>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<number>0</number>' +
- '<number>10</number>' +
- '</children>' +
- '</limboth>' +
- '<identifier>x</identifier>' +
- '<punctuated>' +
- '<content>' +
- '<punctuation>\u2063</punctuation>' +
- '</content>' +
- '<children>' +
- '<identifier>d</identifier>' +
- '<punctuation>\u2063</punctuation>' +
- '<identifier>x</identifier>' +
- '</children>' +
- '</punctuated>' +
- '</children>' +
- '</integral>');
-
- this.executeTreeTest(
- '<munder><mi>\u222B</mi><mn>X</mn></munder><mi>x</mi><mi>dx</mi>',
- '<integral>' +
- '<children>' +
- '<limlower>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<identifier>X</identifier>' +
- '</children>' +
- '</limlower>' +
- '<identifier>x</identifier>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>');
-
- this.executeTreeTest(
- '<munderover><mi>\u222B</mi><mn>0</mn><mn>10</mn></munderover><mi>x</mi>' +
- '<mi>dx</mi><mo>+</mo><munderover><mi>\u222B</mi><mn>10</mn><mn>20</mn>' +
- '</munderover><mi>x</mi><mi>dx</mi><mo>=</mo><munderover><mi>\u222B</mi>' +
- '<mn>0</mn><mn>20</mn></munderover><mi>x</mi><mi>dx</mi>',
- '<relseq>=' +
- '<content>' +
- '<relation>=</relation>' +
- '</content>' +
- '<children>' +
- '<infixop>+' +
- '<content>' +
- '<operator>+</operator>' +
- '</content>' +
- '<children>' +
- '<integral>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<number>0</number>' +
- '<number>10</number>' +
- '</children>' +
- '</limboth>' +
- '<identifier>x</identifier>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>' +
- '<integral>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<number>10</number>' +
- '<number>20</number>' +
- '</children>' +
- '</limboth>' +
- '<identifier>x</identifier>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>' +
- '</children>' +
- '</infixop>' +
- '<integral>' +
- '<children>' +
- '<limboth>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<number>0</number>' +
- '<number>20</number>' +
- '</children>' +
- '</limboth>' +
- '<identifier>x</identifier>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>' +
- '</children>' +
- '</relseq>');
-
- this.executeTreeTest(
- '<mi>\u222B</mi><mi>\u222B</mi><mi>\u222B</mi>' +
- '<mi>dx</mi><mi>dy</mi><mi>dz</mi>',
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<integral>' +
- '<children>' +
- '<largeop>\u222B</largeop>' +
- '<empty/>' +
- '<identifier>dx</identifier>' +
- '</children>' +
- '</integral>' +
- '<identifier>dy</identifier>' +
- '</children>' +
- '</integral>' +
- '<identifier>dz</identifier>' +
- '</children>' +
- '</integral>');
-});
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
deleted file mode 100644
index 8d996874372..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_semantic_util.js
+++ /dev/null
@@ -1,135 +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 Utility functions for semantic tree computations.
- */
-
-goog.provide('cvox.SemanticUtil');
-
-
-/**
- * @constructor
- */
-cvox.SemanticUtil = function() { };
-
-
-/**
- * Merges keys of objects into an array.
- * @param {...Object<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);
- var keys = [];
- return keys.concat.apply(keys, objects.map(Object.keys));
-};
-
-
-/**
- * Merges values of objects into an array.
- * @param {...Object<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);
- var result = [];
- var collectValues = function(obj) {
- for (var key in obj) {
- result.push(obj[key]);
- }
- };
- objects.forEach(collectValues);
- return result;
-};
-
-
-/**
- * Transforms a unicode character into numeric representation. Returns null if
- * the input string is not a valid unicode character.
- * @param {string} unicode Character.
- * @return {?number} The decimal representation if it exists.
- */
-cvox.SemanticUtil.unicodeToNumber = function(unicode) {
- if (!unicode || unicode.length > 2) {
- return null;
- }
- // Treating surrogate pairs.
- if (unicode.length == 2) {
- var hi = unicode.charCodeAt(0);
- var low = unicode.charCodeAt(1);
- if (0xD800 <= hi && hi <= 0xDBFF && !isNaN(low)) {
- return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
- }
- return null;
- }
- return unicode.charCodeAt(0);
-};
-
-
-/**
- * Transforms a numberic representation of a unicode character into its
- * corresponding string.
- * @param {number} number Unicode point.
- * @return {string} The string representation.
- */
-cvox.SemanticUtil.numberToUnicode = function(number) {
- if (number >= 0x10000) {
- var hi = (number - 0x10000) / 0x0400 + 0xD800;
- var lo = (number - 0x10000) % 0x0400 + 0xDC00;
- return String.fromCharCode(hi, lo);
- }
- return String.fromCharCode(number);
-};
-
-
-/**
- * Returns the tagname of an element node in upper case.
- * @param {Element} node The node.
- * @return {string} The node's tagname.
- */
-cvox.SemanticUtil.tagName = function(node) {
- return node.tagName.toUpperCase();
-};
-
-
-/**
- * List of MathML Tags that are to be ignored.
- * @type {Array<string>}
- * @const
- */
-cvox.SemanticUtil.IGNORETAGS = [
- 'MERROR', 'MPHANTOM', 'MSPACE', 'MACTION', 'MALIGNGROUP', 'MALIGNMARK',
- 'MACTION'
-];
-
-
-/**
- * List of MathML Tags to be ignore if they have no children.
- * @type {Array<string>}
- * @const
- */
-cvox.SemanticUtil.EMPTYTAGS = ['MATH', 'MROW', 'MPADDED', 'MSTYLE'];
-
-
-/**
- * Removes elements from a list of MathML nodes that are either to be ignored or
- * 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.
- */
-cvox.SemanticUtil.purgeNodes = function(nodes) {
- var nodeArray = [];
- for (var i = 0, node; node = nodes[i]; i++) {
- var tagName = cvox.SemanticUtil.tagName(node);
- if (cvox.SemanticUtil.IGNORETAGS.indexOf(tagName) != -1) continue;
- if (cvox.SemanticUtil.EMPTYTAGS.indexOf(tagName) != -1 &&
- node.childNodes.length == 0)
- continue;
- nodeArray.push(node);
- }
- return 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
deleted file mode 100644
index 4de27ae3913..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/math_util.js
+++ /dev/null
@@ -1,263 +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 DOM utility functions to aid in math expressions navigation.
- */
-
-goog.provide('cvox.MathUtil');
-
-goog.require('cvox.ChromeVox');
-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.
- * @return {boolean} True if node has a tag name included in tags.
- */
-cvox.MathUtil.isMathmlNodeOfClass_ = function(node, tags) {
- return tags.indexOf(node.tagName.toUpperCase()) != -1;
-};
-
-
-/**
- * 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.
- * @return {boolean} True if node has a tag name included in tags.
- */
-cvox.MathUtil.isMathjaxNodeOfClass_ = function(node, tags) {
- if (node.tagName == 'SPAN') {
- var classes = node.className.split(' ');
- return classes.some(function(x)
- {return tags.indexOf(x.toUpperCase()) != -1;});
- }
- return false;
-};
-
-
-/**
- * Checks if a node is an element node that belongs to a given class
- * of MathML or MathJax nodes.
- * @private
- * @param {!Node} node The node to test.
- * @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) {
- return (node.nodeType == Node.ELEMENT_NODE &&
- (cvox.MathUtil.isMathmlNodeOfClass_(node, tags) ||
- cvox.MathUtil.isMathjaxNodeOfClass_(node, tags)));
-};
-
-
-/**
- * Array of MathML Token Elements.
- * @type {!Array<string>}
- */
-cvox.MathUtil.TOKEN_LIST = ['MI', 'MN', 'MO', 'MTEXT', 'MSPACE', 'MS'];
-
-
-/**
- * Checks if an element of a math expression is a Token Element.
- * Token elements are the following:
- * <mi> identifier.
- * <mn> number.
- * <mo> operator, fence, or separator.
- * <mtext> text.
- * <mspace> space.
- * <ms> string literal.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a token.
- */
-cvox.MathUtil.isToken = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.TOKEN_LIST);
-};
-
-
-/**
- * Array of MathML Layout Schemata.
- * @type {!Array<string>}
- */
-cvox.MathUtil.LAYOUT_LIST = ['MROW', 'MFRAC', 'MSQRT', 'MROOT', 'MSTYLE',
- 'MERROR', 'MPADDED', 'MPHANTOM', 'MFENCED',
- 'MENCLOSE'];
-
-
-/**
- * Checks if an element of a math expression is a Layout Schema.
- * Layout elements are the following:
- * <mrow> group any number of sub-expressions horizontally
- * <mfrac> form a fraction from two sub-expressions
- * <msqrt> form a square root (radical without an index)
- * <mroot> form a radical with specified index
- * <mstyle> style change
- * <merror> enclose a syntax error message from a preprocessor
- * <mpadded> adjust space around content
- * <mphantom> make content invisible but preserve its size
- * <mfenced> surround content with a pair of fences
- * <menclose> enclose content with a stretching symbol such as a long
- * division sign.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a layout schema.
- */
-cvox.MathUtil.isLayout = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.LAYOUT_LIST);
-};
-
-
-/**
- * Array of MathML Script Schemata.
- * @type {!Array<string>}
- */
-cvox.MathUtil.SCRIPT_LIST = ['MSUB', 'MSUP', 'MSUBSUP', 'MUNDER', 'MOVER',
- 'MUNDEROVER', 'MMULTISCRIPTS', 'MPRESCRIPTS'];
-
-
-/**
- * Checks if an element of a math expression is a Script Schema.
- * Script elements are the following:
- * <msub> attach a subscript to a base.
- * <msup> attach a superscript to a base.
- * <msubsup> attach a subscript-superscript pair to a base.
- * <munder> attach an underscript to a base.
- * <mover> attach an overscript to a base.
- * <munderover> attach an underscript-overscript pair to a base.
- * <mmultiscripts> attach prescripts and tensor indices to a base.
- * Prescripts are optional.
- * <mprescripts> two elements prescripts of mmultiscripts. Only makes sense
- * in that environment (although not illegal outside)! Two
- * arguments mandatory (can be <none/>).
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a script schema.
- */
-cvox.MathUtil.isScript = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.SCRIPT_LIST);
-};
-
-
-/**
- * Array of MathML Table and Matrix tokens.
- * @type {!Array<string>}
- */
-cvox.MathUtil.TABLES_LIST = ['MTABLE', 'MLABELEDTR', 'MTR', 'MTD',
- 'MALIGNGROUP', 'MALIGNMARK'];
-
-
-/**
- * Checks if an element of a math expression is a Tables Schema.
- * Tables elements are the following:
- * <mtable> table or matrix.
- * <mlabeledtr> row in a table or matrix with a label or equation number.
- * <mtr> row in a table or matrix.
- * <mtd> one entry in a table or matrix.
- * <maligngroup> and
- * <malignmark> alignment markers.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a tables schema.
- */
-cvox.MathUtil.isTables = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element, cvox.MathUtil.TABLES_LIST);
-};
-
-
-/**
- * Array of MathML Elementary Layout Schemata.
- * @type {!Array<string>}
- */
-cvox.MathUtil.ELEMENTARY_LIST = ['MSTACK', 'MLONGDIV', 'MSGROUP', 'MSROW',
- 'MSCARRIES', 'MSCARRY', 'MSLINE'];
-
-
-/**
- * Checks if an element of a math expression is a Elementary Schema.
- * Elementary elements are the following:
- * <mstack> columns of aligned characters.
- * <mlongdiv> similar to msgroup, with the addition of a divisor and result.
- * <msgroup> a group of rows in an mstack that are shifted by similar amounts.
- * <msrow> a row in an mstack.
- * <mscarries> row in an mstack that whose contents represent carries
- * or borrows.
- * <mscarry> one entry in an mscarries.
- * <msline> horizontal line inside of mstack.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a elementary schema.
- */
-cvox.MathUtil.isElementary = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element,
- cvox.MathUtil.ELEMENTARY_LIST);
-};
-
-
-/**
- * Array of all valid tags in a MathML expression.
- * This is a union of all other token lists.
- * @type {!Array<string>}
- */
-cvox.MathUtil.MATHML_TAG_LIST = [cvox.MathUtil.TOKEN_LIST,
- cvox.MathUtil.LAYOUT_LIST,
- cvox.MathUtil.SCRIPT_LIST,
- cvox.MathUtil.TABLES_LIST,
- cvox.MathUtil.ELEMENTARY_LIST].reduce(
- function(x, y) { return x.concat(y); });
-
-
-/**
- * Checks if a node is valid element of a MathML expression.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element has a valid MathML tag.
- */
-cvox.MathUtil.isMathmlTag = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element,
- cvox.MathUtil.MATHML_TAG_LIST);
-};
-
-
-/**
- * Array of MathML Whitespace and Alignment tokens.
- * These are elements that can occur in the other token lists.
- * @type {!Array<string>}
- */
-cvox.MathUtil.WHITESPACE_LIST = ['MSROW', 'MROW', 'MSPACE',
- 'MPHANTOM', 'MPADDED'];
-
-
-/**
- * Checks if an element of a math expression is whitespace or an
- * alignment marker.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a whitespace node.
- */
-cvox.MathUtil.isWhitespace = function(element) {
- return cvox.MathUtil.isMathNodeOfClass_(element,
- cvox.MathUtil.WHITESPACE_LIST);
-};
-
-
-/**
- * Checks if an element of a math expression is a legal mathml markup element
- * but not a whitespace or an alignment marker.
- * @param {!Node} element The element of the math expression.
- * @return {boolean} True if element is a non-whitespace node.
- */
-cvox.MathUtil.isNotWhitespace = function(element) {
- return (cvox.MathUtil.isMathmlTag(element) &&
- !cvox.MathUtil.isWhitespace(element));
-};
-
-
-/**
- * Computes the union of two arrays (not in a strictly set theoretical sense
- * as all duplicate elements in either array still remain as duplicates!).
- * @param {Array} a An array.
- * @param {Array} b Another array.
- * @return {Array} Union of a and b.
- */
-cvox.MathUtil.union = function(a, b) {
- return a.concat(b.filter(function(x) {return a.indexOf(x) < 0;}));
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/media_widget.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/media_widget.js
deleted file mode 100644
index 7b6dd05ed89..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/media_widget.js
+++ /dev/null
@@ -1,91 +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.
-
-goog.provide('cvox.ChromeVoxHTMLMediaWidget');
-
-/**
- * @fileoverview Gives the user spoken feedback as they interact with the HTML5
- * media widgets (<video> and <audio>) + makes the widget keyboard accessible.
- *
- */
-
-/**
- * A class containing the information needed to speak
- * a media element to the user.
- *
- * @constructor
- * @param {Element} mediaElem The media widget element.
- * @param {cvox.TtsInterface} tts The TTS object from ChromeVox.
- */
-cvox.ChromeVoxHTMLMediaWidget = function(mediaElem, tts){
- var self = this;
- this.mediaElem_ = mediaElem;
- this.mediaTts_ = tts;
-
- this.keyListener_ = function(evt) {
- self.eventHandler_(evt);
- }
- this.blurListener_ = function(evt) {
- self.shutdown();
- }
-
- this.mediaElem_.addEventListener('keydown', this.keyListener_, false);
- this.mediaElem_.addEventListener('keyup', this.keyListener_, false);
- this.mediaElem_.addEventListener('blur', this.blurListener_, false);
-};
-
-/**
- * Removes the key listeners for the media widget.
- */
-cvox.ChromeVoxHTMLMediaWidget.prototype.shutdown = function() {
- this.mediaElem_.removeEventListener('blur', this.blurListener_, false);
- this.mediaElem_.removeEventListener('keydown', this.keyListener_, false);
- this.mediaElem_.removeEventListener('keyup', this.keyListener_, false);
-};
-
-cvox.ChromeVoxHTMLMediaWidget.prototype.jumpToTime_ = function(targetTime) {
- if (targetTime < 0) {
- targetTime = 0;
- }
- if (targetTime > this.mediaElem_.duration) {
- targetTime = this.mediaElem_.duration;
- }
- this.mediaElem_.currentTime = targetTime;
-};
-
-cvox.ChromeVoxHTMLMediaWidget.prototype.setVolume_ = function(targetVolume) {
- if (targetVolume < 0) {
- targetVolume = 0;
- }
- if (targetVolume > 1.0) {
- targetVolume = 1.0;
- }
- this.mediaElem_.volume = targetVolume;
-};
-
-/**
- * Adds basic keyboard handlers to the media widget.
- */
-cvox.ChromeVoxHTMLMediaWidget.prototype.eventHandler_ = function(evt) {
- if (evt.type == 'keydown') {
- // Space/Enter for play/pause toggle.
- if ((evt.keyCode == 13) || (evt.keyCode == 32)) {
- if (this.mediaElem_.paused){
- this.mediaElem_.play();
- } else {
- this.mediaElem_.pause();
- }
- } else if (evt.keyCode == 39) { // Right - FF
- this.jumpToTime_(
- this.mediaElem_.currentTime + (this.mediaElem_.duration/10));
- } else if (evt.keyCode == 37) { // Left - REW
- this.jumpToTime_(
- this.mediaElem_.currentTime - (this.mediaElem_.duration/10));
- } else if (evt.keyCode == 38) { // Up - Vol. Up
- this.setVolume_(this.mediaElem_.volume + .1);
- } else if (evt.keyCode == 40) { // Down - Vol. Down
- this.setVolume_(this.mediaElem_.volume - .1);
- }
- }
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js
deleted file mode 100644
index 0ac3f6386ac..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/memoize.js
+++ /dev/null
@@ -1,133 +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 Provides a system for memoizing computations applied to
- * DOM nodes within the same call stack.
- *
- * To make a function memoizable - suppose you have a function
- * isAccessible that takes a node and returns a boolean:
- *
- * function isAccessible(node) {
- * return expensiveComputation(node);
- * }
- *
- * Make it memoizable like this:
- *
- * function isAccessible(node) {
- * return cvox.Memoize.memoize(computeIsAccessible_, 'isAccessible', node);
- * }
- *
- * function computeIsAccessible_(node) {
- * return expensiveComputation(node);
- * }
- *
- * To take advantage of memoization, you need to wrap a sequence of
- * computations in a call to memoize.scope() - memoization is only
- * enabled while in that scope, and all cached data is thrown away at
- * the end. You should use this only when you're sure the computation
- * being memoized will not change within the scope.
- *
- * cvox.Memoize.scope(function() {
- * console.log(isAccessible(document.body));
- * });
- *
- */
-
-
-goog.provide('cvox.Memoize');
-
-
-/**
- * Create the namespace.
- * @constructor
- */
-cvox.Memoize = function() {
-};
-
-/**
- * The cache: a map from string function name to a WeakMap from DOM node
- * 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<WeakMap<Node, *> >}
- * @private
- */
-cvox.Memoize.nodeMap_ = null;
-
-/**
- * Keeps track of how many nested times scope() has been called.
- * @type {number}
- * @private
- */
-cvox.Memoize.scopeCount_ = 0;
-
-
-/**
- * Enables memoization within the scope of the given function. You should
- * ensure that the DOM is not modified within this scope.
- *
- * It's safe to nest calls to scope. The nested calls have
- * no effect, only the outermost one.
- *
- * @param {Function} functionScope The function to call with memoization
- * enabled.
- * @return {*} The value returned by |functionScope|.
- */
-cvox.Memoize.scope = function(functionScope) {
- var result;
- try {
- cvox.Memoize.scopeCount_++;
- if (cvox.Memoize.scopeCount_ == 1) {
- cvox.Memoize.nodeMap_ = {};
- }
- result = functionScope();
- } finally {
- cvox.Memoize.scopeCount_--;
- if (cvox.Memoize.scopeCount_ == 0) {
- cvox.Memoize.nodeMap_ = null;
- }
- }
- return result;
-};
-
-/**
- * Memoizes the result of a function call, so if you call this again
- * with the same exact parameters and memoization is currently enabled
- * (via a call to scope()), the second time the cached result
- * will just be returned directly.
- *
- * @param {Function} functionClosure The function to call and cache the
- * result of.
- * @param {string} functionName The name of the function you're calling.
- * This string is used to store and retrieve the cached result, so
- * it should be unique. If the function to be memoized takes simple
- * arguments in addition to a DOM node, you can incorporate those
- * arguments into the function name.
- * @param {Node} node The DOM node that should be passed as the argument
- * to the function.
- * @return {*} The return value of |functionClosure|.
- */
-cvox.Memoize.memoize = function(functionClosure, functionName, node) {
- if (cvox.Memoize.nodeMap_ &&
- cvox.Memoize.nodeMap_[functionName] === undefined) {
- cvox.Memoize.nodeMap_[functionName] = new WeakMap();
- }
-
- // If we're not in scope, just call the function directly.
- if (!cvox.Memoize.nodeMap_) {
- return functionClosure(node);
- }
-
- var result = cvox.Memoize.nodeMap_[functionName].get(node);
- if (result === undefined) {
- result = functionClosure(node);
- if (result === undefined) {
- throw 'A memoized function cannot return undefined.';
- }
- cvox.Memoize.nodeMap_[functionName].set(node, result);
- }
-
- return result;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/msgs.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/msgs.js
deleted file mode 100644
index 8a9628e1d46..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/msgs.js
+++ /dev/null
@@ -1,161 +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 Defines methods related to retrieving translated messages.
- */
-
-goog.provide('Msgs');
-
-/**
- * @constructor
- */
-Msgs = function() {};
-
-/**
- * The namespace for all Chromevox messages.
- * @type {string}
- * @const
- * @private
- */
-Msgs.NAMESPACE_ = 'chromevox_';
-
-/**
- * Dictionary of locale names.
- * @type {Object<string>}
- * @private
- */
-Msgs.localeNameDict_ = null;
-
-/**
- * Return the current locale.
- * @return {string} The locale.
- */
-Msgs.getLocale = function() {
- return chrome.i18n.getMessage('locale');
-};
-
-/**
- * Returns the message with the given message id from the ChromeVox namespace.
- *
- * If we can't find a message, throw an exception. This allows us to catch
- * typos early.
- *
- * @param {string} messageId The id.
- * @param {Array<string>=} opt_subs Substitution strings.
- * @return {string} The localized message.
- */
-Msgs.getMsg = function(messageId, opt_subs) {
- var message = Msgs.Untranslated[messageId.toUpperCase()];
- if (message !== undefined)
- return message;
- message = chrome.i18n.getMessage(
- Msgs.NAMESPACE_ + messageId, opt_subs);
- if (message == undefined || message == '') {
- throw new Error('Invalid ChromeVox message id: ' + messageId);
- }
- return message;
-};
-
-/**
- * Processes an HTML DOM, replacing text content with translated text messages
- * on elements marked up for translation. Elements whose class attributes
- * contain the 'i18n' class name are expected to also have an msgid
- * attribute. The value of the msgid attributes are looked up as message
- * IDs and the resulting text is used as the text content of the elements.
- *
- * @param {Node} root The root node where the translation should be performed.
- */
-Msgs.addTranslatedMessagesToDom = function(root) {
- var elts = root.querySelectorAll('.i18n');
- for (var i = 0; i < elts.length; i++) {
- var msgid = elts[i].getAttribute('msgid');
- if (!msgid) {
- throw new Error('Element has no msgid attribute: ' + elts[i]);
- }
- elts[i].textContent = this.getMsg(msgid);
- elts[i].classList.add('i18n-processed');
- }
-};
-
-/**
- * Retuns a number formatted correctly.
- *
- * @param {number} num The number.
- * @return {string} The number in the correct locale.
- */
-Msgs.getNumber = function(num) {
- return '' + num;
-};
-
-/**
- * Gets a localized display name for a locale.
- * NOTE: Only a subset of locale identifiers are supported. See the
- * |CHROMEVOX_LOCALE_DICT| message.
- * @param {string} locale On the form |ll| or |ll_CC|, where |ll| is
- * the language code and |CC| the country code.
- * @return {string} The display name.
- */
-Msgs.getLocaleDisplayName = function(locale) {
- if (!Msgs.localeNameDict_) {
- Msgs.localeNameDict_ = /** @type {!Object<string>} */(
- JSON.parse(this.getMsg('locale_dict')));
- }
- var name = Msgs.localeNameDict_[locale];
- if (!name) {
- throw Error('Unsupported locale identifier: ' + locale);
- }
- return name;
-};
-
-/**
- * Strings that are displayed in the user interface but don't need
- * be translated.
- * @type {Object<string>}
- */
-Msgs.Untranslated = {
- /** The unchecked state for a checkbox in braille. */
- CHECKBOX_UNCHECKED_STATE_BRL: '( )',
- /** The checked state for a checkbox in braille. */
- CHECKBOX_CHECKED_STATE_BRL: '(x)',
- /** The unselected state for a radio button in braille. */
- RADIO_UNSELECTED_STATE_BRL: '( )',
- /** The selected state for a radio button in braille. */
- RADIO_SELECTED_STATE_BRL: '(x)',
- /** Brailled after a menu if the menu has a submenu. */
- ARIA_HAS_SUBMENU_BRL: '->',
- /** Describes an element with the ARIA role option. */
- ROLE_OPTION: ' ',
- /** Braille of element with the ARIA role option. */
- ROLE_OPTION_BRL: ' ',
- /** Braille of element with the ARIA attribute aria-checked=true. */
- ARIA_CHECKED_TRUE_BRL: '(x)',
- /** Braille of element with the ARIA attribute aria-checked=false. */
- ARIA_CHECKED_FALSE_BRL: '( )',
- /** Braille of element with the ARIA attribute aria-checked=mixed. */
- ARIA_CHECKED_MIXED_BRL: '(-)',
- /** Braille of element with the ARIA attribute aria-disabled=true. */
- ARIA_DISABLED_TRUE_BRL: 'xx',
- /** Braille of element with the ARIA attribute aria-expanded=true. */
- ARIA_EXPANDED_TRUE_BRL: '-',
- /** Braille of element with the ARIA attribute aria-expanded=false. */
- ARIA_EXPANDED_FALSE_BRL: '+',
- /** Braille of element with the ARIA attribute aria-invalid=true. */
- ARIA_INVALID_TRUE_BRL: '!',
- /** Braille of element with the ARIA attribute aria-pressed=true. */
- ARIA_PRESSED_TRUE_BRL: '=',
- /** Braille of element with the ARIA attribute aria-pressed=false. */
- ARIA_PRESSED_FALSE_BRL: ' ',
- /** Braille of element with the ARIA attribute aria-pressed=mixed. */
- ARIA_PRESSED_MIXED_BRL: '-',
- /** Braille of element with the ARIA attribute aria-selected=true. */
- ARIA_SELECTED_TRUE_BRL: '(x)',
- /** Braille of element with the ARIA attribute aria-selected=false. */
- ARIA_SELECTED_FALSE_BRL: '( )',
- /** Brailled after a menu if it has a submenu. */
- HAS_SUBMENU_BRL: '->',
- /** Brailled to describe a &lt;time&gt; tag. */
- TAG_TIME_BRL: ' ',
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js
deleted file mode 100644
index a158b5746c8..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_description.js
+++ /dev/null
@@ -1,163 +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 description of a
- * navigation from one object to another.
- *
- */
-
-
-goog.provide('cvox.NavDescription');
-
-goog.require('cvox.AbstractTts');
-goog.require('cvox.ChromeVox');
-goog.require('cvox.CursorSelection');
-goog.require('cvox.QueueMode');
-
-/**
- * A class representing the description of navigation from one object to
- * another.
- * @param {{context: (undefined|string),
- * text: (string),
- * userValue: (undefined|string),
- * annotation: (undefined|string),
- * earcons: (undefined|Array<cvox.Earcon>),
- * personality: (undefined|Object),
- * hint: (undefined|string),
- category: (undefined|string)}} kwargs The arguments for this
- * description.
- * context The context, for example descriptions of objects
- * that were crossed into, like "Toolbar" or "Menu Bar" or "List with
- * 5 items". This is all spoken with an annotation voice.
- * text The text of the object itself, including text from
- * titles, labels, etc.
- * userValue The text that the user has entered.
- * annotation The role and state of the object.
- * earcons A list of the earcon ids to play along
- * with the spoken description of this object.
- * personality Optional TTS personality to use for the text.
- * hint Optional Hint text (.e.g. aria-describedby).
- * category Optional category (for speech queueing behavior).
- * @constructor
- */
-cvox.NavDescription = function(kwargs) {
- this.context = kwargs.context ? kwargs.context : '';
- this.text = kwargs.text ? kwargs.text : '';
- this.userValue = kwargs.userValue ? kwargs.userValue : '';
- this.annotation = kwargs.annotation ? kwargs.annotation : '';
- this.earcons = kwargs.earcons ? kwargs.earcons : [];
- this.personality = kwargs.personality;
- this.hint = kwargs.hint ? kwargs.hint : '';
- this.category = kwargs.category ? kwargs.category : null;
-};
-
-
-/**
- * @return {boolean} true if this description is empty.
- */
-cvox.NavDescription.prototype.isEmpty = function() {
- return (this.context.length == 0 &&
- this.earcons.length == 0 &&
- this.text.length == 0 &&
- this.userValue.length == 0 &&
- this.annotation.length == 0);
-};
-
-
-/**
- * @return {string} A string representation of this object.
- */
-cvox.NavDescription.prototype.toString = function() {
- return 'NavDescription(context="' + this.context + '" ' +
- ' text="' + this.text + '" ' +
- ' userValue="' + this.userValue + '" ' +
- ' annotation="' + this.annotation +
- (this.category ? '" category="' + this.category + '")' : '') +
- '")';
-};
-
-
-/**
- * Modifies the earcon to play along with the spoken description of the object.
- * @param {cvox.Earcon} earconId An earcon id to be pushed on to the list of
- * earcon ids to play along with the spoken description of this object.
- */
-cvox.NavDescription.prototype.pushEarcon = function(earconId) {
- this.earcons.push(earconId);
-};
-
-
-/**
- * Speak this nav description with the given queue mode.
- * @param {cvox.QueueMode=} queueMode The queue mode.
- * @param {function()=} opt_startCallback Function called when this
- * starts speaking.
- * @param {function()=} opt_endCallback Function called when this ends speaking.
- */
-cvox.NavDescription.prototype.speak = function(
- queueMode, opt_startCallback, opt_endCallback) {
- /**
- * Return a deep copy of PERSONALITY_ANNOTATION for modifying.
- * @return {Object} The newly created properties object.
- */
- function makeAnnotationProps() {
- var properties = {};
- var src = cvox.AbstractTts.PERSONALITY_ANNOTATION;
- for (var key in src) {
- properties[key] = src[key];
- }
- return properties;
- }
-
- var speakArgs = new Array();
- if (this.context) {
- speakArgs.push([this.context, queueMode, makeAnnotationProps()]);
- queueMode = cvox.QueueMode.QUEUE;
- }
-
- speakArgs.push([this.text,
- queueMode,
- this.personality ? this.personality : {}]);
- queueMode = cvox.QueueMode.QUEUE;
-
- if (this.userValue) {
- speakArgs.push([this.userValue, queueMode, {}]);
- }
-
- if (this.annotation) {
- speakArgs.push([this.annotation, queueMode, makeAnnotationProps()]);
- }
-
- if (this.hint) {
- speakArgs.push([this.hint, queueMode, makeAnnotationProps()]);
- }
-
- var length = speakArgs.length;
- for (var i = 0; i < length; i++) {
- if (i == 0 && opt_startCallback) {
- speakArgs[i][2]['startCallback'] = opt_startCallback;
- }
- if (i == length - 1 && opt_endCallback) {
- speakArgs[i][2]['endCallback'] = opt_endCallback;
- }
- if (this.category) {
- speakArgs[i][2]['category'] = this.category;
- }
- cvox.ChromeVox.tts.speak.apply(cvox.ChromeVox.tts, speakArgs[i]);
- }
-};
-
-
-/**
- * Compares two NavDescriptions.
- * @param {cvox.NavDescription} that A NavDescription.
- * @return {boolean} True if equal.
- */
-cvox.NavDescription.prototype.equals = function(that) {
- return this.context == that.context &&
- this.text == that.text &&
- this.userValue == that.userValue &&
- this.annotation == that.annotation;
-};
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
deleted file mode 100644
index e76c6886804..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/nav_math_description.js
+++ /dev/null
@@ -1,48 +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 subclass of the navigation description container
- * specialising on math objects.
- *
- */
-
-
-goog.provide('cvox.NavMathDescription');
-
-goog.require('cvox.NavDescription');
-
-
-/**
- * Class specialising navigation descriptions for mathematics.
- * @param {{context: (undefined|string),
- * text: (string),
- * userValue: (undefined|string),
- * annotation: (undefined|string),
- * earcons: (undefined|Array<cvox.Earcon>),
- * personality: (undefined|Object),
- * hint: (undefined|string),
- * category: (undefined|string),
- * domain: (undefined|string),
- * style: (undefined|string)}} kwargs The arguments for
- * the specialised math navigationdescription. See arguments of nav
- * description plus the following:
- * domain Domain for translation.
- * style Style for translation.
- * @constructor
- * @extends {cvox.NavDescription}
- */
-cvox.NavMathDescription = function(kwargs) {
- goog.base(this, kwargs);
-
- var newPersonality = this.personality ? this.personality : {};
- var mathDescr = new Object();
-
- mathDescr['domain'] = kwargs.domain ? kwargs.domain : '';
- // TODO (sorge) Collate and document styles in an enum structure.
- mathDescr['style'] = kwargs.style ? kwargs.style : '';
- newPersonality['math'] = mathDescr;
- this.personality = newPersonality;
-};
-goog.inherits(cvox.NavMathDescription, cvox.NavDescription);
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js
deleted file mode 100644
index d7f97fec382..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/node_state.js
+++ /dev/null
@@ -1,52 +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 The cvox.NodeState typedef.
- */
-
-goog.provide('cvox.NodeState');
-goog.provide('cvox.NodeStateUtil');
-
-goog.require('Msgs');
-
-/**
- * Holds the state of a node. It is an Array or Arrays of strings and numbers.
- * Each sub array is in the format:
- * [state, opt_arg, opt_arg, ...]. These sub arrays map directly to a
- * cvox.ChromeVox.getMsg() call. For example [list_position, 3, 5] maps to
- * getMsg('list_position', [3, 5]);
- *
- * @typedef {!Array<!Array<string|number>>}
- */
-cvox.NodeState;
-
-/**
- * Returns a localized, readable string with the NodeState.
- *
- * NOTE(deboer): Once AriaUtil and DomUtil are using NodeState exclusively, this
- * function can be moved into DescriptionUtil, removing the cvox.ChromeVox
- * dependency here.
- *
- * @param {cvox.NodeState} state The node state.
- * @return {string} The readable state string.
- */
-cvox.NodeStateUtil.expand = function(state) {
- try {
- return state.map(function(s) {
- if (s.length < 1) {
- throw new Error('cvox.NodeState must have at least one entry');
- }
- var args = s.slice(1).map(function(a) {
- if (typeof a == 'number') {
- return Msgs.getNumber(a);
- }
- return a;
- });
- return Msgs.getMsg(/** @type {string} */ (s[0]), args);
- }).join(' ');
- } catch (e) {
- throw new Error('error: ' + e + ' state: ' + state);
- }
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js
deleted file mode 100644
index 7a46db20669..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection.js
+++ /dev/null
@@ -1,107 +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 class representing a DOM selection conveyed through
- * CursorSelection idioms.
- * A PageSelection is just a DOM selection. The class itself manages a single
- * CursorSelection that surrounds a fragment on the page. It also provides an
- * extend operation to either grow or shrink the selection given a
- * CursorSelection. The class handles correctly moving the internal
- * CursorSelection and providing immediate access to a full description of the
- * selection at any time.
- */
-
-goog.provide('cvox.PageSelection');
-
-goog.require('cvox.AbstractEarcons');
-goog.require('cvox.CursorSelection');
-goog.require('cvox.NavDescription');
-
-/**
- * @constructor
- * @param {!cvox.CursorSelection} sel The initial selection.
- */
-cvox.PageSelection = function(sel) {
- this.sel_ = sel.clone();
- this.sel_.select();
- this.wasBegin_ = true;
-};
-
-
-/**
- * Gets a description for the DOM selection during the course of navigation.
- * @param {cvox.AbstractShifter} navShifter Used to obtain walker-based
- * descriptions.
- * @param {!cvox.CursorSelection} prevSel Previous CursorSelection in
- * navigation.
- * @param {!cvox.CursorSelection} curSel Current CursorSelection in navigation.
- * @return {Array<cvox.NavDescription>} The new description.
- */
-cvox.PageSelection.prototype.getDescription =
- function(navShifter, prevSel, curSel) {
- var desc = [];
- if (this.sel_.isReversed() != curSel.isReversed()) {
- // A shrinking selection.
- desc = navShifter.getDescription(curSel, prevSel);
- desc[0].annotation = Msgs.getMsg('describe_unselected');
- desc[0].pushEarcon(cvox.Earcon.SELECTION_REVERSE);
- } else {
- // A growing selection.
- desc = navShifter.getDescription(prevSel, curSel);
- desc[0].annotation = Msgs.getMsg('describe_selected');
- desc[0].pushEarcon(cvox.Earcon.SELECTION);
- if (!this.wasBegin_ && this.sel_.absEquals(curSel.clone().normalize())) {
- // A selection has inverted across the start cursor. Describe it.
- var prevDesc = navShifter.getDescription(curSel, prevSel);
- prevDesc[0].annotation =
- Msgs.getMsg('describe_unselected');
- prevDesc[0].pushEarcon(cvox.Earcon.SELECTION_REVERSE);
- prevDesc[0].pushEarcon(cvox.Earcon.WRAP);
- desc = prevDesc.concat(desc);
- }
- }
- return desc;
-};
-
-
-/**
- * Gets a full description for the entire DOM selection.
- * Use this description when you want to describe the entire selection
- * represented by this instance.
- *
- * @return {Array<cvox.NavDescription>} The new description.
- */
-cvox.PageSelection.prototype.getFullDescription = function() {
- return [new cvox.NavDescription(
- {text: window.getSelection().toString(),
- context: Msgs.getMsg('selection_is')})];
-};
-
-
-/**
- * Extends this selection.
- * @param {!cvox.CursorSelection} sel Extend DOM selection to the selection.
- * @return {boolean} True if the extension occurred, false if the PageSelection
- * was reset to sel.
- */
-cvox.PageSelection.prototype.extend = function(sel) {
- if (!this.sel_.directedBefore(sel)) {
- // Do not allow for crossed selections. This restarts a page selection that
- // has been collapsed. This occurs when two CursorSelection's point away
- // from one another.
- this.sel_ = sel.clone();
- } else {
- // Otherwise, it is assumed that the CursorSelection's are in directed
- // document order. The CursorSelection's are either pointing in the same
- // direction or towards one another. In the first case, shrink/extend this
- // PageSelection to the end of "sel". In the second case, shrink/extend this
- // PageSelection to the start of "sel".
- this.sel_.end = this.sel_.isReversed() == sel.isReversed() ?
- sel.end.clone() : sel.start.clone();
- }
- this.sel_.select();
- this.wasBegin_ = false;
- return !this.sel_.absEquals(sel);
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection_test.unitjs
deleted file mode 100644
index 413b9292415..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/page_selection_test.unitjs
+++ /dev/null
@@ -1,143 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxPageSelectionUnitTest() {}
-
-CvoxPageSelectionUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.CursorSelection',
- 'cvox.PageSelection',
- ],
-
- /** @override */
- setUp: function() {
- this.loadDoc(function() {/*!
- <p id='p1'>The quick</p>
- <a id='a1' href='#'>brown fox</a>
- <h1 id='h1'>jumped over</h1>
- */});
- this.pSel = cvox.CursorSelection.fromNode($('p1'));
- this.pSel.start.index = 0;
- this.pSel.end.index = 1;
- this.aSel = cvox.CursorSelection.fromNode($('a1'));
- this.aSel.start.index = 0;
- this.aSel.end.index = 1;
- this.hSel = cvox.CursorSelection.fromNode($('h1'));
- this.hSel.start.index = 0;
- this.hSel.end.index = 1;
- },
-
- /**
- * Asserts a selection.
- * @param {string} str The expected contents of selection.
- * @private
- */
- assertSelection_: function(str) {
- assertEquals(str, window.getSelection().toString());
- }
-};
-
-TEST_F('CvoxPageSelectionUnitTest', 'BasicExtend', function() {
- var pageSel = new cvox.PageSelection(this.pSel);
- pageSel.extend(this.hSel);
- this.assertSelection_('The quick\n\nbrown fox\njumped over');
- this.hSel.end.node = this.hSel.end.node.firstChild;
- this.hSel.end.index = 6;
- pageSel.extend(this.hSel);
- this.assertSelection_('The quick\n\nbrown fox\njumped');
-});
-
-
-/** Tests a reverse extension. */
-TEST_F('CvoxPageSelectionUnitTest', 'ReverseExtend', function() {
- var pageSel = new cvox.PageSelection(this.pSel);
- this.assertSelection_('The quick');
- pageSel.extend(this.hSel);
- this.assertSelection_('The quick\n\nbrown fox\njumped over');
- pageSel.extend(this.aSel.setReversed(true));
- this.assertSelection_('The quick\n\nbrown fox');
- this.pSel.setReversed(true);
- pageSel.extend(this.pSel);
- this.assertSelection_('The quick');
- this.pSel.start.node = this.pSel.start.node.firstChild;
- this.pSel.start.index = 3;
- pageSel.extend(this.pSel);
- this.assertSelection_('The');
-});
-
-
-/** Tests all possible configurations of PageSelection's and extending
- * CursorSelection's.
- */
-TEST_F('CvoxPageSelectionUnitTest', 'ExtendDirections', function() {
- // A normal page selection, with a normal extension.
- var pageSel = new cvox.PageSelection(this.aSel);
- assertTrue(pageSel.extend(this.hSel));
-
- // A normal page selection, with a reversed extension.
- assertTrue(pageSel.extend(this.hSel.setReversed(true)));
-
- // A reversed page selection, with a normal cursor selection.
- var rPageSel = new cvox.PageSelection(this.aSel.setReversed(true));
- assertTrue(rPageSel.extend(this.pSel));
-
- // A reversed page selection, with a reversed extension.
- assertTrue(rPageSel.extend(this.pSel.setReversed(true)));
-});
-
-
-/** Tests degenerate extensions. */
-TEST_F('CvoxPageSelectionUnitTest', 'DegenerateExtensions', function() {
- var pageSel = new cvox.PageSelection(this.aSel);
-
- // A normal page selection, with a normal extension not in document order.
- assertFalse(pageSel.extend(this.pSel));
-
- // And, this causes a reset of page selection.
- assertTrue(pageSel.sel_.equals(this.pSel));
-
- // Reinitialize.
- pageSel = new cvox.PageSelection(this.aSel.setReversed(false));
-
- // A normal page selection, with a reversed extension not in document order.
- assertFalse(pageSel.extend(this.pSel.setReversed(true)));
-
- // And, again, it causes reset of page selection.
-assertTrue(pageSel.sel_.equals(this.pSel));
-
- // Reverse page selections.
- var rPageSel = new cvox.PageSelection(this.aSel.setReversed(true));
-
- // A reversed page selection, with a normal extension not in document order.
- assertFalse(rPageSel.extend(this.hSel));
- assertTrue(rPageSel.sel_.equals(this.hSel));
-
- // A reversed page selection, with a reversed extension not in document order.
- rPageSel = new cvox.PageSelection(this.aSel.setReversed(true));
- assertFalse(rPageSel.extend(this.hSel.setReversed(true)));
- assertTrue(rPageSel.sel_.equals(this.hSel));
-
- // And, finally, try extending to oneself in either direction.
- pageSel = new cvox.PageSelection(this.aSel.setReversed(false));
-
- // A normal page selection, with an extension to itself.
- assertFalse(pageSel.extend(this.aSel.setReversed(false)));
- assertFalse(pageSel.extend(this.aSel.setReversed(true)));
-
- // A reversed page selection, with an extension to itself.
- var rPageSel = new cvox.PageSelection(this.aSel.setReversed(true));
- assertFalse(rPageSel.extend(this.aSel.setReversed(true)));
- assertFalse(rPageSel.extend(this.aSel.setReversed(false)));
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/platform_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/platform_util.js
deleted file mode 100644
index c1c67ed3807..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/platform_util.js
+++ /dev/null
@@ -1,51 +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 Utilities for working with platforms.
- */
-
-
-goog.provide('cvox.PlatformFilter');
-goog.provide('cvox.PlatformUtil');
-
-goog.require('cvox.ChromeVox');
-
-/**
- * @enum
- */
-cvox.PlatformFilter = {
- NONE: 0,
- WINDOWS: 1,
- MAC: 2,
- LINUX: 4,
- WML: 7,
- CHROMEOS: 8,
- ANDROID: 16
-};
-
-
-/**
- *Checks whether the given filter matches the current platform. An undefined
- * filter always matches the current platform.
- * @param {undefined|cvox.PlatformFilter|number} filter The filter.
- * @return {boolean} Whether the filter matches the current platform.
- */
-cvox.PlatformUtil.matchesPlatform = function(filter) {
- var uA = navigator.userAgent;
- if (filter == undefined) {
- return true;
- } else if (uA.indexOf('Android') != -1) {
- return (filter & cvox.PlatformFilter.ANDROID) != 0;
- } else if (uA.indexOf('Win') != -1) {
- return (filter & cvox.PlatformFilter.WINDOWS) != 0;
- } else if (uA.indexOf('Mac') != -1) {
- return (filter & cvox.PlatformFilter.MAC) != 0;
- } else if (uA.indexOf('Linux') != -1) {
- return (filter & cvox.PlatformFilter.LINUX) != 0;
- } else if (uA.indexOf('CrOS') != -1) {
- return (filter & cvox.PlatformFilter.CHROMEOS) != 0;
- }
- return false;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js
deleted file mode 100644
index 3057d2efc9b..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util.js
+++ /dev/null
@@ -1,611 +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 collection of JavaScript utilities used to improve selection
- * at different granularities.
- */
-
-
-goog.provide('cvox.SelectionUtil');
-
-goog.require('cvox.DomUtil');
-goog.require('cvox.XpathUtil');
-
-/**
- * Utilities for improving selection.
- * @constructor
- */
-cvox.SelectionUtil = function() {};
-
-/**
- * Cleans up a paragraph selection acquired by extending forward.
- * In this context, a paragraph selection is 'clean' when the focus
- * node (the end of the selection) is not on a text node.
- * @param {Selection} sel The paragraph-length selection.
- * @return {boolean} True if the selection has been cleaned.
- * False if the selection cannot be cleaned without invalid extension.
- */
-cvox.SelectionUtil.cleanUpParagraphForward = function(sel) {
- var expand = true;
-
- // nodeType:3 == TEXT_NODE
- while (sel.focusNode.nodeType == 3) {
- // Ending with a text node, which is incorrect. Keep extending forward.
- var fnode = sel.focusNode;
- var foffset = sel.focusOffset;
-
- sel.modify('extend', 'forward', 'sentence');
- if ((fnode == sel.focusNode) && (foffset == sel.focusOffset)) {
- // Nothing more to be done, cannot extend forward further.
- return false;
- }
- }
-
- return true;
-};
-
-/**
- * Cleans up a paragraph selection acquired by extending backward.
- * In this context, a paragraph selection is 'clean' when the focus
- * node (the end of the selection) is not on a text node.
- * @param {Selection} sel The paragraph-length selection.
- * @return {boolean} True if the selection has been cleaned.
- * False if the selection cannot be cleaned without invalid extension.
- */
-cvox.SelectionUtil.cleanUpParagraphBack = function(sel) {
- var expand = true;
-
- var fnode;
- var foffset;
-
- // nodeType:3 == TEXT_NODE
- while (sel.focusNode.nodeType == 3) {
- // Ending with a text node, which is incorrect. Keep extending backward.
- fnode = sel.focusNode;
- foffset = sel.focusOffset;
-
- sel.modify('extend', 'backward', 'sentence');
-
- if ((fnode == sel.focusNode) && (foffset == sel.focusOffset)) {
- // Nothing more to be done, cannot extend backward further.
- return true;
- }
- }
-
- return true;
-};
-
-/**
- * Cleans up a sentence selection by extending forward.
- * In this context, a sentence selection is 'clean' when the focus
- * node (the end of the selection) is either:
- * - not on a text node
- * - on a text node that ends with a period or a space
- * @param {Selection} sel The sentence-length selection.
- * @return {boolean} True if the selection has been cleaned.
- * False if the selection cannot be cleaned without invalid extension.
- */
-cvox.SelectionUtil.cleanUpSentence = function(sel) {
- var expand = true;
- var lastSelection;
- var lastSelectionOffset;
-
- while (expand) {
-
- // nodeType:3 == TEXT_NODE
- if (sel.focusNode.nodeType == 3) {
- // The focus node is of type text, check end for period
-
- var fnode = sel.focusNode;
- var foffset = sel.focusOffset;
-
- if (sel.rangeCount > 0 && sel.getRangeAt(0).endOffset > 0) {
- if (fnode.substringData(sel.getRangeAt(0).endOffset - 1, 1) == '.') {
- // Text node ends with period.
- return true;
- } else if (fnode.substringData(sel.getRangeAt(0).endOffset - 1, 1) ==
- ' ') {
- // Text node ends with space.
- return true;
- } else {
- // Text node does not end with period or space. Extend forward.
- sel.modify('extend', 'forward', 'sentence');
-
- if ((fnode == sel.focusNode) && (foffset == sel.focusOffset)) {
- // Nothing more to be done, cannot extend forward any further.
- return false;
- }
- }
- } else {
- return true;
- }
- } else {
- // Focus node is not text node, no further cleaning required.
- return true;
- }
- }
-
- return true;
-};
-
-/**
- * Finds the starting position (height from top and left width) of a
- * selection in a document.
- * @param {Selection} sel The selection.
- * @return {Array} The coordinates [top, left] of the selection.
- */
-cvox.SelectionUtil.findSelPosition = function(sel) {
- if (sel.rangeCount == 0) {
- return [0, 0];
- }
-
- var clientRect = sel.getRangeAt(0).getBoundingClientRect();
-
- if (!clientRect) {
- return [0, 0];
- }
-
- var top = window.pageYOffset + clientRect.top;
- var left = window.pageXOffset + clientRect.left;
- return [top, left];
-};
-
-/**
- * Calculates the horizontal and vertical position of a node
- * @param {Node} targetNode The node.
- * @return {Array} The coordinates [top, left] of the node.
- */
-cvox.SelectionUtil.findTopLeftPosition = function(targetNode) {
- var left = 0;
- var top = 0;
- var obj = targetNode;
-
- if (obj.offsetParent) {
- left = obj.offsetLeft;
- top = obj.offsetTop;
- obj = obj.offsetParent;
-
- while (obj !== null) {
- left += obj.offsetLeft;
- top += obj.offsetTop;
- obj = obj.offsetParent;
- }
- }
-
- return [top, left];
-};
-
-
-/**
- * Checks the contents of a selection for meaningful content.
- * @param {Selection} sel The selection.
- * @return {boolean} True if the selection is valid. False if the selection
- * contains only whitespace or is an empty string.
- */
-cvox.SelectionUtil.isSelectionValid = function(sel) {
- var regExpWhiteSpace = new RegExp(/^\s+$/);
- return (! ((regExpWhiteSpace.test(sel.toString())) ||
- (sel.toString() == '')));
-};
-
-/**
- * Checks the contents of a range for meaningful content.
- * @param {Range} range The range.
- * @return {boolean} True if the range is valid. False if the range
- * contains only whitespace or is an empty string.
- */
-cvox.SelectionUtil.isRangeValid = function(range) {
- var text = range.cloneContents().textContent;
- var regExpWhiteSpace = new RegExp(/^\s+$/);
- return (! ((regExpWhiteSpace.test(text)) ||
- (text == '')));
-};
-
-/**
- * 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.
- * @private
- */
-cvox.SelectionUtil.findPos_ = function(node) {
- var curLeft = 0;
- var curTop = 0;
- if (node.offsetParent) {
- do {
- curLeft += node.offsetLeft;
- curTop += node.offsetTop;
- } while (node = node.offsetParent);
- }
- return [curLeft, curTop];
-};
-
-/**
- * Scrolls node in its parent node such the given node is visible.
- * @param {Node} focusNode The node.
- */
-cvox.SelectionUtil.scrollElementsToView = function(focusNode) {
- // First, walk up the DOM until we find a node with a bounding rectangle.
- while (focusNode && !focusNode.getBoundingClientRect) {
- focusNode = focusNode.parentElement;
- }
- if (!focusNode) {
- return;
- }
-
- // Walk up the DOM, ensuring each element is visible inside its parent.
- var node = focusNode;
- var parentNode = node.parentElement;
- while (node != document.body && parentNode) {
- node.scrollTop = node.offsetTop;
- node.scrollLeft = node.offsetLeft;
- node = parentNode;
- parentNode = node.parentElement;
- }
-
- // Center the active element on the page once we know it's visible.
- var pos = cvox.SelectionUtil.findPos_(focusNode);
- window.scrollTo(pos[0] - window.innerWidth / 2,
- pos[1] - window.innerHeight / 2);
-};
-
-/**
- * Scrolls the selection into view if it is out of view in the current window.
- * Inspired by workaround for already-on-screen elements @
- * http://
- * www.performantdesign.com/2009/08/26/scrollintoview-but-only-if-out-of-view/
- * @param {Selection} sel The selection to be scrolled into view.
- */
-cvox.SelectionUtil.scrollToSelection = function(sel) {
- if (sel.rangeCount == 0) {
- return;
- }
-
- // First, scroll all parent elements into view. Later, move the body
- // which works slightly differently.
-
- cvox.SelectionUtil.scrollElementsToView(sel.focusNode);
-
- var pos = cvox.SelectionUtil.findSelPosition(sel);
- var top = pos[0];
- var left = pos[1];
-
- var scrolledVertically = window.pageYOffset ||
- document.documentElement.scrollTop ||
- document.body.scrollTop;
- var pageHeight = window.innerHeight ||
- document.documentElement.clientHeight || document.body.clientHeight;
- var pageWidth = window.innerWidth ||
- document.documentElement.innerWidth || document.body.clientWidth;
-
- if (left < pageWidth) {
- left = 0;
- }
-
- // window.scroll puts specified pixel in upper left of window
- if ((scrolledVertically + pageHeight) < top) {
- // Align with bottom of page
- var diff = top - pageHeight;
- window.scroll(left, diff + 100);
- } else if (top < scrolledVertically) {
- // Align with top of page
- window.scroll(left, top - 100);
- }
-};
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Determine whether a node's text content is entirely whitespace.
- *
- * Throughout, whitespace is defined as one of the characters
- * "\t" TAB \u0009
- * "\n" LF \u000A
- * "\r" CR \u000D
- * " " SPC \u0020
- *
- * This does not use Javascript's "\s" because that includes non-breaking
- * spaces (and also some other characters).
- *
- * @param {Node} node A node implementing the |CharacterData| interface (i.e.,
- * a |Text|, |Comment|, or |CDATASection| node.
- * @return {boolean} True if all of the text content of |node| is whitespace,
- * otherwise false.
- */
-cvox.SelectionUtil.isAllWs = function(node) {
- // Use ECMA-262 Edition 3 String and RegExp features
- return !(/[^\t\n\r ]/.test(node.data));
-};
-
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Determine if a node should be ignored by the iterator functions.
- *
- * @param {Node} node An object implementing the DOM1 |Node| interface.
- * @return {boolean} True if the node is:
- * 1) A |Text| node that is all whitespace
- * 2) A |Comment| node
- * and otherwise false.
- */
-
-cvox.SelectionUtil.isIgnorable = function(node) {
- return (node.nodeType == 8) || // A comment node
- ((node.nodeType == 3) &&
- cvox.SelectionUtil.isAllWs(node)); // a text node, all ws
-};
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Version of |previousSibling| that skips nodes that are entirely
- * whitespace or comments. (Normally |previousSibling| is a property
- * of all DOM nodes that gives the sibling node, the node that is
- * a child of the same parent, that occurs immediately before the
- * reference node.)
- *
- * @param {Node} sib The reference node.
- * @return {Node} Either:
- * 1) The closest previous sibling to |sib| that is not
- * ignorable according to |isIgnorable|, or
- * 2) null if no such node exists.
- */
-cvox.SelectionUtil.nodeBefore = function(sib) {
- while ((sib = sib.previousSibling)) {
- if (!cvox.SelectionUtil.isIgnorable(sib)) {
- return sib;
- }
- }
- return null;
-};
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Version of |nextSibling| that skips nodes that are entirely
- * whitespace or comments.
- *
- * @param {Node} sib The reference node.
- * @return {Node} Either:
- * 1) The closest next sibling to |sib| that is not
- * ignorable according to |isIgnorable|, or
- * 2) null if no such node exists.
- */
-cvox.SelectionUtil.nodeAfter = function(sib) {
- while ((sib = sib.nextSibling)) {
- if (!cvox.SelectionUtil.isIgnorable(sib)) {
- return sib;
- }
- }
- return null;
-};
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Version of |lastChild| that skips nodes that are entirely
- * whitespace or comments. (Normally |lastChild| is a property
- * of all DOM nodes that gives the last of the nodes contained
- * directly in the reference node.)
- *
- * @param {Node} par The reference node.
- * @return {Node} Either:
- * 1) The last child of |sib| that is not
- * ignorable according to |isIgnorable|, or
- * 2) null if no such node exists.
- */
-cvox.SelectionUtil.lastChildNode = function(par) {
- var res = par.lastChild;
- while (res) {
- if (!cvox.SelectionUtil.isIgnorable(res)) {
- return res;
- }
- res = res.previousSibling;
- }
- return null;
-};
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Version of |firstChild| that skips nodes that are entirely
- * whitespace and comments.
- *
- * @param {Node} par The reference node.
- * @return {Node} Either:
- * 1) The first child of |sib| that is not
- * ignorable according to |isIgnorable|, or
- * 2) null if no such node exists.
- */
-cvox.SelectionUtil.firstChildNode = function(par) {
- var res = par.firstChild;
- while (res) {
- if (!cvox.SelectionUtil.isIgnorable(res)) {
- return res;
- }
- res = res.nextSibling;
- }
- return null;
-};
-
-/**
- * This is from https://developer.mozilla.org/en/Whitespace_in_the_DOM
- * Version of |data| that doesn't include whitespace at the beginning
- * and end and normalizes all whitespace to a single space. (Normally
- * |data| is a property of text nodes that gives the text of the node.)
- *
- * @param {Node} txt The text node whose data should be returned.
- * @return {string} A string giving the contents of the text node with
- * whitespace collapsed.
- */
-cvox.SelectionUtil.dataOf = function(txt) {
- var data = txt.data;
- // Use ECMA-262 Edition 3 String and RegExp features
- data = data.replace(/[\t\n\r ]+/g, ' ');
- if (data.charAt(0) == ' ') {
- data = data.substring(1, data.length);
- }
- if (data.charAt(data.length - 1) == ' ') {
- data = data.substring(0, data.length - 1);
- }
- return data;
-};
-
-/**
- * Returns true if the selection has content from at least one node
- * that has the specified tagName.
- *
- * @param {Selection} sel The selection.
- * @param {string} tagName Tagname that the selection should be checked for.
- * @return {boolean} True if the selection has content from at least one node
- * with the specified tagName.
- */
-cvox.SelectionUtil.hasContentWithTag = function(sel, tagName) {
- if (!sel || !sel.anchorNode || !sel.focusNode) {
- return false;
- }
- if (sel.anchorNode.tagName && (sel.anchorNode.tagName == tagName)) {
- return true;
- }
- if (sel.focusNode.tagName && (sel.focusNode.tagName == tagName)) {
- return true;
- }
- if (sel.anchorNode.parentNode.tagName &&
- (sel.anchorNode.parentNode.tagName == tagName)) {
- return true;
- }
- if (sel.focusNode.parentNode.tagName &&
- (sel.focusNode.parentNode.tagName == tagName)) {
- return true;
- }
- var docFrag = sel.getRangeAt(0).cloneContents();
- var span = document.createElement('span');
- span.appendChild(docFrag);
- return (span.getElementsByTagName(tagName).length > 0);
-};
-
-/**
- * Selects text within a text node.
- *
- * Note that the input node MUST be of type TEXT; otherwise, the offset
- * count would not mean # of characters - this is because of the way Range
- * works in JavaScript.
- *
- * @param {Node} textNode The text node to select text within.
- * @param {number} start The start of the selection.
- * @param {number} end The end of the selection.
- */
-cvox.SelectionUtil.selectText = function(textNode, start, end) {
- var newRange = document.createRange();
- newRange.setStart(textNode, start);
- newRange.setEnd(textNode, end);
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(newRange);
-};
-
-/**
- * Selects all the text in a given node.
- *
- * @param {Node} node The target node.
- */
-cvox.SelectionUtil.selectAllTextInNode = function(node) {
- var newRange = document.createRange();
- newRange.setStart(node, 0);
- newRange.setEndAfter(node);
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(newRange);
-};
-
-/**
- * Collapses the selection to the start. If nothing is selected,
- * selects the beginning of the given node.
- *
- * @param {Node} node The target node.
- */
-cvox.SelectionUtil.collapseToStart = function(node) {
- var sel = window.getSelection();
- var cursorNode = sel.anchorNode;
- var cursorOffset = sel.anchorOffset;
- if (cursorNode == null) {
- cursorNode = node;
- cursorOffset = 0;
- }
- var newRange = document.createRange();
- newRange.setStart(cursorNode, cursorOffset);
- newRange.setEnd(cursorNode, cursorOffset);
- sel.removeAllRanges();
- sel.addRange(newRange);
-};
-
-/**
- * Collapses the selection to the end. If nothing is selected,
- * selects the end of the given node.
- *
- * @param {Node} node The target node.
- */
-cvox.SelectionUtil.collapseToEnd = function(node) {
- var sel = window.getSelection();
- var cursorNode = sel.focusNode;
- var cursorOffset = sel.focusOffset;
- if (cursorNode == null) {
- cursorNode = node;
- cursorOffset = 0;
- }
- var newRange = document.createRange();
- newRange.setStart(cursorNode, cursorOffset);
- newRange.setEnd(cursorNode, cursorOffset);
- sel.removeAllRanges();
- sel.addRange(newRange);
-};
-
-/**
- * Retrieves all the text within a selection.
- *
- * Note that this can be different than simply using the string from
- * window.getSelection() as this will account for IMG nodes, etc.
- *
- * @return {string} The string of text contained in the current selection.
- */
-cvox.SelectionUtil.getText = function() {
- var sel = window.getSelection();
- if (cvox.SelectionUtil.hasContentWithTag(sel, 'IMG')) {
- var text = '';
- var docFrag = sel.getRangeAt(0).cloneContents();
- var span = document.createElement('span');
- span.appendChild(docFrag);
- var leafNodes = cvox.XpathUtil.getLeafNodes(span);
- for (var i = 0, node; node = leafNodes[i]; i++) {
- text = text + ' ' + cvox.DomUtil.getName(node);
- }
- return text;
- } else {
- return this.getSelectionText_();
- }
-};
-
-/**
- * Returns the selection as text instead of a selection object. Note that this
- * function must be used in place of getting text directly from the DOM
- * if you want i18n tests to pass.
- *
- * @return {string} The text.
- * @private
- */
-cvox.SelectionUtil.getSelectionText_ = function() {
- return '' + window.getSelection();
-};
-
-
-/**
- * Returns a range as text instead of a selection object. Note that this
- * function must be used in place of getting text directly from the DOM
- * if you want i18n tests to pass.
- *
- * @param {Range} range A range.
- * @return {string} The text.
- */
-cvox.SelectionUtil.getRangeText = function(range) {
- if (range)
- return range.cloneContents().textContent.replace(/\s+/g, ' ');
- else
- return '';
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util_test.unitjs
deleted file mode 100644
index 7adbc57a8d3..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/selection_util_test.unitjs
+++ /dev/null
@@ -1,31 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxSelectionUtilUnitTest() {}
-
-CvoxSelectionUtilUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.SelectionUtil'
- ]
-};
-
-TEST_F('CvoxSelectionUtilUnitTest', 'SimpleFindPos', function() {
- this.loadDoc(function() {/*!
- <div id="foo" style="position:absolute;top:50px">
- </div>
- */});
- element = $('foo');
- assertEquals(cvox.SelectionUtil.findPos_(element)[1], 50);
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js
deleted file mode 100644
index be77ba04ae7..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable.js
+++ /dev/null
@@ -1,434 +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 Class which allows construction of annotated strings.
- */
-
-goog.provide('cvox.Spannable');
-
-goog.require('goog.object');
-
-/**
- * @constructor
- * @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) {
- /**
- * Underlying string.
- * @type {string}
- * @private
- */
- this.string_ = opt_string instanceof cvox.Spannable ? '' : opt_string || '';
-
- /**
- * Spans (annotations).
- * @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;
- this.spans_.push({ value: opt_annotation, start: 0, end: len });
- }
-};
-
-
-/** @override */
-cvox.Spannable.prototype.toString = function() {
- return this.string_;
-};
-
-
-/**
- * Returns the length of the string.
- * @return {number} Length of the string.
- */
-cvox.Spannable.prototype.getLength = function() {
- return this.string_.length;
-};
-
-
-/**
- * Adds a span to some region of the string.
- * @param {*} value Annotation.
- * @param {number} start Starting index (inclusive).
- * @param {number} end Ending index (exclusive).
- */
-cvox.Spannable.prototype.setSpan = function(value, start, end) {
- this.removeSpan(value);
- if (0 <= start && start <= end && end <= this.string_.length) {
- // Zero-length spans are explicitly allowed, because it is possible to
- // query for position by annotation as well as the reverse.
- this.spans_.push({ value: value, start: start, end: end });
- this.spans_.sort(function(a, b) {
- var ret = a.start - b.start;
- if (ret == 0)
- ret = a.end - b.end;
- return ret;
- });
- } else {
- throw new RangeError('span out of range (start=' + start +
- ', end=' + end + ', len=' + this.string_.length + ')');
- }
-};
-
-
-/**
- * Removes a span.
- * @param {*} value Annotation.
- */
-cvox.Spannable.prototype.removeSpan = function(value) {
- for (var i = this.spans_.length - 1; i >= 0; i--) {
- if (this.spans_[i].value === value) {
- this.spans_.splice(i, 1);
- }
- }
-};
-
-
-/**
- * Appends another Spannable or string to this one.
- * @param {string|!cvox.Spannable} other String or spannable to concatenate.
- */
-cvox.Spannable.prototype.append = function(other) {
- if (other instanceof cvox.Spannable) {
- var otherSpannable = /** @type {!cvox.Spannable} */ (other);
- var originalLength = this.getLength();
- this.string_ += otherSpannable.string_;
- other.spans_.forEach(goog.bind(function(span) {
- this.setSpan(
- span.value,
- span.start + originalLength,
- span.end + originalLength);
- }, this));
- } else if (typeof other === 'string') {
- this.string_ += /** @type {string} */ (other);
- }
-};
-
-
-/**
- * Returns the first value matching a position.
- * @param {number} position Position to query.
- * @return {*} Value annotating that position, or undefined if none is found.
- */
-cvox.Spannable.prototype.getSpan = function(position) {
- for (var i = 0; i < this.spans_.length; i++) {
- var span = this.spans_[i];
- if (span.start <= position && position < span.end) {
- return span.value;
- }
- }
-};
-
-
-/**
- * Returns the first span value which is an instance of a given constructor.
- * @param {!Function} constructor Constructor.
- * @return {!Object|undefined} Object if found; undefined otherwise.
- */
-cvox.Spannable.prototype.getSpanInstanceOf = function(constructor) {
- for (var i = 0; i < this.spans_.length; i++) {
- var span = this.spans_[i];
- if (span.value instanceof constructor) {
- return span.value;
- }
- }
-};
-
-/**
- * Returns all span values which are an instance of a given constructor.
- * Spans are returned in the order of their starting index and ending index
- * for spans with equals tarting indices.
- * @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.
- * @param {number} position Position to query.
- * @return {!Array} Values annotating that position.
- */
-cvox.Spannable.prototype.getSpans = function(position) {
- var results = [];
- for (var i = 0; i < this.spans_.length; i++) {
- var span = this.spans_[i];
- if (span.start <= position && position < span.end) {
- results.push(span.value);
- }
- }
- return results;
-};
-
-
-/**
- * Returns the start of the requested span.
- * @param {*} value Annotation.
- * @return {number|undefined} Start of the span, or undefined if not attached.
- */
-cvox.Spannable.prototype.getSpanStart = function(value) {
- for (var i = 0; i < this.spans_.length; i++) {
- var span = this.spans_[i];
- if (span.value === value) {
- return span.start;
- }
- }
- return undefined;
-};
-
-
-/**
- * Returns the end of the requested span.
- * @param {*} value Annotation.
- * @return {number|undefined} End of the span, or undefined if not attached.
- */
-cvox.Spannable.prototype.getSpanEnd = function(value) {
- for (var i = 0; i < this.spans_.length; i++) {
- var span = this.spans_[i];
- if (span.value === value) {
- return span.end;
- }
- }
- return undefined;
-};
-
-
-/**
- * Returns a substring of this spannable.
- * Note that while similar to String#substring, this function is much less
- * permissive about its arguments. It does not accept arguments in the wrong
- * order or out of bounds.
- *
- * @param {number} start Start index, inclusive.
- * @param {number=} opt_end End index, exclusive.
- * If excluded, the length of the string is used instead.
- * @return {!cvox.Spannable} Substring requested.
- */
-cvox.Spannable.prototype.substring = function(start, opt_end) {
- var end = goog.isDef(opt_end) ? opt_end : this.string_.length;
-
- if (start < 0 || end > this.string_.length || start > end) {
- throw new RangeError('substring indices out of range');
- }
-
- var result = new cvox.Spannable(this.string_.substring(start, end));
- for (var i = 0; i < this.spans_.length; i++) {
- var span = this.spans_[i];
- if (span.start <= end && span.end >= start) {
- var newStart = Math.max(0, span.start - start);
- var newEnd = Math.min(end - start, span.end - start);
- result.spans_.push({ value: span.value, start: newStart, end: newEnd });
- }
- }
- return result;
-};
-
-
-/**
- * Trims whitespace from the beginning.
- * @return {!cvox.Spannable} String with whitespace removed.
- */
-cvox.Spannable.prototype.trimLeft = function() {
- return this.trim_(true, false);
-};
-
-
-/**
- * Trims whitespace from the end.
- * @return {!cvox.Spannable} String with whitespace removed.
- */
-cvox.Spannable.prototype.trimRight = function() {
- return this.trim_(false, true);
-};
-
-
-/**
- * Trims whitespace from the beginning and end.
- * @return {!cvox.Spannable} String with whitespace removed.
- */
-cvox.Spannable.prototype.trim = function() {
- return this.trim_(true, true);
-};
-
-
-/**
- * Trims whitespace from either the beginning and end or both.
- * @param {boolean} trimStart Trims whitespace from the start of a string.
- * @param {boolean} trimEnd Trims whitespace from the end of a string.
- * @return {!cvox.Spannable} String with whitespace removed.
- * @private
- */
-cvox.Spannable.prototype.trim_ = function(trimStart, trimEnd) {
- if (!trimStart && !trimEnd) {
- return this;
- }
-
- // Special-case whitespace-only strings, including the empty string.
- // As an arbitrary decision, we treat this as trimming the whitespace off the
- // end, rather than the beginning, of the string.
- // This choice affects which spans are kept.
- if (/^\s*$/.test(this.string_)) {
- return this.substring(0, 0);
- }
-
- // Otherwise, we have at least one non-whitespace character to use as an
- // anchor when trimming.
- var trimmedStart = trimStart ? this.string_.match(/^\s*/)[0].length : 0;
- var trimmedEnd = trimEnd ?
- this.string_.match(/\s*$/).index : this.string_.length;
- return this.substring(trimmedStart, trimmedEnd);
-};
-
-
-/**
- * Returns this spannable to a json serializable form, including the text and
- * span objects whose types have been registered with registerSerializableSpan
- * or registerStatelessSerializableSpan.
- * @return {!cvox.Spannable.SerializedSpannable_} the json serializable form.
- */
-cvox.Spannable.prototype.toJson = function() {
- var result = {};
- result.string = this.string_;
- result.spans = [];
- for (var i = 0; i < this.spans_.length; ++i) {
- var span = this.spans_[i];
- // Use linear search, since using functions as property keys
- // is not reliable.
- var serializeInfo = goog.object.findValue(
- cvox.Spannable.serializableSpansByName_,
- function(v) { return v.ctor === span.value.constructor; });
- if (serializeInfo) {
- var spanObj = {type: serializeInfo.name,
- start: span.start,
- end: span.end};
- if (serializeInfo.toJson) {
- spanObj.value = serializeInfo.toJson.apply(span.value);
- }
- result.spans.push(spanObj);
- }
- }
- return result;
-};
-
-
-/**
- * Creates a spannable from a json serializable representation.
- * @param {!cvox.Spannable.SerializedSpannable_} obj object containing the
- * serializable representation.
- * @return {!cvox.Spannable}
- */
-cvox.Spannable.fromJson = function(obj) {
- if (typeof obj.string !== 'string') {
- throw 'Invalid spannable json object: string field not a string';
- }
- if (!(obj.spans instanceof Array)) {
- throw 'Invalid spannable json object: no spans array';
- }
- var result = new cvox.Spannable(obj.string);
- for (var i = 0, span; span = obj.spans[i]; ++i) {
- if (typeof span.type !== 'string') {
- throw 'Invalid span in spannable json object: type not a string';
- }
- if (typeof span.start !== 'number' || typeof span.end !== 'number') {
- throw 'Invalid span in spannable json object: start or end not a number';
- }
- var serializeInfo = cvox.Spannable.serializableSpansByName_[span.type];
- var value = serializeInfo.fromJson(span.value);
- result.setSpan(value, span.start, span.end);
- }
- return result;
-};
-
-
-/**
- * Registers a type that can be converted to a json serializable format.
- * @param {!Function} constructor The type of object that can be converted.
- * @param {string} name String identifier used in the serializable format.
- * @param {function(!Object): !Object} fromJson A function that converts
- * the serializable object to an actual object of this type.
- * @param {function(!Object): !Object} toJson A function that converts
- * this object to a json serializable object. The function will
- * be called with this set to the object to convert.
- */
-cvox.Spannable.registerSerializableSpan = function(
- constructor, name, fromJson, toJson) {
- var obj = {name: name, ctor: constructor,
- fromJson: fromJson, toJson: toJson};
- cvox.Spannable.serializableSpansByName_[name] = obj;
-};
-
-
-/**
- * Registers an object type that can be converted to/from a json serializable
- * form. Objects of this type carry no state that will be preserved
- * when serialized.
- * @param {!Function} constructor The type of the object that can be converted.
- * This constructor will be called with no arguments to construct
- * new objects.
- * @param {string} name Name of the type used in the serializable object.
- */
-cvox.Spannable.registerStatelessSerializableSpan = function(
- constructor, name) {
- var obj = {name: name, ctor: constructor, toJson: undefined};
- /**
- * @param {!Object} obj
- * @return {!Object}
- */
- obj.fromJson = function(obj) {
- return new constructor();
- };
- cvox.Spannable.serializableSpansByName_[name] = obj;
-};
-
-
-/**
- * Describes how to convert a span type to/from serializable json.
- * @typedef {{ctor: !Function, name: string,
- * fromJson: function(!Object): !Object,
- * toJson: ((function(!Object): !Object)|undefined)}}
- * @private
- */
-cvox.Spannable.SerializeInfo_;
-
-
-/**
- * The serialized format of a spannable.
- * @typedef {{string: string, spans: Array<cvox.Spannable.SerializedSpan_>}}
- * @private
- */
-cvox.Spannable.SerializedSpannable_;
-
-
-/**
- * The format of a single annotation in a serialized spannable.
- * @typedef {{type: string, value: !Object, start: number, end: number}}
- * @private
- */
-cvox.Spannable.SerializedSpan_;
-
-/**
- * Maps type names to serialization info objects.
- * @type {Object<cvox.Spannable.SerializeInfo_>}
- * @private
- */
-cvox.Spannable.serializableSpansByName_ = {};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.unitjs
deleted file mode 100644
index 8a26cfeb5d3..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.unitjs
+++ /dev/null
@@ -1,481 +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.
-
-// Include test fixture.
-GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
-
-UnserializableSpan = function() {};
-
-StatelessSerializableSpan = function() {};
-
-NonStatelessSerializableSpan = function(value) {
- this.value = value;
-};
-
-/**
- * @param {!Object} obj object containing the
- * serializable representation.
- * @return {!Object} The Spannable.
- */
-NonStatelessSerializableSpan.fromJson = function(obj) {
- return new NonStatelessSerializableSpan(obj.value / 2);
-};
-
-/**
- * @return {Object} the json serializable form.
- */
-NonStatelessSerializableSpan.prototype.toJson = function() {
- return {value: this.value * 2};
-};
-
-/**
- * Test fixture.
- * @constructor
- * @extends {ChromeVoxUnitTestBase}
- */
-function CvoxSpannableUnitTest() {}
-
-CvoxSpannableUnitTest.prototype = {
- __proto__: ChromeVoxUnitTestBase.prototype,
-
- /** @override */
- closureModuleDeps: [
- 'cvox.Spannable',
- ],
-
- /** @override */
- setUp: function() {
- cvox.Spannable.registerStatelessSerializableSpan(
- StatelessSerializableSpan, 'StatelessSerializableSpan');
-
- cvox.Spannable.registerSerializableSpan(
- NonStatelessSerializableSpan, 'NonStatelessSerializableSpan',
- NonStatelessSerializableSpan.fromJson,
- NonStatelessSerializableSpan.prototype.toJson);
- }
-};
-
-TEST_F('CvoxSpannableUnitTest', 'ToStringUnannotated', function() {
- assertEquals('', new cvox.Spannable().toString());
- assertEquals('hello world', new cvox.Spannable('hello world').toString());
-});
-
-/** Tests that toString works correctly on annotated strings. */
-TEST_F('CvoxSpannableUnitTest', 'ToStringAnnotated', function() {
- var spannable = new cvox.Spannable('Hello Google');
- spannable.setSpan('http://www.google.com/', 6, 12);
- assertEquals('Hello Google', spannable.toString());
-});
-
-/** Tests the length calculation. */
-TEST_F('CvoxSpannableUnitTest', 'GetLength', function() {
- var spannable = new cvox.Spannable('Hello');
- spannable.setSpan({}, 0, 3);
- assertEquals(5, spannable.getLength());
- spannable.append(' world');
- assertEquals(11, spannable.getLength());
- spannable.append(new cvox.Spannable(' from cvox.Spannable'));
- assertEquals(31, spannable.getLength());
-});
-
-/** Tests that a span can be added and retrieved at the beginning. */
-TEST_F('CvoxSpannableUnitTest', 'SpanBeginning', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(annotation, 0, 5);
- assertSame(annotation, spannable.getSpan(0));
- assertSame(annotation, spannable.getSpan(3));
- assertUndefined(spannable.getSpan(5));
- assertUndefined(spannable.getSpan(8));
-});
-
-/** Tests that a span can be added and retrieved at the beginning. */
-TEST_F('CvoxSpannableUnitTest', 'SpanEnd', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(annotation, 6, 11);
- assertUndefined(spannable.getSpan(3));
- assertUndefined(spannable.getSpan(5));
- assertSame(annotation, spannable.getSpan(6));
- assertSame(annotation, spannable.getSpan(10));
-});
-
-/** Tests that a zero-length span is not retrieved. */
-TEST_F('CvoxSpannableUnitTest', 'SpanZeroLength', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(annotation, 3, 3);
- assertUndefined(spannable.getSpan(2));
- assertUndefined(spannable.getSpan(3));
- assertUndefined(spannable.getSpan(4));
-});
-
-/** Tests that a removed span is not returned. */
-TEST_F('CvoxSpannableUnitTest', 'RemoveSpan', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(annotation, 0, 3);
- assertSame(annotation, spannable.getSpan(1));
- spannable.removeSpan(annotation);
- assertUndefined(spannable.getSpan(1));
-});
-
-/** Tests that adding a span in one place removes it from another. */
-TEST_F('CvoxSpannableUnitTest', 'SetSpanMoves', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(annotation, 0, 3);
- assertSame(annotation, spannable.getSpan(1));
- assertUndefined(spannable.getSpan(4));
- spannable.setSpan(annotation, 3, 6);
- assertUndefined(spannable.getSpan(1));
- assertSame(annotation, spannable.getSpan(4));
-});
-
-/** Tests that setSpan objects to out-of-range arguments. */
-TEST_F('CvoxSpannableUnitTest', 'SetSpanRangeError', function() {
- var spannable = new cvox.Spannable('Hello world');
-
- // Start index out of range.
- assertException('expected range error', function() {
- spannable.setSpan({}, -1, 0);
- }, 'RangeError');
-
- // End index out of range.
- assertException('expected range error', function() {
- spannable.setSpan({}, 0, 12);
- }, 'RangeError');
-
- // End before start.
- assertException('expected range error', function() {
- spannable.setSpan({}, 1, 0);
- }, 'RangeError');
-});
-
-/**
- * Tests that multiple spans can be retrieved at one point.
- * The first one added which applies should be returned by getSpan.
- */
-TEST_F('CvoxSpannableUnitTest', 'MultipleSpans', function() {
- var annotation1 = { number: 1 };
- var annotation2 = { number: 2 };
- assertNotSame(annotation1, annotation2);
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(annotation1, 1, 4);
- spannable.setSpan(annotation2, 2, 7);
- assertSame(annotation1, spannable.getSpan(1));
- assertThat([annotation1], eqJSON(spannable.getSpans(1)));
- assertSame(annotation1, spannable.getSpan(3));
- assertThat([annotation1, annotation2], eqJSON(spannable.getSpans(3)));
- assertSame(annotation2, spannable.getSpan(6));
- assertThat([annotation2], eqJSON(spannable.getSpans(6)));
-});
-
-/** Tests that appending appends the strings. */
-TEST_F('CvoxSpannableUnitTest', 'AppendToString', function() {
- var spannable = new cvox.Spannable('Google');
- assertEquals('Google', spannable.toString());
- spannable.append(' Chrome');
- assertEquals('Google Chrome', spannable.toString());
- spannable.append(new cvox.Spannable('Vox'));
- assertEquals('Google ChromeVox', spannable.toString());
-});
-
-/**
- * Tests that appending Spannables combines annotations.
- */
-TEST_F('CvoxSpannableUnitTest', 'AppendAnnotations', function() {
- var annotation1 = { number: 1 };
- var annotation2 = { number: 2 };
- assertNotSame(annotation1, annotation2);
- var left = new cvox.Spannable('hello');
- left.setSpan(annotation1, 0, 3);
- var right = new cvox.Spannable(' world');
- right.setSpan(annotation2, 0, 3);
- left.append(right);
- assertSame(annotation1, left.getSpan(1));
- assertSame(annotation2, left.getSpan(6));
-});
-
-/**
- * Tests that a span's bounds can be retrieved.
- */
-TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEnd', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('potato wedges');
- spannable.setSpan(annotation, 8, 12);
- assertEquals(8, spannable.getSpanStart(annotation));
- assertEquals(12, spannable.getSpanEnd(annotation));
-});
-
-/**
- * Tests that an absent span's bounds are reported correctly.
- */
-TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEndAbsent', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('potato wedges');
- assertUndefined(spannable.getSpanStart(annotation));
- assertUndefined(spannable.getSpanEnd(annotation));
-});
-
-/**
- * Test that a zero length span can still be found.
- */
-TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEndZeroLength', function() {
- var annotation = {};
- var spannable = new cvox.Spannable('potato wedges');
- spannable.setSpan(annotation, 8, 8);
- assertEquals(8, spannable.getSpanStart(annotation));
- assertEquals(8, spannable.getSpanEnd(annotation));
-});
-
-/**
- * Tests that == (but not ===) objects are treated distinctly when getting
- * span bounds.
- */
-TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEndEquality', function() {
- // Note that 0 == '' and '' == 0 in JavaScript.
- var spannable = new cvox.Spannable('wat');
- spannable.setSpan(0, 0, 0);
- spannable.setSpan('', 1, 3);
- assertEquals(0, spannable.getSpanStart(0));
- assertEquals(0, spannable.getSpanEnd(0));
- assertEquals(1, spannable.getSpanStart(''));
- assertEquals(3, spannable.getSpanEnd(''));
-});
-
-/**
- * Tests that substrings have the correct character sequence.
- */
-TEST_F('CvoxSpannableUnitTest', 'Substring', function() {
- var assertSubstringResult = function(expected, initial, start, opt_end) {
- var spannable = new cvox.Spannable(initial);
- var substring = spannable.substring(start, opt_end);
- assertEquals(expected, substring.toString());
- };
- assertSubstringResult('Page', 'Google PageRank', 7, 11);
- assertSubstringResult('Goog', 'Google PageRank', 0, 4);
- assertSubstringResult('Rank', 'Google PageRank', 11, 15);
- assertSubstringResult('Rank', 'Google PageRank', 11);
-});
-
-/**
- * Tests that substring arguments are validated properly.
- */
-TEST_F('CvoxSpannableUnitTest', 'SubstringRangeError', function() {
- var assertRangeError = function(initial, start, opt_end) {
- var spannable = new cvox.Spannable(initial);
- assertException('expected range error', function() {
- spannable.substring(start, opt_end);
- }, 'RangeError');
- };
- assertRangeError('Google PageRank', -1, 5);
- assertRangeError('Google PageRank', 0, 99);
- assertRangeError('Google PageRank', 5, 2);
-});
-
-/**
- * Tests that spans in the substring range are preserved.
- */
-TEST_F('CvoxSpannableUnitTest', 'SubstringSpansIncluded', function() {
- var assertSpanIncluded = function(expectedSpanStart, expectedSpanEnd,
- initial, initialSpanStart, initialSpanEnd, start, opt_end) {
- var annotation = {};
- var spannable = new cvox.Spannable(initial);
- spannable.setSpan(annotation, initialSpanStart, initialSpanEnd);
- var substring = spannable.substring(start, opt_end);
- assertEquals(expectedSpanStart, substring.getSpanStart(annotation));
- assertEquals(expectedSpanEnd, substring.getSpanEnd(annotation));
- };
- assertSpanIncluded(1, 5, 'potato wedges', 8, 12, 7);
- assertSpanIncluded(1, 5, 'potato wedges', 8, 12, 7, 13);
- assertSpanIncluded(1, 5, 'potato wedges', 8, 12, 7, 12);
- assertSpanIncluded(0, 4, 'potato wedges', 8, 12, 8, 12);
- assertSpanIncluded(0, 3, 'potato wedges', 0, 3, 0);
- assertSpanIncluded(0, 3, 'potato wedges', 0, 3, 0, 3);
- assertSpanIncluded(0, 3, 'potato wedges', 0, 3, 0, 6);
- assertSpanIncluded(0, 5, 'potato wedges', 8, 13, 8);
- assertSpanIncluded(0, 5, 'potato wedges', 8, 13, 8, 13);
- assertSpanIncluded(1, 6, 'potato wedges', 8, 13, 7, 13);
-
- // Note: we should keep zero-length spans, even at the edges of the range.
- assertSpanIncluded(0, 0, 'potato wedges', 0, 0, 0, 0);
- assertSpanIncluded(0, 0, 'potato wedges', 0, 0, 0, 6);
- assertSpanIncluded(1, 1, 'potato wedges', 8, 8, 7, 13);
- assertSpanIncluded(6, 6, 'potato wedges', 6, 6, 0, 6);
-});
-
-/**
- * Tests that spans outside the range are omitted.
- * It's fine to keep zero-length spans at the ends, though.
- */
-TEST_F('CvoxSpannableUnitTest', 'SubstringSpansExcluded', function() {
- var assertSpanExcluded = function(initial, spanStart, spanEnd,
- start, opt_end) {
- var annotation = {};
- var spannable = new cvox.Spannable(initial);
- spannable.setSpan(annotation, spanStart, spanEnd);
- var substring = spannable.substring(start, opt_end);
- assertUndefined(substring.getSpanStart(annotation));
- assertUndefined(substring.getSpanEnd(annotation));
- };
- assertSpanExcluded('potato wedges', 8, 12, 0, 6);
- assertSpanExcluded('potato wedges', 7, 12, 0, 6);
- assertSpanExcluded('potato wedges', 0, 6, 8);
- assertSpanExcluded('potato wedges', 6, 6, 8);
-});
-
-/**
- * Tests that spans which cross the boundary are clipped.
- */
-TEST_F('CvoxSpannableUnitTest', 'SubstringSpansClipped', function() {
- var assertSpanIncluded = function(expectedSpanStart, expectedSpanEnd,
- initial, initialSpanStart, initialSpanEnd, start, opt_end) {
- var annotation = {};
- var spannable = new cvox.Spannable(initial);
- spannable.setSpan(annotation, initialSpanStart, initialSpanEnd);
- var substring = spannable.substring(start, opt_end);
- assertEquals(expectedSpanStart, substring.getSpanStart(annotation));
- assertEquals(expectedSpanEnd, substring.getSpanEnd(annotation));
- };
- assertSpanIncluded(0, 4, 'potato wedges', 7, 13, 8, 12);
- assertSpanIncluded(0, 0, 'potato wedges', 0, 6, 0, 0);
- assertSpanIncluded(0, 0, 'potato wedges', 0, 6, 6, 6);
-
- // The first of the above should produce "edge".
- assertEquals('edge',
- new cvox.Spannable('potato wedges').substring(8, 12).toString());
-});
-
-/**
- * Tests that whitespace is trimmed.
- */
-TEST_F('CvoxSpannableUnitTest', 'Trim', function() {
- var assertTrimResult = function(expected, initial) {
- assertEquals(expected, new cvox.Spannable(initial).trim().toString());
- };
- assertTrimResult('John F. Kennedy', 'John F. Kennedy');
- assertTrimResult('John F. Kennedy', ' John F. Kennedy');
- assertTrimResult('John F. Kennedy', 'John F. Kennedy ');
- assertTrimResult('John F. Kennedy', ' \r\t \nJohn F. Kennedy\n\n \n');
- assertTrimResult('', '');
- assertTrimResult('', ' \t\t \n\r');
-});
-
-/**
- * Tests that trim keeps, drops and clips spans.
- */
-TEST_F('CvoxSpannableUnitTest', 'TrimSpans', function() {
- var spannable = new cvox.Spannable(' \t Kennedy\n');
- spannable.setSpan('tab', 1, 2);
- spannable.setSpan('jfk', 3, 10);
- spannable.setSpan('jfk-newline', 3, 11);
- var trimmed = spannable.trim();
- assertUndefined(trimmed.getSpanStart('tab'));
- assertUndefined(trimmed.getSpanEnd('tab'));
- assertEquals(0, trimmed.getSpanStart('jfk'));
- assertEquals(7, trimmed.getSpanEnd('jfk'));
- assertEquals(0, trimmed.getSpanStart('jfk-newline'));
- assertEquals(7, trimmed.getSpanEnd('jfk-newline'));
-});
-
-/**
- * Tests that when a string is all whitespace, we trim off the *end*.
- */
-TEST_F('CvoxSpannableUnitTest', 'TrimAllWhitespace', function() {
- var spannable = new cvox.Spannable(' ');
- spannable.setSpan('cursor 1', 0, 0);
- spannable.setSpan('cursor 2', 2, 2);
- var trimmed = spannable.trim();
- assertEquals(0, trimmed.getSpanStart('cursor 1'));
- assertEquals(0, trimmed.getSpanEnd('cursor 1'));
- assertUndefined(trimmed.getSpanStart('cursor 2'));
- assertUndefined(trimmed.getSpanEnd('cursor 2'));
-});
-
-/**
- * Tests finding a span which is an instance of a given class.
- */
-TEST_F('CvoxSpannableUnitTest', 'GetSpanInstanceOf', function() {
- function ExampleConstructorBase() {}
- function ExampleConstructor1() {}
- function ExampleConstructor2() {}
- function ExampleConstructor3() {}
- ExampleConstructor1.prototype = new ExampleConstructorBase();
- ExampleConstructor2.prototype = new ExampleConstructorBase();
- ExampleConstructor3.prototype = new ExampleConstructorBase();
- var ex1 = new ExampleConstructor1();
- var ex2 = new ExampleConstructor2();
- var spannable = new cvox.Spannable('Hello world');
- spannable.setSpan(ex1, 0, 0);
- spannable.setSpan(ex2, 1, 1);
- assertEquals(ex1, spannable.getSpanInstanceOf(ExampleConstructor1));
- assertEquals(ex2, spannable.getSpanInstanceOf(ExampleConstructor2));
- assertUndefined(spannable.getSpanInstanceOf(ExampleConstructor3));
- assertEquals(ex1, spannable.getSpanInstanceOf(ExampleConstructorBase));
-});
-
-/** Tests trimming only left or right. */
-TEST_F('CvoxSpannableUnitTest', 'TrimLeftOrRight', function() {
- var spannable = new cvox.Spannable(' ');
- spannable.setSpan('cursor 1', 0, 0);
- spannable.setSpan('cursor 2', 2, 2);
- var trimmed = spannable.trimLeft();
- assertEquals(0, trimmed.getSpanStart('cursor 1'));
- assertEquals(0, trimmed.getSpanEnd('cursor 1'));
- assertUndefined(trimmed.getSpanStart('cursor 2'));
- assertUndefined(trimmed.getSpanEnd('cursor 2'));
-
- var spannable2 = new cvox.Spannable('0 ');
- spannable2.setSpan('cursor 1', 0, 0);
- spannable2.setSpan('cursor 2', 2, 2);
- var trimmed2 = spannable2.trimLeft();
- assertEquals(0, trimmed2.getSpanStart('cursor 1'));
- assertEquals(0, trimmed2.getSpanEnd('cursor 1'));
- assertEquals(2, trimmed2.getSpanStart('cursor 2'));
- assertEquals(2, trimmed2.getSpanEnd('cursor 2'));
- trimmed2 = trimmed2.trimRight();
- assertEquals(0, trimmed2.getSpanStart('cursor 1'));
- assertEquals(0, trimmed2.getSpanEnd('cursor 1'));
- assertUndefined(trimmed2.getSpanStart('cursor 2'));
- assertUndefined(trimmed2.getSpanEnd('cursor 2'));
-
- var spannable3 = new cvox.Spannable(' 0');
- spannable3.setSpan('cursor 1', 0, 0);
- spannable3.setSpan('cursor 2', 2, 2);
- var trimmed3 = spannable3.trimRight();
- assertEquals(0, trimmed3.getSpanStart('cursor 1'));
- assertEquals(0, trimmed3.getSpanEnd('cursor 1'));
- assertEquals(2, trimmed3.getSpanStart('cursor 2'));
- assertEquals(2, trimmed3.getSpanEnd('cursor 2'));
- trimmed3 = trimmed3.trimLeft();
- assertUndefined(trimmed3.getSpanStart('cursor 1'));
- assertUndefined(trimmed3.getSpanEnd('cursor 1'));
- assertEquals(0, trimmed3.getSpanStart('cursor 2'));
- assertEquals(0, trimmed3.getSpanEnd('cursor 2'));
-});
-
-TEST_F('CvoxSpannableUnitTest', 'Serialize', function() {
- var fresh = new cvox.Spannable('text');
- var freshStatelessSerializable = new StatelessSerializableSpan();
- var freshNonStatelessSerializable = new NonStatelessSerializableSpan(14);
- fresh.setSpan(new UnserializableSpan(), 0, 1);
- fresh.setSpan(freshStatelessSerializable, 0, 2);
- fresh.setSpan(freshNonStatelessSerializable, 3, 4);
- var thawn = cvox.Spannable.fromJson(fresh.toJson());
- var thawnStatelessSerializable = thawn.getSpanInstanceOf(
- StatelessSerializableSpan);
- var thawnNonStatelessSerializable = thawn.getSpanInstanceOf(
- NonStatelessSerializableSpan);
- assertThat('text', eqJSON(thawn.toString()));
- assertUndefined(thawn.getSpanInstanceOf(UnserializableSpan));
- assertThat(
- fresh.getSpanStart(freshStatelessSerializable),
- eqJSON(thawn.getSpanStart(thawnStatelessSerializable)));
- assertThat(
- fresh.getSpanEnd(freshStatelessSerializable),
- eqJSON(thawn.getSpanEnd(thawnStatelessSerializable)));
- assertThat(freshNonStatelessSerializable,
- eqJSON(thawnNonStatelessSerializable));
-});
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js
deleted file mode 100644
index 5b771c5a774..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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
deleted file mode 100644
index efd31a5afdb..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/string_util_test.unitjs
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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/table_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/table_util.js
deleted file mode 100644
index ec22512c1a5..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/table_util.js
+++ /dev/null
@@ -1,179 +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 DOM utility functions to aid in table navigation.
- */
-
-goog.provide('cvox.TableUtil');
-
-goog.require('cvox.XpathUtil');
-
-
-/**
- * Utility function to check if a particular table cell is a candidate
- * header cell.
- * @param {Node} cell The table cell.
- * @return {boolean} Whether or not the table cell is acting as a header cell.
- */
-cvox.TableUtil.checkIfHeader = function(cell) {
- /*
- * Headers are defined here as <TH> or <TD> elements. <TD> elements when
- * serving as header cells must have either:
- * - The scope attribute defined
- * - Their IDs referenced in the header content attribute of another <TD> or
- * <TH> element.
- * This function does not check whether this cell is referenced by another
- * <TD>. So this function by itself will not be able to gather all possible
- * header cells when applied across all table cells.
- *
- * Please Note:
- * The HTML5 spec specifies that only header <TH> elements can be headers
- * ( http://dev.w3.org/html5/spec/tabular-data.html#row-header ) but the
- * HTML4 spec says that <TD> elements can act as headers if they have a
- * scope attribute defined
- * ( http://www.w3.org/TR/html401/struct/tables.html#h-11.2.6 ). In the
- * interest of providing meaningful header information for all tables, here
- * we take the position that <TD> elements can act as headers.
- */
- return ((cell.tagName == 'TH') ||
- cell.hasAttribute('scope') || (cell.hasAttribute('role') &&
- ((cell.getAttribute('role') == 'rowheader') ||
- (cell.getAttribute('role') == 'columnheader'))));
-};
-
-
-/**
- * Utility function to determine colgroup structure. Builds an array that
- * associates a column number to a particular col group.
- * @param {Array} colGroups An array of all the colgroup elements in a
- * particular table.
- * @return {Array} An array that maps indexes representing table columns
- * to indexes into the colGroups array.
- */
-cvox.TableUtil.determineColGroups = function(colGroups) {
- var colToColGroup = [];
-
- if (colGroups.length == 0) {
- return colToColGroup;
- }
- // A colgroup has either a series of col element children or a span
- // attribute. If it has col children, ignore the span attribute
- for (var colGroupCtr = 0; colGroupCtr < colGroups.length;
- colGroupCtr++) {
-
- var currentColGroup = colGroups[colGroupCtr];
-
- var childCols = cvox.TableUtil.getColNodes(currentColGroup);
- if (childCols.length > 0) {
- for (var colNodeCtr = 0; colNodeCtr < childCols.length;
- colNodeCtr++) {
- var colElement = childCols[colNodeCtr];
-
- if (colElement.hasAttribute('span')) {
- var span = parseInt(colElement.getAttribute('span'), 10);
-
- for (var s = 0; s < span; s++) {
- colToColGroup.push(colGroupCtr);
- }
- } else {
- colToColGroup.push(colGroupCtr);
- }
- }
- } else {
- // No children of the current colgroup. Does it have a span attribute?
- if (currentColGroup.hasAttribute('span')) {
- var span = parseInt(currentColGroup.getAttribute('span'), 10);
-
- for (var s = 0; s < span; s++) {
- colToColGroup.push(colGroupCtr);
- }
- } else {
- // Default span value is 1
- colToColGroup.push(colGroupCtr);
- }
- }
- }
- return colToColGroup;
-
-};
-
-
-/**
- * Utility function to push an element into a given array only if that element
- * is not already contained in the array.
- * @param {Array} givenArray The given array.
- * @param {Node} givenElement The given element.
- */
-cvox.TableUtil.pushIfNotContained = function(givenArray, givenElement) {
- if (givenArray.indexOf(givenElement) == -1) {
- givenArray.push(givenElement);
- }
-};
-
-
-/**
- * Returns a JavaScript array of all the non-nested rows in the given table.
- *
- * @param {Node} table A table node.
- * @return {Array} An array of all the child rows of the active table.
- */
-cvox.TableUtil.getChildRows = function(table) {
- return cvox.XpathUtil.evalXPath('child::tbody/tr | child::thead/tr | ' +
- 'child::*[attribute::role="row"]', table);
-};
-
-
-/**
- * Returns a JavaScript array of all the child cell <TD> or <TH> or
- * role='gridcell' nodes of the given row.
- *
- * @param {Node} rowNode The specified row node.
- * @return {Array} An array of all the child cells of the given row node.
- */
-cvox.TableUtil.getChildCells = function(rowNode) {
- return cvox.XpathUtil.evalXPath('child::td | child::th | ' +
- 'child::*[attribute::role="gridcell"] |' +
- 'child::*[attribute::role="rowheader"] |' +
- 'child::*[attribute::role="columnheader"]', rowNode);
-};
-
-
-/**
- * Returns a JavaScript array containing the cell in the active table
- * with the given ID.
- *
- * @param {Node} table A table node.
- * @param {string} cellID The specified ID.
- * @return {Array} An array containing the cell with the specified ID.
- */
-cvox.TableUtil.getCellWithID = function(table, cellID) {
- return cvox.XpathUtil.evalXPath('id(\'' + cellID + '\')', table);
-};
-
-
-/**
- * Returns a Javascript array containing the colgroup elements in the
- * active table.
- *
- * @param {Node} table A table node.
- * @return {Array} An array of all the colgroup elements in the active table.
- */
-cvox.TableUtil.getColGroups = function(table) {
- return cvox.XpathUtil.evalXPath('child::colgroup', table);
-};
-
-
-/**
- * Returns a Javascript array containing the child col elements of the given
- * colgroup element.
- *
- * @param {Node} colGroupNode The specified <COLGROUP> element.
- * @return {Array} An array of all of the child col elements of the given
- * colgroup element.
- */
-cvox.TableUtil.getColNodes = function(colGroupNode) {
- return cvox.XpathUtil.evalXPath('child::col', colGroupNode);
-};
-
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/time_widget.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/time_widget.js
deleted file mode 100644
index 8691d63fb85..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/time_widget.js
+++ /dev/null
@@ -1,221 +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.
-
-goog.provide('cvox.ChromeVoxHTMLTimeWidget');
-
-/**
- * @fileoverview Gives the user spoken feedback as they interact with the time
- * widget (input type=time).
- *
- */
-
-/**
- * A class containing the information needed to speak
- * a text change event to the user.
- *
- * @constructor
- * @param {Element} timeElem The time widget element.
- * @param {cvox.TtsInterface} tts The TTS object from ChromeVox.
- */
-cvox.ChromeVoxHTMLTimeWidget = function(timeElem, tts) {
- var self = this;
- this.timeElem_ = timeElem;
- this.timeTts_ = tts;
- this.pHours_ = -1;
- this.pMinutes_ = -1;
- this.pSeconds_ = 0;
- this.pMilliseconds_ = 0;
- this.pAmpm_ = '';
- this.pos_ = 0;
- this.maxPos_ = 2;
- this.keyListener_ = function(evt) {
- self.eventHandler_(evt);
- };
- this.blurListener_ = function(evt) {
- self.shutdown();
- };
- if (this.timeElem_.hasAttribute('step')) {
- var step = this.timeElem_.getAttribute('step');
- if (step > 0) { // 0 or invalid values show hh:mm AM/PM
- if (step >= 1) {
- this.maxPos_ = 3; // Anything larger than 1 shows hh:mm:ss AM/PM
- } else {
- this.maxPos_ = 4; // Anything less than 1 shows hh:mm:ss.ms AM/PM
- }
- }
- }
-
- // Ensure we have a reasonable value to start with.
- if (this.timeElem_.value.length == 0) {
- this.forceInitTime_();
- }
-
- // Move the cursor to the first position so that we are guaranteed to start
- // off at the hours position.
- for (var i = 0; i < this.maxPos_; i++) {
- var evt = document.createEvent('KeyboardEvent');
- evt.initKeyboardEvent(
- 'keydown', true, true, window, 'Left', 0, false, false, false, false);
- this.timeElem_.dispatchEvent(evt);
- evt = document.createEvent('KeyboardEvent');
- evt.initKeyboardEvent(
- 'keyup', true, true, window, 'Left', 0, false, false, false, false);
- this.timeElem_.dispatchEvent(evt);
- }
-
- this.timeElem_.addEventListener('keydown', this.keyListener_, false);
- this.timeElem_.addEventListener('keyup', this.keyListener_, false);
- this.timeElem_.addEventListener('blur', this.blurListener_, false);
- this.update_(true);
-};
-
-/**
- * Removes the key listeners for the time widget.
- *
- */
-cvox.ChromeVoxHTMLTimeWidget.prototype.shutdown = function() {
- this.timeElem_.removeEventListener('blur', this.blurListener_, false);
- this.timeElem_.removeEventListener('keydown', this.keyListener_, false);
- this.timeElem_.removeEventListener('keyup', this.keyListener_, false);
-};
-
-/**
- * Initialize to midnight.
- * @private
- */
-cvox.ChromeVoxHTMLTimeWidget.prototype.forceInitTime_ = function() {
- this.timeElem_.setAttribute('value', '12:00');
-};
-
-/**
- * Called when the position changes.
- * @private
- */
-cvox.ChromeVoxHTMLTimeWidget.prototype.handlePosChange_ = function() {
- if (this.pos_ < 0) {
- this.pos_ = 0;
- }
- if (this.pos_ > this.maxPos_) {
- this.pos_ = this.maxPos_;
- }
- // Reset the cached state of the new field so that the field will be spoken
- // in the update.
- if (this.pos_ == this.maxPos_) {
- this.pAmpm_ = '';
- return;
- }
- switch (this.pos_) {
- case 0:
- this.pHours_ = -1;
- break;
- case 1:
- this.pMinutes_ = -1;
- break;
- case 2:
- this.pSeconds_ = -1;
- break;
- case 3:
- this.pMilliseconds_ = -1;
- break;
- }
-};
-
-/**
- * @param {boolean} shouldSpeakLabel True if the label should be spoken.
- * @private
- */
-cvox.ChromeVoxHTMLTimeWidget.prototype.update_ = function(shouldSpeakLabel) {
- var splitTime = this.timeElem_.value.split(':');
- if (splitTime.length < 1) {
- this.forceInitTime_();
- return;
- }
-
- var hours = splitTime[0];
- var minutes = -1;
- var seconds = 0;
- var milliseconds = 0;
- var ampm = Msgs.getMsg('timewidget_am');
- if (splitTime.length > 1) {
- minutes = splitTime[1];
- }
- if (splitTime.length > 2) {
- var splitSecondsAndMilliseconds = splitTime[2].split('.');
- seconds = splitSecondsAndMilliseconds[0];
- if (splitSecondsAndMilliseconds.length > 1) {
- milliseconds = splitSecondsAndMilliseconds[1];
- }
- }
- if (hours > 12) {
- hours = hours - 12;
- ampm = Msgs.getMsg('timewidget_pm');
- }
- if (hours == 12) {
- ampm = Msgs.getMsg('timewidget_pm');
- }
- if (hours == 0) {
- hours = 12;
- ampm = Msgs.getMsg('timewidget_am');
- }
-
- var changeMessage = '';
-
- if (shouldSpeakLabel) {
- changeMessage = cvox.DomUtil.getName(this.timeElem_, true, true) + '\n';
- }
-
- if (hours != this.pHours_) {
- changeMessage = changeMessage + hours + ' ' +
- Msgs.getMsg('timewidget_hours') + '\n';
- this.pHours_ = hours;
- }
-
- if (minutes != this.pMinutes_) {
- changeMessage = changeMessage + minutes + ' ' +
- Msgs.getMsg('timewidget_minutes') + '\n';
- this.pMinutes_ = minutes;
- }
-
- if (seconds != this.pSeconds_) {
- changeMessage = changeMessage + seconds + ' ' +
- Msgs.getMsg('timewidget_seconds') + '\n';
- this.pSeconds_ = seconds;
- }
-
- if (milliseconds != this.pMilliseconds_) {
- changeMessage = changeMessage + milliseconds + ' ' +
- Msgs.getMsg('timewidget_milliseconds') + '\n';
- this.pMilliseconds_ = milliseconds;
- }
-
- if (ampm != this.pAmpm_) {
- changeMessage = changeMessage + ampm;
- this.pAmpm_ = ampm;
- }
-
- if (changeMessage.length > 0) {
- this.timeTts_.speak(changeMessage, cvox.QueueMode.FLUSH, null);
- }
-};
-
-/**
- * @param {Object} evt The event to handle.
- * @private
- */
-cvox.ChromeVoxHTMLTimeWidget.prototype.eventHandler_ = function(evt) {
- var shouldSpeakLabel = false;
- if (evt.type == 'keydown') {
- if (((evt.keyCode == 9) && !evt.shiftKey) || (evt.keyCode == 39)) {
- this.pos_++;
- this.handlePosChange_();
- shouldSpeakLabel = true;
- }
- if (((evt.keyCode == 9) && evt.shiftKey) || (evt.keyCode == 37)) {
- this.pos_--;
- this.handlePosChange_();
- shouldSpeakLabel = true;
- }
- }
- this.update_(shouldSpeakLabel);
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js
deleted file mode 100644
index 4ca1ec4183c..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_content.js
+++ /dev/null
@@ -1,482 +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 DOM traversal interface for moving a selection around a
- * webpage. Provides multiple granularities:
- * 1. Move by paragraph.
- * 2. Move by sentence.
- * 3. Move by line.
- * 4. Move by word.
- * 5. Move by character.
- */
-
-goog.provide('cvox.TraverseContent');
-
-goog.require('cvox.CursorSelection');
-goog.require('cvox.DomUtil');
-goog.require('cvox.SelectionUtil');
-goog.require('cvox.TraverseUtil');
-
-/**
- * Moves a selection around a document or within a provided DOM object.
- *
- * @constructor
- * @param {Node=} domObj a DOM node (optional).
- */
-cvox.TraverseContent = function(domObj) {
- if (domObj != null) {
- this.currentDomObj = domObj;
- } else {
- this.currentDomObj = document.body;
- }
- var range = document.createRange();
- // TODO (dmazzoni): Switch this to avoid using range methods. Range methods
- // can cause exceptions (such as if the node is not attached to the DOM).
- try {
- range.selectNode(this.currentDomObj);
- this.startCursor_ = new cvox.Cursor(
- range.startContainer, range.startOffset,
- cvox.TraverseUtil.getNodeText(range.startContainer));
- this.endCursor_ = new cvox.Cursor(
- range.endContainer, range.endOffset,
- cvox.TraverseUtil.getNodeText(range.endContainer));
- } catch (e) {
- // Ignoring this error so that it will not break everything else.
- window.console.log('Error: Unselectable node:');
- window.console.log(domObj);
- }
-};
-goog.addSingletonGetter(cvox.TraverseContent);
-
-/**
- * Whether the last navigated selection only contained whitespace.
- * @type {boolean}
- */
-cvox.TraverseContent.prototype.lastSelectionWasWhitespace = false;
-
-/**
- * Whether we should skip whitespace when traversing individual characters.
- * @type {boolean}
- */
-cvox.TraverseContent.prototype.skipWhitespace = false;
-
-/**
- * If moveNext and movePrev should skip past an invalid selection,
- * so the user never gets stuck. Ideally the navigation code should never
- * return a range that's not a valid selection, but this keeps the user from
- * getting stuck if that code fails. This is set to false for unit testing.
- * @type {boolean}
- */
-cvox.TraverseContent.prototype.skipInvalidSelections = true;
-
-/**
- * If line and sentence navigation should break at <a> links.
- * @type {boolean}
- */
-cvox.TraverseContent.prototype.breakAtLinks = true;
-
-/**
- * The string constant for character granularity.
- * @type {string}
- * @const
- */
-cvox.TraverseContent.kCharacter = 'character';
-
-/**
- * The string constant for word granularity.
- * @type {string}
- * @const
- */
-cvox.TraverseContent.kWord = 'word';
-
-/**
- * The string constant for sentence granularity.
- * @type {string}
- * @const
- */
-cvox.TraverseContent.kSentence = 'sentence';
-
-/**
- * The string constant for line granularity.
- * @type {string}
- * @const
- */
-cvox.TraverseContent.kLine = 'line';
-
-/**
- * The string constant for paragraph granularity.
- * @type {string}
- * @const
- */
-cvox.TraverseContent.kParagraph = 'paragraph';
-
-/**
- * A constant array of all granularities.
- * @type {Array<string>}
- * @const
- */
-cvox.TraverseContent.kAllGrains =
- [cvox.TraverseContent.kParagraph,
- cvox.TraverseContent.kSentence,
- cvox.TraverseContent.kLine,
- cvox.TraverseContent.kWord,
- cvox.TraverseContent.kCharacter];
-
-/**
- * Set the current position to match the current WebKit selection.
- */
-cvox.TraverseContent.prototype.syncToSelection = function() {
- this.normalizeSelection();
-
- var selection = window.getSelection();
- if (!selection || !selection.anchorNode || !selection.focusNode) {
- return;
- }
- this.startCursor_ = new cvox.Cursor(
- selection.anchorNode, selection.anchorOffset,
- cvox.TraverseUtil.getNodeText(selection.anchorNode));
- this.endCursor_ = new cvox.Cursor(
- selection.focusNode, selection.focusOffset,
- cvox.TraverseUtil.getNodeText(selection.focusNode));
-};
-
-/**
- * Set the start and end cursors to the selection.
- * @param {cvox.CursorSelection} sel The selection.
- */
-cvox.TraverseContent.prototype.syncToCursorSelection = function(sel) {
- this.startCursor_ = sel.start.clone();
- this.endCursor_ = sel.end.clone();
-};
-
-/**
- * Get the cursor selection.
- * @return {cvox.CursorSelection} The selection.
- */
-cvox.TraverseContent.prototype.getCurrentCursorSelection = function() {
- return new cvox.CursorSelection(this.startCursor_, this.endCursor_);
-};
-
-/**
- * Set the WebKit selection based on the current position.
- */
-cvox.TraverseContent.prototype.updateSelection = function() {
- cvox.TraverseUtil.setSelection(this.startCursor_, this.endCursor_);
- cvox.SelectionUtil.scrollToSelection(window.getSelection());
-};
-
-/**
- * Get the current position as a range.
- * @return {Range} The current range.
- */
-cvox.TraverseContent.prototype.getCurrentRange = function() {
- var range = document.createRange();
- try {
- range.setStart(this.startCursor_.node, this.startCursor_.index);
- range.setEnd(this.endCursor_.node, this.endCursor_.index);
- } catch (e) {
- console.log('Invalid range ');
- }
- return range;
-};
-
-/**
- * Get the current text content as a string.
- * @return {string} The current spanned content.
- */
-cvox.TraverseContent.prototype.getCurrentText = function() {
- return cvox.SelectionUtil.getRangeText(this.getCurrentRange());
-};
-
-/**
- * Collapse to the end of the range.
- */
-cvox.TraverseContent.prototype.collapseToEnd = function() {
- this.startCursor_ = this.endCursor_.clone();
-};
-
-/**
- * Collapse to the start of the range.
- */
-cvox.TraverseContent.prototype.collapseToStart = function() {
- this.endCursor_ = this.startCursor_.clone();
-};
-
-/**
- * Moves selection forward.
- *
- * @param {string} grain specifies "sentence", "word", "character",
- * or "paragraph" granularity.
- * @return {?string} Either:
- * 1) The new selected text.
- * 2) null if the end of the domObj has been reached.
- */
-cvox.TraverseContent.prototype.moveNext = function(grain) {
- var breakTags = this.getBreakTags();
-
- // As a special case, if the current selection is empty or all
- // whitespace, ensure that the next returned selection will NOT be
- // only whitespace - otherwise you can get trapped.
- var skipWhitespace = this.skipWhitespace;
-
- var range = this.getCurrentRange();
- if (!cvox.SelectionUtil.isRangeValid(range)) {
- skipWhitespace = true;
- }
-
- var elementsEntered = [];
- var elementsLeft = [];
- var str;
- do {
- if (grain === cvox.TraverseContent.kSentence) {
- str = cvox.TraverseUtil.getNextSentence(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- breakTags);
- } else if (grain === cvox.TraverseContent.kWord) {
- str = cvox.TraverseUtil.getNextWord(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft);
- } else if (grain === cvox.TraverseContent.kCharacter) {
- str = cvox.TraverseUtil.getNextChar(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- skipWhitespace);
- } else if (grain === cvox.TraverseContent.kParagraph) {
- str = cvox.TraverseUtil.getNextParagraph(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft);
- } else if (grain === cvox.TraverseContent.kLine) {
- str = cvox.TraverseUtil.getNextLine(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- breakTags);
- } else {
- // User has provided an invalid string.
- // Fall through to default: extend by sentence
- window.console.log('Invalid selection granularity: "' + grain + '"');
- grain = cvox.TraverseContent.kSentence;
- str = cvox.TraverseUtil.getNextSentence(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- breakTags);
- }
-
- if (str == null) {
- // We reached the end of the document.
- return null;
- }
-
- range = this.getCurrentRange();
- var isInvalid = !range.getBoundingClientRect();
- } while (this.skipInvalidSelections && isInvalid);
-
- if (!cvox.SelectionUtil.isRangeValid(range)) {
- // It's OK if the selection navigation lands on whitespace once (in
- // character granularity), but if it hits whitespace more than once, then
- // skip forward until there is real content.
- if (!this.lastSelectionWasWhitespace &&
- grain == cvox.TraverseContent.kCharacter) {
- this.lastSelectionWasWhitespace = true;
- } else {
- while (!cvox.SelectionUtil.isRangeValid(this.getCurrentRange())) {
- if (this.moveNext(grain) == null) {
- break;
- }
- }
- }
- } else {
- this.lastSelectionWasWhitespace = false;
- }
-
- return this.getCurrentText();
-};
-
-
-/**
- * Moves selection backward.
- *
- * @param {string} grain specifies "sentence", "word", "character",
- * or "paragraph" granularity.
- * @return {?string} Either:
- * 1) The new selected text.
- * 2) null if the beginning of the domObj has been reached.
- */
-cvox.TraverseContent.prototype.movePrev = function(grain) {
- var breakTags = this.getBreakTags();
-
- // As a special case, if the current selection is empty or all
- // whitespace, ensure that the next returned selection will NOT be
- // only whitespace - otherwise you can get trapped.
- var skipWhitespace = this.skipWhitespace;
-
- var range = this.getCurrentRange();
- if (!cvox.SelectionUtil.isRangeValid(range)) {
- skipWhitespace = true;
- }
-
- var elementsEntered = [];
- var elementsLeft = [];
- var str;
- do {
- if (grain === cvox.TraverseContent.kSentence) {
- str = cvox.TraverseUtil.getPreviousSentence(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- breakTags);
- } else if (grain === cvox.TraverseContent.kWord) {
- str = cvox.TraverseUtil.getPreviousWord(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft);
- } else if (grain === cvox.TraverseContent.kCharacter) {
- str = cvox.TraverseUtil.getPreviousChar(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- skipWhitespace);
- } else if (grain === cvox.TraverseContent.kParagraph) {
- str = cvox.TraverseUtil.getPreviousParagraph(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft);
- } else if (grain === cvox.TraverseContent.kLine) {
- str = cvox.TraverseUtil.getPreviousLine(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- breakTags);
- } else {
- // User has provided an invalid string.
- // Fall through to default: extend by sentence
- window.console.log('Invalid selection granularity: "' + grain + '"');
- grain = cvox.TraverseContent.kSentence;
- str = cvox.TraverseUtil.getPreviousSentence(
- this.startCursor_, this.endCursor_, elementsEntered, elementsLeft,
- breakTags);
- }
-
- if (str == null) {
- // We reached the end of the document.
- return null;
- }
-
- range = this.getCurrentRange();
- var isInvalid = !range.getBoundingClientRect();
- } while (this.skipInvalidSelections && isInvalid);
-
- if (!cvox.SelectionUtil.isRangeValid(range)) {
- // It's OK if the selection navigation lands on whitespace once (in
- // character granularity), but if it hits whitespace more than once, then
- // skip forward until there is real content.
- if (!this.lastSelectionWasWhitespace &&
- grain == cvox.TraverseContent.kCharacter) {
- this.lastSelectionWasWhitespace = true;
- } else {
- while (!cvox.SelectionUtil.isRangeValid(this.getCurrentRange())) {
- if (this.movePrev(grain) == null) {
- break;
- }
- }
- }
- } else {
- this.lastSelectionWasWhitespace = false;
- }
-
- return this.getCurrentText();
-};
-
-/**
- * Get the tag names that should break a sentence or line. Currently
- * just an anchor 'A' should break a sentence or line if the breakAtLinks
- * flag is true, but in the future we might have other rules for breaking.
- *
- * @return {Object} An associative array mapping a tag name to true if
- * it should break a sentence or line.
- */
-cvox.TraverseContent.prototype.getBreakTags = function() {
- return {
- 'A': this.breakAtLinks,
- 'BR': true,
- 'HR': true
- };
-};
-
-/**
- * Selects the next element of the document or within the provided DOM object.
- * Scrolls the window as appropriate.
- *
- * @param {string} grain specifies "sentence", "word", "character",
- * or "paragraph" granularity.
- * @param {Node=} domObj a DOM node (optional).
- * @return {?string} Either:
- * 1) The new selected text.
- * 2) null if the end of the domObj has been reached.
- */
-cvox.TraverseContent.prototype.nextElement = function(grain, domObj) {
- if (domObj != null) {
- this.currentDomObj = domObj;
- }
-
- var result = this.moveNext(grain);
- if (result != null &&
- (!cvox.DomUtil.isDescendantOfNode(
- this.startCursor_.node, this.currentDomObj) ||
- !cvox.DomUtil.isDescendantOfNode(
- this.endCursor_.node, this.currentDomObj))) {
- return null;
- }
-
- return result;
-};
-
-
-/**
- * Selects the previous element of the document or within the provided DOM
- * object. Scrolls the window as appropriate.
- *
- * @param {string} grain specifies "sentence", "word", "character",
- * or "paragraph" granularity.
- * @param {Node=} domObj a DOM node (optional).
- * @return {?string} Either:
- * 1) The new selected text.
- * 2) null if the beginning of the domObj has been reached.
- */
-cvox.TraverseContent.prototype.prevElement = function(grain, domObj) {
- if (domObj != null) {
- this.currentDomObj = domObj;
- }
-
- var result = this.movePrev(grain);
- if (result != null &&
- (!cvox.DomUtil.isDescendantOfNode(
- this.startCursor_.node, this.currentDomObj) ||
- !cvox.DomUtil.isDescendantOfNode(
- this.endCursor_.node, this.currentDomObj))) {
- return null;
- }
-
- return result;
-};
-
-/**
- * Make sure that exactly one item is selected. If there's no selection,
- * set the selection to the start of the document.
- */
-cvox.TraverseContent.prototype.normalizeSelection = function() {
- var selection = window.getSelection();
- if (selection.rangeCount < 1) {
- // Before the user has clicked a freshly-loaded page
-
- var range = document.createRange();
- range.setStart(this.currentDomObj, 0);
- range.setEnd(this.currentDomObj, 0);
-
- selection.removeAllRanges();
- selection.addRange(range);
-
- } else if (selection.rangeCount > 1) {
- // Multiple ranges exist - remove all ranges but the last one
- for (var i = 0; i < (selection.rangeCount - 1); i++) {
- selection.removeRange(selection.getRangeAt(i));
- }
- }
-};
-
-/**
- * Resets the selection.
- *
- * @param {Node=} domObj a DOM node. Optional.
- *
- */
-cvox.TraverseContent.prototype.reset = function(domObj) {
- window.getSelection().removeAllRanges();
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js
deleted file mode 100644
index f14d8c29242..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_math.js
+++ /dev/null
@@ -1,446 +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.
-
-goog.provide('cvox.TraverseMath');
-
-goog.require('cvox.ChromeVox');
-goog.require('cvox.DomUtil');
-goog.require('cvox.SemanticTree');
-
-
-/**
- * Initializes the traversal with the provided math node.
- *
- * @constructor
- */
-cvox.TraverseMath = function() {
- /**
- * The active math <MATH> node. In this context, "active" means that this is
- * the math expression the TraverseMath object is navigating.
- * @type {Node}
- */
- this.activeMath = null;
-
- /**
- * The node currently under inspection.
- * @type {Node}
- */
- this.activeNode = null;
-
- /**
- * Dictionary of all LaTeX elements in the page if there are any.
- * @type {!Object<!Node>}
- * @private
- */
- this.allTexs_ = {};
-
- /**
- * Dictionary of all MathJaxs elements in the page if there are any.
- * @type {!Object<!Node>}
- * @private
- */
- this.allMathjaxs_ = {};
-
- /**
- * Dictionary of all MathJaxs elements that have not yet been translated at
- * page load or during MathJax rendering.
- * @type {!Object<!Node>}
- * @private
- */
- this.todoMathjaxs_ = {};
-
- /**
- * When traversing a Mathjax node this will contain the internal
- * MathML representation of the node.
- * @type {Node}
- */
- this.activeMathmlHost = null;
-
- /**
- * Semantic representation of the current node.
- * @type {Node}
- */
- this.activeSemanticHost = null;
-
- /**
- * List of domain names.
- * @type {Array<string>}
- */
- this.allDomains = [];
-
- /**
- * List of style names.
- * @type {Array<string>}
- */
- this.allStyles = [];
-
- /**
- * Current domain.
- * @type {string}
- */
- this.domain = 'default';
-
- /**
- * Current style.
- * @type {string}
- */
- this.style = 'short';
-
- /**
- * Initialize special objects if necessary.
- */
- if (cvox.ChromeVox.mathJax) {
- this.initializeMathjaxs();
- this.initializeAltMaths();
- }
-};
-goog.addSingletonGetter(cvox.TraverseMath);
-
-
-/**
- * @type {boolean}
- * @private
- */
-cvox.TraverseMath.setSemantic_ = false;
-
-
-/**
- * Toggles the semantic setting.
- * @return {boolean} True if semantic interpretation is switched on. False
- * otherwise.
- */
-cvox.TraverseMath.toggleSemantic = function() {
- return cvox.TraverseMath.setSemantic_ = !cvox.TraverseMath.setSemantic_;
-};
-
-
-/**
- * Initializes a traversal of a math expression.
- * @param {Node} node A MathML node.
- */
-cvox.TraverseMath.prototype.initialize = function(node) {
- if (cvox.DomUtil.isMathImg(node)) {
- // If a node has a cvoxid attribute we know that it contains a LaTeX
- // expression that we have rewritten into its corresponding MathML
- // representation, which we can speak and walk.
- if (!node.hasAttribute('cvoxid')) {
- return;
- }
- var cvoxid = node.getAttribute('cvoxid');
- node = this.allTexs_[cvoxid];
- }
- if (cvox.DomUtil.isMathJax(node)) {
- this.activeMathmlHost = this.allMathjaxs_[node.getAttribute('id')];
- }
- this.activeMath = this.activeMathmlHost || node;
- this.activeNode = this.activeMathmlHost || node;
- if (this.activeNode && cvox.TraverseMath.setSemantic_ &&
- this.activeNode.nodeType == Node.ELEMENT_NODE) {
- this.activeNode =
- (new cvox.SemanticTree(/** @type {!Element} */ (this.activeNode))).xml();
- }
-};
-
-
-/**
- * Adds a mapping of a MathJax node to its MathML representation to the
- * dictionary of MathJax elements.
- * @param {!Node} mml The MathML node.
- * @param {string} id The MathJax node id.
- */
-cvox.TraverseMath.prototype.addMathjax = function(mml, id) {
- var spanId = cvox.DomUtil.getMathSpanId(id);
- if (spanId) {
- this.allMathjaxs_[spanId] = mml;
- } else {
- this.redoMathjaxs(mml, id);
- }
-};
-
-
-/**
- * Retries to compute MathML representations of MathJax elements, if
- * they have not been filled in during rendering.
- * @param {!Node} mml The MathML node.
- * @param {string} id The MathJax node id.
- */
-cvox.TraverseMath.prototype.redoMathjaxs = function(mml, id) {
- var fetch = goog.bind(function() {this.addMathjax(mml, id);}, this);
- setTimeout(fetch, 500);
-};
-
-
-/**
- * Initializes the MathJax to MathML mapping.
- * We first try to get all MathJax elements that are already being rendered.
- * Secondly, we register a signal to get updated on all elements that are
- * rendered or re-rendered later.
- */
-cvox.TraverseMath.prototype.initializeMathjaxs = function() {
- var callback =
- goog.bind(function(mml, id) {
- this.addMathjax(mml, id);
- }, this);
- cvox.ChromeVox.mathJax.isMathjaxActive(
- function(bool) {
- if (bool) {
- cvox.ChromeVox.mathJax.getAllJax(callback);
- cvox.ChromeVox.mathJax.registerSignal(callback, 'New Math');
- }
- });
-};
-
-
-/**
- * Initializes the elements in the page that we identify as potentially
- * containing tex or asciimath alt text.
- */
-cvox.TraverseMath.prototype.initializeAltMaths = function() {
- if (!document.querySelector(
- cvox.DomUtil.altMathQuerySelector('tex') + ', ' +
- cvox.DomUtil.altMathQuerySelector('asciimath'))) {
- return;
- }
- var callback = goog.bind(
- function(mml, id) {
- this.allTexs_[id] = mml;
- }, this);
- // Inject a minimalistic version of MathJax into the page.
- cvox.ChromeVox.mathJax.injectScripts();
- // Once MathJax is injected we harvest all Latex and AsciiMath in alt
- // attributes and translate them to MathML expression.
- cvox.ChromeVox.mathJax.isMathjaxActive(
- function(active) {
- if (active) {
- cvox.ChromeVox.mathJax.configMediaWiki();
- cvox.ChromeVox.mathJax.getAllTexs(callback);
- cvox.ChromeVox.mathJax.getAllAsciiMaths(callback);
- }
- });
-};
-
-
-/**
- * Moves to the next leaf node in the current Math expression if it exists.
- * @param {boolean} reverse True if reversed. False by default.
- * @param {function(!Node):boolean} pred Predicate deciding what a leaf is.
- * @return {Node} The next node.
- */
-cvox.TraverseMath.prototype.nextLeaf = function(reverse, pred) {
- if (this.activeNode && this.activeMath) {
- var next = pred(this.activeNode) ?
- cvox.DomUtil.directedFindNextNode(
- this.activeNode, this.activeMath, reverse, pred) :
- cvox.DomUtil.directedFindFirstNode(this.activeNode, reverse, pred);
- if (next) {
- this.activeNode = next;
- }
- }
- return this.activeNode;
-};
-
-
-// TODO (sorge) Refactor this logic into single walkers.
-/**
- * Returns a string with the content of the active node.
- * @return {string} The active content.
- */
-cvox.TraverseMath.prototype.activeContent = function() {
- return this.activeNode.textContent;
-};
-
-
-/**
- * Moves to the next subtree from a given node in a depth first fashion.
- * @param {boolean} reverse True if reversed. False by default.
- * @param {function(!Node):boolean} pred Predicate deciding what a subtree is.
- * @return {Node} The next subtree.
- */
-cvox.TraverseMath.prototype.nextSubtree = function(reverse, pred) {
- if (!this.activeNode || !this.activeMath) {
- return null;
- }
- if (!reverse) {
- var child = cvox.DomUtil.directedFindFirstNode(
- this.activeNode, reverse, pred);
- if (child) {
- this.activeNode = child;
- } else {
- var next = cvox.DomUtil.directedFindNextNode(
- this.activeNode, this.activeMath, reverse, pred);
- if (next) {
- this.activeNode = next;
- }
- }
- } else {
- if (this.activeNode == this.activeMath) {
- var child = cvox.DomUtil.directedFindDeepestNode(
- this.activeNode, reverse, pred);
- if (child != this.activeNode) {
- this.activeNode = child;
- return this.activeNode;
- }
- }
- var prev = cvox.DomUtil.directedFindNextNode(
- this.activeNode, this.activeMath, reverse, pred, true, true);
- if (prev) {
- this.activeNode = prev;
- }
- }
- return this.activeNode;
-};
-
-
-/**
- * left or right in the math expression.
- * Navigation is bounded by the presence of a sibling.
- * @param {boolean} r True to move left; false to move right.
- * @return {Node} The result.
- */
-cvox.TraverseMath.prototype.nextSibling = function(r) {
- if (!this.activeNode || !this.activeMath) {
- return null;
- }
- var node = this.activeNode;
- node = r ? node.previousSibling : node.nextSibling;
- if (!node) {
- return null;
- }
- this.activeNode = node;
- return this.activeNode;
-};
-
-
-/**
- * Moves up or down the math expression.
- * Navigation is bounded by the root math expression.
- * @param {boolean} r True to move up; false to move down.
- * @return {Node} The result.
- */
-cvox.TraverseMath.prototype.nextParentChild = function(r) {
- if (!this.activeNode || !this.activeMath) {
- return null;
- }
- if (this.activeNode == this.activeMath && r) {
- return null;
- }
- var node = this.activeNode;
- node = r ? node.parentNode : node.firstChild;
- if (!node) {
- return null;
- }
- this.activeNode = node;
- return this.activeNode;
-};
-
-
-/**
- * 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.
- */
-cvox.TraverseMath.prototype.addDomainsAndStyles = function(domains, styles) {
- this.allDomains.push.apply(
- this.allDomains,
- domains.filter(
- goog.bind(function(x) {return this.allDomains.indexOf(x) < 0;},
- this)));
- this.allStyles.push.apply(
- this.allStyles,
- styles.filter(
- goog.bind(function(x) {return this.allStyles.indexOf(x) < 0;},
- this)));
-};
-
-
-/**
- * Gets a list of domains and styles from the symbol and function mappings.
- * Depending on the platform they either live in the background page or
- * in the android math map.
- */
-cvox.TraverseMath.prototype.initDomainsAndStyles = function() {
- if (cvox.ChromeVox.host['mathMap']) {
- this.addDomainsAndStyles(
- cvox.ChromeVox.host['mathMap'].allDomains,
- cvox.ChromeVox.host['mathMap'].allStyles);
- } else {
- cvox.ChromeVox.host.sendToBackgroundPage(
- {'target': 'Math',
- 'action': 'getDomains'});
- }
-};
-
-
-/**
- * Sets the domain for the TraverseMath object to the next one in the list
- * restarting from the first, if necessary.
- * @return {string} The name of the newly set domain.
- */
-cvox.TraverseMath.prototype.cycleDomain = function() {
- this.initDomainsAndStyles();
- var index = this.allDomains.indexOf(this.domain);
- if (index == -1) {
- return this.domain;
- }
- this.domain = this.allDomains[(++index) % this.allDomains.length];
- return this.domain;
-};
-
-
-/**
- * Sets the style for the TraverseMath object to the next one in the list
- * restarting from the first, if necessary.
- * @return {string} The name of the newly set style.
- */
-cvox.TraverseMath.prototype.cycleStyle = function() {
- this.initDomainsAndStyles();
- var index = this.allStyles.indexOf(this.style);
- if (index == -1) {
- return this.domain;
- }
- this.style = this.allStyles[(++index) % this.allStyles.length];
- return this.style;
-};
-
-
-/**
- * Sets the domain for the TraverseMath object.
- * @param {string} domain Name of the domain.
- * @private
- */
-cvox.TraverseMath.prototype.setDomain_ = function(domain) {
- if (this.allDomains.indexOf(domain) != -1) {
- this.domain = domain;
- } else {
- this.domain = 'default';
- }
-};
-
-
-/**
- * Sets the style for the TraverseMath object.
- * @param {string} style Name of the style.
- * @private
- */
-cvox.TraverseMath.prototype.setStyle_ = function(style) {
- if (this.allStyles.indexOf(style) != -1) {
- this.style = style;
- } else {
- this.style = 'default';
- }
-};
-
-
-/**
- * Gets the active node attached to the current document.
- * @return {Node} The active node, if it exists.
- */
-cvox.TraverseMath.prototype.getAttachedActiveNode = function() {
- var node = this.activeNode;
- if (!node || node.nodeType != Node.ELEMENT_NODE) {
- return null;
- }
- var id = node.getAttribute('spanID');
- return document.getElementById(id);
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js
deleted file mode 100644
index 8927c1d8846..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_table.js
+++ /dev/null
@@ -1,1309 +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.
-
-/**
- * TODO(stoarca): This class has become obsolete except for the shadow table.
- * Chop most of it away.
- * @fileoverview A DOM traversal interface for navigating data in tables.
- */
-
-goog.provide('cvox.TraverseTable');
-
-goog.require('cvox.DomPredicates');
-goog.require('cvox.DomUtil');
-goog.require('cvox.SelectionUtil');
-goog.require('cvox.TableUtil');
-goog.require('cvox.TraverseUtil');
-
-
-
-/**
- * An object that represents an active table cell inside the shadow table.
- * @constructor
- */
-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 = [];
-}
-
-
-/**
- * Whether or not the active cell is spanned by a preceding cell.
- * @type {boolean}
- */
-ShadowTableNode.prototype.spanned;
-
-
-/**
- * Whether or not this cell is spanned by a rowSpan.
- * @type {?boolean}
- */
-ShadowTableNode.prototype.rowSpan;
-
-
-/**
- * Whether or not this cell is spanned by a colspan
- * @type {?boolean}
- */
-ShadowTableNode.prototype.colSpan;
-
-
-/**
- * The row index of the corresponding active table cell
- * @type {?number}
- */
-ShadowTableNode.prototype.i;
-
-
-/**
- * The column index of the corresponding active table cell
- * @type {?number}
- */
-ShadowTableNode.prototype.j;
-
-
-/**
- * The corresponding <TD> or <TH> node in the active table.
- * @type {?Node}
- */
-ShadowTableNode.prototype.activeCell;
-
-
-/**
- * Initializes the traversal with the provided table node.
- *
- * @constructor
- * @param {Node} tableNode The table to be traversed.
- */
-cvox.TraverseTable = function(tableNode) {
-
- /**
- * The active table <TABLE> node. In this context, "active" means that this is
- * the table the TraverseTable object is navigating.
- * @type {Node}
- * @private
- */
- this.activeTable_ = null;
-
- /**
- * A 2D array "shadow table" that contains pointers to nodes in the active
- * table. More specifically, each cell of the shadow table contains a special
- * object ShadowTableNode that has as one of its member variables the
- * corresponding cell in the active table.
- *
- * The shadow table will allow us efficient navigation of tables with
- * rowspans and colspans without needing to repeatedly scan the table. For
- * example, if someone requests a cell at (1,3), predecessor cells with
- * rowspans/colspans mean the cell you eventually return could actually be
- * one located at (0,2) that spans out to (1,3).
- *
- * This shadow table will contain a ShadowTableNode with the (0, 2) index at
- * 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>>}
- * @private
- */
- this.shadowTable_ = [];
-
- /**
- * An array of shadow table nodes that have been determined to contain header
- * cells or information about header cells. This array is collected at
- * 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>}
- * @private
- */
- this.candidateHeaders_ = [];
-
- /**
- * An array that associates cell IDs with their corresponding shadow nodes.
- * If there are two shadow nodes for the same cell (i.e. when a cell spans
- * 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>}
- * @private
- */
- this.idToShadowNode_ = [];
-
- this.initialize(tableNode);
-};
-
-
-/**
- * The cell cursor, represented by an array that stores the row and
- * column location [i, j] of the active cell. These numbers are 0-based.
- * In this context, "active" means that this is the cell the user is
- * currently looking at.
- * @type {Array}
- */
-cvox.TraverseTable.prototype.currentCellCursor;
-
-
-/**
- * The number of columns in the active table. This is calculated at
- * initialization and then only recalculated if the table changes.
- *
- * Please Note: We have chosen to use the number of columns in the shadow
- * table as the canonical column count. This is important for tables that
- * have colspans - the number of columns in the active table will always be
- * less than the true number of columns.
- * @type {?number}
- */
-cvox.TraverseTable.prototype.colCount = null;
-
-
-/**
- * The number of rows in the active table. This is calculated at
- * initialization and then only recalculated if the table changes.
- * @type {?number}
- */
-cvox.TraverseTable.prototype.rowCount = null;
-
-
-/**
- * The row headers in the active table. This is calculated at
- * initialization and then only recalculated if the table changes.
- *
- * Please Note:
- * Row headers are defined here as <TH> or <TD> elements. <TD> elements when
- * serving as header cells must have either:
- * - The scope attribute defined
- * - Their IDs referenced in the header content attribute of another <TD> or
- * <TH> element.
- *
- * The HTML5 spec specifies that only header <TH> elements can be row headers
- * ( http://dev.w3.org/html5/spec/tabular-data.html#row-header ) but the
- * HTML4 spec says that <TD> elements can act as both
- * ( http://www.w3.org/TR/html401/struct/tables.html#h-11.2.6 ). In the
- * interest of providing meaningful header information for all tables, here
- * we take the position that <TD> elements can act as both.
- *
- * @type {Array}
- */
-cvox.TraverseTable.prototype.tableRowHeaders = null;
-
-
-/**
- * The column headers in the active table. This is calculated at
- * initialization and then only recalculated if the table changes.
- *
- * Please Note: see comment for tableRowHeaders.
- *
- * @type {Array}
- */
-cvox.TraverseTable.prototype.tableColHeaders = null;
-
-
-// TODO (stoarca): tighten up interface to {!Node}
-/**
- * Initializes the class member variables.
- * @param {Node} tableNode The table to be traversed.
- */
-cvox.TraverseTable.prototype.initialize = function(tableNode) {
- if (!tableNode) {
- return;
- }
- if (tableNode == this.activeTable_) {
- return;
- }
- this.activeTable_ = tableNode;
- this.currentCellCursor = null;
-
- this.tableRowHeaders = [];
- this.tableColHeaders = [];
-
- this.buildShadowTable_();
-
- this.colCount = this.shadowColCount_();
- this.rowCount = this.countRows_();
-
- this.findHeaderCells_();
-
- // Listen for changes to the active table. If the active table changes,
- // rebuild the shadow table.
- // TODO (stoarca): Is this safe? When this object goes away, doesn't the
- // eventListener stay on the node? Someone with better knowledge of js
- // please confirm. If so, this is a leak.
- this.activeTable_.addEventListener('DOMSubtreeModified',
- goog.bind(function() {
- this.buildShadowTable_();
- this.colCount = this.shadowColCount_();
- this.rowCount = this.countRows_();
-
- this.tableRowHeaders = [];
- this.tableColHeaders = [];
- this.findHeaderCells_();
-
- if (this.colCount == 0 && this.rowCount == 0) {
- return;
- }
-
- if (this.getCell() == null) {
- this.attachCursorToNearestCell_();
- }
- }, this), false);
-};
-
-
-/**
- * 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.
- */
-cvox.TraverseTable.prototype.findNearestCursor = function(node) {
- // TODO (stoarca): The current structure for representing the
- // shadow table is not optimal for this query, but it's not urgent
- // since this only gets executed at most once per user action.
-
- // In case node is in a table but above any individual cell, we go down as
- // deep as we can, being careful to avoid going into nested tables.
- var n = node;
-
- while (n.firstElementChild &&
- !(n.firstElementChild.tagName == 'TABLE' ||
- cvox.AriaUtil.isGrid(n.firstElementChild))) {
- n = n.firstElementChild;
- }
- while (!cvox.DomPredicates.cellPredicate(cvox.DomUtil.getAncestors(n))) {
- n = cvox.DomUtil.directedNextLeafNode(n);
- // TODO(stoarca): Ugly logic. Captions should be part of tables.
- // There have been a bunch of bugs as a result of
- // DomUtil.findTableNodeInList excluding captions from tables because
- // it makes them non-contiguous.
- if (!cvox.DomUtil.getContainingTable(n, {allowCaptions: true})) {
- return null;
- }
- }
- for (var i = 0; i < this.rowCount; ++i) {
- for (var j = 0; j < this.colCount; ++j) {
- if (this.shadowTable_[i][j]) {
- if (cvox.DomUtil.isDescendantOfNode(
- n, this.shadowTable_[i][j].activeCell)) {
- return [i, j];
- }
- }
- }
- }
- return null;
-};
-
-/**
- * Finds the valid cell nearest to the current cell cursor and moves the cell
- * cursor there. To be used when the table has changed and the current cell
- * cursor is now invalid (doesn't exist anymore).
- * @private
- */
-cvox.TraverseTable.prototype.attachCursorToNearestCell_ = function() {
- if (!this.currentCellCursor) {
- // We have no idea. Just go 'somewhere'. Other code paths in this
- // function go to the last cell, so let's do that!
- this.goToLastCell();
- return;
- }
-
- var currentCursor = this.currentCellCursor;
-
- // Does the current row still exist in the table?
- var currentRow = this.shadowTable_[currentCursor[0]];
- if (currentRow) {
- // Try last cell of current row
- this.currentCellCursor = [currentCursor[0], (currentRow.length - 1)];
- } else {
- // Current row does not exist anymore. Does current column still exist?
- // Try last cell of current column
- var numRows = this.shadowTable_.length;
- if (numRows == 0) {
- // Table has been deleted!
- this.currentCellCursor = null;
- return;
- }
- var aboveCell =
- this.shadowTable_[numRows - 1][currentCursor[1]];
- if (aboveCell) {
- this.currentCellCursor = [(numRows - 1), currentCursor[1]];
- } else {
- // Current column does not exist anymore either.
- // Move cursor to last cell in table.
- this.goToLastCell();
- }
- }
-};
-
-
-/**
- * Builds or rebuilds the shadow table by iterating through all of the cells
- * ( <TD> or <TH> or role='gridcell' nodes) of the active table.
- * @return {!Array} The shadow table.
- * @private
- */
-cvox.TraverseTable.prototype.buildShadowTable_ = function() {
- // Clear shadow table
- this.shadowTable_ = [];
-
- // Build shadow table structure. Initialize it as a 2D array.
- var allRows = cvox.TableUtil.getChildRows(this.activeTable_);
- var currentRowParent = null;
- var currentRowGroup = null;
-
- var colGroups = cvox.TableUtil.getColGroups(this.activeTable_);
- var colToColGroup = cvox.TableUtil.determineColGroups(colGroups);
-
- for (var ctr = 0; ctr < allRows.length; ctr++) {
- this.shadowTable_.push([]);
- }
-
- // Iterate through active table by row
- for (var i = 0; i < allRows.length; i++) {
- var childCells = cvox.TableUtil.getChildCells(allRows[i]);
-
- // Keep track of position in active table
- var activeTableCol = 0;
- // Keep track of position in shadow table
- var shadowTableCol = 0;
-
- while (activeTableCol < childCells.length) {
-
- // Check to make sure we haven't already filled this cell.
- if (this.shadowTable_[i][shadowTableCol] == null) {
-
- var activeTableCell = childCells[activeTableCol];
-
- // Default value for colspan and rowspan is 1
- var colsSpanned = 1;
- var rowsSpanned = 1;
-
- if (activeTableCell.hasAttribute('colspan')) {
-
- colsSpanned =
- parseInt(activeTableCell.getAttribute('colspan'), 10);
-
- if ((isNaN(colsSpanned)) || (colsSpanned <= 0)) {
- // The HTML5 spec defines colspan MUST be greater than 0:
- // http://dev.w3.org/html5/spec/Overview.html#attr-tdth-colspan
- //
- // This is a change from the HTML4 spec:
- // http://www.w3.org/TR/html401/struct/tables.html#adef-colspan
- //
- // We will degrade gracefully by treating a colspan=0 as
- // equivalent to a colspan=1.
- // Tested in method testColSpan0 in rowColSpanTable_test.js
- colsSpanned = 1;
- }
- }
- if (activeTableCell.hasAttribute('rowspan')) {
- rowsSpanned =
- parseInt(activeTableCell.getAttribute('rowspan'), 10);
-
- if ((isNaN(rowsSpanned)) || (rowsSpanned <= 0)) {
- // The HTML5 spec defines that rowspan can be any non-negative
- // integer, including 0:
- // http://dev.w3.org/html5/spec/Overview.html#attr-tdth-rowspan
- //
- // However, Chromium treats rowspan=0 as rowspan=1. This appears
- // to be a bug from WebKit:
- // https://bugs.webkit.org/show_bug.cgi?id=10300
- // Inherited from a bug (since fixed) in KDE:
- // http://bugs.kde.org/show_bug.cgi?id=41063
- //
- // We will follow Chromium and treat rowspan=0 as equivalent to
- // rowspan=1.
- //
- // Tested in method testRowSpan0 in rowColSpanTable_test.js
- //
- // Filed as a bug in Chromium: http://crbug.com/58223
- rowsSpanned = 1;
- }
- }
- for (var r = 0; r < rowsSpanned; r++) {
- for (var c = 0; c < colsSpanned; c++) {
- var shadowNode = new ShadowTableNode();
- if ((r == 0) && (c == 0)) {
- // This position is not spanned.
- shadowNode.spanned = false;
- shadowNode.rowSpan = false;
- shadowNode.colSpan = false;
- shadowNode.i = i;
- shadowNode.j = shadowTableCol;
- shadowNode.activeCell = activeTableCell;
- shadowNode.rowHeaderCells = [];
- shadowNode.colHeaderCells = [];
- shadowNode.isRowHeader = false;
- shadowNode.isColHeader = false;
- } else {
- // This position is spanned.
- shadowNode.spanned = true;
- shadowNode.rowSpan = (rowsSpanned > 1);
- shadowNode.colSpan = (colsSpanned > 1);
- shadowNode.i = i;
- shadowNode.j = shadowTableCol;
- shadowNode.activeCell = activeTableCell;
- shadowNode.rowHeaderCells = [];
- shadowNode.colHeaderCells = [];
- shadowNode.isRowHeader = false;
- shadowNode.isColHeader = false;
- }
- // Check this shadowNode to see if it is a candidate header cell
- if (cvox.TableUtil.checkIfHeader(shadowNode.activeCell)) {
- this.candidateHeaders_.push(shadowNode);
- } else if (shadowNode.activeCell.hasAttribute('headers')) {
- // This shadowNode has information about other header cells
- this.candidateHeaders_.push(shadowNode);
- }
-
- // Check and update row group status.
- if (currentRowParent == null) {
- // This is the first row
- currentRowParent = allRows[i].parentNode;
- currentRowGroup = 0;
- } else {
- if (allRows[i].parentNode != currentRowParent) {
- // We're in a different row group now
- currentRowParent = allRows[i].parentNode;
- currentRowGroup = currentRowGroup + 1;
- }
- }
- shadowNode.rowGroup = currentRowGroup;
-
- // Check and update col group status
- if (colToColGroup.length > 0) {
- shadowNode.colGroup = colToColGroup[shadowTableCol];
- } else {
- shadowNode.colGroup = 0;
- }
-
- if (! shadowNode.spanned) {
- if (activeTableCell.id != null) {
- this.idToShadowNode_[activeTableCell.id] = shadowNode;
- }
- }
-
- this.shadowTable_[i + r][shadowTableCol + c] = shadowNode;
- }
- }
- shadowTableCol += colsSpanned;
- activeTableCol++;
- } else {
- // This position has already been filled (by a previous cell that has
- // a colspan or a rowspan)
- shadowTableCol += 1;
- }
- }
- }
- return this.shadowTable_;
-};
-
-
-/**
- * Finds header cells from the list of candidate headers and classifies them
- * in two ways:
- * -- Identifies them for the entire table by adding them to
- * this.tableRowHeaders and this.tableColHeaders.
- * -- Identifies them for each shadow table node by adding them to the node's
- * rowHeaderCells or colHeaderCells arrays.
- *
- * @private
- */
-cvox.TraverseTable.prototype.findHeaderCells_ = function() {
- // Forming relationships between data cells and header cells:
- // http://dev.w3.org/html5/spec/tabular-data.html
- // #header-and-data-cell-semantics
-
- for (var i = 0; i < this.candidateHeaders_.length; i++) {
-
- var currentShadowNode = this.candidateHeaders_[i];
- var currentCell = currentShadowNode.activeCell;
-
- var assumedScope = null;
- var specifiedScope = null;
-
- if (currentShadowNode.spanned) {
- continue;
- }
-
- if ((currentCell.tagName == 'TH') &&
- !(currentCell.hasAttribute('scope'))) {
- // No scope specified - compute scope ourselves.
- // Go left/right - if there's a header node, then this is a column
- // header
- if (currentShadowNode.j > 0) {
- if (this.shadowTable_[currentShadowNode.i][currentShadowNode.j - 1].
- activeCell.tagName == 'TH') {
- assumedScope = 'col';
- }
- } else if (currentShadowNode.j < this.shadowTable_[currentShadowNode.i].
- length - 1) {
- if (this.shadowTable_[currentShadowNode.i][currentShadowNode.j + 1].
- activeCell.tagName == 'TH') {
- assumedScope = 'col';
- }
- } else {
- // This row has a width of 1 cell, just assume this is a colum header
- assumedScope = 'col';
- }
-
- if (assumedScope == null) {
- // Go up/down - if there's a header node, then this is a row header
- if (currentShadowNode.i > 0) {
- if (this.shadowTable_[currentShadowNode.i - 1][currentShadowNode.j].
- activeCell.tagName == 'TH') {
- assumedScope = 'row';
- }
- } else if (currentShadowNode.i < this.shadowTable_.length - 1) {
- if (this.shadowTable_[currentShadowNode.i + 1][currentShadowNode.j].
- activeCell.tagName == 'TH') {
- assumedScope = 'row';
- }
- } else {
- // This column has a height of 1 cell, just assume that this is
- // a row header
- assumedScope = 'row';
- }
- }
- } else if (currentCell.hasAttribute('scope')) {
- specifiedScope = currentCell.getAttribute('scope');
- } else if (currentCell.hasAttribute('role') &&
- (currentCell.getAttribute('role') == 'rowheader')) {
- specifiedScope = 'row';
- } else if (currentCell.hasAttribute('role') &&
- (currentCell.getAttribute('role') == 'columnheader')) {
- specifiedScope = 'col';
- }
-
- if ((specifiedScope == 'row') || (assumedScope == 'row')) {
- currentShadowNode.isRowHeader = true;
-
- // Go right until you hit the edge of the table or a data
- // cell after another header cell.
- // Add this cell to each shadowNode.rowHeaderCells attribute as you go.
- for (var rightCtr = currentShadowNode.j;
- rightCtr < this.shadowTable_[currentShadowNode.i].length;
- rightCtr++) {
-
- var rightShadowNode = this.shadowTable_[currentShadowNode.i][rightCtr];
- var rightCell = rightShadowNode.activeCell;
-
- if ((rightCell.tagName == 'TH') ||
- (rightCell.hasAttribute('scope'))) {
-
- if (rightCtr < this.shadowTable_[currentShadowNode.i].length - 1) {
- var checkDataCell =
- this.shadowTable_[currentShadowNode.i][rightCtr + 1];
- }
- }
- rightShadowNode.rowHeaderCells.push(currentCell);
- }
- this.tableRowHeaders.push(currentCell);
- } else if ((specifiedScope == 'col') || (assumedScope == 'col')) {
- currentShadowNode.isColHeader = true;
-
- // Go down until you hit the edge of the table or a data cell
- // after another header cell.
- // Add this cell to each shadowNode.colHeaders attribute as you go.
-
- for (var downCtr = currentShadowNode.i;
- downCtr < this.shadowTable_.length;
- downCtr++) {
-
- var downShadowNode = this.shadowTable_[downCtr][currentShadowNode.j];
- if (downShadowNode == null) {
- break;
- }
- var downCell = downShadowNode.activeCell;
-
- if ((downCell.tagName == 'TH') ||
- (downCell.hasAttribute('scope'))) {
-
- if (downCtr < this.shadowTable_.length - 1) {
- var checkDataCell =
- this.shadowTable_[downCtr + 1][currentShadowNode.j];
- }
- }
- downShadowNode.colHeaderCells.push(currentCell);
- }
- this.tableColHeaders.push(currentCell);
- } else if (specifiedScope == 'rowgroup') {
- currentShadowNode.isRowHeader = true;
-
- // This cell is a row header for the rest of the cells in this row group.
- var currentRowGroup = currentShadowNode.rowGroup;
-
- // Get the rest of the cells in this row first
- for (var cellsInRow = currentShadowNode.j + 1;
- cellsInRow < this.shadowTable_[currentShadowNode.i].length;
- cellsInRow++) {
- this.shadowTable_[currentShadowNode.i][cellsInRow].
- rowHeaderCells.push(currentCell);
- }
-
- // Now propagate to rest of row group
- for (var downCtr = currentShadowNode.i + 1;
- downCtr < this.shadowTable_.length;
- downCtr++) {
-
- if (this.shadowTable_[downCtr][0].rowGroup != currentRowGroup) {
- break;
- }
-
- for (var rightCtr = 0;
- rightCtr < this.shadowTable_[downCtr].length;
- rightCtr++) {
-
- this.shadowTable_[downCtr][rightCtr].
- rowHeaderCells.push(currentCell);
- }
- }
- this.tableRowHeaders.push(currentCell);
-
- } else if (specifiedScope == 'colgroup') {
- currentShadowNode.isColHeader = true;
-
- // This cell is a col header for the rest of the cells in this col group.
- var currentColGroup = currentShadowNode.colGroup;
-
- // Get the rest of the cells in this colgroup first
- for (var cellsInCol = currentShadowNode.j + 1;
- cellsInCol < this.shadowTable_[currentShadowNode.i].length;
- cellsInCol++) {
- if (this.shadowTable_[currentShadowNode.i][cellsInCol].colGroup ==
- currentColGroup) {
- this.shadowTable_[currentShadowNode.i][cellsInCol].
- colHeaderCells.push(currentCell);
- }
- }
-
- // Now propagate to rest of col group
- for (var downCtr = currentShadowNode.i + 1;
- downCtr < this.shadowTable_.length;
- downCtr++) {
-
- for (var rightCtr = 0;
- rightCtr < this.shadowTable_[downCtr].length;
- rightCtr++) {
-
- if (this.shadowTable_[downCtr][rightCtr].colGroup ==
- currentColGroup) {
- this.shadowTable_[downCtr][rightCtr].
- colHeaderCells.push(currentCell);
- }
- }
- }
- this.tableColHeaders.push(currentCell);
- }
- if (currentCell.hasAttribute('headers')) {
- this.findAttrbHeaders_(currentShadowNode);
- }
- if (currentCell.hasAttribute('aria-describedby')) {
- this.findAttrbDescribedBy_(currentShadowNode);
- }
- }
-};
-
-
-/**
- * Finds header cells from the 'headers' attribute of a given shadow node's
- * active cell and classifies them in two ways:
- * -- Identifies them for the entire table by adding them to
- * this.tableRowHeaders and this.tableColHeaders.
- * -- Identifies them for the shadow table node by adding them to the node's
- * rowHeaderCells or colHeaderCells arrays.
- * Please note that header cells found through the 'headers' attribute are
- * difficult to attribute to being either row or column headers because a
- * table cell can declare arbitrary cells as its headers. A guess is made here
- * based on which axis the header cell is closest to.
- *
- * @param {ShadowTableNode} currentShadowNode A shadow node with an active cell
- * that has a 'headers' attribute.
- *
- * @private
- */
-cvox.TraverseTable.prototype.findAttrbHeaders_ = function(currentShadowNode) {
- var activeTableCell = currentShadowNode.activeCell;
-
- var idList = activeTableCell.getAttribute('headers').split(' ');
- for (var idToken = 0; idToken < idList.length; idToken++) {
- // Find cell(s) with this ID, add to header list
- var idCellArray = cvox.TableUtil.getCellWithID(this.activeTable_,
- idList[idToken]);
-
- for (var idCtr = 0; idCtr < idCellArray.length; idCtr++) {
- if (idCellArray[idCtr].id == activeTableCell.id) {
- // Skip if the ID is the same as the current cell's ID
- break;
- }
- // Check if this list of candidate headers contains a
- // shadowNode with an active cell with this ID already
- var possibleHeaderNode =
- this.idToShadowNode_[idCellArray[idCtr].id];
- if (! cvox.TableUtil.checkIfHeader(possibleHeaderNode.activeCell)) {
- // This listed header cell will not be handled later.
- // Determine whether this is a row or col header for
- // the active table cell
-
- var iDiff = Math.abs(possibleHeaderNode.i - currentShadowNode.i);
- var jDiff = Math.abs(possibleHeaderNode.j - currentShadowNode.j);
- if ((iDiff == 0) || (iDiff < jDiff)) {
- cvox.TableUtil.pushIfNotContained(currentShadowNode.rowHeaderCells,
- possibleHeaderNode.activeCell);
- cvox.TableUtil.pushIfNotContained(this.tableRowHeaders,
- possibleHeaderNode.activeCell);
- } else {
- // This is a column header
- cvox.TableUtil.pushIfNotContained(currentShadowNode.colHeaderCells,
- possibleHeaderNode.activeCell);
- cvox.TableUtil.pushIfNotContained(this.tableColHeaders,
- possibleHeaderNode.activeCell);
- }
- }
- }
- }
-};
-
-
-/**
- * Finds header cells from the 'aria-describedby' attribute of a given shadow
- * node's active cell and classifies them in two ways:
- * -- Identifies them for the entire table by adding them to
- * this.tableRowHeaders and this.tableColHeaders.
- * -- Identifies them for the shadow table node by adding them to the node's
- * rowHeaderCells or colHeaderCells arrays.
- *
- * Please note that header cells found through the 'aria-describedby' attribute
- * must have the role='rowheader' or role='columnheader' attributes in order to
- * be considered header cells.
- *
- * @param {ShadowTableNode} currentShadowNode A shadow node with an active cell
- * that has an 'aria-describedby' attribute.
- *
- * @private
- */
-cvox.TraverseTable.prototype.findAttrbDescribedBy_ =
- function(currentShadowNode) {
- var activeTableCell = currentShadowNode.activeCell;
-
- var idList = activeTableCell.getAttribute('aria-describedby').split(' ');
- for (var idToken = 0; idToken < idList.length; idToken++) {
- // Find cell(s) with this ID, add to header list
- var idCellArray = cvox.TableUtil.getCellWithID(this.activeTable_,
- idList[idToken]);
-
- for (var idCtr = 0; idCtr < idCellArray.length; idCtr++) {
- if (idCellArray[idCtr].id == activeTableCell.id) {
- // Skip if the ID is the same as the current cell's ID
- break;
- }
- // Check if this list of candidate headers contains a
- // shadowNode with an active cell with this ID already
- var possibleHeaderNode =
- this.idToShadowNode_[idCellArray[idCtr].id];
- if (! cvox.TableUtil.checkIfHeader(possibleHeaderNode.activeCell)) {
- // This listed header cell will not be handled later.
- // Determine whether this is a row or col header for
- // the active table cell
-
- if (possibleHeaderNode.activeCell.hasAttribute('role') &&
- (possibleHeaderNode.activeCell.getAttribute('role') ==
- 'rowheader')) {
- cvox.TableUtil.pushIfNotContained(currentShadowNode.rowHeaderCells,
- possibleHeaderNode.activeCell);
- cvox.TableUtil.pushIfNotContained(this.tableRowHeaders,
- possibleHeaderNode.activeCell);
- } else if (possibleHeaderNode.activeCell.hasAttribute('role') &&
- (possibleHeaderNode.activeCell.getAttribute('role') ==
- 'columnheader')) {
- cvox.TableUtil.pushIfNotContained(currentShadowNode.colHeaderCells,
- possibleHeaderNode.activeCell);
- cvox.TableUtil.pushIfNotContained(this.tableColHeaders,
- possibleHeaderNode.activeCell);
- }
- }
- }
- }
-};
-
-
-/**
- * Gets the current cell or null if there is no current cell.
- * @return {?Node} The cell <TD> or <TH> or role='gridcell' node.
- */
-cvox.TraverseTable.prototype.getCell = function() {
- if (!this.currentCellCursor || !this.shadowTable_) {
- return null;
- }
-
- var shadowEntry =
- this.shadowTable_[this.currentCellCursor[0]][this.currentCellCursor[1]];
-
- return shadowEntry && shadowEntry.activeCell;
-};
-
-
-/**
- * Gets the cell at the specified location.
- * @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.
- */
-cvox.TraverseTable.prototype.getCellAt = function(index) {
- if (((index[0] < this.rowCount) && (index[0] >= 0)) &&
- ((index[1] < this.colCount) && (index[1] >= 0))) {
- var shadowEntry = this.shadowTable_[index[0]][index[1]];
- if (shadowEntry != null) {
- return shadowEntry.activeCell;
- }
- }
- return null;
-};
-
-
-/**
- * Gets the cells that are row headers of the current cell.
- * @return {!Array} The cells that are row headers of the current cell. Empty if
- * the current cell does not have row headers.
- */
-cvox.TraverseTable.prototype.getCellRowHeaders = function() {
- var shadowEntry =
- this.shadowTable_[this.currentCellCursor[0]][this.currentCellCursor[1]];
-
- return shadowEntry.rowHeaderCells;
-};
-
-
-/**
- * Gets the cells that are col headers of the current cell.
- * @return {!Array} The cells that are col headers of the current cell. Empty if
- * the current cell does not have col headers.
- */
-cvox.TraverseTable.prototype.getCellColHeaders = function() {
- var shadowEntry =
- this.shadowTable_[this.currentCellCursor[0]][this.currentCellCursor[1]];
-
- return shadowEntry.colHeaderCells;
-};
-
-
-/**
- * Whether or not the current cell is spanned by another cell.
- * @return {boolean} Whether or not the current cell is spanned by another cell.
- */
-cvox.TraverseTable.prototype.isSpanned = function() {
- var shadowEntry =
- this.shadowTable_[this.currentCellCursor[0]][this.currentCellCursor[1]];
-
- return shadowEntry.spanned;
-};
-
-
-/**
- * Whether or not the current cell is a row header cell.
- * @return {boolean} Whether or not the current cell is a row header cell.
- */
-cvox.TraverseTable.prototype.isRowHeader = function() {
- var shadowEntry =
- this.shadowTable_[this.currentCellCursor[0]][this.currentCellCursor[1]];
-
- return shadowEntry.isRowHeader;
-};
-
-
-/**
- * Whether or not the current cell is a col header cell.
- * @return {boolean} Whether or not the current cell is a col header cell.
- */
-cvox.TraverseTable.prototype.isColHeader = function() {
- var shadowEntry =
- this.shadowTable_[this.currentCellCursor[0]][this.currentCellCursor[1]];
-
- return shadowEntry.isColHeader;
-};
-
-
-/**
- * Gets the active column, represented as an array of <TH> or <TD> nodes that
- * make up a column. In this context, "active" means that this is the column
- * that contains the cell the user is currently looking at.
- * @return {Array} An array of <TH> or <TD> or role='gridcell' nodes.
- */
-cvox.TraverseTable.prototype.getCol = function() {
- var colArray = [];
- for (var i = 0; i < this.shadowTable_.length; i++) {
-
- if (this.shadowTable_[i][this.currentCellCursor[1]]) {
- var shadowEntry = this.shadowTable_[i][this.currentCellCursor[1]];
-
- if (shadowEntry.colSpan && shadowEntry.rowSpan) {
- // Look at the last element in the column cell aray.
- var prev = colArray[colArray.length - 1];
- if (prev !=
- shadowEntry.activeCell) {
- // Watch out for positions spanned by a cell with rowspan and
- // colspan. We don't want the same cell showing up multiple times
- // in per-column cell lists.
- colArray.push(
- shadowEntry.activeCell);
- }
- } else if ((shadowEntry.colSpan) || (!shadowEntry.rowSpan)) {
- colArray.push(
- shadowEntry.activeCell);
- }
- }
- }
- return colArray;
-};
-
-
-/**
- * Gets the active row <TR> node. In this context, "active" means that this is
- * the row that contains the cell the user is currently looking at.
- * @return {Node} The active row node.
- */
-cvox.TraverseTable.prototype.getRow = function() {
- var childRows = cvox.TableUtil.getChildRows(this.activeTable_);
- return childRows[this.currentCellCursor[0]];
-};
-
-
-/**
- * Gets the table summary text.
- *
- * @return {?string} Either:
- * 1) The table summary text
- * 2) Null if the table does not contain a summary attribute.
- */
-cvox.TraverseTable.prototype.summaryText = function() {
- // see http://code.google.com/p/chromium/issues/detail?id=46567
- // for information why this is necessary
- if (!this.activeTable_.hasAttribute('summary')) {
- return null;
- }
- return this.activeTable_.getAttribute('summary');
-};
-
-
-/**
- * Gets the table caption text.
- *
- * @return {?string} Either:
- * 1) The table caption text
- * 2) Null if the table does not include a caption tag.
- */
-cvox.TraverseTable.prototype.captionText = function() {
- // If there's more than one outer <caption> element, choose the first one.
- var captionNodes = cvox.XpathUtil.evalXPath('caption\[1]',
- this.activeTable_);
- if (captionNodes.length > 0) {
- return captionNodes[0].innerHTML;
- } else {
- return null;
- }
-};
-
-
-/**
- * Calculates the number of columns in the shadow table.
- * @return {number} The number of columns in the shadow table.
- * @private
- */
-cvox.TraverseTable.prototype.shadowColCount_ = function() {
- // As the shadow table is a 2D array, the number of columns is the
- // max number of elements in the second-level arrays.
- var max = 0;
- for (var i = 0; i < this.shadowTable_.length; i++) {
- if (this.shadowTable_[i].length > max) {
- max = this.shadowTable_[i].length;
- }
- }
- return max;
-};
-
-
-/**
- * Calculates the number of rows in the table.
- * @return {number} The number of rows in the table.
- * @private
- */
-cvox.TraverseTable.prototype.countRows_ = function() {
- // Number of rows in a table is equal to the number of TR elements contained
- // by the (outer) TBODY elements.
- var rowCount = cvox.TableUtil.getChildRows(this.activeTable_);
- return rowCount.length;
-};
-
-
-/**
- * Calculates the number of columns in the table.
- * This uses the W3C recommended algorithm for calculating number of
- * columns, but it does not take rowspans or colspans into account. This means
- * that the number of columns calculated here might be lower than the actual
- * number of columns in the table if columns are indicated by colspans.
- * @return {number} The number of columns in the table.
- * @private
- */
-cvox.TraverseTable.prototype.getW3CColCount_ = function() {
- // See http://www.w3.org/TR/html401/struct/tables.html#h-11.2.4.3
-
- var colgroupNodes = cvox.XpathUtil.evalXPath('child::colgroup',
- this.activeTable_);
- var colNodes = cvox.XpathUtil.evalXPath('child::col', this.activeTable_);
-
- if ((colgroupNodes.length == 0) && (colNodes.length == 0)) {
- var maxcols = 0;
- var outerChildren = cvox.TableUtil.getChildRows(this.activeTable_);
- for (var i = 0; i < outerChildren.length; i++) {
- var childrenCount = cvox.TableUtil.getChildCells(outerChildren[i]);
- if (childrenCount.length > maxcols) {
- maxcols = childrenCount.length;
- }
- }
- return maxcols;
- } else {
- var sum = 0;
- for (var i = 0; i < colNodes.length; i++) {
- if (colNodes[i].hasAttribute('span')) {
- sum += colNodes[i].getAttribute('span');
- } else {
- sum += 1;
- }
- }
- for (i = 0; i < colgroupNodes.length; i++) {
- var colChildren = cvox.XpathUtil.evalXPath('child::col',
- colgroupNodes[i]);
- if (colChildren.length == 0) {
- if (colgroupNodes[i].hasAttribute('span')) {
- sum += colgroupNodes[i].getAttribute('span');
- } else {
- sum += 1;
- }
- }
- }
- }
- return sum;
-};
-
-
-/**
- * Moves to the next row in the table. Updates the cell cursor.
- *
- * @return {boolean} Either:
- * 1) True if the update has been made.
- * 2) False if the end of the table has been reached and the update has not
- * happened.
- */
-cvox.TraverseTable.prototype.nextRow = function() {
- if (!this.currentCellCursor) {
- // We have not started moving through the table yet
- return this.goToRow(0);
- } else {
- return this.goToRow(this.currentCellCursor[0] + 1);
- }
-
-};
-
-
-/**
- * Moves to the previous row in the table. Updates the cell cursor.
- *
- * @return {boolean} Either:
- * 1) True if the update has been made.
- * 2) False if the end of the table has been reached and the update has not
- * happened.
- */
-cvox.TraverseTable.prototype.prevRow = function() {
- if (!this.currentCellCursor) {
- // We have not started moving through the table yet
- return this.goToRow(this.rowCount - 1);
- } else {
- return this.goToRow(this.currentCellCursor[0] - 1);
- }
-};
-
-
-/**
- * Moves to the next column in the table. Updates the cell cursor.
- *
- * @return {boolean} Either:
- * 1) True if the update has been made.
- * 2) False if the end of the table has been reached and the update has not
- * happened.
- */
-cvox.TraverseTable.prototype.nextCol = function() {
- if (!this.currentCellCursor) {
- // We have not started moving through the table yet
- return this.goToCol(0);
- } else {
- return this.goToCol(this.currentCellCursor[1] + 1);
- }
-};
-
-
-/**
- * Moves to the previous column in the table. Updates the cell cursor.
- *
- * @return {boolean} Either:
- * 1) True if the update has been made.
- * 2) False if the end of the table has been reached and the update has not
- * happened.
- */
-cvox.TraverseTable.prototype.prevCol = function() {
- if (!this.currentCellCursor) {
- // We have not started moving through the table yet
- return this.goToCol(this.shadowColCount_() - 1);
- } else {
- return this.goToCol(this.currentCellCursor[1] - 1);
- }
-};
-
-
-/**
- * Moves to the row at the specified index in the table. Updates the cell
- * cursor.
- * @param {number} index The index of the required row.
- * @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 or greater than
- * the number of rows in the table).
- */
-cvox.TraverseTable.prototype.goToRow = function(index) {
- if (this.shadowTable_[index] != null) {
- if (this.currentCellCursor == null) {
- // We haven't started moving through the table yet
- this.currentCellCursor = [index, 0];
- } else {
- this.currentCellCursor = [index, this.currentCellCursor[1]];
- }
- return true;
- } else {
- return false;
- }
-};
-
-
-/**
- * Moves to the column at the specified index in the table. Updates the cell
- * cursor.
- * @param {number} index The index of the required column.
- * @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 or greater than
- * the number of rows in the table).
- */
-cvox.TraverseTable.prototype.goToCol = function(index) {
- if (index < 0 || index >= this.colCount) {
- return false;
- }
- if (this.currentCellCursor == null) {
- // We haven't started moving through the table yet
- this.currentCellCursor = [0, index];
- } else {
- this.currentCellCursor = [this.currentCellCursor[0], index];
- }
- return true;
-};
-
-
-/**
- * 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.
- * @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
- * the number of rows or columns in the table, or there is no cell
- * at that location).
- */
-cvox.TraverseTable.prototype.goToCell = function(index) {
- if (((index[0] < this.rowCount) && (index[0] >= 0)) &&
- ((index[1] < this.colCount) && (index[1] >= 0))) {
- var cell = this.shadowTable_[index[0]][index[1]];
- if (cell != null) {
- this.currentCellCursor = index;
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Moves to the cell at the last index in the table. Updates the cell cursor.
- * @return {boolean} Either:
- * 1) True if the index is valid and the update has been made.
- * 2) False if the index is not valid (there is no cell at that location).
- */
-cvox.TraverseTable.prototype.goToLastCell = function() {
- var numRows = this.shadowTable_.length;
- if (numRows == 0) {
- return false;
- }
- var lastRow = this.shadowTable_[numRows - 1];
- var lastIndex = [(numRows - 1), (lastRow.length - 1)];
- var cell =
- this.shadowTable_[lastIndex[0]][lastIndex[1]];
- if (cell != null) {
- this.currentCellCursor = lastIndex;
- return true;
- }
- return false;
-};
-
-
-/**
- * Moves to the cell at the last index in the current row of the table. Update
- * the cell cursor.
- * @return {boolean} Either:
- * 1) True if the index is valid and the update has been made.
- * 2) False if the index is not valid (there is no cell at that location).
- */
-cvox.TraverseTable.prototype.goToRowLastCell = function() {
- var currentRow = this.currentCellCursor[0];
- var lastIndex = [currentRow, (this.shadowTable_[currentRow].length - 1)];
- var cell =
- this.shadowTable_[lastIndex[0]][lastIndex[1]];
- if (cell != null) {
- this.currentCellCursor = lastIndex;
- return true;
- }
- return false;
-};
-
-
-/**
- * Moves to the cell at the last index in the current column of the table.
- * Update the cell cursor.
- * @return {boolean} Either:
- * 1) True if the index is valid and the update has been made.
- * 2) False if the index is not valid (there is no cell at that location).
- */
-cvox.TraverseTable.prototype.goToColLastCell = function() {
- var currentCol = this.getCol();
- var lastIndex = [(currentCol.length - 1), this.currentCellCursor[1]];
- var cell =
- this.shadowTable_[lastIndex[0]][lastIndex[1]];
- if (cell != null) {
- this.currentCellCursor = lastIndex;
- return true;
- }
- return false;
-};
-
-
-/**
- * Resets the table cursors.
- *
- */
-cvox.TraverseTable.prototype.resetCursor = function() {
- this.currentCellCursor = null;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js
deleted file mode 100644
index a77ac3eb284..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/traverse_util.js
+++ /dev/null
@@ -1,927 +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 Low-level DOM traversal utility functions to find the
- * next (or previous) character, word, sentence, line, or paragraph,
- * in a completely stateless manner without actually manipulating the
- * selection.
- */
-
-goog.provide('cvox.TraverseUtil');
-
-goog.require('cvox.Cursor');
-goog.require('cvox.DomPredicates');
-goog.require('cvox.DomUtil');
-
-/**
- * Utility functions for stateless DOM traversal.
- * @constructor
- */
-cvox.TraverseUtil = function() {};
-
-/**
- * Gets the text representation of a node. This allows us to substitute
- * alt text, names, or titles for html elements that provide them.
- * @param {Node} node A DOM node.
- * @return {string} A text string representation of the node.
- */
-cvox.TraverseUtil.getNodeText = function(node) {
- if (node.constructor == Text) {
- return node.data;
- } else {
- return '';
- }
-};
-
-/**
- * Return true if a node should be treated as a leaf node, because
- * its children are properties of the object that shouldn't be traversed.
- *
- * TODO(dmazzoni): replace this with a predicate that detects nodes with
- * ARIA roles and other objects that have their own description.
- * For now we just detect a couple of common cases.
- *
- * @param {Node} node A DOM node.
- * @return {boolean} True if the node should be treated as a leaf node.
- */
-cvox.TraverseUtil.treatAsLeafNode = function(node) {
- return node.childNodes.length == 0 ||
- node.nodeName == 'SELECT' ||
- node.getAttribute('role') == 'listbox' ||
- node.nodeName == 'OBJECT';
-};
-
-/**
- * Return true only if a single character is whitespace.
- * From https://developer.mozilla.org/en/Whitespace_in_the_DOM,
- * whitespace is defined as one of the characters
- * "\t" TAB \u0009
- * "\n" LF \u000A
- * "\r" CR \u000D
- * " " SPC \u0020.
- *
- * @param {string} c A string containing a single character.
- * @return {boolean} True if the character is whitespace, otherwise false.
- */
-cvox.TraverseUtil.isWhitespace = function(c) {
- return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
-};
-
-/**
- * Set the selection to the range between the given start and end cursors.
- * @param {cvox.Cursor} start The desired start of the selection.
- * @param {cvox.Cursor} end The desired end of the selection.
- * @return {Selection} the selection object.
- */
-cvox.TraverseUtil.setSelection = function(start, end) {
- var sel = window.getSelection();
- sel.removeAllRanges();
- var range = document.createRange();
- range.setStart(start.node, start.index);
- range.setEnd(end.node, end.index);
- sel.addRange(range);
-
- return sel;
-};
-
-// TODO(dtseng): Combine with cvox.DomUtil.hasContent.
-/**
- * Check if this DOM node has the attribute aria-hidden='true', which should
- * hide it from screen readers.
- * @param {Node} node An HTML DOM node.
- * @return {boolean} Whether or not the html node should be traversed.
- */
-cvox.TraverseUtil.isHidden = function(node) {
- if (node instanceof HTMLElement &&
- node.getAttribute('aria-hidden') == 'true') {
- return true;
- }
- switch (node.tagName) {
- case 'SCRIPT':
- case 'NOSCRIPT':
- return true;
- }
- return false;
-};
-
-/**
- * Moves the cursor forwards until it has crossed exactly one character.
- * @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.
- * @return {?string} The character found, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.forwardsChar = function(
- cursor, elementsEntered, elementsLeft) {
- while (true) {
- // Move down until we get to a leaf node.
- var childNode = null;
- if (!cvox.TraverseUtil.treatAsLeafNode(cursor.node)) {
- for (var i = cursor.index; i < cursor.node.childNodes.length; i++) {
- var node = cursor.node.childNodes[i];
- if (cvox.TraverseUtil.isHidden(node)) {
- if (node instanceof HTMLElement) {
- elementsEntered.push(node);
- }
- continue;
- }
- if (cvox.DomUtil.isVisible(node, {checkAncestors: false})) {
- childNode = node;
- break;
- }
- }
- }
- if (childNode) {
- cursor.node = childNode;
- cursor.index = 0;
- cursor.text = cvox.TraverseUtil.getNodeText(cursor.node);
- if (cursor.node instanceof HTMLElement) {
- elementsEntered.push(cursor.node);
- }
- continue;
- }
-
- // Return the next character from this leaf node.
- if (cursor.index < cursor.text.length)
- return cursor.text[cursor.index++];
-
- // Move to the next sibling, going up the tree as necessary.
- while (cursor.node != null) {
- // Try to move to the next sibling.
- var siblingNode = null;
- for (var node = cursor.node.nextSibling;
- node != null;
- node = node.nextSibling) {
- if (cvox.TraverseUtil.isHidden(node)) {
- if (node instanceof HTMLElement) {
- elementsEntered.push(node);
- }
- continue;
- }
- if (cvox.DomUtil.isVisible(node, {checkAncestors: false})) {
- siblingNode = node;
- break;
- }
- }
- if (siblingNode) {
- if (cursor.node instanceof HTMLElement) {
- elementsLeft.push(cursor.node);
- }
-
- cursor.node = siblingNode;
- cursor.text = cvox.TraverseUtil.getNodeText(siblingNode);
- cursor.index = 0;
-
- if (cursor.node instanceof HTMLElement) {
- elementsEntered.push(cursor.node);
- }
-
- break;
- }
-
- // Otherwise, move to the parent.
- if (cursor.node.parentNode &&
- cursor.node.parentNode.constructor != HTMLBodyElement) {
- if (cursor.node instanceof HTMLElement) {
- elementsLeft.push(cursor.node);
- }
- cursor.node = cursor.node.parentNode;
- cursor.text = null;
- cursor.index = 0;
- } else {
- return null;
- }
- }
- }
-};
-
-/**
- * Moves the cursor backwards until it has crossed exactly one character.
- * @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.
- * @return {?string} The previous character, or null if the top of the
- * document has been reached.
- */
-cvox.TraverseUtil.backwardsChar = function(
- cursor, elementsEntered, elementsLeft) {
- while (true) {
- // Move down until we get to a leaf node.
- var childNode = null;
- if (!cvox.TraverseUtil.treatAsLeafNode(cursor.node)) {
- for (var i = cursor.index - 1; i >= 0; i--) {
- var node = cursor.node.childNodes[i];
- if (cvox.TraverseUtil.isHidden(node)) {
- if (node instanceof HTMLElement) {
- elementsEntered.push(node);
- }
- continue;
- }
- if (cvox.DomUtil.isVisible(node, {checkAncestors: false})) {
- childNode = node;
- break;
- }
- }
- }
- if (childNode) {
- cursor.node = childNode;
- cursor.text = cvox.TraverseUtil.getNodeText(cursor.node);
- if (cursor.text.length)
- cursor.index = cursor.text.length;
- else
- cursor.index = cursor.node.childNodes.length;
- if (cursor.node instanceof HTMLElement) {
- elementsEntered.push(cursor.node);
- }
- continue;
- }
-
- // Return the previous character from this leaf node.
- if (cursor.text.length > 0 && cursor.index > 0) {
- return cursor.text[--cursor.index];
- }
-
- // Move to the previous sibling, going up the tree as necessary.
- while (true) {
- // Try to move to the previous sibling.
- var siblingNode = null;
- for (var node = cursor.node.previousSibling;
- node != null;
- node = node.previousSibling) {
- if (cvox.TraverseUtil.isHidden(node)) {
- if (node instanceof HTMLElement) {
- elementsEntered.push(node);
- }
- continue;
- }
- if (cvox.DomUtil.isVisible(node, {checkAncestors: false})) {
- siblingNode = node;
- break;
- }
- }
- if (siblingNode) {
- if (cursor.node instanceof HTMLElement) {
- elementsLeft.push(cursor.node);
- }
-
- cursor.node = siblingNode;
- cursor.text = cvox.TraverseUtil.getNodeText(siblingNode);
- if (cursor.text.length)
- cursor.index = cursor.text.length;
- else
- cursor.index = cursor.node.childNodes.length;
-
- if (cursor.node instanceof HTMLElement) {
- elementsEntered.push(cursor.node);
- }
- break;
- }
-
- // Otherwise, move to the parent.
- if (cursor.node.parentNode &&
- cursor.node.parentNode.constructor != HTMLBodyElement) {
- if (cursor.node instanceof HTMLElement) {
- elementsLeft.push(cursor.node);
- }
- cursor.node = cursor.node.parentNode;
- cursor.text = null;
- cursor.index = 0;
- } else {
- return null;
- }
- }
- }
-};
-
-/**
- * Finds the next character, starting from endCursor. Upon exit, startCursor
- * and endCursor will surround the next character. If skipWhitespace is
- * true, will skip until a real character is found. Otherwise, it will
- * attempt to select all of the whitespace between the initial position
- * of endCursor and the next non-whitespace character.
- * @param {!cvox.Cursor} startCursor On exit, points 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.
- * 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.
- * @return {?string} The next char, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.getNextChar = function(
- startCursor, endCursor, elementsEntered, elementsLeft, skipWhitespace) {
-
- // Save the starting position and get the first character.
- startCursor.copyFrom(endCursor);
- var c = cvox.TraverseUtil.forwardsChar(
- endCursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
-
- // Keep track of whether the first character was whitespace.
- var initialWhitespace = cvox.TraverseUtil.isWhitespace(c);
-
- // Keep scanning until we find a non-whitespace or non-skipped character.
- while ((cvox.TraverseUtil.isWhitespace(c)) ||
- (cvox.TraverseUtil.isHidden(endCursor.node))) {
- c = cvox.TraverseUtil.forwardsChar(
- endCursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
- }
- if (skipWhitespace || !initialWhitespace) {
- // If skipWhitepace is true, or if the first character we encountered
- // was not whitespace, return that non-whitespace character.
- startCursor.copyFrom(endCursor);
- startCursor.index--;
- return c;
- }
- else {
- for (var i = 0; i < elementsEntered.length; i++) {
- if (cvox.TraverseUtil.isHidden(elementsEntered[i])) {
- // We need to make sure that startCursor and endCursor aren't
- // surrounding a skippable node.
- endCursor.index--;
- startCursor.copyFrom(endCursor);
- startCursor.index--;
- return ' ';
- }
- }
- // Otherwise, return all of the whitespace before that last character.
- endCursor.index--;
- return ' ';
- }
-};
-
-/**
- * Finds the previous character, starting from startCursor. Upon exit,
- * startCursor and endCursor will surround the previous character.
- * If skipWhitespace is true, will skip until a real character is found.
- * Otherwise, it will attempt to select all of the whitespace between
- * the initial position of endCursor and the next non-whitespace character.
- * @param {!cvox.Cursor} startCursor The position to start searching for the
- * 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.
- * 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.
- * @return {?string} The previous char, or null if the top of the
- * document has been reached.
- */
-cvox.TraverseUtil.getPreviousChar = function(
- startCursor, endCursor, elementsEntered, elementsLeft, skipWhitespace) {
-
- // Save the starting position and get the first character.
- endCursor.copyFrom(startCursor);
- var c = cvox.TraverseUtil.backwardsChar(
- startCursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
-
- // Keep track of whether the first character was whitespace.
- var initialWhitespace = cvox.TraverseUtil.isWhitespace(c);
-
- // Keep scanning until we find a non-whitespace or non-skipped character.
- while ((cvox.TraverseUtil.isWhitespace(c)) ||
- (cvox.TraverseUtil.isHidden(startCursor.node))) {
- c = cvox.TraverseUtil.backwardsChar(
- startCursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
- }
- if (skipWhitespace || !initialWhitespace) {
- // If skipWhitepace is true, or if the first character we encountered
- // was not whitespace, return that non-whitespace character.
- endCursor.copyFrom(startCursor);
- endCursor.index++;
- return c;
- } else {
- for (var i = 0; i < elementsEntered.length; i++) {
- if (cvox.TraverseUtil.isHidden(elementsEntered[i])) {
- startCursor.index++;
- endCursor.copyFrom(startCursor);
- endCursor.index++;
- return ' ';
- }
- }
- // Otherwise, return all of the whitespace before that last character.
- startCursor.index++;
- return ' ';
- }
-};
-
-/**
- * Finds the next word, starting from endCursor. Upon exit, startCursor
- * and endCursor will surround the next word. A word is defined to be
- * a string of 1 or more non-whitespace characters in the same DOM node.
- * @param {cvox.Cursor} startCursor On exit, will point to the beginning of the
- * 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.
- * @return {?string} The next word, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.getNextWord = function(startCursor, endCursor,
- elementsEntered, elementsLeft) {
-
- // Find the first non-whitespace or non-skipped character.
- var cursor = endCursor.clone();
- var c = cvox.TraverseUtil.forwardsChar(cursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
- while ((cvox.TraverseUtil.isWhitespace(c)) ||
- (cvox.TraverseUtil.isHidden(cursor.node))) {
- c = cvox.TraverseUtil.forwardsChar(cursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
- }
-
- // Set startCursor to the position immediately before the first
- // character in our word. It's safe to decrement |index| because
- // forwardsChar guarantees that the cursor will be immediately to the
- // right of the returned character on exit.
- startCursor.copyFrom(cursor);
- startCursor.index--;
-
- // Keep building up our word until we reach a whitespace character or
- // would cross a tag. Don't actually return any tags crossed, because this
- // word goes up until the tag boundary but not past it.
- endCursor.copyFrom(cursor);
- var word = c;
- var newEntered = [];
- var newLeft = [];
- c = cvox.TraverseUtil.forwardsChar(cursor, newEntered, newLeft);
- if (c == null) {
- return word;
- }
- while (!cvox.TraverseUtil.isWhitespace(c) &&
- newEntered.length == 0 &&
- newLeft == 0) {
- word += c;
- endCursor.copyFrom(cursor);
- c = cvox.TraverseUtil.forwardsChar(cursor, newEntered, newLeft);
- if (c == null) {
- return word;
- }
- }
-
- return word;
-};
-
-/**
- * Finds the previous word, starting from startCursor. Upon exit, startCursor
- * and endCursor will surround the previous word. A word is defined to be
- * a string of 1 or more non-whitespace characters in the same DOM node.
- * @param {cvox.Cursor} startCursor The position to start searching for the
- * previous word. On exit, will point to the beginning of the
- * 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.
- * @return {?string} The previous word, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.getPreviousWord = function(startCursor, endCursor,
- elementsEntered, elementsLeft) {
- // Find the first non-whitespace or non-skipped character.
- var cursor = startCursor.clone();
- var c = cvox.TraverseUtil.backwardsChar(
- cursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
- while ((cvox.TraverseUtil.isWhitespace(c) ||
- (cvox.TraverseUtil.isHidden(cursor.node)))) {
- c = cvox.TraverseUtil.backwardsChar(cursor, elementsEntered, elementsLeft);
- if (c == null)
- return null;
- }
-
- // Set endCursor to the position immediately after the first
- // character we've found (the last character of the word, since we're
- // searching backwards).
- endCursor.copyFrom(cursor);
- endCursor.index++;
-
- // Keep building up our word until we reach a whitespace character or
- // would cross a tag. Don't actually return any tags crossed, because this
- // word goes up until the tag boundary but not past it.
- startCursor.copyFrom(cursor);
- var word = c;
- var newEntered = [];
- var newLeft = [];
- c = cvox.TraverseUtil.backwardsChar(cursor, newEntered, newLeft);
- if (c == null)
- return word;
- while (!cvox.TraverseUtil.isWhitespace(c) &&
- newEntered.length == 0 &&
- newLeft.length == 0) {
- word = c + word;
- startCursor.copyFrom(cursor);
-
- c = cvox.TraverseUtil.backwardsChar(cursor, newEntered, newLeft);
- if (c == null)
- return word;
- }
-
- return word;
-};
-
-
-/**
- * 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<boolean>} breakTags Associative array of tags that should
- * break.
- * @return {boolean} True if elementsEntered or elementsLeft include an
- * element with one of these tags.
- */
-cvox.TraverseUtil.includesBreakTagOrSkippedNode = function(
- elementsEntered, elementsLeft, breakTags) {
- for (var i = 0; i < elementsEntered.length; i++) {
- if (cvox.TraverseUtil.isHidden(elementsEntered[i])) {
- return true;
- }
- var style = window.getComputedStyle(elementsEntered[i], null);
- if ((style && style.display != 'inline') ||
- breakTags[elementsEntered[i].tagName]) {
- return true;
- }
- }
- for (i = 0; i < elementsLeft.length; i++) {
- var style = window.getComputedStyle(elementsLeft[i], null);
- if ((style && style.display != 'inline') ||
- breakTags[elementsLeft[i].tagName]) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Finds the next sentence, starting from endCursor. Upon exit,
- * startCursor and endCursor will surround the next sentence.
- *
- * @param {cvox.Cursor} startCursor On exit, marks the beginning of the
- * 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<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.
- */
-cvox.TraverseUtil.getNextSentence = function(
- startCursor, endCursor, elementsEntered, elementsLeft, breakTags) {
- return cvox.TraverseUtil.getNextString(
- startCursor, endCursor, elementsEntered, elementsLeft,
- function(str, word, elementsEntered, elementsLeft) {
- if (str.substr(-1) == '.')
- return true;
- return cvox.TraverseUtil.includesBreakTagOrSkippedNode(
- elementsEntered, elementsLeft, breakTags);
- });
-};
-
-/**
- * Finds the previous sentence, starting from startCursor. Upon exit,
- * startCursor and endCursor will surround the previous sentence.
- *
- * @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<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.
- */
-cvox.TraverseUtil.getPreviousSentence = function(
- startCursor, endCursor, elementsEntered, elementsLeft, breakTags) {
- return cvox.TraverseUtil.getPreviousString(
- startCursor, endCursor, elementsEntered, elementsLeft,
- function(str, word, elementsEntered, elementsLeft) {
- if (word.substr(-1) == '.')
- return true;
- return cvox.TraverseUtil.includesBreakTagOrSkippedNode(
- elementsEntered, elementsLeft, breakTags);
- });
-};
-
-/**
- * Finds the next line, starting from endCursor. Upon exit,
- * startCursor and endCursor will surround the next line.
- *
- * @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<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.
- */
-cvox.TraverseUtil.getNextLine = function(
- startCursor, endCursor, elementsEntered, elementsLeft, breakTags) {
- var range = document.createRange();
- var currentRect = null;
- var rightMostRect = null;
- var prevCursor = endCursor.clone();
- return cvox.TraverseUtil.getNextString(
- startCursor, endCursor, elementsEntered, elementsLeft,
- function(str, word, elementsEntered, elementsLeft) {
- range.setStart(startCursor.node, startCursor.index);
- range.setEnd(endCursor.node, endCursor.index);
- var currentRect = range.getBoundingClientRect();
- if (!rightMostRect) {
- rightMostRect = currentRect;
- }
-
- // Break at new lines except when within a link.
- if (currentRect.bottom != rightMostRect.bottom &&
- !cvox.DomPredicates.linkPredicate(cvox.DomUtil.getAncestors(
- endCursor.node))) {
- endCursor.copyFrom(prevCursor);
- return true;
- }
-
- rightMostRect = currentRect;
- prevCursor.copyFrom(endCursor);
-
- return cvox.TraverseUtil.includesBreakTagOrSkippedNode(
- elementsEntered, elementsLeft, breakTags);
- });
-};
-
-/**
- * Finds the previous line, starting from startCursor. Upon exit,
- * startCursor and endCursor will surround the previous line.
- *
- * @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<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.
- */
-cvox.TraverseUtil.getPreviousLine = function(
- startCursor, endCursor, elementsEntered, elementsLeft, breakTags) {
- var range = document.createRange();
- var currentRect = null;
- var leftMostRect = null;
- var prevCursor = startCursor.clone();
- return cvox.TraverseUtil.getPreviousString(
- startCursor, endCursor, elementsEntered, elementsLeft,
- function(str, word, elementsEntered, elementsLeft) {
- range.setStart(startCursor.node, startCursor.index);
- range.setEnd(endCursor.node, endCursor.index);
- var currentRect = range.getBoundingClientRect();
- if (!leftMostRect) {
- leftMostRect = currentRect;
- }
-
- // Break at new lines except when within a link.
- if (currentRect.top != leftMostRect.top &&
- !cvox.DomPredicates.linkPredicate(cvox.DomUtil.getAncestors(
- startCursor.node))) {
- startCursor.copyFrom(prevCursor);
- return true;
- }
-
- leftMostRect = currentRect;
- prevCursor.copyFrom(startCursor);
-
- return cvox.TraverseUtil.includesBreakTagOrSkippedNode(
- elementsEntered, elementsLeft, breakTags);
- });
-};
-
-/**
- * Finds the next paragraph, starting from endCursor. Upon exit,
- * startCursor and endCursor will surround the next paragraph.
- *
- * @param {cvox.Cursor} startCursor On exit, marks the beginning of the
- * 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.
- * @return {?string} The next paragraph, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.getNextParagraph = function(startCursor, endCursor,
- elementsEntered, elementsLeft) {
- return cvox.TraverseUtil.getNextString(
- startCursor, endCursor, elementsEntered, elementsLeft,
- function(str, word, elementsEntered, elementsLeft) {
- for (var i = 0; i < elementsEntered.length; i++) {
- if (cvox.TraverseUtil.isHidden(elementsEntered[i])) {
- return true;
- }
- var style = window.getComputedStyle(elementsEntered[i], null);
- if (style && style.display != 'inline') {
- return true;
- }
- }
- for (i = 0; i < elementsLeft.length; i++) {
- var style = window.getComputedStyle(elementsLeft[i], null);
- if (style && style.display != 'inline') {
- return true;
- }
- }
- return false;
- });
-};
-
-/**
- * Finds the previous paragraph, starting from startCursor. Upon exit,
- * startCursor and endCursor will surround the previous paragraph.
- *
- * @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.
- * @return {?string} The previous paragraph, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.getPreviousParagraph = function(
- startCursor, endCursor, elementsEntered, elementsLeft) {
- return cvox.TraverseUtil.getPreviousString(
- startCursor, endCursor, elementsEntered, elementsLeft,
- function(str, word, elementsEntered, elementsLeft) {
- for (var i = 0; i < elementsEntered.length; i++) {
- if (cvox.TraverseUtil.isHidden(elementsEntered[i])) {
- return true;
- }
- var style = window.getComputedStyle(elementsEntered[i], null);
- if (style && style.display != 'inline') {
- return true;
- }
- }
- for (i = 0; i < elementsLeft.length; i++) {
- var style = window.getComputedStyle(elementsLeft[i], null);
- if (style && style.display != 'inline') {
- return true;
- }
- }
- return false;
- });
-};
-
-/**
- * Customizable function to return the next string of words in the DOM, based
- * on provided functions to decide when to break one string and start
- * the next. This can be used to get the next sentence, line, paragraph,
- * or potentially other granularities.
- *
- * Finds the next contiguous string, starting from endCursor. Upon exit,
- * startCursor and endCursor will surround the next string.
- *
- * The breakBefore function takes four parameters, and
- * should return true if the string should be broken before the proposed
- * next word:
- * str The string so far.
- * word The next word to be added.
- * elementsEntered The elements entered in reaching this next word.
- * elementsLeft The elements left in reaching this next word.
- *
- * @param {cvox.Cursor} startCursor On exit, will point to the beginning of the
- * 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>)}
- * 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.
- * @return {?string} The next string, or null if the bottom of the
- * document has been reached.
- */
-cvox.TraverseUtil.getNextString = function(
- startCursor, endCursor, elementsEntered, elementsLeft, breakBefore) {
- // Get the first word and set the start cursor to the start of the
- // first word.
- var wordStartCursor = endCursor.clone();
- var wordEndCursor = endCursor.clone();
- var newEntered = [];
- var newLeft = [];
- var str = '';
- var word = cvox.TraverseUtil.getNextWord(
- wordStartCursor, wordEndCursor, newEntered, newLeft);
- if (word == null)
- return null;
- startCursor.copyFrom(wordStartCursor);
-
- // Always add the first word when the string is empty, and then keep
- // adding more words as long as breakBefore returns false
- while (!str || !breakBefore(str, word, newEntered, newLeft)) {
- // Append this word, set the end cursor to the end of this word, and
- // update the returned list of nodes crossed to include ones we crossed
- // in reaching this word.
- if (str)
- str += ' ';
- str += word;
- elementsEntered = elementsEntered.concat(newEntered);
- elementsLeft = elementsLeft.concat(newLeft);
- endCursor.copyFrom(wordEndCursor);
-
- // Get the next word and go back to the top of the loop.
- newEntered = [];
- newLeft = [];
- word = cvox.TraverseUtil.getNextWord(
- wordStartCursor, wordEndCursor, newEntered, newLeft);
- if (word == null)
- return str;
- }
-
- return str;
-};
-
-/**
- * Customizable function to return the previous string of words in the DOM,
- * based on provided functions to decide when to break one string and start
- * the next. See getNextString, above, for more details.
- *
- * Finds the previous contiguous string, starting from startCursor. Upon exit,
- * startCursor and endCursor will surround the next string.
- *
- * @param {cvox.Cursor} startCursor The position to start searching for the
- * previous string. On exit, will point to the beginning of the
- * 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>)}
- * 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.
- * @return {?string} The next string, or null if the top of the
- * document has been reached.
- */
-cvox.TraverseUtil.getPreviousString = function(
- startCursor, endCursor, elementsEntered, elementsLeft, breakBefore) {
- // Get the first word and set the end cursor to the end of the
- // first word.
- var wordStartCursor = startCursor.clone();
- var wordEndCursor = startCursor.clone();
- var newEntered = [];
- var newLeft = [];
- var str = '';
- var word = cvox.TraverseUtil.getPreviousWord(
- wordStartCursor, wordEndCursor, newEntered, newLeft);
- if (word == null)
- return null;
- endCursor.copyFrom(wordEndCursor);
-
- // Always add the first word when the string is empty, and then keep
- // adding more words as long as breakBefore returns false
- while (!str || !breakBefore(str, word, newEntered, newLeft)) {
- // Prepend this word, set the start cursor to the start of this word, and
- // update the returned list of nodes crossed to include ones we crossed
- // in reaching this word.
- if (str)
- str = ' ' + str;
- str = word + str;
- elementsEntered = elementsEntered.concat(newEntered);
- elementsLeft = elementsLeft.concat(newLeft);
- startCursor.copyFrom(wordStartCursor);
-
- // Get the previous word and go back to the top of the loop.
- newEntered = [];
- newLeft = [];
- word = cvox.TraverseUtil.getPreviousWord(
- wordStartCursor, wordEndCursor, newEntered, newLeft);
- if (word == null)
- return str;
- }
-
- return str;
-};
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/xpath_util.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/xpath_util.js
deleted file mode 100644
index cad6346c016..00000000000
--- a/chromium/chrome/browser/resources/chromeos/chromevox/common/xpath_util.js
+++ /dev/null
@@ -1,152 +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 collection of JavaScript utilities used to simplify working
- * with xpaths.
- */
-
-
-goog.provide('cvox.XpathUtil');
-
-
-/**
- * Utilities for simplifying working with xpaths
- * @constructor
- */
-cvox.XpathUtil = function() {
- };
-
-
-/**
- * Mapping for some default namespaces.
- * @const
- * @private
- */
-cvox.XpathUtil.nameSpaces_ = {
- 'xhtml' : 'http://www.w3.org/1999/xhtml',
- 'mathml': 'http://www.w3.org/1998/Math/MathML'
-};
-
-
-/**
- * Resolve some default name spaces.
- * @param {string} prefix Namespace prefix.
- * @return {string} The corresponding namespace URI.
- */
-cvox.XpathUtil.resolveNameSpace = function(prefix) {
- return cvox.XpathUtil.nameSpaces_[prefix] || null;
-};
-
-
-/**
- * Given an XPath expression and rootNode, it returns an array of children nodes
- * that match. The code for this function was taken from Mihai Parparita's GMail
- * Macros Greasemonkey Script.
- * http://gmail-greasemonkey.googlecode.com/svn/trunk/scripts/gmail-new-macros.user.js
- * @param {string} expression The XPath expression to evaluate.
- * @param {Node} rootNode The HTML node to start evaluating the XPath from.
- * @return {Array} The array of children nodes that match.
- */
-cvox.XpathUtil.evalXPath = function(expression, rootNode) {
- try {
- var xpathIterator = rootNode.ownerDocument.evaluate(
- expression,
- rootNode,
- cvox.XpathUtil.resolveNameSpace,
- XPathResult.ORDERED_NODE_ITERATOR_TYPE,
- null); // no existing results
- } catch (err) {
- return [];
- }
- var results = [];
- // Convert result to JS array
- for (var xpathNode = xpathIterator.iterateNext();
- xpathNode;
- xpathNode = xpathIterator.iterateNext()) {
- results.push(xpathNode);
- }
- return results;
-};
-
-/**
- * Given a rootNode, it returns an array of all its leaf nodes.
- * @param {Node} rootNode The node to get the leaf nodes from.
- * @return {Array} The array of leaf nodes for the given rootNode.
- */
-cvox.XpathUtil.getLeafNodes = function(rootNode) {
- try {
- var xpathIterator = rootNode.ownerDocument.evaluate(
- './/*[count(*)=0]',
- rootNode,
- null, // no namespace resolver
- XPathResult.ORDERED_NODE_ITERATOR_TYPE,
- null); // no existing results
- } catch (err) {
- return [];
- }
- var results = [];
- // Convert result to JS array
- for (var xpathNode = xpathIterator.iterateNext();
- xpathNode;
- xpathNode = xpathIterator.iterateNext()) {
- results.push(xpathNode);
- }
- return results;
-};
-
-/**
- * Returns whether or not xpath is supported.
- * @return {boolean} True if xpath is supported.
- */
-cvox.XpathUtil.xpathSupported = function() {
- if (typeof(XPathResult) == 'undefined') {
- return false;
- }
- return true;
-};
-
-
-/**
- * Given an XPath expression and rootNode, it evaluates the XPath expression as
- * a boolean type and returns the result.
- * @param {string} expression The XPath expression to evaluate.
- * @param {Node} rootNode The HTML node to start evaluating the XPath from.
- * @return {boolean} The result of evaluating the xpath expression.
- */
-cvox.XpathUtil.evaluateBoolean = function(expression, rootNode) {
- try {
- var xpathResult = rootNode.ownerDocument.evaluate(
- expression,
- rootNode,
- cvox.XpathUtil.resolveNameSpace,
- XPathResult.BOOLEAN_TYPE,
- null); // no existing results
- } catch (err) {
- return false;
- }
- return xpathResult.booleanValue;
-};
-
-
-/**
- * Given an XPath expression and rootNode, it evaluates the XPath expression as
- * a string type and returns the result.
- * @param {string} expression The XPath expression to evaluate.
- * @param {Node} rootNode The HTML node to start evaluating the XPath from.
- * @return {string} The result of evaluating the Xpath expression.
- */
-cvox.XpathUtil.evaluateString = function(expression, rootNode) {
- try {
- var xpathResult = rootNode.ownerDocument.evaluate(
- expression,
- rootNode,
- cvox.XpathUtil.resolveNameSpace,
- XPathResult.STRING_TYPE,
- null); // no existing results
- } catch (err) {
- return '';
- }
- return xpathResult.stringValue;
-};