Click events are duplicated for form-associated custom elements placed inside of a label element
Categories
(Core :: DOM: Core & HTML, defect)
Tracking
()
People
(Reporter: cob.bzmoz, Assigned: edgar)
References
(Depends on 1 open bug, Blocks 1 open bug, Regression, )
Details
(Keywords: nightly-community, regression)
Attachments
(2 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Steps to reproduce:
- Define a custom element that is form-associated (
static formAssociated = true
). - Have the custom element's constructor create a shadow root and, inside of that, an unnamed
slot
element. Have the custom element's constructor add a "click" event listener to the custom element. The listener should console.log all incoming events. - In your HTML markup, place an instance of that element inside of a LABEL element.
- Place a visible and clickable element inside of the custom element, e.g. a DIV or an SVG.
- Click on the inner (slotted) element.
- Use JavaScript to dispatch a "click" event to the custom element. Here, I am referring to constructing a new
MouseEvent
with "click" as its argument, and then callingdispatchEvent
. - Use JavaScript to dispatch a "click" event to the custom element's shadow root or any descendant thereof.
The attached HTML file can be used to perform steps 1 through 5.
Version affected is Firefox stable, 112.0.2 (64-bit). My current user-agent string is "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0".
Actual results:
The actual result of steps 1 - 5 is that the event is duplicated. The original event lists the slotted element as its target, and bubbles outward from the slotted element to the containing custom element and beyond. If this event's default action is not prevented, then Firefox creates a new click event listing the custom element as its target and the slotted element as its explicitOriginalTarget
. This event bubbles outward from the custom element to the rest of the document. A "click" listener set on the custom element will therefore catch both events.
Continuing onward, the actual result of step 6 is that two "click" events are fired, both listing the form-associated custom element as their target.
Continuing onward, the actual result of step 7 is that two "click" events are fired, both listing the form-associated custom element as their target. The first event lists the intended target as its originalTarget
, but the explicitOriginalTarget
is still the whole custom element.
Bizarrely, in all cases of event duplication, the duplicate event has a timeStamp
around 15 to 50 milliseconds after the original event.
These issues only occur if the custom element is form-associated and if it is wrapped in a LABEL element. Form-associated custom elements produce the expected results if they are not in a LABEL. Custom elements inside of a label produce the expected results if they are not form-associated.
Expected results:
The expected result of steps 1 - 5 is that Firefox should only have fired a single click event, with the slotted element as its target, and this event should have bubbled outward to the entire document.
The expected result of step 6 is that Firefox should only have fired a single click event, with the custom element as its target.
The expected result of step 7 is that Firefox should only have fired a single click event, with the intended target (i.e. shadow root or descendant) as its target.
This behavior causes major problems for custom elements used to implement checkbox form controls and other toggleable/clickable form controls, as responding to both of a pair of duplicated click events would break the checkbox (e.g. clicking it toggles it twice, producing no change).
If a form-associated custom element is placed inside of a label, the only way to avoid reacting twice to every click is: if event.target
is the custom element, then you must ignore the click event if either of explicitOriginalTarget
and originalTarget
are non-null and not equal to the custom element. This will allow you to ignore the second fired event in each duplicated pair. However, as these are non-standard properties, and it's not possible to know with 100% certainty which event (the first or the second) is the incorrectly-fired event, this workaround is not future-proof. (What if y'all decide that the first event is the fake one? What if y'all change the behavior of these non-standard properties? MDN doesn't even offer a clear description of the logic by which they get their values.)
Comment 2•2 years ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::DOM: Core & HTML' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Updated•2 years ago
|
I also encountered this bug. Example to reproduce:
<html>
<body>
<label>Label<my-checkbox></my-checkbox></label>
<script>
class MyCheckbox extends HTMLElement {
static formAssociated=true;
constructor() {
super();
this.addEventListener('click', e=>console.log('click',e));
var shadow=this.attachShadow({mode: 'open'});
shadow.innerHTML='<div>shadow CLICK ME</div>';
}
}
customElements.define('my-checkbox', MyCheckbox);
</script>
</body>
</html>
Comment 7•1 year ago
|
||
Regression window:
https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=6ed00b7f71c2a534bd8c824c6c54442b202efb15&tochange=b64579fab76b572919af61bcaf45350572f91b92
The former build: When shadow CLICK ME
is clicked, one event is fired. But when Label
is clicked, no event is fired.
The latter build: When shadow CLICK ME
is clicked, two events are fired. But when Label
is clicked, one event is fired.
So, this seems to be implementation bug of Bug 1556373.
Expected results:
Clicking on shadow CLICK ME
or Label
should both fire only one event, like Chrome.
Comment 8•1 year ago
|
||
:edgar, since you are the author of the regressor, bug 1556373, could you take a look?
For more information, please visit BugBot documentation.
Assignee | ||
Comment 9•1 year ago
|
||
This could also happens to elements that are in the labeled element category but are not considered interactive content, such as the output
element, e.g. https://codepen.io/edgarchen-the-decoder/pen/yLQGORG. There is a spec discussion for this, https://github.com/whatwg/html/issues/5415. I feel Chrome/Safari behavior make more sense.
Assignee | ||
Comment 10•1 year ago
|
||
Comment 11•1 year ago
|
||
Set release status flags based on info from the regressing bug 1556373
Updated•1 year ago
|
Updated•1 year ago
|
Assignee | ||
Comment 12•1 year ago
|
||
Let's wait for bug 1851970 which is going to use EventTarget::ActivationBehavior
for label element.
Description
•