app/assets/javascripts/mediaelement_rails/mediaelement.js in mediaelement_rails-0.5.1 vs app/assets/javascripts/mediaelement_rails/mediaelement.js in mediaelement_rails-0.7.0
- old
+ new
@@ -5,20 +5,21 @@
*
* Creates a JavaScript object that mimics HTML5 MediaElement API
* for browsers that don't understand HTML5 or can't play the provided codec
* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
*
-* Copyright 2010-2012, John Dyer (http://j.hn)
+* Copyright 2010-2013, John Dyer (http://j.hn)
* License: MIT
*
*/
// Namespace
var mejs = mejs || {};
// version number
-mejs.version = '2.11.0';
+mejs.version = '2.13.2';
+
// player number (for missing, same id attr)
mejs.meIndex = 0;
// media types accepted by plugins
mejs.plugins = {
@@ -35,11 +36,10 @@
vimeo: [
{version: null, types: ['video/vimeo', 'video/x-vimeo']}
]
};
-
/*
Utility methods
*/
mejs.Utility = {
encodeUrl: function(url) {
@@ -55,31 +55,51 @@
},
getScriptPath: function(scriptNames) {
var
i = 0,
j,
- path = '',
- name = '',
- script,
+ codePath = '',
+ testname = '',
+ slashPos,
+ filenamePos,
+ scriptUrl,
+ scriptPath,
+ scriptFilename,
scripts = document.getElementsByTagName('script'),
il = scripts.length,
jl = scriptNames.length;
-
+
+ // go through all <script> tags
for (; i < il; i++) {
- script = scripts[i].src;
+ scriptUrl = scripts[i].src;
+ slashPos = scriptUrl.lastIndexOf('/');
+ if (slashPos > -1) {
+ scriptFilename = scriptUrl.substring(slashPos + 1);
+ scriptPath = scriptUrl.substring(0, slashPos + 1);
+ } else {
+ scriptFilename = scriptUrl;
+ scriptPath = '';
+ }
+
+ // see if any <script> tags have a file name that matches the
for (j = 0; j < jl; j++) {
- name = scriptNames[j];
- if (script.indexOf(name) > -1) {
- path = script.substring(0, script.indexOf(name));
+ testname = scriptNames[j];
+ filenamePos = scriptFilename.indexOf(testname);
+ if (filenamePos > -1) {
+ codePath = scriptPath;
break;
}
}
- if (path !== '') {
+
+ // if we found a path, then break and return it
+ if (codePath !== '') {
break;
}
}
- return path;
+
+ // send the best path back
+ return codePath;
},
secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
//add framecount
if (typeof showFrameCount == 'undefined') {
showFrameCount=false;
@@ -295,17 +315,18 @@
t.isiPad = (ua.match(/ipad/i) !== null);
t.isiPhone = (ua.match(/iphone/i) !== null);
t.isiOS = t.isiPhone || t.isiPad;
t.isAndroid = (ua.match(/android/i) !== null);
t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
- t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
+ t.isBustedNativeHTTPS = (location.protocol === 'https:' && (ua.match(/android [12]\./) !== null || ua.match(/macintosh.* version.* safari/) !== null));
+ t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1 || nav.appName.toLowerCase().match(/trident/gi) !== null);
t.isChrome = (ua.match(/chrome/gi) !== null);
t.isFirefox = (ua.match(/firefox/gi) !== null);
t.isWebkit = (ua.match(/webkit/gi) !== null);
- t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
+ t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit && !t.isIE;
t.isOpera = (ua.match(/opera/gi) !== null);
- t.hasTouch = ('ontouchstart' in window);
+ t.hasTouch = ('ontouchstart' in window); // && window.ontouchstart != null); // this breaks iOS 7
// borrowed from Modernizr
t.svg = !! document.createElementNS &&
!! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect;
@@ -314,56 +335,93 @@
v = document.createElement(html5Elements[i]);
}
t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid);
+ // Fix for IE9 on Windows 7N / Windows 7KN (Media Player not installer)
+ try{
+ v.canPlayType("video/mp4");
+ }catch(e){
+ t.supportsMediaTag = false;
+ }
+
// detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails)
// iOS
t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined');
- // Webkit/firefox
+ // W3C
+ t.hasNativeFullscreen = (typeof v.requestFullscreen !== 'undefined');
+
+ // webkit/firefox/IE11+
t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
+ t.hasMsNativeFullScreen = (typeof v.msRequestFullscreen !== 'undefined');
- t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen);
+ t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen || t.hasMsNativeFullScreen);
t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
+
+ // Enabled?
if (t.hasMozNativeFullScreen) {
- t.nativeFullScreenEnabled = v.mozFullScreenEnabled;
+ t.nativeFullScreenEnabled = document.mozFullScreenEnabled;
+ } else if (t.hasMsNativeFullScreen) {
+ t.nativeFullScreenEnabled = document.msFullscreenEnabled;
}
-
- if (this.isChrome) {
+ if (t.isChrome) {
t.hasSemiNativeFullScreen = false;
}
if (t.hasTrueNativeFullScreen) {
- t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange';
+ t.fullScreenEventName = '';
+ if (t.hasWebkitNativeFullScreen) {
+ t.fullScreenEventName = 'webkitfullscreenchange';
+
+ } else if (t.hasMozNativeFullScreen) {
+ t.fullScreenEventName = 'mozfullscreenchange';
+
+ } else if (t.hasMsNativeFullScreen) {
+ t.fullScreenEventName = 'MSFullscreenChange';
+ }
t.isFullScreen = function() {
if (v.mozRequestFullScreen) {
return d.mozFullScreen;
+
} else if (v.webkitRequestFullScreen) {
return d.webkitIsFullScreen;
+
+ } else if (v.hasMsNativeFullScreen) {
+ return d.msFullscreenElement !== null;
}
}
t.requestFullScreen = function(el) {
if (t.hasWebkitNativeFullScreen) {
el.webkitRequestFullScreen();
+
} else if (t.hasMozNativeFullScreen) {
el.mozRequestFullScreen();
+
+ } else if (t.hasMsNativeFullScreen) {
+ el.msRequestFullscreen();
+
}
}
t.cancelFullScreen = function() {
if (t.hasWebkitNativeFullScreen) {
document.webkitCancelFullScreen();
+
} else if (t.hasMozNativeFullScreen) {
document.mozCancelFullScreen();
+
+ } else if (t.hasMsNativeFullScreen) {
+ document.msExitFullscreen();
+
}
}
}
@@ -542,11 +600,11 @@
return '';
},
positionFullscreenButton: function(x,y,visibleAndAbove) {
if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
- this.pluginApi.positionFullscreenButton(x,y,visibleAndAbove);
+ this.pluginApi.positionFullscreenButton(Math.floor(x),Math.floor(y),visibleAndAbove);
}
},
hideFullscreenButton: function() {
if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
@@ -754,10 +812,14 @@
e,
i,
bufferedTime,
pluginMediaElement = this.pluginMediaElements[id];
+ if(!pluginMediaElement){
+ return;
+ }
+
// fake event object to mimic real HTML media event.
e = {
type: eventName,
target: pluginMediaElement
};
@@ -798,20 +860,26 @@
mode: 'auto',
// remove or reorder to change plugin priority and availability
plugins: ['flash','silverlight','youtube','vimeo'],
// shows debug errors on screen
enablePluginDebug: false,
+ // use plugin for browsers that have trouble with Basic Authentication on HTTPS sites
+ httpsBasicAuthSite: false,
// overrides the type specified, useful for dynamic instantiation
type: '',
// path to Flash and Silverlight plugins
pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
// name of flash file
flashName: 'flashmediaelement.swf',
// streamer for RTMP streaming
flashStreamer: '',
// turns on the smoothing filter in Flash
enablePluginSmoothing: false,
+ // enabled pseudo-streaming (seek) on .mp4 files
+ enablePseudoStreaming: false,
+ // start query parameter sent to server for pseudo-streaming
+ pseudoStreamingStartQueryParam: 'start',
// name of silverlight file
silverlightName: 'silverlightmediaelement.xap',
// default if the <video width> is not specified
defaultVideoWidth: 480,
// default if the <video height> is not specified
@@ -964,11 +1032,11 @@
};
}
// test for native playback first
- if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native')) {
+ if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native') && !(mejs.MediaFeatures.isBustedNativeHTTPS && options.httpsBasicAuthSite === true)) {
if (!isMediaTag) {
// create a real HTML5 Media Element
dummy = document.createElement( result.isVideo ? 'video' : 'audio');
@@ -1073,11 +1141,11 @@
}
},
getTypeFromFile: function(url) {
url = url.split('?')[0];
- var ext = url.substring(url.lastIndexOf('.') + 1);
+ var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext);
},
getTypeFromExtension: function(ext) {
@@ -1108,13 +1176,17 @@
try {
errorContainer.style.width = htmlMediaElement.width + 'px';
errorContainer.style.height = htmlMediaElement.height + 'px';
} catch (e) {}
- errorContainer.innerHTML = (poster !== '') ?
- '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
- '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>';
+ if (options.customError) {
+ errorContainer.innerHTML = options.customError;
+ } else {
+ errorContainer.innerHTML = (poster !== '') ?
+ '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
+ '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>';
+ }
htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
htmlMediaElement.style.display = 'none';
options.error(htmlMediaElement);
@@ -1152,12 +1224,12 @@
}
node = node.parentNode;
}
if (playback.isVideo) {
- width = (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
- height = (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
+ width = (options.pluginWidth > 0) ? options.pluginWidth : (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
+ height = (options.pluginHeight > 0) ? options.pluginHeight : (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
// in case of '%' make sure it's encoded
width = mejs.Utility.encodeUrl(width);
height = mejs.Utility.encodeUrl(height);
@@ -1190,11 +1262,12 @@
'preload=' + preload,
'width=' + width,
'startvolume=' + options.startVolume,
'timerrate=' + options.timerRate,
'flashstreamer=' + options.flashStreamer,
- 'height=' + height];
+ 'height=' + height,
+ 'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
if (playback.url !== null) {
if (playback.method == 'flash') {
initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
} else {
@@ -1205,10 +1278,13 @@
initVars.push('debug=true');
}
if (options.enablePluginSmoothing) {
initVars.push('smoothing=true');
}
+ if (options.enablePseudoStreaming) {
+ initVars.push('pseudostreaming=true');
+ }
if (controls) {
initVars.push('controls=true'); // shows controls in the plugin if desired
}
if (options.pluginVars) {
initVars = initVars.concat(options.pluginVars);
@@ -1240,10 +1316,11 @@
'<param name="quality" value="high" />' +
'<param name="bgcolor" value="#000000" />' +
'<param name="wmode" value="transparent" />' +
'<param name="allowScriptAccess" value="always" />' +
'<param name="allowFullScreen" value="true" />' +
+'<param name="scale" value="default" />' +
'</object>';
} else {
container.innerHTML =
@@ -1258,10 +1335,11 @@
'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
'src="' + options.pluginPath + options.flashName + '" ' +
'flashvars="' + initVars.join('&') + '" ' +
'width="' + width + '" ' +
'height="' + height + '" ' +
+'scale="default"' +
'class="mejs-shim"></embed>';
}
break;
case 'youtube':
@@ -1287,11 +1365,11 @@
break;
// DEMO Code. Does NOT work.
case 'vimeo':
- //console.log('vimeoid');
+ //
pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
container.innerHTML ='<iframe src="http://player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?portrait=0&byline=0&title=0" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim"></iframe>';
@@ -1308,10 +1386,12 @@
break;
}
// hide original element
htmlMediaElement.style.display = 'none';
+ // prevent browser from autoplaying when using a plugin
+ htmlMediaElement.removeAttribute('autoplay');
// FYI: options.success will be fired by the MediaPluginBridge
return pluginMediaElement;
},
@@ -1373,11 +1453,11 @@
isIframeStarted: false,
isIframeLoaded: false,
loadIframeApi: function() {
if (!this.isIframeStarted) {
var tag = document.createElement('script');
- tag.src = "http://www.youtube.com/player_api";
+ tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
this.isIframeStarted = true;
}
},
@@ -1491,11 +1571,11 @@
'<param name="wmode" value="transparent">' +
'</object>';
*/
var specialIEContainer,
- youtubeUrl = 'http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0';
+ youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0';
if (mejs.MediaFeatures.isIE) {
specialIEContainer = document.createElement('div');
settings.container.appendChild(specialIEContainer);
@@ -1590,81 +1670,74 @@
window.mejs = mejs;
window.MediaElement = mejs.MediaElement;
/*!
- * Adds Internationalization and localization to objects.
+ * Adds Internationalization and localization to mediaelement.
*
- * What is the concept beyond i18n?
- * http://en.wikipedia.org/wiki/Internationalization_and_localization
+ * This file does not contain translations, you have to add the manually.
+ * The schema is always the same: me-i18n-locale-[ISO_639-1 Code].js
*
+ * Examples are provided both for german and chinese translation.
*
- * This file both i18n methods and locale which is used to translate
- * strings into other languages.
*
- * Default translations are not available, you have to add them
- * through locale objects which are named exactly as the langcode
- * they stand for. The default language is always english (en).
+ * What is the concept beyond i18n?
+ * http://en.wikipedia.org/wiki/Internationalization_and_localization
*
+ * What langcode should i use?
+ * http://en.wikipedia.org/wiki/ISO_639-1
*
- * Wrapper built to be able to attach the i18n object to
- * other objects without changing more than one line.
*
+ * License?
*
- * LICENSE:
- *
* The i18n file uses methods from the Drupal project (drupal.js):
* - i18n.methods.t() (modified)
* - i18n.methods.checkPlain() (full copy)
- * - i18n.methods.formatString() (full copy)
*
* The Drupal project is (like mediaelementjs) licensed under GPLv2.
* - http://drupal.org/licensing/faq/#q1
* - https://github.com/johndyer/mediaelement
* - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
*
* @author
* Tim Latz (latz.tim@gmail.com)
*
- * @see
- * me-i18n-locale.js
*
* @params
- * - $ - zepto || jQuery ..
* - context - document, iframe ..
* - exports - CommonJS, window ..
*
*/
-;(function($, context, exports, undefined) {
+;(function(context, exports, undefined) {
"use strict";
var i18n = {
"locale": {
+ "language" : '',
"strings" : {}
},
"methods" : {}
};
// start i18n
/**
- * Get the current browser's language
- *
- * @see: i18n.methods.t()
+ * Get language, fallback to browser's language if empty
*/
- i18n.locale.getLanguage = function () {
- return {
- "language" : navigator.language
- };
+ i18n.getLanguage = function () {
+ var language = i18n.locale.language || window.navigator.userLanguage || window.navigator.language;
+ // convert to iso 639-1 (2-letters, lower case)
+ return language.substr(0, 2).toLowerCase();
};
- /**
- * Store the language the locale object was initialized with
- */
- i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage();
+ // i18n fixes for compatibility with WordPress
+ if ( typeof mejsL10n != 'undefined' ) {
+ i18n.locale.language = mejsL10n.language;
+ }
+
/**
* Encode special characters in a plain-text string for display as HTML.
*/
i18n.methods.checkPlain = function (str) {
var character, regex,
@@ -1683,115 +1756,81 @@
}
return str;
};
/**
- * Replace placeholders with sanitized values in a string.
- *
- * @param str
- * A string with placeholders.
- * @param args
- * An object of replacements pairs to make. Incidences of any key in this
- * array are replaced with the corresponding value. Based on the first
- * character of the key, the value is escaped and/or themed:
- * - !variable: inserted as is
- * - @variable: escape plain text to HTML (i18n.methods.checkPlain)
- * - %variable: escape text and theme as a placeholder for user-submitted
- * content (checkPlain + <em class="placeholder" > )
- *
- * @see i18n.methods.t()
- */
- i18n.methods.formatString = function(str, args) {
- // Transform arguments before inserting them.
- for (var key in args) {
- switch (key.charAt(0)) {
- // Escaped only.
- case '@':
- args[key] = i18n.methods.checkPlain(args[key]);
- break;
- // Pass-through.
- case '!':
- break;
- // Escaped and placeholder.
- case '%':
- default:
- args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>';
- break;
- }
- str = str.replace(key, args[key]);
- }
- return str;
- };
-
- /**
* Translate strings to the page language or a given language.
*
- * See the documentation of the server-side t() function for further details.
*
* @param str
* A string containing the English string to translate.
- * @param args
- * An object of replacements pairs to make after translation. Incidences
- * of any key in this array are replaced with the corresponding value.
- * See i18n.methods.formatString().
*
* @param options
* - 'context' (defaults to the default context): The context the source string
* belongs to.
*
* @return
- * The translated string.
+ * The translated string, escaped via i18n.methods.checkPlain()
*/
- i18n.methods.t = function (str, args, options) {
+ i18n.methods.t = function (str, options) {
// Fetch the localized version of the string.
if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) {
str = i18n.locale.strings[options.context][str];
}
- if (args) {
- str = i18n.methods.formatString(str, args);
- }
- return str;
+ return i18n.methods.checkPlain(str);
};
/**
* Wrapper for i18n.methods.t()
*
* @see i18n.methods.t()
* @throws InvalidArgumentException
*/
- i18n.t = function(str, args, options) {
+ i18n.t = function(str, options) {
if (typeof str === 'string' && str.length > 0) {
- // check every time due languge can change for
+ // check every time due language can change for
// different reasons (translation, lang switcher ..)
- var lang = i18n.locale.getLanguage();
+ var language = i18n.getLanguage();
options = options || {
- "context" : lang.language
+ "context" : language
};
- return i18n.methods.t(str, args, options);
+ return i18n.methods.t(str, options);
}
else {
throw {
"name" : 'InvalidArgumentException',
"message" : 'First argument is either not a string or empty.'
- }
+ };
}
};
// end i18n
exports.i18n = i18n;
-}(jQuery, document, mejs));
+}(document, mejs));
+
+// i18n fixes for compatibility with WordPress
+;(function(exports, undefined) {
+
+ "use strict";
+
+ if ( typeof mejsL10n != 'undefined' ) {
+ exports[mejsL10n.language] = mejsL10n.strings;
+ }
+
+}(mejs.i18n.locale.strings));
+
/*!
* This is a i18n.locale language object.
*
- *<de> German translation by Tim Latz, latz.tim@gmail.com
+ * German translation by Tim Latz, latz.tim@gmail.com
*
* @author
* Tim Latz (latz.tim@gmail.com)
*
* @see
@@ -1802,13 +1841,44 @@
*/
;(function(exports, undefined) {
"use strict";
- exports.de = {
- "Fullscreen" : "Vollbild",
- "Go Fullscreen" : "Vollbild an",
- "Turn off Fullscreen" : "Vollbild aus",
- "Close" : "Schließen"
- };
+ if (typeof exports.de === 'undefined') {
+ exports.de = {
+ "Fullscreen" : "Vollbild",
+ "Go Fullscreen" : "Vollbild an",
+ "Turn off Fullscreen" : "Vollbild aus",
+ "Close" : "Schließen"
+ };
+ }
}(mejs.i18n.locale.strings));
+/*!
+ * This is a i18n.locale language object.
+ *
+ * Traditional chinese translation by Tim Latz, latz.tim@gmail.com
+ *
+ * @author
+ * Tim Latz (latz.tim@gmail.com)
+ *
+ * @see
+ * me-i18n.js
+ *
+ * @params
+ * - exports - CommonJS, window ..
+ */
+;(function(exports, undefined) {
+
+ "use strict";
+
+ if (typeof exports.zh === 'undefined') {
+ exports.zh = {
+ "Fullscreen" : "全螢幕",
+ "Go Fullscreen" : "全屏模式",
+ "Turn off Fullscreen" : "退出全屏模式",
+ "Close" : "關閉"
+ };
+ }
+
+}(mejs.i18n.locale.strings));
+