コミュニティアチーブメントバーを展開する。

Submissions are now open for the 2026 Adobe Experience Maker Awards
解決済み

"click" vs "mouseup" in an event listener (custom activity map implementation)

Avatar

Level 4

Hi, we have shadow DOM elements (#shadow-root (open) ) on the site and I have observed that the "click" event type doesn't work in the listener (using plain javaScript). However, substituting it with a "mouseup" event produces the relevant outcome. Namely, I am talking about our custom activity map implementation. Has anyone come across this before? Thanks.

1 受け入れられたソリューション

Avatar

正解者
Community Advisor

Hi @Franc_G 

You’re definitely not alone in running into this. Shadow DOM introduces some quirks when it comes to event handling, and the click event is one of the trickier ones because of how event retargeting and encapsulation work.

If mouseup is working and click isn’t, it likely comes down to how the Shadow DOM manages event bubbling. click doesn't always bubble through the shadow boundary the way you'd expect, whereas moueup tends to behave more reliably in that regard, especially with custom listeners or tracking layers like Activity Map.

You can do the following -

  • If you control the component, make sure any custom events are fired with composed: true and bubbles: true so they can cross the shadow boundary.

  • If you're just listening from outside and can't modify the component, then sticking with mouseup is a perfectly valid workaround and quite common in shadow-heavy apps.

  • Also worth checking if the component has a click handler that’s stopping propagation. That would explain why your external listener never fires on click, but mouseup sneaks through.

Your current fix using mouseup is solid, and unless you can tweak the component’s internals, it might be the best route.


Hope it works!

元の投稿で解決策を見る

7 返信

Avatar

Community Advisor

Hey @Franc_G 

and your event listener is custom and not a built-in click event?
Could it be that the click is not bubbling and captured by the element itself i .e., in the component's custom click handler?

That could explain why the mouseup still works if the event propagation is working there.

I would reach out to a developer about that and ask him if they explicitly stop event bubbling / propagation

Cheers from Switzerland!


Avatar

Community Advisor

Hi @Franc_G ,

 

Yes, this is a known behavior. When working with Shadow DOM elements, the "click" event often doesn’t work as expected in external event listeners due to event retargeting and the encapsulation that Shadow DOM enforces. In many cases, "mouseup" propagates more reliably across shadow boundaries, which is why you might see it working better especially in custom implementations like Activity Map.

 

 

Some recommendations: 

 

Use mouseup for Shadow DOM elements:

If it works and suits your tracking goals, it's a valid and simple workaround.

 

 

Use composed: true in event listeners (for custom events)
If you control the Shadow DOM components, ensure events are dispatched with:
 
new CustomEvent('your-event', {
bubbles: true,
composed: true // allows event to cross shadow boundary
});

 

Delegate Listener inside Shadow DOM

If you have access to the shadow root:

shadowRoot.querySelector('button').addEventListener('click', function(e) {
// track click
});

 

Patch Activity Map
If you’re using a custom Activity Map, you may consider replacing click with mouseup for better reliability on sites using shadow DOM.
 
Hope this helps you.
 
Thanks.
Pradnya

Avatar

正解者
Community Advisor

Hi @Franc_G 

You’re definitely not alone in running into this. Shadow DOM introduces some quirks when it comes to event handling, and the click event is one of the trickier ones because of how event retargeting and encapsulation work.

If mouseup is working and click isn’t, it likely comes down to how the Shadow DOM manages event bubbling. click doesn't always bubble through the shadow boundary the way you'd expect, whereas moueup tends to behave more reliably in that regard, especially with custom listeners or tracking layers like Activity Map.

You can do the following -

  • If you control the component, make sure any custom events are fired with composed: true and bubbles: true so they can cross the shadow boundary.

  • If you're just listening from outside and can't modify the component, then sticking with mouseup is a perfectly valid workaround and quite common in shadow-heavy apps.

  • Also worth checking if the component has a click handler that’s stopping propagation. That would explain why your external listener never fires on click, but mouseup sneaks through.

Your current fix using mouseup is solid, and unless you can tweak the component’s internals, it might be the best route.


Hope it works!

Avatar

Level 4

@bjoern__koth @pradnya_balvir @Vinay_Chauhan 

Thank you for the suggestions—exactly what I needed! I was, and still am, a bit hesitant to change the event type from "click" to "mouseup" in the custom activity map, but you’ve given me all the information I need. Much appreciated.

 

Additionally, I’ve discovered an easy way to test whether this issue is related to event bubbling (see below).

 

By tweaking the options parameter in the listener, we can quickly determine whether the event type bubbles or not.

  • If true, the event listener is triggered during the capturing phase of event propagation.
  • If false, the event listener is triggered during the bubbling phase (default).

Event propagation in JavaScript consists of three phases:

  1. Capturing Phase: The event travels from the root element of the DOM down to the target element.
  2. Target Phase: The event reaches the target element itself.
  3. Bubbling Phase: The event bubbles back up from the target element to the root element.

By default, most event listeners in JavaScript respond during the bubbling phase, but you can also configure them to respond during the capturing phase.

 

document.addEventListener('click', function () {
    console.log('Capturing phase');
}, true); // Capturing phase

document.addEventListener('click', function () {
    console.log('Bubbling phase');
}, false); // Bubbling phase (default)

 

Upon multiple interactions with the shadow DOM element I get the following log. 

 

Franc_G_0-1753175948910.png

Franc_G_0-1753177591978.png

 

 

Avatar

Level 4

@bjoern__koth @pradnya_balvir @Vinay_Chauhan 

Does anyone have an opinion on which one is better?

document.addEventListener('click', function () {
    console.log('Capturing phase');
}, true); // Capturing phase

 

OR

document.addEventListener('mouseup', function () {
    console.log('Capturing phase');
}); // "mouseup" event type;

 

I know it’s pretty much the same thing, but nevertheless, I’m talking specifically about the activity map custom implementation.

Avatar

Community Advisor and Adobe Champion

I am not sure what is the safest, however, you might want to also run a test using mobile devices? Like test with a real android and iOS (or multiple) devices to ensure the listener works for them too....

 

I feel like click might work better on mobile devices.. but that's a guess.....

 

Or you might have to create separate listeners for mobile devices that look for the touchend (equivalent to mouseup) or touchstart (equivalent to mousedown) events... since there is definitely no "mouse" events on a phone or tablet (well.... in most cases... I'm sure there is some person out there with a mouse on their tablet....)

Avatar

Level 4

@Jennifer_Dungan it is a good point, thank you. I did some testing in the console using mobile type devices provided (iPhone and android), but will try to experiment with an actual mobile phone. Thanks once again.