<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
<script>
function init() {
var vid = document.getElementById('vid');
addListeners(vid);
}
function toggleNotes() {
var notes = document.getElementsByClassName('note');
var isShowing = parseInt(window.getComputedStyle(notes[0],null).getPropertyValue("opacity"));
for (var i = 0; i < notes.length; i++) {
notes[i].style.opacity = isShowing ? 0 : 1;
}
// toggle text to "Show Notes" or "Hide Notes"
document.getElementById('notes').className = isShowing ? 'off' : 'on';
}
function addListeners(vid)
{
/* add all event listeners for HTML5 media element events */
vid.addEventListener('loadstart', function(evt) { logEvent(evt,'#000099'); }, false);
vid.addEventListener('canplaythrough',function(evt) { logEvent(evt,'#66CC33'); }, false);
vid.addEventListener('canplay', function(evt) { logEvent(evt,'#66CC33'); }, false);
vid.addEventListener('loadeddata', function(evt) { logEvent(evt,'#00CCCC'); }, false);
vid.addEventListener('loadedmetadata', function(evt) { logEvent(evt,'#00CCCC'); }, false);
vid.addEventListener('abort', function(evt) { logEvent(evt,'red'); }, false);
vid.addEventListener('emptied', function(evt) { logEvent(evt,'red'); }, false);
vid.addEventListener('error', function(evt) { logEvent(evt,'red'); }, false);
vid.addEventListener('stalled', function(evt) { logEvent(evt,'red'); }, false);
vid.addEventListener('suspend', function(evt) { logEvent(evt,'red'); }, false);
vid.addEventListener('waiting', function(evt) { logEvent(evt,'red'); }, false);
vid.addEventListener('pause', function(evt) { logEvent(evt,'orange'); }, false);
vid.addEventListener('play', function(evt) { logEvent(evt,'orange'); }, false);
vid.addEventListener('volumechange', function(evt) { logEvent(evt,'orange'); }, false);
vid.addEventListener('playing', function(evt) { logEvent(evt,'purple'); }, false);
vid.addEventListener('seeked', function(evt) { logEvent(evt,'teal'); }, false);
vid.addEventListener('seeking', function(evt) { logEvent(evt,'teal'); }, false);
vid.addEventListener('durationchange', function(evt) { logEvent(evt,'#cc0066'); }, false);
vid.addEventListener('progress', function(evt) { logEvent(evt,'#cc0066'); }, false);
vid.addEventListener('ratechange', function(evt) { logEvent(evt,'#cc0066'); }, false);
vid.addEventListener('timeupdate', function(evt) { logEvent(evt,'gray'); }, false);
vid.addEventListener('ended', function(evt) { logEvent(evt,'#000099'); }, false);
vid.addEventListener('webkitbeginfullscreen', function(evt) { logEvent(evt,'#FF6666'); }, false);
vid.addEventListener('webkitendfullscreen', function(evt) { logEvent(evt,'#FF6666'); }, false);
}
function logEvent(evt, color)
{
var log = document.createElement("div");
log.innerHTML = evt.type;
log.style.color = color;
var note = document.createElement("span");
note.setAttribute('class', 'note');
/* set the opacity of the note on the fly, based on whether notes are currently toggled on or off */
note.style.opacity = document.getElementById('notes').className == 'on' ? '1' : '0';
/* add a note describing what each event does */
switch (evt.type) {
case 'loadstart' :
note.innerHTML = "begin loading media data";
break;
case 'progress':
note.innerHTML = "fetching media...";
break;
case 'canplay':
note.innerHTML = "can play, but will eventually have to buffer";
break;
case 'canplaythrough':
note.innerHTML = "can play, won't have to buffer anymore";
break;
case 'loadeddata':
note.innerHTML = "can render media data at current playback position";
break;
case 'loadedmetadata':
note.innerHTML = "now we know duration, height, width, and more";
break;
case 'timeupdate':
log.innerHTML += " " + evt.target.currentTime.toFixed(3);
break;
case 'durationchange':
note.innerHTML = "new info about the duration";
break;
case 'volumechange':
note.innerHTML = "volume or muted property has changed";
break;
case 'play':
note.innerHTML = "just returned from the play function";
break;
case 'playing':
note.innerHTML = "playback has started";
break;
case 'pause':
note.innerHTML = "just returned from the pause function";
break;
case 'suspend':
note.innerHTML = "loading has stopped, but not all of the media has downloaded";
break;
case 'waiting':
note.innerHTML = "stopped playback because we're waiting for the next frame";
break;
case 'stalled':
note.innerHTML = "fetching media data, but none is arriving";
break;
case 'webkitbeginfullscreen':
note.innerHTML = "entering fullscreen mode";
break;
case 'webkitendfullscreen':
note.innerHTML = "exiting fullscreen mode";
break;
case 'error':
var error = document.querySelector('video').error;
switch (error.code) {
case error.MEDIA_ERR_ABORTED:
note.innerHTML = "fetching aborted at the user's request";
break;
case error.MEDIA_ERR_NETWORK:
note.innerHTML = "a network error caused the browser to stop fetching the media";
break;
case error.MEDIA_ERR_DECODE:
note.innerHTML = "an error occurred while decoding the media";
break;
case error.MEDIA_ERR_SRC_NOT_SUPPORTED:
note.innerHTML = "the media indicated by the src attribute was not suitable";
break;
default:
note.innerHTML = "an error occurred";
break;
}
break;
}
/* create the log message and append it to the events log */
log.appendChild(note);
var eventslog = document.getElementById('eventslog');
eventslog.insertBefore(log, eventslog.firstChild);
}
</script>
</head>
<body onload='init();'>
<h1>Events for the <video> element</h1>
Example showing the differents events. Code borrowed and adapted from: <a href="http://developer.apple.com/library/safari/samplecode/HTML5VideoEventFlow/Listings/events_js.html">http://developer.apple.com/library/safari/samplecode/HTML5VideoEventFlow/Listings/events_js.html</a><p>
<p><b>If running in jsbin.com, you need to run it "externally", use the small arrow on top right.</b> <p>
<!-- <video> tag, with the @controls attribute
giving it the play/pause/seeker controls. Try removing the controls attribute,
adding autoplay or loop -->
<video id="vid" controls>
<!-- I have three versions of the video encoded with
different codecs. The browser will automatically
choose the first one it knows it can play. -->
<source src=http://html5doctor.com/demos/video-canvas-magic/video.webm type=video/webm>
<source src=http://html5doctor.com/demos/video-canvas-magic/video.ogg type=video/ogg>
<source src=http://html5doctor.com/demos/video-canvas-magic/video.mp4 type=video/mp4>
</video> <p>
<div id="notes"></div><p>
<div id="eventslog"></div>
</body>
</html>
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |