blob: 5de8f6adca6036a9e3cbea474c7905e03010af20 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<script>
description("This tests that the input events are dispatched when contentEditable nodes are edited");
var actualInputEventCount = 0;
var expectedInputEventCount = 0;
function fired(evt, expectedId, expectedText)
{
actualInputEventCount++;
shouldBe("event.target.id", "'" + expectedId + "'");
shouldBe("event.target.innerHTML", "'" + expectedText + "'");
}
var testDataRoot = document.createElement("div");
document.body.appendChild(testDataRoot);
function makeTestTarget(fragment)
{
testDataRoot.innerHTML = fragment;
return testDataRoot.firstChild;
}
function clearTestTarget()
{
makeTestTarget("");
}
function setupForFiringTest(fragment, expectedText)
{
var target = makeTestTarget(fragment);
target.addEventListener("input", function(evt) { fired(evt, target.id, expectedText); });
sel.selectAllChildren(target);
expectedInputEventCount++;
return target;
}
var sel = document.getSelection();
// A trivial case: inserting text should dispatch the event
var target0 = setupForFiringTest('<p id="target0" contentEditable>Text should be replace this</p>', "Text");
sel.selectAllChildren(target0);
document.execCommand("insertText", false, "Text");
// A direct DOM manipulation shouldn't dispatch the event
var target1 = makeTestTarget('<p id="target1" contentEditable>Text should be insert via script:</p>');
target1.addEventListener("input", function(evt) { testFailed("should not be reached"); });
target1.firstChild.data += "Text";
// An event should be dispatched even if resulting DOM tree doesn't change after the edit. (with replacing it)
var target2Text = "This text should not be changed.";
var target2 = setupForFiringTest('<p id="target2" contentEditable>This text should not be changed.</p>', target2Text);
document.execCommand("insertText", false, target2Text);
// An "delete" command should dispatch an input event.
var target3 = setupForFiringTest('<p id="target3" contentEditable>This text shouldn be deleted.</p>', "<br>");
document.execCommand("delete", false);
// A command other than text-editing should dispatch an input event.
// Also note that createLink is a composite command,
// so this test also ensures that even composite command dispatches the event only once.
var target4 = setupForFiringTest('<p id="target4" contentEditable>This text should be a link.</p>', "<a href=\"http://www.example.com/\">This text should be a link.</a>");
document.execCommand("createLink", false, "http://www.example.com/");
// An event should be dispatched to a 'display:none' node.
var target5A = setupForFiringTest('<p id="target5A" contentEditable>This will not be rendered.</p>', 'Text');
sel.selectAllChildren(target5A);
target5A.style.display = "none";
document.execCommand("insertText", false, "Text");
// An event should be dispatched to a child of a 'display:none' node.
var target5B = setupForFiringTest('<p id="target5B" contentEditable>This <span id="target5BDestination">replace</span> will not be rendered.</p>', 'This <span id="target5BDestination">text</span> will not be rendered.');
var target5BDestination = document.getElementById("target5BDestination");
sel.selectAllChildren(target5BDestination);
target5B.style.display = "none";
document.execCommand("insertText", false, "text");
// The event should be dispatched from the editable root.
makeTestTarget('<p id="target6parent" contentEditable><span id="target6start">Start,</span><span id="target6middle">Middle,</span><span id="target6end">End.</span></p>');
var target6parent = document.getElementById("target6parent");
var target6start = document.getElementById("target6start");
var target6middle = document.getElementById("target6middle");
var target6end = document.getElementById("target6end");
var expectedText6 = "<a href=\"http://www.example.com/\"><span id=\"target6start\">Start,</span><span id=\"target6middle\">Middle,</span><span id=\"target6end\">End.</span></a>";
target6parent.addEventListener("input", function(evt) { fired(evt, "target6parent", expectedText6); });
expectedInputEventCount++;
target6start.addEventListener("input", function(evt) { testFailed("should not be reached"); });
target6end.addEventListener("input", function(evt) { testFailed("should not be reached"); });
target6middle.addEventListener("input", function(evt) { fired(evt, "target6end", ""); });
sel.selectAllChildren(target6parent);
document.execCommand("createLink", false, "http://www.example.com/");
// Ensure key events can cause the event
var target7 = setupForFiringTest('<p id="target7" contentEditable>Replaced</p>', "X");
sel.selectAllChildren(target7);
eventSender.keyDown('X');
var target8 = setupForFiringTest('<p id="target8" contentEditable>Deleted</p>', '<br>');
sel.selectAllChildren(target8);
eventSender.keyDown('delete');
var target9parent = makeTestTarget('<div id="target9parent" contenteditable><div id="target9child" contenteditable>foo</div></div>');
var target9child = document.getElementById('target9child');
target9child.addEventListener("input", function(evt) { testFailed("should not be reached"); });
target9parent.addEventListener("input", function(evt) { fired(evt, target9parent.id, '<div id="target9child" contenteditable="">Replacing</div>'); });
sel.selectAllChildren(target9child);
document.execCommand("insertText", false, "Replacing");
expectedInputEventCount++;
var target10parent = makeTestTarget('<div id="t10parent" contenteditable><div id="t10child" contenteditable=false><div id="t10gch" contenteditable>foo</div></div></div>');
var target10child = document.getElementById("t10child");
var target10gch = document.getElementById("t10gch");
target10gch.addEventListener("input", function(evt) { fired(evt, target10gch.id, 'Replacing'); });
sel.selectAllChildren(target10gch);
document.execCommand("insertText", false, "Replacing");
expectedInputEventCount++;
shouldBe("expectedInputEventCount", "actualInputEventCount");
clearTestTarget();
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>