Skip to content

Reference Target: How to handle events fired on the reference target by related elements? #1098

@alice

Description

@alice

This was raised by @jakearchibald in whatwg/html#10707 (comment):

An interesting case here:

<button popovertarget="component-a"></button>
<component-a id="component-a">
  <template shadowrootmode="closed" shadowrootreferencetarget="inner-thing">
    <div id="inner-thing" popover></div>
  </template>
</component-a>

As the owner of the button, is it weird that I don't get a toggle event on component-a, despite the popover being successfully opened?

and whatwg/html#11148 (comment):

Because the problem is referenceTarget specific, a solution tailored to referenceTarget seems ok. As in, the command event (and other related events like popover toggle) can flow through retargeted boundaries.

<component-a>
  <template shadowrootmode="closed">
    <button command="--foo" commandFor="component-b"></button>
    <component-b id="component-b">
      <template shadowrootmode="closed" shadowrootreferencetarget="inner-thing">
        <div id="inner-thing"></div>
      </template>
    </component-b>
  </template>
</component-a>

In the example above, the command would be seen within component-b's shadow root, since that's where the ultimate target is, but it would also be seen in component-a's shadow root, since it was retargeted from there.

We'd need to consider cases where retargeting was between multiple shadow roots.

[We should] work on the referenceTarget-specific issues as part of that feature work. I don't think we should solve this just for command, nor should we end up having to default to composed events everywhere due to referenceTarget.


My proposal (see also #1098 (comment)):

  • Certain events get a source, which already exists on CommandEvent. We would also need to add it to:
    • SubmitEvent, which already has submitter for the same thing, so submitter could be used as an alias
    • ToggleEvent
    • The definition of the event concept, so that it can be used in algorithms, analogous to how relatedTarget is.
  • Set source to the element which causes an event to fire on another element before firing the event; some locations for where this needs to happen are listed below.
  • Modify shadow root's get the parent algorithm to:
    1. let target be event’s path’s first struct’s invocation target;
    2. if event’s composed flag is set, return shadow root’s host;
    3. if shadow root is not the root of target, and event does not have a source or shadow root is not the root of event's source, return shadow root's host;
    4. if event has a source, and event's source's root is a shadow-including ancestor of shadow root, return the result of retargeting target against event's triggering element;
    5. otherwise, return null.

Some places we'd need to modify event initialisation:


Draft PRs:
whatwg/dom#1377
whatwg/html#11349

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions