WICG / close-watcher

A web API proposal for watching for close requests (e.g. Esc, Android back button, ...)
https://html.spec.whatwg.org/multipage/interaction.html#close-requests-and-close-watchers
71 stars 5 forks source link

Why not just an event? #10

Closed othermaciej closed 2 years ago

othermaciej commented 2 years ago

Why does this API involve instantiating an object and assigning callback functions to it, instead of an event dispatched to window and/or to the currently keyboard focused element? I'm not saying it has to be that, perhaps there is a good reason, but there's no "alternatives considered" section to explain it.

domenic commented 2 years ago

Fair question, sorry for not explaining!

The big thing is we need a signal for when the browser should direct such events to their normal processing, versus to the application. This is most easily seen in the case of the Android back button. (Maybe it might also apply to VoiceOver gestures or PlayStation square buttons?) Example 3 at https://wicg.github.io/close-watcher/#close-signal-steps explains that case.

Similarly, for cases where close signals can fall back to an important default action (like going back in the history list), we need a time to intervene and say "no, application, you cannot capture close signals at this time; you might be using them to trap the user". The constructor provides that opportunity in a nice way. I guess you could still get that just by not firing the global event in such abuse scenarios (I.e., not firing the global event twice in a row without an intervening user activation.) But right now we have the property that once you can construct a CloseWatcher, you are guaranteed it will get a close event if a close signal happens, which seems kinda nice.

A less fundamental benefit is for developer ergonomics. By having essentially one event per close watcher, we get a kind of stack for free. For example, if various modal dialog components (including the <dialog> element itself) use the close watcher infrastructure, then we can be sure to always route the event to the "topmost" (i.e., most-recently-created) modal dialog. If we had just one global event, then such components would need to coordinate with each other to ensure that only the topmost acts on the event, and the others ignore it.

I'll definitely spend time updating the explainer to discuss this, although I'm curious to hear if you have any reactions first...

othermaciej commented 2 years ago

It seems like the key point here is that, on some platforms, an active CloseWatcher would prevent system handling of the close signal (e.g. back button on Android; perhaps that's the only currently known case). This was not especially clear in the Explainer and would be worth an update.

This seems to be the aspect that requires a user action, scoping of listening, etc, because listening for (and preventing default action of) the Escape key is not a dangerous action.

I wonder if it would be possible to make the registration of the event listener the privileged action? Fails to register if there are not sufficient user actions (in situations where it's relevant).

domenic commented 2 years ago

I think we've tried to avoid making registering an event listener have any side effects, or be fallible. Service workers are an exception, but people (e.g. @annevk) are pretty unhappy with that. Combined with the developer ergonomics benefits, I think that argues for keeping the current two-stage approach of constructor + event listener registration.

annevk commented 2 years ago

Yeah, see https://dom.spec.whatwg.org/#observing-event-listeners. (That text could probably do more to admit that implementations will optimize the lack of event listeners, but I think the main point stands nonetheless.)