Skip to content

Commit

Permalink
Let document.caretPositionFromPoint work correctly in text control.
Browse files Browse the repository at this point in the history
If the point is inside input/text area element, the `CaretPosition`
should have `offsetNode` pointing to the text control element instead
of the inner editor element inside the user-agent shadow tree.

The behavior is also defined in step 4 of the
spec[1].

[1]: https://drafts.csswg.org/cssom-view/#dom-document-caretpositionfrompoint

Bug: 41487363
Change-Id: I1c024bdf6ce9620905a28487c8c91383f2086a54
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5531199
Reviewed-by: Koji Ishii <kojii@chromium.org>
Reviewed-by: Sanket Joshi <sajos@microsoft.com>
Reviewed-by: Mason Freed <masonf@chromium.org>
Commit-Queue: Siye Liu <siliu@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1301622}
  • Loading branch information
siliu1 authored and chromium-wpt-export-bot committed May 15, 2024
1 parent f23e47a commit dd39fe6
Showing 1 changed file with 70 additions and 0 deletions.
70 changes: 70 additions & 0 deletions shadow-dom/Document-caretPositionFromPoint.tentative.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,34 @@
assert_equals(caretPosition.offset, characterIndex);
}, "document.caretPositionFromPoint() should return a CaretPosition at the specified location");

test(() => {
container.setHTMLUnsafe(`<input value='text inside input' />`);
const rect = container.firstChild.getBoundingClientRect();
// Get x and y coordinate at left-most location inside input element.
const x = rect.left + 1;
const y = rect.top + rect.height / 2;
const caretPosition = document.caretPositionFromPoint(x, y);
assert_true(caretPosition instanceof CaretPosition);
assert_true(caretPosition.offsetNode instanceof Node);
assert_equals(typeof(caretPosition.offset), "number");
assert_equals(caretPosition.offsetNode, container.firstChild);
assert_equals(caretPosition.offset, 0);
}, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to an input element which is the offsetNode.");

test(() => {
container.setHTMLUnsafe(`<textarea rows="2" cols="4">12345678901234567890</textarea>`);
const rect = container.firstChild.getBoundingClientRect();
// Get x and y coordinate at "1234|5678..."
const x = rect.left + 1;
const y = rect.top + rect.height * 0.75;
const caretPosition = document.caretPositionFromPoint(x, y);
assert_true(caretPosition instanceof CaretPosition);
assert_true(caretPosition.offsetNode instanceof Node);
assert_equals(typeof(caretPosition.offset), "number");
assert_equals(caretPosition.offsetNode, container.firstChild);
assert_equals(caretPosition.offset, 4);
}, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to a textarea element which is the offsetNode.");

test(() => {
container.setHTMLUnsafe(`a<div id="host"></div>b`);
const shadowRoot = host.attachShadow({mode: 'closed'});
Expand Down Expand Up @@ -72,6 +100,48 @@
assert_equals(caretPosition.offset, characterIndex);
}, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location when the non-intersecting shadow tree is specified as an argument');

test(() => {
container.setHTMLUnsafe(`
a<div id="host">
<template shadowrootmode=open>
<input value='text inside input' />
</template>
</div>efg`);
const shadowRoot = host.shadowRoot;
const shadowRootInputElement = shadowRoot.querySelector("input");
const rect = shadowRootInputElement.getBoundingClientRect();
// Get x and y coordinate at left-most location inside input element.
const x = rect.left + 1;
const y = rect.top + rect.height / 2;
const caretPosition = document.caretPositionFromPoint(x, y, shadowRoot);
assert_true(caretPosition instanceof CaretPosition);
assert_true(caretPosition.offsetNode instanceof Node);
assert_equals(typeof(caretPosition.offset), "number");
assert_equals(caretPosition.offsetNode, shadowRootInputElement);
assert_equals(caretPosition.offset, 0);
}, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to an input element when the shadow tree is specified as an argument.");

test(() => {
container.setHTMLUnsafe(`
a<div id="host">
<template shadowrootmode=open>
<input value='text inside input' />
</template>
</div>efg`);
const shadowRoot = host.shadowRoot;
const shadowRootInputElement = shadowRoot.querySelector("input");
const rect = shadowRootInputElement.getBoundingClientRect();
// Get x and y coordinate at left-most location inside input element.
const x = rect.left + 1;
const y = rect.top + rect.height / 2;
const caretPosition = document.caretPositionFromPoint(x, y);
assert_true(caretPosition instanceof CaretPosition);
assert_true(caretPosition.offsetNode instanceof Node);
assert_equals(typeof(caretPosition.offset), "number");
assert_equals(caretPosition.offsetNode, container);
assert_equals(caretPosition.offset, 1);
}, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the input element's shadow host\'s parent when the shadow tree is not specified as an argument.");

test(() => {
container.setHTMLUnsafe(`
a<div id="host">
Expand Down

0 comments on commit dd39fe6

Please sign in to comment.