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

Unified Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js

Issue 2945703002: add support for rich text selections (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/chromevox/injected/externs.js ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
index a07c9049b60bc9a84c4ab7e2d79e36e55742c34b..34a4f699a65959ab011d333545a5625dc20e3d7d 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -227,8 +227,14 @@ function AutomationRichEditableText(node) {
if (!root || !root.anchorObject || !root.focusObject)
return;
- this.line_ = new editing.EditableLine(
- root.anchorObject, root.anchorOffset, root.focusObject, root.focusOffset);
+ this.anchorLine_ = new editing.EditableLine(root.anchorObject,
dmazzoni 2017/06/19 15:11:51 Is the plan to refactor EditableLine to only take
David Tseng 2017/06/19 18:27:47 No, added comments to clarify. An editable line co
+ root.anchorOffset,
+ root.anchorObject,
+ root.anchorOffset);
+ this.focusLine_ = new editing.EditableLine(root.focusObject,
+ root.focusOffset,
+ root.focusObject,
+ root.focusOffset);
}
AutomationRichEditableText.prototype = {
@@ -240,14 +246,34 @@ AutomationRichEditableText.prototype = {
if (!root.anchorObject || !root.focusObject)
return;
+ var anchorLine = new editing.EditableLine(root.anchorObject,
+ root.anchorOffset,
+ root.anchorObject,
+ root.anchorOffset);
+ var focusLine = new editing.EditableLine(root.focusObject,
+ root.focusOffset,
+ root.focusObject,
+ root.focusOffset);
+
+ var prevAnchorLine = this.anchorLine_;
+ var prevFocusLine = this.focusLine_;
+ this.anchorLine_ = anchorLine;
+ this.focusLine_ = focusLine;
+
+ // Compute the current line based upon whether the current selection was
+ // extended from anchor or focus. The default behavior is to compute lines
+ // via focus.
+ var baseLineOnStart = prevFocusLine.strictEquals(focusLine);
+
var cur = new editing.EditableLine(
root.anchorObject, root.anchorOffset || 0,
- root.focusObject, root.focusOffset || 0);
- var prev = this.line_;
+ root.focusObject, root.focusOffset || 0,
+ baseLineOnStart);
this.line_ = cur;
- if (prev.equals(cur)) {
- // Collapsed cursor.
+ // Selection stayed within the same line(s) and didn't cross into new lines.
+ if (anchorLine.equals(prevAnchorLine) && focusLine.equals(prevFocusLine)) {
+ // Intra-line changes.
this.changed(new cvox.TextChangeEvent(
cur.text || '',
cur.startOffset || 0,
@@ -295,9 +321,24 @@ AutomationRichEditableText.prototype = {
return;
}
- // Just output the current line.
- cvox.ChromeVox.tts.speak(cur.text, cvox.QueueMode.CATEGORY_FLUSH);
- this.brailleCurrentRichLine_();
+ if (anchorLine.equals(focusLine)) {
+ // Current selection is on a new line not part of the previous selection.
+ this.line_ = focusLine;
+ cvox.ChromeVox.tts.speak(focusLine.text, cvox.QueueMode.CATEGORY_FLUSH);
+ this.brailleCurrentRichLine_();
+ } if (prevAnchorLine.equals(anchorLine)) {
+ // The selection changed in focus position.
+ this.line_ = focusLine;
+ cvox.ChromeVox.tts.speak(focusLine.text, cvox.QueueMode.CATEGORY_FLUSH);
+ this.brailleCurrentRichLine_();
+ } else if (prevFocusLine.equals(focusLine)) {
+ // The selection changed in anchor position.
+ this.line_ = anchorLine;
+ cvox.ChromeVox.tts.speak(anchorLine.text, cvox.QueueMode.CATEGORY_FLUSH);
+ this.brailleCurrentRichLine_();
+ } else {
+ // Describe a generic DOM selection.
dmazzoni 2017/06/19 15:11:51 Want to put some sort of placeholder here? Or may
David Tseng 2017/06/19 18:27:47 Removed. We don't want to favor focus but favor th
+ }
// The state in EditableTextBase needs to get updated with the new line
// contents, so that subsequent intra-line changes get the right state
@@ -455,9 +496,15 @@ editing.observer_ = new editing.EditingChromeVoxStateObserver();
/**
* An EditableLine encapsulates all data concerning a line in the automation
* tree necessary to provide output.
+ * @param {AutomationNode} startNode
+ * @param {number} startIndex
+ * @param {AutomationNode} endNode
+ * @param {number} endIndex
+ * @param {boolean=} opt_baseLineOnStart
* @constructor
*/
-editing.EditableLine = function(startNode, startIndex, endNode, endIndex) {
+editing.EditableLine =
+ function(startNode, startIndex, endNode, endIndex, opt_baseLineOnStart) {
/** @private {!Cursor} */
this.start_ = new Cursor(startNode, startIndex);
this.start_ = this.start_.deepEquivalent || this.start_;
@@ -481,26 +528,38 @@ editing.EditableLine = function(startNode, startIndex, endNode, endIndex) {
this.lineStartContainer_;
/** @private {number} */
this.localLineStartContainerOffset_ = 0;
+ /** @private {AutomationNode|undefined} */
+ this.lineEndContainer_;
+ /** @private {number} */
+ this.localLineEndContainerOffset_ = 0;
- this.computeLineData_();
+ this.computeLineData_(opt_baseLineOnStart);
};
editing.EditableLine.prototype = {
/** @private */
- computeLineData_: function() {
+ computeLineData_: function(opt_baseLineOnStart) {
+ // Note that we calculate the line based only upon anchor or focus even if
+ // they do not fall on the same line. It is up to the caller to specify
+ // which end to base this line upon since it requires reasoning about two
+ // lines.
var nameLen = 0;
- if (this.start_.node.name)
- nameLen = this.start_.node.name.length;
+ var lineBase = opt_baseLineOnStart ? this.start_ : this.end_;
+ var lineExtend = opt_baseLineOnStart ? this.end_ : this.start_;
+
+ if (lineBase.node.name)
+ nameLen = lineBase.node.name.length;
- this.value_ = new Spannable(this.start_.node.name || '', this.start_);
- if (this.start_.node == this.end_.node)
- this.value_.setSpan(this.end_, 0, nameLen);
+ this.value_ = new Spannable(lineBase.node.name || '', lineBase);
+ if (lineBase.node == lineExtend.node)
+ this.value_.setSpan(lineExtend, 0, nameLen);
// Initialize defaults.
- this.lineStart_ = this.start_.node;
+ this.lineStart_ = lineBase.node;
this.lineEnd_ = this.lineStart_;
this.startContainer_ = this.lineStart_.parent;
this.lineStartContainer_ = this.lineStart_.parent;
+ this.lineEndContainer_ = this.lineStart_.parent;
// Annotate each chunk with its associated inline text box node.
this.value_.setSpan(this.lineStart_, 0, this.lineStart_.name.length);
@@ -547,6 +606,7 @@ editing.EditableLine.prototype = {
this.value_.append(new Spannable(lineEnd.name, annotation));
}
+ this.lineEndContainer_ = this.lineEnd_.parent;
// Finally, annotate with all parent static texts as NodeSpan's so that
// braille routing can key properly into the node with an offset.
@@ -566,6 +626,11 @@ editing.EditableLine.prototype = {
textCountAfterLineEnd += finder.name.length;
}
+ if (this.lineEndContainer_.name) {
+ this.localLineEndContainerOffset_ =
+ this.lineEndContainer_.name.length - textCountAfterLineEnd;
+ }
+
var len = 0;
for (var i = 0; i < parents.length; i++) {
var parent = parents[i];
@@ -605,7 +670,14 @@ editing.EditableLine.prototype = {
* @return {number}
*/
get startOffset() {
- return this.value_.getSpanStart(this.start_) + this.start_.index;
+ // It is possible that the start cursor points to content before this line
+ // (e.g. in a multi-line selection).
+ try {
+ return this.value_.getSpanStart(this.start_) + this.start_.index;
+ } catch (e) {
+ // When that happens, fall back to the start of this line.
+ return 0;
+ }
},
/**
@@ -613,7 +685,11 @@ editing.EditableLine.prototype = {
* @return {number}
*/
get endOffset() {
- return this.value_.getSpanStart(this.end_) + this.end_.index;
+ try {
+ return this.value_.getSpanStart(this.end_) + this.end_.index;
+ } catch (e) {
+ return this.value_.length - 1;
+ }
},
/**
@@ -660,6 +736,21 @@ editing.EditableLine.prototype = {
return this.value_.toString();
},
+ /**
+ *
+ */
+ equalsStart: function(otherLine) {
+ return otherLine.lineStartContainer_ == this.lineStartContainer_ &&
+ otherLine.localLineStartContainerOffset_ ==
+ this.localLineStartContainerOffset_;
+ },
+
+ equalsEnd: function(otherLine) {
+ return otherLine.lineEndContainer_ == this.lineEndContainer_ &&
+ otherLine.localLineEndContainerOffset_ ==
+ this.localLineEndContainerOffset_;
+ },
+
/**
* Returns true if |otherLine| surrounds the same line as |this|. Note that
* the contents of the line might be different.
@@ -669,9 +760,13 @@ editing.EditableLine.prototype = {
// Equality is intentionally loose here as any of the state nodes can be
// invalidated at any time. We rely upon the start/anchor of the line
// staying the same.
- return otherLine.lineStartContainer_ == this.lineStartContainer_ &&
- otherLine.localLineStartContainerOffset_ ==
- this.localLineStartContainerOffset_;
+ return this.equalsStart(otherLine) || this.equalsEnd(otherLine);
+ },
+
+ strictEquals: function(otherLine) {
+ return this.equals(otherLine) &&
+ this.startOffset == otherLine.startOffset &&
+ this.endOffset == otherLine.endOffset;
}
};
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/chromevox/injected/externs.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698