Skip to content
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

Allow custom activation behavior to be added to an event #1320

Open
jakearchibald opened this issue Oct 31, 2024 · 5 comments
Open

Allow custom activation behavior to be added to an event #1320

jakearchibald opened this issue Oct 31, 2024 · 5 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: events

Comments

@jakearchibald
Copy link
Collaborator

jakearchibald commented Oct 31, 2024

What problem are you trying to solve?

const button = document.querySelector('button');

button.addEventListener('click', (event) => {
  // …
});

I want to add activation behavior to the above button, such as "when this button is clicked, toggle this checkbox". As expected on the platform, I don't want this action to happen if a listener calls event.preventDefault().

What solutions exist today?

const button = document.querySelector('button');

button.addEventListener('click', (event) => {
  if (event.defaultPrevented) return;
  checkCustomCheckbox();
});

This isn't great because the default may be prevented by a listener further along the path.

const button = document.querySelector('button');

button.addEventListener('click', (event) => {
  setTimeout(() => {
    if (event.defaultPrevented) return;
    checkCustomCheckbox();
  }, 0);  
});

This isn't great because the effect may happen a frame later (rAF isn't a reliable solution here due to whatwg/html#10113). It's also observably async:

button.click();
console.log(customCheckboxChecked); // expected true, but got false

Other techniques, like adding listeners to window may be missed due to stopPropagation(), and may still be 'beaten' by another listener.

How would you solve it?

Something like:

const button = document.querySelector('button');

button.addEventListener('click', (event) => {
  event.addActivationBehavior(() => {
    checkCustomCheckbox();
  });
});

Anything else?

No response

@jakearchibald jakearchibald added needs implementer interest Moving the issue forward requires implementers to express interest addition/proposal New features or enhancements labels Oct 31, 2024
@annevk
Copy link
Member

annevk commented Nov 4, 2024

In the specification activation behavior is associated with the event target, not the event. And it's very much tied to click events as well.

(This reminds me a bit of the "event group" concept in https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Event-groups.)

cc @smaug---- @rniwa

@smaug----
Copy link
Collaborator

Gecko has a variant of "event group", so called system event group, and listeners in that are called after the normal DOM event dispatch. (And it was also exposed to XBL)
But I wouldn't add anything like that to the web, too complicated.

EventTargets could perhaps have some callback for activation behavior, and that could either override the native activation behavior, or other option is to control that using .preventDefault() if the callback gets the event as param. Certain cases like nesting inside an anchor element might complicate things - which all activation behaviors should be triggered?

@jakearchibald
Copy link
Collaborator Author

EventTargets could perhaps have some callback for activation behavior, and that could either override the native activation behavior

Yeah, I like that idea.

or other option is to control that using .preventDefault() if the callback gets the event as param

I don't think that works, because you want the activation behaviour to not-run if the default is prevented.

@Krinkle
Copy link
Member

Krinkle commented Nov 5, 2024

For input fields and forms, we have "change" and "submit" events as happening after processing a lower level event like click, keydown, keyup, Enter, drag-and-drop, clipboard paste, etc.

What if anchor elements emitted an event like "navigate" or "activate" which wouldn't be cancellable, to happen when performing the action, regardless of how it was triggered and whether it was cancelled?

  • This would have the benefit of allowing you to listen declaratively (instead of attaching it just-in-time).
  • Naturally sharing and reusing the function in memory.
  • Allows for delegation, to listen from a parent or ancestor element for this event across a wider range of elements, without needing to select and attach on each one.
  • Simpler API for beginners, by using the event model people know instead of having to know about this specific method.

@jakearchibald
Copy link
Collaborator Author

For input fields and forms, we have "change" and "submit"

"submit" is another problem event here, as it can be cancelled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: events
Development

No branches or pull requests

4 participants