Skip to content

Instantly share code, notes, and snippets.

@remy
Created March 3, 2010 16:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save remy/320747 to your computer and use it in GitHub Desktop.
Save remy/320747 to your computer and use it in GitHub Desktop.
(function(window, document, undefined) {
// Enable all HTML5 elements in IE. For discussion and comments, see: http://remysharp.com/2009/01/07/html5-enabling-script/
/*@cc_on'abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video'.replace(/\w+/g,function(n){document.createElement(n)})@*/
if (![].forEach) {
Array.prototype.forEach = function (fn) {
var len = this.length || 0, that = arguments[1];
if (typeof fn == 'function') {
for (var i = 0; i < len; i++) {
fn.call(that, this[i], i, this);
}
}
};
}
var each = [].forEach;
/**
* Replaces all video tags with flowplayer video player if the browser does
* not support either the video tag the h.264 codex.
*
* This is run automatically on document ready, but can be run manually
* again after dynamically creating HTML5 video tags.
*/
function html5media() {
each.call(document.getElementsByTagName('video'), function (video) {
var requiresFallback = true;
// Test if the video tag is supported.
if (video.canPlayType) {
// If the video has a src attribute, and can play it, then all is good.
if (video.src && video.canPlayType(guessFormat(video.src))) {
requiresFallback = false;
} else {
// Check for source child attributes.
each.call(video.getElementsByTagName('source'), function (source) {
if (video.canPlayType(guessFormat(source.src, source.type))) {
requiresFallback = false;
}
});
}
}
// If cannot play video, create the fallback.
if (requiresFallback) {
createVideoFallback(video);
}
});
}
/**
* The locations of the flowplayer and flowplayer controls SWF files.
*
* Override this if they are not located in the same folder as the
*/
// HACK: This could be done much easier with a selector, but there is a bug in IE6 that doesn't allow dots in attribute selectors.
var scriptRoot = "";
each.call(document.getElementsByTagName('script'), function (script) {
var src = script.src;
if (src.substr(src.length - 20) == "jquery.html5media.js" || src.substr(src.length - 24) == "jquery.html5media.min.js") {
scriptRoot = src.split("/").slice(0, -1).join("/") + "/";
}
});
html5media.flowplayerSwf = scriptRoot + "flowplayer.swf";
html5media.flowplayerControlsSwf = scriptRoot + "flowplayer.controls.swf";
/**
* Known video formats. Used to change the assumed format to a different
* format, such as Theora, if desired.
*/
html5media.H264_FORMAT = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
html5media.THEORA_FORMAT = 'video/ogg; codecs="theora, vorbis"';
/**
* The video format to assume if it cannot be determined what format a video
* file is.
*/
html5media.assumedFormat = html5media.H264_FORMAT;
// Trys to determine the format of a given video file.
function guessFormat(src, type) {
// If a type is explicitly given, then use this.
if (type) {
return type;
}
// Try to guess based on file extension.
type = {
"avi": html5media.H264_FORMAT,
"mp4": html5media.H264_FORMAT,
"mkv": html5media.H264_FORMAT,
"h264": html5media.H264_FORMAT,
"264": html5media.H264_FORMAT,
"avc": html5media.H264_FORMAT,
"m4v": html5media.H264_FORMAT,
"3gp": html5media.H264_FORMAT,
"3gpp": html5media.H264_FORMAT,
"3g2": html5media.H264_FORMAT,
"ogg": html5media.THEORA_FORMAT,
"ogv": html5media.THEORA_FORMAT
}[src.split(".").slice(-1)[0]];
return type || html5media.assumedFormat;
}
// Detects presence of HTML5 attributes.
function hasAttr(element, attr) {
var val = element.getAttribute(attr);
return val == true || typeof val == "string";
}
/**
* Default callback for creating a fallback for html5 video tags.
*
* This implementation creates flowplayer instances, but this can
* theoretically be used to support all different types of flash player.
*/
function createVideoFallback(video) {
// Standardize the src and poster.
var baseUrl = window.location.protocol + "//" + window.location.host;
function addDomain(url) {
if (url.substr(0, 1) == "/") {
return baseUrl + url;
}
return url;
}
var poster = addDomain(video.poster || "");
var src = video.src;
if (!src) {
// Find a h.264 file.
each.call(video.getElementsByTagName('source'), function (source) {
if (guessFormat(source.src, source.type) == html5media.H264_FORMAT) {
src = source.src;
}
});
}
src = addDomain(src || "");
// Add in the replacement video div.
var replacement = document.createElement('div');
"className id title".split(' ').forEach(function (k) {
replacement[k] = video[k];
});
replacement.style.width = video.width + 'px';
replacement.style.height = video.height + 'px';
video.parentNode.replaceChild(replacement, video);
// Activate flowplayer.
var flowplayerControls = null;
if (hasAttr(video, "controls")) {
flowplayerControls = {
url: html5media.flowplayerControlsSwf,
fullscreen: false,
autoHide: "always"
}
}
var playlist = [{
url: src,
autoPlay: hasAttr(video, "autoplay"),
autoBuffering: hasAttr(video, "autobuffer"),
onBeforeFinish: function() {
return !hasAttr(video, "loop");
}
}];
if (poster) {
playlist.splice(0, 0, {url: poster});
}
flowplayer(replacement, html5media.flowplayerSwf, {
play: null,
playlist: playlist,
clip: {
scaling: "fit",
fadeInSpeed: 0,
fadeOutSpeed: 0
},
plugins: {
controls: flowplayerControls
}
});
}
// must be included before </body> or after all video elements
html5media();
})(this, document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment