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

Unified Diff: third_party/WebKit/Source/core/editing/DOMSelection.cpp

Issue 2704443002: Selection API: extend() should operate DOM Ranges. (Closed)
Patch Set: rebase Created 3 years, 10 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 | « third_party/WebKit/Source/core/editing/DOMSelection.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/editing/DOMSelection.cpp
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
index da74aa29d601e9082424cc260e49acffe948b5b7..8d1a24704a2080ce07acdbb13d972dded6a10509 100644
--- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -81,6 +81,13 @@ bool DOMSelection::isBaseFirstInSelection() const {
return selection.base() <= selection.extent();
}
+const Position& DOMSelection::anchorPosition() const {
+ DCHECK(frame());
+ return frame()->selection().selectionInDOMTree().base();
+}
+
+// TODO(tkent): Following four functions based on VisibleSelection should be
+// removed.
static Position anchorPosition(const VisibleSelection& selection) {
Position anchor =
selection.isBaseFirst() ? selection.start() : selection.end();
@@ -405,7 +412,10 @@ void DOMSelection::extend(Node* node,
int offset,
ExceptionState& exceptionState) {
DCHECK(node);
+ // https://www.w3.org/TR/selection-api/#dom-selection-extend
+ // 2. If the context object is empty, throw an InvalidStateError exception and
+ // abort these steps.
if (rangeCount() == 0) {
exceptionState.throwDOMException(
InvalidStateError, "This Selection object doesn't have any Ranges.");
@@ -421,25 +431,51 @@ void DOMSelection::extend(Node* node,
if (exceptionState.hadException())
return;
+ // 1. If node's root is not the document associated with the context object,
+ // abort these steps.
if (!isValidForPosition(node))
return;
+ // 3. Let oldAnchor and oldFocus be the context object's anchor and focus, and
+ // let newFocus be the boundary point (node, offset).
+ const Position& oldAnchor = anchorPosition();
+ DCHECK(!oldAnchor.isNull());
+ const Position newFocus(node, offset);
+
clearCachedRangeIfSelectionOfDocument();
- const Position& base = frame()->selection().base();
- if (base.isNull()) {
- // TODO(editing-dev): We should throw |InvalidStateError| if selection is
- // none to follow the spec.
- frame()->selection().setSelection(SelectionInDOMTree::Builder()
- .collapse(Position(node, offset))
- .setIsDirectional(true)
- .build());
- return;
+
+ // 4. Let newRange be a new range.
+ Range* newRange = Range::create(*frame()->document());
+
+ // 5. If node's root is not the same as the context object's range's root, set
+ // newRange's start and end to newFocus.
+ // E.g. oldAnchor might point in shadow Text node in TextControlElement.
+ if (oldAnchor.anchorNode()->treeRoot() != node->treeRoot()) {
+ newRange->setStart(node, offset);
+ newRange->setEnd(node, offset);
+
+ } else if (oldAnchor <= newFocus) {
+ // 6. Otherwise, if oldAnchor is before or equal to newFocus, set newRange's
+ // start to oldAnchor, then set its end to newFocus.
+ newRange->setStart(oldAnchor.anchorNode(),
+ oldAnchor.offsetInContainerNode());
+ newRange->setEnd(node, offset);
+
+ } else {
+ // 7. Otherwise, set newRange's start to newFocus, then set its end to
+ // oldAnchor.
+ newRange->setStart(node, offset);
+ newRange->setEnd(oldAnchor.anchorNode(), oldAnchor.offsetInContainerNode());
}
- frame()->selection().setSelection(SelectionInDOMTree::Builder()
- .collapse(base)
- .extend(Position(node, offset))
- .setIsDirectional(true)
- .build());
+
+ // 8. Set the context object's range to newRange.
+ SelectionInDOMTree::Builder builder;
+ if (newRange->collapsed())
+ builder.collapse(newFocus);
+ else
+ builder.collapse(oldAnchor).extend(newFocus);
+ frame()->selection().setSelection(builder.setIsDirectional(true).build());
+ cacheRangeIfSelectionOfDocument(newRange);
}
Range* DOMSelection::getRangeAt(int index,
@@ -469,7 +505,7 @@ Range* DOMSelection::primaryRangeOrNull() const {
}
Range* DOMSelection::createRangeFromSelectionEditor() const {
- Position anchor = anchorPosition(visibleSelection());
+ Position anchor = blink::anchorPosition(visibleSelection());
if (isSelectionOfDocument() && !anchor.anchorNode()->isInShadowTree())
return frame()->selection().firstRange();
« no previous file with comments | « third_party/WebKit/Source/core/editing/DOMSelection.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698