1 description("This tests that the input events are dispatched when contentEditable nodes are edited");
3 var actualInputEventCount = 0;
4 var expectedInputEventCount = 0;
6 function fired(evt, expectedId, expectedText)
8 actualInputEventCount++;
9 shouldBe("event.target.id", "'" + expectedId + "'");
10 shouldBe("event.target.innerHTML", "'" + expectedText + "'");
13 var testDataRoot = document.createElement("div");
14 document.body.appendChild(testDataRoot);
16 function makeTestTarget(fragment)
18 testDataRoot.innerHTML = fragment;
19 return testDataRoot.firstChild;
22 function clearTestTarget()
27 function setupForFiringTest(fragment, expectedText)
29 var target = makeTestTarget(fragment);
30 target.addEventListener("input", function(evt) { fired(evt, target.id, expectedText); });
31 sel.selectAllChildren(target);
32 expectedInputEventCount++;
36 var sel = document.getSelection();
38 // A trivial case: inserting text should dispatch the event
39 var target0 = setupForFiringTest('<p id="target0" contentEditable>Text should be replace this</p>', "Text");
40 sel.selectAllChildren(target0);
41 document.execCommand("insertText", false, "Text");
43 // A direct DOM manipulation shouldn't dispatch the event
44 var target1 = makeTestTarget('<p id="target1" contentEditable>Text should be insert via script:</p>');
45 target1.addEventListener("input", function(evt) { testFailed("should not be reached"); });
46 target1.firstChild.data += "Text";
48 // An event should be dispatched even if resulting DOM tree doesn't change after the edit. (with replacing it)
49 var target2Text = "This text should not be changed.";
50 var target2 = setupForFiringTest('<p id="target2" contentEditable>This text should not be changed.</p>', target2Text);
51 document.execCommand("insertText", false, target2Text);
53 // An "delete" command should dispatch an input event.
54 var target3 = setupForFiringTest('<p id="target3" contentEditable>This text shouldn be deleted.</p>', '');
55 document.execCommand("delete", false);
57 // A command other than text-editing should dispatch an input event.
58 // Also note that createLink is a composite command,
59 // so this test also ensures that even composite command dispatches the event only once.
60 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>");
61 document.execCommand("createLink", false, "http://www.example.com/");
63 // An event shouldn't be dispatched to a 'display:none' node.
64 var target5 = makeTestTarget('<p id="target5" contentEditable>This will not be rendered.</p>');
65 target5.addEventListener("input", function(evt) { testFailed("should not be reached"); });
66 sel.selectAllChildren(target5);
67 target5.style.display = "none";
68 document.execCommand("insertText", false, "Text");
70 // The event should be dispatched from the editable root.
71 makeTestTarget('<p id="target6parent" contentEditable><span id="target6start">Start,</span><span id="target6middle">Middle,</span><span id="target6end">End.</span></p>');
72 var target6parent = document.getElementById("target6parent");
73 var target6start = document.getElementById("target6start");
74 var target6middle = document.getElementById("target6middle");
75 var target6end = document.getElementById("target6end");
77 var expectedText6 = "<a href=\"http://www.example.com/\"><span id=\"target6start\">Start,</span><span id=\"target6middle\">Middle,</span><span id=\"target6end\">End.</span></a>";
78 target6parent.addEventListener("input", function(evt) { fired(evt, "target6parent", expectedText6); });
79 expectedInputEventCount++;
80 target6start.addEventListener("input", function(evt) { testFailed("should not be reached"); });
81 target6end.addEventListener("input", function(evt) { testFailed("should not be reached"); });
82 target6middle.addEventListener("input", function(evt) { fired(evt, "target6end", ""); });
83 sel.selectAllChildren(target6parent);
84 document.execCommand("createLink", false, "http://www.example.com/");
86 // Ensure key events can cause the event
87 var target7 = setupForFiringTest('<p id="target7" contentEditable>Replaced</p>', "X");
88 sel.selectAllChildren(target7);
89 eventSender.keyDown('X');
91 var target8 = setupForFiringTest('<p id="target8" contentEditable>Deleted</p>', '');
92 sel.selectAllChildren(target8);
93 eventSender.keyDown('delete');
95 var target9parent = makeTestTarget('<div id="target9parent" contenteditable><div id="target9child" contenteditable>foo</div></div>');
96 var target9child = document.getElementById('target9child');
97 target9child.addEventListener("input", function(evt) { testFailed("should not be reached"); });
98 target9parent.addEventListener("input", function(evt) { fired(evt, target9parent.id, '<div id="target9child" contenteditable="">Replacing</div>'); });
99 sel.selectAllChildren(target9child);
100 document.execCommand("insertText", false, "Replacing");
101 expectedInputEventCount++;
103 var target10parent = makeTestTarget('<div id="t10parent" contenteditable><div id="t10child" contenteditable=false><div id="t10gch" contenteditable>foo</div></div></div>');
104 var target10child = document.getElementById("t10child");
105 var target10gch = document.getElementById("t10gch");
106 target10gch.addEventListener("input", function(evt) { fired(evt, target10gch.id, 'Replacing'); });
107 sel.selectAllChildren(target10gch);
108 document.execCommand("insertText", false, "Replacing");
109 expectedInputEventCount++;
111 shouldBe("expectedInputEventCount", "actualInputEventCount");