events-on-pseudo-element.tentative.html (11804B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>CSS Test: event.pseudoTarget tests with different events </title> 4 <link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-marker-pseudo"> 5 <link rel="help" href="https://drafts.csswg.org/css-pseudo/#CSSPseudoElement-interface"> 6 <script src="/dom/events/scrolling/scroll_support.js"></script> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="/resources/testdriver.js"></script> 10 <script src="/resources/testdriver-actions.js"></script> 11 <script src="/resources/testdriver-vendor.js"></script> 12 <style> 13 @keyframes slide-in { 14 from { 15 transform: translateX(100%) scaleX(3); 16 } 17 18 to { 19 transform: translateX(0) scaleX(1); 20 } 21 } 22 23 div { 24 scroll-marker-group: after; 25 overflow: scroll; 26 height: 200px; 27 28 li { 29 height: 200px; 30 background: purple; 31 border: 1px solid black; 32 33 &::scroll-marker { 34 content: "S"; 35 padding: 10px; 36 color: white; 37 background: red; 38 transition-property: transform, background; 39 transition-duration: 2s; 40 transition-delay: 1s; 41 animation-duration: 2s; 42 animation-name: slide-in; 43 } 44 45 &::scroll-marker:hover { 46 background: blue; 47 transform: rotate(90deg); 48 } 49 } 50 } 51 </style> 52 <div> 53 <li id="target">1</li> 54 </div> 55 <script> 56 const target = document.getElementById("target"); 57 58 let animationstartTarget = null; 59 let animationstartPseudoTarget = null; 60 let animationendTarget = null; 61 let animationendPseudoTarget = null; 62 let clickTarget = null; 63 let clickPseudoTarget = null; 64 let dblclickTarget = null; 65 let dblclickPseudoTarget = null; 66 let mouseoverTarget = null; 67 let mouseoverPseudoTarget = null; 68 let mouseoutTarget = null; 69 let mouseoutPseudoTarget = null; 70 let mouseenterTarget = null; 71 let mouseenterPseudoTarget = null; 72 let mouseleaveTarget = null; 73 let mouseleavePseudoTarget = null; 74 let pointeroverTarget = null; 75 let pointeroverPseudoTarget = null; 76 let pointeroutTarget = null; 77 let pointeroutPseudoTarget = null; 78 let pointerenterTarget = null; 79 let pointerenterPseudoTarget = null; 80 let pointerleaveTarget = null; 81 let pointerleavePseudoTarget = null; 82 let wheelTarget = null; 83 let wheelPseudoTarget = null; 84 let scrollTarget = null; 85 let scrollPseudoTarget = null; 86 let focusinTarget = null; 87 let focusinPseudoTarget = null; 88 let focusoutTarget = null; 89 let focusoutPseudoTarget = null; 90 let keydownTarget = null; 91 let keydownPseudoTarget = null; 92 let keyupTarget = null; 93 let keyupPseudoTarget = null; 94 let transitionstartTarget = null; 95 let transitionstartPseudoTarget = null; 96 let transitionendTarget = null; 97 let transitionendPseudoTarget = null; 98 99 function waitForEvent(element, eventName) { 100 return new Promise(resolve => { 101 element.addEventListener(eventName, resolve, { once: true }); 102 }); 103 } 104 105 target.addEventListener("animationstart", (e) => { 106 animationstartTarget = e.target; 107 animationstartPseudoTarget = e.pseudoTarget; 108 }); 109 110 target.addEventListener("animationend", (e) => { 111 animationendTarget = e.target; 112 animationendPseudoTarget = e.pseudoTarget; 113 }); 114 115 target.addEventListener("click", (e) => { 116 clickTarget = e.target; 117 clickPseudoTarget = e.pseudoTarget; 118 }); 119 120 target.addEventListener("dblclick", (e) => { 121 dblclickTarget = e.target; 122 dblclickPseudoTarget = e.pseudoTarget; 123 }); 124 125 target.addEventListener("mouseover", (e) => { 126 mouseoverTarget = e.target; 127 mouseoverPseudoTarget = e.pseudoTarget; 128 }); 129 target.addEventListener("mouseout", (e) => { 130 mouseoutTarget = e.target; 131 mouseoutPseudoTarget = e.pseudoTarget; 132 }); 133 target.addEventListener("mouseenter", (e) => { 134 mouseenterTarget = e.target; 135 mouseenterPseudoTarget = e.pseudoTarget; 136 }); 137 target.addEventListener("mouseleave", (e) => { 138 mouseleaveTarget = e.target; 139 mouseleavePseudoTarget = e.pseudoTarget; 140 }); 141 target.addEventListener("pointerover", (e) => { 142 pointeroverTarget = e.target; 143 pointeroverPseudoTarget = e.pseudoTarget; 144 }); 145 target.addEventListener("pointerout", (e) => { 146 pointeroutTarget = e.target; 147 pointeroutPseudoTarget = e.pseudoTarget; 148 }); 149 target.addEventListener("pointerenter", (e) => { 150 pointerenterTarget = e.target; 151 pointerenterPseudoTarget = e.pseudoTarget; 152 }); 153 target.addEventListener("pointerleave", (e) => { 154 pointerleaveTarget = e.target; 155 pointerleavePseudoTarget = e.pseudoTarget; 156 }); 157 158 target.addEventListener("focusin", (e) => { 159 focusinTarget = e.target; 160 focusinPseudoTarget = e.pseudoTarget; 161 }); 162 163 target.addEventListener("focusout", (e) => { 164 focusoutTarget = e.target; 165 focusoutPseudoTarget = e.pseudoTarget; 166 }); 167 168 target.addEventListener("keydown", (e) => { 169 keydownTarget = e.target; 170 keydownPseudoTarget = e.pseudoTarget; 171 }); 172 173 target.addEventListener("keyup", (e) => { 174 keyupTarget = e.target; 175 keyupPseudoTarget = e.pseudoTarget; 176 }); 177 178 target.addEventListener("transitionstart", (e) => { 179 transitionstartTarget = e.target; 180 transitionstartPseudoTarget = e.pseudoTarget; 181 }); 182 183 target.addEventListener("transitionend", (e) => { 184 transitionendTarget = e.target; 185 transitionendPseudoTarget = e.pseudoTarget; 186 }); 187 188 target.addEventListener('wheel', (e) => { 189 wheelTarget = e.target; 190 wheelPseudoTarget = e.pseudoTarget; 191 }); 192 target.addEventListener('scroll', (e) => { 193 scrollTarget = e.target; 194 scrollPseudoTarget = e.pseudoTarget; 195 }); 196 197 const kTab = "\uE004"; 198 const kEnter = "\uE007"; 199 const scrollMarkerX = 20; 200 const scrollMarkerY = 220; 201 const pseudoElement = target.pseudo("::scroll-marker"); 202 203 const animationStartPromise = waitForEvent(target, "animationstart"); 204 205 promise_test(async t => { 206 await animationStartPromise; 207 assert_equals(animationstartTarget, target, "event.target is ultimate originating element for animationstart"); 208 assert_equals(animationstartPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for animationstart"); 209 210 await waitForEvent(target, "animationend"); 211 assert_equals(animationendTarget, target, "event.target is ultimate originating element for animationend"); 212 assert_equals(animationendPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for animationend"); 213 214 const transitionStartPromise = waitForEvent(target, "transitionstart"); 215 await new test_driver.Actions() 216 .pointerMove(scrollMarkerX, scrollMarkerY) 217 .pointerDown() 218 .pointerUp() 219 .pointerDown() 220 .pointerUp() 221 .send(); 222 await transitionStartPromise; 223 224 assert_equals(clickTarget, target, "event.target is ultimate originating element for click"); 225 assert_equals(clickPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for click"); 226 227 assert_equals(dblclickTarget, target, "event.target is ultimate originating element for double click"); 228 assert_equals(dblclickPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for double click"); 229 230 assert_equals(mouseoverTarget, target, "event.target is ultimate originating element for mouseover"); 231 // `mouseover` is a boundary event; currently `pseudoTarget` is not 232 // defined for boundary events, so it should be null. 233 assert_equals(mouseoverPseudoTarget, null, "event.pseudoTarget is null for mouseover (boundary event)"); 234 235 await new test_driver.Actions() 236 .keyDown(kTab) 237 .keyUp(kTab) 238 .keyDown(kEnter) 239 .keyUp(kEnter) 240 .send(); 241 242 assert_equals(focusinTarget, target, "event.target is ultimate originating element for focusin"); 243 assert_equals(focusinPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for focusin"); 244 245 assert_equals(focusoutTarget, target, "event.target is ultimate originating element for focusout"); 246 assert_equals(focusoutPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for focusout"); 247 248 assert_equals(keydownTarget, target, "event.target is ultimate originating element for keydown"); 249 assert_equals(keydownPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for keydown"); 250 251 assert_equals(keyupTarget, target, "event.target is ultimate originating element for keyup"); 252 assert_equals(keyupPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for keyup"); 253 254 assert_equals(transitionstartTarget, target, "event.target is ultimate originating element for transitionstart"); 255 assert_equals(transitionstartPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for transitionstart"); 256 257 await waitForEvent(target, "transitionend"); 258 assert_equals(transitionendTarget, target, "event.target is ultimate originating element for transitionend"); 259 assert_equals(transitionendPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for transitionend"); 260 261 // Move pointer away to trigger boundary events (mouseout / pointerout / leave) 262 const mouseOutPromise = waitForEvent(target, 'mouseout'); 263 const pointerOutPromise = waitForEvent(target, 'pointerout'); 264 const mouseLeavePromise = waitForEvent(target, 'mouseleave'); 265 const pointerLeavePromise = waitForEvent(target, 'pointerleave'); 266 await new test_driver.Actions() 267 .pointerMove(0, 0) 268 .send(); 269 await Promise.all([mouseOutPromise, pointerOutPromise, mouseLeavePromise, pointerLeavePromise]); 270 271 // Boundary events should not have pseudoTarget set. 272 assert_equals(mouseoutTarget, target, "event.target is ultimate originating element for mouseout"); 273 assert_equals(mouseoutPseudoTarget, null, "event.pseudoTarget is null for mouseout (boundary event)"); 274 assert_equals(pointeroutTarget, target, "event.target is ultimate originating element for pointerout"); 275 assert_equals(pointeroutPseudoTarget, null, "event.pseudoTarget is null for pointerout (boundary event)"); 276 assert_equals(mouseleaveTarget, target, "event.target is ultimate originating element for mouseleave"); 277 assert_equals(mouseleavePseudoTarget, null, "event.pseudoTarget is null for mouseleave (boundary event)"); 278 assert_equals(pointerleaveTarget, target, "event.target is ultimate originating element for pointerleave"); 279 assert_equals(pointerleavePseudoTarget, null, "event.pseudoTarget is null for pointerleave (boundary event)"); 280 281 // Move pointer back in to trigger enter events; they should also be null 282 const mouseEnterPromise = waitForEvent(target, 'mouseenter'); 283 const pointerEnterPromise = waitForEvent(target, 'pointerenter'); 284 await new test_driver.Actions() 285 .pointerMove(scrollMarkerX, scrollMarkerY) 286 .send(); 287 await Promise.all([mouseEnterPromise, pointerEnterPromise]); 288 assert_equals(mouseenterTarget, target, "event.target is ultimate originating element for mouseenter"); 289 assert_equals(mouseenterPseudoTarget, null, "event.pseudoTarget is null for mouseenter (boundary event)"); 290 assert_equals(pointerenterTarget, target, "event.target is ultimate originating element for pointerenter"); 291 assert_equals(pointerenterPseudoTarget, null, "event.pseudoTarget is null for pointerenter (boundary event)"); 292 293 // Dispatch some unrelated events and ensure pseudoTarget is null. 294 target.dispatchEvent(new WheelEvent('wheel')); 295 assert_equals(wheelTarget, target, 'wheel event target should be the element'); 296 assert_equals(wheelPseudoTarget, null, 'wheel event pseudoTarget should be null'); 297 298 target.dispatchEvent(new Event('scroll')); 299 assert_equals(scrollTarget, target, 'scroll event target should be the element'); 300 assert_equals(scrollPseudoTarget, undefined, 'scroll event pseudoTarget should be null'); 301 }); 302 </script>