edit-context-inheritability.tentative.html (7504B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>EditContext: Inherited Editability</title> 5 <meta name="author" title="Dan Clark" href="mailto:daniec@microsoft.com"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="/resources/testdriver.js"></script> 9 <script src="/resources/testdriver-actions.js"></script> 10 <script src="/resources/testdriver-vendor.js"></script> 11 </head> 12 <body> 13 <div id="edit-context-top-0">Text in EditContext-associated element, should be editable</div> 14 15 <div id="edit-context-top-1"> 16 <div id="default-1"> 17 Element child of EditContext, should be editable 18 </div> 19 </div> 20 21 <div id="edit-context-top-2"> 22 <div id="noteditable-2" contenteditable="false"> 23 <div id="editable-in-noteditable-2" contenteditable=""> 24 This is a contenteditable="" child of contenteditable="false" parent. 25 This node should be editable. It should be the target of beforeinput/input events when the user edits here. 26 The grandparent node #edit-context-0 should not be the target of beforeinput/input events, 27 and the EditContext should not receive 28 textupdate events 29 </div> 30 </div> 31 </div> 32 33 <div id="edit-context-top-3"> 34 <div id="noteditable-3" contenteditable="false"> 35 <div id="editable-in-noteditable-3" contenteditable=""> 36 <div id="contenteditable-in-contenteditable-3" contenteditable=""> 37 This is an contenteditable="" child of a contenteditable="". Since this is the child of an 38 editable element, when the user types here, it's the parent contenteditable="" that gets 39 input/beforeinput events, and this doesn't. Basically the child contenteditable="" attribute 40 is a no-op. 41 </div> 42 </div> 43 </div> 44 </div> 45 46 <div id="edit-context-top-4"> 47 <div id="noteditable-4" contenteditable="false"> 48 <div id="edit-context-in-noteditable-4"> 49 This is an EditContext child of contenteditable="false" parent. 50 This node should be editable, and this EditContext (but not the 51 grandparent EditContext) should get events, since there is an 52 intermediate non-editable parent. 53 </div> 54 </div> 55 </div> 56 57 <div id="edit-context-top-5"> 58 <div id="contenteditable-in-ec-5" contenteditable=""> 59 This is a contenteditable="" child of EditContext. 60 It inherits editability from the parent and it should not be the target of beforeinput/input events. 61 Setting contenteditable="" on this node is basically a no-op. 62 </div> 63 </div> 64 65 <div id="edit-context-top-6"> 66 <input id="input-in-ec-6" value="Input in EditContext. Events are fired against this element, and not against any parent EditContext."> 67 </div> 68 69 <div id="edit-context-top-7"> 70 <div id="edit-context-in-ec-7"> 71 EditContext child of EditContext. When user types here, 72 events are fired only against the parent EditContext, not this one. 73 Since the parent element was editable, the EditContext association is basically a no-op. 74 </div> 75 </div> 76 77 <script> 78 const event_log = []; 79 80 const editContextElements = document.querySelectorAll("div[id^='edit-context-']"); 81 editContextElements.forEach((element) => { 82 element.editContext = new EditContext(); 83 }); 84 85 const divs = Array.from(document.querySelectorAll("div")); 86 const inputs = Array.from(document.querySelectorAll("input")); 87 const eventTargets = divs.concat(inputs); 88 eventTargets.forEach((element) => { 89 element.addEventListener("beforeinput", (e) => { 90 if (element == e.target) { 91 event_log.push(`beforeinput: ${element.id}`); 92 } 93 }); 94 95 element.addEventListener("input", (e) => { 96 if (element === e.target) { 97 event_log.push(`input: ${element.id}`); 98 } 99 }); 100 101 if (element.editContext) { 102 element.editContext.addEventListener("textupdate", () => { 103 event_log.push(`textupdate: ${element.id}`); 104 }); 105 } 106 }); 107 108 promise_test(async () => { 109 event_log.length = 0; 110 111 const input_target = document.querySelector("#edit-context-top-0"); 112 await test_driver.click(input_target); 113 await test_driver.send_keys(input_target, "a"); 114 assert_array_equals(event_log, ["beforeinput: edit-context-top-0", "textupdate: edit-context-top-0"]); 115 }, 'Check that element with EditContext is editable and gets events'); 116 117 promise_test(async () => { 118 event_log.length = 0; 119 120 const input_target = document.querySelector("#default-1"); 121 await test_driver.click(input_target); 122 await test_driver.send_keys(input_target, "a"); 123 assert_array_equals(event_log, ["beforeinput: edit-context-top-1", "textupdate: edit-context-top-1"]); 124 }, 'Check that child of EditContext is editable and the parent EditContext gets the events'); 125 126 promise_test(async () => { 127 event_log.length = 0; 128 129 const input_target = document.querySelector("#editable-in-noteditable-2"); 130 await test_driver.click(input_target); 131 await test_driver.send_keys(input_target, "a"); 132 assert_array_equals(event_log, ["beforeinput: editable-in-noteditable-2", "input: editable-in-noteditable-2"]); 133 }, 'Check that a contenteditable child of a contenteditable="false" is editable'); 134 135 promise_test(async () => { 136 event_log.length = 0; 137 138 const input_target = document.querySelector("#contenteditable-in-contenteditable-3"); 139 await test_driver.click(input_target); 140 await test_driver.send_keys(input_target, "a"); 141 assert_array_equals(event_log, ["beforeinput: editable-in-noteditable-3", "input: editable-in-noteditable-3"]); 142 }, 'Check that a contenteditable child of a contenteditable is editable, but the parent contenteditable gets the events'); 143 144 promise_test(async () => { 145 event_log.length = 0; 146 147 const input_target = document.querySelector("#edit-context-in-noteditable-4"); 148 await test_driver.click(input_target); 149 await test_driver.send_keys(input_target, "a"); 150 assert_array_equals(event_log, ["beforeinput: edit-context-in-noteditable-4", "textupdate: edit-context-in-noteditable-4"]); 151 }, 'Check that an EditContext child of a contenteditable="false" parent is editable and gets events'); 152 153 promise_test(async () => { 154 event_log.length = 0; 155 156 const input_target = document.querySelector("#contenteditable-in-ec-5"); 157 await test_driver.click(input_target); 158 await test_driver.send_keys(input_target, "a"); 159 assert_array_equals(event_log, ["beforeinput: edit-context-top-5", "textupdate: edit-context-top-5"]); 160 }, 'Check that an contenteditable child of an EditContext is editable, but the EditContext gets the events'); 161 162 promise_test(async () => { 163 event_log.length = 0; 164 165 const input_target = document.querySelector("#input-in-ec-6"); 166 await test_driver.click(input_target); 167 await test_driver.send_keys(input_target, "a"); 168 assert_array_equals(event_log, ["beforeinput: input-in-ec-6", "input: input-in-ec-6"]); 169 }, 'Check that an input element in an EditContext is the event target for beforeinput/input'); 170 171 promise_test(async () => { 172 event_log.length = 0; 173 174 const input_target = document.querySelector("#edit-context-in-ec-7"); 175 await test_driver.click(input_target); 176 await test_driver.send_keys(input_target, "a"); 177 assert_array_equals(event_log, ["beforeinput: edit-context-top-7", "textupdate: edit-context-top-7"]); 178 }, 'Check that for an EditContext child of an EditContext, the parent is the one that gets the events'); 179 180 </script> 181 </body> 182 </html>