[whatwg/dom] Allow for filtering events in "once" handlers (#990)

Currently when listening for events one may wish to filter events for certain criterion.

This is doable today by :

```js
someElement.addEventListener("keypress", (event) => {
    if (event.key !== "Escape") { // Only escape key presses
        return;
    }
    // Process the event
});
```

However the problem with explicit checks is it doesn't compose whatsoever with the `once` option that can be passed to `.addEventListener`.

e.g. Consider the following example with `AbortController`:

```js
const abortController = new AbortController();
const { signal: abortSignal } = abortController;

abortSignal.addEventListener("abort", (event) => {
    if (!event.isTrusted) { 
        // Not a real abort, we can't trust this to update our internal state or whatever
        return;
    }
    console.log(".abort() was called"); // This never happens
}, { once: true });

abortSignal.dispatchEvent(new Event("abort"));

abortController.abort(); // Nothing happens
```

Now it's possible to work around this by essentially reimplementing "once", but this seems rather redundant when the "once" option already exists.

As such I'd like to suggest that a way to filter events be added, such that failure in the filter does not prevent a "once" handler from running.

As some examples of where this would be useful:
- Ignoring fake events (i.e. ones without `.isTrusted`) for robustness in library code where users may be using synthetic events for triggering their own listeners
- Capturing an event the first time something happens, e.g. the first time the cursor is some distance from some initial point 
- Ignoring events of certain kinds when multiple different kinds come under the same event type, e.g. capturing the next time the escape key is pressed (rather than any other key)

I'm not sure exactly what the API shape would be, but I imagine passing a filter function in the options bag:

```js
someElement.addEventListener("keypress", (event) => {
    hideTheModal();
}, {
    once: true,
    eventFilter: (event) => event.key === "Escape",
});
```

It's kinda redundant if you're not using `once: true` (as you can just do `if (!condition) return`), in principle it could just replace the `once` e.g. `once: (event) => event.key === "Escape"`, but it also seems kinda weird to overload the option (although also maybe not). 

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/990

Received on Saturday, 12 June 2021 08:06:01 UTC