1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
<!DOCTYPE html>
<meta charset=utf-8>
<title>text field selection: setRangeText</title>
<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#display_none {display:none;}
</style>
<div id="log"></div>
<input type=text id=text value="foobar">
<input type=search id=search value="foobar">
<input type=tel id=tel value="foobar">
<input type=url id=url value="foobar">
<input type=password id=password value="foobar">
<input id=display_none value="foobar">
<textarea id=textarea>foobar</textarea>
<script>
var input = document.createElement("input");
input.id = "input_not_in_doc";
input.value = "foobar";
var elements = [
document.getElementById("text"),
document.getElementById("search"),
document.getElementById("tel"),
document.getElementById("url"),
document.getElementById("password"),
document.getElementById("display_none"),
document.getElementById("textarea"),
input,
]
function untilEvent(element, eventName) {
return new Promise((resolve) => {
element.addEventListener(eventName, resolve, { once: true });
});
}
elements.forEach(function(element) {
test(function() {
element.value = "foobar";
element.selectionStart = 0;
element.selectionEnd = 3;
assert_equals(element.selectionStart, 0);
assert_equals(element.selectionEnd, 3);
element.setRangeText("foobar2");
assert_equals(element.value, "foobar2bar");
assert_equals(element.selectionStart, 0);
assert_equals(element.selectionEnd, 7);
element.setRangeText("foobar3", 7, 10);
assert_equals(element.value, "foobar2foobar3");
}, element.id + " setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments");
test(function(){
element.value = "foobar";
element.selectionStart = 0;
element.selectionEnd = 0;
element.setRangeText("foobar2", 0, 3); // no 4th arg, default "preserve"
assert_equals(element.value, "foobar2bar");
assert_equals(element.selectionStart, 0);
assert_equals(element.selectionEnd, 0);
}, element.id + " selectionMode missing");
test(function(){
element.value = "foobar"
element.setRangeText("foo", 3, 6, "select");
assert_equals(element.value, "foofoo");
assert_equals(element.selectionStart, 3);
assert_equals(element.selectionEnd, 6);
}, element.id + " selectionMode 'select'");
test(function(){
element.value = "foobar"
element.setRangeText("foo", 3, 6, "start");
assert_equals(element.value, "foofoo");
assert_equals(element.selectionStart, 3);
assert_equals(element.selectionEnd, 3);
}, element.id + " selectionMode 'start'");
test(function(){
element.value = "foobar"
element.setRangeText("foobar", 3, 6, "end");
assert_equals(element.value, "foofoobar");
assert_equals(element.selectionStart, 9);
assert_equals(element.selectionEnd, 9);
}, element.id + " selectionMode 'end'");
test(function(){
element.value = "foobar"
element.selectionStart = 0;
element.selectionEnd = 5;
assert_equals(element.selectionStart, 0);
element.setRangeText("", 3, 6, "preserve");
assert_equals(element.value, "foo");
assert_equals(element.selectionStart, 0);
assert_equals(element.selectionEnd, 3);
}, element.id + " selectionMode 'preserve'");
test(function(){
assert_throws_dom("INDEX_SIZE_ERR", function() {
element.setRangeText("barfoo", 2, 1);
});
}, element.id + " setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception");
test(function(){
assert_throws_js(TypeError, function() {
element.setRangeText();
});
}, element.id + " setRangeText without argument throws a type error");
promise_test(async (t) => {
// At this point there are already "select" events queued up on
// "element". Give them time to fire; otherwise we can get spurious
// passes.
//
// This is unfortunately racy in that we might _still_ get spurious
// passes. I'm not sure how best to handle that.
t.step_timeout(function() {
var q = false;
element.onselect = t.step_func_done(function(e) {
assert_true(q, "event should be queued");
assert_true(e.isTrusted, "event is trusted");
assert_true(e.bubbles, "event bubbles");
assert_false(e.cancelable, "event is not cancelable");
});
element.setRangeText("foobar2", 0, 6);
q = true;
}, 10);
}, element.id + " setRangeText fires a select event");
promise_test(async () => {
element.value = "XXXXXXXXXXXXXXXXXXX";
const { length } = element.value;
element.setSelectionRange(0, length);
await untilEvent(element, "select");
element.setRangeText("foo", 2, 2);
await untilEvent(element, "select");
assert_equals(element.selectionStart, 0, ".selectionStart");
assert_equals(element.selectionEnd, length + 3, ".selectionEnd");
}, element.id + " setRangeText fires a select event when fully selected");
promise_test(async () => {
element.value = "XXXXXXXXXXXXXXXXXXX";
element.select();
await untilEvent(element, "select");
element.setRangeText("foo", 2, 2);
await untilEvent(element, "select");
assert_equals(element.selectionStart, 0, ".selectionStart");
assert_equals(element.selectionEnd, element.value.length, ".selectionEnd");
}, element.id + " setRangeText fires a select event after select()");
})
</script>
|