Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Test: event.pseudoTarget tests with different events </title>
<script src="/dom/events/scrolling/scroll_support.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<style>
@keyframes slide-in {
from {
transform: translateX(100%) scaleX(3);
}
to {
transform: translateX(0) scaleX(1);
}
}
div {
scroll-marker-group: after;
overflow: scroll;
height: 200px;
li {
height: 200px;
background: purple;
border: 1px solid black;
&::scroll-marker {
content: "S";
padding: 10px;
color: white;
background: red;
transition-property: transform, background;
transition-duration: 2s;
transition-delay: 1s;
animation-duration: 2s;
animation-name: slide-in;
}
&::scroll-marker:hover {
background: blue;
transform: rotate(90deg);
}
}
}
</style>
<div>
<li id="target">1</li>
</div>
<script>
const target = document.getElementById("target");
let animationstartTarget = null;
let animationstartPseudoTarget = null;
let animationendTarget = null;
let animationendPseudoTarget = null;
let clickTarget = null;
let clickPseudoTarget = null;
let dblclickTarget = null;
let dblclickPseudoTarget = null;
let mouseoverTarget = null;
let mouseoverPseudoTarget = null;
let mouseoutTarget = null;
let mouseoutPseudoTarget = null;
let mouseenterTarget = null;
let mouseenterPseudoTarget = null;
let mouseleaveTarget = null;
let mouseleavePseudoTarget = null;
let pointeroverTarget = null;
let pointeroverPseudoTarget = null;
let pointeroutTarget = null;
let pointeroutPseudoTarget = null;
let pointerenterTarget = null;
let pointerenterPseudoTarget = null;
let pointerleaveTarget = null;
let pointerleavePseudoTarget = null;
let wheelTarget = null;
let wheelPseudoTarget = null;
let scrollTarget = null;
let scrollPseudoTarget = null;
let focusinTarget = null;
let focusinPseudoTarget = null;
let focusoutTarget = null;
let focusoutPseudoTarget = null;
let keydownTarget = null;
let keydownPseudoTarget = null;
let keyupTarget = null;
let keyupPseudoTarget = null;
let transitionstartTarget = null;
let transitionstartPseudoTarget = null;
let transitionendTarget = null;
let transitionendPseudoTarget = null;
function waitForEvent(element, eventName) {
return new Promise(resolve => {
element.addEventListener(eventName, resolve, { once: true });
});
}
target.addEventListener("animationstart", (e) => {
animationstartTarget = e.target;
animationstartPseudoTarget = e.pseudoTarget;
});
target.addEventListener("animationend", (e) => {
animationendTarget = e.target;
animationendPseudoTarget = e.pseudoTarget;
});
target.addEventListener("click", (e) => {
clickTarget = e.target;
clickPseudoTarget = e.pseudoTarget;
});
target.addEventListener("dblclick", (e) => {
dblclickTarget = e.target;
dblclickPseudoTarget = e.pseudoTarget;
});
target.addEventListener("mouseover", (e) => {
mouseoverTarget = e.target;
mouseoverPseudoTarget = e.pseudoTarget;
});
target.addEventListener("mouseout", (e) => {
mouseoutTarget = e.target;
mouseoutPseudoTarget = e.pseudoTarget;
});
target.addEventListener("mouseenter", (e) => {
mouseenterTarget = e.target;
mouseenterPseudoTarget = e.pseudoTarget;
});
target.addEventListener("mouseleave", (e) => {
mouseleaveTarget = e.target;
mouseleavePseudoTarget = e.pseudoTarget;
});
target.addEventListener("pointerover", (e) => {
pointeroverTarget = e.target;
pointeroverPseudoTarget = e.pseudoTarget;
});
target.addEventListener("pointerout", (e) => {
pointeroutTarget = e.target;
pointeroutPseudoTarget = e.pseudoTarget;
});
target.addEventListener("pointerenter", (e) => {
pointerenterTarget = e.target;
pointerenterPseudoTarget = e.pseudoTarget;
});
target.addEventListener("pointerleave", (e) => {
pointerleaveTarget = e.target;
pointerleavePseudoTarget = e.pseudoTarget;
});
target.addEventListener("focusin", (e) => {
focusinTarget = e.target;
focusinPseudoTarget = e.pseudoTarget;
});
target.addEventListener("focusout", (e) => {
focusoutTarget = e.target;
focusoutPseudoTarget = e.pseudoTarget;
});
target.addEventListener("keydown", (e) => {
keydownTarget = e.target;
keydownPseudoTarget = e.pseudoTarget;
});
target.addEventListener("keyup", (e) => {
keyupTarget = e.target;
keyupPseudoTarget = e.pseudoTarget;
});
target.addEventListener("transitionstart", (e) => {
transitionstartTarget = e.target;
transitionstartPseudoTarget = e.pseudoTarget;
});
target.addEventListener("transitionend", (e) => {
transitionendTarget = e.target;
transitionendPseudoTarget = e.pseudoTarget;
});
target.addEventListener('wheel', (e) => {
wheelTarget = e.target;
wheelPseudoTarget = e.pseudoTarget;
});
target.addEventListener('scroll', (e) => {
scrollTarget = e.target;
scrollPseudoTarget = e.pseudoTarget;
});
const kTab = "\uE004";
const kEnter = "\uE007";
const scrollMarkerX = 20;
const scrollMarkerY = 220;
const pseudoElement = target.pseudo("::scroll-marker");
const animationStartPromise = waitForEvent(target, "animationstart");
promise_test(async t => {
await animationStartPromise;
assert_equals(animationstartTarget, target, "event.target is ultimate originating element for animationstart");
assert_equals(animationstartPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for animationstart");
await waitForEvent(target, "animationend");
assert_equals(animationendTarget, target, "event.target is ultimate originating element for animationend");
assert_equals(animationendPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for animationend");
const transitionStartPromise = waitForEvent(target, "transitionstart");
await new test_driver.Actions()
.pointerMove(scrollMarkerX, scrollMarkerY)
.pointerDown()
.pointerUp()
.pointerDown()
.pointerUp()
.send();
await transitionStartPromise;
assert_equals(clickTarget, target, "event.target is ultimate originating element for click");
assert_equals(clickPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for click");
assert_equals(dblclickTarget, target, "event.target is ultimate originating element for double click");
assert_equals(dblclickPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for double click");
assert_equals(mouseoverTarget, target, "event.target is ultimate originating element for mouseover");
// `mouseover` is a boundary event; currently `pseudoTarget` is not
// defined for boundary events, so it should be null.
assert_equals(mouseoverPseudoTarget, null, "event.pseudoTarget is null for mouseover (boundary event)");
await new test_driver.Actions()
.keyDown(kTab)
.keyUp(kTab)
.keyDown(kEnter)
.keyUp(kEnter)
.send();
assert_equals(focusinTarget, target, "event.target is ultimate originating element for focusin");
assert_equals(focusinPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for focusin");
assert_equals(focusoutTarget, target, "event.target is ultimate originating element for focusout");
assert_equals(focusoutPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for focusout");
assert_equals(keydownTarget, target, "event.target is ultimate originating element for keydown");
assert_equals(keydownPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for keydown");
assert_equals(keyupTarget, target, "event.target is ultimate originating element for keyup");
assert_equals(keyupPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for keyup");
assert_equals(transitionstartTarget, target, "event.target is ultimate originating element for transitionstart");
assert_equals(transitionstartPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for transitionstart");
await waitForEvent(target, "transitionend");
assert_equals(transitionendTarget, target, "event.target is ultimate originating element for transitionend");
assert_equals(transitionendPseudoTarget, pseudoElement, "event.pseudoTarget is ::scroll-marker for transitionend");
// Move pointer away to trigger boundary events (mouseout / pointerout / leave)
const mouseOutPromise = waitForEvent(target, 'mouseout');
const pointerOutPromise = waitForEvent(target, 'pointerout');
const mouseLeavePromise = waitForEvent(target, 'mouseleave');
const pointerLeavePromise = waitForEvent(target, 'pointerleave');
await new test_driver.Actions()
.pointerMove(0, 0)
.send();
await Promise.all([mouseOutPromise, pointerOutPromise, mouseLeavePromise, pointerLeavePromise]);
// Boundary events should not have pseudoTarget set.
assert_equals(mouseoutTarget, target, "event.target is ultimate originating element for mouseout");
assert_equals(mouseoutPseudoTarget, null, "event.pseudoTarget is null for mouseout (boundary event)");
assert_equals(pointeroutTarget, target, "event.target is ultimate originating element for pointerout");
assert_equals(pointeroutPseudoTarget, null, "event.pseudoTarget is null for pointerout (boundary event)");
assert_equals(mouseleaveTarget, target, "event.target is ultimate originating element for mouseleave");
assert_equals(mouseleavePseudoTarget, null, "event.pseudoTarget is null for mouseleave (boundary event)");
assert_equals(pointerleaveTarget, target, "event.target is ultimate originating element for pointerleave");
assert_equals(pointerleavePseudoTarget, null, "event.pseudoTarget is null for pointerleave (boundary event)");
// Move pointer back in to trigger enter events; they should also be null
const mouseEnterPromise = waitForEvent(target, 'mouseenter');
const pointerEnterPromise = waitForEvent(target, 'pointerenter');
await new test_driver.Actions()
.pointerMove(scrollMarkerX, scrollMarkerY)
.send();
await Promise.all([mouseEnterPromise, pointerEnterPromise]);
assert_equals(mouseenterTarget, target, "event.target is ultimate originating element for mouseenter");
assert_equals(mouseenterPseudoTarget, null, "event.pseudoTarget is null for mouseenter (boundary event)");
assert_equals(pointerenterTarget, target, "event.target is ultimate originating element for pointerenter");
assert_equals(pointerenterPseudoTarget, null, "event.pseudoTarget is null for pointerenter (boundary event)");
// Dispatch some unrelated events and ensure pseudoTarget is null.
target.dispatchEvent(new WheelEvent('wheel'));
assert_equals(wheelTarget, target, 'wheel event target should be the element');
assert_equals(wheelPseudoTarget, null, 'wheel event pseudoTarget should be null');
target.dispatchEvent(new Event('scroll'));
assert_equals(scrollTarget, target, 'scroll event target should be the element');
assert_equals(scrollPseudoTarget, undefined, 'scroll event pseudoTarget should be null');
});
</script>