let input = document.querySelector("input[type=text]");
// Setting value during composition causes committing composition before setting the value. input.focus();
let description = 'Setting input value at first "compositionupdate" event: '; input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "", `${description}input value should not have been modified at first "compositionupdate" event yet`); input.value = "def";
is(input.value, "def", `${description}input value should be the specified value at "compositionupdate" event (after setting the value)`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "def", `${description}input value should be the specified value at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
todo_is(input.value, "def", `${description}input value should be the specified value at "input" event`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
todo_is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`);
input.value = "";
description = 'Setting input value at second "compositionupdate" event: ';
synthesizeCompositionChange(
{ "composition":
{ "string": "ab", "clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 2, "length": 0 },
}); input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "ab", `${description}input value should not have been modified at second "compositionupdate" event yet`); input.value = "def";
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
is(input.value, "def", `${description}input value should be specified value at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "def", `${description}input value should be specified value at "input" event`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`);
input.value = "";
description = 'Setting input value at "input" event for first composition update: '; input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "", `${description}input value should not have been modified at first "compositionupdate" event yet`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "abc", `${description}input value should be the composition string at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "abc", `${description}input value should be the composition string at "input" event`); input.value = "def";
is(input.value, "def", `${description}input value should be the specified value at "input"event (after setting the value)`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`);
input.value = "";
description = 'Setting input value at "input" event for second composition update: ';
synthesizeCompositionChange(
{ "composition":
{ "string": "ab", "clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 2, "length": 0 },
}); input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "ab", `${description}input value should not have been modified at second "compositionupdate" event yet`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "abc", `${description}input value should be the composition string at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "abc", `${description}input value should be the composition string at "input" event`); input.value = "def";
is(input.value, "def", `${description}input value should be the specified value at "input"event (after setting the value)`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`);
input.value = "";
description = 'Setting input value and reframing at "input" event for first composition update: '; input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "", `${description}input value should not have been modified at first "compositionupdate" event yet`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "abc", `${description}input value should be the composition string at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "abc", `${description}input value should be the composition string at "input" event`); input.value = "def"; input.style.width = "1000px";
is(input.value, "def", `${description}input value should be the specified value at "input"event (after setting the value)`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`); input.style.width = "";
input.value = "";
description = 'Setting input value and reframing at "input" event for second composition update: ';
synthesizeCompositionChange(
{ "composition":
{ "string": "ab", "clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 2, "length": 0 },
}); input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "ab", `${description}input value should not have been modified at second "compositionupdate" event yet`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "abc", `${description}input value should be the composition string at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "abc", `${description}input value should be the composition string at "input" event`); input.value = "def"; input.style.width = "1000px";
is(input.value, "def", `${description}input value should be the specified value at "input"event (after setting the value)`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`); input.style.width = "";
input.value = "";
description = 'Setting input value and reframing with flushing layout at "input" event for first composition update: '; input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "", `${description}input value should not have been modified at first "compositionupdate" event yet`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "abc", `${description}input value should be the composition string at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "abc", `${description}input value should be the composition string at "input" event`); input.value = "def"; input.style.width = "1000px";
document.documentElement.scrollTop;
is(input.value, "def", `${description}input value should be the specified value at "input"event (after setting the value)`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`); input.style.width = "";
input.value = "";
description = 'Setting input value and reframing with flushing layout at "input" event for second composition update: ';
synthesizeCompositionChange(
{ "composition":
{ "string": "ab", "clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 2, "length": 0 },
}); input.addEventListener("compositionupdate", (aEvent) => {
is(input.value, "ab", `${description}input value should not have been modified at second "compositionupdate" event yet`);
}, {once: true}); input.addEventListener("compositionend", (aEvent) => {
todo_is(input.value, "abc", `${description}input value should be the composition string at "compositionend" event`);
}, {once: true}); input.addEventListener("input", (aEvent) => {
is(input.value, "abc", `${description}input value should be the composition string at "input" event`); input.value = "def"; input.style.width = "1000px";
document.documentElement.scrollTop;
is(input.value, "def", `${description}input value should be the specified value at "input"event (after setting the value)`);
}, {once: true});
synthesizeCompositionChange(
{ "composition":
{ "string": "abc", "clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
}, "caret": { "start": 3, "length": 0 },
});
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should be set to specified value after the last "input" event`); input.style.width = "";
// autocomplete and correcting misspelled word by spellchecker cause an "input" event with same path as setting input value. input.value = "";
description = 'Setting input value at "input" event whose inputType is "insertReplacementText';
let inputEventFired = false; input.addEventListener("input", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
inputEventFired = true;
is(input.value, "abc", `${description}input value should be inserted value at "input" event (before setting value)`); input.value = "def";
is(input.value, "def", `${description}input value should be specified value at "input" event (after setting value)`);
}, {once: true});
SpecialPowers.wrap(input).setUserInput("abc");
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should keep the specified value after the last "input" event`);
ok(inputEventFired, `${description}"input" event should've been fired for setUserInput("abc")`);
input.value = "";
description = 'Setting input value and reframing at "input" event whose inputType is "insertReplacementText';
inputEventFired = false; input.addEventListener("input", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
inputEventFired = true;
is(input.value, "abc", `${description}input value should be inserted value at "input" event (before setting value)`); input.value = "def"; input.style.width = "1000px";
is(input.value, "def", `${description}input value should be specified value at "input" event (after setting value)`);
}, {once: true});
SpecialPowers.wrap(input).setUserInput("abc");
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should keep the specified value after the last "input" event`);
ok(inputEventFired, `${description}"input" event should've been fired for setUserInput("abc")`); input.style.width = "";
input.value = "";
description = 'Setting input value and reframing with flushing layout at "input" event whose inputType is "insertReplacementText';
inputEventFired = false; input.addEventListener("input", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
inputEventFired = true;
is(input.value, "abc", `${description}input value should be inserted value at "input" event (before setting value)`); input.value = "def"; input.style.width = "1000px";
document.documentElement.scrollTop;
is(input.value, "def", `${description}input value should be specified value at "input" event (after setting value)`);
}, {once: true});
SpecialPowers.wrap(input).setUserInput("abc");
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should keep the specified value after the last "input" event`);
ok(inputEventFired, `${description}"input" event should've been fired for setUserInput("abc")`); input.style.width = "";
input.value = "";
description = 'Setting input value and destroying the frame at "input" event whose inputType is "insertReplacementText';
inputEventFired = false; input.addEventListener("input", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
inputEventFired = true;
is(input.value, "abc", `${description}input value should be inserted value at "input" event (before setting value)`); input.value = "def"; input.style.display = "none";
is(input.value, "def", `${description}input value should be specified value at "input" event (after setting value)`);
}, {once: true});
SpecialPowers.wrap(input).setUserInput("abc");
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "def", `${description}input value should keep the specified value after the last "input" event`);
ok(inputEventFired, `${description}"input" event should've been fired for setUserInput("abc")`); input.style.display = "inline";
input.value = "";
description = 'Changing input type at "input" event whose inputType is "insertReplacementText';
inputEventFired = false; input.addEventListener("input", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
inputEventFired = true;
is(input.value, "abc", `${description}input value should be inserted value at "input" event (before changing type)`); input.type = "button";
is(input.value, "abc", `${description}input value should keep inserted value at "input" event (after changing type)`);
}, {once: true});
SpecialPowers.wrap(input).setUserInput("abc");
is(input.value, "abc", `${description}input value should keep inserted value after the last "input" event`);
is(input.type, "button", `${description}input type should be changed correctly`);
ok(inputEventFired, `${description}"input" event should've been fired for setUserInput("abc")`); input.type = "text";
is(input.value, "abc", `${description}input value should keep inserted value immediately after restoring the type`);
todo(SpecialPowers.wrap(input).hasEditor, `${description}restoring input type should create editor if it's focused element`); input.blur(); input.focus();
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "abc", `${description}input value should keep inserted value after creating editor`);
input.value = "";
description = 'Changing input type and flush layout at "input" event whose inputType is "insertReplacementText';
inputEventFired = false; input.addEventListener("input", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
inputEventFired = true;
is(input.value, "abc", `${description}input value should be inserted value at "input" event (before changing type)`); input.type = "button"; input.getBoundingClientRect().height;
is(input.value, "abc", `${description}input value should keep inserted value at "input" event (after changing type)`);
}, {once: true});
SpecialPowers.wrap(input).setUserInput("abc");
is(input.value, "abc", `${description}input value should keep inserted value after the last "input" event`);
is(input.type, "button", `${description}input type should be changed correctly`);
ok(inputEventFired, `${description}"input" event should've been fired for setUserInput("abc")`); input.type = "text";
is(input.value, "abc", `${description}input value should keep inserted value immediately after restoring the type`);
todo(SpecialPowers.wrap(input).hasEditor, `${description}restoring input type should create editor if it's focused element`); input.blur(); input.focus();
is(SpecialPowers.wrap(input).editor.rootElement.firstChild.wholeText, input.value,
`${description}native anonymous text node should have exactly same value as value of <input> element`);
is(input.value, "abc", `${description}input value should keep inserted value after creating editor`);
function testSettingValueFromBeforeInput(aWithEditor, aPreventDefaultOfBeforeInput) {
let beforeInputEvents = [];
let inputEvents = [];
function recordEvent(aEvent) {
if (aEvent.type === "beforeinput") {
beforeInputEvents.push(aEvent);
} else {
inputEvents.push(aEvent);
}
}
let condition = `(${aWithEditor ? "with editor" : "without editor"}${aPreventDefaultOfBeforeInput ? ' and canceling "beforeinput" event' : ""}, the pref ${kSetUserInputCancelable ? "allows" : "disallows"} to cancel "beforeinput" event})`;
function Reset() {
beforeInputEvents = [];
inputEvents = [];
if (SpecialPowers.wrap(input).hasEditor != aWithEditor) {
if (aWithEditor) { input.blur(); input.focus(); // Associate `TextEditor` with input
if (!SpecialPowers.wrap(input).hasEditor) {
ok(false, `${description}Failed to associate TextEditor with the input ${condition}`);
return false;
}
} else { input.blur(); input.type = "button"; input.type = "text";
if (SpecialPowers.wrap(input).hasEditor) {
ok(false, `${description}Failed to disassociate TextEditor from the input ${condition}`);
return false;
}
}
}
return true;
}
description = `Setting value from "beforeinput" event listener whose inputType is "insertReplacementText" ${condition}: `; input.value = "abc";
if (!Reset()) {
return;
} input.addEventListener("beforeinput", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "beforeinput" event should be "insertReplacementText"`);
is(aEvent.cancelable, kSetUserInputCancelable, `${description}"beforeinput" event should be cancelable unless it's suppressed by the pref`);
is(input.value, "abc", `${description}The value shouldn't have been modified yet at "beforeinput" event listener`); input.addEventListener("beforeinput", recordEvent); input.addEventListener("input", recordEvent); input.value = "hig";
if (aPreventDefaultOfBeforeInput) {
aEvent.preventDefault();
}
}, {once: true});
SpecialPowers.wrap(input).setUserInput("def");
is(beforeInputEvents.length, 0, `${description}"beforeinput" event shouldn't be fired again`);
if (aPreventDefaultOfBeforeInput && kSetUserInputCancelable) {
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since "beforeinput" was canceled`);
is(inputEvents.length, 0,
`${description}"input" event shouldn't be fired since "beforeinput" was canceled`);
} else {
// XXX This result is different from Chrome (verified with spellchecker).
// Chrome inserts the new text to current value and selected range.
// It might be reasonable, but we don't touch this for now since it
// requires a lot of changes.
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since the event target was already modified`);
is(inputEvents.length, 1, `${description}"input" event should be fired`);
if (inputEvents.length) {
is(inputEvents[0].inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
is(inputEvents[0].data, "def",
`${description}data of "input" event should be the value specified by setUserInput()`);
}
} input.removeEventListener("beforeinput", recordEvent); input.removeEventListener("input", recordEvent);
description = `Setting value from "beforeinput" event listener whose inputType is "insertReplacementText" and changing the type to "button" ${condition}: `; input.value = "abc";
if (!Reset()) {
return;
} input.addEventListener("beforeinput", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "beforeinput" event should be "insertReplacementText"`);
is(aEvent.cancelable, kSetUserInputCancelable, `${description}"beforeinput" event should be cancelable unless it's suppressed by the pref`);
is(input.value, "abc", `${description}The value shouldn't have been modified yet at "beforeinput" event listener`); input.addEventListener("beforeinput", recordEvent); input.addEventListener("input", recordEvent); input.value = "hig"; input.type = "button";
if (aPreventDefaultOfBeforeInput) {
aEvent.preventDefault();
}
}, {once: true});
SpecialPowers.wrap(input).setUserInput("def");
is(beforeInputEvents.length, 0, `${description}"beforeinput" event shouldn't be fired again`);
if (aPreventDefaultOfBeforeInput && kSetUserInputCancelable) {
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since "beforeinput" was canceled`);
is(inputEvents.length, 0,
`${description}"input" event shouldn't be fired since "beforeinput" was canceled`);
} else {
// XXX This result is same as Chrome (verified with spellchecker).
// But this behavior is not consistent with just setting the value on Chrome.
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since the event target was already modified`);
// Same as Chrome
is(inputEvents.length, 0,
`${description}"input" event shouldn't be fired since the input element's type is changed`);
} input.type = "text"; input.removeEventListener("beforeinput", recordEvent); input.removeEventListener("input", recordEvent);
description = `Setting value from "beforeinput" event listener whose inputType is "insertReplacementText" and destroying the frame ${condition}: `; input.value = "abc";
if (!Reset()) {
return;
} input.addEventListener("beforeinput", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "beforeinput" event should be "insertReplacementText"`);
is(aEvent.cancelable, kSetUserInputCancelable, `${description}"beforeinput" event should be cancelable unless it's suppressed by the pref`);
is(input.value, "abc", `${description}The value shouldn't have been modified yet at "beforeinput" event listener`); input.addEventListener("beforeinput", recordEvent); input.addEventListener("input", recordEvent); input.value = "hig"; input.style.display = "none";
if (aPreventDefaultOfBeforeInput) {
aEvent.preventDefault();
}
}, {once: true});
SpecialPowers.wrap(input).setUserInput("def");
is(beforeInputEvents.length, 0, `${description}"beforeinput" event shouldn't be fired again`);
if (aPreventDefaultOfBeforeInput && kSetUserInputCancelable) {
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since "beforeinput" was canceled`);
is(inputEvents.length, 0,
`${description}"input" event shouldn't be fired since "beforeinput" was canceled`);
} else {
// XXX This result is same as Chrome (verified with spellchecker).
// But this behavior is not consistent with just setting the value on Chrome.
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since the event target was already modified`);
// Different from Chrome
is(inputEvents.length, 1,
`${description}"input" event should be fired even if the frame of target is destroyed`);
if (inputEvents.length) {
is(inputEvents[0].inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
is(inputEvents[0].data, "def",
`${description}data of "input" event should be the value specified by setUserInput()`);
}
} input.style.display = "inline"; input.removeEventListener("beforeinput", recordEvent); input.removeEventListener("input", recordEvent);
if (aWithEditor) {
return;
}
description = `Setting value from "beforeinput" event listener whose inputType is "insertReplacementText and create editor" ${condition}: `; input.value = "abc";
if (!Reset()) {
return;
} input.addEventListener("beforeinput", (aEvent) => {
is(aEvent.inputType, "insertReplacementText", `${description}inputType of "beforeinput" event should be "insertReplacementText"`);
is(aEvent.cancelable, kSetUserInputCancelable, `${description}"beforeinput" event should be cancelable unless it's suppressed by the pref`);
is(input.value, "abc", `${description}The value shouldn't have been modified yet at "beforeinput" event listener`); input.addEventListener("beforeinput", recordEvent); input.addEventListener("input", recordEvent); input.value = "hig"; input.focus();
if (aPreventDefaultOfBeforeInput) {
aEvent.preventDefault();
}
}, {once: true});
SpecialPowers.wrap(input).setUserInput("def");
is(beforeInputEvents.length, 0, `${description}"beforeinput" event shouldn't be fired again`);
if (aPreventDefaultOfBeforeInput && kSetUserInputCancelable) {
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since "beforeinput" was canceled`);
is(inputEvents.length, 0,
`${description}"input" event shouldn't be fired since "beforeinput" was canceled`);
} else {
// XXX This result is different from Chrome (verified with spellchecker).
// Chrome inserts the new text to current value and selected range.
// It might be reasonable, but we don't touch this for now since it
// requires a lot of changes.
is(input.value, "hig",
`${description}The value should be set to the specified value in "beforeinput" event listener since the event target was already modified`);
is(inputEvents.length, 1, `${description}"input" event should be fired`);
if (inputEvents.length) {
is(inputEvents[0].inputType, "insertReplacementText", `${description}inputType of "input" event should be "insertReplacementText"`);
is(inputEvents[0].data, "def",
`${description}data of "input" event should be the value specified by setUserInput()`);
}
} input.removeEventListener("beforeinput", recordEvent); input.removeEventListener("input", recordEvent);
}
// testSettingValueFromBeforeInput(true, true);
// testSettingValueFromBeforeInput(true, false);
testSettingValueFromBeforeInput(false, true);
testSettingValueFromBeforeInput(false, false);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.