Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[css-pseudo] Fix text selection and drag-and-drop for pseudo-elements
Before this patch, if you had a tree like <div><div::before>abc</div::before>def</div> and you tried to select "bc", Chromium would end up selecting "ef" in some cases. Similarly, trying to drag a text and drop it between "bc", would end up inserting the text between "ef". This patch fixes the problem, now trying to select "bc" won't select anything. And dropping some text between "bc" will insert it between the "cd". BUG=1051685 TEST=external/wpt/css/css-pseudo/text-selection.html TEST=fast/css-generated-content/drag-and-drop.html The 2nd test is internal because I didn't manage to properly simulate drag and drop using testdriver.js Change-Id: Iedd594b46022ed434bdb1462232c717ec08f5304
- Loading branch information
1 parent
3c631e2
commit e578588
Showing
1 changed file
with
87 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>CSS Pseudo-Elements Test: Text selection</title> | ||
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#treelike"> | ||
<link rel="help" href="https://drafts.csswg.org/css-ui/#user-interaction"> | ||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com"> | ||
<meta name="assert" content="This test checks that text in a ::before or ::marker pseudo-element can't be selected." /> | ||
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> | ||
<style> | ||
.test { | ||
font: 10px/1 Ahem; | ||
margin-left: 200px; | ||
} | ||
#before::before { | ||
content: "::before"; | ||
display: inline-block; | ||
margin-left: -80px; | ||
} | ||
#marker { | ||
display: list-item; | ||
list-style-type: "::marker"; | ||
} | ||
#before-marker::before { | ||
content: ""; | ||
display: list-item; | ||
list-style-type: "::marker"; | ||
height: 0; | ||
} | ||
</style> | ||
<div class="test" id="before"><span>helloworld</span></div> | ||
<div class="test" id="marker"><span>helloworld</span></div> | ||
<div class="test" id="before-marker"><span>helloworld</span></div> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-actions.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script> | ||
function createSelection(element, start, end, step) { | ||
getSelection().empty(); | ||
step = Math.abs(step); | ||
const actions = new test_driver.Actions(); | ||
actions.pointerMove(start, 0, {origin: element}); | ||
actions.pointerDown(); | ||
if (start < end) { | ||
for (let x = start + step; x < end; x += step) | ||
actions.pointerMove(x, 0, {origin: element}); | ||
} else { | ||
for (let x = start - step; x > end; x -= step) | ||
actions.pointerMove(x, 0, {origin: element}); | ||
} | ||
actions.pointerMove(end, 0, {origin: element}); | ||
actions.pointerUp(); | ||
return actions.send(); | ||
} | ||
(async function() { | ||
setup({ explicit_done: true }); | ||
for (let target of document.querySelectorAll(".test")) { | ||
const contents = target.querySelector("span"); | ||
const text = contents.firstChild; | ||
const s = getSelection(); | ||
|
||
// Create a selection that starts in the middle of the element contents | ||
// and ends in the middle of the pseudo-element | ||
await createSelection(contents, 0, -90, 10); | ||
test(function(t) { | ||
assert_equals(s.toString(), "hello", "toString"); | ||
assert_equals(s.anchorNode, text, "anchorNode"); | ||
assert_equals(s.anchorOffset, 5, "anchorOffset"); | ||
assert_equals(s.focusNode, text, "focusNode"); | ||
assert_equals(s.focusOffset, 0, "focusOffset"); | ||
}, "Selection ending in ::" + target.id); | ||
|
||
// Create a selection that starts and ends inside the pseudo-element. | ||
await createSelection(contents, -80, -110, 10); | ||
test(function(t) { | ||
assert_equals(s.toString(), "", "toString"); | ||
assert_in_array(s.anchorNode, [text, null], "anchorNode"); | ||
assert_equals(s.anchorOffset, 0, "anchorOffset"); | ||
assert_in_array(s.focusNode, [text, null], "focusNode"); | ||
assert_equals(s.focusOffset, 0, "focusOffset"); | ||
}, "Selection contained in ::" + target.id); | ||
} | ||
done(); | ||
})(); | ||
</script> | ||
|