Find file
Fetching contributors…
Cannot retrieve contributors at this time
108 lines (93 sloc) 3.65 KB
<video preload="metadata"> <!-- -->
<source src="assets/dizzy.mp4" type="video/mp4" />
<source src="assets/dizzy.webm" type="video/webm" />
<source src="assets/dizzy.ogv" type="video/ogg" />
<p id="controls">
<input type="button" id="play" value="play">
<span id="position">00:00</span> / <span id="duration">loading...</span>
<p>Video loaded: <span id="using">loading...</span></p>
<p>Note that (at time of writing) <a href="" title="The WebKit Open Source Project">Webkit nightly</a> supports full screen mode, which will add a button above.</p>
Note that this example used to contain the video inline in the HTML above.
However, since it's been understood that there's the possible risk of a race
condition (which I'll explain in a moment), it means the best way to prevent
this problem is to generate the video element attaching the events, and only
once all this is in place, assign the source and insert the element.
Other possible alternatives would be to listen on the window object for the
loadedmetadata event and to check the with the element we're
interested in, but it would require the script at the top of the code -
which would block, and that's something I prefer not to do.
Another alternative is to put inline event handlers in the markup, again
this is something I prefer not to do.
One final alternative is to create the meida element and bind the event
before dropping it in the DOM.
Instead of all of these workarounds, I'm going to test the readyState
of the media element. If readyState is > 0, then it means the metadata
has loaded, and therefore I'll have to run the event handler manually.
var video = document.getElementsByTagName('video')[0],
togglePlay = document.getElementById('play'),
position = document.getElementById('position'),
using = document.getElementById('using'),
ready = false,
controls = document.getElementById('controls'),
fullscreen = null;
addEvent(togglePlay, 'click', function () {
if (ready) {
// video.playbackRate = 0.5;
if (video.paused) {
if (video.ended) video.currentTime = 0;;
this.value = "pause";
} else {
this.value = "play";
addEvent(video, 'timeupdate', function () {
position.innerHTML = asTime(this.currentTime);
addEvent(video, 'ended', function () {
togglePlay.value = "play";
// this used to be canplay, but really it should have been loadedmetadata - sorry folks
function loadedmetadata() {
video.muted = true;
ready = true;
document.querySelector('#duration').innerHTML = asTime(this.duration);
using.innerHTML = this.currentSrc;
// note: .webkitSupportsFullscreen is false while the video is loading, so we bind in to the canplay event
if (video.webkitSupportsFullscreen) {
fullscreen = document.createElement('input');
fullscreen.setAttribute('type', 'button');
fullscreen.setAttribute('value', 'fullscreen');
controls.insertBefore(fullscreen, controls.firstChild);
addEvent(fullscreen, 'click', function () {
if (video.readyState > 0) { // metadata is loaded already - fire the event handler manually;
} else {
addEvent(video, 'loadedmetadata', loadedmetadata);
function asTime(t) {
t = Math.round(t);
var s = t % 60;
var m = Math.floor(t / 60);
return two(m) + ':' + two(s);
function two(s) {
s += "";
if (s.length < 2) s = "0" + s;
return s;