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

Representing support of events #7545

Closed
foolip opened this issue Nov 30, 2020 · 36 comments
Closed

Representing support of events #7545

foolip opened this issue Nov 30, 2020 · 36 comments
Labels
data:api 🐇 Compat data for Web APIs. https://developer.mozilla.org/docs/Web/API data:html 📄 Compat data for HTML elements. https://developer.mozilla.org/docs/Web/HTML

Comments

@foolip
Copy link
Collaborator

foolip commented Nov 30, 2020

Understanding and communicating the support of events in implementations is complicated. Taking the "keydown" event an example, there are many different facets of it:

Unfortunately, all four facets can come apart:

  • Events being fired but onfoo IDL attributes being missing (very common)
  • The reverse situation, where onfoo is supported despite "foo" never being fired, also happens.
  • Events being fired, but as Event and not a more specialized FooEvent.
  • The event handler content attributes being missing (relatively rare, but happened historically)

These situations are generally not handled well in BCD, and because only event interface and event handler IDL attribute can be detected with simple feature detection, it's often come up in #6369.

What I believe we need:

  • Guidelines for where foo_event entries should be and what they communicate to data consumers.
  • Guidelines or agreement on how to communicate a mismatch between especially cut_event and oncut entries.
    • Should there be notes on both, and what should they say?
    • Since this has happened so much but is usually fixed after some time, how do we avoid cluttering up the data with notes?

@Elchi3 @ddbeck @sideshowbarker @vinyldarkscratch

@foolip foolip added data:api 🐇 Compat data for Web APIs. https://developer.mozilla.org/docs/Web/API data:html 📄 Compat data for HTML elements. https://developer.mozilla.org/docs/Web/HTML labels Nov 30, 2020
@Elchi3
Copy link
Member

Elchi3 commented Nov 30, 2020

Yay events! 🕺

I refactored the MDN events docs 2 years ago and I'm still familiar with the complicated situation. :)
(see https://docs.google.com/document/d/15F4ttUm7HSPKQNxKqzdiTHGTydDyFyVzyCVABbMHJKg/edit# for MDN thoughts)


To give an overview about MDN/BCD and events, with your example above:

"keydown" is an event type fired on multiple targets and so it appears on a few interfaces, like:

"keydown" is defined by an interface called "KeyBoardEvent":

"onkeydown" is an event handler property and it runs into the "mixin problem", so we have:

"onkeydown" is an event handler content attribute.

  • For HTML, we have https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes but BCD only records data for html.global_attributes. One could image to add html.event_handler_content_attributes. This indicates support throughout all HTML elements. If support is partial or missing for a specific HTML element (we might have run into this for global attributes already), I would suggest to add something to that element. For example, html.element.dialog.onkeydown.
  • For SVG, I don't know. MDN docs are sparse and not as well laid out as HTML.

For your specific scenarios I have some proposals (I might have practiced this already, but surely these aren't enforced guidelines)

Events being fired but onfoo IDL attributes being missing (very common)

api.Document.keydown_event and api.Element.keydown_event marked supported and api.GlobalEventHandlers.onkeydown marked unsupported.

The reverse situation, where onfoo is supported despite "foo" never being fired, also happens.

api.Document.keydown_event and api.Element.keydown_event marked unsupported and api.GlobalEventHandlers.onkeydown marked supported.

Events being fired, but as Event and not a more specialized FooEvent.

api.KeyBoardEvent marked as unsupported? Plus probably api.Document.keydown_event marked as partial support, with a note saying it is of type Event and not KeyBoard event.

The event handler content attributes being missing (relatively rare, but happened historically)

As said above, we may want to have html.event_handler_content_attributes analog to html.global_attributes. If it is only missing on certain elements, then more data could be added at say html.element.dialog.onkeydown.


I agree all this should be written down in extensive guidelines for events in BCD (and even more so for how to document all this on MDN). I think it comes down to agreeing to some of the more fine grained structures that I've outlined above. The events work we did 2 years ago started some of this, but it seems like it wasn't sufficient enough yet (or it is just very complicated and we should expand and add more clarity to events.)

@ddbeck
Copy link
Collaborator

ddbeck commented Nov 30, 2020

In terms of composing the guidelines, it might help to start with some definitions for support on onevent, eventname_event and EventInterface. Very roughly:

  • onevent is supported when "onevent" in target is true
  • eventname_event is supported when the parent feature is a target of the event (that actually fires)
  • EventInterface is supported when the interface is exposed as a global object
  • onevent HTML attribute is suported when mumble something something

Then show some examples of oddities and how to represent them across the 3 or 4 corresponding features.

(I think the definitions correspond to what @Elchi3 is saying above, except the HTML bit, though I might be missing some subtleties.)

@sideshowbarker
Copy link
Collaborator

I’m just leaving a comment for now just to ack this and to say I’m not ignoring it, but it’ll be a while before I can free up some time* to think about it enough to be able to comment usefully.

* Lacking any other clear place to let others on the project know, I’ll just note here that my availability is gonna be a bit limited for while — the reason being that my partner and I just had a new baby girl last week (November 25th), and with two other preschool-age young ones at home already, most of my bandwidth right now is going towards time with the kids :)

@foolip
Copy link
Collaborator Author

foolip commented Dec 2, 2020

Writing up guidelines for what the different types of entries are sounds great, and apart from the foo_event entries does not involve a whole lot of judgement calls, I think.

The main problem and the real reason I filed this issue is at the very end of my writeup:

Guidelines or agreement on how to communicate a mismatch between especially cut_event and oncut entries.

Carefully documenting the support for each will not, I think, lead to something that's good enough. Let's take https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition#Browser_compatibility as an example, a case where both kinds of entries exist for most of the events. (Ignore the prefix mess, fixed in #7554.)

As a reader, seeing "end event" and "onend" with the same support versions is conveying the same information twice: there's an "end" event that I can use. This is the normal case, which everything will be trending towards as the mismatches are discovered and fixed.

So what I wonder is whether we should move towards MDN conveying support for an event as a unified entry, with the details being hidden away unless there's something interesting going on. And what representation in BCD would help make that possible?

@Elchi3
Copy link
Member

Elchi3 commented Dec 2, 2020

As a reader, seeing "end event" and "onend" with the same support versions is conveying the same information twice: there's an "end" event that I can use. This is the normal case, which everything will be trending towards as the mismatches are discovered and fixed.

Nowadays, this is probably normal, but historically MDN had documentation for both, events and event handlers, as it happened that there was only one and not the other. It still happens, I don't know how often though.

We updated the docs, so that both, event and handler, live together in the same reference page tree and now there is a bit of duplication indeed. (the writing guidelines say that event pages need to have a code example using addEventListener and the event handler pages should, well, use the even handler notation). I'd say this is an editorial policy that we could discuss in an MDN issue (sprints repo). Maybe there are better ways to document events in a more unified way with less pages?

So what I wonder is whether we should move towards MDN conveying support for an event as a unified entry, with the details being hidden away unless there's something interesting going on. And what representation in BCD would help make that possible?

Possibly. Usually BCD follows MDN structures, so either we get a discussion going how to document events in a unified way on MDN, or we first outline something for BCD that then informs MDN structures? Either way it seems like we should split out this issue and involve MDN.

@foolip
Copy link
Collaborator Author

foolip commented Dec 3, 2020

Sounds good. What's the right place to raise editorial issues for MDN?

@Elchi3
Copy link
Member

Elchi3 commented Dec 3, 2020

I talked to Chris and for now it is https://github.com/mdn/sprints/
(it might become https://github.com/mdn/content, discussion ongoing).

@ddbeck
Copy link
Collaborator

ddbeck commented Dec 4, 2020

Every now and then something comes up that makes me think we ought to have a way of producing "synthetic" features that group together hierarchically dispersed features (e.g., onsomeevent, someevent_event, SomeEvent(), or some collection of related CSS properties or whatever).

@foolip
Copy link
Collaborator Author

foolip commented Dec 8, 2020

@ddbeck that sounds like it might help with the events situation. Pairing reflected IDL attributes with their content attributes would also be sensible. Beyond that, are you thinking something as large as "flexbox" as one grouped feature? Would this end up with a feature hierarchy for the whole platform?

@ddbeck
Copy link
Collaborator

ddbeck commented Dec 10, 2020

Would this end up with a feature hierarchy for the whole platform?

Yeah, this is the question that discourages me from putting effort into this. I don't want to have to maintain many hierarchies—it just seems like I ought to be able to query our data across our boundaries. Though maybe spec_urls could help with this sort of thing.

@foolip
Copy link
Collaborator Author

foolip commented Jun 11, 2021

I think this issue is going to block #8929. The issue is that when demixing GlobalEventHandlers and WindowEventHandlers, we would add onfoo properties to lots of interfaces, exacerbating the problem described.

GlobalEventHandlers is mixed into 5 interfaces: Document, Window, HTMLElement, MathMLElement and SVGElement

WindowEventHandlers is mixed into 4 interfaces: Window, HTMLBodyElement, HTMLFrameSetElement and SVGSVGElement. Possibly a MathML interfaces could be added here in the future.

Whether 4 or 5 interfaces, the outcome would be totally unreasonable IMHO. Example:

The "volumechange" event is fired in a single place. Because the event doesn't bubble, the only onvolumechange property that's useful is the one on HTMLElement, for instances of HTMLMediaElement. What web developers need to know (or did 10 years ago when this was new) is whether and when this event will be fired, and whether they can use mediaElement.onvolumechange = callback in addition to mediaElement.addEventListener('volumechange', callback).

What we'd get in BCD if just demixing this is the existing api.HTMLMediaElement.volumechange_event entry, and then 5 onvolumechange entries in different places. (There's also svg.attributes.events.global.onvolumechange which I think should be removed.)

Sorting this out would take a huge effort also involving mdn/content, so I'll file a sibling issue there.

@foolip
Copy link
Collaborator Author

foolip commented Jun 11, 2021

Created https://github.com/mdn/content/discussions/5898 to stir up trouble over in mdn/content.

@ddbeck
Copy link
Collaborator

ddbeck commented Jun 11, 2021

I was noodling on this problem earlier and got to thinking what if I didn't have to respect any of the existing structures, what might I end up with? I was toying with the idea of supposing that events are sort of special and seeing if I could consolidate the interesting characteristics of events. I ended up here before calling it quits:

api
└── Event

events
└── volumechange_event
    ├── fires_interface_Event
    └── targets_HTMLMediaElement
        └── onvolumechange // IDL attribute for HTMLMediaElement

html
└── elements
    ├── audio
    │   └── onvolumechange  // content attribute
    └── video
        └── onvolumechange

As you can see, I still don't know what to do with content attributes. But I think this might be a nice way to make sure only record data for the genuinely interesting event targets and interfaces (and we could, if we wanted, automatically duplicate the onevent handler data to the API tree). It would also put a lot more of the data in one place, for the convenience of BCD contributors.

@foolip
Copy link
Collaborator Author

foolip commented Jun 11, 2021

@ddbeck something like that which links together the interesting things about each distinct event sounds promising.

Some care would be needed to define what a distinct event is, since there are many events using the same type string, "error" being the most overloaded I believe. We would probably run into tricky cases where the separateness or sameness of two events is a judgement call or has changed over time.

But that's the kind of editorial judgement I think is needed for the result to make sense, just presenting all the information is not good enough IMHO.

@foolip
Copy link
Collaborator Author

foolip commented Jun 11, 2021

On another note, the support of onfoo attributes is going to be full of partial support and moves along the prototype chain and so on, so I think that data has to be recorded faithfully and can't be automatically duplicated. But it also needs to be summarized into something simpler I think.

@foolip
Copy link
Collaborator Author

foolip commented Jun 12, 2021

We would probably run into tricky cases where the separateness or sameness of two events is a judgement call or has changed over time.

Well, it didn't take long before running into such a tricky judgement case. #10837 (comment) describes the "storage" event in IE8 vs. IE9 and later browsers. The event target, event interface and its properties are different, but the event type ("storage") and cause (a storage area was updated) are the same. Here the question wasn't if this is 1 or 2 events, but I expect we'll run into cases like this in abundance if we try to really get the event data right.

@ddbeck
Copy link
Collaborator

ddbeck commented Jun 16, 2021

@foolip following up from our discussion earlier, do you have some examples of events I could use to test out actually writing some JSON to the above proposal? A small number of straightforward, messy, and typical events would probably be pretty revealing, as an actual demonstration of the idea.

@foolip
Copy link
Collaborator Author

foolip commented Jun 18, 2021

Let's take some examples from simple to complicated.

Simple non-bubbling events

The "toggle" event fired at a <details> element is an example of the simplest kind of event, one that uses the Event interface and does not bubble. Example:

<details>
  <summary>toggle me</summary>
  stuff stuff stuff
</details>
<script>
var details = document.querySelector('details');
details.addEventListener('toggle', console.log);
</script>

This event has ontoggle in GlobalEventHandlers which means details.ontoggle works (inherited from HTMLElement).

One can also use a capturing event listener to listen for it on an ancestor of <details>, e.g., document.body.addEventListener('toggle', console.log, /* capture */ true).

In BCD, these events usually have foo_event and onfoo property entries, and sometimes also onfoo content attribute entries.

Simple bubbling events

Like above but they bubble. The "input" event is an example of this. The interesting difference is that the event handler can be anywhere without being capturing, notably like this:

<input type=checkbox>check me
<script>
window.addEventListener('input', console.log);
</script>

Events with their own interfaces

There are lots of these, for example the "message" event triggered by postMessage uses MessageEvent. Example:

self.addEventListener('message', function(event) {
  console.assert(event instanceof MessageEvent);
});
self.postMessage('', '*');

In BCD, these additionally have entries for the event interface, api.MessageEvent in this case. Common sources of messiness:

  • The event was originally a simple event and later got its own interface, e.g., SubmitEvent came long after the "submit" event
  • The event interface might have been supported, but not exposed
  • The event constructors were added after the interface objects were exposed (but also, event constructors are mostly useless)

Prefixes

Both event types and event interfaces can be prefixed, and the onfoo properties can be infixed. Examples of each are "webkitfullscreenchange", WebKitAnimationEvent and onwebkitfullscreenchange.


That's about it.

@foolip
Copy link
Collaborator Author

foolip commented Aug 10, 2021

I have just stumbled upon another quirky thing with events in BCD. It turns out there are 3 "animationend_event" entries, one in Document.json , one in HTMLElement.json and one in Window.json. This is presumably because the event bubbles and it's possible to listen for it on both document and window, but this still seems incredibly unhelpful. It's also duplicated on MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Document/animationend_event
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event
https://developer.mozilla.org/en-US/docs/Web/API/Window/animationend_event

However we end up dealing with the onanimationend properties, I hope we can merge all of these.

@Elchi3
Copy link
Member

Elchi3 commented Sep 3, 2021

I don't have the bandwidth to fix this issue in Q3 still. If it is brought up again for Q4 and voted as important enough, I'm happy to help solving this then, though.

@foolip
Copy link
Collaborator Author

foolip commented Sep 3, 2021

Thanks @Elchi3, good to know! (Preparing my votes and sock puppets now...)

@Elchi3
Copy link
Member

Elchi3 commented Apr 25, 2022

I have just stumbled upon another quirky thing with events in BCD. It turns out there are 3 "animationend_event" entries, one in Document.json , one in HTMLElement.json and one in Window.json. This is presumably because the event bubbles and it's possible to listen for it on both document and window, but this still seems incredibly unhelpful. It's also duplicated on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Document/animationend_event https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event https://developer.mozilla.org/en-US/docs/Web/API/Window/animationend_event

However we end up dealing with the onanimationend properties, I hope we can merge all of these.

Now that we worked through almost all events, the only structure that hasn't been updated is GlobalEventHandlers and there we can observe the problem you described.

Instead of all the following MDN pages and BCD entries (that would be correct per the IDL)...

https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onanimationend
https://developer.mozilla.org/en-US/docs/Web/API/Document/animationend_event
https://developer.mozilla.org/en-US/docs/Web/API/Window/animationend_event
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event
(https://developer.mozilla.org/en-US/docs/Web/API/SVGElement/animationend_event)
(https://developer.mozilla.org/en-US/docs/Web/API/MathMLElement/animationend_event)

... we should agree on merging this to a single place, but where should that be? Window? Or use the GlobalEventHandlers namespace?

@teoli2003
Copy link
Contributor

Suppose we put it on Window. How can we know which events that are on Window also apply to Document, HTMLElement, SVGElement, …, and which don't?

@Elchi3
Copy link
Member

Elchi3 commented Apr 25, 2022

I think I'm leaning towards creating single pages (and BCD entries) under GlobalEventHandlers like so:

https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/animationend_event
api.GlobalEventHandlers.animantionend_event

Such MDN page could then list where the event is available per IDL (Window, Document, HTMLElement, SVGElement, MathMLElement) and the BCD can use partial support if exposure to some interface is wrong or missing.

Happy to hear other thoughts.

@queengooborg
Copy link
Collaborator

As big of a mixin as GlobalEventHandlers is, I still feel that we should at least separate the BCD entries. It feels a little odd to make the decision to demix all of the mixins, but skip over one or two. On an additional note, it's harder for tooling like the mdn-bcd-collector to update a mixin as we would have to add special logic to formulate partial support entries (which would be a significant amount of work for just one mixin).

@saschanaz
Copy link
Contributor

(If it requires a change in bcd collector, then it's absolutely a logical breaking change, please consider major version up.)

@Elchi3
Copy link
Member

Elchi3 commented Apr 26, 2022

I made a content draft PR for an example event that is defined on GlobalEventHandlers.: mdn/content#15376

Feedback please :)

@Rumyra
Copy link
Collaborator

Rumyra commented Apr 26, 2022

I think the draft looks good @Elchi3 - I also think for content keeping GlobalEventHandlers/one namespace makes sense - otherwise maintenance of duplicates would be cumbersome.

@Elchi3
Copy link
Member

Elchi3 commented Apr 26, 2022

I played this through for two selection events for further illustration.

mdn/content#15385
#16029

partial interface mixin GlobalEventHandlers {
  attribute EventHandler onselectstart;
  attribute EventHandler onselectionchange;
};

For selectionchange, the compat data is not the same across all specific interfaces. I created a sub feature but I'm happy to change that to partial support instead or do something else. Let me know.

@queengooborg
Copy link
Collaborator

(If it requires a change in bcd collector, then it's absolutely a logical breaking change, please consider major version up.)

Well actually, this wouldn't break anything that isn't already broken in the collector. Currently, since the collector de-mixes all mixins, the add-new-bcd script keeps wanting to add the entries to the individual interfaces. I've just been manually discarding those changes, but I could very well be discarding other entries in the process. I've not put any work into remapping GlobalEventHandlers entries to api.GlobalEventHandlers on the collector and have been performing this workaround because it would be a significant amount of work for a format I had been expecting to change in the near future.

I just don't feel like keeping api.GlobalEventHandlers is the right call. (And if we're adding notes or subfeatures to indicate a difference in support across the various interfaces (ex. api.GlobalEventHandlers.<event>_event.supported_on_<interface>), then even moreso.) As a BCD consumer, I really would want to know one thing: is the feature on a particular interface supported in my browser? I wouldn't care much about the history of its implementation on mixins, and depending on my expertise, I may not even know what a mixin is in the first place (which is a big reason why we made our avoid-adding-mixins guideline).

@Elchi3
Copy link
Member

Elchi3 commented Apr 28, 2022

Currently, since the collector de-mixes all mixins, the add-new-bcd script keeps wanting to add the entries to the individual interfaces.

For illustration, can you post how many entries this would add? My assumption is that it not practical to add so many entries, but looking at it might help me and others to think more about it.

@queengooborg
Copy link
Collaborator

I ran the add-new-bcd script from the collector, then used the diff script introduced in #7486 to determine what is added. I filtered for events added specifically to the affected interfaces (Document, Element, HTMLBodyElement, HTMLElement, HTMLFrameSetElement, MathMLElement, SVGElement, and Window), and found that we'd be adding around 480 entries. It's a lot of new entries, yes, but it's also much more machine-readable too.

@Elchi3
Copy link
Member

Elchi3 commented May 3, 2022

Thanks for your research!
Curios to hear what other people think. I think it is quite a lot to add, but I will not block it.
However, I won't create 480 MDN pages for these events, so there we definitely need some other solution. It would be very impractical for the reader if we had that many event pages.

@foolip
Copy link
Collaborator Author

foolip commented May 18, 2022

I don't think we should always add *_event entries when an on* property is supported on an interface. Often these properties aren't on the interface that is the event target, and sometimes these event handler properties are where no even can be fired at all.

The "contextlost" event is a good example of this. The event target can be either a HTMLCanvasElement or an OffscreenCanvas object. The event doesn't bubble, so window.oncontextlost and document.oncontextlost are both useless. The HTMLElement.prototype.oncontextlost is what makes canvasElement.oncontextlost work, but it's less specific than it should be.

In this case, we should have api.HTMLCanvasElement.contextlost_event and api.OffscreenCanvas.contextlost_event, which probably have different support data. And the various oncontextlost properties are only weak clues about what the correct support data is.

foolip added a commit to foolip/browser-compat-data that referenced this issue May 19, 2022
foolip added a commit to foolip/browser-compat-data that referenced this issue May 19, 2022
foolip added a commit to foolip/browser-compat-data that referenced this issue May 19, 2022
foolip added a commit to foolip/browser-compat-data that referenced this issue May 23, 2022
foolip added a commit to foolip/browser-compat-data that referenced this issue May 23, 2022
foolip added a commit to foolip/browser-compat-data that referenced this issue Jul 7, 2022
foolip added a commit to foolip/browser-compat-data that referenced this issue Jul 7, 2022
queengooborg added a commit that referenced this issue Jul 12, 2022
* Adapt selectstart/selectionchange events to new event structure

Part of #7545.

* Update Node.selectstart_event

Co-authored-by: Queen Vinyl Da.i'gyu-Kazotetsu <[email protected]>
@queengooborg
Copy link
Collaborator

I think that we've come to a solid conclusion on how to represent event support in BCD. Can we close this issue?

@foolip
Copy link
Collaborator Author

foolip commented Sep 15, 2023

Yes, I'm very happy with the outcome in BCD, closing now. 👍

@foolip foolip closed this as completed Sep 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
data:api 🐇 Compat data for Web APIs. https://developer.mozilla.org/docs/Web/API data:html 📄 Compat data for HTML elements. https://developer.mozilla.org/docs/Web/HTML
Projects
None yet
Development

No branches or pull requests

8 participants