Make WordPress Core

Changeset 23968


Ignore:
Timestamp:
04/11/2013 10:13:44 PM (12 years ago)
Author:
markjaquith
Message:

Update MediaElement.js to 2.11.1

Also get rid of its non-minified JS/CSS files.

props wonderboymusic, ocean90. fixes #24015.

Location:
trunk/wp-includes
Files:
2 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/js/mediaelement/mediaelement-and-player.js

    r23958 r23968  
    1111* License: MIT
    1212*
    13 */
    14 // Namespace
    15 var mejs = mejs || {};
    16 
    17 // version number
    18 mejs.version = '2.11.0';
    19 
    20 // player number (for missing, same id attr)
    21 mejs.meIndex = 0;
    22 
    23 // media types accepted by plugins
    24 mejs.plugins = {
    25     silverlight: [
    26         {version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
    27     ],
    28     flash: [
    29         {version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/rtmp','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg', 'video/youtube', 'video/x-youtube']}
    30         //,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
    31     ],
    32     youtube: [
    33         {version: null, types: ['video/youtube', 'video/x-youtube', 'audio/youtube', 'audio/x-youtube']}
    34     ],
    35     vimeo: [
    36         {version: null, types: ['video/vimeo', 'video/x-vimeo']}
    37     ]
    38 };
    39 
    40 
    41 /*
    42 Utility methods
    43 */
    44 mejs.Utility = {
    45     encodeUrl: function(url) {
    46         return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
    47     },
    48     escapeHTML: function(s) {
    49         return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
    50     },
    51     absolutizeUrl: function(url) {
    52         var el = document.createElement('div');
    53         el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
    54         return el.firstChild.href;
    55     },
    56     getScriptPath: function(scriptNames) {
    57         var
    58             i = 0,
    59             j,
    60             path = '',
    61             name = '',
    62             script,
    63             scripts = document.getElementsByTagName('script'),
    64             il = scripts.length,
    65             jl = scriptNames.length;
    66 
    67         for (; i < il; i++) {
    68             script = scripts[i].src;
    69             for (j = 0; j < jl; j++) {
    70                 name = scriptNames[j];
    71                 if (script.indexOf(name) > -1) {
    72                     path = script.substring(0, script.indexOf(name));
    73                     break;
    74                 }
    75             }
    76             if (path !== '') {
    77                 break;
    78             }
    79         }
    80         return path;
    81     },
    82     secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
    83         //add framecount
    84         if (typeof showFrameCount == 'undefined') {
    85             showFrameCount=false;
    86         } else if(typeof fps == 'undefined') {
    87             fps = 25;
    88         }
    89 
    90         var hours = Math.floor(time / 3600) % 24,
    91             minutes = Math.floor(time / 60) % 60,
    92             seconds = Math.floor(time % 60),
    93             frames = Math.floor(((time % 1)*fps).toFixed(3)),
    94             result =
    95                     ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
    96                         + (minutes < 10 ? '0' + minutes : minutes) + ':'
    97                         + (seconds < 10 ? '0' + seconds : seconds)
    98                         + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
    99 
    100         return result;
    101     },
    102 
    103     timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
    104         if (typeof showFrameCount == 'undefined') {
    105             showFrameCount=false;
    106         } else if(typeof fps == 'undefined') {
    107             fps = 25;
    108         }
    109 
    110         var tc_array = hh_mm_ss_ff.split(":"),
    111             tc_hh = parseInt(tc_array[0], 10),
    112             tc_mm = parseInt(tc_array[1], 10),
    113             tc_ss = parseInt(tc_array[2], 10),
    114             tc_ff = 0,
    115             tc_in_seconds = 0;
    116 
    117         if (showFrameCount) {
    118             tc_ff = parseInt(tc_array[3])/fps;
    119         }
    120 
    121         tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
    122 
    123         return tc_in_seconds;
    124     },
    125 
    126 
    127     convertSMPTEtoSeconds: function (SMPTE) {
    128         if (typeof SMPTE != 'string')
    129             return false;
    130 
    131         SMPTE = SMPTE.replace(',', '.');
    132 
    133         var secs = 0,
    134             decimalLen = (SMPTE.indexOf('.') != -1) ? SMPTE.split('.')[1].length : 0,
    135             multiplier = 1;
    136 
    137         SMPTE = SMPTE.split(':').reverse();
    138 
    139         for (var i = 0; i < SMPTE.length; i++) {
    140             multiplier = 1;
    141             if (i > 0) {
    142                 multiplier = Math.pow(60, i);
    143             }
    144             secs += Number(SMPTE[i]) * multiplier;
    145         }
    146         return Number(secs.toFixed(decimalLen));
    147     },
    148 
    149     /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
    150     removeSwf: function(id) {
    151         var obj = document.getElementById(id);
    152         if (obj && /object|embed/i.test(obj.nodeName)) {
    153             if (mejs.MediaFeatures.isIE) {
    154                 obj.style.display = "none";
    155                 (function(){
    156                     if (obj.readyState == 4) {
    157                         mejs.Utility.removeObjectInIE(id);
    158                     } else {
    159                         setTimeout(arguments.callee, 10);
    160                     }
    161                 })();
    162             } else {
    163                 obj.parentNode.removeChild(obj);
    164             }
    165         }
    166     },
    167     removeObjectInIE: function(id) {
    168         var obj = document.getElementById(id);
    169         if (obj) {
    170             for (var i in obj) {
    171                 if (typeof obj[i] == "function") {
    172                     obj[i] = null;
    173                 }
    174             }
    175             obj.parentNode.removeChild(obj);
    176         }
    177     }
    178 };
    179 
    180 
    181 // Core detector, plugins are added below
    182 mejs.PluginDetector = {
    183 
    184     // main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
    185     hasPluginVersion: function(plugin, v) {
    186         var pv = this.plugins[plugin];
    187         v[1] = v[1] || 0;
    188         v[2] = v[2] || 0;
    189         return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
    190     },
    191 
    192     // cached values
    193     nav: window.navigator,
    194     ua: window.navigator.userAgent.toLowerCase(),
    195 
    196     // stored version numbers
    197     plugins: [],
    198 
    199     // runs detectPlugin() and stores the version number
    200     addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
    201         this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
    202     },
    203 
    204     // get the version number from the mimetype (all but IE) or ActiveX (IE)
    205     detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
    206 
    207         var version = [0,0,0],
    208             description,
    209             i,
    210             ax;
    211 
    212         // Firefox, Webkit, Opera
    213         if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
    214             description = this.nav.plugins[pluginName].description;
    215             if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
    216                 version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
    217                 for (i=0; i<version.length; i++) {
    218                     version[i] = parseInt(version[i].match(/\d+/), 10);
    219                 }
    220             }
    221         // Internet Explorer / ActiveX
    222         } else if (typeof(window.ActiveXObject) != 'undefined') {
    223             try {
    224                 ax = new ActiveXObject(activeX);
    225                 if (ax) {
    226                     version = axDetect(ax);
    227                 }
    228             }
    229             catch (e) { }
    230         }
    231         return version;
    232     }
    233 };
    234 
    235 // Add Flash detection
    236 mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
    237     // adapted from SWFObject
    238     var version = [],
    239         d = ax.GetVariable("$version");
    240     if (d) {
    241         d = d.split(" ")[1].split(",");
    242         version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
    243     }
    244     return version;
    245 });
    246 
    247 // Add Silverlight detection
    248 mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
    249     // Silverlight cannot report its version number to IE
    250     // but it does have a isVersionSupported function, so we have to loop through it to get a version number.
    251     // adapted from http://www.silverlightversion.com/
    252     var v = [0,0,0,0],
    253         loopMatch = function(ax, v, i, n) {
    254             while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
    255                 v[i]+=n;
    256             }
    257             v[i] -= n;
    258         };
    259     loopMatch(ax, v, 0, 1);
    260     loopMatch(ax, v, 1, 1);
    261     loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
    262     loopMatch(ax, v, 2, 1000);
    263     loopMatch(ax, v, 2, 100);
    264     loopMatch(ax, v, 2, 10);
    265     loopMatch(ax, v, 2, 1);
    266     loopMatch(ax, v, 3, 1);
    267 
    268     return v;
    269 });
    270 // add adobe acrobat
    271 /*
    272 PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
    273     var version = [],
    274         d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
    275 
    276     if (d) {
    277         version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
    278     }
    279     return version;
    280 });
    281 */
    282 // necessary detection (fixes for <IE9)
    283 mejs.MediaFeatures = {
    284     init: function() {
    285         var
    286             t = this,
    287             d = document,
    288             nav = mejs.PluginDetector.nav,
    289             ua = mejs.PluginDetector.ua.toLowerCase(),
    290             i,
    291             v,
    292             html5Elements = ['source','track','audio','video'];
    293 
    294         // detect browsers (only the ones that have some kind of quirk we need to work around)
    295         t.isiPad = (ua.match(/ipad/i) !== null);
    296         t.isiPhone = (ua.match(/iphone/i) !== null);
    297         t.isiOS = t.isiPhone || t.isiPad;
    298         t.isAndroid = (ua.match(/android/i) !== null);
    299         t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
    300         t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
    301         t.isChrome = (ua.match(/chrome/gi) !== null);
    302         t.isFirefox = (ua.match(/firefox/gi) !== null);
    303         t.isWebkit = (ua.match(/webkit/gi) !== null);
    304         t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
    305         t.isOpera = (ua.match(/opera/gi) !== null);
    306         t.hasTouch = ('ontouchstart' in window);
    307 
    308         // borrowed from Modernizr
    309         t.svg = !! document.createElementNS &&
    310                 !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect;
    311 
    312         // create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
    313         for (i=0; i<html5Elements.length; i++) {
    314             v = document.createElement(html5Elements[i]);
    315         }
    316 
    317         t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid);
    318 
    319         // detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails)
    320 
    321         // iOS
    322         t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined');
    323 
    324         // Webkit/firefox
    325         t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
    326         t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
    327 
    328         t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen);
    329         t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
    330         if (t.hasMozNativeFullScreen) {
    331             t.nativeFullScreenEnabled = v.mozFullScreenEnabled;
    332         }
    333 
    334 
    335         if (this.isChrome) {
    336             t.hasSemiNativeFullScreen = false;
    337         }
    338 
    339         if (t.hasTrueNativeFullScreen) {
    340             t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange';
    341 
    342 
    343             t.isFullScreen = function() {
    344                 if (v.mozRequestFullScreen) {
    345                     return d.mozFullScreen;
    346                 } else if (v.webkitRequestFullScreen) {
    347                     return d.webkitIsFullScreen;
    348                 }
    349             }
    350 
    351             t.requestFullScreen = function(el) {
    352 
    353                 if (t.hasWebkitNativeFullScreen) {
    354                     el.webkitRequestFullScreen();
    355                 } else if (t.hasMozNativeFullScreen) {
    356                     el.mozRequestFullScreen();
    357                 }
    358             }
    359 
    360             t.cancelFullScreen = function() {
    361                 if (t.hasWebkitNativeFullScreen) {
    362                     document.webkitCancelFullScreen();
    363                 } else if (t.hasMozNativeFullScreen) {
    364                     document.mozCancelFullScreen();
    365                 }
    366             }
    367 
    368         }
    369 
    370 
    371         // OS X 10.5 can't do this even if it says it can :(
    372         if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) {
    373             t.hasNativeFullScreen = false;
    374             t.hasSemiNativeFullScreen = false;
    375         }
    376 
    377     }
    378 };
    379 mejs.MediaFeatures.init();
    380 
    381 /*
    382 extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
    383 */
    384 mejs.HtmlMediaElement = {
    385     pluginType: 'native',
    386     isFullScreen: false,
    387 
    388     setCurrentTime: function (time) {
    389         this.currentTime = time;
    390     },
    391 
    392     setMuted: function (muted) {
    393         this.muted = muted;
    394     },
    395 
    396     setVolume: function (volume) {
    397         this.volume = volume;
    398     },
    399 
    400     // for parity with the plugin versions
    401     stop: function () {
    402         this.pause();
    403     },
    404 
    405     // This can be a url string
    406     // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
    407     setSrc: function (url) {
    408 
    409         // Fix for IE9 which can't set .src when there are <source> elements. Awesome, right?
    410         var
    411             existingSources = this.getElementsByTagName('source');
    412         while (existingSources.length > 0){
    413             this.removeChild(existingSources[0]);
    414         }
    415 
    416         if (typeof url == 'string') {
    417             this.src = url;
    418         } else {
    419             var i, media;
    420 
    421             for (i=0; i<url.length; i++) {
    422                 media = url[i];
    423                 if (this.canPlayType(media.type)) {
    424                     this.src = media.src;
    425                     break;
    426                 }
    427             }
    428         }
    429     },
    430 
    431     setVideoSize: function (width, height) {
    432         this.width = width;
    433         this.height = height;
    434     }
    435 };
    436 
    437 /*
    438 Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
    439 */
    440 mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
    441     this.id = pluginid;
    442     this.pluginType = pluginType;
    443     this.src = mediaUrl;
    444     this.events = {};
    445     this.attributes = {};
    446 };
    447 
    448 // JavaScript values and ExternalInterface methods that match HTML5 video properties methods
    449 // http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
    450 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
    451 mejs.PluginMediaElement.prototype = {
    452 
    453     // special
    454     pluginElement: null,
    455     pluginType: '',
    456     isFullScreen: false,
    457 
    458     // not implemented :(
    459     playbackRate: -1,
    460     defaultPlaybackRate: -1,
    461     seekable: [],
    462     played: [],
    463 
    464     // HTML5 read-only properties
    465     paused: true,
    466     ended: false,
    467     seeking: false,
    468     duration: 0,
    469     error: null,
    470     tagName: '',
    471 
    472     // HTML5 get/set properties, but only set (updated by event handlers)
    473     muted: false,
    474     volume: 1,
    475     currentTime: 0,
    476 
    477     // HTML5 methods
    478     play: function () {
    479         if (this.pluginApi != null) {
    480             if (this.pluginType == 'youtube') {
    481                 this.pluginApi.playVideo();
    482             } else {
    483                 this.pluginApi.playMedia();
    484             }
    485             this.paused = false;
    486         }
    487     },
    488     load: function () {
    489         if (this.pluginApi != null) {
    490             if (this.pluginType == 'youtube') {
    491             } else {
    492                 this.pluginApi.loadMedia();
    493             }
    494 
    495             this.paused = false;
    496         }
    497     },
    498     pause: function () {
    499         if (this.pluginApi != null) {
    500             if (this.pluginType == 'youtube') {
    501                 this.pluginApi.pauseVideo();
    502             } else {
    503                 this.pluginApi.pauseMedia();
    504             }
    505 
    506 
    507             this.paused = true;
    508         }
    509     },
    510     stop: function () {
    511         if (this.pluginApi != null) {
    512             if (this.pluginType == 'youtube') {
    513                 this.pluginApi.stopVideo();
    514             } else {
    515                 this.pluginApi.stopMedia();
    516             }
    517             this.paused = true;
    518         }
    519     },
    520     canPlayType: function(type) {
    521         var i,
    522             j,
    523             pluginInfo,
    524             pluginVersions = mejs.plugins[this.pluginType];
    525 
    526         for (i=0; i<pluginVersions.length; i++) {
    527             pluginInfo = pluginVersions[i];
    528 
    529             // test if user has the correct plugin version
    530             if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
    531 
    532                 // test for plugin playback types
    533                 for (j=0; j<pluginInfo.types.length; j++) {
    534                     // find plugin that can play the type
    535                     if (type == pluginInfo.types[j]) {
    536                         return 'probably';
    537                     }
    538                 }
    539             }
    540         }
    541 
    542         return '';
    543     },
    544 
    545     positionFullscreenButton: function(x,y,visibleAndAbove) {
    546         if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
    547             this.pluginApi.positionFullscreenButton(x,y,visibleAndAbove);
    548         }
    549     },
    550 
    551     hideFullscreenButton: function() {
    552         if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
    553             this.pluginApi.hideFullscreenButton();
    554         }
    555     },
    556 
    557 
    558     // custom methods since not all JavaScript implementations support get/set
    559 
    560     // This can be a url string
    561     // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
    562     setSrc: function (url) {
    563         if (typeof url == 'string') {
    564             this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
    565             this.src = mejs.Utility.absolutizeUrl(url);
    566         } else {
    567             var i, media;
    568 
    569             for (i=0; i<url.length; i++) {
    570                 media = url[i];
    571                 if (this.canPlayType(media.type)) {
    572                     this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
    573                     this.src = mejs.Utility.absolutizeUrl(url);
    574                     break;
    575                 }
    576             }
    577         }
    578 
    579     },
    580     setCurrentTime: function (time) {
    581         if (this.pluginApi != null) {
    582             if (this.pluginType == 'youtube') {
    583                 this.pluginApi.seekTo(time);
    584             } else {
    585                 this.pluginApi.setCurrentTime(time);
    586             }
    587 
    588 
    589 
    590             this.currentTime = time;
    591         }
    592     },
    593     setVolume: function (volume) {
    594         if (this.pluginApi != null) {
    595             // same on YouTube and MEjs
    596             if (this.pluginType == 'youtube') {
    597                 this.pluginApi.setVolume(volume * 100);
    598             } else {
    599                 this.pluginApi.setVolume(volume);
    600             }
    601             this.volume = volume;
    602         }
    603     },
    604     setMuted: function (muted) {
    605         if (this.pluginApi != null) {
    606             if (this.pluginType == 'youtube') {
    607                 if (muted) {
    608                     this.pluginApi.mute();
    609                 } else {
    610                     this.pluginApi.unMute();
    611                 }
    612                 this.muted = muted;
    613                 this.dispatchEvent('volumechange');
    614             } else {
    615                 this.pluginApi.setMuted(muted);
    616             }
    617             this.muted = muted;
    618         }
    619     },
    620 
    621     // additional non-HTML5 methods
    622     setVideoSize: function (width, height) {
    623 
    624         //if (this.pluginType == 'flash' || this.pluginType == 'silverlight') {
    625             if ( this.pluginElement.style) {
    626                 this.pluginElement.style.width = width + 'px';
    627                 this.pluginElement.style.height = height + 'px';
    628             }
    629             if (this.pluginApi != null && this.pluginApi.setVideoSize) {
    630                 this.pluginApi.setVideoSize(width, height);
    631             }
    632         //}
    633     },
    634 
    635     setFullscreen: function (fullscreen) {
    636         if (this.pluginApi != null && this.pluginApi.setFullscreen) {
    637             this.pluginApi.setFullscreen(fullscreen);
    638         }
    639     },
    640 
    641     enterFullScreen: function() {
    642         if (this.pluginApi != null && this.pluginApi.setFullscreen) {
    643             this.setFullscreen(true);
    644         }
    645 
    646     },
    647 
    648     exitFullScreen: function() {
    649         if (this.pluginApi != null && this.pluginApi.setFullscreen) {
    650             this.setFullscreen(false);
    651         }
    652     },
    653 
    654     // start: fake events
    655     addEventListener: function (eventName, callback, bubble) {
    656         this.events[eventName] = this.events[eventName] || [];
    657         this.events[eventName].push(callback);
    658     },
    659     removeEventListener: function (eventName, callback) {
    660         if (!eventName) { this.events = {}; return true; }
    661         var callbacks = this.events[eventName];
    662         if (!callbacks) return true;
    663         if (!callback) { this.events[eventName] = []; return true; }
    664         for (i = 0; i < callbacks.length; i++) {
    665             if (callbacks[i] === callback) {
    666                 this.events[eventName].splice(i, 1);
    667                 return true;
    668             }
    669         }
    670         return false;
    671     },
    672     dispatchEvent: function (eventName) {
    673         var i,
    674             args,
    675             callbacks = this.events[eventName];
    676 
    677         if (callbacks) {
    678             args = Array.prototype.slice.call(arguments, 1);
    679             for (i = 0; i < callbacks.length; i++) {
    680                 callbacks[i].apply(null, args);
    681             }
    682         }
    683     },
    684     // end: fake events
    685 
    686     // fake DOM attribute methods
    687     hasAttribute: function(name){
    688         return (name in this.attributes);
    689     },
    690     removeAttribute: function(name){
    691         delete this.attributes[name];
    692     },
    693     getAttribute: function(name){
    694         if (this.hasAttribute(name)) {
    695             return this.attributes[name];
    696         }
    697         return '';
    698     },
    699     setAttribute: function(name, value){
    700         this.attributes[name] = value;
    701     },
    702 
    703     remove: function() {
    704         mejs.Utility.removeSwf(this.pluginElement.id);
    705         mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id);
    706     }
    707 };
    708 
    709 // Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
    710 mejs.MediaPluginBridge = {
    711 
    712     pluginMediaElements:{},
    713     htmlMediaElements:{},
    714 
    715     registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
    716         this.pluginMediaElements[id] = pluginMediaElement;
    717         this.htmlMediaElements[id] = htmlMediaElement;
    718     },
    719 
    720     unregisterPluginElement: function (id) {
    721         delete this.pluginMediaElements[id];
    722         delete this.htmlMediaElements[id];
    723     },
    724 
    725     // when Flash/Silverlight is ready, it calls out to this method
    726     initPlugin: function (id) {
    727 
    728         var pluginMediaElement = this.pluginMediaElements[id],
    729             htmlMediaElement = this.htmlMediaElements[id];
    730 
    731         if (pluginMediaElement) {
    732             // find the javascript bridge
    733             switch (pluginMediaElement.pluginType) {
    734                 case "flash":
    735                     pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
    736                     break;
    737                 case "silverlight":
    738                     pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
    739                     pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
    740                     break;
    741             }
    742 
    743             if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
    744                 pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
    745             }
    746         }
    747     },
    748 
    749     // receives events from Flash/Silverlight and sends them out as HTML5 media events
    750     // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
    751     fireEvent: function (id, eventName, values) {
    752 
    753         var
    754             e,
    755             i,
    756             bufferedTime,
    757             pluginMediaElement = this.pluginMediaElements[id];
    758 
    759         // fake event object to mimic real HTML media event.
    760         e = {
    761             type: eventName,
    762             target: pluginMediaElement
    763         };
    764 
    765         // attach all values to element and event object
    766         for (i in values) {
    767             pluginMediaElement[i] = values[i];
    768             e[i] = values[i];
    769         }
    770 
    771         // fake the newer W3C buffered TimeRange (loaded and total have been removed)
    772         bufferedTime = values.bufferedTime || 0;
    773 
    774         e.target.buffered = e.buffered = {
    775             start: function(index) {
    776                 return 0;
    777             },
    778             end: function (index) {
    779                 return bufferedTime;
    780             },
    781             length: 1
    782         };
    783 
    784         pluginMediaElement.dispatchEvent(e.type, e);
    785     }
    786 };
    787 
    788 /*
    789 Default options
    790 */
    791 mejs.MediaElementDefaults = {
    792     // allows testing on HTML5, flash, silverlight
    793     // auto: attempts to detect what the browser can do
    794     // auto_plugin: prefer plugins and then attempt native HTML5
    795     // native: forces HTML5 playback
    796     // shim: disallows HTML5, will attempt either Flash or Silverlight
    797     // none: forces fallback view
    798     mode: 'auto',
    799     // remove or reorder to change plugin priority and availability
    800     plugins: ['flash','silverlight','youtube','vimeo'],
    801     // shows debug errors on screen
    802     enablePluginDebug: false,
    803     // overrides the type specified, useful for dynamic instantiation
    804     type: '',
    805     // path to Flash and Silverlight plugins
    806     pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
    807     // name of flash file
    808     flashName: 'flashmediaelement.swf',
    809     // streamer for RTMP streaming
    810     flashStreamer: '',
    811     // turns on the smoothing filter in Flash
    812     enablePluginSmoothing: false,
    813     // name of silverlight file
    814     silverlightName: 'silverlightmediaelement.xap',
    815     // default if the <video width> is not specified
    816     defaultVideoWidth: 480,
    817     // default if the <video height> is not specified
    818     defaultVideoHeight: 270,
    819     // overrides <video width>
    820     pluginWidth: -1,
    821     // overrides <video height>
    822     pluginHeight: -1,
    823     // additional plugin variables in 'key=value' form
    824     pluginVars: [],
    825     // rate in milliseconds for Flash and Silverlight to fire the timeupdate event
    826     // larger number is less accurate, but less strain on plugin->JavaScript bridge
    827     timerRate: 250,
    828     // initial volume for player
    829     startVolume: 0.8,
    830     success: function () { },
    831     error: function () { }
    832 };
    833 
    834 /*
    835 Determines if a browser supports the <video> or <audio> element
    836 and returns either the native element or a Flash/Silverlight version that
    837 mimics HTML5 MediaElement
    838 */
    839 mejs.MediaElement = function (el, o) {
    840     return mejs.HtmlMediaElementShim.create(el,o);
    841 };
    842 
    843 mejs.HtmlMediaElementShim = {
    844 
    845     create: function(el, o) {
    846         var
    847             options = mejs.MediaElementDefaults,
    848             htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
    849             tagName = htmlMediaElement.tagName.toLowerCase(),
    850             isMediaTag = (tagName === 'audio' || tagName === 'video'),
    851             src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'),
    852             poster = htmlMediaElement.getAttribute('poster'),
    853             autoplay =  htmlMediaElement.getAttribute('autoplay'),
    854             preload =  htmlMediaElement.getAttribute('preload'),
    855             controls =  htmlMediaElement.getAttribute('controls'),
    856             playback,
    857             prop;
    858 
    859         // extend options
    860         for (prop in o) {
    861             options[prop] = o[prop];
    862         }
    863 
    864         // clean up attributes
    865         src =       (typeof src == 'undefined'  || src === null || src == '') ? null : src;
    866         poster =    (typeof poster == 'undefined'   || poster === null) ? '' : poster;
    867         preload =   (typeof preload == 'undefined'  || preload === null || preload === 'false') ? 'none' : preload;
    868         autoplay =  !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
    869         controls =  !(typeof controls == 'undefined' || controls === null || controls === 'false');
    870 
    871         // test for HTML5 and plugin capabilities
    872         playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
    873         playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
    874 
    875         if (playback.method == 'native') {
    876             // second fix for android
    877             if (mejs.MediaFeatures.isBustedAndroid) {
    878                 htmlMediaElement.src = playback.url;
    879                 htmlMediaElement.addEventListener('click', function() {
    880                     htmlMediaElement.play();
    881                 }, false);
    882             }
    883 
    884             // add methods to native HTMLMediaElement
    885             return this.updateNative(playback, options, autoplay, preload);
    886         } else if (playback.method !== '') {
    887             // create plugin to mimic HTMLMediaElement
    888 
    889             return this.createPlugin( playback,  options, poster, autoplay, preload, controls);
    890         } else {
    891             // boo, no HTML5, no Flash, no Silverlight.
    892             this.createErrorMessage( playback, options, poster );
    893 
    894             return this;
    895         }
    896     },
    897 
    898     determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) {
    899         var
    900             mediaFiles = [],
    901             i,
    902             j,
    903             k,
    904             l,
    905             n,
    906             type,
    907             result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
    908             pluginName,
    909             pluginVersions,
    910             pluginInfo,
    911             dummy,
    912             media;
    913 
    914         // STEP 1: Get URL and type from <video src> or <source src>
    915 
    916         // supplied type overrides <video type> and <source type>
    917         if (typeof options.type != 'undefined' && options.type !== '') {
    918 
    919             // accept either string or array of types
    920             if (typeof options.type == 'string') {
    921                 mediaFiles.push({type:options.type, url:src});
    922             } else {
    923 
    924                 for (i=0; i<options.type.length; i++) {
    925                     mediaFiles.push({type:options.type[i], url:src});
    926                 }
    927             }
    928 
    929         // test for src attribute first
    930         } else if (src !== null) {
    931             type = this.formatType(src, htmlMediaElement.getAttribute('type'));
    932             mediaFiles.push({type:type, url:src});
    933 
    934         // then test for <source> elements
    935         } else {
    936             // test <source> types to see if they are usable
    937             for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
    938                 n = htmlMediaElement.childNodes[i];
    939                 if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
    940                     src = n.getAttribute('src');
    941                     type = this.formatType(src, n.getAttribute('type'));
    942                     media = n.getAttribute('media');
    943 
    944                     if (!media || !window.matchMedia || (window.matchMedia && window.matchMedia(media).matches)) {
    945                         mediaFiles.push({type:type, url:src});
    946                     }
    947                 }
    948             }
    949         }
    950 
    951         // in the case of dynamicly created players
    952         // check for audio types
    953         if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) {
    954             result.isVideo = false;
    955         }
    956 
    957 
    958         // STEP 2: Test for playback method
    959 
    960         // special case for Android which sadly doesn't implement the canPlayType function (always returns '')
    961         if (mejs.MediaFeatures.isBustedAndroid) {
    962             htmlMediaElement.canPlayType = function(type) {
    963                 return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
    964             };
    965         }
    966 
    967 
    968         // test for native playback first
    969         if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native')) {
    970 
    971             if (!isMediaTag) {
    972 
    973                 // create a real HTML5 Media Element
    974                 dummy = document.createElement( result.isVideo ? 'video' : 'audio');
    975                 htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement);
    976                 htmlMediaElement.style.display = 'none';
    977 
    978                 // use this one from now on
    979                 result.htmlMediaElement = htmlMediaElement = dummy;
    980             }
    981 
    982             for (i=0; i<mediaFiles.length; i++) {
    983                 // normal check
    984                 if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
    985                     // special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
    986                     || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
    987                     result.method = 'native';
    988                     result.url = mediaFiles[i].url;
    989                     break;
    990                 }
    991             }
    992 
    993             if (result.method === 'native') {
    994                 if (result.url !== null) {
    995                     htmlMediaElement.src = result.url;
    996                 }
    997 
    998                 // if `auto_plugin` mode, then cache the native result but try plugins.
    999                 if (options.mode !== 'auto_plugin') {
    1000                     return result;
    1001                 }
    1002             }
    1003         }
    1004 
    1005         // if native playback didn't work, then test plugins
    1006         if (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'shim') {
    1007             for (i=0; i<mediaFiles.length; i++) {
    1008                 type = mediaFiles[i].type;
    1009 
    1010                 // test all plugins in order of preference [silverlight, flash]
    1011                 for (j=0; j<options.plugins.length; j++) {
    1012 
    1013                     pluginName = options.plugins[j];
    1014 
    1015                     // test version of plugin (for future features)
    1016                     pluginVersions = mejs.plugins[pluginName];
    1017 
    1018                     for (k=0; k<pluginVersions.length; k++) {
    1019                         pluginInfo = pluginVersions[k];
    1020 
    1021                         // test if user has the correct plugin version
    1022 
    1023                         // for youtube/vimeo
    1024                         if (pluginInfo.version == null ||
    1025 
    1026                             mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
    1027 
    1028                             // test for plugin playback types
    1029                             for (l=0; l<pluginInfo.types.length; l++) {
    1030                                 // find plugin that can play the type
    1031                                 if (type == pluginInfo.types[l]) {
    1032                                     result.method = pluginName;
    1033                                     result.url = mediaFiles[i].url;
    1034                                     return result;
    1035                                 }
    1036                             }
    1037                         }
    1038                     }
    1039                 }
    1040             }
    1041         }
    1042 
    1043         // at this point, being in 'auto_plugin' mode implies that we tried plugins but failed.
    1044         // if we have native support then return that.
    1045         if (options.mode === 'auto_plugin' && result.method === 'native') {
    1046             return result;
    1047         }
    1048 
    1049         // what if there's nothing to play? just grab the first available
    1050         if (result.method === '' && mediaFiles.length > 0) {
    1051             result.url = mediaFiles[0].url;
    1052         }
    1053 
    1054         return result;
    1055     },
    1056 
    1057     formatType: function(url, type) {
    1058         var ext;
    1059 
    1060         // if no type is supplied, fake it with the extension
    1061         if (url && !type) {
    1062             return this.getTypeFromFile(url);
    1063         } else {
    1064             // only return the mime part of the type in case the attribute contains the codec
    1065             // see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
    1066             // `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
    1067 
    1068             if (type && ~type.indexOf(';')) {
    1069                 return type.substr(0, type.indexOf(';'));
    1070             } else {
    1071                 return type;
    1072             }
    1073         }
    1074     },
    1075 
    1076     getTypeFromFile: function(url) {
    1077         url = url.split('?')[0];
    1078         var ext = url.substring(url.lastIndexOf('.') + 1);
    1079         return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext);
    1080     },
    1081 
    1082     getTypeFromExtension: function(ext) {
    1083 
    1084         switch (ext) {
    1085             case 'mp4':
    1086             case 'm4v':
    1087                 return 'mp4';
    1088             case 'webm':
    1089             case 'webma':
    1090             case 'webmv':
    1091                 return 'webm';
    1092             case 'ogg':
    1093             case 'oga':
    1094             case 'ogv':
    1095                 return 'ogg';
    1096             default:
    1097                 return ext;
    1098         }
    1099     },
    1100 
    1101     createErrorMessage: function(playback, options, poster) {
    1102         var
    1103             htmlMediaElement = playback.htmlMediaElement,
    1104             errorContainer = document.createElement('div');
    1105 
    1106         errorContainer.className = 'me-cannotplay';
    1107 
    1108         try {
    1109             errorContainer.style.width = htmlMediaElement.width + 'px';
    1110             errorContainer.style.height = htmlMediaElement.height + 'px';
    1111         } catch (e) {}
    1112 
    1113         errorContainer.innerHTML = (poster !== '') ?
    1114             '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
    1115             '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>';
    1116 
    1117         htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
    1118         htmlMediaElement.style.display = 'none';
    1119 
    1120         options.error(htmlMediaElement);
    1121     },
    1122 
    1123     createPlugin:function(playback, options, poster, autoplay, preload, controls) {
    1124         var
    1125             htmlMediaElement = playback.htmlMediaElement,
    1126             width = 1,
    1127             height = 1,
    1128             pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++),
    1129             pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url),
    1130             container = document.createElement('div'),
    1131             specialIEContainer,
    1132             node,
    1133             initVars;
    1134 
    1135         // copy tagName from html media element
    1136         pluginMediaElement.tagName = htmlMediaElement.tagName
    1137 
    1138         // copy attributes from html media element to plugin media element
    1139         for (var i = 0; i < htmlMediaElement.attributes.length; i++) {
    1140             var attribute = htmlMediaElement.attributes[i];
    1141             if (attribute.specified == true) {
    1142                 pluginMediaElement.setAttribute(attribute.name, attribute.value);
    1143             }
    1144         }
    1145 
    1146         // check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
    1147         node = htmlMediaElement.parentNode;
    1148         while (node !== null && node.tagName.toLowerCase() != 'body') {
    1149             if (node.parentNode.tagName.toLowerCase() == 'p') {
    1150                 node.parentNode.parentNode.insertBefore(node, node.parentNode);
    1151                 break;
    1152             }
    1153             node = node.parentNode;
    1154         }
    1155 
    1156         if (playback.isVideo) {
    1157             width = (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
    1158             height = (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
    1159 
    1160             // in case of '%' make sure it's encoded
    1161             width = mejs.Utility.encodeUrl(width);
    1162             height = mejs.Utility.encodeUrl(height);
    1163 
    1164         } else {
    1165             if (options.enablePluginDebug) {
    1166                 width = 320;
    1167                 height = 240;
    1168             }
    1169         }
    1170 
    1171         // register plugin
    1172         pluginMediaElement.success = options.success;
    1173         mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
    1174 
    1175         // add container (must be added to DOM before inserting HTML for IE)
    1176         container.className = 'me-plugin';
    1177         container.id = pluginid + '_container';
    1178 
    1179         if (playback.isVideo) {
    1180                 htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
    1181         } else {
    1182                 document.body.insertBefore(container, document.body.childNodes[0]);
    1183         }
    1184 
    1185         // flash/silverlight vars
    1186         initVars = [
    1187             'id=' + pluginid,
    1188             'isvideo=' + ((playback.isVideo) ? "true" : "false"),
    1189             'autoplay=' + ((autoplay) ? "true" : "false"),
    1190             'preload=' + preload,
    1191             'width=' + width,
    1192             'startvolume=' + options.startVolume,
    1193             'timerrate=' + options.timerRate,
    1194             'flashstreamer=' + options.flashStreamer,
    1195             'height=' + height];
    1196 
    1197         if (playback.url !== null) {
    1198             if (playback.method == 'flash') {
    1199                 initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
    1200             } else {
    1201                 initVars.push('file=' + playback.url);
    1202             }
    1203         }
    1204         if (options.enablePluginDebug) {
    1205             initVars.push('debug=true');
    1206         }
    1207         if (options.enablePluginSmoothing) {
    1208             initVars.push('smoothing=true');
    1209         }
    1210         if (controls) {
    1211             initVars.push('controls=true'); // shows controls in the plugin if desired
    1212         }
    1213         if (options.pluginVars) {
    1214             initVars = initVars.concat(options.pluginVars);
    1215         }
    1216 
    1217         switch (playback.method) {
    1218             case 'silverlight':
    1219                 container.innerHTML =
    1220 '<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
    1221 '<param name="initParams" value="' + initVars.join(',') + '" />' +
    1222 '<param name="windowless" value="true" />' +
    1223 '<param name="background" value="black" />' +
    1224 '<param name="minRuntimeVersion" value="3.0.0.0" />' +
    1225 '<param name="autoUpgrade" value="true" />' +
    1226 '<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
    1227 '</object>';
    1228                     break;
    1229 
    1230             case 'flash':
    1231 
    1232                 if (mejs.MediaFeatures.isIE) {
    1233                     specialIEContainer = document.createElement('div');
    1234                     container.appendChild(specialIEContainer);
    1235                     specialIEContainer.outerHTML =
    1236 '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
    1237 'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
    1238 '<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
    1239 '<param name="flashvars" value="' + initVars.join('&amp;') + '" />' +
    1240 '<param name="quality" value="high" />' +
    1241 '<param name="bgcolor" value="#000000" />' +
    1242 '<param name="wmode" value="transparent" />' +
    1243 '<param name="allowScriptAccess" value="always" />' +
    1244 '<param name="allowFullScreen" value="true" />' +
    1245 '</object>';
    1246 
    1247                 } else {
    1248 
    1249                     container.innerHTML =
    1250 '<embed id="' + pluginid + '" name="' + pluginid + '" ' +
    1251 'play="true" ' +
    1252 'loop="false" ' +
    1253 'quality="high" ' +
    1254 'bgcolor="#000000" ' +
    1255 'wmode="transparent" ' +
    1256 'allowScriptAccess="always" ' +
    1257 'allowFullScreen="true" ' +
    1258 'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
    1259 'src="' + options.pluginPath + options.flashName + '" ' +
    1260 'flashvars="' + initVars.join('&') + '" ' +
    1261 'width="' + width + '" ' +
    1262 'height="' + height + '" ' +
    1263 'class="mejs-shim"></embed>';
    1264                 }
    1265                 break;
    1266 
    1267             case 'youtube':
    1268 
    1269 
    1270                 var
    1271                     videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
    1272                     youtubeSettings = {
    1273                         container: container,
    1274                         containerId: container.id,
    1275                         pluginMediaElement: pluginMediaElement,
    1276                         pluginId: pluginid,
    1277                         videoId: videoId,
    1278                         height: height,
    1279                         width: width
    1280                     };
    1281 
    1282                 if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) {
    1283                     mejs.YouTubeApi.createFlash(youtubeSettings);
    1284                 } else {
    1285                     mejs.YouTubeApi.enqueueIframe(youtubeSettings);
    1286                 }
    1287 
    1288                 break;
    1289 
    1290             // DEMO Code. Does NOT work.
    1291             case 'vimeo':
    1292                 //console.log('vimeoid');
    1293 
    1294                 pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
    1295 
    1296                 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>';
    1297 
    1298                 /*
    1299                 container.innerHTML =
    1300                     '<object width="' + width + '" height="' + height + '" class="mejs-shim">' +
    1301                         '<param name="allowfullscreen" value="true" />' +
    1302                         '<param name="allowscriptaccess" value="always" />' +
    1303                         '<param name="flashvars" value="api=1" />' +
    1304                         '<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" />' +
    1305                         '<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 + '" class="mejs-shim"></embed>' +
    1306                     '</object>';
    1307                     */
    1308 
    1309                 break;
    1310         }
    1311         // hide original element
    1312         htmlMediaElement.style.display = 'none';
    1313 
    1314         // FYI: options.success will be fired by the MediaPluginBridge
    1315 
    1316         return pluginMediaElement;
    1317     },
    1318 
    1319     updateNative: function(playback, options, autoplay, preload) {
    1320 
    1321         var htmlMediaElement = playback.htmlMediaElement,
    1322             m;
    1323 
    1324 
    1325         // add methods to video object to bring it into parity with Flash Object
    1326         for (m in mejs.HtmlMediaElement) {
    1327             htmlMediaElement[m] = mejs.HtmlMediaElement[m];
    1328         }
    1329 
    1330         /*
    1331         Chrome now supports preload="none"
    1332         if (mejs.MediaFeatures.isChrome) {
    1333 
    1334             // special case to enforce preload attribute (Chrome doesn't respect this)
    1335             if (preload === 'none' && !autoplay) {
    1336 
    1337                 // forces the browser to stop loading (note: fails in IE9)
    1338                 htmlMediaElement.src = '';
    1339                 htmlMediaElement.load();
    1340                 htmlMediaElement.canceledPreload = true;
    1341 
    1342                 htmlMediaElement.addEventListener('play',function() {
    1343                     if (htmlMediaElement.canceledPreload) {
    1344                         htmlMediaElement.src = playback.url;
    1345                         htmlMediaElement.load();
    1346                         htmlMediaElement.play();
    1347                         htmlMediaElement.canceledPreload = false;
    1348                     }
    1349                 }, false);
    1350             // for some reason Chrome forgets how to autoplay sometimes.
    1351             } else if (autoplay) {
    1352                 htmlMediaElement.load();
    1353                 htmlMediaElement.play();
    1354             }
    1355         }
    1356         */
    1357 
    1358         // fire success code
    1359         options.success(htmlMediaElement, htmlMediaElement);
    1360 
    1361         return htmlMediaElement;
    1362     }
    1363 };
    1364 
    1365 /*
    1366  - test on IE (object vs. embed)
    1367  - determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE)
    1368  - fullscreen?
    1369 */
    1370 
    1371 // YouTube Flash and Iframe API
    1372 mejs.YouTubeApi = {
    1373     isIframeStarted: false,
    1374     isIframeLoaded: false,
    1375     loadIframeApi: function() {
    1376         if (!this.isIframeStarted) {
    1377             var tag = document.createElement('script');
    1378             tag.src = "http://www.youtube.com/player_api";
    1379             var firstScriptTag = document.getElementsByTagName('script')[0];
    1380             firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    1381             this.isIframeStarted = true;
    1382         }
    1383     },
    1384     iframeQueue: [],
    1385     enqueueIframe: function(yt) {
    1386 
    1387         if (this.isLoaded) {
    1388             this.createIframe(yt);
    1389         } else {
    1390             this.loadIframeApi();
    1391             this.iframeQueue.push(yt);
    1392         }
    1393     },
    1394     createIframe: function(settings) {
    1395 
    1396         var
    1397         pluginMediaElement = settings.pluginMediaElement,
    1398         player = new YT.Player(settings.containerId, {
    1399             height: settings.height,
    1400             width: settings.width,
    1401             videoId: settings.videoId,
    1402             playerVars: {controls:0},
    1403             events: {
    1404                 'onReady': function() {
    1405 
    1406                     // hook up iframe object to MEjs
    1407                     settings.pluginMediaElement.pluginApi = player;
    1408 
    1409                     // init mejs
    1410                     mejs.MediaPluginBridge.initPlugin(settings.pluginId);
    1411 
    1412                     // create timer
    1413                     setInterval(function() {
    1414                         mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
    1415                     }, 250);
    1416                 },
    1417                 'onStateChange': function(e) {
    1418 
    1419                     mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement);
    1420 
    1421                 }
    1422             }
    1423         });
    1424     },
    1425 
    1426     createEvent: function (player, pluginMediaElement, eventName) {
    1427         var obj = {
    1428             type: eventName,
    1429             target: pluginMediaElement
    1430         };
    1431 
    1432         if (player && player.getDuration) {
    1433 
    1434             // time
    1435             pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime();
    1436             pluginMediaElement.duration = obj.duration = player.getDuration();
    1437 
    1438             // state
    1439             obj.paused = pluginMediaElement.paused;
    1440             obj.ended = pluginMediaElement.ended;
    1441 
    1442             // sound
    1443             obj.muted = player.isMuted();
    1444             obj.volume = player.getVolume() / 100;
    1445 
    1446             // progress
    1447             obj.bytesTotal = player.getVideoBytesTotal();
    1448             obj.bufferedBytes = player.getVideoBytesLoaded();
    1449 
    1450             // fake the W3C buffered TimeRange
    1451             var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration;
    1452 
    1453             obj.target.buffered = obj.buffered = {
    1454                 start: function(index) {
    1455                     return 0;
    1456                 },
    1457                 end: function (index) {
    1458                     return bufferedTime;
    1459                 },
    1460                 length: 1
    1461             };
    1462 
    1463         }
    1464 
    1465         // send event up the chain
    1466         pluginMediaElement.dispatchEvent(obj.type, obj);
    1467     },
    1468 
    1469     iFrameReady: function() {
    1470 
    1471         this.isLoaded = true;
    1472         this.isIframeLoaded = true;
    1473 
    1474         while (this.iframeQueue.length > 0) {
    1475             var settings = this.iframeQueue.pop();
    1476             this.createIframe(settings);
    1477         }
    1478     },
    1479 
    1480     // FLASH!
    1481     flashPlayers: {},
    1482     createFlash: function(settings) {
    1483 
    1484         this.flashPlayers[settings.pluginId] = settings;
    1485 
    1486         /*
    1487         settings.container.innerHTML =
    1488             '<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" ' +
    1489                 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
    1490                 '<param name="allowScriptAccess" value="always">' +
    1491                 '<param name="wmode" value="transparent">' +
    1492             '</object>';
    1493         */
    1494 
    1495         var specialIEContainer,
    1496             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';
    1497 
    1498         if (mejs.MediaFeatures.isIE) {
    1499 
    1500             specialIEContainer = document.createElement('div');
    1501             settings.container.appendChild(specialIEContainer);
    1502             specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
    1503 'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' +
    1504     '<param name="movie" value="' + youtubeUrl + '" />' +
    1505     '<param name="wmode" value="transparent" />' +
    1506     '<param name="allowScriptAccess" value="always" />' +
    1507     '<param name="allowFullScreen" value="true" />' +
    1508 '</object>';
    1509         } else {
    1510         settings.container.innerHTML =
    1511             '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' +
    1512                 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
    1513                 '<param name="allowScriptAccess" value="always">' +
    1514                 '<param name="wmode" value="transparent">' +
    1515             '</object>';
    1516         }
    1517 
    1518     },
    1519 
    1520     flashReady: function(id) {
    1521         var
    1522             settings = this.flashPlayers[id],
    1523             player = document.getElementById(id),
    1524             pluginMediaElement = settings.pluginMediaElement;
    1525 
    1526         // hook up and return to MediaELementPlayer.success
    1527         pluginMediaElement.pluginApi =
    1528         pluginMediaElement.pluginElement = player;
    1529         mejs.MediaPluginBridge.initPlugin(id);
    1530 
    1531         // load the youtube video
    1532         player.cueVideoById(settings.videoId);
    1533 
    1534         var callbackName = settings.containerId + '_callback';
    1535 
    1536         window[callbackName] = function(e) {
    1537             mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
    1538         }
    1539 
    1540         player.addEventListener('onStateChange', callbackName);
    1541 
    1542         setInterval(function() {
    1543             mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
    1544         }, 250);
    1545     },
    1546 
    1547     handleStateChange: function(youTubeState, player, pluginMediaElement) {
    1548         switch (youTubeState) {
    1549             case -1: // not started
    1550                 pluginMediaElement.paused = true;
    1551                 pluginMediaElement.ended = true;
    1552                 mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata');
    1553                 //createYouTubeEvent(player, pluginMediaElement, 'loadeddata');
    1554                 break;
    1555             case 0:
    1556                 pluginMediaElement.paused = false;
    1557                 pluginMediaElement.ended = true;
    1558                 mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended');
    1559                 break;
    1560             case 1:
    1561                 pluginMediaElement.paused = false;
    1562                 pluginMediaElement.ended = false;
    1563                 mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play');
    1564                 mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing');
    1565                 break;
    1566             case 2:
    1567                 pluginMediaElement.paused = true;
    1568                 pluginMediaElement.ended = false;
    1569                 mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause');
    1570                 break;
    1571             case 3: // buffering
    1572                 mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress');
    1573                 break;
    1574             case 5:
    1575                 // cued?
    1576                 break;
    1577 
    1578         }
    1579 
    1580     }
    1581 }
    1582 // IFRAME
    1583 function onYouTubePlayerAPIReady() {
    1584     mejs.YouTubeApi.iFrameReady();
    1585 }
    1586 // FLASH
    1587 function onYouTubePlayerReady(id) {
    1588     mejs.YouTubeApi.flashReady(id);
    1589 }
    1590 
    1591 window.mejs = mejs;
    1592 window.MediaElement = mejs.MediaElement;
    1593 
    1594 /*!
    1595  * Adds Internationalization and localization to objects.
    1596  *
    1597  * What is the concept beyond i18n?
    1598  *   http://en.wikipedia.org/wiki/Internationalization_and_localization
    1599  *
    1600  *
    1601  * This file both i18n methods and locale which is used to translate
    1602  * strings into other languages.
    1603  *
    1604  * Default translations are not available, you have to add them
    1605  * through locale objects which are named exactly as the langcode
    1606  * they stand for. The default language is always english (en).
    1607  *
    1608  *
    1609  * Wrapper built to be able to attach the i18n object to
    1610  * other objects without changing more than one line.
    1611  *
    1612  *
    1613  * LICENSE:
    1614  *
    1615  *   The i18n file uses methods from the Drupal project (drupal.js):
    1616  *     - i18n.methods.t() (modified)
    1617  *     - i18n.methods.checkPlain() (full copy)
    1618  *     - i18n.methods.formatString() (full copy)
    1619  *
    1620  *   The Drupal project is (like mediaelementjs) licensed under GPLv2.
    1621  *    - http://drupal.org/licensing/faq/#q1
    1622  *    - https://github.com/johndyer/mediaelement
    1623  *    - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    1624  *
    1625  *
    1626  * @author
    1627  *   Tim Latz (latz.tim@gmail.com)
    1628  *
    1629  * @see
    1630  *   me-i18n-locale.js
    1631  *
    1632  * @params
    1633  *  - $       - zepto || jQuery  ..
    1634  *  - context - document, iframe ..
    1635  *  - exports - CommonJS, window ..
    1636  *
    1637  */
    1638 ;(function($, context, exports, undefined) {
    1639     "use strict";
    1640     var i18n = {
    1641         "locale": {
    1642             "strings" : {}
    1643         },
    1644         "methods" : {}
    1645     };
    1646 // start i18n
    1647 
    1648 
    1649     /**
    1650      * Get the current browser's language
    1651      *
    1652      * @see: i18n.methods.t()
    1653      */
    1654     i18n.locale.getLanguage = function () {
    1655         return {
    1656             "language" : navigator.language
    1657         };
    1658     };
    1659 
    1660     /**
    1661      * Store the language the locale object was initialized with
    1662      */
    1663     i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage();
    1664 
    1665 
    1666     /**
    1667      * Encode special characters in a plain-text string for display as HTML.
    1668      */
    1669     i18n.methods.checkPlain = function (str) {
    1670         var character, regex,
    1671         replace = {
    1672             '&': '&amp;',
    1673             '"': '&quot;',
    1674             '<': '&lt;',
    1675             '>': '&gt;'
    1676         };
    1677         str = String(str);
    1678         for (character in replace) {
    1679             if (replace.hasOwnProperty(character)) {
    1680                 regex = new RegExp(character, 'g');
    1681                 str = str.replace(regex, replace[character]);
    1682             }
    1683         }
    1684         return str;
    1685     };
    1686 
    1687     /**
    1688      * Replace placeholders with sanitized values in a string.
    1689      *
    1690      * @param str
    1691      *   A string with placeholders.
    1692      * @param args
    1693      *   An object of replacements pairs to make. Incidences of any key in this
    1694      *   array are replaced with the corresponding value. Based on the first
    1695      *   character of the key, the value is escaped and/or themed:
    1696      *    - !variable: inserted as is
    1697      *    - @variable: escape plain text to HTML (i18n.methods.checkPlain)
    1698      *    - %variable: escape text and theme as a placeholder for user-submitted
    1699      *      content (checkPlain + <em class="placeholder" > )
    1700      *
    1701      * @see i18n.methods.t()
    1702      */
    1703     i18n.methods.formatString = function(str, args) {
    1704         // Transform arguments before inserting them.
    1705         for (var key in args) {
    1706             switch (key.charAt(0)) {
    1707                 // Escaped only.
    1708                 case '@':
    1709                     args[key] = i18n.methods.checkPlain(args[key]);
    1710                     break;
    1711                 // Pass-through.
    1712                 case '!':
    1713                     break;
    1714                 // Escaped and placeholder.
    1715                 case '%':
    1716                 default:
    1717                     args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>';
    1718                     break;
    1719             }
    1720             str = str.replace(key, args[key]);
    1721         }
    1722         return str;
    1723     };
    1724 
    1725     /**
    1726      * Translate strings to the page language or a given language.
    1727      *
    1728      * See the documentation of the server-side t() function for further details.
    1729      *
    1730      * @param str
    1731      *   A string containing the English string to translate.
    1732      * @param args
    1733      *   An object of replacements pairs to make after translation. Incidences
    1734      *   of any key in this array are replaced with the corresponding value.
    1735      *   See i18n.methods.formatString().
    1736      *
    1737      * @param options
    1738      *   - 'context' (defaults to the default context): The context the source string
    1739      *     belongs to.
    1740      *
    1741      * @return
    1742      *   The translated string.
    1743      */
    1744     i18n.methods.t = function (str, args, options) {
    1745 
    1746         // Fetch the localized version of the string.
    1747         if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) {
    1748             str = i18n.locale.strings[options.context][str];
    1749         }
    1750 
    1751         if (args) {
    1752             str = i18n.methods.formatString(str, args);
    1753         }
    1754         return str;
    1755     };
    1756 
    1757 
    1758     /**
    1759      * Wrapper for i18n.methods.t()
    1760      *
    1761      * @see i18n.methods.t()
    1762      * @throws InvalidArgumentException
    1763      */
    1764     i18n.t = function(str, args, options) {
    1765 
    1766         if (typeof str === 'string' && str.length > 0) {
    1767 
    1768             // check every time due languge can change for
    1769             // different reasons (translation, lang switcher ..)
    1770             var lang = i18n.locale.getLanguage();
    1771 
    1772             options = options || {
    1773                 "context" : lang.language
    1774             };
    1775 
    1776             return i18n.methods.t(str, args, options);
    1777         }
    1778         else {
    1779             throw {
    1780                 "name" : 'InvalidArgumentException',
    1781                 "message" : 'First argument is either not a string or empty.'
    1782             }
    1783         }
    1784     };
    1785 
    1786 // end i18n
    1787     exports.i18n = i18n;
    1788 }(jQuery, document, mejs));
    1789 /*!
    1790  * This is a i18n.locale language object.
    1791  *
    1792  *<de> German translation by Tim Latz, latz.tim@gmail.com
    1793  *
    1794  * @author
    1795  *   Tim Latz (latz.tim@gmail.com)
    1796  *
    1797  * @see
    1798  *   me-i18n.js
    1799  *
    1800  * @params
    1801  *  - exports - CommonJS, window ..
    1802  */
    1803 ;(function(exports, undefined) {
    1804 
    1805     "use strict";
    1806 
    1807     exports.de = {
    1808         "Fullscreen" : "Vollbild",
    1809         "Go Fullscreen" : "Vollbild an",
    1810         "Turn off Fullscreen" : "Vollbild aus",
    1811         "Close" : "Schließen"
    1812     };
    1813 
    1814 }(mejs.i18n.locale.strings));
     13*/var mejs=mejs||{};mejs.version="2.11.1";mejs.meIndex=0;
     14mejs.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/rtmp","video/x-flv","audio/flv","audio/x-flv","audio/mp3","audio/m4a","audio/mpeg","video/youtube","video/x-youtube"]}],youtube:[{version:null,types:["video/youtube","video/x-youtube","audio/youtube","audio/x-youtube"]}],vimeo:[{version:null,types:["video/vimeo",
     15"video/x-vimeo"]}]};
     16mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&amp;").split("<").join("&lt;").split('"').join("&quot;")},absolutizeUrl:function(a){var b=document.createElement("div");b.innerHTML='<a href="'+this.escapeHTML(a)+'">x</a>';return b.firstChild.href},getScriptPath:function(a){for(var b=0,c,d="",e="",g,f,h=document.getElementsByTagName("script"),l=h.length,j=a.length;b<l;b++){f=h[b].src;for(c=0;c<j;c++){e=a[c];g=f.indexOf(e);
     17if(g>-1&&g==f.length-e.length){d=f.substring(0,g);break}}if(d!=="")break}return d},secondsToTimeCode:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;var e=Math.floor(a/3600)%24,g=Math.floor(a/60)%60,f=Math.floor(a%60);a=Math.floor((a%1*d).toFixed(3));return(b||e>0?(e<10?"0"+e:e)+":":"")+(g<10?"0"+g:g)+":"+(f<10?"0"+f:f)+(c?":"+(a<10?"0"+a:a):"")},timeCodeToSeconds:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;a=a.split(":");
     18b=parseInt(a[0],10);var e=parseInt(a[1],10),g=parseInt(a[2],10),f=0,h=0;if(c)f=parseInt(a[3])/d;return h=b*3600+e*60+g+f},convertSMPTEtoSeconds:function(a){if(typeof a!="string")return false;a=a.replace(",",".");var b=0,c=a.indexOf(".")!=-1?a.split(".")[1].length:0,d=1;a=a.split(":").reverse();for(var e=0;e<a.length;e++){d=1;if(e>0)d=Math.pow(60,e);b+=Number(a[e])*d}return Number(b.toFixed(c))},removeSwf:function(a){var b=document.getElementById(a);if(b&&/object|embed/i.test(b.nodeName))if(mejs.MediaFeatures.isIE){b.style.display=
     19"none";(function(){b.readyState==4?mejs.Utility.removeObjectInIE(a):setTimeout(arguments.callee,10)})()}else b.parentNode.removeChild(b)},removeObjectInIE:function(a){if(a=document.getElementById(a)){for(var b in a)if(typeof a[b]=="function")a[b]=null;a.parentNode.removeChild(a)}}};
     20mejs.PluginDetector={hasPluginVersion:function(a,b){var c=this.plugins[a];b[1]=b[1]||0;b[2]=b[2]||0;return c[0]>b[0]||c[0]==b[0]&&c[1]>b[1]||c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]?true:false},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(a,b,c,d,e){this.plugins[a]=this.detectPlugin(b,c,d,e)},detectPlugin:function(a,b,c,d){var e=[0,0,0],g;if(typeof this.nav.plugins!="undefined"&&typeof this.nav.plugins[a]=="object"){if((c=this.nav.plugins[a].description)&&
     21!(typeof this.nav.mimeTypes!="undefined"&&this.nav.mimeTypes[b]&&!this.nav.mimeTypes[b].enabledPlugin)){e=c.replace(a,"").replace(/^\s+/,"").replace(/\sr/gi,".").split(".");for(a=0;a<e.length;a++)e[a]=parseInt(e[a].match(/\d+/),10)}}else if(typeof window.ActiveXObject!="undefined")try{if(g=new ActiveXObject(c))e=d(g)}catch(f){}return e}};
     22mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(a){var b=[];if(a=a.GetVariable("$version")){a=a.split(" ")[1].split(",");b=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}return b});
     23mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(a){var b=[0,0,0,0],c=function(d,e,g,f){for(;d.isVersionSupported(e[0]+"."+e[1]+"."+e[2]+"."+e[3]);)e[g]+=f;e[g]-=f};c(a,b,0,1);c(a,b,1,1);c(a,b,2,1E4);c(a,b,2,1E3);c(a,b,2,100);c(a,b,2,10);c(a,b,2,1);c(a,b,3,1);return b});
     24mejs.MediaFeatures={init:function(){var a=this,b=document,c=mejs.PluginDetector.nav,d=mejs.PluginDetector.ua.toLowerCase(),e,g=["source","track","audio","video"];a.isiPad=d.match(/ipad/i)!==null;a.isiPhone=d.match(/iphone/i)!==null;a.isiOS=a.isiPhone||a.isiPad;a.isAndroid=d.match(/android/i)!==null;a.isBustedAndroid=d.match(/android 2\.[12]/)!==null;a.isIE=c.appName.toLowerCase().indexOf("microsoft")!=-1;a.isChrome=d.match(/chrome/gi)!==null;a.isFirefox=d.match(/firefox/gi)!==null;a.isWebkit=d.match(/webkit/gi)!==
     25null;a.isGecko=d.match(/gecko/gi)!==null&&!a.isWebkit;a.isOpera=d.match(/opera/gi)!==null;a.hasTouch="ontouchstart"in window;a.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect;for(c=0;c<g.length;c++)e=document.createElement(g[c]);a.supportsMediaTag=typeof e.canPlayType!=="undefined"||a.isBustedAndroid;a.hasSemiNativeFullScreen=typeof e.webkitEnterFullscreen!=="undefined";a.hasWebkitNativeFullScreen=typeof e.webkitRequestFullScreen!=="undefined";
     26a.hasMozNativeFullScreen=typeof e.mozRequestFullScreen!=="undefined";a.hasTrueNativeFullScreen=a.hasWebkitNativeFullScreen||a.hasMozNativeFullScreen;a.nativeFullScreenEnabled=a.hasTrueNativeFullScreen;if(a.hasMozNativeFullScreen)a.nativeFullScreenEnabled=e.mozFullScreenEnabled;if(this.isChrome)a.hasSemiNativeFullScreen=false;if(a.hasTrueNativeFullScreen){a.fullScreenEventName=a.hasWebkitNativeFullScreen?"webkitfullscreenchange":"mozfullscreenchange";a.isFullScreen=function(){if(e.mozRequestFullScreen)return b.mozFullScreen;
     27else if(e.webkitRequestFullScreen)return b.webkitIsFullScreen};a.requestFullScreen=function(f){if(a.hasWebkitNativeFullScreen)f.webkitRequestFullScreen();else a.hasMozNativeFullScreen&&f.mozRequestFullScreen()};a.cancelFullScreen=function(){if(a.hasWebkitNativeFullScreen)document.webkitCancelFullScreen();else a.hasMozNativeFullScreen&&document.mozCancelFullScreen()}}if(a.hasSemiNativeFullScreen&&d.match(/mac os x 10_5/i)){a.hasNativeFullScreen=false;a.hasSemiNativeFullScreen=false}}};mejs.MediaFeatures.init();
     28mejs.HtmlMediaElement={pluginType:"native",isFullScreen:false,setCurrentTime:function(a){this.currentTime=a},setMuted:function(a){this.muted=a},setVolume:function(a){this.volume=a},stop:function(){this.pause()},setSrc:function(a){for(var b=this.getElementsByTagName("source");b.length>0;)this.removeChild(b[0]);if(typeof a=="string")this.src=a;else{var c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.src=c.src;break}}}},setVideoSize:function(a,b){this.width=a;this.height=b}};
     29mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={};this.attributes={}};
     30mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:false,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:true,ended:false,seeking:false,duration:0,error:null,tagName:"",muted:false,volume:1,currentTime:0,play:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.playVideo():this.pluginApi.playMedia();this.paused=false}},load:function(){if(this.pluginApi!=null){this.pluginType!="youtube"&&this.pluginApi.loadMedia();this.paused=
     31false}},pause:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia();this.paused=true}},stop:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.stopVideo():this.pluginApi.stopMedia();this.paused=true}},canPlayType:function(a){var b,c,d,e=mejs.plugins[this.pluginType];for(b=0;b<e.length;b++){d=e[b];if(mejs.PluginDetector.hasPluginVersion(this.pluginType,d.version))for(c=0;c<d.types.length;c++)if(a==d.types[c])return"probably"}return""},
     32positionFullscreenButton:function(a,b,c){this.pluginApi!=null&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(a,b,c)},hideFullscreenButton:function(){this.pluginApi!=null&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(a){if(typeof a=="string"){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(a));this.src=mejs.Utility.absolutizeUrl(a)}else{var b,c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c.src));
     33this.src=mejs.Utility.absolutizeUrl(a);break}}}},setCurrentTime:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.seekTo(a):this.pluginApi.setCurrentTime(a);this.currentTime=a}},setVolume:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.setVolume(a*100):this.pluginApi.setVolume(a);this.volume=a}},setMuted:function(a){if(this.pluginApi!=null){if(this.pluginType=="youtube"){a?this.pluginApi.mute():this.pluginApi.unMute();this.muted=a;this.dispatchEvent("volumechange")}else this.pluginApi.setMuted(a);
     34this.muted=a}},setVideoSize:function(a,b){if(this.pluginElement.style){this.pluginElement.style.width=a+"px";this.pluginElement.style.height=b+"px"}this.pluginApi!=null&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(a,b)},setFullscreen:function(a){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(a)},enterFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(true)},exitFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&
     35this.setFullscreen(false)},addEventListener:function(a,b){this.events[a]=this.events[a]||[];this.events[a].push(b)},removeEventListener:function(a,b){if(!a){this.events={};return true}var c=this.events[a];if(!c)return true;if(!b){this.events[a]=[];return true}for(i=0;i<c.length;i++)if(c[i]===b){this.events[a].splice(i,1);return true}return false},dispatchEvent:function(a){var b,c,d=this.events[a];if(d){c=Array.prototype.slice.call(arguments,1);for(b=0;b<d.length;b++)d[b].apply(null,c)}},hasAttribute:function(a){return a in
     36this.attributes},removeAttribute:function(a){delete this.attributes[a]},getAttribute:function(a){if(this.hasAttribute(a))return this.attributes[a];return""},setAttribute:function(a,b){this.attributes[a]=b},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id);mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id)}};
     37mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(a,b,c){this.pluginMediaElements[a]=b;this.htmlMediaElements[a]=c},unregisterPluginElement:function(a){delete this.pluginMediaElements[a];delete this.htmlMediaElements[a]},initPlugin:function(a){var b=this.pluginMediaElements[a],c=this.htmlMediaElements[a];if(b){switch(b.pluginType){case "flash":b.pluginElement=b.pluginApi=document.getElementById(a);break;case "silverlight":b.pluginElement=document.getElementById(b.id);
     38b.pluginApi=b.pluginElement.Content.MediaElementJS}b.pluginApi!=null&&b.success&&b.success(b,c)}},fireEvent:function(a,b,c){var d,e;a=this.pluginMediaElements[a];b={type:b,target:a};for(d in c){a[d]=c[d];b[d]=c[d]}e=c.bufferedTime||0;b.target.buffered=b.buffered={start:function(){return 0},end:function(){return e},length:1};a.dispatchEvent(b.type,b)}};
     39mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:false,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",flashStreamer:"",enablePluginSmoothing:false,enablePseudoStreaming:false,pseudoStreamingStartQueryParam:"start",silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480,defaultVideoHeight:270,
     40pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)};
     41mejs.HtmlMediaElementShim={create:function(a,b){var c=mejs.MediaElementDefaults,d=typeof a=="string"?document.getElementById(a):a,e=d.tagName.toLowerCase(),g=e==="audio"||e==="video",f=g?d.getAttribute("src"):d.getAttribute("href");e=d.getAttribute("poster");var h=d.getAttribute("autoplay"),l=d.getAttribute("preload"),j=d.getAttribute("controls"),k;for(k in b)c[k]=b[k];f=typeof f=="undefined"||f===null||f==""?null:f;e=typeof e=="undefined"||e===null?"":e;l=typeof l=="undefined"||l===null||l==="false"?
     42"none":l;h=!(typeof h=="undefined"||h===null||h==="false");j=!(typeof j=="undefined"||j===null||j==="false");k=this.determinePlayback(d,c,mejs.MediaFeatures.supportsMediaTag,g,f);k.url=k.url!==null?mejs.Utility.absolutizeUrl(k.url):"";if(k.method=="native"){if(mejs.MediaFeatures.isBustedAndroid){d.src=k.url;d.addEventListener("click",function(){d.play()},false)}return this.updateNative(k,c,h,l)}else if(k.method!=="")return this.createPlugin(k,c,e,h,l,j);else{this.createErrorMessage(k,c,e);return this}},
     43determinePlayback:function(a,b,c,d,e){var g=[],f,h,l,j={method:"",url:"",htmlMediaElement:a,isVideo:a.tagName.toLowerCase()!="audio"},k;if(typeof b.type!="undefined"&&b.type!=="")if(typeof b.type=="string")g.push({type:b.type,url:e});else for(f=0;f<b.type.length;f++)g.push({type:b.type[f],url:e});else if(e!==null){l=this.formatType(e,a.getAttribute("type"));g.push({type:l,url:e})}else for(f=0;f<a.childNodes.length;f++){h=a.childNodes[f];if(h.nodeType==1&&h.tagName.toLowerCase()=="source"){e=h.getAttribute("src");
     44l=this.formatType(e,h.getAttribute("type"));h=h.getAttribute("media");if(!h||!window.matchMedia||window.matchMedia&&window.matchMedia(h).matches)g.push({type:l,url:e})}}if(!d&&g.length>0&&g[0].url!==null&&this.getTypeFromFile(g[0].url).indexOf("audio")>-1)j.isVideo=false;if(mejs.MediaFeatures.isBustedAndroid)a.canPlayType=function(m){return m.match(/video\/(mp4|m4v)/gi)!==null?"maybe":""};if(c&&(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="native")){if(!d){f=document.createElement(j.isVideo?
     45"video":"audio");a.parentNode.insertBefore(f,a);a.style.display="none";j.htmlMediaElement=a=f}for(f=0;f<g.length;f++)if(a.canPlayType(g[f].type).replace(/no/,"")!==""||a.canPlayType(g[f].type.replace(/mp3/,"mpeg")).replace(/no/,"")!==""){j.method="native";j.url=g[f].url;break}if(j.method==="native"){if(j.url!==null)a.src=j.url;if(b.mode!=="auto_plugin")return j}}if(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="shim")for(f=0;f<g.length;f++){l=g[f].type;for(a=0;a<b.plugins.length;a++){e=b.plugins[a];
     46h=mejs.plugins[e];for(c=0;c<h.length;c++){k=h[c];if(k.version==null||mejs.PluginDetector.hasPluginVersion(e,k.version))for(d=0;d<k.types.length;d++)if(l==k.types[d]){j.method=e;j.url=g[f].url;return j}}}}if(b.mode==="auto_plugin"&&j.method==="native")return j;if(j.method===""&&g.length>0)j.url=g[0].url;return j},formatType:function(a,b){return a&&!b?this.getTypeFromFile(a):b&&~b.indexOf(";")?b.substr(0,b.indexOf(";")):b},getTypeFromFile:function(a){a=a.split("?")[0];a=a.substring(a.lastIndexOf(".")+
     471).toLowerCase();return(/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(a)?"video":"audio")+"/"+this.getTypeFromExtension(a)},getTypeFromExtension:function(a){switch(a){case "mp4":case "m4v":return"mp4";case "webm":case "webma":case "webmv":return"webm";case "ogg":case "oga":case "ogv":return"ogg";default:return a}},createErrorMessage:function(a,b,c){var d=a.htmlMediaElement,e=document.createElement("div");e.className="me-cannotplay";try{e.style.width=d.width+"px";e.style.height=d.height+"px"}catch(g){}e.innerHTML=
     48c!==""?'<a href="'+a.url+'"><img src="'+c+'" width="100%" height="100%" /></a>':'<a href="'+a.url+'"><span>'+mejs.i18n.t("Download File")+"</span></a>";d.parentNode.insertBefore(e,d);d.style.display="none";b.error(d)},createPlugin:function(a,b,c,d,e,g){c=a.htmlMediaElement;var f=1,h=1,l="me_"+a.method+"_"+mejs.meIndex++,j=new mejs.PluginMediaElement(l,a.method,a.url),k=document.createElement("div"),m;j.tagName=c.tagName;for(m=0;m<c.attributes.length;m++){var n=c.attributes[m];n.specified==true&&j.setAttribute(n.name,
     49n.value)}for(m=c.parentNode;m!==null&&m.tagName.toLowerCase()!="body";){if(m.parentNode.tagName.toLowerCase()=="p"){m.parentNode.parentNode.insertBefore(m,m.parentNode);break}m=m.parentNode}if(a.isVideo){f=b.videoWidth>0?b.videoWidth:c.getAttribute("width")!==null?c.getAttribute("width"):b.defaultVideoWidth;h=b.videoHeight>0?b.videoHeight:c.getAttribute("height")!==null?c.getAttribute("height"):b.defaultVideoHeight;f=mejs.Utility.encodeUrl(f);h=mejs.Utility.encodeUrl(h)}else if(b.enablePluginDebug){f=
     50320;h=240}j.success=b.success;mejs.MediaPluginBridge.registerPluginElement(l,j,c);k.className="me-plugin";k.id=l+"_container";a.isVideo?c.parentNode.insertBefore(k,c):document.body.insertBefore(k,document.body.childNodes[0]);d=["id="+l,"isvideo="+(a.isVideo?"true":"false"),"autoplay="+(d?"true":"false"),"preload="+e,"width="+f,"startvolume="+b.startVolume,"timerrate="+b.timerRate,"flashstreamer="+b.flashStreamer,"height="+h,"pseudostreamstart="+b.pseudoStreamingStartQueryParam];if(a.url!==null)a.method==
     51"flash"?d.push("file="+mejs.Utility.encodeUrl(a.url)):d.push("file="+a.url);b.enablePluginDebug&&d.push("debug=true");b.enablePluginSmoothing&&d.push("smoothing=true");b.enablePseudoStreaming&&d.push("pseudostreaming=true");g&&d.push("controls=true");if(b.pluginVars)d=d.concat(b.pluginVars);switch(a.method){case "silverlight":k.innerHTML='<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="'+l+'" name="'+l+'" width="'+f+'" height="'+h+'" class="mejs-shim"><param name="initParams" value="'+
     52d.join(",")+'" /><param name="windowless" value="true" /><param name="background" value="black" /><param name="minRuntimeVersion" value="3.0.0.0" /><param name="autoUpgrade" value="true" /><param name="source" value="'+b.pluginPath+b.silverlightName+'" /></object>';break;case "flash":if(mejs.MediaFeatures.isIE){a=document.createElement("div");k.appendChild(a);a.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+
     53l+'" width="'+f+'" height="'+h+'" class="mejs-shim"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&amp;")+'" /><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" /></object>'}else k.innerHTML='<embed id="'+l+'" name="'+l+'" play="true" loop="false" quality="high" bgcolor="#000000" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" src="'+
     54b.pluginPath+b.flashName+'" flashvars="'+d.join("&")+'" width="'+f+'" height="'+h+'" class="mejs-shim"></embed>';break;case "youtube":b=a.url.substr(a.url.lastIndexOf("=")+1);youtubeSettings={container:k,containerId:k.id,pluginMediaElement:j,pluginId:l,videoId:b,height:h,width:f};mejs.PluginDetector.hasPluginVersion("flash",[10,0,0])?mejs.YouTubeApi.createFlash(youtubeSettings):mejs.YouTubeApi.enqueueIframe(youtubeSettings);break;case "vimeo":j.vimeoid=a.url.substr(a.url.lastIndexOf("/")+1);k.innerHTML=
     55'<iframe src="http://player.vimeo.com/video/'+j.vimeoid+'?portrait=0&byline=0&title=0" width="'+f+'" height="'+h+'" frameborder="0" class="mejs-shim"></iframe>'}c.style.display="none";return j},updateNative:function(a,b){var c=a.htmlMediaElement,d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}};
     56mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="http://www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}},iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId,
     57{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused;
     58c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]=
     59a;var b,c="http://www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid="+a.pluginId+"&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+a.pluginId+'" width="'+a.width+'" height="'+a.height+'" class="mejs-shim"><param name="movie" value="'+
     60c+'" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else a.container.innerHTML='<object type="application/x-shockwave-flash" id="'+a.pluginId+'" data="'+c+'" width="'+a.width+'" height="'+a.height+'" style="visibility: visible; " class="mejs-shim"><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>'},flashReady:function(a){var b=this.flashPlayers[a],c=
     61document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250)},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"loadedmetadata");break;case 0:c.paused=false;
     62c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)}window.mejs=mejs;window.MediaElement=mejs.MediaElement;
     63(function(a,b){var c={locale:{strings:{}},methods:{}};c.locale.getLanguage=function(){return{language:navigator.language}};c.locale.INIT_LANGUAGE=c.locale.getLanguage();c.methods.checkPlain=function(d){var e,g,f={"&":"&amp;",'"':"&quot;","<":"&lt;",">":"&gt;"};d=String(d);for(e in f)if(f.hasOwnProperty(e)){g=RegExp(e,"g");d=d.replace(g,f[e])}return d};c.methods.formatString=function(d,e){for(var g in e){switch(g.charAt(0)){case "@":e[g]=c.methods.checkPlain(e[g]);break;case "!":break;default:e[g]=
     64'<em class="placeholder">'+c.methods.checkPlain(e[g])+"</em>"}d=d.replace(g,e[g])}return d};c.methods.t=function(d,e,g){if(c.locale.strings&&c.locale.strings[g.context]&&c.locale.strings[g.context][d])d=c.locale.strings[g.context][d];if(e)d=c.methods.formatString(d,e);return d};c.t=function(d,e,g){if(typeof d==="string"&&d.length>0){var f=c.locale.getLanguage();g=g||{context:f.language};return c.methods.t(d,e,g)}else throw{name:"InvalidArgumentException",message:"First argument is either not a string or empty."};
     65};b.i18n=c})(document,mejs);(function(a){a.de={Fullscreen:"Vollbild","Go Fullscreen":"Vollbild an","Turn off Fullscreen":"Vollbild aus",Close:"Schlie\u00dfen"}})(mejs.i18n.locale.strings);(function(a){a.zh={Fullscreen:"\u5168\u87a2\u5e55","Go Fullscreen":"\u5168\u5c4f\u6a21\u5f0f","Turn off Fullscreen":"\u9000\u51fa\u5168\u5c4f\u6a21\u5f0f",Close:"\u95dc\u9589"}})(mejs.i18n.locale.strings);
    181566
    181667/*!
     
    182475 * License: MIT
    182576 *
    1826  */
    1827 if (typeof jQuery != 'undefined') {
    1828     mejs.$ = jQuery;
    1829 } else if (typeof ender != 'undefined') {
    1830     mejs.$ = ender;
    1831 }
    1832 (function ($) {
    1833 
    1834     // default player values
    1835     mejs.MepDefaults = {
    1836         // url to poster (to fix iOS 3.x)
    1837         poster: '',
    1838         // default if the <video width> is not specified
    1839         defaultVideoWidth: 480,
    1840         // default if the <video height> is not specified
    1841         defaultVideoHeight: 270,
    1842         // if set, overrides <video width>
    1843         videoWidth: -1,
    1844         // if set, overrides <video height>
    1845         videoHeight: -1,
    1846         // default if the user doesn't specify
    1847         defaultAudioWidth: 400,
    1848         // default if the user doesn't specify
    1849         defaultAudioHeight: 30,
    1850 
    1851         // default amount to move back when back key is pressed
    1852         defaultSeekBackwardInterval: function(media) {
    1853             return (media.duration * 0.05);
    1854         },
    1855         // default amount to move forward when forward key is pressed
    1856         defaultSeekForwardInterval: function(media) {
    1857             return (media.duration * 0.05);
    1858         },
    1859 
    1860         // width of audio player
    1861         audioWidth: -1,
    1862         // height of audio player
    1863         audioHeight: -1,
    1864         // initial volume when the player starts (overrided by user cookie)
    1865         startVolume: 0.8,
    1866         // useful for <audio> player loops
    1867         loop: false,
    1868         // rewind to beginning when media ends
    1869                 autoRewind: true,
    1870         // resize to media dimensions
    1871         enableAutosize: true,
    1872         // forces the hour marker (##:00:00)
    1873         alwaysShowHours: false,
    1874 
    1875         // show framecount in timecode (##:00:00:00)
    1876         showTimecodeFrameCount: false,
    1877         // used when showTimecodeFrameCount is set to true
    1878         framesPerSecond: 25,
    1879 
    1880         // automatically calculate the width of the progress bar based on the sizes of other elements
    1881         autosizeProgress : true,
    1882         // Hide controls when playing and mouse is not over the video
    1883         alwaysShowControls: false,
    1884         // Display the video control
    1885         hideVideoControlsOnLoad: false,
    1886         // Enable click video element to toggle play/pause
    1887         clickToPlayPause: true,
    1888         // force iPad's native controls
    1889         iPadUseNativeControls: false,
    1890         // force iPhone's native controls
    1891         iPhoneUseNativeControls: false,
    1892         // force Android's native controls
    1893         AndroidUseNativeControls: false,
    1894         // features to show
    1895         features: ['playpause','current','progress','duration','tracks','volume','fullscreen'],
    1896         // only for dynamic
    1897         isVideo: true,
    1898 
    1899         // turns keyboard support on and off for this instance
    1900         enableKeyboard: true,
    1901 
    1902         // whenthis player starts, it will pause other players
    1903         pauseOtherPlayers: true,
    1904 
    1905         // array of keyboard actions such as play pause
    1906         keyActions: [
    1907                 {
    1908                         keys: [
    1909                                 32, // SPACE
    1910                                 179 // GOOGLE play/pause button
    1911                               ],
    1912                         action: function(player, media) {
    1913                                 if (media.paused || media.ended) {
    1914                                         media.play();
    1915                                 } else {
    1916                                         media.pause();
    1917                                 }
    1918                         }
    1919                 },
    1920                 {
    1921                         keys: [38], // UP
    1922                         action: function(player, media) {
    1923                                 var newVolume = Math.min(media.volume + 0.1, 1);
    1924                                 media.setVolume(newVolume);
    1925                         }
    1926                 },
    1927                 {
    1928                         keys: [40], // DOWN
    1929                         action: function(player, media) {
    1930                                 var newVolume = Math.max(media.volume - 0.1, 0);
    1931                                 media.setVolume(newVolume);
    1932                         }
    1933                 },
    1934                 {
    1935                         keys: [
    1936                                 37, // LEFT
    1937                                 227 // Google TV rewind
    1938                         ],
    1939                         action: function(player, media) {
    1940                                 if (!isNaN(media.duration) && media.duration > 0) {
    1941                                         if (player.isVideo) {
    1942                                                 player.showControls();
    1943                                                 player.startControlsTimer();
    1944                                         }
    1945 
    1946                                         // 5%
    1947                                         var newTime = Math.max(media.currentTime - player.options.defaultSeekBackwardInterval(media), 0);
    1948                                         media.setCurrentTime(newTime);
    1949                                 }
    1950                         }
    1951                 },
    1952                 {
    1953                         keys: [
    1954                                 39, // RIGHT
    1955                                 228 // Google TV forward
    1956                         ],
    1957                         action: function(player, media) {
    1958                                 if (!isNaN(media.duration) && media.duration > 0) {
    1959                                         if (player.isVideo) {
    1960                                                 player.showControls();
    1961                                                 player.startControlsTimer();
    1962                                         }
    1963 
    1964                                         // 5%
    1965                                         var newTime = Math.min(media.currentTime + player.options.defaultSeekForwardInterval(media), media.duration);
    1966                                         media.setCurrentTime(newTime);
    1967                                 }
    1968                         }
    1969                 },
    1970                 {
    1971                         keys: [70], // f
    1972                         action: function(player, media) {
    1973                                 if (typeof player.enterFullScreen != 'undefined') {
    1974                                         if (player.isFullScreen) {
    1975                                                 player.exitFullScreen();
    1976                                         } else {
    1977                                                 player.enterFullScreen();
    1978                                         }
    1979                                 }
    1980                         }
    1981                 }
    1982         ]
    1983     };
    1984 
    1985     mejs.mepIndex = 0;
    1986 
    1987     mejs.players = {};
    1988 
    1989     // wraps a MediaElement object in player controls
    1990     mejs.MediaElementPlayer = function(node, o) {
    1991         // enforce object, even without "new" (via John Resig)
    1992         if ( !(this instanceof mejs.MediaElementPlayer) ) {
    1993             return new mejs.MediaElementPlayer(node, o);
    1994         }
    1995 
    1996         var t = this;
    1997 
    1998         // these will be reset after the MediaElement.success fires
    1999         t.$media = t.$node = $(node);
    2000         t.node = t.media = t.$media[0];
    2001 
    2002         // check for existing player
    2003         if (typeof t.node.player != 'undefined') {
    2004             return t.node.player;
    2005         } else {
    2006             // attach player to DOM node for reference
    2007             t.node.player = t;
    2008         }
    2009 
    2010 
    2011         // try to get options from data-mejsoptions
    2012         if (typeof o == 'undefined') {
    2013             o = t.$node.data('mejsoptions');
    2014         }
    2015 
    2016         // extend default options
    2017         t.options = $.extend({},mejs.MepDefaults,o);
    2018 
    2019         // unique ID
    2020         t.id = 'mep_' + mejs.mepIndex++;
    2021 
    2022         // add to player array (for focus events)
    2023         mejs.players[t.id] = t;
    2024 
    2025         // start up
    2026         t.init();
    2027 
    2028         return t;
    2029     };
    2030 
    2031     // actual player
    2032     mejs.MediaElementPlayer.prototype = {
    2033 
    2034         hasFocus: false,
    2035 
    2036         controlsAreVisible: true,
    2037 
    2038         init: function() {
    2039 
    2040             var
    2041                 t = this,
    2042                 mf = mejs.MediaFeatures,
    2043                 // options for MediaElement (shim)
    2044                 meOptions = $.extend(true, {}, t.options, {
    2045                     success: function(media, domNode) { t.meReady(media, domNode); },
    2046                     error: function(e) { t.handleError(e);}
    2047                 }),
    2048                 tagName = t.media.tagName.toLowerCase();
    2049 
    2050             t.isDynamic = (tagName !== 'audio' && tagName !== 'video');
    2051 
    2052             if (t.isDynamic) {
    2053                 // get video from src or href?
    2054                 t.isVideo = t.options.isVideo;
    2055             } else {
    2056                 t.isVideo = (tagName !== 'audio' && t.options.isVideo);
    2057             }
    2058 
    2059             // use native controls in iPad, iPhone, and Android
    2060             if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) {
    2061 
    2062                 // add controls and stop
    2063                 t.$media.attr('controls', 'controls');
    2064 
    2065                 // attempt to fix iOS 3 bug
    2066                 //t.$media.removeAttr('poster');
    2067                                 // no Issue found on iOS3 -ttroxell
    2068 
    2069                 // override Apple's autoplay override for iPads
    2070                 if (mf.isiPad && t.media.getAttribute('autoplay') !== null) {
    2071                     t.media.load();
    2072                     t.media.play();
    2073                 }
    2074 
    2075             } else if (mf.isAndroid && t.options.AndroidUseNativeControls) {
    2076 
    2077                 // leave default player
    2078 
    2079             } else {
    2080 
    2081                 // DESKTOP: use MediaElementPlayer controls
    2082 
    2083                 // remove native controls
    2084                 t.$media.removeAttr('controls');
    2085 
    2086                 // build container
    2087                 t.container =
    2088                     $('<div id="' + t.id + '" class="mejs-container ' + (mejs.MediaFeatures.svg ? 'svg' : 'no-svg') + '">'+
    2089                         '<div class="mejs-inner">'+
    2090                             '<div class="mejs-mediaelement"></div>'+
    2091                             '<div class="mejs-layers"></div>'+
    2092                             '<div class="mejs-controls"></div>'+
    2093                             '<div class="mejs-clear"></div>'+
    2094                         '</div>' +
    2095                     '</div>')
    2096                     .addClass(t.$media[0].className)
    2097                     .insertBefore(t.$media);
    2098 
    2099                 // add classes for user and content
    2100                 t.container.addClass(
    2101                     (mf.isAndroid ? 'mejs-android ' : '') +
    2102                     (mf.isiOS ? 'mejs-ios ' : '') +
    2103                     (mf.isiPad ? 'mejs-ipad ' : '') +
    2104                     (mf.isiPhone ? 'mejs-iphone ' : '') +
    2105                     (t.isVideo ? 'mejs-video ' : 'mejs-audio ')
    2106                 );
    2107 
    2108 
    2109                 // move the <video/video> tag into the right spot
    2110                 if (mf.isiOS) {
    2111 
    2112                     // sadly, you can't move nodes in iOS, so we have to destroy and recreate it!
    2113                     var $newMedia = t.$media.clone();
    2114 
    2115                     t.container.find('.mejs-mediaelement').append($newMedia);
    2116 
    2117                     t.$media.remove();
    2118                     t.$node = t.$media = $newMedia;
    2119                     t.node = t.media = $newMedia[0]
    2120 
    2121                 } else {
    2122 
    2123                     // normal way of moving it into place (doesn't work on iOS)
    2124                     t.container.find('.mejs-mediaelement').append(t.$media);
    2125                 }
    2126 
    2127                 // find parts
    2128                 t.controls = t.container.find('.mejs-controls');
    2129                 t.layers = t.container.find('.mejs-layers');
    2130 
    2131                 // determine the size
    2132 
    2133                 /* size priority:
    2134                     (1) videoWidth (forced),
    2135                     (2) style="width;height;"
    2136                     (3) width attribute,
    2137                     (4) defaultVideoWidth (for unspecified cases)
    2138                 */
    2139 
    2140                 var tagType = (t.isVideo ? 'video' : 'audio'),
    2141                     capsTagName = tagType.substring(0,1).toUpperCase() + tagType.substring(1);
    2142 
    2143 
    2144                 if (t.options[tagType + 'Width'] > 0 || t.options[tagType + 'Width'].toString().indexOf('%') > -1) {
    2145                     t.width = t.options[tagType + 'Width'];
    2146                 } else if (t.media.style.width !== '' && t.media.style.width !== null) {
    2147                     t.width = t.media.style.width;
    2148                 } else if (t.media.getAttribute('width') !== null) {
    2149                     t.width = t.$media.attr('width');
    2150                 } else {
    2151                     t.width = t.options['default' + capsTagName + 'Width'];
    2152                 }
    2153 
    2154                 if (t.options[tagType + 'Height'] > 0 || t.options[tagType + 'Height'].toString().indexOf('%') > -1) {
    2155                     t.height = t.options[tagType + 'Height'];
    2156                 } else if (t.media.style.height !== '' && t.media.style.height !== null) {
    2157                     t.height = t.media.style.height;
    2158                 } else if (t.$media[0].getAttribute('height') !== null) {
    2159                     t.height = t.$media.attr('height');
    2160                 } else {
    2161                     t.height = t.options['default' + capsTagName + 'Height'];
    2162                 }
    2163 
    2164                 // set the size, while we wait for the plugins to load below
    2165                 t.setPlayerSize(t.width, t.height);
    2166 
    2167                 // create MediaElementShim
    2168                 meOptions.pluginWidth = t.height;
    2169                 meOptions.pluginHeight = t.width;
    2170             }
    2171 
    2172 
    2173 
    2174             // create MediaElement shim
    2175             mejs.MediaElement(t.$media[0], meOptions);
    2176 
    2177             // controls are shown when loaded
    2178             t.container.trigger('controlsshown');
    2179         },
    2180 
    2181         showControls: function(doAnimation) {
    2182             var t = this;
    2183 
    2184             doAnimation = typeof doAnimation == 'undefined' || doAnimation;
    2185 
    2186             if (t.controlsAreVisible)
    2187                 return;
    2188 
    2189             if (doAnimation) {
    2190                 t.controls
    2191                     .css('visibility','visible')
    2192                     .stop(true, true).fadeIn(200, function() {
    2193                           t.controlsAreVisible = true;
    2194                           t.container.trigger('controlsshown');
    2195                     });
    2196 
    2197                 // any additional controls people might add and want to hide
    2198                 t.container.find('.mejs-control')
    2199                     .css('visibility','visible')
    2200                     .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;});
    2201 
    2202             } else {
    2203                 t.controls
    2204                     .css('visibility','visible')
    2205                     .css('display','block');
    2206 
    2207                 // any additional controls people might add and want to hide
    2208                 t.container.find('.mejs-control')
    2209                     .css('visibility','visible')
    2210                     .css('display','block');
    2211 
    2212                 t.controlsAreVisible = true;
    2213                 t.container.trigger('controlsshown');
    2214             }
    2215 
    2216             t.setControlsSize();
    2217 
    2218         },
    2219 
    2220         hideControls: function(doAnimation) {
    2221             var t = this;
    2222 
    2223             doAnimation = typeof doAnimation == 'undefined' || doAnimation;
    2224 
    2225             if (!t.controlsAreVisible)
    2226                 return;
    2227 
    2228             if (doAnimation) {
    2229                 // fade out main controls
    2230                 t.controls.stop(true, true).fadeOut(200, function() {
    2231                     $(this)
    2232                         .css('visibility','hidden')
    2233                         .css('display','block');
    2234 
    2235                     t.controlsAreVisible = false;
    2236                     t.container.trigger('controlshidden');
    2237                 });
    2238 
    2239                 // any additional controls people might add and want to hide
    2240                 t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() {
    2241                     $(this)
    2242                         .css('visibility','hidden')
    2243                         .css('display','block');
    2244                 });
    2245             } else {
    2246 
    2247                 // hide main controls
    2248                 t.controls
    2249                     .css('visibility','hidden')
    2250                     .css('display','block');
    2251 
    2252                 // hide others
    2253                 t.container.find('.mejs-control')
    2254                     .css('visibility','hidden')
    2255                     .css('display','block');
    2256 
    2257                 t.controlsAreVisible = false;
    2258                 t.container.trigger('controlshidden');
    2259             }
    2260         },
    2261 
    2262         controlsTimer: null,
    2263 
    2264         startControlsTimer: function(timeout) {
    2265 
    2266             var t = this;
    2267 
    2268             timeout = typeof timeout != 'undefined' ? timeout : 1500;
    2269 
    2270             t.killControlsTimer('start');
    2271 
    2272             t.controlsTimer = setTimeout(function() {
    2273                 //console.log('timer fired');
    2274                 t.hideControls();
    2275                 t.killControlsTimer('hide');
    2276             }, timeout);
    2277         },
    2278 
    2279         killControlsTimer: function(src) {
    2280 
    2281             var t = this;
    2282 
    2283             if (t.controlsTimer !== null) {
    2284                 clearTimeout(t.controlsTimer);
    2285                 delete t.controlsTimer;
    2286                 t.controlsTimer = null;
    2287             }
    2288         },
    2289 
    2290         controlsEnabled: true,
    2291 
    2292         disableControls: function() {
    2293             var t= this;
    2294 
    2295             t.killControlsTimer();
    2296             t.hideControls(false);
    2297             this.controlsEnabled = false;
    2298         },
    2299 
    2300         enableControls: function() {
    2301             var t= this;
    2302 
    2303             t.showControls(false);
    2304 
    2305             t.controlsEnabled = true;
    2306         },
    2307 
    2308 
    2309         // Sets up all controls and events
    2310         meReady: function(media, domNode) {
    2311 
    2312 
    2313             var t = this,
    2314                 mf = mejs.MediaFeatures,
    2315                 autoplayAttr = domNode.getAttribute('autoplay'),
    2316                 autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'),
    2317                 featureIndex,
    2318                 feature;
    2319 
    2320             // make sure it can't create itself again if a plugin reloads
    2321             if (t.created)
    2322                 return;
    2323             else
    2324                 t.created = true;
    2325 
    2326             t.media = media;
    2327             t.domNode = domNode;
    2328 
    2329             if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) {
    2330 
    2331                 // two built in features
    2332                 t.buildposter(t, t.controls, t.layers, t.media);
    2333                 t.buildkeyboard(t, t.controls, t.layers, t.media);
    2334                 t.buildoverlays(t, t.controls, t.layers, t.media);
    2335 
    2336                 // grab for use by features
    2337                 t.findTracks();
    2338 
    2339                 // add user-defined features/controls
    2340                 for (featureIndex in t.options.features) {
    2341                     feature = t.options.features[featureIndex];
    2342                     if (t['build' + feature]) {
    2343                         try {
    2344                             t['build' + feature](t, t.controls, t.layers, t.media);
    2345                         } catch (e) {
    2346                             // TODO: report control error
    2347                             //throw e;
    2348                             //console.log('error building ' + feature);
    2349                             //console.log(e);
    2350                         }
    2351                     }
    2352                 }
    2353 
    2354                 t.container.trigger('controlsready');
    2355 
    2356                 // reset all layers and controls
    2357                 t.setPlayerSize(t.width, t.height);
    2358                 t.setControlsSize();
    2359 
    2360 
    2361                 // controls fade
    2362                 if (t.isVideo) {
    2363 
    2364                     if (mejs.MediaFeatures.hasTouch) {
    2365 
    2366                         // for touch devices (iOS, Android)
    2367                         // show/hide without animation on touch
    2368 
    2369                         t.$media.bind('touchstart', function() {
    2370 
    2371 
    2372                             // toggle controls
    2373                             if (t.controlsAreVisible) {
    2374                                 t.hideControls(false);
    2375                             } else {
    2376                                 if (t.controlsEnabled) {
    2377                                     t.showControls(false);
    2378                                 }
    2379                             }
    2380                         });
    2381 
    2382                     } else {
    2383             // click to play/pause
    2384             t.media.addEventListener('click', function() {
    2385               if (t.options.clickToPlayPause) {
    2386                   if (t.media.paused) {
    2387                     t.media.play();
    2388                   } else {
    2389                     t.media.pause();
    2390                   }
    2391               }
    2392             });
    2393 
    2394                         // show/hide controls
    2395                         t.container
    2396                             .bind('mouseenter mouseover', function () {
    2397                                 if (t.controlsEnabled) {
    2398                                     if (!t.options.alwaysShowControls) {
    2399                                         t.killControlsTimer('enter');
    2400                                         t.showControls();
    2401                                         t.startControlsTimer(2500);
    2402                                     }
    2403                                 }
    2404                             })
    2405                             .bind('mousemove', function() {
    2406                                 if (t.controlsEnabled) {
    2407                                     if (!t.controlsAreVisible) {
    2408                                         t.showControls();
    2409                                     }
    2410                                     //t.killControlsTimer('move');
    2411                                     if (!t.options.alwaysShowControls) {
    2412                                         t.startControlsTimer(2500);
    2413                                     }
    2414                                 }
    2415                             })
    2416                             .bind('mouseleave', function () {
    2417                                 if (t.controlsEnabled) {
    2418                                     if (!t.media.paused && !t.options.alwaysShowControls) {
    2419                                         t.startControlsTimer(1000);
    2420                                     }
    2421                                 }
    2422                             });
    2423                     }
    2424 
    2425                     if(t.options.hideVideoControlsOnLoad) {
    2426                         t.hideControls(false);
    2427                     }
    2428 
    2429                     // check for autoplay
    2430                     if (autoplay && !t.options.alwaysShowControls) {
    2431                         t.hideControls();
    2432                     }
    2433 
    2434                     // resizer
    2435                     if (t.options.enableAutosize) {
    2436                         t.media.addEventListener('loadedmetadata', function(e) {
    2437                             // if the <video height> was not set and the options.videoHeight was not set
    2438                             // then resize to the real dimensions
    2439                             if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) {
    2440                                 t.setPlayerSize(e.target.videoWidth, e.target.videoHeight);
    2441                                 t.setControlsSize();
    2442                                 t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight);
    2443                             }
    2444                         }, false);
    2445                     }
    2446                 }
    2447 
    2448                 // EVENTS
    2449 
    2450                 // FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them)
    2451                 media.addEventListener('play', function() {
    2452                         var playerIndex;
    2453 
    2454                         // go through all other players
    2455                         for (playerIndex in mejs.players) {
    2456                             var p = mejs.players[playerIndex];
    2457                             if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) {
    2458                                 p.pause();
    2459                             }
    2460                             p.hasFocus = false;
    2461                         }
    2462 
    2463                         t.hasFocus = true;
    2464                 },false);
    2465 
    2466 
    2467                 // ended for all
    2468                 t.media.addEventListener('ended', function (e) {
    2469                     if(t.options.autoRewind) {
    2470                         try{
    2471                             t.media.setCurrentTime(0);
    2472                         } catch (exp) {
    2473 
    2474                         }
    2475                     }
    2476                     t.media.pause();
    2477 
    2478                     if (t.setProgressRail)
    2479                         t.setProgressRail();
    2480                     if (t.setCurrentRail)
    2481                         t.setCurrentRail();
    2482 
    2483                     if (t.options.loop) {
    2484                         t.media.play();
    2485                     } else if (!t.options.alwaysShowControls && t.controlsEnabled) {
    2486                         t.showControls();
    2487                     }
    2488                 }, false);
    2489 
    2490                 // resize on the first play
    2491                 t.media.addEventListener('loadedmetadata', function(e) {
    2492                     if (t.updateDuration) {
    2493                         t.updateDuration();
    2494                     }
    2495                     if (t.updateCurrent) {
    2496                         t.updateCurrent();
    2497                     }
    2498 
    2499                     if (!t.isFullScreen) {
    2500                         t.setPlayerSize(t.width, t.height);
    2501                         t.setControlsSize();
    2502                     }
    2503                 }, false);
    2504 
    2505 
    2506                 // webkit has trouble doing this without a delay
    2507                 setTimeout(function () {
    2508                     t.setPlayerSize(t.width, t.height);
    2509                     t.setControlsSize();
    2510                 }, 50);
    2511 
    2512                 // adjust controls whenever window sizes (used to be in fullscreen only)
    2513                 t.globalBind('resize', function() {
    2514 
    2515                     // don't resize for fullscreen mode
    2516                     if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) {
    2517                         t.setPlayerSize(t.width, t.height);
    2518                     }
    2519 
    2520                     // always adjust controls
    2521                     t.setControlsSize();
    2522                 });
    2523 
    2524                 // TEMP: needs to be moved somewhere else
    2525                 if (t.media.pluginType == 'youtube') {
    2526                     t.container.find('.mejs-overlay-play').hide();
    2527                 }
    2528             }
    2529 
    2530             // force autoplay for HTML5
    2531             if (autoplay && media.pluginType == 'native') {
    2532                 media.load();
    2533                 media.play();
    2534             }
    2535 
    2536 
    2537             if (t.options.success) {
    2538 
    2539                 if (typeof t.options.success == 'string') {
    2540                         window[t.options.success](t.media, t.domNode, t);
    2541                 } else {
    2542                         t.options.success(t.media, t.domNode, t);
    2543                 }
    2544             }
    2545         },
    2546 
    2547         handleError: function(e) {
    2548             var t = this;
    2549 
    2550             t.controls.hide();
    2551 
    2552             // Tell user that the file cannot be played
    2553             if (t.options.error) {
    2554                 t.options.error(e);
    2555             }
    2556         },
    2557 
    2558         setPlayerSize: function(width,height) {
    2559             var t = this;
    2560 
    2561             if (typeof width != 'undefined')
    2562                 t.width = width;
    2563 
    2564             if (typeof height != 'undefined')
    2565                 t.height = height;
    2566 
    2567       // detect 100% mode - use currentStyle for IE since css() doesn't return percentages
    2568       if (t.height.toString().indexOf('%') > 0 || t.$node.css('max-width') === '100%' || (t.$node[0].currentStyle && t.$node[0].currentStyle.maxWidth === '100%')) {
    2569 
    2570                 // do we have the native dimensions yet?
    2571                 var
    2572                     nativeWidth = t.isVideo ? ((t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth) : t.options.defaultAudioWidth,
    2573                     nativeHeight = t.isVideo ? ((t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight) : t.options.defaultAudioHeight,
    2574                     parentWidth = t.container.parent().closest(':visible').width(),
    2575                     newHeight = t.isVideo || !t.options.autosizeProgress ? parseInt(parentWidth * nativeHeight/nativeWidth, 10) : nativeHeight;
    2576 
    2577                 if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) {
    2578                     parentWidth = $(window).width();
    2579                     newHeight = $(window).height();
    2580                 }
    2581 
    2582                 if ( newHeight != 0 && parentWidth != 0 ) {
    2583                     // set outer container size
    2584                     t.container
    2585                         .width(parentWidth)
    2586                         .height(newHeight);
    2587 
    2588                     // set native <video> or <audio> and shims
    2589                     t.$media.add(t.container.find('.mejs-shim'))
    2590                         .width('100%')
    2591                         .height('100%');
    2592 
    2593                     // if shim is ready, send the size to the embeded plugin
    2594                     if (t.isVideo) {
    2595                         if (t.media.setVideoSize) {
    2596                             t.media.setVideoSize(parentWidth, newHeight);
    2597                         }
    2598                     }
    2599 
    2600                     // set the layers
    2601                     t.layers.children('.mejs-layer')
    2602                         .width('100%')
    2603                         .height('100%');
    2604                 }
    2605 
    2606 
    2607             } else {
    2608 
    2609                 t.container
    2610                     .width(t.width)
    2611                     .height(t.height);
    2612 
    2613                 t.layers.children('.mejs-layer')
    2614                     .width(t.width)
    2615                     .height(t.height);
    2616 
    2617             }
    2618         },
    2619 
    2620         setControlsSize: function() {
    2621             var t = this,
    2622                 usedWidth = 0,
    2623                 railWidth = 0,
    2624                 rail = t.controls.find('.mejs-time-rail'),
    2625                 total = t.controls.find('.mejs-time-total'),
    2626                 current = t.controls.find('.mejs-time-current'),
    2627                 loaded = t.controls.find('.mejs-time-loaded'),
    2628                 others = rail.siblings();
    2629 
    2630 
    2631             // allow the size to come from custom CSS
    2632             if (t.options && !t.options.autosizeProgress) {
    2633                 // Also, frontends devs can be more flexible
    2634                 // due the opportunity of absolute positioning.
    2635                 railWidth = parseInt(rail.css('width'));
    2636             }
    2637 
    2638             // attempt to autosize
    2639             if (railWidth === 0 || !railWidth) {
    2640 
    2641                 // find the size of all the other controls besides the rail
    2642                 others.each(function() {
    2643                     var $this = $(this);
    2644                     if ($this.css('position') != 'absolute' && $this.is(':visible')) {
    2645                         usedWidth += $(this).outerWidth(true);
    2646                     }
    2647                 });
    2648 
    2649                 // fit the rail into the remaining space
    2650                 railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width());
    2651             }
    2652 
    2653             // outer area
    2654             rail.width(railWidth);
    2655             // dark space
    2656             total.width(railWidth - (total.outerWidth(true) - total.width()));
    2657 
    2658             if (t.setProgressRail)
    2659                 t.setProgressRail();
    2660             if (t.setCurrentRail)
    2661                 t.setCurrentRail();
    2662         },
    2663 
    2664 
    2665         buildposter: function(player, controls, layers, media) {
    2666             var t = this,
    2667                 poster =
    2668                 $('<div class="mejs-poster mejs-layer">' +
    2669                 '</div>')
    2670                     .appendTo(layers),
    2671                 posterUrl = player.$media.attr('poster');
    2672 
    2673             // prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster)
    2674             if (player.options.poster !== '') {
    2675                 posterUrl = player.options.poster;
    2676             }
    2677 
    2678             // second, try the real poster
    2679             if (posterUrl !== '' && posterUrl != null) {
    2680                 t.setPoster(posterUrl);
    2681             } else {
    2682                 poster.hide();
    2683             }
    2684 
    2685             media.addEventListener('play',function() {
    2686                 poster.hide();
    2687             }, false);
    2688         },
    2689 
    2690         setPoster: function(url) {
    2691             var t = this,
    2692                 posterDiv = t.container.find('.mejs-poster'),
    2693                 posterImg = posterDiv.find('img');
    2694 
    2695             if (posterImg.length == 0) {
    2696                 posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv);
    2697             }
    2698 
    2699             posterImg.attr('src', url);
    2700         },
    2701 
    2702         buildoverlays: function(player, controls, layers, media) {
    2703             var t = this;
    2704             if (!player.isVideo)
    2705                 return;
    2706 
    2707             var
    2708             loading =
    2709                 $('<div class="mejs-overlay mejs-layer">'+
    2710                     '<div class="mejs-overlay-loading"><span></span></div>'+
    2711                 '</div>')
    2712                 .hide() // start out hidden
    2713                 .appendTo(layers),
    2714             error =
    2715                 $('<div class="mejs-overlay mejs-layer">'+
    2716                     '<div class="mejs-overlay-error"></div>'+
    2717                 '</div>')
    2718                 .hide() // start out hidden
    2719                 .appendTo(layers),
    2720             // this needs to come last so it's on top
    2721             bigPlay =
    2722                 $('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+
    2723                     '<div class="mejs-overlay-button"></div>'+
    2724                 '</div>')
    2725                 .appendTo(layers)
    2726                 .click(function() {
    2727                     if (t.options.clickToPlayPause) {
    2728                         if (media.paused) {
    2729                             media.play();
    2730                         } else {
    2731                             media.pause();
    2732                         }
    2733                     }
    2734                 });
    2735 
    2736             /*
    2737             if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) {
    2738                 bigPlay.remove();
    2739                 loading.remove();
    2740             }
    2741             */
    2742 
    2743 
    2744             // show/hide big play button
    2745             media.addEventListener('play',function() {
    2746                 bigPlay.hide();
    2747                 loading.hide();
    2748                 controls.find('.mejs-time-buffering').hide();
    2749                 error.hide();
    2750             }, false);
    2751 
    2752             media.addEventListener('playing', function() {
    2753                 bigPlay.hide();
    2754                 loading.hide();
    2755                 controls.find('.mejs-time-buffering').hide();
    2756                 error.hide();
    2757             }, false);
    2758 
    2759             media.addEventListener('seeking', function() {
    2760                 loading.show();
    2761                 controls.find('.mejs-time-buffering').show();
    2762             }, false);
    2763 
    2764             media.addEventListener('seeked', function() {
    2765                 loading.hide();
    2766                 controls.find('.mejs-time-buffering').hide();
    2767             }, false);
    2768 
    2769             media.addEventListener('pause',function() {
    2770                 if (!mejs.MediaFeatures.isiPhone) {
    2771                     bigPlay.show();
    2772                 }
    2773             }, false);
    2774 
    2775             media.addEventListener('waiting', function() {
    2776                 loading.show();
    2777                 controls.find('.mejs-time-buffering').show();
    2778             }, false);
    2779 
    2780 
    2781             // show/hide loading
    2782             media.addEventListener('loadeddata',function() {
    2783                 // for some reason Chrome is firing this event
    2784                 //if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none')
    2785                 //  return;
    2786 
    2787                 loading.show();
    2788                 controls.find('.mejs-time-buffering').show();
    2789             }, false);
    2790             media.addEventListener('canplay',function() {
    2791                 loading.hide();
    2792                 controls.find('.mejs-time-buffering').hide();
    2793             }, false);
    2794 
    2795             // error handling
    2796             media.addEventListener('error',function() {
    2797                 loading.hide();
    2798                 controls.find('.mejs-time-buffering').hide();
    2799                 error.show();
    2800                 error.find('mejs-overlay-error').html("Error loading this resource");
    2801             }, false);
    2802         },
    2803 
    2804         buildkeyboard: function(player, controls, layers, media) {
    2805 
    2806                 var t = this;
    2807 
    2808                 // listen for key presses
    2809                 t.globalBind('keydown', function(e) {
    2810 
    2811                         if (player.hasFocus && player.options.enableKeyboard) {
    2812 
    2813                                 // find a matching key
    2814                                 for (var i=0, il=player.options.keyActions.length; i<il; i++) {
    2815                                         var keyAction = player.options.keyActions[i];
    2816 
    2817                                         for (var j=0, jl=keyAction.keys.length; j<jl; j++) {
    2818                                                 if (e.keyCode == keyAction.keys[j]) {
    2819                                                         e.preventDefault();
    2820                                                         keyAction.action(player, media, e.keyCode);
    2821                                                         return false;
    2822                                                 }
    2823                                         }
    2824                                 }
    2825                         }
    2826 
    2827                         return true;
    2828                 });
    2829 
    2830                 // check if someone clicked outside a player region, then kill its focus
    2831                 t.globalBind('click', function(event) {
    2832                         if ($(event.target).closest('.mejs-container').length == 0) {
    2833                                 player.hasFocus = false;
    2834                         }
    2835                 });
    2836 
    2837         },
    2838 
    2839         findTracks: function() {
    2840             var t = this,
    2841                 tracktags = t.$media.find('track');
    2842 
    2843             // store for use by plugins
    2844             t.tracks = [];
    2845             tracktags.each(function(index, track) {
    2846 
    2847                 track = $(track);
    2848 
    2849                 t.tracks.push({
    2850                     srclang: (track.attr('srclang')) ? track.attr('srclang').toLowerCase() : '',
    2851                     src: track.attr('src'),
    2852                     kind: track.attr('kind'),
    2853                     label: track.attr('label') || '',
    2854                     entries: [],
    2855                     isLoaded: false
    2856                 });
    2857             });
    2858         },
    2859         changeSkin: function(className) {
    2860             this.container[0].className = 'mejs-container ' + className;
    2861             this.setPlayerSize(this.width, this.height);
    2862             this.setControlsSize();
    2863         },
    2864         play: function() {
    2865             this.media.play();
    2866         },
    2867         pause: function() {
    2868             this.media.pause();
    2869         },
    2870         load: function() {
    2871             this.media.load();
    2872         },
    2873         setMuted: function(muted) {
    2874             this.media.setMuted(muted);
    2875         },
    2876         setCurrentTime: function(time) {
    2877             this.media.setCurrentTime(time);
    2878         },
    2879         getCurrentTime: function() {
    2880             return this.media.currentTime;
    2881         },
    2882         setVolume: function(volume) {
    2883             this.media.setVolume(volume);
    2884         },
    2885         getVolume: function() {
    2886             return this.media.volume;
    2887         },
    2888         setSrc: function(src) {
    2889             this.media.setSrc(src);
    2890         },
    2891         remove: function() {
    2892             var t = this, featureIndex, feature;
    2893 
    2894             // invoke features cleanup
    2895             for (featureIndex in t.options.features) {
    2896                 feature = t.options.features[featureIndex];
    2897                 if (t['clean' + feature]) {
    2898                     try {
    2899                         t['clean' + feature](t);
    2900                     } catch (e) {
    2901                         // TODO: report control error
    2902                         //throw e;
    2903                         //console.log('error building ' + feature);
    2904                         //console.log(e);
    2905                     }
    2906                 }
    2907             }
    2908 
    2909             if (t.media.pluginType === 'native') {
    2910                 t.$media.prop('controls', true);
    2911             } else {
    2912                 t.media.remove();
    2913             }
    2914 
    2915             // grab video and put it back in place
    2916             if (!t.isDynamic) {
    2917                 if (t.media.pluginType === 'native') {
    2918                     // detach events from the video
    2919                     // TODO: detach event listeners better than this;
    2920                     //       also detach ONLY the events attached by this plugin!
    2921                     //t.$node.clone().insertBefore(t.container);
    2922                     //t.$node.remove();
    2923                 }
    2924                 /*else*/ t.$node.insertBefore(t.container)
    2925             }
    2926 
    2927             // Remove the player from the mejs.players array so that pauseOtherPlayers doesn't blow up when trying to pause a non existance flash api.
    2928             mejs.players.splice( $.inArray( t, mejs.players ), 1);
    2929 
    2930             t.container.remove();
    2931             t.globalUnbind();
    2932             delete t.node.player;
    2933             delete mejs.players[t.id];
    2934         }
    2935     };
    2936 
    2937     (function(){
    2938         var rwindow = /^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/;
    2939 
    2940         function splitEvents(events, id) {
    2941             // add player ID as an event namespace so it's easier to unbind them all later
    2942             var ret = {d: [], w: []};
    2943             $.each((events || '').split(' '), function(k, v){
    2944                 ret[rwindow.test(v) ? 'w' : 'd'].push(v + '.' + id);
    2945             });
    2946             ret.d = ret.d.join(' ');
    2947             ret.w = ret.w.join(' ');
    2948             return ret;
    2949         }
    2950 
    2951         mejs.MediaElementPlayer.prototype.globalBind = function(events, data, callback) {
    2952             var t = this;
    2953             events = splitEvents(events, t.id);
    2954             if (events.d) $(document).bind(events.d, data, callback);
    2955             if (events.w) $(window).bind(events.w, data, callback);
    2956         };
    2957 
    2958         mejs.MediaElementPlayer.prototype.globalUnbind = function(events, callback) {
    2959             var t = this;
    2960             events = splitEvents(events, t.id);
    2961             if (events.d) $(document).unbind(events.d, callback);
    2962             if (events.w) $(window).unbind(events.w, callback);
    2963         };
    2964     })();
    2965 
    2966     // turn into jQuery plugin
    2967     if (typeof jQuery != 'undefined') {
    2968         jQuery.fn.mediaelementplayer = function (options) {
    2969             if (options === false) {
    2970                 this.each(function () {
    2971                     var player = jQuery(this).data('mediaelementplayer');
    2972                     if (player) {
    2973                         player.remove();
    2974                     }
    2975                     jQuery(this).removeData('mediaelementplayer');
    2976                 });
    2977             }
    2978             else {
    2979                 this.each(function () {
    2980                     jQuery(this).data('mediaelementplayer', new mejs.MediaElementPlayer(this, options));
    2981                 });
    2982             }
    2983             return this;
    2984         };
    2985     }
    2986 
    2987     $(document).ready(function() {
    2988         // auto enable using JSON attribute
    2989         $('.mejs-player').mediaelementplayer();
    2990     });
    2991 
    2992     // push out to window
    2993     window.MediaElementPlayer = mejs.MediaElementPlayer;
    2994 
    2995 })(mejs.$);
    2996 
    2997 (function($) {
    2998 
    2999     $.extend(mejs.MepDefaults, {
    3000         playpauseText: 'Play/Pause'
    3001     });
    3002 
    3003     // PLAY/pause BUTTON
    3004     $.extend(MediaElementPlayer.prototype, {
    3005         buildplaypause: function(player, controls, layers, media) {
    3006             var
    3007                 t = this,
    3008                 play =
    3009                 $('<div class="mejs-button mejs-playpause-button mejs-play" >' +
    3010                     '<button type="button" aria-controls="' + t.id + '" title="' + t.options.playpauseText + '"></button>' +
    3011                 '</div>')
    3012                 .appendTo(controls)
    3013                 .click(function(e) {
    3014                     e.preventDefault();
    3015 
    3016                     if (media.paused) {
    3017                         media.play();
    3018                     } else {
    3019                         media.pause();
    3020                     }
    3021 
    3022                     return false;
    3023                 });
    3024 
    3025             media.addEventListener('play',function() {
    3026                 play.removeClass('mejs-play').addClass('mejs-pause');
    3027             }, false);
    3028             media.addEventListener('playing',function() {
    3029                 play.removeClass('mejs-play').addClass('mejs-pause');
    3030             }, false);
    3031 
    3032 
    3033             media.addEventListener('pause',function() {
    3034                 play.removeClass('mejs-pause').addClass('mejs-play');
    3035             }, false);
    3036             media.addEventListener('paused',function() {
    3037                 play.removeClass('mejs-pause').addClass('mejs-play');
    3038             }, false);
    3039         }
    3040     });
    3041 
    3042 })(mejs.$);
    3043 (function($) {
    3044 
    3045     $.extend(mejs.MepDefaults, {
    3046         stopText: 'Stop'
    3047     });
    3048 
    3049     // STOP BUTTON
    3050     $.extend(MediaElementPlayer.prototype, {
    3051         buildstop: function(player, controls, layers, media) {
    3052             var t = this,
    3053                 stop =
    3054                 $('<div class="mejs-button mejs-stop-button mejs-stop">' +
    3055                     '<button type="button" aria-controls="' + t.id + '" title="' + t.options.stopText + '"></button>' +
    3056                 '</div>')
    3057                 .appendTo(controls)
    3058                 .click(function() {
    3059                     if (!media.paused) {
    3060                         media.pause();
    3061                     }
    3062                     if (media.currentTime > 0) {
    3063                         media.setCurrentTime(0);
    3064                         media.pause();
    3065                         controls.find('.mejs-time-current').width('0px');
    3066                         controls.find('.mejs-time-handle').css('left', '0px');
    3067                         controls.find('.mejs-time-float-current').html( mejs.Utility.secondsToTimeCode(0) );
    3068                         controls.find('.mejs-currenttime').html( mejs.Utility.secondsToTimeCode(0) );
    3069                         layers.find('.mejs-poster').show();
    3070                     }
    3071                 });
    3072         }
    3073     });
    3074 
    3075 })(mejs.$);
    3076 (function($) {
    3077     // progress/loaded bar
    3078     $.extend(MediaElementPlayer.prototype, {
    3079         buildprogress: function(player, controls, layers, media) {
    3080 
    3081             $('<div class="mejs-time-rail">'+
    3082                 '<span class="mejs-time-total">'+
    3083                     '<span class="mejs-time-buffering"></span>'+
    3084                     '<span class="mejs-time-loaded"></span>'+
    3085                     '<span class="mejs-time-current"></span>'+
    3086                     '<span class="mejs-time-handle"></span>'+
    3087                     '<span class="mejs-time-float">' +
    3088                         '<span class="mejs-time-float-current">00:00</span>' +
    3089                         '<span class="mejs-time-float-corner"></span>' +
    3090                     '</span>'+
    3091                 '</span>'+
    3092             '</div>')
    3093                 .appendTo(controls);
    3094                 controls.find('.mejs-time-buffering').hide();
    3095 
    3096             var
    3097                 t = this,
    3098                 total = controls.find('.mejs-time-total'),
    3099                 loaded  = controls.find('.mejs-time-loaded'),
    3100                 current  = controls.find('.mejs-time-current'),
    3101                 handle  = controls.find('.mejs-time-handle'),
    3102                 timefloat  = controls.find('.mejs-time-float'),
    3103                 timefloatcurrent  = controls.find('.mejs-time-float-current'),
    3104                 handleMouseMove = function (e) {
    3105                     // mouse position relative to the object
    3106                     var x = e.pageX,
    3107                         offset = total.offset(),
    3108                         width = total.outerWidth(true),
    3109                         percentage = 0,
    3110                         newTime = 0,
    3111                         pos = 0;
    3112 
    3113 
    3114                     if (media.duration) {
    3115                         if (x < offset.left) {
    3116                             x = offset.left;
    3117                         } else if (x > width + offset.left) {
    3118                             x = width + offset.left;
    3119                         }
    3120 
    3121                         pos = x - offset.left;
    3122                         percentage = (pos / width);
    3123                         newTime = (percentage <= 0.02) ? 0 : percentage * media.duration;
    3124 
    3125                         // seek to where the mouse is
    3126                         if (mouseIsDown && newTime !== media.currentTime) {
    3127                             media.setCurrentTime(newTime);
    3128                         }
    3129 
    3130                         // position floating time box
    3131                         if (!mejs.MediaFeatures.hasTouch) {
    3132                                 timefloat.css('left', pos);
    3133                                 timefloatcurrent.html( mejs.Utility.secondsToTimeCode(newTime) );
    3134                                 timefloat.show();
    3135                         }
    3136                     }
    3137                 },
    3138                 mouseIsDown = false,
    3139                 mouseIsOver = false;
    3140 
    3141             // handle clicks
    3142             //controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove);
    3143             total
    3144                 .bind('mousedown', function (e) {
    3145                     // only handle left clicks
    3146                     if (e.which === 1) {
    3147                         mouseIsDown = true;
    3148                         handleMouseMove(e);
    3149                         t.globalBind('mousemove.dur', function(e) {
    3150                             handleMouseMove(e);
    3151                         });
    3152                         t.globalBind('mouseup.dur', function (e) {
    3153                             mouseIsDown = false;
    3154                             timefloat.hide();
    3155                             t.globalUnbind('.dur');
    3156                         });
    3157                         return false;
    3158                     }
    3159                 })
    3160                 .bind('mouseenter', function(e) {
    3161                     mouseIsOver = true;
    3162                     t.globalBind('mousemove.dur', function(e) {
    3163                         handleMouseMove(e);
    3164                     });
    3165                     if (!mejs.MediaFeatures.hasTouch) {
    3166                         timefloat.show();
    3167                     }
    3168                 })
    3169                 .bind('mouseleave',function(e) {
    3170                     mouseIsOver = false;
    3171                     if (!mouseIsDown) {
    3172                         t.globalUnbind('.dur');
    3173                         timefloat.hide();
    3174                     }
    3175                 });
    3176 
    3177             // loading
    3178             media.addEventListener('progress', function (e) {
    3179                 player.setProgressRail(e);
    3180                 player.setCurrentRail(e);
    3181             }, false);
    3182 
    3183             // current time
    3184             media.addEventListener('timeupdate', function(e) {
    3185                 player.setProgressRail(e);
    3186                 player.setCurrentRail(e);
    3187             }, false);
    3188 
    3189 
    3190             // store for later use
    3191             t.loaded = loaded;
    3192             t.total = total;
    3193             t.current = current;
    3194             t.handle = handle;
    3195         },
    3196         setProgressRail: function(e) {
    3197 
    3198             var
    3199                 t = this,
    3200                 target = (e != undefined) ? e.target : t.media,
    3201                 percent = null;
    3202 
    3203             // newest HTML5 spec has buffered array (FF4, Webkit)
    3204             if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) {
    3205                 // TODO: account for a real array with multiple values (only Firefox 4 has this so far)
    3206                 percent = target.buffered.end(0) / target.duration;
    3207             }
    3208             // Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
    3209             // to be anything other than 0. If the byte count is available we use this instead.
    3210             // Browsers that support the else if do not seem to have the bufferedBytes value and
    3211             // should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
    3212             else if (target && target.bytesTotal != undefined && target.bytesTotal > 0 && target.bufferedBytes != undefined) {
    3213                 percent = target.bufferedBytes / target.bytesTotal;
    3214             }
    3215             // Firefox 3 with an Ogg file seems to go this way
    3216             else if (e && e.lengthComputable && e.total != 0) {
    3217                 percent = e.loaded/e.total;
    3218             }
    3219 
    3220             // finally update the progress bar
    3221             if (percent !== null) {
    3222                 percent = Math.min(1, Math.max(0, percent));
    3223                 // update loaded bar
    3224                 if (t.loaded && t.total) {
    3225                     t.loaded.width(t.total.width() * percent);
    3226                 }
    3227             }
    3228         },
    3229         setCurrentRail: function() {
    3230 
    3231             var t = this;
    3232 
    3233             if (t.media.currentTime != undefined && t.media.duration) {
    3234 
    3235                 // update bar and handle
    3236                 if (t.total && t.handle) {
    3237                     var
    3238                         newWidth = Math.round(t.total.width() * t.media.currentTime / t.media.duration),
    3239                         handlePos = newWidth - Math.round(t.handle.outerWidth(true) / 2);
    3240 
    3241                     t.current.width(newWidth);
    3242                     t.handle.css('left', handlePos);
    3243                 }
    3244             }
    3245 
    3246         }
    3247     });
    3248 })(mejs.$);
    3249 
    3250 (function($) {
    3251 
    3252     // options
    3253     $.extend(mejs.MepDefaults, {
    3254         duration: -1,
    3255         timeAndDurationSeparator: ' <span> | </span> '
    3256     });
    3257 
    3258 
    3259     // current and duration 00:00 / 00:00
    3260     $.extend(MediaElementPlayer.prototype, {
    3261         buildcurrent: function(player, controls, layers, media) {
    3262             var t = this;
    3263 
    3264             $('<div class="mejs-time">'+
    3265                     '<span class="mejs-currenttime">' + (player.options.alwaysShowHours ? '00:' : '')
    3266                     + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')+ '</span>'+
    3267                     '</div>')
    3268                     .appendTo(controls);
    3269 
    3270             t.currenttime = t.controls.find('.mejs-currenttime');
    3271 
    3272             media.addEventListener('timeupdate',function() {
    3273                 player.updateCurrent();
    3274             }, false);
    3275         },
    3276 
    3277 
    3278         buildduration: function(player, controls, layers, media) {
    3279             var t = this;
    3280 
    3281             if (controls.children().last().find('.mejs-currenttime').length > 0) {
    3282                 $(t.options.timeAndDurationSeparator +
    3283                     '<span class="mejs-duration">' +
    3284                         (t.options.duration > 0 ?
    3285                             mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount,  t.options.framesPerSecond || 25) :
    3286                             ((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00'))
    3287                         ) +
    3288                     '</span>')
    3289                     .appendTo(controls.find('.mejs-time'));
    3290             } else {
    3291 
    3292                 // add class to current time
    3293                 controls.find('.mejs-currenttime').parent().addClass('mejs-currenttime-container');
    3294 
    3295                 $('<div class="mejs-time mejs-duration-container">'+
    3296                     '<span class="mejs-duration">' +
    3297                         (t.options.duration > 0 ?
    3298                             mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount,  t.options.framesPerSecond || 25) :
    3299                             ((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00'))
    3300                         ) +
    3301                     '</span>' +
    3302                 '</div>')
    3303                 .appendTo(controls);
    3304             }
    3305 
    3306             t.durationD = t.controls.find('.mejs-duration');
    3307 
    3308             media.addEventListener('timeupdate',function() {
    3309                 player.updateDuration();
    3310             }, false);
    3311         },
    3312 
    3313         updateCurrent:  function() {
    3314             var t = this;
    3315 
    3316             if (t.currenttime) {
    3317                 t.currenttime.html(mejs.Utility.secondsToTimeCode(t.media.currentTime, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount,  t.options.framesPerSecond || 25));
    3318             }
    3319         },
    3320 
    3321         updateDuration: function() {
    3322             var t = this;
    3323 
    3324             //Toggle the long video class if the video is longer than an hour.
    3325             t.container.toggleClass("mejs-long-video", t.media.duration > 3600);
    3326 
    3327             if (t.durationD && (t.options.duration > 0 || t.media.duration)) {
    3328                 t.durationD.html(mejs.Utility.secondsToTimeCode(t.options.duration > 0 ? t.options.duration : t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25));
    3329             }
    3330         }
    3331     });
    3332 
    3333 })(mejs.$);
    3334 (function($) {
    3335 
    3336     $.extend(mejs.MepDefaults, {
    3337         muteText: 'Mute Toggle',
    3338         hideVolumeOnTouchDevices: true,
    3339 
    3340         audioVolume: 'horizontal',
    3341         videoVolume: 'vertical'
    3342     });
    3343 
    3344     $.extend(MediaElementPlayer.prototype, {
    3345         buildvolume: function(player, controls, layers, media) {
    3346 
    3347             // Android and iOS don't support volume controls
    3348             if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices)
    3349                 return;
    3350 
    3351             var t = this,
    3352                 mode = (t.isVideo) ? t.options.videoVolume : t.options.audioVolume,
    3353                 mute = (mode == 'horizontal') ?
    3354 
    3355                 // horizontal version
    3356                 $('<div class="mejs-button mejs-volume-button mejs-mute">'+
    3357                     '<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
    3358                 '</div>' +
    3359                 '<div class="mejs-horizontal-volume-slider">'+ // outer background
    3360                     '<div class="mejs-horizontal-volume-total"></div>'+ // line background
    3361                     '<div class="mejs-horizontal-volume-current"></div>'+ // current volume
    3362                     '<div class="mejs-horizontal-volume-handle"></div>'+ // handle
    3363                 '</div>'
    3364                 )
    3365                     .appendTo(controls) :
    3366 
    3367                 // vertical version
    3368                 $('<div class="mejs-button mejs-volume-button mejs-mute">'+
    3369                     '<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '"></button>'+
    3370                     '<div class="mejs-volume-slider">'+ // outer background
    3371                         '<div class="mejs-volume-total"></div>'+ // line background
    3372                         '<div class="mejs-volume-current"></div>'+ // current volume
    3373                         '<div class="mejs-volume-handle"></div>'+ // handle
    3374                     '</div>'+
    3375                 '</div>')
    3376                     .appendTo(controls),
    3377             volumeSlider = t.container.find('.mejs-volume-slider, .mejs-horizontal-volume-slider'),
    3378             volumeTotal = t.container.find('.mejs-volume-total, .mejs-horizontal-volume-total'),
    3379             volumeCurrent = t.container.find('.mejs-volume-current, .mejs-horizontal-volume-current'),
    3380             volumeHandle = t.container.find('.mejs-volume-handle, .mejs-horizontal-volume-handle'),
    3381 
    3382             positionVolumeHandle = function(volume, secondTry) {
    3383 
    3384                 if (!volumeSlider.is(':visible') && typeof secondTry == 'undefined') {
    3385                     volumeSlider.show();
    3386                     positionVolumeHandle(volume, true);
    3387                     volumeSlider.hide()
    3388                     return;
    3389                 }
    3390 
    3391                 // correct to 0-1
    3392                 volume = Math.max(0,volume);
    3393                 volume = Math.min(volume,1);
    3394 
    3395                 // ajust mute button style
    3396                 if (volume == 0) {
    3397                     mute.removeClass('mejs-mute').addClass('mejs-unmute');
    3398                 } else {
    3399                     mute.removeClass('mejs-unmute').addClass('mejs-mute');
    3400                 }
    3401 
    3402                 // position slider
    3403                 if (mode == 'vertical') {
    3404                     var
    3405 
    3406                         // height of the full size volume slider background
    3407                         totalHeight = volumeTotal.height(),
    3408 
    3409                         // top/left of full size volume slider background
    3410                         totalPosition = volumeTotal.position(),
    3411 
    3412                         // the new top position based on the current volume
    3413                         // 70% volume on 100px height == top:30px
    3414                         newTop = totalHeight - (totalHeight * volume);
    3415 
    3416                     // handle
    3417                     volumeHandle.css('top', Math.round(totalPosition.top + newTop - (volumeHandle.height() / 2)));
    3418 
    3419                     // show the current visibility
    3420                     volumeCurrent.height(totalHeight - newTop );
    3421                     volumeCurrent.css('top', totalPosition.top + newTop);
    3422                 } else {
    3423                     var
    3424 
    3425                         // height of the full size volume slider background
    3426                         totalWidth = volumeTotal.width(),
    3427 
    3428                         // top/left of full size volume slider background
    3429                         totalPosition = volumeTotal.position(),
    3430 
    3431                         // the new left position based on the current volume
    3432                         newLeft = totalWidth * volume;
    3433 
    3434                     // handle
    3435                     volumeHandle.css('left', Math.round(totalPosition.left + newLeft - (volumeHandle.width() / 2)));
    3436 
    3437                     // rezize the current part of the volume bar
    3438                     volumeCurrent.width( Math.round(newLeft) );
    3439                 }
    3440             },
    3441             handleVolumeMove = function(e) {
    3442 
    3443                 var volume = null,
    3444                     totalOffset = volumeTotal.offset();
    3445 
    3446                 // calculate the new volume based on the moust position
    3447                 if (mode == 'vertical') {
    3448 
    3449                     var
    3450                         railHeight = volumeTotal.height(),
    3451                         totalTop = parseInt(volumeTotal.css('top').replace(/px/,''),10),
    3452                         newY = e.pageY - totalOffset.top;
    3453 
    3454                     volume = (railHeight - newY) / railHeight;
    3455 
    3456                     // the controls just hide themselves (usually when mouse moves too far up)
    3457                     if (totalOffset.top == 0 || totalOffset.left == 0)
    3458                         return;
    3459 
    3460                 } else {
    3461                     var
    3462                         railWidth = volumeTotal.width(),
    3463                         newX = e.pageX - totalOffset.left;
    3464 
    3465                     volume = newX / railWidth;
    3466                 }
    3467 
    3468                 // ensure the volume isn't outside 0-1
    3469                 volume = Math.max(0,volume);
    3470                 volume = Math.min(volume,1);
    3471 
    3472                 // position the slider and handle
    3473                 positionVolumeHandle(volume);
    3474 
    3475                 // set the media object (this will trigger the volumechanged event)
    3476                 if (volume == 0) {
    3477                     media.setMuted(true);
    3478                 } else {
    3479                     media.setMuted(false);
    3480                 }
    3481                 media.setVolume(volume);
    3482             },
    3483             mouseIsDown = false,
    3484             mouseIsOver = false;
    3485 
    3486             // SLIDER
    3487 
    3488             mute
    3489                 .hover(function() {
    3490                     volumeSlider.show();
    3491                     mouseIsOver = true;
    3492                 }, function() {
    3493                     mouseIsOver = false;
    3494 
    3495                     if (!mouseIsDown && mode == 'vertical') {
    3496                         volumeSlider.hide();
    3497                     }
    3498                 });
    3499 
    3500             volumeSlider
    3501                 .bind('mouseover', function() {
    3502                     mouseIsOver = true;
    3503                 })
    3504                 .bind('mousedown', function (e) {
    3505                     handleVolumeMove(e);
    3506                     t.globalBind('mousemove.vol', function(e) {
    3507                         handleVolumeMove(e);
    3508                     });
    3509                     t.globalBind('mouseup.vol', function () {
    3510                         mouseIsDown = false;
    3511                         t.globalUnbind('.vol');
    3512 
    3513                         if (!mouseIsOver && mode == 'vertical') {
    3514                             volumeSlider.hide();
    3515                         }
    3516                     });
    3517                     mouseIsDown = true;
    3518 
    3519                     return false;
    3520                 });
    3521 
    3522 
    3523             // MUTE button
    3524             mute.find('button').click(function() {
    3525                 media.setMuted( !media.muted );
    3526             });
    3527 
    3528             // listen for volume change events from other sources
    3529             media.addEventListener('volumechange', function(e) {
    3530                 if (!mouseIsDown) {
    3531                     if (media.muted) {
    3532                         positionVolumeHandle(0);
    3533                         mute.removeClass('mejs-mute').addClass('mejs-unmute');
    3534                     } else {
    3535                         positionVolumeHandle(media.volume);
    3536                         mute.removeClass('mejs-unmute').addClass('mejs-mute');
    3537                     }
    3538                 }
    3539             }, false);
    3540 
    3541             if (t.container.is(':visible')) {
    3542                 // set initial volume
    3543                 positionVolumeHandle(player.options.startVolume);
    3544 
    3545                 // mutes the media and sets the volume icon muted if the initial volume is set to 0
    3546         if (player.options.startVolume === 0) {
    3547           media.setMuted(true);
    3548         }
    3549 
    3550                 // shim gets the startvolume as a parameter, but we have to set it on the native <video> and <audio> elements
    3551                 if (media.pluginType === 'native') {
    3552                     media.setVolume(player.options.startVolume);
    3553                 }
    3554             }
    3555         }
    3556     });
    3557 
    3558 })(mejs.$);
    3559 
    3560 (function($) {
    3561 
    3562     $.extend(mejs.MepDefaults, {
    3563         usePluginFullScreen: true,
    3564         newWindowCallback: function() { return '';},
    3565         fullscreenText: mejs.i18n.t('Fullscreen')
    3566     });
    3567 
    3568     $.extend(MediaElementPlayer.prototype, {
    3569 
    3570         isFullScreen: false,
    3571 
    3572         isNativeFullScreen: false,
    3573 
    3574         docStyleOverflow: null,
    3575 
    3576         isInIframe: false,
    3577 
    3578         buildfullscreen: function(player, controls, layers, media) {
    3579 
    3580             if (!player.isVideo)
    3581                 return;
    3582 
    3583             player.isInIframe = (window.location != window.parent.location);
    3584 
    3585             // native events
    3586             if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
    3587 
    3588                 // chrome doesn't alays fire this in an iframe
    3589                 var func = function(e) {
    3590 
    3591                     if (mejs.MediaFeatures.isFullScreen()) {
    3592                         player.isNativeFullScreen = true;
    3593                         // reset the controls once we are fully in full screen
    3594                         player.setControlsSize();
    3595                     } else {
    3596                         player.isNativeFullScreen = false;
    3597                         // when a user presses ESC
    3598                         // make sure to put the player back into place
    3599                         player.exitFullScreen();
    3600                     }
    3601                 };
    3602 
    3603                 if (mejs.MediaFeatures.hasMozNativeFullScreen) {
    3604                     player.globalBind(mejs.MediaFeatures.fullScreenEventName, func);
    3605                 } else {
    3606                     player.container.bind(mejs.MediaFeatures.fullScreenEventName, func);
    3607                 }
    3608             }
    3609 
    3610             var t = this,
    3611                 normalHeight = 0,
    3612                 normalWidth = 0,
    3613                 container = player.container,
    3614                 fullscreenBtn =
    3615                     $('<div class="mejs-button mejs-fullscreen-button">' +
    3616                         '<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '"></button>' +
    3617                     '</div>')
    3618                     .appendTo(controls);
    3619 
    3620                 if (t.media.pluginType === 'native' || (!t.options.usePluginFullScreen && !mejs.MediaFeatures.isFirefox)) {
    3621 
    3622                     fullscreenBtn.click(function() {
    3623                         var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen;
    3624 
    3625                         if (isFullScreen) {
    3626                             player.exitFullScreen();
    3627                         } else {
    3628                             player.enterFullScreen();
    3629                         }
    3630                     });
    3631 
    3632                 } else {
    3633 
    3634                     var hideTimeout = null,
    3635                         supportsPointerEvents = (function() {
    3636                             // TAKEN FROM MODERNIZR
    3637                             var element = document.createElement('x'),
    3638                                 documentElement = document.documentElement,
    3639                                 getComputedStyle = window.getComputedStyle,
    3640                                 supports;
    3641                             if(!('pointerEvents' in element.style)){
    3642                                 return false;
    3643                             }
    3644                             element.style.pointerEvents = 'auto';
    3645                             element.style.pointerEvents = 'x';
    3646                             documentElement.appendChild(element);
    3647                             supports = getComputedStyle &&
    3648                                 getComputedStyle(element, '').pointerEvents === 'auto';
    3649                             documentElement.removeChild(element);
    3650                             return !!supports;
    3651                         })();
    3652 
    3653                     //console.log('supportsPointerEvents', supportsPointerEvents);
    3654 
    3655                     if (supportsPointerEvents && !mejs.MediaFeatures.isOpera) { // opera doesn't allow this :(
    3656 
    3657                         // allows clicking through the fullscreen button and controls down directly to Flash
    3658 
    3659                         /*
    3660                          When a user puts his mouse over the fullscreen button, the controls are disabled
    3661                          So we put a div over the video and another one on iether side of the fullscreen button
    3662                          that caputre mouse movement
    3663                          and restore the controls once the mouse moves outside of the fullscreen button
    3664                         */
    3665 
    3666                         var fullscreenIsDisabled = false,
    3667                             restoreControls = function() {
    3668                                 if (fullscreenIsDisabled) {
    3669                                     // hide the hovers
    3670                                     videoHoverDiv.hide();
    3671                                     controlsLeftHoverDiv.hide();
    3672                                     controlsRightHoverDiv.hide();
    3673 
    3674                                     // restore the control bar
    3675                                     fullscreenBtn.css('pointer-events', '');
    3676                                     t.controls.css('pointer-events', '');
    3677 
    3678                                     // store for later
    3679                                     fullscreenIsDisabled = false;
    3680                                 }
    3681                             },
    3682                             videoHoverDiv = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls),
    3683                             controlsLeftHoverDiv = $('<div class="mejs-fullscreen-hover"  />').appendTo(t.container).mouseover(restoreControls),
    3684                             controlsRightHoverDiv = $('<div class="mejs-fullscreen-hover"  />').appendTo(t.container).mouseover(restoreControls),
    3685                             positionHoverDivs = function() {
    3686                                 var style = {position: 'absolute', top: 0, left: 0}; //, backgroundColor: '#f00'};
    3687                                 videoHoverDiv.css(style);
    3688                                 controlsLeftHoverDiv.css(style);
    3689                                 controlsRightHoverDiv.css(style);
    3690 
    3691                                 // over video, but not controls
    3692                                 videoHoverDiv
    3693                                     .width( t.container.width() )
    3694                                     .height( t.container.height() - t.controls.height() );
    3695 
    3696                                 // over controls, but not the fullscreen button
    3697                                 var fullScreenBtnOffset = fullscreenBtn.offset().left - t.container.offset().left;
    3698                                     fullScreenBtnWidth = fullscreenBtn.outerWidth(true);
    3699 
    3700                                 controlsLeftHoverDiv
    3701                                     .width( fullScreenBtnOffset )
    3702                                     .height( t.controls.height() )
    3703                                     .css({top: t.container.height() - t.controls.height()});
    3704 
    3705                                 // after the fullscreen button
    3706                                 controlsRightHoverDiv
    3707                                     .width( t.container.width() - fullScreenBtnOffset - fullScreenBtnWidth )
    3708                                     .height( t.controls.height() )
    3709                                     .css({top: t.container.height() - t.controls.height(),
    3710                                          left: fullScreenBtnOffset + fullScreenBtnWidth});
    3711                             };
    3712 
    3713                         t.globalBind('resize', function() {
    3714                             positionHoverDivs();
    3715                         });
    3716 
    3717                         // on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash
    3718                         fullscreenBtn
    3719                             .mouseover(function() {
    3720 
    3721                                 if (!t.isFullScreen) {
    3722 
    3723                                     var buttonPos = fullscreenBtn.offset(),
    3724                                         containerPos = player.container.offset();
    3725 
    3726                                     // move the button in Flash into place
    3727                                     media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false);
    3728 
    3729                                     // allows click through
    3730                                     fullscreenBtn.css('pointer-events', 'none');
    3731                                     t.controls.css('pointer-events', 'none');
    3732 
    3733                                     // show the divs that will restore things
    3734                                     videoHoverDiv.show();
    3735                                     controlsRightHoverDiv.show();
    3736                                     controlsLeftHoverDiv.show();
    3737                                     positionHoverDivs();
    3738 
    3739                                     fullscreenIsDisabled = true;
    3740                                 }
    3741 
    3742                             });
    3743 
    3744                         // restore controls anytime the user enters or leaves fullscreen
    3745                         media.addEventListener('fullscreenchange', function(e) {
    3746                             restoreControls();
    3747                         });
    3748 
    3749 
    3750                         // the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events
    3751                         // so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button
    3752                         /*
    3753                         t.globalBind('mousemove', function(e) {
    3754 
    3755                             // if the mouse is anywhere but the fullsceen button, then restore it all
    3756                             if (fullscreenIsDisabled) {
    3757 
    3758                                 var fullscreenBtnPos = fullscreenBtn.offset();
    3759 
    3760 
    3761                                 if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) ||
    3762                                     e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true)
    3763                                     ) {
    3764 
    3765                                     fullscreenBtn.css('pointer-events', '');
    3766                                     t.controls.css('pointer-events', '');
    3767 
    3768                                     fullscreenIsDisabled = false;
    3769                                 }
    3770                             }
    3771                         });
    3772                         */
    3773 
    3774 
    3775                     } else {
    3776 
    3777                         // the hover state will show the fullscreen button in Flash to hover up and click
    3778 
    3779                         fullscreenBtn
    3780                             .mouseover(function() {
    3781 
    3782                                 if (hideTimeout !== null) {
    3783                                     clearTimeout(hideTimeout);
    3784                                     delete hideTimeout;
    3785                                 }
    3786 
    3787                                 var buttonPos = fullscreenBtn.offset(),
    3788                                     containerPos = player.container.offset();
    3789 
    3790                                 media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true);
    3791 
    3792                             })
    3793                             .mouseout(function() {
    3794 
    3795                                 if (hideTimeout !== null) {
    3796                                     clearTimeout(hideTimeout);
    3797                                     delete hideTimeout;
    3798                                 }
    3799 
    3800                                 hideTimeout = setTimeout(function() {
    3801                                     media.hideFullscreenButton();
    3802                                 }, 1500);
    3803 
    3804 
    3805                             });
    3806                     }
    3807                 }
    3808 
    3809             player.fullscreenBtn = fullscreenBtn;
    3810 
    3811             t.globalBind('keydown',function (e) {
    3812                 if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) {
    3813                     player.exitFullScreen();
    3814                 }
    3815             });
    3816 
    3817         },
    3818 
    3819         cleanfullscreen: function(player) {
    3820             player.exitFullScreen();
    3821         },
    3822 
    3823         enterFullScreen: function() {
    3824 
    3825             var t = this;
    3826 
    3827             // firefox+flash can't adjust plugin sizes without resetting :(
    3828             if (t.media.pluginType !== 'native' && (mejs.MediaFeatures.isFirefox || t.options.usePluginFullScreen)) {
    3829                 //t.media.setFullscreen(true);
    3830                 //player.isFullScreen = true;
    3831                 return;
    3832             }
    3833 
    3834             // store overflow
    3835             docStyleOverflow = document.documentElement.style.overflow;
    3836             // set it to not show scroll bars so 100% will work
    3837             document.documentElement.style.overflow = 'hidden';
    3838 
    3839             // store sizing
    3840             normalHeight = t.container.height();
    3841             normalWidth = t.container.width();
    3842 
    3843             // attempt to do true fullscreen (Safari 5.1 and Firefox Nightly only for now)
    3844             if (t.media.pluginType === 'native') {
    3845                 if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
    3846 
    3847                     mejs.MediaFeatures.requestFullScreen(t.container[0]);
    3848                     //return;
    3849 
    3850                     if (t.isInIframe) {
    3851                         // sometimes exiting from fullscreen doesn't work
    3852                         // notably in Chrome <iframe>. Fixed in version 17
    3853                         setTimeout(function checkFullscreen() {
    3854 
    3855                             if (t.isNativeFullScreen) {
    3856 
    3857                                 // check if the video is suddenly not really fullscreen
    3858                                 if ($(window).width() !== screen.width) {
    3859                                     // manually exit
    3860                                     t.exitFullScreen();
    3861                                 } else {
    3862                                     // test again
    3863                                     setTimeout(checkFullscreen, 500);
    3864                                 }
    3865                             }
    3866 
    3867 
    3868                         }, 500);
    3869                     }
    3870 
    3871                 } else if (mejs.MediaFeatures.hasSemiNativeFullScreen) {
    3872                     t.media.webkitEnterFullscreen();
    3873                     return;
    3874                 }
    3875             }
    3876 
    3877             // check for iframe launch
    3878             if (t.isInIframe) {
    3879                 var url = t.options.newWindowCallback(this);
    3880 
    3881 
    3882                 if (url !== '') {
    3883 
    3884                     // launch immediately
    3885                     if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
    3886                         t.pause();
    3887                         window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
    3888                         return;
    3889                     } else {
    3890                         setTimeout(function() {
    3891                             if (!t.isNativeFullScreen) {
    3892                                 t.pause();
    3893                                 window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no');
    3894                             }
    3895                         }, 250);
    3896                     }
    3897                 }
    3898 
    3899             }
    3900 
    3901             // full window code
    3902 
    3903 
    3904 
    3905             // make full size
    3906             t.container
    3907                 .addClass('mejs-container-fullscreen')
    3908                 .width('100%')
    3909                 .height('100%');
    3910                 //.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000});
    3911 
    3912             // Only needed for safari 5.1 native full screen, can cause display issues elsewhere
    3913             // Actually, it seems to be needed for IE8, too
    3914             //if (mejs.MediaFeatures.hasTrueNativeFullScreen) {
    3915                 setTimeout(function() {
    3916                     t.container.css({width: '100%', height: '100%'});
    3917                     t.setControlsSize();
    3918                 }, 500);
    3919             //}
    3920 
    3921             if (t.pluginType === 'native') {
    3922                 t.$media
    3923                     .width('100%')
    3924                     .height('100%');
    3925             } else {
    3926                 t.container.find('.mejs-shim')
    3927                     .width('100%')
    3928                     .height('100%');
    3929 
    3930                 //if (!mejs.MediaFeatures.hasTrueNativeFullScreen) {
    3931                     t.media.setVideoSize($(window).width(),$(window).height());
    3932                 //}
    3933             }
    3934 
    3935             t.layers.children('div')
    3936                 .width('100%')
    3937                 .height('100%');
    3938 
    3939             if (t.fullscreenBtn) {
    3940                 t.fullscreenBtn
    3941                     .removeClass('mejs-fullscreen')
    3942                     .addClass('mejs-unfullscreen');
    3943             }
    3944 
    3945             t.setControlsSize();
    3946             t.isFullScreen = true;
    3947         },
    3948 
    3949         exitFullScreen: function() {
    3950 
    3951             var t = this;
    3952 
    3953             // firefox can't adjust plugins
    3954             if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) {
    3955                 t.media.setFullscreen(false);
    3956                 //player.isFullScreen = false;
    3957                 return;
    3958             }
    3959 
    3960             // come outo of native fullscreen
    3961             if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) {
    3962                 mejs.MediaFeatures.cancelFullScreen();
    3963             }
    3964 
    3965             // restore scroll bars to document
    3966             document.documentElement.style.overflow = docStyleOverflow;
    3967 
    3968             t.container
    3969                 .removeClass('mejs-container-fullscreen')
    3970                 .width(normalWidth)
    3971                 .height(normalHeight);
    3972                 //.css({position: '', left: '', top: '', right: '', bottom: '', overflow: 'inherit', width: normalWidth + 'px', height: normalHeight + 'px', 'z-index': 1});
    3973 
    3974             if (t.pluginType === 'native') {
    3975                 t.$media
    3976                     .width(normalWidth)
    3977                     .height(normalHeight);
    3978             } else {
    3979                 t.container.find('object embed')
    3980                     .width(normalWidth)
    3981                     .height(normalHeight);
    3982 
    3983                 t.media.setVideoSize(normalWidth, normalHeight);
    3984             }
    3985 
    3986             t.layers.children('div')
    3987                 .width(normalWidth)
    3988                 .height(normalHeight);
    3989 
    3990             t.fullscreenBtn
    3991                 .removeClass('mejs-unfullscreen')
    3992                 .addClass('mejs-fullscreen');
    3993 
    3994             t.setControlsSize();
    3995             t.isFullScreen = false;
    3996         }
    3997     });
    3998 
    3999 })(mejs.$);
    4000 
    4001 (function($) {
    4002 
    4003     // add extra default options
    4004     $.extend(mejs.MepDefaults, {
    4005         // this will automatically turn on a <track>
    4006         startLanguage: '',
    4007 
    4008         tracksText: 'Captions/Subtitles',
    4009 
    4010         // option to remove the [cc] button when no <track kind="subtitles"> are present
    4011         hideCaptionsButtonWhenEmpty: true,
    4012 
    4013         // If true and we only have one track, change captions to popup
    4014         toggleCaptionsButtonWhenOnlyOne: false,
    4015 
    4016         // #id or .class
    4017         slidesSelector: ''
    4018     });
    4019 
    4020     $.extend(MediaElementPlayer.prototype, {
    4021 
    4022         hasChapters: false,
    4023 
    4024         buildtracks: function(player, controls, layers, media) {
    4025             if (!player.isVideo)
    4026                 return;
    4027 
    4028             if (player.tracks.length == 0)
    4029                 return;
    4030 
    4031             var t = this,
    4032                 i,
    4033                 options = '';
    4034 
    4035             player.chapters =
    4036                     $('<div class="mejs-chapters mejs-layer"></div>')
    4037                         .prependTo(layers).hide();
    4038             player.captions =
    4039                     $('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>')
    4040                         .prependTo(layers).hide();
    4041             player.captionsText = player.captions.find('.mejs-captions-text');
    4042             player.captionsButton =
    4043                     $('<div class="mejs-button mejs-captions-button">'+
    4044                         '<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '"></button>'+
    4045                         '<div class="mejs-captions-selector">'+
    4046                             '<ul>'+
    4047                                 '<li>'+
    4048                                     '<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' +
    4049                                     '<label for="' + player.id + '_captions_none">None</label>'+
    4050                                 '</li>' +
    4051                             '</ul>'+
    4052                         '</div>'+
    4053                     '</div>')
    4054                         .appendTo(controls);
    4055 
    4056 
    4057             var subtitleCount = 0;
    4058             for (i=0; i<player.tracks.length; i++) {
    4059                 if (player.tracks[i].kind == 'subtitles') {
    4060                     subtitleCount++;
    4061                 }
    4062             }
    4063 
    4064             // if only one language then just make the button a toggle
    4065             if (t.options.toggleCaptionsButtonWhenOnlyOne && subtitleCount == 1){
    4066                 // click
    4067                 player.captionsButton.on('click',function() {
    4068                     if (player.selectedTrack == null) {
    4069                         var lang = player.tracks[0].srclang;
    4070                     } else {
    4071                         var lang = 'none';
    4072                     }
    4073                     player.setTrack(lang);
    4074                 });
    4075             } else {
    4076                 // hover
    4077                 player.captionsButton.hover(function() {
    4078                     $(this).find('.mejs-captions-selector').css('visibility','visible');
    4079                 }, function() {
    4080                     $(this).find('.mejs-captions-selector').css('visibility','hidden');
    4081                 })
    4082 
    4083                 // handle clicks to the language radio buttons
    4084                 .on('click','input[type=radio]',function() {
    4085                     lang = this.value;
    4086                     player.setTrack(lang);
    4087                 });
    4088 
    4089             }
    4090 
    4091             if (!player.options.alwaysShowControls) {
    4092                 // move with controls
    4093                 player.container
    4094                     .bind('controlsshown', function () {
    4095                         // push captions above controls
    4096                         player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
    4097 
    4098                     })
    4099                     .bind('controlshidden', function () {
    4100                         if (!media.paused) {
    4101                             // move back to normal place
    4102                             player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover');
    4103                         }
    4104                     });
    4105             } else {
    4106                 player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
    4107             }
    4108 
    4109             player.trackToLoad = -1;
    4110             player.selectedTrack = null;
    4111             player.isLoadingTrack = false;
    4112 
    4113 
    4114 
    4115             // add to list
    4116             for (i=0; i<player.tracks.length; i++) {
    4117                 if (player.tracks[i].kind == 'subtitles') {
    4118                     player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label);
    4119                 }
    4120             }
    4121 
    4122             // start loading tracks
    4123             player.loadNextTrack();
    4124 
    4125 
    4126             media.addEventListener('timeupdate',function(e) {
    4127                 player.displayCaptions();
    4128             }, false);
    4129 
    4130             if (player.options.slidesSelector != '') {
    4131                 player.slidesContainer = $(player.options.slidesSelector);
    4132 
    4133                 media.addEventListener('timeupdate',function(e) {
    4134                     player.displaySlides();
    4135                 }, false);
    4136 
    4137             }
    4138 
    4139             media.addEventListener('loadedmetadata', function(e) {
    4140                 player.displayChapters();
    4141             }, false);
    4142 
    4143             player.container.hover(
    4144                 function () {
    4145                     // chapters
    4146                     if (player.hasChapters) {
    4147                         player.chapters.css('visibility','visible');
    4148                         player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight());
    4149                     }
    4150                 },
    4151                 function () {
    4152                     if (player.hasChapters && !media.paused) {
    4153                         player.chapters.fadeOut(200, function() {
    4154                             $(this).css('visibility','hidden');
    4155                             $(this).css('display','block');
    4156                         });
    4157                     }
    4158                 });
    4159 
    4160             // check for autoplay
    4161             if (player.node.getAttribute('autoplay') !== null) {
    4162                 player.chapters.css('visibility','hidden');
    4163             }
    4164         },
    4165 
    4166         setTrack: function(lang){
    4167 
    4168             var t = this,
    4169                 i;
    4170 
    4171             if (lang == 'none') {
    4172                 t.selectedTrack = null;
    4173                 t.captionsButton.removeClass('mejs-captions-enabled');
    4174             } else {
    4175                 for (i=0; i<t.tracks.length; i++) {
    4176                     if (t.tracks[i].srclang == lang) {
    4177                         if (t.selectedTrack == null)
    4178                             t.captionsButton.addClass('mejs-captions-enabled');
    4179                         t.selectedTrack = t.tracks[i];
    4180                         t.captions.attr('lang', t.selectedTrack.srclang);
    4181                         t.displayCaptions();
    4182                         break;
    4183                     }
    4184                 }
    4185             }
    4186         },
    4187 
    4188         loadNextTrack: function() {
    4189             var t = this;
    4190 
    4191             t.trackToLoad++;
    4192             if (t.trackToLoad < t.tracks.length) {
    4193                 t.isLoadingTrack = true;
    4194                 t.loadTrack(t.trackToLoad);
    4195             } else {
    4196                 // add done?
    4197                 t.isLoadingTrack = false;
    4198 
    4199                 t.checkForTracks();
    4200             }
    4201         },
    4202 
    4203         loadTrack: function(index){
    4204             var
    4205                 t = this,
    4206                 track = t.tracks[index],
    4207                 after = function() {
    4208 
    4209                     track.isLoaded = true;
    4210 
    4211                     // create button
    4212                     //t.addTrackButton(track.srclang);
    4213                     t.enableTrackButton(track.srclang, track.label);
    4214 
    4215                     t.loadNextTrack();
    4216 
    4217                 };
    4218 
    4219 
    4220             $.ajax({
    4221                 url: track.src,
    4222                 dataType: "text",
    4223                 success: function(d) {
    4224 
    4225                     // parse the loaded file
    4226                     if (typeof d == "string" && (/<tt\s+xml/ig).exec(d)) {
    4227                         track.entries = mejs.TrackFormatParser.dfxp.parse(d);
    4228                     } else {
    4229                         track.entries = mejs.TrackFormatParser.webvvt.parse(d);
    4230                     }
    4231 
    4232                     after();
    4233 
    4234                     if (track.kind == 'chapters') {
    4235                         t.media.addEventListener('play', function(e) {
    4236                             if (t.media.duration > 0) {
    4237                                 t.displayChapters(track);
    4238                             }
    4239                         }, false);
    4240                     }
    4241 
    4242                     if (track.kind == 'slides') {
    4243                         t.setupSlides(track);
    4244                     }
    4245                 },
    4246                 error: function() {
    4247                     t.loadNextTrack();
    4248                 }
    4249             });
    4250         },
    4251 
    4252         enableTrackButton: function(lang, label) {
    4253             var t = this;
    4254 
    4255             if (label === '') {
    4256                 label = mejs.language.codes[lang] || lang;
    4257             }
    4258 
    4259             t.captionsButton
    4260                 .find('input[value=' + lang + ']')
    4261                     .prop('disabled',false)
    4262                 .siblings('label')
    4263                     .html( label );
    4264 
    4265             // auto select
    4266             if (t.options.startLanguage == lang) {
    4267                 $('#' + t.id + '_captions_' + lang).click();
    4268             }
    4269 
    4270             t.adjustLanguageBox();
    4271         },
    4272 
    4273         addTrackButton: function(lang, label) {
    4274             var t = this;
    4275             if (label === '') {
    4276                 label = mejs.language.codes[lang] || lang;
    4277             }
    4278 
    4279             t.captionsButton.find('ul').append(
    4280                 $('<li>'+
    4281                     '<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' +
    4282                     '<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+
    4283                 '</li>')
    4284             );
    4285 
    4286             t.adjustLanguageBox();
    4287 
    4288             // remove this from the dropdownlist (if it exists)
    4289             t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove();
    4290         },
    4291 
    4292         adjustLanguageBox:function() {
    4293             var t = this;
    4294             // adjust the size of the outer box
    4295             t.captionsButton.find('.mejs-captions-selector').height(
    4296                 t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) +
    4297                 t.captionsButton.find('.mejs-captions-translations').outerHeight(true)
    4298             );
    4299         },
    4300 
    4301         checkForTracks: function() {
    4302             var
    4303                 t = this,
    4304                 hasSubtitles = false;
    4305 
    4306             // check if any subtitles
    4307             if (t.options.hideCaptionsButtonWhenEmpty) {
    4308                 for (i=0; i<t.tracks.length; i++) {
    4309                     if (t.tracks[i].kind == 'subtitles') {
    4310                         hasSubtitles = true;
    4311                         break;
    4312                     }
    4313                 }
    4314 
    4315                 if (!hasSubtitles) {
    4316                     t.captionsButton.hide();
    4317                     t.setControlsSize();
    4318                 }
    4319             }
    4320         },
    4321 
    4322         displayCaptions: function() {
    4323 
    4324             if (typeof this.tracks == 'undefined')
    4325                 return;
    4326 
    4327             var
    4328                 t = this,
    4329                 i,
    4330                 track = t.selectedTrack;
    4331 
    4332             if (track != null && track.isLoaded) {
    4333                 for (i=0; i<track.entries.times.length; i++) {
    4334                     if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){
    4335                         t.captionsText.html(track.entries.text[i]);
    4336                         t.captions.show().height(0);
    4337                         return; // exit out if one is visible;
    4338                     }
    4339                 }
    4340                 t.captions.hide();
    4341             } else {
    4342                 t.captions.hide();
    4343             }
    4344         },
    4345 
    4346         setupSlides: function(track) {
    4347             var t = this;
    4348 
    4349             t.slides = track;
    4350             t.slides.entries.imgs = [t.slides.entries.text.length];
    4351             t.showSlide(0);
    4352 
    4353         },
    4354 
    4355         showSlide: function(index) {
    4356             if (typeof this.tracks == 'undefined' || typeof this.slidesContainer == 'undefined') {
    4357                 return;
    4358             }
    4359 
    4360             var t = this,
    4361                 url = t.slides.entries.text[index],
    4362                 img = t.slides.entries.imgs[index];
    4363 
    4364             if (typeof img == 'undefined' || typeof img.fadeIn == 'undefined') {
    4365 
    4366                 t.slides.entries.imgs[index] = img = $('<img src="' + url + '">')
    4367                         .on('load', function() {
    4368                             img.appendTo(t.slidesContainer)
    4369                                 .hide()
    4370                                 .fadeIn()
    4371                                 .siblings(':visible')
    4372                                     .fadeOut();
    4373 
    4374                         });
    4375 
    4376             } else {
    4377 
    4378                 if (!img.is(':visible') && !img.is(':animated')) {
    4379 
    4380                     console.log('showing existing slide');
    4381 
    4382                     img.fadeIn()
    4383                         .siblings(':visible')
    4384                             .fadeOut();
    4385                 }
    4386             }
    4387 
    4388         },
    4389 
    4390         displaySlides: function() {
    4391 
    4392             if (typeof this.slides == 'undefined')
    4393                 return;
    4394 
    4395             var
    4396                 t = this,
    4397                 slides = t.slides,
    4398                 i;
    4399 
    4400             for (i=0; i<slides.entries.times.length; i++) {
    4401                 if (t.media.currentTime >= slides.entries.times[i].start && t.media.currentTime <= slides.entries.times[i].stop){
    4402 
    4403                     t.showSlide(i);
    4404 
    4405                     return; // exit out if one is visible;
    4406                 }
    4407             }
    4408         },
    4409 
    4410         displayChapters: function() {
    4411             var
    4412                 t = this,
    4413                 i;
    4414 
    4415             for (i=0; i<t.tracks.length; i++) {
    4416                 if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) {
    4417                     t.drawChapters(t.tracks[i]);
    4418                     t.hasChapters = true;
    4419                     break;
    4420                 }
    4421             }
    4422         },
    4423 
    4424         drawChapters: function(chapters) {
    4425             var
    4426                 t = this,
    4427                 i,
    4428                 dur,
    4429                 //width,
    4430                 //left,
    4431                 percent = 0,
    4432                 usedPercent = 0;
    4433 
    4434             t.chapters.empty();
    4435 
    4436             for (i=0; i<chapters.entries.times.length; i++) {
    4437                 dur = chapters.entries.times[i].stop - chapters.entries.times[i].start;
    4438                 percent = Math.floor(dur / t.media.duration * 100);
    4439                 if (percent + usedPercent > 100 || // too large
    4440                     i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in
    4441                     {
    4442                     percent = 100 - usedPercent;
    4443                 }
    4444                 //width = Math.floor(t.width * dur / t.media.duration);
    4445                 //left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration);
    4446                 //if (left + width > t.width) {
    4447                 //  width = t.width - left;
    4448                 //}
    4449 
    4450                 t.chapters.append( $(
    4451                     '<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' +
    4452                         '<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' +
    4453                             '<span class="ch-title">' + chapters.entries.text[i] + '</span>' +
    4454                             '<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '&ndash;' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' +
    4455                         '</div>' +
    4456                     '</div>'));
    4457                 usedPercent += percent;
    4458             }
    4459 
    4460             t.chapters.find('div.mejs-chapter').click(function() {
    4461                 t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) );
    4462                 if (t.media.paused) {
    4463                     t.media.play();
    4464                 }
    4465             });
    4466 
    4467             t.chapters.show();
    4468         }
    4469     });
    4470 
    4471 
    4472 
    4473     mejs.language = {
    4474         codes:  {
    4475             af:'Afrikaans',
    4476             sq:'Albanian',
    4477             ar:'Arabic',
    4478             be:'Belarusian',
    4479             bg:'Bulgarian',
    4480             ca:'Catalan',
    4481             zh:'Chinese',
    4482             'zh-cn':'Chinese Simplified',
    4483             'zh-tw':'Chinese Traditional',
    4484             hr:'Croatian',
    4485             cs:'Czech',
    4486             da:'Danish',
    4487             nl:'Dutch',
    4488             en:'English',
    4489             et:'Estonian',
    4490             tl:'Filipino',
    4491             fi:'Finnish',
    4492             fr:'French',
    4493             gl:'Galician',
    4494             de:'German',
    4495             el:'Greek',
    4496             ht:'Haitian Creole',
    4497             iw:'Hebrew',
    4498             hi:'Hindi',
    4499             hu:'Hungarian',
    4500             is:'Icelandic',
    4501             id:'Indonesian',
    4502             ga:'Irish',
    4503             it:'Italian',
    4504             ja:'Japanese',
    4505             ko:'Korean',
    4506             lv:'Latvian',
    4507             lt:'Lithuanian',
    4508             mk:'Macedonian',
    4509             ms:'Malay',
    4510             mt:'Maltese',
    4511             no:'Norwegian',
    4512             fa:'Persian',
    4513             pl:'Polish',
    4514             pt:'Portuguese',
    4515             //'pt-pt':'Portuguese (Portugal)',
    4516             ro:'Romanian',
    4517             ru:'Russian',
    4518             sr:'Serbian',
    4519             sk:'Slovak',
    4520             sl:'Slovenian',
    4521             es:'Spanish',
    4522             sw:'Swahili',
    4523             sv:'Swedish',
    4524             tl:'Tagalog',
    4525             th:'Thai',
    4526             tr:'Turkish',
    4527             uk:'Ukrainian',
    4528             vi:'Vietnamese',
    4529             cy:'Welsh',
    4530             yi:'Yiddish'
    4531         }
    4532     };
    4533 
    4534     /*
    4535     Parses WebVVT format which should be formatted as
    4536     ================================
    4537     WEBVTT
    4538 
    4539     1
    4540     00:00:01,1 --> 00:00:05,000
    4541     A line of text
    4542 
    4543     2
    4544     00:01:15,1 --> 00:02:05,000
    4545     A second line of text
    4546 
    4547     ===============================
    4548 
    4549     Adapted from: http://www.delphiki.com/html5/playr
    4550     */
    4551     mejs.TrackFormatParser = {
    4552         webvvt: {
    4553             // match start "chapter-" (or anythingelse)
    4554             pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/,
    4555             pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,
    4556 
    4557             parse: function(trackText) {
    4558                 var
    4559                     i = 0,
    4560                     lines = mejs.TrackFormatParser.split2(trackText, /\r?\n/),
    4561                     entries = {text:[], times:[]},
    4562                     timecode,
    4563                     text;
    4564                 for(; i<lines.length; i++) {
    4565                     // check for the line number
    4566                     if (this.pattern_identifier.exec(lines[i])){
    4567                         // skip to the next line where the start --> end time code should be
    4568                         i++;
    4569                         timecode = this.pattern_timecode.exec(lines[i]);
    4570 
    4571                         if (timecode && i<lines.length){
    4572                             i++;
    4573                             // grab all the (possibly multi-line) text that follows
    4574                             text = lines[i];
    4575                             i++;
    4576                             while(lines[i] !== '' && i<lines.length){
    4577                                 text = text + '\n' + lines[i];
    4578                                 i++;
    4579                             }
    4580                             text = $.trim(text).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>");
    4581                             // Text is in a different array so I can use .join
    4582                             entries.text.push(text);
    4583                             entries.times.push(
    4584                             {
    4585                                 start: (mejs.Utility.convertSMPTEtoSeconds(timecode[1]) == 0) ? 0.200 : mejs.Utility.convertSMPTEtoSeconds(timecode[1]),
    4586                                 stop: mejs.Utility.convertSMPTEtoSeconds(timecode[3]),
    4587                                 settings: timecode[5]
    4588                             });
    4589                         }
    4590                     }
    4591                 }
    4592                 return entries;
    4593             }
    4594         },
    4595         // Thanks to Justin Capella: https://github.com/johndyer/mediaelement/pull/420
    4596         dfxp: {
    4597             parse: function(trackText) {
    4598                 trackText = $(trackText).filter("tt");
    4599                 var
    4600                     i = 0,
    4601                     container = trackText.children("div").eq(0),
    4602                     lines = container.find("p"),
    4603                     styleNode = trackText.find("#" + container.attr("style")),
    4604                     styles,
    4605                     begin,
    4606                     end,
    4607                     text,
    4608                     entries = {text:[], times:[]};
    4609 
    4610 
    4611                 if (styleNode.length) {
    4612                     var attributes = styleNode.removeAttr("id").get(0).attributes;
    4613                     if (attributes.length) {
    4614                         styles = {};
    4615                         for (i = 0; i < attributes.length; i++) {
    4616                             styles[attributes[i].name.split(":")[1]] = attributes[i].value;
    4617                         }
    4618                     }
    4619                 }
    4620 
    4621                 for(i = 0; i<lines.length; i++) {
    4622                     var style;
    4623                     var _temp_times = {
    4624                         start: null,
    4625                         stop: null,
    4626                         style: null
    4627                     };
    4628                     if (lines.eq(i).attr("begin")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("begin"));
    4629                     if (!_temp_times.start && lines.eq(i-1).attr("end")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i-1).attr("end"));
    4630                     if (lines.eq(i).attr("end")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("end"));
    4631                     if (!_temp_times.stop && lines.eq(i+1).attr("begin")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i+1).attr("begin"));
    4632                     if (styles) {
    4633                         style = "";
    4634                         for (var _style in styles) {
    4635                             style += _style + ":" + styles[_style] + ";";
    4636                         }
    4637                     }
    4638                     if (style) _temp_times.style = style;
    4639                     if (_temp_times.start == 0) _temp_times.start = 0.200;
    4640                     entries.times.push(_temp_times);
    4641                     text = $.trim(lines.eq(i).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>");
    4642                     entries.text.push(text);
    4643                     if (entries.times.start == 0) entries.times.start = 2;
    4644                 }
    4645                 return entries;
    4646             }
    4647         },
    4648         split2: function (text, regex) {
    4649             // normal version for compliant browsers
    4650             // see below for IE fix
    4651             return text.split(regex);
    4652         }
    4653     };
    4654 
    4655     // test for browsers with bad String.split method.
    4656     if ('x\n\ny'.split(/\n/gi).length != 3) {
    4657         // add super slow IE8 and below version
    4658         mejs.TrackFormatParser.split2 = function(text, regex) {
    4659             var
    4660                 parts = [],
    4661                 chunk = '',
    4662                 i;
    4663 
    4664             for (i=0; i<text.length; i++) {
    4665                 chunk += text.substring(i,i+1);
    4666                 if (regex.test(chunk)) {
    4667                     parts.push(chunk.replace(regex, ''));
    4668                     chunk = '';
    4669                 }
    4670             }
    4671             parts.push(chunk);
    4672             return parts;
    4673         }
    4674     }
    4675 
    4676 })(mejs.$);
    4677 
    4678 /*
    4679 * ContextMenu Plugin
    4680 *
    4681 *
    4682 */
    4683 
    4684 (function($) {
    4685 
    4686 $.extend(mejs.MepDefaults,
    4687     { 'contextMenuItems': [
    4688         // demo of a fullscreen option
    4689         {
    4690             render: function(player) {
    4691 
    4692                 // check for fullscreen plugin
    4693                 if (typeof player.enterFullScreen == 'undefined')
    4694                     return null;
    4695 
    4696                 if (player.isFullScreen) {
    4697                     return "Turn off Fullscreen";
    4698                 } else {
    4699                     return "Go Fullscreen";
    4700                 }
    4701             },
    4702             click: function(player) {
    4703                 if (player.isFullScreen) {
    4704                     player.exitFullScreen();
    4705                 } else {
    4706                     player.enterFullScreen();
    4707                 }
    4708             }
    4709         }
    4710         ,
    4711         // demo of a mute/unmute button
    4712         {
    4713             render: function(player) {
    4714                 if (player.media.muted) {
    4715                     return "Unmute";
    4716                 } else {
    4717                     return "Mute";
    4718                 }
    4719             },
    4720             click: function(player) {
    4721                 if (player.media.muted) {
    4722                     player.setMuted(false);
    4723                 } else {
    4724                     player.setMuted(true);
    4725                 }
    4726             }
    4727         },
    4728         // separator
    4729         {
    4730             isSeparator: true
    4731         }
    4732         ,
    4733         // demo of simple download video
    4734         {
    4735             render: function(player) {
    4736                 return "Download Video";
    4737             },
    4738             click: function(player) {
    4739                 window.location.href = player.media.currentSrc;
    4740             }
    4741         }
    4742     ]}
    4743 );
    4744 
    4745 
    4746     $.extend(MediaElementPlayer.prototype, {
    4747         buildcontextmenu: function(player, controls, layers, media) {
    4748 
    4749             // create context menu
    4750             player.contextMenu = $('<div class="mejs-contextmenu"></div>')
    4751                                 .appendTo($('body'))
    4752                                 .hide();
    4753 
    4754             // create events for showing context menu
    4755             player.container.bind('contextmenu', function(e) {
    4756                 if (player.isContextMenuEnabled) {
    4757                     e.preventDefault();
    4758                     player.renderContextMenu(e.clientX-1, e.clientY-1);
    4759                     return false;
    4760                 }
    4761             });
    4762             player.container.bind('click', function() {
    4763                 player.contextMenu.hide();
    4764             });
    4765             player.contextMenu.bind('mouseleave', function() {
    4766 
    4767                 //console.log('context hover out');
    4768                 player.startContextMenuTimer();
    4769 
    4770             });
    4771         },
    4772 
    4773         cleancontextmenu: function(player) {
    4774             player.contextMenu.remove();
    4775         },
    4776 
    4777         isContextMenuEnabled: true,
    4778         enableContextMenu: function() {
    4779             this.isContextMenuEnabled = true;
    4780         },
    4781         disableContextMenu: function() {
    4782             this.isContextMenuEnabled = false;
    4783         },
    4784 
    4785         contextMenuTimeout: null,
    4786         startContextMenuTimer: function() {
    4787             //console.log('startContextMenuTimer');
    4788 
    4789             var t = this;
    4790 
    4791             t.killContextMenuTimer();
    4792 
    4793             t.contextMenuTimer = setTimeout(function() {
    4794                 t.hideContextMenu();
    4795                 t.killContextMenuTimer();
    4796             }, 750);
    4797         },
    4798         killContextMenuTimer: function() {
    4799             var timer = this.contextMenuTimer;
    4800 
    4801             //console.log('killContextMenuTimer', timer);
    4802 
    4803             if (timer != null) {
    4804                 clearTimeout(timer);
    4805                 delete timer;
    4806                 timer = null;
    4807             }
    4808         },
    4809 
    4810         hideContextMenu: function() {
    4811             this.contextMenu.hide();
    4812         },
    4813 
    4814         renderContextMenu: function(x,y) {
    4815 
    4816             // alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly
    4817             var t = this,
    4818                 html = '',
    4819                 items = t.options.contextMenuItems;
    4820 
    4821             for (var i=0, il=items.length; i<il; i++) {
    4822 
    4823                 if (items[i].isSeparator) {
    4824                     html += '<div class="mejs-contextmenu-separator"></div>';
    4825                 } else {
    4826 
    4827                     var rendered = items[i].render(t);
    4828 
    4829                     // render can return null if the item doesn't need to be used at the moment
    4830                     if (rendered != null) {
    4831                         html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>';
    4832                     }
    4833                 }
    4834             }
    4835 
    4836             // position and show the context menu
    4837             t.contextMenu
    4838                 .empty()
    4839                 .append($(html))
    4840                 .css({top:y, left:x})
    4841                 .show();
    4842 
    4843             // bind events
    4844             t.contextMenu.find('.mejs-contextmenu-item').each(function() {
    4845 
    4846                 // which one is this?
    4847                 var $dom = $(this),
    4848                     itemIndex = parseInt( $dom.data('itemindex'), 10 ),
    4849                     item = t.options.contextMenuItems[itemIndex];
    4850 
    4851                 // bind extra functionality?
    4852                 if (typeof item.show != 'undefined')
    4853                     item.show( $dom , t);
    4854 
    4855                 // bind click action
    4856                 $dom.click(function() {
    4857                     // perform click action
    4858                     if (typeof item.click != 'undefined')
    4859                         item.click(t);
    4860 
    4861                     // close
    4862                     t.contextMenu.hide();
    4863                 });
    4864             });
    4865 
    4866             // stop the controls from hiding
    4867             setTimeout(function() {
    4868                 t.killControlsTimer('rev3');
    4869             }, 100);
    4870 
    4871         }
    4872     });
    4873 
    4874 })(mejs.$);
    4875 /**
    4876  * Postroll plugin
    4877  */
    4878 (function($) {
    4879 
    4880     $.extend(mejs.MepDefaults, {
    4881         postrollCloseText: mejs.i18n.t('Close')
    4882     });
    4883 
    4884     // Postroll
    4885     $.extend(MediaElementPlayer.prototype, {
    4886         buildpostroll: function(player, controls, layers, media) {
    4887             var
    4888                 t = this,
    4889                 postrollLink = t.container.find('link[rel="postroll"]').attr('href');
    4890 
    4891             if (typeof postrollLink !== 'undefined') {
    4892                 player.postroll =
    4893                     $('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">' + t.options.postrollCloseText + '</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(layers).hide();
    4894 
    4895                 t.media.addEventListener('ended', function (e) {
    4896                     $.ajax({
    4897                         dataType: 'html',
    4898                         url: postrollLink,
    4899                         success: function (data, textStatus) {
    4900                             layers.find('.mejs-postroll-layer-content').html(data);
    4901                         }
    4902                     });
    4903                     player.postroll.show();
    4904                 }, false);
    4905             }
    4906         }
    4907     });
    4908 
    4909 })(mejs.$);
    4910 
     77 */if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender;
     78(function(f){mejs.MepDefaults={poster:"",defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,defaultSeekBackwardInterval:function(a){return a.duration*0.05},defaultSeekForwardInterval:function(a){return a.duration*0.05},audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,autoRewind:true,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true,alwaysShowControls:false,hideVideoControlsOnLoad:false,
     79clickToPlayPause:true,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks","volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?b.play():b.pause()}},{keys:[38],action:function(a,b){b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a,
     80b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.max(b.currentTime-a.options.defaultSeekBackwardInterval(b),0);b.setCurrentTime(c)}}},{keys:[39,228],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.min(b.currentTime+a.options.defaultSeekForwardInterval(b),b.duration);b.setCurrentTime(c)}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen?
     81a.exitFullScreen():a.enterFullScreen()}}]};mejs.mepIndex=0;mejs.players={};mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);this.id="mep_"+mejs.mepIndex++;mejs.players[this.id]=
     82this;this.init();return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(e,g){a.meReady(e,g)},error:function(e){a.handleError(e)}}),d=a.media.tagName.toLowerCase();a.isDynamic=d!=="audio"&&d!=="video";a.isVideo=a.isDynamic?a.options.isVideo:d!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls",
     83"controls");if(b.isiPad&&a.media.getAttribute("autoplay")!==null){a.media.load();a.media.play()}}else if(!(b.isAndroid&&a.options.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.container=f('<div id="'+a.id+'" class="mejs-container '+(mejs.MediaFeatures.svg?"svg":"no-svg")+'"><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(a.$media[0].className).insertBefore(a.$media);
     84a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=a.isVideo?"video":"audio";d=b.substring(0,
     851).toUpperCase()+b.substring(1);a.width=a.options[b+"Width"]>0||a.options[b+"Width"].toString().indexOf("%")>-1?a.options[b+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+d+"Width"];a.height=a.options[b+"Height"]>0||a.options[b+"Height"].toString().indexOf("%")>-1?a.options[b+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!==
     86null?a.$media.attr("height"):a.options["default"+d+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.height;c.pluginHeight=a.width}mejs.MediaElement(a.$media[0],c);typeof a.container!="undefined"&&a.container.trigger("controlsshown")},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true;b.container.trigger("controlsshown")});b.container.find(".mejs-control").css("visibility",
     87"visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility","visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true;b.container.trigger("controlsshown")}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(b.controlsAreVisible)if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display",
     88"block");b.controlsAreVisible=false;b.container.trigger("controlshidden")});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")}},controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"?
     89a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true},meReady:function(a,b){var c=this,
     90d=mejs.MediaFeatures,e=b.getAttribute("autoplay");e=!(typeof e=="undefined"||e===null||e==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(d.isAndroid&&c.options.AndroidUseNativeControls)&&!(d.isiPad&&c.options.iPadUseNativeControls)&&!(d.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){d=c.options.features[g];
     91if(c["build"+d])try{c["build"+d](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);else c.controlsEnabled&&c.showControls(false)});else{c.media.addEventListener("click",function(){if(c.options.clickToPlayPause)c.media.paused?c.media.play():c.media.pause()});c.container.bind("mouseenter mouseover",
     92function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&&c.startControlsTimer(1E3)})}c.options.hideVideoControlsOnLoad&&c.hideControls(false);e&&!c.options.alwaysShowControls&&
     93c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(j){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(j.target.videoHeight)){c.setPlayerSize(j.target.videoWidth,j.target.videoHeight);c.setControlsSize();c.media.setVideoSize(j.target.videoWidth,j.target.videoHeight)}},false)}a.addEventListener("play",function(){for(var j in mejs.players){var l=mejs.players[j];l.id!=c.id&&c.options.pauseOtherPlayers&&!l.paused&&!l.ended&&l.pause();
     94l.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){if(c.options.autoRewind)try{c.media.setCurrentTime(0)}catch(j){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",function(){c.updateDuration&&c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,
     95c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);c.globalBind("resize",function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(e&&a.pluginType=="native"){a.load();a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media,
     96c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0||this.$node.css("max-width")==="100%"||this.$node[0].currentStyle&&this.$node[0].currentStyle.maxWidth==="100%"){var c=this.isVideo?this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth:
     97this.options.defaultAudioWidth,d=this.isVideo?this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight:this.options.defaultAudioHeight,e=this.container.parent().closest(":visible").width();c=this.isVideo||!this.options.autosizeProgress?parseInt(e*d/c,10):d;if(this.container.parent()[0].tagName.toLowerCase()==="body"){e=f(window).width();c=f(window).height()}if(c!=0&&e!=0){this.container.width(e).height(c);this.$media.add(this.container.find(".mejs-shim")).width("100%").height("100%");
     98this.isVideo&&this.media.setVideoSize&&this.media.setVideoSize(e,c);this.layers.children(".mejs-layer").width("100%").height("100%")}}else{this.container.width(this.width).height(this.height);this.layers.children(".mejs-layer").width(this.width).height(this.height)}},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),d=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var e=c.siblings();if(this.options&&
     99!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){e.each(function(){var g=f(this);if(g.css("position")!="absolute"&&g.is(":visible"))a+=f(this).outerWidth(true)});b=this.controls.width()-a-(c.outerWidth(true)-c.width())}c.width(b);d.width(b-(d.outerWidth(true)-d.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,d){var e=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster");
     100if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):e.hide();d.addEventListener("play",function(){e.hide()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"),c=b.find("img");if(c.length==0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a)},buildoverlays:function(a,b,c,d){var e=this;if(a.isVideo){var g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c),
     101j=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).click(function(){if(e.options.clickToPlayPause)d.paused?d.play():d.pause()});d.addEventListener("play",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);d.addEventListener("playing",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);d.addEventListener("seeking",function(){g.show();b.find(".mejs-time-buffering").show()},
     102false);d.addEventListener("seeked",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||j.show()},false);d.addEventListener("waiting",function(){g.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("loadeddata",function(){g.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("canplay",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("error",function(){g.hide();
     103b.find(".mejs-time-buffering").hide();k.show();k.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,d){this.globalBind("keydown",function(e){if(a.hasFocus&&a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g<k;g++)for(var j=a.options.keyActions[g],l=0,q=j.keys.length;l<q;l++)if(e.keyCode==j.keys[l]){e.preventDefault();j.action(a,d,e.keyCode);return false}return true});this.globalBind("click",function(e){if(f(e.target).closest(".mejs-container").length==
     1040)a.hasFocus=false})},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,d){d=f(d);a.tracks.push({srclang:d.attr("srclang")?d.attr("srclang").toLowerCase():"",src:d.attr("src"),kind:d.attr("kind"),label:d.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.media.play()},pause:function(){this.media.pause()},
     105load:function(){this.media.load()},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime},setVolume:function(a){this.media.setVolume(a)},getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){var a,b;for(a in this.options.features){b=this.options.features[a];if(this["clean"+b])try{this["clean"+b](this)}catch(c){}}this.media.pluginType==="native"?
     106this.$media.prop("controls",true):this.media.remove();this.isDynamic||this.$node.insertBefore(this.container);delete mejs.players[this.id];this.container.remove();this.globalUnbind();delete this.node.player}};(function(){function a(c,d){var e={d:[],w:[]};f.each((c||"").split(" "),function(g,k){e[b.test(k)?"w":"d"].push(k+"."+d)});e.d=e.d.join(" ");e.w=e.w.join(" ");return e}var b=/^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/;mejs.MediaElementPlayer.prototype.globalBind=
     107function(c,d,e){c=a(c,this.id);c.d&&f(document).bind(c.d,d,e);c.w&&f(window).bind(c.w,d,e)};mejs.MediaElementPlayer.prototype.globalUnbind=function(c,d){c=a(c,this.id);c.d&&f(document).unbind(c.d,d);c.w&&f(window).unbind(c.w,d)}})();if(typeof jQuery!="undefined")jQuery.fn.mediaelementplayer=function(a){a===false?this.each(function(){var b=jQuery(this).data("mediaelementplayer");b&&b.remove();jQuery(this).removeData("mediaelementplayer")}):this.each(function(){jQuery(this).data("mediaelementplayer",
     108new mejs.MediaElementPlayer(this,a))});return this};f(document).ready(function(){f(".mejs-player").mediaelementplayer()});window.MediaElementPlayer=mejs.MediaElementPlayer})(mejs.$);
     109(function(f){f.extend(mejs.MepDefaults,{playpauseText:"Play/Pause"});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,d){var e=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'" aria-label="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();d.paused?d.play():d.pause();return false});d.addEventListener("play",function(){e.removeClass("mejs-play").addClass("mejs-pause")},
     110false);d.addEventListener("playing",function(){e.removeClass("mejs-play").addClass("mejs-pause")},false);d.addEventListener("pause",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false);d.addEventListener("paused",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$);
     111(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,d){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'" aria-label="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){d.paused||d.pause();if(d.currentTime>0){d.setCurrentTime(0);d.pause();b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left",
     112"0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$);
     113(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,d){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var e=
     114this,g=b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var k=b.find(".mejs-time-current"),j=b.find(".mejs-time-handle"),l=b.find(".mejs-time-float"),q=b.find(".mejs-time-float-current"),p=function(h){h=h.pageX;var m=g.offset(),r=g.outerWidth(true),n=0,o=n=0;if(d.duration){if(h<m.left)h=m.left;else if(h>r+m.left)h=r+m.left;o=h-m.left;n=o/r;n=n<=0.02?0:n*d.duration;t&&n!==d.currentTime&&d.setCurrentTime(n);if(!mejs.MediaFeatures.hasTouch){l.css("left",o);q.html(mejs.Utility.secondsToTimeCode(n));
     115l.show()}}},t=false;g.bind("mousedown",function(h){if(h.which===1){t=true;p(h);e.globalBind("mousemove.dur",function(m){p(m)});e.globalBind("mouseup.dur",function(){t=false;l.hide();e.globalUnbind(".dur")});return false}}).bind("mouseenter",function(){e.globalBind("mousemove.dur",function(h){p(h)});mejs.MediaFeatures.hasTouch||l.show()}).bind("mouseleave",function(){if(!t){e.globalUnbind(".dur");l.hide()}});d.addEventListener("progress",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);
     116d.addEventListener("timeupdate",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);e.loaded=c;e.total=g;e.current=k;e.handle=j},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1,
     117Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=Math.round(this.total.width()*this.media.currentTime/this.media.duration),b=a-Math.round(this.handle.outerWidth(true)/2);this.current.width(a);this.handle.css("left",b)}}})})(mejs.$);
     118(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" <span> | </span> "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,d){f('<div class="mejs-time"><span class="mejs-currenttime">'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");d.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a,
     119b,c,d){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container");
     120f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");d.addEventListener("timeupdate",function(){a.updateDuration()},
     121false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){this.container.toggleClass("mejs-long-video",this.media.duration>3600);if(this.durationD&&(this.options.duration>0||this.media.duration))this.durationD.html(mejs.Utility.secondsToTimeCode(this.options.duration>0?this.options.duration:
     122this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$);
     123(function(f){f.extend(mejs.MepDefaults,{muteText:"Mute Toggle",hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,d){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var e=this,g=e.isVideo?e.options.videoVolume:e.options.audioVolume,k=g=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+e.id+'" title="'+e.options.muteText+
     124'" aria-label="'+e.options.muteText+'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+e.id+'" title="'+e.options.muteText+'" aria-label="'+e.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b),
     125j=e.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),l=e.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),q=e.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),p=e.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),t=function(n,o){if(!j.is(":visible")&&typeof o=="undefined"){j.show();t(n,true);j.hide()}else{n=Math.max(0,n);n=Math.min(n,1);n==0?k.removeClass("mejs-mute").addClass("mejs-unmute"):k.removeClass("mejs-unmute").addClass("mejs-mute");
     126if(g=="vertical"){var s=l.height(),u=l.position(),v=s-s*n;p.css("top",Math.round(u.top+v-p.height()/2));q.height(s-v);q.css("top",u.top+v)}else{s=l.width();u=l.position();s=s*n;p.css("left",Math.round(u.left+s-p.width()/2));q.width(Math.round(s))}}},h=function(n){var o=null,s=l.offset();if(g=="vertical"){o=l.height();parseInt(l.css("top").replace(/px/,""),10);o=(o-(n.pageY-s.top))/o;if(s.top==0||s.left==0)return}else{o=l.width();o=(n.pageX-s.left)/o}o=Math.max(0,o);o=Math.min(o,1);t(o);o==0?d.setMuted(true):
     127d.setMuted(false);d.setVolume(o)},m=false,r=false;k.hover(function(){j.show();r=true},function(){r=false;!m&&g=="vertical"&&j.hide()});j.bind("mouseover",function(){r=true}).bind("mousedown",function(n){h(n);e.globalBind("mousemove.vol",function(o){h(o)});e.globalBind("mouseup.vol",function(){m=false;e.globalUnbind(".vol");!r&&g=="vertical"&&j.hide()});m=true;return false});k.find("button").click(function(){d.setMuted(!d.muted)});d.addEventListener("volumechange",function(){if(!m)if(d.muted){t(0);
     128k.removeClass("mejs-mute").addClass("mejs-unmute")}else{t(d.volume);k.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(e.container.is(":visible")){t(a.options.startVolume);a.options.startVolume===0&&d.setMuted(true);d.pluginType==="native"&&d.setVolume(a.options.startVolume)}}}})})(mejs.$);
     129(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:mejs.i18n.t("Fullscreen")});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,docStyleOverflow:null,isInIframe:false,buildfullscreen:function(a,b,c,d){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=function(){if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen=
     130false;a.exitFullScreen()}};mejs.MediaFeatures.hasMozNativeFullScreen?a.globalBind(mejs.MediaFeatures.fullScreenEventName,c):a.container.bind(mejs.MediaFeatures.fullScreenEventName,c)}var e=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+e.id+'" title="'+e.options.fullscreenText+'" aria-label="'+e.options.fullscreenText+'"></button></div>').appendTo(b);if(e.media.pluginType==="native"||!e.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&&
     131mejs.MediaFeatures.isFullScreen()||a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;if(function(){var h=document.createElement("x"),m=document.documentElement,r=window.getComputedStyle;if(!("pointerEvents"in h.style))return false;h.style.pointerEvents="auto";h.style.pointerEvents="x";m.appendChild(h);r=r&&r(h,"").pointerEvents==="auto";m.removeChild(h);return!!r}()&&!mejs.MediaFeatures.isOpera){var j=false,l=function(){if(j){for(var h in q)q[h].hide();g.css("pointer-events",
     132"");e.controls.css("pointer-events","");j=false}},q={};b=["top","left","right","bottom"];var p,t=function(){var h=g.offset().left-e.container.offset().left,m=g.offset().top-e.container.offset().top,r=g.outerWidth(true),n=g.outerHeight(true),o=e.container.width(),s=e.container.height();for(p in q)q[p].css({position:"absolute",top:0,left:0});q.top.width(o).height(m);q.left.width(h).height(n).css({top:m});q.right.width(o-h-r).height(n).css({top:m,left:h+r});q.bottom.width(o).height(s-n-m).css({top:m+
     133n})};e.globalBind("resize",function(){t()});p=0;for(c=b.length;p<c;p+=1)q[b[p]]=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(l).hide();g.mouseover(function(){if(!e.isFullScreen){var h=g.offset(),m=a.container.offset();d.positionFullscreenButton(h.left-m.left,h.top-m.top,false);g.css("pointer-events","none");e.controls.css("pointer-events","none");for(p in q)q[p].show();t();j=true}});d.addEventListener("fullscreenchange",function(){l()})}else g.mouseover(function(){if(k!==
     134null){clearTimeout(k);delete k}var h=g.offset(),m=a.container.offset();d.positionFullscreenButton(h.left-m.left,h.top-m.top,true)}).mouseout(function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){d.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;e.globalBind("keydown",function(h){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||e.isFullScreen)&&h.keyCode==27)a.exitFullScreen()})}},cleanfullscreen:function(a){a.exitFullScreen()},containerSizeTimeout:null,
     135enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){docStyleOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow="hidden";normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!==
     136screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},250);else{a.pause();window.open(b,a.id,
     137"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");a.containerSizeTimeout=setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find(".mejs-shim").width("100%").height("100%");a.media.setVideoSize(f(window).width(),f(window).height())}a.layers.children("div").width("100%").height("100%");
     138a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){clearTimeout(this.containerSizeTimeout);if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen();document.documentElement.style.overflow=docStyleOverflow;
     139this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find("object embed").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen");this.setControlsSize();this.isFullScreen=false}}})})(mejs.$);
     140(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:"Captions/Subtitles",hideCaptionsButtonWhenEmpty:true,toggleCaptionsButtonWhenOnlyOne:false,slidesSelector:""});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,d){if(a.tracks.length!=0){a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide();a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide();
     141a.captionsText=a.captions.find(".mejs-captions-text");a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'" aria-label="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">None</label></li></ul></div></div>').appendTo(b);for(b=c=0;b<
     142a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&c++;this.options.toggleCaptionsButtonWhenOnlyOne&&c==1?a.captionsButton.on("click",function(){a.setTrack(a.selectedTrack==null?a.tracks[0].srclang:"none")}):a.captionsButton.hover(function(){f(this).find(".mejs-captions-selector").css("visibility","visible")},function(){f(this).find(".mejs-captions-selector").css("visibility","hidden")}).on("click","input[type=radio]",function(){lang=this.value;a.setTrack(lang)});a.options.alwaysShowControls?a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"):
     143a.container.bind("controlsshown",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("controlshidden",function(){d.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")});a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(b=0;b<a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&a.addTrackButton(a.tracks[b].srclang,a.tracks[b].label);a.loadNextTrack();d.addEventListener("timeupdate",function(){a.displayCaptions()},
     144false);if(a.options.slidesSelector!=""){a.slidesContainer=f(a.options.slidesSelector);d.addEventListener("timeupdate",function(){a.displaySlides()},false)}d.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility","visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&&!d.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden");
     145f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},setTrack:function(a){var b;if(a=="none"){this.selectedTrack=null;this.captionsButton.removeClass("mejs-captions-enabled")}else for(b=0;b<this.tracks.length;b++)if(this.tracks[b].srclang==a){this.selectedTrack==null&&this.captionsButton.addClass("mejs-captions-enabled");this.selectedTrack=this.tracks[b];this.captions.attr("lang",this.selectedTrack.srclang);this.displayCaptions();break}},
     146loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else{this.isLoadingTrack=false;this.checkForTracks()}},loadTrack:function(a){var b=this,c=b.tracks[a];f.ajax({url:c.src,dataType:"text",success:function(d){c.entries=typeof d=="string"&&/<tt\s+xml/ig.exec(d)?mejs.TrackFormatParser.dfxp.parse(d):mejs.TrackForma