WordPress.org

Make WordPress Core

Ticket #24015: 24015.2.diff

File 24015.2.diff, 246.2 KB (added by wonderboymusic, 15 months ago)
  • wp-includes/js/mediaelement/mediaelement-and-player.js

    diff --git wp-includes/js/mediaelement/mediaelement-and-player.js wp-includes/js/mediaelement/mediaelement-and-player.js
    index bb49d60..048c8f0 100644
     
    1010* Copyright 2010-2012, John Dyer (http://j.hn) 
    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; 
     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); 
    159366 
    159467/*! 
    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). 
     68 * MediaElementPlayer 
     69 * http://mediaelementjs.com/ 
    160770 * 
     71 * Creates a controller bar for HTML5 <video> add <audio> tags 
     72 * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) 
    160873 * 
    1609  * Wrapper built to be able to attach the i18n object to 
    1610  * other objects without changing more than one line. 
     74 * Copyright 2010-2012, John Dyer (http://j.hn/) 
     75 * License: MIT 
    161176 * 
    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)); 
    1815  
    1816 /*! 
    1817  * MediaElementPlayer 
    1818  * http://mediaelementjs.com/ 
    1819  * 
    1820  * Creates a controller bar for HTML5 <video> add <audio> tags 
    1821  * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) 
    1822  * 
    1823  * Copyright 2010-2012, John Dyer (http://j.hn/) 
    1824  * License: MIT 
    1825  * 
    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 &nbs