Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>Selection.modify() inside contenteditable</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div contenteditable id="host">Editable</div>
<div>Non-editable</div>
<div id="inlinehosts">
Prefix: <span contenteditable title="inline">Editable</span>: Suffix<br>
Prefix: <span contenteditable style="display:inline-block;" title="inline-block">Editable</span>: Suffix<br>
<span contenteditable title="suffix only">Editable</span>: Suffix<br>
Prefix: <span contenteditable title="prefix only">Editable</span><br>
<span contenteditable title="standalone">Editable</span><br>
Prefix: <span contenteditable title="inline linebreak">Edit<br>able</span>: Suffix<br>
Prefix: <span contenteditable style="display:inline-block;" title="inline-block linebreak">Edit<br>able</span>:
Suffix<br>
</div>
<script>
/** @param {Node} parent */
function* textNodeEntries(parent) {
for (const [i, node] of parent.childNodes.entries()) {
if (node.nodeType === Node.TEXT_NODE) {
yield [i, node];
}
}
}
const selection = getSelection();
test(() => {
selection.collapse(host);
selection.modify('extend', 'forward', 'word');
selection.modify('extend', 'forward', 'word');
assert_equals(selection.focusNode.parentElement, host);
}, "Selection.modify() must not select outside of the host");
/** @type {NodeListOf<HTMLElement>} */
const hosts = inlinehosts.querySelectorAll("span[contenteditable]");
for (const host of hosts) {
test(() => {
for (const [i, text] of textNodeEntries(host)) {
selection.collapse(text, 1);
selection.modify("move", "forward", "lineboundary");
if (selection.focusNode === host) {
assert_equals(selection.focusOffset, i + 1, "focusOffset should be after the text node");
} else {
assert_equals(selection.focusNode, text, "focusNode should be the text node");
assert_equals(selection.focusOffset, text.textContent.length, "focusOffset should be the length of the text node");
}
}
}, `Selection.modify('move', 'forward', 'lineboundary') must be within the inline editing host: ${host.title}`);
test(() => {
for (const [i, text] of textNodeEntries(host)) {
selection.collapse(text, 1);
selection.modify("move", "backward", "lineboundary");
assert_equals(selection.focusNode, text, "focusNode should be the text node");
assert_equals(selection.focusOffset, 0, "focusOffset should be 0");
}
}, `Selection.modify('move', 'backward', 'lineboundary') must be within the inline editing host: ${host.title}`);
}
</script>