Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Bump mediaelement version to 2.6.4 and this version to 0.3.2

  • Loading branch information...
commit f061d59cc3018ecd800ec93e4e26c5f8fb228939 1 parent 6777055
xanview hackeron authored
1  .gitignore
View
@@ -1,3 +1,4 @@
+*.DS_Store
.bundle/
pkg/
Gemfile.lock
0  app/assets/images/mediaelement_rails/background.png 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
0  app/assets/images/mediaelement_rails/bigplay.png 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  app/assets/images/mediaelement_rails/controls-ted.png 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  app/assets/images/mediaelement_rails/controls-wmp-bg.png 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  app/assets/images/mediaelement_rails/controls-wmp.png 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
0  app/assets/images/mediaelement_rails/controls.png 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
0  app/assets/images/mediaelement_rails/loading.gif 100644 → 100755
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
695 app/assets/javascripts/mediaelement_rails/mediaelement.js 100644 → 100755
View
@@ -11,109 +11,145 @@
* Dual licensed under the MIT or GPL Version 2 licenses.
*
*/
-// Namespace
-var mejs = mejs || {};
-
-// version number
-mejs.version = '2.2.5';
-
-// player number (for missing, same id attr)
-mejs.meIndex = 0;
-
-// media types accepted by plugins
-mejs.plugins = {
- silverlight: [
- {version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
- ],
- flash: [
- {version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg']}
- //,{version: [12,0], types: ['video/webm']} // for future reference
- ]
-};
-
-/*
-Utility methods
-*/
-mejs.Utility = {
- encodeUrl: function(url) {
- return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
- },
- escapeHTML: function(s) {
- return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
- },
- absolutizeUrl: function(url) {
- var el = document.createElement('div');
- el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
- return el.firstChild.href;
- },
- getScriptPath: function(scriptNames) {
- var
- i = 0,
- j,
- path = '',
- name = '',
- script,
- scripts = document.getElementsByTagName('script');
-
- for (; i < scripts.length; i++) {
- script = scripts[i].src;
- for (j = 0; j < scriptNames.length; j++) {
- name = scriptNames[j];
- if (script.indexOf(name) > -1) {
- path = script.substring(0, script.indexOf(name));
- break;
- }
- }
- if (path !== '') {
- break;
- }
- }
- return path;
- },
- secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
- //add framecount
- if (typeof showFrameCount == 'undefined') {
- showFrameCount=false;
- } else if(typeof fps == 'undefined') {
- fps = 25;
- }
-
- var hours = Math.floor(time / 3600) % 24,
- minutes = Math.floor(time / 60) % 60,
- seconds = Math.floor(time % 60),
- frames = Math.floor(((time % 1)*fps).toFixed(3)),
- result =
- ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
- + (minutes < 10 ? '0' + minutes : minutes) + ':'
- + (seconds < 10 ? '0' + seconds : seconds)
- + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
-
- return result;
- },
-
- timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
- if (typeof showFrameCount == 'undefined') {
- showFrameCount=false;
- } else if(typeof fps == 'undefined') {
- fps = 25;
- }
-
- var tc_array = hh_mm_ss_ff.split(":"),
- tc_hh = parseInt(tc_array[0]),
- tc_mm = parseInt(tc_array[1]),
- tc_ss = parseInt(tc_array[2]),
- tc_ff = 0,
- tc_in_seconds = 0;
-
- if (showFrameCount) {
- tc_ff = parseInt(tc_array[3])/fps;
- }
-
- tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
-
- return tc_in_seconds;
- }
+// Namespace
+var mejs = mejs || {};
+
+// version number
+mejs.version = '2.6.5';
+
+// player number (for missing, same id attr)
+mejs.meIndex = 0;
+
+// media types accepted by plugins
+mejs.plugins = {
+ silverlight: [
+ {version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
+ ],
+ flash: [
+ {version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg']}
+ //,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
+ ],
+ youtube: [
+ {version: null, types: ['video/youtube']}
+ ],
+ vimeo: [
+ {version: null, types: ['video/vimeo']}
+ ]
};
+
+/*
+Utility methods
+*/
+mejs.Utility = {
+ encodeUrl: function(url) {
+ return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
+ },
+ escapeHTML: function(s) {
+ return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
+ },
+ absolutizeUrl: function(url) {
+ var el = document.createElement('div');
+ el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
+ return el.firstChild.href;
+ },
+ getScriptPath: function(scriptNames) {
+ var
+ i = 0,
+ j,
+ path = '',
+ name = '',
+ script,
+ scripts = document.getElementsByTagName('script');
+
+ for (; i < scripts.length; i++) {
+ script = scripts[i].src;
+ for (j = 0; j < scriptNames.length; j++) {
+ name = scriptNames[j];
+ if (script.indexOf(name) > -1) {
+ path = script.substring(0, script.indexOf(name));
+ break;
+ }
+ }
+ if (path !== '') {
+ break;
+ }
+ }
+ return path;
+ },
+ secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
+ //add framecount
+ if (typeof showFrameCount == 'undefined') {
+ showFrameCount=false;
+ } else if(typeof fps == 'undefined') {
+ fps = 25;
+ }
+
+ var hours = Math.floor(time / 3600) % 24,
+ minutes = Math.floor(time / 60) % 60,
+ seconds = Math.floor(time % 60),
+ frames = Math.floor(((time % 1)*fps).toFixed(3)),
+ result =
+ ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
+ + (minutes < 10 ? '0' + minutes : minutes) + ':'
+ + (seconds < 10 ? '0' + seconds : seconds)
+ + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
+
+ return result;
+ },
+
+ timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
+ if (typeof showFrameCount == 'undefined') {
+ showFrameCount=false;
+ } else if(typeof fps == 'undefined') {
+ fps = 25;
+ }
+
+ var tc_array = hh_mm_ss_ff.split(":"),
+ tc_hh = parseInt(tc_array[0], 10),
+ tc_mm = parseInt(tc_array[1], 10),
+ tc_ss = parseInt(tc_array[2], 10),
+ tc_ff = 0,
+ tc_in_seconds = 0;
+
+ if (showFrameCount) {
+ tc_ff = parseInt(tc_array[3])/fps;
+ }
+
+ tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
+
+ return tc_in_seconds;
+ },
+
+ /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
+ removeSwf: function(id) {
+ var obj = document.getElementById(id);
+ if (obj && obj.nodeName == "OBJECT") {
+ if (mejs.MediaFeatures.isIE) {
+ obj.style.display = "none";
+ (function(){
+ if (obj.readyState == 4) {
+ mejs.Utility.removeObjectInIE(id);
+ } else {
+ setTimeout(arguments.callee, 10);
+ }
+ })();
+ } else {
+ obj.parentNode.removeChild(obj);
+ }
+ }
+ },
+ removeObjectInIE: function(id) {
+ var obj = document.getElementById(id);
+ if (obj) {
+ for (var i in obj) {
+ if (typeof obj[i] == "function") {
+ obj[i] = null;
+ }
+ }
+ obj.parentNode.removeChild(obj);
+ }
+ }
+};
// Core detector, plugins are added below
@@ -238,8 +274,10 @@ mejs.MediaFeatures = {
t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
t.isChrome = (ua.match(/chrome/gi) !== null);
t.isFirefox = (ua.match(/firefox/gi) !== null);
- t.isGecko = (ua.match(/gecko/gi) !== null);
t.isWebkit = (ua.match(/webkit/gi) !== null);
+ t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
+ t.isOpera = (ua.match(/opera/gi) !== null);
+ t.hasTouch = ('ontouchstart' in window);
// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
for (i=0; i<html5Elements.length; i++) {
@@ -258,6 +296,10 @@ mejs.MediaFeatures = {
t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen);
+ t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
+ if (t.hasMozNativeFullScreen) {
+ t.nativeFullScreenEnabled = v.mozFullScreenEnabled;
+ }
if (this.isChrome) {
@@ -403,25 +445,43 @@ mejs.PluginMediaElement.prototype = {
// HTML5 methods
play: function () {
if (this.pluginApi != null) {
- this.pluginApi.playMedia();
+ if (this.pluginType == 'youtube') {
+ this.pluginApi.playVideo();
+ } else {
+ this.pluginApi.playMedia();
+ }
this.paused = false;
}
},
load: function () {
if (this.pluginApi != null) {
- this.pluginApi.loadMedia();
+ if (this.pluginType == 'youtube') {
+ } else {
+ this.pluginApi.loadMedia();
+ }
+
this.paused = false;
}
},
pause: function () {
if (this.pluginApi != null) {
- this.pluginApi.pauseMedia();
+ if (this.pluginType == 'youtube') {
+ this.pluginApi.pauseVideo();
+ } else {
+ this.pluginApi.pauseMedia();
+ }
+
+
this.paused = true;
}
},
stop: function () {
if (this.pluginApi != null) {
- this.pluginApi.stopMedia();
+ if (this.pluginType == 'youtube') {
+ this.pluginApi.stopVideo();
+ } else {
+ this.pluginApi.stopMedia();
+ }
this.paused = true;
}
},
@@ -449,6 +509,19 @@ mejs.PluginMediaElement.prototype = {
return false;
},
+
+ positionFullscreenButton: function(x,y,visibleAndAbove) {
+ if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
+ this.pluginApi.positionFullscreenButton(x,y,visibleAndAbove);
+ }
+ },
+
+ hideFullscreenButton: function() {
+ if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
+ this.pluginApi.hideFullscreenButton();
+ }
+ },
+
// custom methods since not all JavaScript implementations support get/set
@@ -473,46 +546,76 @@ mejs.PluginMediaElement.prototype = {
},
setCurrentTime: function (time) {
if (this.pluginApi != null) {
- this.pluginApi.setCurrentTime(time);
+ if (this.pluginType == 'youtube') {
+ this.pluginApi.seekTo(time);
+ } else {
+ this.pluginApi.setCurrentTime(time);
+ }
+
+
+
this.currentTime = time;
}
},
setVolume: function (volume) {
if (this.pluginApi != null) {
- this.pluginApi.setVolume(volume);
+ // same on YouTube and MEjs
+ if (this.pluginType == 'youtube') {
+ this.pluginApi.setVolume(volume * 100);
+ } else {
+ this.pluginApi.setVolume(volume);
+ }
this.volume = volume;
}
},
setMuted: function (muted) {
if (this.pluginApi != null) {
- this.pluginApi.setMuted(muted);
+ if (this.pluginType == 'youtube') {
+ if (muted) {
+ this.pluginApi.mute();
+ } else {
+ this.pluginApi.unMute();
+ }
+ this.muted = muted;
+ this.dispatchEvent('volumechange');
+ } else {
+ this.pluginApi.setMuted(muted);
+ }
this.muted = muted;
}
},
// additional non-HTML5 methods
setVideoSize: function (width, height) {
- if ( this.pluginElement.style) {
- this.pluginElement.style.width = width + 'px';
- this.pluginElement.style.height = height + 'px';
- }
- if (this.pluginApi != null) {
- this.pluginApi.setVideoSize(width, height);
- }
+
+ //if (this.pluginType == 'flash' || this.pluginType == 'silverlight') {
+ if ( this.pluginElement.style) {
+ this.pluginElement.style.width = width + 'px';
+ this.pluginElement.style.height = height + 'px';
+ }
+ if (this.pluginApi != null && this.pluginApi.setVideoSize) {
+ this.pluginApi.setVideoSize(width, height);
+ }
+ //}
},
setFullscreen: function (fullscreen) {
- if (this.pluginApi != null) {
+ if (this.pluginApi != null && this.pluginApi.setFullscreen) {
this.pluginApi.setFullscreen(fullscreen);
}
},
enterFullScreen: function() {
- this.setFullscreen(true);
+ if (this.pluginApi != null && this.pluginApi.setFullscreen) {
+ this.setFullscreen(true);
+ }
+
},
- enterFullScreen: function() {
- this.setFullscreen(false);
+ exitFullScreen: function() {
+ if (this.pluginApi != null && this.pluginApi.setFullscreen) {
+ this.setFullscreen(false);
+ }
},
// start: fake events
@@ -544,11 +647,14 @@ mejs.PluginMediaElement.prototype = {
callbacks[i].apply(null, args);
}
}
- }
+ },
// end: fake events
+
+ remove: function() {
+ mejs.Utility.removeSwf(this.pluginElement.id);
+ }
};
-
// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
mejs.MediaPluginBridge = {
@@ -566,19 +672,21 @@ mejs.MediaPluginBridge = {
var pluginMediaElement = this.pluginMediaElements[id],
htmlMediaElement = this.htmlMediaElements[id];
- // find the javascript bridge
- switch (pluginMediaElement.pluginType) {
- case "flash":
- pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
- break;
- case "silverlight":
- pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
- pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
- break;
- }
-
- if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
- pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
+ if (pluginMediaElement) {
+ // find the javascript bridge
+ switch (pluginMediaElement.pluginType) {
+ case "flash":
+ pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
+ break;
+ case "silverlight":
+ pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
+ pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
+ break;
+ }
+
+ if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
+ pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
+ }
}
},
@@ -635,7 +743,7 @@ mejs.MediaElementDefaults = {
// none: forces fallback view
mode: 'auto',
// remove or reorder to change plugin priority and availability
- plugins: ['flash','silverlight'],
+ plugins: ['flash','silverlight','youtube','vimeo'],
// shows debug errors on screen
enablePluginDebug: false,
// overrides the type specified, useful for dynamic instantiation
@@ -656,6 +764,8 @@ mejs.MediaElementDefaults = {
pluginWidth: -1,
// overrides <video height>
pluginHeight: -1,
+ // additional plugin variables in 'key=value' form
+ pluginVars: [],
// rate in milliseconds for Flash and Silverlight to fire the timeupdate event
// larger number is less accurate, but less strain on plugin->JavaScript bridge
timerRate: 250,
@@ -696,11 +806,11 @@ mejs.HtmlMediaElementShim = {
}
// clean up attributes
- src = (src == 'undefined' || src == '' || src === null) ? null : src;
- poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
- preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
- autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
- controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
+ src = (typeof src == 'undefined' || src === null || src == '') ? null : src;
+ poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
+ preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
+ autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
+ controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
// test for HTML5 and plugin capabilities
playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
@@ -711,8 +821,8 @@ mejs.HtmlMediaElementShim = {
if (mejs.MediaFeatures.isBustedAndroid) {
htmlMediaElement.src = playback.url;
htmlMediaElement.addEventListener('click', function() {
- htmlMediaElement.play();
- }, true);
+ htmlMediaElement.play();
+ }, false);
}
// add methods to native HTMLMediaElement
@@ -724,6 +834,8 @@ mejs.HtmlMediaElementShim = {
} else {
// boo, no HTML5, no Flash, no Silverlight.
this.createErrorMessage( playback, options, poster );
+
+ return this;
}
},
@@ -835,14 +947,19 @@ mejs.HtmlMediaElementShim = {
for (j=0; j<options.plugins.length; j++) {
pluginName = options.plugins[j];
-
+
// test version of plugin (for future features)
- pluginVersions = mejs.plugins[pluginName];
+ pluginVersions = mejs.plugins[pluginName];
+
for (k=0; k<pluginVersions.length; k++) {
pluginInfo = pluginVersions[k];
-
+
// test if user has the correct plugin version
- if (mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
+
+ // for youtube/vimeo
+ if (pluginInfo.version == null ||
+
+ mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
// test for plugin playback types
for (l=0; l<pluginInfo.types.length; l++) {
@@ -860,7 +977,7 @@ mejs.HtmlMediaElementShim = {
}
// what if there's nothing to play? just grab the first available
- if (result.method === '') {
+ if (result.method === '' && mediaFiles.length > 0) {
result.url = mediaFiles[0].url;
}
@@ -956,7 +1073,13 @@ mejs.HtmlMediaElementShim = {
// add container (must be added to DOM before inserting HTML for IE)
container.className = 'me-plugin';
- htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
+ container.id = pluginid + '_container';
+
+ if (playback.isVideo) {
+ htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
+ } else {
+ document.body.insertBefore(container, document.body.childNodes[0]);
+ }
// flash/silverlight vars
initVars = [
@@ -985,6 +1108,9 @@ mejs.HtmlMediaElementShim = {
if (controls) {
initVars.push('controls=true'); // shows controls in the plugin if desired
}
+ if (options.pluginVars) {
+ initVars = initVars.concat(options.pluginVars);
+ }
switch (playback.method) {
case 'silverlight':
@@ -1005,7 +1131,7 @@ mejs.HtmlMediaElementShim = {
specialIEContainer = document.createElement('div');
container.appendChild(specialIEContainer);
specialIEContainer.outerHTML =
-'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
+'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
'id="' + pluginid + '" width="' + width + '" height="' + height + '">' +
'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
'<param name="flashvars" value="' + initVars.join('&amp;') + '" />' +
@@ -1027,13 +1153,53 @@ mejs.HtmlMediaElementShim = {
'wmode="transparent" ' +
'allowScriptAccess="always" ' +
'allowFullScreen="true" ' +
-'type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" ' +
+'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
'src="' + options.pluginPath + options.flashName + '" ' +
'flashvars="' + initVars.join('&') + '" ' +
'width="' + width + '" ' +
'height="' + height + '"></embed>';
}
break;
+
+ case 'youtube':
+
+
+ var
+ videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
+ youtubeSettings = {
+ container: container,
+ containerId: container.id,
+ pluginMediaElement: pluginMediaElement,
+ pluginId: pluginid,
+ videoId: videoId,
+ height: height,
+ width: width
+ };
+
+ if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) {
+ mejs.YouTubeApi.createFlash(youtubeSettings);
+ } else {
+ mejs.YouTubeApi.enqueueIframe(youtubeSettings);
+ }
+
+ break;
+
+ // DEMO Code. Does NOT work.
+ case 'vimeo':
+ console.log('vimeoid');
+
+ pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
+
+ container.innerHTML =
+ '<object width="' + width + '" height="' + height + '">' +
+ '<param name="allowfullscreen" value="true" />' +
+ '<param name="allowscriptaccess" value="always" />' +
+ '<param name="flashvars" value="api=1" />' +
+ '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" />' +
+ '<embed src="//vimeo.com/moogaloop.swf?api=1&amp;clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '"></embed>' +
+ '</object>';
+
+ break;
}
// hide original element
htmlMediaElement.style.display = 'none';
@@ -1089,5 +1255,230 @@ mejs.HtmlMediaElementShim = {
}
};
+/*
+ - test on IE (object vs. embed)
+ - determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE)
+ - fullscreen?
+*/
+
+// YouTube Flash and Iframe API
+mejs.YouTubeApi = {
+ isIframeStarted: false,
+ isIframeLoaded: false,
+ loadIframeApi: function() {
+ if (!this.isIframeStarted) {
+ var tag = document.createElement('script');
+ tag.src = "http://www.youtube.com/player_api";
+ var firstScriptTag = document.getElementsByTagName('script')[0];
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
+ this.isIframeStarted = true;
+ }
+ },
+ iframeQueue: [],
+ enqueueIframe: function(yt) {
+
+ if (this.isLoaded) {
+ this.createIframe(yt);
+ } else {
+ this.loadIframeApi();
+ this.iframeQueue.push(yt);
+ }
+ },
+ createIframe: function(settings) {
+
+ var
+ pluginMediaElement = settings.pluginMediaElement,
+ player = new YT.Player(settings.containerId, {
+ height: settings.height,
+ width: settings.width,
+ videoId: settings.videoId,
+ playerVars: {controls:0},
+ events: {
+ 'onReady': function() {
+
+ // hook up iframe object to MEjs
+ settings.pluginMediaElement.pluginApi = player;
+
+ // init mejs
+ mejs.MediaPluginBridge.initPlugin(settings.pluginId);
+
+ // create timer
+ setInterval(function() {
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
+ }, 250);
+ },
+ 'onStateChange': function(e) {
+
+ mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement);
+
+ }
+ }
+ });
+ },
+
+ createEvent: function (player, pluginMediaElement, eventName) {
+ var obj = {
+ type: eventName,
+ target: pluginMediaElement
+ };
+
+ if (player && player.getDuration) {
+
+ // time
+ pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime();
+ pluginMediaElement.duration = obj.duration = player.getDuration();
+
+ // state
+ obj.paused = pluginMediaElement.paused;
+ obj.ended = pluginMediaElement.ended;
+
+ // sound
+ obj.muted = player.isMuted();
+ obj.volume = player.getVolume() / 100;
+
+ // progress
+ obj.bytesTotal = player.getVideoBytesTotal();
+ obj.bufferedBytes = player.getVideoBytesLoaded();
+
+ // fake the W3C buffered TimeRange
+ var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration;
+
+ obj.target.buffered = obj.buffered = {
+ start: function(index) {
+ return 0;
+ },
+ end: function (index) {
+ return bufferedTime;
+ },
+ length: 1
+ };
+
+ }
+
+ // send event up the chain
+ pluginMediaElement.dispatchEvent(obj.type, obj);
+ },
+
+ iFrameReady: function() {
+
+ this.isIframeLoaded = true;
+
+ while (this.iframeQueue.length > 0) {
+ var settings = this.iframeQueue.pop();
+ this.createIframe(settings);
+ }
+ },
+
+ // FLASH!
+ flashPlayers: {},
+ createFlash: function(settings) {
+
+ this.flashPlayers[settings.pluginId] = settings;
+
+ /*
+ settings.container.innerHTML =
+ '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' +
+ 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; ">' +
+ '<param name="allowScriptAccess" value="always">' +
+ '<param name="wmode" value="transparent">' +
+ '</object>';
+ */
+
+ var specialIEContainer,
+ youtubeUrl = 'http://www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0';
+
+ if (mejs.MediaFeatures.isIE) {
+
+ specialIEContainer = document.createElement('div');
+ settings.container.appendChild(specialIEContainer);
+ specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
+'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '">' +
+ '<param name="movie" value="' + youtubeUrl + '" />' +
+ '<param name="wmode" value="transparent" />' +
+ '<param name="allowScriptAccess" value="always" />' +
+ '<param name="allowFullScreen" value="true" />' +
+'</object>';
+ } else {
+ settings.container.innerHTML =
+ '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' +
+ 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; ">' +
+ '<param name="allowScriptAccess" value="always">' +
+ '<param name="wmode" value="transparent">' +
+ '</object>';
+ }
+
+ },
+
+ flashReady: function(id) {
+ var
+ settings = this.flashPlayers[id],
+ player = document.getElementById(id),
+ pluginMediaElement = settings.pluginMediaElement;
+
+ // hook up and return to MediaELementPlayer.success
+ pluginMediaElement.pluginApi =
+ pluginMediaElement.pluginElement = player;
+ mejs.MediaPluginBridge.initPlugin(id);
+
+ // load the youtube video
+ player.cueVideoById(settings.videoId);
+
+ var callbackName = settings.containerId + '_callback'
+
+ window[callbackName] = function(e) {
+ mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
+ }
+
+ player.addEventListener('onStateChange', callbackName);
+
+ setInterval(function() {
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
+ }, 250);
+ },
+
+ handleStateChange: function(youTubeState, player, pluginMediaElement) {
+ switch (youTubeState) {
+ case -1: // not started
+ pluginMediaElement.paused = true;
+ pluginMediaElement.ended = true;
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata');
+ //createYouTubeEvent(player, pluginMediaElement, 'loadeddata');
+ break;
+ case 0:
+ pluginMediaElement.paused = false;
+ pluginMediaElement.ended = true;
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended');
+ break;
+ case 1:
+ pluginMediaElement.paused = false;
+ pluginMediaElement.ended = false;
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play');
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing');
+ break;
+ case 2:
+ pluginMediaElement.paused = true;
+ pluginMediaElement.ended = false;
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause');
+ break;
+ case 3: // buffering
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress');
+ break;
+ case 5:
+ // cued?
+ break;
+
+ }
+
+ }
+}
+// IFRAME
+function onYouTubePlayerAPIReady() {
+ mejs.YouTubeApi.iFrameReady();
+}
+// FLASH
+function onYouTubePlayerReady(id) {
+ mejs.YouTubeApi.flashReady(id);
+}
+
window.mejs = mejs;
window.MediaElement = mejs.MediaElement;
3,184 app/assets/javascripts/mediaelement_rails/mediaelementplayer.js 100644 → 100755
View
@@ -14,768 +14,1050 @@ if (typeof jQuery != 'undefined') {
} else if (typeof ender != 'undefined') {
mejs.$ = ender;
}
-(function ($) {
-
- // default player values
- mejs.MepDefaults = {
- // url to poster (to fix iOS 3.x)
- poster: '',
- // default if the <video width> is not specified
- defaultVideoWidth: 480,
- // default if the <video height> is not specified
- defaultVideoHeight: 270,
- // if set, overrides <video width>
- videoWidth: -1,
- // if set, overrides <video height>
- videoHeight: -1,
- // width of audio player
- audioWidth: 400,
- // height of audio player
- audioHeight: 30,
- // initial volume when the player starts (overrided by user cookie)
- startVolume: 0.8,
- // useful for <audio> player loops
- loop: false,
- // resize to media dimensions
- enableAutosize: true,
- // forces the hour marker (##:00:00)
- alwaysShowHours: false,
-
- // show framecount in timecode (##:00:00:00)
- showTimecodeFrameCount: false,
- // used when showTimecodeFrameCount is set to true
- framesPerSecond: 25,
-
- // Hide controls when playing and mouse is not over the video
- alwaysShowControls: false,
- // force iPad's native controls
- iPadUseNativeControls: false,
- // force iPad's native controls
- iPhoneUseNativeControls: false,
- // force iPad's native controls
- AndroidUseNativeControls: false,
- // features to show
- features: ['playpause','current','progress','duration','tracks','volume','fullscreen'],
- // only for dynamic
- isVideo: true
- };
-
- mejs.mepIndex = 0;
-
- // wraps a MediaElement object in player controls
- mejs.MediaElementPlayer = function(node, o) {
- // enforce object, even without "new" (via John Resig)
- if ( !(this instanceof mejs.MediaElementPlayer) ) {
- return new mejs.MediaElementPlayer(node, o);
- }
-
- var t = this;
-
- // these will be reset after the MediaElement.success fires
- t.$media = t.$node = $(node);
- t.node = t.media = t.$media[0];
-
- // check for existing player
- if (typeof t.node.player != 'undefined') {
- return t.node.player;
- } else {
- // attach player to DOM node for reference
- t.node.player = t;
- }
-
- // create options
- t.options = $.extend({},mejs.MepDefaults,o);
-
- // start up
- t.init();
-
- return t;
- };
-
- // actual player
- mejs.MediaElementPlayer.prototype = {
- init: function() {
-
- var
- t = this,
- mf = mejs.MediaFeatures,
- // options for MediaElement (shim)
- meOptions = $.extend(true, {}, t.options, {
- success: function(media, domNode) { t.meReady(media, domNode); },
- error: function(e) { t.handleError(e);}
- }),
- tagName = t.media.tagName.toLowerCase();
-
- t.isDynamic = (tagName !== 'audio' && tagName !== 'video');
-
- if (t.isDynamic) {
- // get video from src or href?
- t.isVideo = t.options.isVideo;
- } else {
- t.isVideo = (tagName !== 'audio' && t.options.isVideo);
- }
-
- // use native controls in iPad, iPhone, and Android
- if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) {
-
- // add controls and stop
- t.$media.attr('controls', 'controls');
-
- // attempt to fix iOS 3 bug
- t.$media.removeAttr('poster');
-
- // override Apple's autoplay override for iPads
- if (mf.isiPad && t.media.getAttribute('autoplay') !== null) {
- t.media.load();
- t.media.play();
- }
-
- } else if (mf.isAndroid && t.AndroidUseNativeControls) {
-
- // leave default player
-
- } else {
-
- // DESKTOP: use MediaElementPlayer controls
-
- // remove native controls
- t.$media.removeAttr('controls');
-
- // unique ID
- t.id = 'mep_' + mejs.mepIndex++;
-
- // build container
- t.container =
- $('<div id="' + t.id + '" class="mejs-container">'+
- '<div class="mejs-inner">'+
- '<div class="mejs-mediaelement"></div>'+
- '<div class="mejs-layers"></div>'+
- '<div class="mejs-controls"></div>'+
- '<div class="mejs-clear"></div>'+
- '</div>' +
- '</div>')
- .addClass(t.$media[0].className)
- .insertBefore(t.$media);
-
- // move the <video/video> tag into the right spot
- if (mf.isiPad || mf.isiPhone) {
-
- // sadly, you can't move nodes in iOS, so we have to destroy and recreate it!
- var $newMedia = t.$media.clone();
-
- t.container.find('.mejs-mediaelement').append($newMedia);
-
- t.$media.remove();
- t.$node = t.$media = $newMedia;
- t.node = t.media = $newMedia[0]
-
- } else {
-
- // normal way of moving it into place (doesn't work on iOS)
- t.container.find('.mejs-mediaelement').append(t.$media);
- }
-
- // find parts
- t.controls = t.container.find('.mejs-controls');
- t.layers = t.container.find('.mejs-layers');
-
- // determine the size
- if (t.isVideo) {
- // priority = videoWidth (forced), width attribute, defaultVideoWidth (for unspecified cases)
- t.width = (t.options.videoWidth > 0) ? t.options.videoWidth : (t.$media[0].getAttribute('width') !== null) ? t.$media.attr('width') : t.options.defaultVideoWidth;
- t.height = (t.options.videoHeight > 0) ? t.options.videoHeight : (t.$media[0].getAttribute('height') !== null) ? t.$media.attr('height') : t.options.defaultVideoHeight;
- } else {
- t.width = t.options.audioWidth;
- t.height = t.options.audioHeight;
- }
-
- // set the size, while we wait for the plugins to load below
- t.setPlayerSize(t.width, t.height);
-
- // create MediaElementShim
- meOptions.pluginWidth = t.height;
- meOptions.pluginHeight = t.width;
- }
-
- // create MediaElement shim
- mejs.MediaElement(t.$media[0], meOptions);
- },
-
- controlsAreVisible: true,
-
- showControls: function(doAnimation) {
- var t = this,
- doAnimation = typeof doAnimation == 'undefined' || doAnimation;
-
- if (t.controlsAreVisible)
- return;
-
- if (doAnimation) {
- t.controls
- .css('visibility','visible')
- .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
-
- // any additional controls people might add and want to hide
- t.container.find('.mejs-control')
- .css('visibility','visible')
- .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
-
- } else {
- t.controls
- .css('visibility','visible')
- .css('display','block');
-
- // any additional controls people might add and want to hide
- t.container.find('.mejs-control')
- .css('visibility','visible')
- .css('display','block');
-
- t.controlsAreVisible = true;
- }
-
- t.setControlsSize();
-
- },
-
- hideControls: function(doAnimation) {
- //console.log('hide doAnimation', doAnimation);
- var t = this,
- doAnimation = typeof doAnimation == 'undefined' || doAnimation;
-
- if (!t.controlsAreVisible)
- return;
-
- if (doAnimation) {
- // fade out main controls
- t.controls.stop(true, true).fadeOut(200, function() {
- $(this)
- .css('visibility','hidden')
- .css('display','block');
-
- t.controlsAreVisible = false;
- });
-
- // any additional controls people might add and want to hide
- t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() {
- $(this)
- .css('visibility','hidden')
- .css('display','block');
- });
- } else {
-
- // hide main controls
- t.controls
- .css('visibility','hidden')
- .css('display','block');
-
- // hide others
- t.container.find('.mejs-control')
- .css('visibility','hidden')
- .css('display','block');
-
- t.controlsAreVisible = false;
- }
- },
-
- controlsTimer: null,
-
- startControlsTimer: function(timeout) {
-
- var t = this,
- timeout = typeof timeout != 'undefined' ? timeout : 500;
-
- t.killControlsTimer('start');
-
- t.controlsTimer = setTimeout(function() {
- //console.log('timer fired');
- t.hideControls();
- t.killControlsTimer('hide');
- }, timeout);
- },
-
- killControlsTimer: function(src) {
-
- var t = this;
-
- if (t.controlsTimer !== null) {
- clearTimeout(t.controlsTimer);
- delete t.controlsTimer;
- t.controlsTimer = null;
- }
- },
-
- controlsEnabled: true,
-
- disableControls: function() {
- var t= this;
-
- t.killControlsTimer();
- t.hideControls(false);
- this.controlsEnabled = false;
- },
-
- enableControls: function() {
- var t= this;
-
- t.showControls(false);
-
- t.controlsEnabled = true;
- },
-
-
- // Sets up all controls and events
- meReady: function(media, domNode) {
-
-
- var t = this,
- mf = mejs.MediaFeatures,
- autoplayAttr = domNode.getAttribute('autoplay'),
- autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'),
- featureIndex,
- feature;
-
- // make sure it can't create itself again if a plugin reloads
- if (t.created)
- return;
- else
- t.created = true;
-
- t.media = media;
- t.domNode = domNode;
-
- if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) {
-
- // two built in features
- t.buildposter(t, t.controls, t.layers, t.media);
- t.buildoverlays(t, t.controls, t.layers, t.media);
-
- // grab for use by features
- t.findTracks();
-
- // add user-defined features/controls
- for (featureIndex in t.options.features) {
- feature = t.options.features[featureIndex];
- if (t['build' + feature]) {
- try {
- t['build' + feature](t, t.controls, t.layers, t.media);
- } catch (e) {
- // TODO: report control error
- //throw e;
- //console.log('error building ' + feature);
- //console.log(e);
- }
- }
- }
-
- t.container.trigger('controlsready');
-
- // reset all layers and controls
- t.setPlayerSize(t.width, t.height);
- t.setControlsSize();
-
-
- // controls fade
- if (t.isVideo) {
- // click controls
- if (t.media.pluginType == 'native') {
- t.$media.click(function() {
- if (media.paused) {
- media.play();
- } else {
- media.pause();
- }
- });
- } else {
- $(t.media.pluginElement).click(function() {
- if (media.paused) {
- media.play();
- } else {
- media.pause();
- }
- });
- }
-
-
-
- // show/hide controls
- t.container
- .bind('mouseenter mouseover', function () {
- if (t.controlsEnabled) {
- if (!t.options.alwaysShowControls) {
- t.killControlsTimer('enter');
- t.showControls();
- t.startControlsTimer(2500);
- }
- }
- })
- .bind('mousemove', function() {
- if (t.controlsEnabled) {
- if (!t.controlsAreVisible)
- t.showControls();
- //t.killControlsTimer('move');
- t.startControlsTimer(2500);
- }
- })
- .bind('mouseleave', function () {
- if (t.controlsEnabled) {
- if (!t.media.paused && !t.options.alwaysShowControls) {
- t.startControlsTimer(1000);
- }
- }
- });
-
- // check for autoplay
- if (autoplay && !t.options.alwaysShowControls) {
- t.hideControls();
- }
-
- // resizer
- if (t.options.enableAutosize) {
- t.media.addEventListener('loadedmetadata', function(e) {
- // if the <video height> was not set and the options.videoHeight was not set
- // then resize to the real dimensions
- if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) {
- t.setPlayerSize(e.target.videoWidth, e.target.videoHeight);
- t.setControlsSize();
- t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight);
- }
- }, false);
- }
- }
-
- // ended for all
- t.media.addEventListener('ended', function (e) {
- t.media.setCurrentTime(0);
- t.media.pause();
-
- if (t.setProgressRail)
- t.setProgressRail();
- if (t.setCurrentRail)
- t.setCurrentRail();
-
- if (t.options.loop) {
- t.media.play();
- } else if (!t.options.alwaysShowControls && t.controlsEnabled) {
- t.showControls();
- }
- }, true);
-
- // resize on the first play
- t.media.addEventListener('loadedmetadata', function(e) {
- if (t.updateDuration) {
- t.updateDuration();
- }
- if (t.updateCurrent) {
- t.updateCurrent();
- }
-
- t.setPlayerSize(t.width, t.height);
- t.setControlsSize();
- }, true);
-
-
- // webkit has trouble doing this without a delay
- setTimeout(function () {
- t.setPlayerSize(t.width, t.height);
- t.setControlsSize();
- }, 50);
-
- // adjust controls whenever window sizes (used to be in fullscreen only)
- $(window).resize(function() {
-
- // don't resize for fullscreen mode
- if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) {
- t.setPlayerSize(t.width, t.height);
- }
-
- // always adjust controls
- t.setControlsSize();
- });
-
- }
-
- // force autoplay for HTML5
- if (autoplay && media.pluginType == 'native') {
- media.load();
- media.play();
- }
-
-
- if (t.options.success) {
- t.options.success(t.media, t.domNode, t);
- }
- },
-
- handleError: function(e) {
- var t = this;
-
- t.controls.hide();
-
- // Tell user that the file cannot be played
- if (t.options.error) {
- t.options.error(e);
- }
- },
-
- setPlayerSize: function(width,height) {
- var t = this;
-
- // ie9 appears to need this (jQuery bug?)
- //t.width = parseInt(width, 10);
- //t.height = parseInt(height, 10);
-
- if (t.height.toString().indexOf('%') > 0) {
-
- // do we have the native dimensions yet?
- var
- nativeWidth = (t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth,
- nativeHeight = (t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight,
- parentWidth = t.container.parent().width(),
- newHeight = parseInt(parentWidth * nativeHeight/nativeWidth, 10);
-
- if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
- parentWidth = $(window).width();
- newHeight = $(window).height();
- }
-
-
- // set outer container size
- t.container
- .width(parentWidth)
- .height(newHeight);
-
- // set native <video>
- t.$media
- .width('100%')
- .height('100%');
-
- // set shims
- t.container.find('object embed')
- .width('100%')
- .height('100%');
-
- // if shim is ready, send the size to the embeded plugin
- if (t.media.setVideoSize)
- t.media.setVideoSize(parentWidth, newHeight);
-
- // set the layers
- t.layers.children('.mejs-layer')
- .width('100%')
- .height('100%');
-
-
- } else {
-
- t.container
- .width(t.width)
- .height(t.height);
-
- t.layers.children('.mejs-layer')
- .width(t.width)
- .height(t.height);
-
- }
- },
-
- setControlsSize: function() {
- var t = this,
- usedWidth = 0,
- railWidth = 0,
- rail = t.controls.find('.mejs-time-rail'),
- total = t.controls.find('.mejs-time-total'),
- current = t.controls.find('.mejs-time-current'),
- loaded = t.controls.find('.mejs-time-loaded');
- others = rail.siblings();
-
- // find the size of all the other controls besides the rail
- others.each(function() {
- if ($(this).css('position') != 'absolute') {
- usedWidth += $(this).outerWidth(true);
- }
- });
- // fit the rail into the remaining space
- railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.outerWidth(false));
-
- // outer area
- rail.width(railWidth);
- // dark space
- total.width(railWidth - (total.outerWidth(true) - total.width()));
-
- if (t.setProgressRail)
- t.setProgressRail();
- if (t.setCurrentRail)
- t.setCurrentRail();
- },
-
-
- buildposter: function(player, controls, layers, media) {
- var t = this,
- poster =
- $('<div class="mejs-poster mejs-layer">' +
- '</div>')
- .appendTo(layers),
- posterUrl = player.$media.attr('poster');
-
- // prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster)
- if (player.options.poster !== '') {
- posterUrl = player.options.poster;
- }
-
- // second, try the real poster
- if (posterUrl !== '' && posterUrl != null) {
- t.setPoster(posterUrl);
- } else {
- poster.hide();
- }
-
- media.addEventListener('play',function() {
- poster.hide();
- }, false);
- },
-
- setPoster: function(url) {
- var t = this,
- posterDiv = t.container.find('.mejs-poster'),
- posterImg = posterDiv.find('img');
-
- if (posterImg.length == 0) {
- posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv);
- }
-
- posterImg.attr('src', url);
- },
-
- buildoverlays: function(player, controls, layers, media) {
- if (!player.isVideo)
- return;
-
- var
- loading =
- $('<div class="mejs-overlay mejs-layer">'+
- '<div class="mejs-overlay-loading"><span></span></div>'+
- '</div>')
- .hide() // start out hidden
- .appendTo(layers),
- error =
- $('<div class="mejs-overlay mejs-layer">'+
- '<div class="mejs-overlay-error"></div>'+
- '</div>')
- .hide() // start out hidden
- .appendTo(layers),
-
- // this needs to come last so it's on top
- bigPlay =
- $('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+
- '<div class="mejs-overlay-button"></div>'+
- '</div>')
- .appendTo(layers)
- .click(function() {
- if (media.paused) {
- media.play();
- } else {
- media.pause();
- }
- });
-
- if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) {
- bigPlay.remove();
- loading.remove();
- }
-
-
- // show/hide big play button
- media.addEventListener('play',function() {
- bigPlay.hide();
- error.hide();
- }, false);
- media.addEventListener('pause',function() {
- bigPlay.show();
- }, false);
-
- // show/hide loading
- media.addEventListener('loadeddata',function() {
- // for some reason Chrome is firing this event
- //if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none')
- // return;
-
- loading.show();
- }, false);
- media.addEventListener('canplay',function() {
- loading.hide();
- }, false);
-
- // error handling
- media.addEventListener('error',function() {
- loading.hide();
- error.show();
- error.find('mejs-overlay-error').html("Error loading this resource");
- }, false);
- },
-
- findTracks: function() {
- var t = this,
- tracktags = t.$media.find('track');
-
- // store for use by plugins
- t.tracks = [];
- tracktags.each(function() {
- t.tracks.push({
- srclang: $(this).attr('srclang').toLowerCase(),
- src: $(this).attr('src'),
- kind: $(this).attr('kind'),
- entries: [],
- isLoaded: false
- });
- });
- },
- changeSkin: function(className) {
- this.container[0].className = 'mejs-container ' + className;
- this.setPlayerSize();
- this.setControlsSize();
- },
- play: function() {
- this.media.play();
- },
- pause: function() {
- this.media.pause();
- },
- load: function() {
- this.media.load();
- },
- setMuted: function(muted) {
- this.media.setMuted(muted);
- },
- setCurrentTime: function(time) {
- this.media.setCurrentTime(time);
- },
- getCurrentTime: function() {
- return this.media.currentTime;
- },
- setVolume: function(volume) {
- this.media.setVolume(volume);
- },
- getVolume: function() {
- return this.media.volume;
- },
- setSrc: function(src) {
- this.media.setSrc(src);
- }
- };
-
- // turn into jQuery plugin
- if (typeof jQuery != 'undefined') {
- jQuery.fn.mediaelementplayer = function (options) {
- return this.each(function () {
- new mejs.MediaElementPlayer(this, options);
- });
- };
- }
-
- // push out to window
- window.MediaElementPlayer = mejs.MediaElementPlayer;
-
+(function ($) {
+
+ // default player values
+ mejs.MepDefaults = {
+ // url to poster (to fix iOS 3.x)
+ poster: '',
+ // default if the <video width> is not specified
+ defaultVideoWidth: 480,
+ // default if the <video height> is not specified
+ defaultVideoHeight: 270,
+ // if set, overrides <video width>
+ videoWidth: -1,
+ // if set, overrides <video height>
+ videoHeight: -1,
+ // default if the user doesn't specify
+ defaultAudioWidth: 400,
+ // default if the user doesn't specify
+ defaultAudioHeight: 30,
+ // width of audio player
+ audioWidth: -1,
+ // height of audio player
+ audioHeight: -1,
+ // initial volume when the player starts (overrided by user cookie)
+ startVolume: 0.8,
+ // useful for <audio> player loops
+ loop: false,
+ // resize to media dimensions
+ enableAutosize: true,
+ // forces the hour marker (##:00:00)
+ alwaysShowHours: false,
+
+ // show framecount in timecode (##:00:00:00)
+ showTimecodeFrameCount: false,
+ // used when showTimecodeFrameCount is set to true
+ framesPerSecond: 25,
+
+ // automatically calculate the width of the progress bar based on the sizes of other elements
+ autosizeProgress : true,
+ // Hide controls when playing and mouse is not over the video
+ alwaysShowControls: false,
+ // force iPad's native controls
+ iPadUseNativeControls: false,
+ // force iPad's native controls
+ iPhoneUseNativeControls: false,
+ // force iPad's native controls
+ AndroidUseNativeControls: false,
+ // features to show
+ features: ['playpause','current','progress','duration','tracks','volume','fullscreen'],
+ // only for dynamic
+ isVideo: true,
+
+ // turns keyboard support on and off for this instance
+ enableKeyboard: true,
+
+ // whenthis player starts, it will pause other players
+ pauseOtherPlayers: true,
+
+ // array of keyboard actions such as play pause
+ keyActions: [
+ {
+ keys: [
+ 32, // SPACE
+ 179 // GOOGLE play/pause button
+ ],
+ action: function(player, media) {
+ if (media.paused || media.ended) {
+ media.play();
+ } else {
+ media.pause();
+ }
+ }
+ },
+ {
+ keys: [38], // UP
+ action: function(player, media) {
+ var newVolume = Math.min(media.volume + 0.1, 1);
+ media.setVolume(newVolume);
+ }
+ },
+ {
+ keys: [40], // DOWN
+ action: function(player, media) {
+ var newVolume = Math.max(media.volume - 0.1, 0);
+ media.setVolume(newVolume);
+ }
+ },
+ {
+ keys: [
+ 37, // LEFT
+ 227 // Google TV rewind
+ ],
+ action: function(player, media) {
+ if (!isNaN(media.duration) && media.duration > 0) {
+ if (player.isVideo) {
+ player.showControls();
+ player.startControlsTimer();
+ }
+
+ // 5%
+ var newTime = Math.min(media.currentTime - (media.duration * 0.05), media.duration);
+ media.setCurrentTime(newTime);
+ }
+ }
+ },
+ {
+ keys: [
+ 39, // RIGHT
+ 228 // Google TV forward
+ ],
+ action: function(player, media) {
+ if (!isNaN(media.duration) && media.duration > 0) {
+ if (player.isVideo) {
+ player.showControls();
+ player.startControlsTimer();
+ }
+
+ // 5%
+ var newTime = Math.max(media.currentTime + (media.duration * 0.05), 0);
+ media.setCurrentTime(newTime);
+ }
+ }
+ },
+ {
+ keys: [70], // f
+ action: function(player, media) {
+ if (typeof player.enterFullScreen != 'undefined') {
+ if (player.isFullScreen) {
+ player.exitFullScreen();
+ } else {
+ player.enterFullScreen();
+ }
+ }
+ }
+ }
+ ]
+ };
+
+ mejs.mepIndex = 0;
+
+ mejs.players = [];
+
+ // wraps a MediaElement object in player controls
+ mejs.MediaElementPlayer = function(node, o) {
+ // enforce object, even without "new" (via John Resig)
+ if ( !(this instanceof mejs.MediaElementPlayer) ) {
+ return new mejs.MediaElementPlayer(node, o);
+ }
+
+ var t = this;
+
+ // these will be reset after the MediaElement.success fires
+ t.$media = t.$node = $(node);
+ t.node = t.media = t.$media[0];
+
+ // check for existing player
+ if (typeof t.node.player != 'undefined') {
+ return t.node.player;
+ } else {
+ // attach player to DOM node for reference
+ t.node.player = t;
+ }
+
+
+ // try to get options from data-mejsoptions
+ if (typeof o == 'undefined') {
+ o = t.$node.data('mejsoptions');
+ }
+
+ // extend default options
+ t.options = $.extend({},mejs.MepDefaults,o);
+
+ // add to player array (for focus events)
+ mejs.players.push(t);
+
+ // start up
+ t.init();
+
+ return t;
+ };
+
+ // actual player
+ mejs.MediaElementPlayer.prototype = {
+
+ hasFocus: false,
+
+ controlsAreVisible: true,
+
+ init: function() {
+
+ var
+ t = this,
+ mf = mejs.MediaFeatures,
+ // options for MediaElement (shim)
+ meOptions = $.extend(true, {}, t.options, {
+ success: function(media, domNode) { t.meReady(media, domNode); },
+ error: function(e) { t.handleError(e);}
+ }),
+ tagName = t.media.tagName.toLowerCase();
+
+ t.isDynamic = (tagName !== 'audio' && tagName !== 'video');
+
+ if (t.isDynamic) {
+ // get video from src or href?
+ t.isVideo = t.options.isVideo;
+ } else {
+ t.isVideo = (tagName !== 'audio' && t.options.isVideo);
+ }
+
+ // use native controls in iPad, iPhone, and Android
+ if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) {
+
+ // add controls and stop
+ t.$media.attr('controls', 'controls');
+
+ // attempt to fix iOS 3 bug
+ t.$media.removeAttr('poster');
+
+ // override Apple's autoplay override for iPads
+ if (mf.isiPad && t.media.getAttribute('autoplay') !== null) {
+ t.media.load();
+ t.media.play();
+ }
+
+ } else if (mf.isAndroid && t.AndroidUseNativeControls) {
+
+ // leave default player
+
+ } else {
+
+ // DESKTOP: use MediaElementPlayer controls
+
+ // remove native controls
+ t.$media.removeAttr('controls');
+
+ // unique ID
+ t.id = 'mep_' + mejs.mepIndex++;
+
+ // build container
+ t.container =
+ $('<div id="' + t.id + '" class="mejs-container">'+
+ '<div class="mejs-inner">'+
+ '<div class="mejs-mediaelement"></div>'+
+ '<div class="mejs-layers"></div>'+
+ '<div class="mejs-controls"></div>'+
+ '<div class="mejs-clear"></div>'+
+ '</div>' +
+ '</div>')
+ .addClass(t.$media[0].className)
+ .insertBefore(t.$media);
+
+ // add classes for user and content
+ t.container.addClass(
+ (mf.isAndroid ? 'mejs-android ' : '') +
+ (mf.isiOS ? 'mejs-ios ' : '') +
+ (mf.isiPad ? 'mejs-ipad ' : '') +
+ (mf.isiPhone ? 'mejs-iphone ' : '') +
+ (t.isVideo ? 'mejs-video ' : 'mejs-audio ')
+ );
+
+
+ // move the <video/video> tag into the right spot
+ if (mf.isiOS) {
+
+ // sadly, you can't move nodes in iOS, so we have to destroy and recreate it!
+ var $newMedia = t.$media.clone();
+
+ t.container.find('.mejs-mediaelement').append($newMedia);
+
+ t.$media.remove();
+ t.$node = t.$media = $newMedia;
+ t.node = t.media = $newMedia[0]
+
+ } else {
+
+ // normal way of moving it into place (doesn't work on iOS)
+ t.container.find('.mejs-mediaelement').append(t.$media);
+ }
+
+ // find parts
+ t.controls = t.container.find('.mejs-controls');
+ t.layers = t.container.find('.mejs-layers');
+
+ // determine the size
+
+ /* size priority:
+ (1) videoWidth (forced),
+ (2) style="width;height;"
+ (3) width attribute,
+ (4) defaultVideoWidth (for unspecified cases)
+ */
+
+ var capsTagName = tagName.substring(0,1).toUpperCase() + tagName.substring(1);
+
+ if (t.options[tagName + 'Width'] > 0 || t.options[tagName + 'Width'].toString().indexOf('%') > -1) {
+ t.width = t.options[tagName + 'Width'];
+ } else if (t.media.style.width !== '' && t.media.style.width !== null) {
+ t.width = t.media.style.width;
+ } else if (t.media.getAttribute('width') !== null) {
+ t.width = t.$media.attr('width');
+ } else {
+ t.width = t.options['default' + capsTagName + 'Width'];
+ }
+
+ if (t.options[tagName + 'Height'] > 0 || t.options[tagName + 'Height'].toString().indexOf('%') > -1) {
+ t.height = t.options[tagName + 'Height'];
+ } else if (t.media.style.height !== '' && t.media.style.height !== null) {
+ t.height = t.media.style.height;
+ } else if (t.$media[0].getAttribute('height') !== null) {
+ t.height = t.$media.attr('height');
+ } else {
+ t.height = t.options['default' + capsTagName + 'Height'];
+ }
+
+ // set the size, while we wait for the plugins to load below
+ t.setPlayerSize(t.width, t.height);
+
+ // create MediaElementShim
+ meOptions.pluginWidth = t.height;
+ meOptions.pluginHeight = t.width;
+ }
+
+
+
+ // create MediaElement shim
+ mejs.MediaElement(t.$media[0], meOptions);
+ },
+
+ showControls: function(doAnimation) {
+ var t = this;
+
+ doAnimation = typeof doAnimation == 'undefined' || doAnimation;
+
+ if (t.controlsAreVisible)
+ return;
+
+ if (doAnimation) {
+ t.controls
+ .css('visibility','visible')
+ .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
+
+ // any additional controls people might add and want to hide
+ t.container.find('.mejs-control')
+ .css('visibility','visible')
+ .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
+
+ } else {
+ t.controls
+ .css('visibility','visible')
+ .css('display','block');
+
+ // any additional controls people might add and want to hide
+ t.container.find('.mejs-control')
+ .css('visibility','visible')
+ .css('display','block');
+
+ t.controlsAreVisible = true;
+ }
+
+ t.setControlsSize();
+
+ },
+
+ hideControls: function(doAnimation) {
+ var t = this;
+
+ doAnimation = typeof doAnimation == 'undefined' || doAnimation;
+
+ if (!t.controlsAreVisible)
+ return;
+
+ if (doAnimation) {
+ // fade out main controls
+ t.controls.stop(true, true).fadeOut(200, function() {
+ $(this)
+ .css('visibility','hidden')
+ .css('display','block');
+
+ t.controlsAreVisible = false;
+ });
+
+ // any additional controls people might add and want to hide
+ t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() {
+ $(this)
+ .css('visibility','hidden')
+ .css('display','block');
+ });
+ } else {
+
+ // hide main controls
+ t.controls
+ .css('visibility','hidden')
+ .css('display','block');
+
+ // hide others
+ t.container.find('.mejs-control')
+ .css('visibility','hidden')
+ .css('display','block');
+
+ t.controlsAreVisible = false;
+ }
+ },
+
+ controlsTimer: null,
+
+ startControlsTimer: function(timeout) {
+
+ var t = this;
+
+ timeout = typeof timeout != 'undefined' ? timeout : 1500;
+
+ t.killControlsTimer('start');
+
+ t.controlsTimer = setTimeout(function() {
+ //console.log('timer fired');
+ t.hideControls();
+ t.killControlsTimer('hide');
+ }, timeout);
+ },
+
+ killControlsTimer: function(src) {
+
+ var t = this;
+
+ if (t.controlsTimer !== null) {
+ clearTimeout(t.controlsTimer);
+ delete t.controlsTimer;
+ t.controlsTimer = null;
+ }
+ },
+
+ controlsEnabled: true,
+
+ disableControls: function() {
+ var t= this;
+
+ t.killControlsTimer();
+ t.hideControls(false);
+ this.controlsEnabled = false;
+ },
+
+ enableControls: function() {
+ var t= this;
+
+ t.showControls(false);
+
+ t.controlsEnabled = true;
+ },
+
+
+ // Sets up all controls and events
+ meReady: function(media, domNode) {
+
+
+ var t = this,
+ mf = mejs.MediaFeatures,
+ autoplayAttr = domNode.getAttribute('autoplay'),
+ autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'),
+ featureIndex,
+ feature;
+
+ // make sure it can't create itself again if a plugin reloads
+ if (t.created)
+ return;
+ else
+ t.created = true;
+
+ t.media = media;
+ t.domNode = domNode;
+
+ if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) {
+
+ // two built in features
+ t.buildposter(t, t.controls, t.layers, t.media);
+ t.buildkeyboard(t, t.controls, t.layers, t.media);
+ t.buildoverlays(t, t.controls, t.layers, t.media);
+
+ // grab for use by features
+ t.findTracks();
+
+ // add user-defined features/controls
+ for (featureIndex in t.options.features) {
+ feature = t.options.features[featureIndex];
+ if (t['build' + feature]) {
+ try {
+ t['build' + feature](t, t.controls, t.layers, t.media);
+ } catch (e) {
+ // TODO: report control error
+ //throw e;
+ //console.log('error building ' + feature);
+ //console.log(e);
+ }
+ }
+ }
+
+ t.container.trigger('controlsready');
+
+ // reset all layers and controls
+ t.setPlayerSize(t.width, t.height);
+ t.setControlsSize();
+
+
+ // controls fade
+ if (t.isVideo) {
+
+ if (mejs.MediaFeatures.hasTouch) {
+
+ // for touch devices (iOS, Android)
+ // show/hide without animation on touch
+
+ t.$media.bind('touchstart', function() {
+
+
+ // toggle controls
+ if (t.controlsAreVisible) {
+ t.hideControls(false);
+ } else {
+ if (t.controlsEnabled) {
+ t.showControls(false);
+ }
+ }
+ });
+
+ } else {
+ // click controls
+ var clickElement = (t.media.pluginType == 'native') ? t.$media : $(t.media.pluginElement);
+
+ // click to play/pause
+ clickElement.click(function() {
+ if (media.paused) {
+ media.play();
+ } else {
+ media.pause();
+ }
+ });
+
+
+ // show/hide controls
+ t.container
+ .bind('mouseenter mouseover', function () {
+ if (t.controlsEnabled) {
+ if (!t.options.alwaysShowControls) {
+ t.killControlsTimer('enter');
+ t.showControls();
+ t.startControlsTimer(2500);
+ }
+ }
+ })
+ .bind('mousemove', function() {
+ if (t.controlsEnabled) {
+ if (!t.controlsAreVisible) {
+ t.showControls();
+ }
+ //t.killControlsTimer('move');
+ if (!t.options.alwaysShowControls) {
+ t.startControlsTimer(2500);
+ }
+ }
+ })
+ .bind('mouseleave', function () {
+ if (t.controlsEnabled) {
+ if (!t.media.paused && !t.options.alwaysShowControls) {
+ t.startControlsTimer(1000);
+ }
+ }
+ });
+ }
+
+ // check for autoplay
+ if (autoplay && !t.options.alwaysShowControls) {
+ t.hideControls();
+ }
+
+ // resizer
+ if (t.options.enableAutosize) {
+ t.media.addEventListener('loadedmetadata', function(e) {
+ // if the <video height> was not set and the options.videoHeight was not set
+ // then resize to the real dimensions
+ if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) {
+ t.setPlayerSize(e.target.videoWidth, e.target.videoHeight);
+ t.setControlsSize();
+ t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight);
+ }
+ }, false);
+ }
+ }
+
+ // EVENTS
+
+ // FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them)
+ media.addEventListener('play', function() {
+
+ // go through all other players
+ for (var i=0, il=mejs.players.length; i<il; i++) {
+ var p = mejs.players[i];
+ if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) {
+ p.pause();
+ }
+ p.hasFocus = false;
+ }
+
+ t.hasFocus = true;
+ },false);
+
+
+ // ended for all
+ t.media.addEventListener('ended', function (e) {
+ try{
+ t.media.setCurrentTime(0);
+ } catch (exp) {
+
+ }
+ t.media.pause();
+
+ if (t.setProgressRail)
+ t.setProgressRail();
+ if (t.setCurrentRail)
+ t.setCurrentRail();
+
+ if (t.options.loop) {
+ t.media.play();
+ } else if (!t.options.alwaysShowControls && t.controlsEnabled) {
+ t.showControls();
+ }
+ }, false);
+
+ // resize on the first play
+ t.media.addEventListener('loadedmetadata', function(e) {
+ if (t.updateDuration) {
+ t.updateDuration();
+ }
+ if (t.updateCurrent) {
+ t.updateCurrent();
+ }
+
+ if (!t.isFullScreen) {
+ t.setPlayerSize(t.width, t.height);
+ t.setControlsSize();
+ }
+ }, false);
+
+
+ // webkit has trouble doing this without a delay
+ setTimeout(function () {
+ t.setPlayerSize(t.width, t.height);
+ t.setControlsSize();
+ }, 50);
+
+ // adjust controls whenever window sizes (used to be in fullscreen only)
+ $(window).resize(function() {
+
+ // don't resize for fullscreen mode
+ if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) {
+ t.setPlayerSize(t.width, t.height);
+ }
+
+ // always adjust controls
+ t.setControlsSize();
+ });
+
+ // TEMP: needs to be moved somewhere else
+ if (t.media.pluginType == 'youtube') {
+ t.container.find('.mejs-overlay-play').hide();
+ }
+ }
+
+ // force autoplay for HTML5
+ if (autoplay && media.pluginType == 'native') {
+ media.load();
+ media.play();
+ }
+
+
+ if (t.options.success) {
+
+ if (typeof t.options.success == 'string') {
+ window[t.options.success](t.media, t.domNode, t);
+ } else {
+ t.options.success(t.media, t.domNode, t);
+ }
+ }
+ },
+
+ handleError: function(e) {
+ var t = this;
+
+ t.controls.hide();
+
+ // Tell user that the file cannot be played
+ if (t.options.error) {
+ t.options.error(e);
+ }
+ },
+
+ setPlayerSize: function(width,height) {
+ var t = this;
+
+ // testing for 100% code
+ if (t.height.toString().indexOf('%') > 0) {
+
+ // do we have the native dimensions yet?
+ var
+ nativeWidth = (t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth,
+ nativeHeight = (t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight,
+ parentWidth = t.container.parent().width(),
+ newHeight = parseInt(parentWidth * nativeHeight/nativeWidth, 10);
+
+ if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
+ parentWidth = $(window).width();
+ newHeight = $(window).height();
+ }
+
+
+ // set outer container size
+ t.container
+ .width(parentWidth)
+ .height(newHeight);
+
+ // set native <video>
+ t.$media
+ .width('100%')
+ .height('100%');
+
+ // set shims
+ t.container.find('object, embed, iframe')
+ .width('100%')
+ .height('100%');
+
+ // if shim is ready, send the size to the embeded plugin
+ if (t.media.setVideoSize)
+ t.media.setVideoSize(parentWidth, newHeight);
+
+ // set the layers
+ t.layers.children('.mejs-layer')
+ .width('100%')
+ .height('100%');
+
+
+ } else {
+
+ t.container
+ .width(t.width)
+ .height(t.height);
+
+ t.layers.children('.mejs-layer')
+ .width(t.width)
+ .height(t.height);
+
+ }
+ },
+
+ setControlsSize: function() {
+ var t = this,
+ usedWidth = 0,
+ railWidth = 0,
+ rail = t.controls.find('.mejs-time-rail'),
+ total = t.controls.find('.mejs-time-total'),
+ current = t.controls.find('.mejs-time-current'),
+ loaded = t.controls.find('.mejs-time-loaded');
+ others = rail.siblings();
+
+
+ // allow the size to come from custom CSS
+ if (t.options && !t.options.autosizeProgress) {
+ // Also, frontends devs can be more flexible
+ // due the opportunity of absolute positioning.
+ railWidth = parseInt(rail.css('width'));
+ }
+
+ // attempt to autosize
+ if (railWidth === 0 || !railWidth) {
+
+ // find the size of all the other controls besides the rail
+ others.each(function() {
+ if ($(this).css('position') != 'absolute') {
+ usedWidth += $(this).outerWidth(true);
+ }
+ });
+
+ // fit the rail into the remaining space
+ railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.outerWidth(false));
+ }
+
+ // outer area
+ rail.width(railWidth);
+ // dark space
+ total.width(railWidth - (total.outerWidth(true) - total.width()));
+
+ if (t.setProgressRail)
+ t.setProgressRail();
+ if (t.setCurrentRail)
+ t.setCurrentRail();
+ },
+
+
+ buildposter: function(player, controls, layers, media) {
+ var t = this,
+ poster =
+ $('<div class="mejs-poster mejs-layer">' +
+ '</div>')
+ .appendTo(layers),
+ posterUrl = player.$media.attr('poster');
+
+ // prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster)
+ if (player.options.poster !== '') {
+ posterUrl = player.options.poster;
+ }
+
+ // second, try the real poster
+ if (posterUrl !== '' && posterUrl != null) {
+ t.setPoster(posterUrl);
+ } else {
+ poster.hide();
+ }
+
+ media.addEventListener('play',function() {
+ poster.hide();
+ }, false);
+ },
+
+ setPoster: function(url) {
+ var t = this,
+ posterDiv = t.container.find('.mejs-poster'),
+ posterImg = posterDiv.find('img');
+
+ if (posterImg.length == 0) {
+ posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv);
+ }
+
+ posterImg.attr('src', url);
+ },
+
+ buildoverlays: function(player, controls, layers, media) {
+ if (!player.isVideo)
+ return;
+
+ var
+ loading =
+ $('<div class="mejs-overlay mejs-layer">'+
+ '<div class="mejs-overlay-loading"><span></span></div>'+
+ '</div>')
+ .hide() // start out hidden
+ .appendTo(layers),
+ error =
+ $('<div class="mejs-overlay mejs-layer">'+
+ '<div class="mejs-overlay-error"></div>'+
+ '</div>')
+ .hide() // start out hidden
+ .appendTo(layers),
+
+ // this needs to come last so it's on top
+ bigPlay =
+ $('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+
+ '<div class="mejs-overlay-button"></div>'+
+ '</div>')
+ .appendTo(layers)
+ .click(function() {
+ if (media.paused) {
+ media.play();
+ } else {
+ media.pause();
+ }
+ });
+
+ /*
+ if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) {
+ bigPlay.remove();
+ loading.remove();