slotchange.html (7608B)
1 <!DOCTYPE html> 2 <title>Shadow DOM: slotchange Events</title> 3 <meta name="author" title="Hayato Ito" href="mailto:hayato@google.com"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="resources/shadow-dom.js"></script> 7 8 <div id="test1"> 9 <div id="host1"> 10 <template data-mode="open"> 11 <slot id="s1" name="slot1"></slot> 12 </template> 13 <div id="c1" slot="slot1"></div> 14 </div> 15 </div> 16 17 <script> 18 function arraysEqual(a, b) { 19 if (a === b) return true; 20 if (a == null || b == null) return false; 21 if (a.length !== b.length) return false; 22 for (var i = 0; i < a.length; ++i) { 23 if (a[i] !== b[i]) return false; 24 } 25 return true; 26 } 27 function doneIfSlotChange(slots, expectedAssignedNodes, test) { 28 let matched = Array(slots.length).fill(false); 29 for (let i=0; i<slots.length; i++) { 30 slots[i].addEventListener('slotchange', test.step_func((e) => { 31 matched[i] = arraysEqual(slots[i].assignedNodes(), expectedAssignedNodes[i]); 32 if (matched.every(v => v)) { 33 test.done(); 34 } 35 })) 36 } 37 } 38 39 async_test((test) => { 40 let n = createTestTree(test1); 41 removeWhiteSpaceOnlyTextNodes(n.test1); 42 43 let d1 = document.createElement('div'); 44 d1.setAttribute('slot', 'slot1'); 45 46 doneIfSlotChange([n.s1], [[n.c1, d1]], test); 47 48 n.host1.appendChild(d1); 49 }, 'slotchange event: Append a child to a host.'); 50 51 async_test((test) => { 52 let n = createTestTree(test1); 53 removeWhiteSpaceOnlyTextNodes(n.test1); 54 55 doneIfSlotChange([n.s1], [[]], test); 56 57 n.c1.remove(); 58 }, 'slotchange event: Remove a child from a host.'); 59 60 async_test((test) => { 61 let n = createTestTree(test1); 62 removeWhiteSpaceOnlyTextNodes(n.test1); 63 64 n.c1.remove(); 65 66 doneIfSlotChange([n.s1], [[]], test); 67 }, 'slotchange event: Remove a child before adding an event listener.'); 68 69 async_test((test) => { 70 let n = createTestTree(test1); 71 removeWhiteSpaceOnlyTextNodes(n.test1); 72 73 doneIfSlotChange([n.s1], [[]], test); 74 75 n.c1.setAttribute('slot', 'slot-none'); 76 }, 'slotchange event: Change slot= attribute to make it un-assigned.'); 77 78 async_test((test) => { 79 let n = createTestTree(test1); 80 removeWhiteSpaceOnlyTextNodes(n.test1); 81 82 doneIfSlotChange([n.s1], [[]], test); 83 84 n.s1.setAttribute('name', 'slot-none'); 85 }, 'slotchange event: Change slot\'s name= attribute so that none is assigned.'); 86 </script> 87 88 <div id="test2"> 89 <div id="host1"> 90 <template data-mode="open"> 91 <slot id="s1" name="slot1"></slot> 92 </template> 93 <div id="c2" slot="slot2"></div> 94 </div> 95 </div> 96 97 <script> 98 async_test((test) => { 99 let n = createTestTree(test2); 100 removeWhiteSpaceOnlyTextNodes(n.test2); 101 102 doneIfSlotChange([n.s1], [[n.c2]], test); 103 104 n.c2.setAttribute('slot', 'slot1'); 105 }, 'slotchange event: Change slot= attribute to make it assigned.'); 106 107 async_test((test) => { 108 let n = createTestTree(test2); 109 removeWhiteSpaceOnlyTextNodes(n.test2); 110 111 doneIfSlotChange([n.s1], [[n.c2]], test); 112 113 n.s1.setAttribute('name', 'slot2'); 114 }, 'slotchange event: Change slot\'s name= attribute so that a node is assigned to the slot.'); 115 </script> 116 117 <div id="test_fallback"> 118 <div id="host1"> 119 <template data-mode="open"> 120 <slot id="s1"></slot> 121 </template> 122 </div> 123 </div> 124 125 <script> 126 async_test((test) => { 127 let n = createTestTree(test_fallback); 128 removeWhiteSpaceOnlyTextNodes(n.test_fallback); 129 130 doneIfSlotChange([n.s1], [[]], test); 131 132 n.s1.appendChild(document.createElement('div')); 133 }, 'slotchange event: Change fallback content - assignedNodes still empty.'); 134 </script> 135 136 <div id="test_fallback2"> 137 <div id="host1"> 138 <template data-mode="open"> 139 <slot id="s1"> 140 <div id="f1"></div> 141 </slot> 142 </template> 143 </div> 144 </div> 145 146 <script> 147 async_test((test) => { 148 let n = createTestTree(test_fallback2); 149 removeWhiteSpaceOnlyTextNodes(n.test_fallback2); 150 151 doneIfSlotChange([n.s1], [[]], test); 152 153 n.f1.remove(); 154 }, 'slotchange event: Remove a fallback content - assignedNodes still empty.'); 155 </script> 156 157 <div id="test_fallback3"> 158 <div id="host1"> 159 <template data-mode="open"> 160 <slot id="s2"> 161 <slot id="s1"> 162 <div id="f1"></div> 163 </slot> 164 </slot> 165 </template> 166 </div> 167 </div> 168 169 <script> 170 async_test((test) => { 171 let n = createTestTree(test_fallback3); 172 removeWhiteSpaceOnlyTextNodes(n.test_fallback3); 173 174 doneIfSlotChange([n.s1, n.s2], [[],[]], test); 175 176 n.s1.appendChild(document.createElement('div')); 177 }, 'slotchange event: Add a fallback content to nested slots - assignedNodes still empty.'); 178 179 async_test((test) => { 180 let n = createTestTree(test_fallback3); 181 removeWhiteSpaceOnlyTextNodes(n.test_fallback3); 182 183 doneIfSlotChange([n.s1, n.s2], [[],[]], test); 184 185 n.f1.remove(); 186 }, 'slotchange event: Remove a fallback content from nested slots - assignedNodes still empty.'); 187 </script> 188 189 <div id="test3"> 190 <div id="host1"> 191 <template id="shadowroot" data-mode="open"> 192 <slot id="s1" name="slot1"></slot> 193 </template> 194 <div id="c1" slot="slot1"></div> 195 </div> 196 </div> 197 198 <script> 199 async_test((test) => { 200 let n = createTestTree(test3); 201 removeWhiteSpaceOnlyTextNodes(n.test3); 202 203 doneIfSlotChange([n.s1], [[]], test); 204 205 let slot = document.createElement('slot'); 206 slot.setAttribute('name', 'slot1'); 207 n.shadowroot.insertBefore(slot, n.s1); 208 }, "slotchange event: Insert a slot before an existing slot."); 209 </script> 210 211 <div id="test4"> 212 <div id="host1"> 213 <template id="shadowroot" data-mode="open"> 214 <slot id="s1" name="slot1"></slot> 215 <slot id="s2" name="slot1"></slot> 216 </template> 217 <div id="c1" slot="slot1"></div> 218 </div> 219 </div> 220 221 <script> 222 async_test((test) => { 223 let n = createTestTree(test4); 224 removeWhiteSpaceOnlyTextNodes(n.test4); 225 226 doneIfSlotChange([n.s2], [[n.c1]], test); 227 228 n.s1.remove(); 229 }, "slotchange event: Remove a preceding slot."); 230 </script> 231 232 <div id="test5"> 233 <div id="host1"> 234 <template data-mode="open"> 235 <div id="host2"> 236 <template data-mode="open"> 237 <slot id="s2" name="slot2"></slot> 238 </template> 239 <slot id="s1" name="slot1" slot="slot2"></slot> 240 </div> 241 </template> 242 <div id="c1" slot="slot1"></div> 243 </div> 244 </div> 245 246 <script> 247 async_test((test) => { 248 let n = createTestTree(test5); 249 removeWhiteSpaceOnlyTextNodes(n.test5); 250 251 doneIfSlotChange([n.s1, n.s2], [[],[n.s1]], test); 252 253 n.c1.remove(); 254 }, "slotchange event: A slot is assigned to another slot."); 255 </script> 256 257 <div id="test6"> 258 <div id="host1"> 259 <template data-mode="open"> 260 <div id="host2"> 261 <template data-mode="open"> 262 <slot id="s2" name="slot2"></slot> 263 </template> 264 <slot id="s1" name="slot1" slot="slot2"></slot> 265 </div> 266 </template> 267 </div> 268 </div> 269 270 <script> 271 async_test((test) => { 272 let n = createTestTree(test6); 273 removeWhiteSpaceOnlyTextNodes(n.test6); 274 275 doneIfSlotChange([n.s2], [[]], test); 276 277 n.s1.remove(); 278 }, "slotchange event: Slotchange should be fired if assigned nodes are changed."); 279 </script> 280 281 <div id="test7"> 282 <div id="host1"> 283 <template data-mode="open"> 284 <div id="host2"> 285 <template data-mode="open"> 286 <slot id="s2" name="slot2"></slot> 287 </template> 288 <slot id="s1" name="slot1" slot="slot2"></slot> 289 </div> 290 </template> 291 </div> 292 </div> 293 294 <script> 295 async_test((test) => { 296 let n = createTestTree(test7); 297 removeWhiteSpaceOnlyTextNodes(n.test7); 298 299 let d1 = document.createElement('div'); 300 d1.setAttribute('slot', 'slot1'); 301 doneIfSlotChange([n.s1, n.s2], [[d1],[n.s1]], test); 302 303 n.host1.appendChild(d1); 304 }, "slotchange event: Child content is added to nested slots."); 305 </script>