I’ve recently been trying to track down a bug related to permalinks in Slide-Drive. They usually work fine, jumping to the right point in the presentation as soon as the document is loaded. However, it would occasionally jump right back to the beginning after jumping to the correct time. Removing MediaElementPlayer fixed the bug, but I haven’t been able to narrow it down any further and have difficulty even reproducing it reliably.

My current goal is to have a working demo, not an entirely polished product, so after fighting with this for a while I decided to just try to find a workaround. I could see that a timeupdate event was being fired each time the audio would jump back. Inspecting the event, I noticed that its .cancelable property was true.

Great! I’ll just add a handler to cancel any timeupdate events that try to move to time 0 within a short time of the page loading. It’s ugly, but it should serve well enough for my demo, right?

Wrong. I tried this but it had no effect. My handler would run and call .cancelDefault(), but nothing would happen. I threw in .stopPropagation() and return false; on the chance that it would help, but to no avail.

Frustrated, I consulted the specification for HTML5 media elements and events. Most of the events it specified, including timeupdate, were described as “simple events”. It described a “simple event” as an event… (emphasis mine)

…which does not bubble (except where otherwise stated) and is not cancelable (except where otherwise stated), and which uses the Event interface

As it happens, it is not otherwise stated that timeupdate should be cancelable, so it should not be. Upon reflection, this is reasonable: cancelling a direct navigation to a specific time makes sense, but timeupdate is also fired at intervals while the video is playing normally. What would it mean to cancel one of those? Perhaps pause the video and rewind to the time of the last timeupdate event? Something could be defined, but there isn’t an obvious interpretation.

So, why was the event marked as .cancelable?

I experimented with some other “simple events” on HTML5 media: play, playing, pause, seeking, seeked. None of them were specified as cancelable in the specification and none of them responded to .preventDefault(), but all of them were marked as .cancelable. This behaviour was the same in Firefox, Chrome, Safari and Opera.

The specification seems unambiguous, and the behaviour it describes actually makes sense. Why do no browsers adhere to it?

I’ve filed a bug against Firefox. I’m going to wait for a response to see if there’s some explanation I’ve missed. If not, I’ll file bugs against the others too.

Advertisements