-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: getLeafTarget() method #624
Comments
Particularly in case of [deeply] nested shadows, e.g. to intercept I wonder if this is something that should be solved in the web platform? I mean maybe they didn't do it initially because custom elements were expected to be simple and self-contained, but now they are used as freely as standard elements and contain complex layouts, which makes event delegation desirable to reduce the amount of listeners. |
Independently of extensions, by design shadow DOM comes in two flavors, closed and open shadow DOM. If the shadow root was created with Closed shadow DOM is supposed to represent a self-contained piece of DOM structure. In reality, web pages can of course use it for anything and embed complicated DOM trees. What are the use cases of wanting to reach deep into closed shadow DOM? |
Most are already served by Use case 1If an extension implements shortcut keys using keyboard events, it's best practice to not trigger when the event target is an input element, textarea, etc. That way if the user is trying to type, the extension's shortcut won't be triggered. Using window.addEventListener("keyup", e => {
const target = browser.dom.getLeafEvent(e.target)
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") return
if (e.code === "Space") {
activateShortcut()
e.stopPropagation().
e.preventDefault()
}
}, {capture: true}) Use case 2I wanted to show an overlay to interactively change the video's brightness.
Use case 3Translating text while hovering over it. If the text is inside a closed shadow DOM, you won't be able to detect the text target unless you recursively add listeners to all shadow DOMs (as @tophf mentioned, this approach is complicated and can have memory implications). In addition, if event propagation was stopped, there will be no way for the extension to access the text target. |
I think this is a weird question in the context of extensions. The answer is the same as why you build extensions (and content scripts specifically): to extract, manipulate, extend content. The page should be fully accessible to extensions regardless of the encapsulation web page authors used — unless it's protected in the name of security. I don’t think that's the case here. |
We would need to confirm with the web platform team how best to expose this, but in general we support solving this use case. |
@xeenon expressed being supportive for this capability in the meeting. @oliverdunk will follow up with Chrome. |
Status as of TPAC 2024 (#659) is still for Oliver to follow up with Chrome to see the preferred approach. |
Context
Normally, when an event is fired,
event.target
returns the element on which the event occurred. However, when the event originates inside a Shadow DOM,event.target
only provides the first shadow host element, not the actual element inside the Shadow DOM where the event originated.Current Workarounds and Their Limitations
To access the true event target, you can add event listeners directly to the Shadow DOMs. However, this approach has two significant drawbacks:
stopPropagation()
.Proposal
I propose a
getLeafTarget(event: Event): Element
function to solve this problem. It takes an event as an argument and returns the actual, or leaf, target of the event. With this function, a single event listener attached to the window object can replace the need for hundreds of event listeners attached to individual Shadow DOMs.Example Use Case
Translate any button's text on mouse hover. Using
getLeafTarget
allows the extension to work on websites that use Shadow DOMs. To replicate this functionality withoutgetLeafTarget
will require much, much, more work.The text was updated successfully, but these errors were encountered: