Index: chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js |
diff --git a/chrome/browser/resources/chromeos/chromevox/common/editable_text.js b/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js |
similarity index 52% |
copy from chrome/browser/resources/chromeos/chromevox/common/editable_text.js |
copy to chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js |
index 54312e0eb0e761eeafca49a99e82b91c7d1a34e5..d7d7bd47dac7443e9196c1706b4d6341be3c4ba0 100644 |
--- a/chrome/browser/resources/chromeos/chromevox/common/editable_text.js |
+++ b/chrome/browser/resources/chromeos/chromevox/common/editable_text_base.js |
@@ -1,43 +1,26 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
+// 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.ChromeVoxEditableContentEditable'); |
-goog.provide('cvox.ChromeVoxEditableHTMLInput'); |
-goog.provide('cvox.ChromeVoxEditableTextArea'); |
goog.provide('cvox.ChromeVoxEditableTextBase'); |
goog.provide('cvox.TextChangeEvent'); |
-goog.provide('cvox.TextHandlerInterface'); |
goog.provide('cvox.TypingEcho'); |
- |
-goog.require('cvox.BrailleTextHandler'); |
-goog.require('cvox.ContentEditableExtractor'); |
-goog.require('cvox.DomUtil'); |
-goog.require('cvox.EditableTextAreaShadow'); |
+goog.require('cvox.ChromeVox'); |
goog.require('cvox.TtsInterface'); |
goog.require('goog.i18n.MessageFormat'); |
+ |
/** |
- * @fileoverview Gives the user spoken feedback as they type, select text, |
- * and move the cursor in editable text controls, including multiline |
- * controls. |
- * |
- * The majority of the code is in ChromeVoxEditableTextBase, a generalized |
- * class that takes the current state in the form of a text string, a |
- * cursor start location and a cursor end location, and calls a speak |
- * method with the resulting text to be spoken. If the control is multiline, |
- * information about line breaks (including automatic ones) is also needed. |
- * |
- * Two subclasses, ChromeVoxEditableHTMLInput and |
- * ChromeVoxEditableTextArea, take a HTML input (type=text) or HTML |
- * textarea node (respectively) in the constructor, and automatically |
- * handle retrieving the current state of the control, including |
- * computing line break information for a textarea using an offscreen |
- * shadow object. It is still the responsibility of the user of this |
- * class to trap key and focus events and call this class's update |
- * method. |
+ * @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. |
*/ |
@@ -106,20 +89,6 @@ cvox.TypingEcho.shouldSpeakChar = function(typingEcho) { |
/** |
- * 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 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. |
@@ -172,12 +141,14 @@ cvox.ChromeVoxEditableTextBase = function(value, start, end, isPassword, tts) { |
this.multiline = false; |
/** |
- * An optional handler for braille output. |
- * @type {cvox.BrailleTextHandler|undefined} |
- * @private |
+ * 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.brailleHandler_ = cvox.ChromeVox.braille ? |
- new cvox.BrailleTextHandler(cvox.ChromeVox.braille) : undefined; |
+ this.lastChangeDescribed = false; |
+ |
}; |
@@ -234,24 +205,6 @@ cvox.ChromeVoxEditableTextBase.prototype.maxShortPhraseLen = 60; |
/** |
- * Whether or not the text control is a password. |
- * |
- * @type {boolean} |
- */ |
-cvox.ChromeVoxEditableTextBase.prototype.isPassword = false; |
- |
- |
-/** |
- * Whether or not the last update to the text and selection was described. |
- * |
- * Some consumers of this flag like |ChromeVoxEventWatcher| depend on and |
- * react to when this flag is false by generating alternative feedback. |
- * @type {boolean} |
- */ |
-cvox.ChromeVoxEditableTextBase.prototype.lastChangeDescribed = false; |
- |
- |
-/** |
* Get the line number corresponding to a particular index. |
* Default implementation that can be overridden by subclasses. |
* @param {number} index The 0-based character index. |
@@ -339,11 +292,6 @@ cvox.ChromeVoxEditableTextBase.prototype.shouldDescribeChange = function(evt) { |
*/ |
cvox.ChromeVoxEditableTextBase.prototype.speak = |
function(str, opt_triggeredByUser, opt_personality) { |
- // If there is a node associated with the editable text object, |
- // make sure that node has focus before speaking it. |
- if (this.node && (document.activeElement != this.node)) { |
- return; |
- } |
var queueMode = cvox.QueueMode.QUEUE; |
if (opt_triggeredByUser === true) { |
queueMode = cvox.QueueMode.FLUSH; |
@@ -374,36 +322,10 @@ cvox.ChromeVoxEditableTextBase.prototype.changed = function(evt) { |
this.value = evt.value; |
this.start = evt.start; |
this.end = evt.end; |
- |
- this.brailleCurrentLine_(); |
}; |
/** |
- * Shows the current line on the braille display. |
- * @private |
- */ |
-cvox.ChromeVoxEditableTextBase.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); |
- } |
-}; |
- |
-/** |
* Describe a change in the selection or cursor position when the text |
* stays the same. |
* @param {cvox.TextChangeEvent} evt The text change event. |
@@ -787,567 +709,3 @@ cvox.ChromeVoxEditableTextBase.prototype.moveCursorToPreviousParagraph = |
/******************************************/ |
- |
- |
-/** |
- * 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); |
- |
- /** |
- * 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); |
- |
- |
-/** |
- * Update the state of the text and selection and describe any changes as |
- * appropriate. |
- * |
- * @param {cvox.TextChangeEvent} evt The text change event. |
- */ |
-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); |
-}; |
- |
- |
-/** @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; |
-}; |
- |
- |
-/******************************************/ |
- |
- |
-/** |
- * 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(cvox.ChromeVox.msgs.getMsg('text_box_blank'), true); |
- if (this.brailleHandler_) { |
- this.brailleHandler_.changed('' /*line*/, 0 /*start*/, 0 /*end*/, |
- true /*multiline*/, null /*element*/, |
- evt.start /*lineStart*/); |
- } |
- } else { |
- goog.base(this, 'changed', evt); |
- } |
-}; |
- |
- |
-/** @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; |
-}; |