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

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

Issue 2704443002: Selection API: extend() should operate DOM Ranges. (Closed)
Patch Set: . 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..f22507c13b0bcdd743b7d5f35b7cce75dbb18640 100644
--- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -81,6 +81,18 @@ bool DOMSelection::isBaseFirstInSelection() const {
return selection.base() <= selection.extent();
}
+const Position& DOMSelection::anchorPosition() const {
+ DCHECK(frame());
+ return frame()->selection().selectionInDOMTree().base();
+}
+
+const Position& DOMSelection::focusPosition() const {
+ DCHECK(frame());
+ return frame()->selection().selectionInDOMTree().extent();
+}
+
+// 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 +417,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 +436,57 @@ 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());
+ Position newFocus(node, offset);
yoichio 2017/02/16 07:26:05 Could you declare |const Position newFocus| ?
tkent 2017/02/16 08:14:38 Yes, done.
+
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.
+
+ // 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());
+ }
+
+ // 8. Set the context object's range to newRange.
yoichio 2017/02/16 07:26:05 How about following code to share?: SelectionInDO
tkent 2017/02/16 08:14:38 Done.
+ if (newRange->collapsed()) {
frame()->selection().setSelection(SelectionInDOMTree::Builder()
- .collapse(Position(node, offset))
+ .collapse(newFocus)
+ .setIsDirectional(true)
+ .build());
+ } else {
+ frame()->selection().setSelection(SelectionInDOMTree::Builder()
+ .collapse(oldAnchor)
+ .extend(newFocus)
.setIsDirectional(true)
.build());
- return;
}
- frame()->selection().setSelection(SelectionInDOMTree::Builder()
- .collapse(base)
- .extend(Position(node, offset))
- .setIsDirectional(true)
- .build());
+ cacheRangeIfSelectionOfDocument(newRange);
}
Range* DOMSelection::getRangeAt(int index,
@@ -469,14 +516,14 @@ 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();
Node* node = shadowAdjustedNode(anchor);
if (!node) // crbug.com/595100
return nullptr;
- Position focus = focusPosition(visibleSelection());
+ Position focus = blink::focusPosition(visibleSelection());
if (!visibleSelection().isBaseFirst()) {
return Range::create(*anchor.document(), shadowAdjustedNode(focus),
shadowAdjustedOffset(focus), node,
« 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