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('&').split('<').join('<').split('"').join('"'); |
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('&') + '" />' + |
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 + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&loop=0" />' + |
1305 | | '<embed src="//vimeo.com/moogaloop.swf?api=1&clip_id=' + pluginMediaElement.vimeoid + '&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00adef&fullscreen=1&autoplay=0&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&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&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&playerapiid=' + settings.pluginId + '&version=3&autoplay=0&controls=0&modestbranding=1&loop=0'; |
1497 | | |
1498 | | if (mejs.MediaFeatures.isIE) { |
1499 | | |
1500 | | specialIEContainer = document.createElement('div'); |
1501 | | settings.container.appendChild(specialIEContainer); |
1502 | | specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' + |
1503 | | 'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' + |
1504 | | '<param name="movie" value="' + youtubeUrl + '" />' + |
1505 | | '<param name="wmode" value="transparent" />' + |
1506 | | '<param name="allowScriptAccess" value="always" />' + |
1507 | | '<param name="allowFullScreen" value="true" />' + |
1508 | | '</object>'; |
1509 | | } else { |
1510 | | settings.container.innerHTML = |
1511 | | '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' + |
1512 | | 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' + |
1513 | | '<param name="allowScriptAccess" value="always">' + |
1514 | | '<param name="wmode" value="transparent">' + |
1515 | | '</object>'; |
1516 | | } |
1517 | | |
1518 | | }, |
1519 | | |
1520 | | flashReady: function(id) { |
1521 | | var |
1522 | | settings = this.flashPlayers[id], |
1523 | | player = document.getElementById(id), |
1524 | | pluginMediaElement = settings.pluginMediaElement; |
1525 | | |
1526 | | // hook up and return to MediaELementPlayer.success |
1527 | | pluginMediaElement.pluginApi = |
1528 | | pluginMediaElement.pluginElement = player; |
1529 | | mejs.MediaPluginBridge.initPlugin(id); |
1530 | | |
1531 | | // load the youtube video |
1532 | | player.cueVideoById(settings.videoId); |
1533 | | |
1534 | | var callbackName = settings.containerId + '_callback'; |
1535 | | |
1536 | | window[callbackName] = function(e) { |
1537 | | mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement); |
1538 | | } |
1539 | | |
1540 | | player.addEventListener('onStateChange', callbackName); |
1541 | | |
1542 | | setInterval(function() { |
1543 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate'); |
1544 | | }, 250); |
1545 | | }, |
1546 | | |
1547 | | handleStateChange: function(youTubeState, player, pluginMediaElement) { |
1548 | | switch (youTubeState) { |
1549 | | case -1: // not started |
1550 | | pluginMediaElement.paused = true; |
1551 | | pluginMediaElement.ended = true; |
1552 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata'); |
1553 | | //createYouTubeEvent(player, pluginMediaElement, 'loadeddata'); |
1554 | | break; |
1555 | | case 0: |
1556 | | pluginMediaElement.paused = false; |
1557 | | pluginMediaElement.ended = true; |
1558 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended'); |
1559 | | break; |
1560 | | case 1: |
1561 | | pluginMediaElement.paused = false; |
1562 | | pluginMediaElement.ended = false; |
1563 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play'); |
1564 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing'); |
1565 | | break; |
1566 | | case 2: |
1567 | | pluginMediaElement.paused = true; |
1568 | | pluginMediaElement.ended = false; |
1569 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause'); |
1570 | | break; |
1571 | | case 3: // buffering |
1572 | | mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress'); |
1573 | | break; |
1574 | | case 5: |
1575 | | // cued? |
1576 | | break; |
1577 | | |
1578 | | } |
1579 | | |
1580 | | } |
1581 | | } |
1582 | | // IFRAME |
1583 | | function onYouTubePlayerAPIReady() { |
1584 | | mejs.YouTubeApi.iFrameReady(); |
1585 | | } |
1586 | | // FLASH |
1587 | | function onYouTubePlayerReady(id) { |
1588 | | mejs.YouTubeApi.flashReady(id); |
1589 | | } |
1590 | | |
1591 | | window.mejs = mejs; |
1592 | | window.MediaElement = mejs.MediaElement; |
1593 | | |
1594 | | /*! |
1595 | | * Adds Internationalization and localization to objects. |
1596 | | * |
1597 | | * What is the concept beyond i18n? |
1598 | | * http://en.wikipedia.org/wiki/Internationalization_and_localization |
1599 | | * |
1600 | | * |
1601 | | * This file both i18n methods and locale which is used to translate |
1602 | | * strings into other languages. |
1603 | | * |
1604 | | * Default translations are not available, you have to add them |
1605 | | * through locale objects which are named exactly as the langcode |
1606 | | * they stand for. The default language is always english (en). |
1607 | | * |
1608 | | * |
1609 | | * Wrapper built to be able to attach the i18n object to |
1610 | | * other objects without changing more than one line. |
1611 | | * |
1612 | | * |
1613 | | * LICENSE: |
1614 | | * |
1615 | | * The i18n file uses methods from the Drupal project (drupal.js): |
1616 | | * - i18n.methods.t() (modified) |
1617 | | * - i18n.methods.checkPlain() (full copy) |
1618 | | * - i18n.methods.formatString() (full copy) |
1619 | | * |
1620 | | * The Drupal project is (like mediaelementjs) licensed under GPLv2. |
1621 | | * - http://drupal.org/licensing/faq/#q1 |
1622 | | * - https://github.com/johndyer/mediaelement |
1623 | | * - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
1624 | | * |
1625 | | * |
1626 | | * @author |
1627 | | * Tim Latz (latz.tim@gmail.com) |
1628 | | * |
1629 | | * @see |
1630 | | * me-i18n-locale.js |
1631 | | * |
1632 | | * @params |
1633 | | * - $ - zepto || jQuery .. |
1634 | | * - context - document, iframe .. |
1635 | | * - exports - CommonJS, window .. |
1636 | | * |
1637 | | */ |
1638 | | ;(function($, context, exports, undefined) { |
1639 | | "use strict"; |
1640 | | var i18n = { |
1641 | | "locale": { |
1642 | | "strings" : {} |
1643 | | }, |
1644 | | "methods" : {} |
1645 | | }; |
1646 | | // start i18n |
1647 | | |
1648 | | |
1649 | | /** |
1650 | | * Get the current browser's language |
1651 | | * |
1652 | | * @see: i18n.methods.t() |
1653 | | */ |
1654 | | i18n.locale.getLanguage = function () { |
1655 | | return { |
1656 | | "language" : navigator.language |
1657 | | }; |
1658 | | }; |
1659 | | |
1660 | | /** |
1661 | | * Store the language the locale object was initialized with |
1662 | | */ |
1663 | | i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage(); |
1664 | | |
1665 | | |
1666 | | /** |
1667 | | * Encode special characters in a plain-text string for display as HTML. |
1668 | | */ |
1669 | | i18n.methods.checkPlain = function (str) { |
1670 | | var character, regex, |
1671 | | replace = { |
1672 | | '&': '&', |
1673 | | '"': '"', |
1674 | | '<': '<', |
1675 | | '>': '>' |
1676 | | }; |
1677 | | str = String(str); |
1678 | | for (character in replace) { |
1679 | | if (replace.hasOwnProperty(character)) { |
1680 | | regex = new RegExp(character, 'g'); |
1681 | | str = str.replace(regex, replace[character]); |
1682 | | } |
1683 | | } |
1684 | | return str; |
1685 | | }; |
1686 | | |
1687 | | /** |
1688 | | * Replace placeholders with sanitized values in a string. |
1689 | | * |
1690 | | * @param str |
1691 | | * A string with placeholders. |
1692 | | * @param args |
1693 | | * An object of replacements pairs to make. Incidences of any key in this |
1694 | | * array are replaced with the corresponding value. Based on the first |
1695 | | * character of the key, the value is escaped and/or themed: |
1696 | | * - !variable: inserted as is |
1697 | | * - @variable: escape plain text to HTML (i18n.methods.checkPlain) |
1698 | | * - %variable: escape text and theme as a placeholder for user-submitted |
1699 | | * content (checkPlain + <em class="placeholder" > ) |
1700 | | * |
1701 | | * @see i18n.methods.t() |
1702 | | */ |
1703 | | i18n.methods.formatString = function(str, args) { |
1704 | | // Transform arguments before inserting them. |
1705 | | for (var key in args) { |
1706 | | switch (key.charAt(0)) { |
1707 | | // Escaped only. |
1708 | | case '@': |
1709 | | args[key] = i18n.methods.checkPlain(args[key]); |
1710 | | break; |
1711 | | // Pass-through. |
1712 | | case '!': |
1713 | | break; |
1714 | | // Escaped and placeholder. |
1715 | | case '%': |
1716 | | default: |
1717 | | args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>'; |
1718 | | break; |
1719 | | } |
1720 | | str = str.replace(key, args[key]); |
1721 | | } |
1722 | | return str; |
1723 | | }; |
1724 | | |
1725 | | /** |
1726 | | * Translate strings to the page language or a given language. |
1727 | | * |
1728 | | * See the documentation of the server-side t() function for further details. |
1729 | | * |
1730 | | * @param str |
1731 | | * A string containing the English string to translate. |
1732 | | * @param args |
1733 | | * An object of replacements pairs to make after translation. Incidences |
1734 | | * of any key in this array are replaced with the corresponding value. |
1735 | | * See i18n.methods.formatString(). |
1736 | | * |
1737 | | * @param options |
1738 | | * - 'context' (defaults to the default context): The context the source string |
1739 | | * belongs to. |
1740 | | * |
1741 | | * @return |
1742 | | * The translated string. |
1743 | | */ |
1744 | | i18n.methods.t = function (str, args, options) { |
1745 | | |
1746 | | // Fetch the localized version of the string. |
1747 | | if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) { |
1748 | | str = i18n.locale.strings[options.context][str]; |
1749 | | } |
1750 | | |
1751 | | if (args) { |
1752 | | str = i18n.methods.formatString(str, args); |
1753 | | } |
1754 | | return str; |
1755 | | }; |
1756 | | |
1757 | | |
1758 | | /** |
1759 | | * Wrapper for i18n.methods.t() |
1760 | | * |
1761 | | * @see i18n.methods.t() |
1762 | | * @throws InvalidArgumentException |
1763 | | */ |
1764 | | i18n.t = function(str, args, options) { |
1765 | | |
1766 | | if (typeof str === 'string' && str.length > 0) { |
1767 | | |
1768 | | // check every time due languge can change for |
1769 | | // different reasons (translation, lang switcher ..) |
1770 | | var lang = i18n.locale.getLanguage(); |
1771 | | |
1772 | | options = options || { |
1773 | | "context" : lang.language |
1774 | | }; |
1775 | | |
1776 | | return i18n.methods.t(str, args, options); |
1777 | | } |
1778 | | else { |
1779 | | throw { |
1780 | | "name" : 'InvalidArgumentException', |
1781 | | "message" : 'First argument is either not a string or empty.' |
1782 | | } |
1783 | | } |
1784 | | }; |
1785 | | |
1786 | | // end i18n |
1787 | | exports.i18n = i18n; |
1788 | | }(jQuery, document, mejs)); |
1789 | | /*! |
1790 | | * This is a i18n.locale language object. |
1791 | | * |
1792 | | *<de> German translation by Tim Latz, latz.tim@gmail.com |
1793 | | * |
1794 | | * @author |
1795 | | * Tim Latz (latz.tim@gmail.com) |
1796 | | * |
1797 | | * @see |
1798 | | * me-i18n.js |
1799 | | * |
1800 | | * @params |
1801 | | * - exports - CommonJS, window .. |
1802 | | */ |
1803 | | ;(function(exports, undefined) { |
1804 | | |
1805 | | "use strict"; |
1806 | | |
1807 | | exports.de = { |
1808 | | "Fullscreen" : "Vollbild", |
1809 | | "Go Fullscreen" : "Vollbild an", |
1810 | | "Turn off Fullscreen" : "Vollbild aus", |
1811 | | "Close" : "Schließen" |
1812 | | }; |
1813 | | |
1814 | | }(mejs.i18n.locale.strings)); |
| 13 | */var mejs=mejs||{};mejs.version="2.11.1";mejs.meIndex=0; |
| 14 | mejs.plugins={silverlight:[{version:[3,0],types:["video/mp4","video/m4v","video/mov","video/wmv","audio/wma","audio/m4a","audio/mp3","audio/wav","audio/mpeg"]}],flash:[{version:[9,0,124],types:["video/mp4","video/m4v","video/mov","video/flv","video/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"]}]}; |
| 16 | mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&").split("<").join("<").split('"').join(""")},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); |
| 17 | if(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(":"); |
| 18 | b=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)}}}; |
| 20 | mejs.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}}; |
| 22 | mejs.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}); |
| 23 | mejs.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}); |
| 24 | mejs.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)!== |
| 25 | null;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"; |
| 26 | a.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; |
| 27 | else 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(); |
| 28 | mejs.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}}; |
| 29 | mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={};this.attributes={}}; |
| 30 | mejs.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= |
| 31 | false}},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""}, |
| 32 | positionFullscreenButton: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)); |
| 33 | this.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); |
| 34 | this.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&& |
| 35 | this.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 |
| 36 | this.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)}}; |
| 37 | mejs.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); |
| 38 | b.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)}}; |
| 39 | mejs.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, |
| 40 | pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)}; |
| 41 | mejs.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}}, |
| 43 | determinePlayback: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"); |
| 44 | l=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]; |
| 46 | h=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(".")+ |
| 47 | 1).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= |
| 48 | c!==""?'<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, |
| 49 | n.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= |
| 50 | 320;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="'+ |
| 52 | d.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="'+ |
| 53 | l+'" width="'+f+'" height="'+h+'" class="mejs-shim"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&")+'" /><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="'+ |
| 54 | b.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}}; |
| 56 | mejs.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; |
| 58 | c.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]= |
| 59 | a;var b,c="http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid="+a.pluginId+"&version=3&autoplay=0&controls=0&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="'+ |
| 60 | c+'" /><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= |
| 61 | document.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; |
| 62 | c.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={"&":"&",'"':""","<":"<",">":">"};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); |
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) + '–' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' + |
4455 | | '</div>' + |
4456 | | '</div>')); |
4457 | | usedPercent += percent; |
4458 | | } |
4459 | | |
4460 | | t.chapters.find('div.mejs-chapter').click(function() { |
4461 | | t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) ); |
4462 | | if (t.media.paused) { |
4463 | | t.media.play(); |
4464 | | } |
4465 | | }); |
4466 | | |
4467 | | t.chapters.show(); |
4468 | | } |
4469 | | }); |
4470 | | |
4471 | | |
4472 | | |
4473 | | mejs.language = { |
4474 | | codes: { |
4475 | | af:'Afrikaans', |
4476 | | sq:'Albanian', |
4477 | | ar:'Arabic', |
4478 | | be:'Belarusian', |
4479 | | bg:'Bulgarian', |
4480 | | ca:'Catalan', |
4481 | | zh:'Chinese', |
4482 | | 'zh-cn':'Chinese Simplified', |
4483 | | 'zh-tw':'Chinese Traditional', |
4484 | | hr:'Croatian', |
4485 | | cs:'Czech', |
4486 | | da:'Danish', |
4487 | | nl:'Dutch', |
4488 | | en:'English', |
4489 | | et:'Estonian', |
4490 | | tl:'Filipino', |
4491 | | fi:'Finnish', |
4492 | | fr:'French', |
4493 | | gl:'Galician', |
4494 | | de:'German', |
4495 | | el:'Greek', |
4496 | | ht:'Haitian Creole', |
4497 | | iw:'Hebrew', |
4498 | | hi:'Hindi', |
4499 | | hu:'Hungarian', |
4500 | | is:'Icelandic', |
4501 | | id:'Indonesian', |
4502 | | ga:'Irish', |
4503 | | it:'Italian', |
4504 | | ja:'Japanese', |
4505 | | ko:'Korean', |
4506 | | lv:'Latvian', |
4507 | | lt:'Lithuanian', |
4508 | | mk:'Macedonian', |
4509 | | ms:'Malay', |
4510 | | mt:'Maltese', |
4511 | | no:'Norwegian', |
4512 | | fa:'Persian', |
4513 | | pl:'Polish', |
4514 | | pt:'Portuguese', |
4515 | | //'pt-pt':'Portuguese (Portugal)', |
4516 | | ro:'Romanian', |
4517 | | ru:'Russian', |
4518 | | sr:'Serbian', |
4519 | | sk:'Slovak', |
4520 | | sl:'Slovenian', |
4521 | | es:'Spanish', |
4522 | | sw:'Swahili', |
4523 | | sv:'Swedish', |
4524 | | tl:'Tagalog', |
4525 | | th:'Thai', |
4526 | | tr:'Turkish', |
4527 | | uk:'Ukrainian', |
4528 | | vi:'Vietnamese', |
4529 | | cy:'Welsh', |
4530 | | yi:'Yiddish' |
4531 | | } |
4532 | | }; |
4533 | | |
4534 | | /* |
4535 | | Parses WebVVT format which should be formatted as |
4536 | | ================================ |
4537 | | WEBVTT |
4538 | | |
4539 | | 1 |
4540 | | 00:00:01,1 --> 00:00:05,000 |
4541 | | A line of text |
4542 | | |
4543 | | 2 |
4544 | | 00:01:15,1 --> 00:02:05,000 |
4545 | | A second line of text |
4546 | | |
4547 | | =============================== |
4548 | | |
4549 | | Adapted from: http://www.delphiki.com/html5/playr |
4550 | | */ |
4551 | | mejs.TrackFormatParser = { |
4552 | | webvvt: { |
4553 | | // match start "chapter-" (or anythingelse) |
4554 | | pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/, |
4555 | | pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, |
4556 | | |
4557 | | parse: function(trackText) { |
4558 | | var |
4559 | | i = 0, |
4560 | | lines = mejs.TrackFormatParser.split2(trackText, /\r?\n/), |
4561 | | entries = {text:[], times:[]}, |
4562 | | timecode, |
4563 | | text; |
4564 | | for(; i<lines.length; i++) { |
4565 | | // check for the line number |
4566 | | if (this.pattern_identifier.exec(lines[i])){ |
4567 | | // skip to the next line where the start --> end time code should be |
4568 | | i++; |
4569 | | timecode = this.pattern_timecode.exec(lines[i]); |
4570 | | |
4571 | | if (timecode && i<lines.length){ |
4572 | | i++; |
4573 | | // grab all the (possibly multi-line) text that follows |
4574 | | text = lines[i]; |
4575 | | i++; |
4576 | | while(lines[i] !== '' && i<lines.length){ |
4577 | | text = text + '\n' + lines[i]; |
4578 | | i++; |
4579 | | } |
4580 | | text = $.trim(text).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>"); |
4581 | | // Text is in a different array so I can use .join |
4582 | | entries.text.push(text); |
4583 | | entries.times.push( |
4584 | | { |
4585 | | start: (mejs.Utility.convertSMPTEtoSeconds(timecode[1]) == 0) ? 0.200 : mejs.Utility.convertSMPTEtoSeconds(timecode[1]), |
4586 | | stop: mejs.Utility.convertSMPTEtoSeconds(timecode[3]), |
4587 | | settings: timecode[5] |
4588 | | }); |
4589 | | } |
4590 | | } |
4591 | | } |
4592 | | return entries; |
4593 | | } |
4594 | | }, |
4595 | | // Thanks to Justin Capella: https://github.com/johndyer/mediaelement/pull/420 |
4596 | | dfxp: { |
4597 | | parse: function(trackText) { |
4598 | | trackText = $(trackText).filter("tt"); |
4599 | | var |
4600 | | i = 0, |
4601 | | container = trackText.children("div").eq(0), |
4602 | | lines = container.find("p"), |
4603 | | styleNode = trackText.find("#" + container.attr("style")), |
4604 | | styles, |
4605 | | begin, |
4606 | | end, |
4607 | | text, |
4608 | | entries = {text:[], times:[]}; |
4609 | | |
4610 | | |
4611 | | if (styleNode.length) { |
4612 | | var attributes = styleNode.removeAttr("id").get(0).attributes; |
4613 | | if (attributes.length) { |
4614 | | styles = {}; |
4615 | | for (i = 0; i < attributes.length; i++) { |
4616 | | styles[attributes[i].name.split(":")[1]] = attributes[i].value; |
4617 | | } |
4618 | | } |
4619 | | } |
4620 | | |
4621 | | for(i = 0; i<lines.length; i++) { |
4622 | | var style; |
4623 | | var _temp_times = { |
4624 | | start: null, |
4625 | | stop: null, |
4626 | | style: null |
4627 | | }; |
4628 | | if (lines.eq(i).attr("begin")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("begin")); |
4629 | | if (!_temp_times.start && lines.eq(i-1).attr("end")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i-1).attr("end")); |
4630 | | if (lines.eq(i).attr("end")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("end")); |
4631 | | if (!_temp_times.stop && lines.eq(i+1).attr("begin")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i+1).attr("begin")); |
4632 | | if (styles) { |
4633 | | style = ""; |
4634 | | for (var _style in styles) { |
4635 | | style += _style + ":" + styles[_style] + ";"; |
4636 | | } |
4637 | | } |
4638 | | if (style) _temp_times.style = style; |
4639 | | if (_temp_times.start == 0) _temp_times.start = 0.200; |
4640 | | entries.times.push(_temp_times); |
4641 | | text = $.trim(lines.eq(i).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>"); |
4642 | | entries.text.push(text); |
4643 | | if (entries.times.start == 0) entries.times.start = 2; |
4644 | | } |
4645 | | return entries; |
4646 | | } |
4647 | | }, |
4648 | | split2: function (text, regex) { |
4649 | | // normal version for compliant browsers |
4650 | | // see below for IE fix |
4651 | | return text.split(regex); |
4652 | | } |
4653 | | }; |
4654 | | |
4655 | | // test for browsers with bad String.split method. |
4656 | | if ('x\n\ny'.split(/\n/gi).length != 3) { |
4657 | | // add super slow IE8 and below version |
4658 | | mejs.TrackFormatParser.split2 = function(text, regex) { |
4659 | | var |
4660 | | parts = [], |
4661 | | chunk = '', |
4662 | | i; |
4663 | | |
4664 | | for (i=0; i<text.length; i++) { |
4665 | | chunk += text.substring(i,i+1); |
4666 | | if (regex.test(chunk)) { |
4667 | | parts.push(chunk.replace(regex, '')); |
4668 | | chunk = ''; |
4669 | | } |
4670 | | } |
4671 | | parts.push(chunk); |
4672 | | return parts; |
4673 | | } |
4674 | | } |
4675 | | |
4676 | | })(mejs.$); |
4677 | | |
4678 | | /* |
4679 | | * ContextMenu Plugin |
4680 | | * |
4681 | | * |
4682 | | */ |
4683 | | |
4684 | | (function($) { |
4685 | | |
4686 | | $.extend(mejs.MepDefaults, |
4687 | | { 'contextMenuItems': [ |
4688 | | // demo of a fullscreen option |
4689 | | { |
4690 | | render: function(player) { |
4691 | | |
4692 | | // check for fullscreen plugin |
4693 | | if (typeof player.enterFullScreen == 'undefined') |
4694 | | return null; |
4695 | | |
4696 | | if (player.isFullScreen) { |
4697 | | return "Turn off Fullscreen"; |
4698 | | } else { |
4699 | | return "Go Fullscreen"; |
4700 | | } |
4701 | | }, |
4702 | | click: function(player) { |
4703 | | if (player.isFullScreen) { |
4704 | | player.exitFullScreen(); |
4705 | | } else { |
4706 | | player.enterFullScreen(); |
4707 | | } |
4708 | | } |
4709 | | } |
4710 | | , |
4711 | | // demo of a mute/unmute button |
4712 | | { |
4713 | | render: function(player) { |
4714 | | if (player.media.muted) { |
4715 | | return "Unmute"; |
4716 | | } else { |
4717 | | return "Mute"; |
4718 | | } |
4719 | | }, |
4720 | | click: function(player) { |
4721 | | if (player.media.muted) { |
4722 | | player.setMuted(false); |
4723 | | } else { |
4724 | | player.setMuted(true); |
4725 | | } |
4726 | | } |
4727 | | }, |
4728 | | // separator |
4729 | | { |
4730 | | isSeparator: true |
4731 | | } |
4732 | | , |
4733 | | // demo of simple download video |
4734 | | { |
4735 | | render: function(player) { |
4736 | | return "Download Video"; |
4737 | | }, |
4738 | | click: function(player) { |
4739 | | window.location.href = player.media.currentSrc; |
4740 | | } |
4741 | | } |
4742 | | ]} |
4743 | | ); |
4744 | | |
4745 | | |
4746 | | $.extend(MediaElementPlayer.prototype, { |
4747 | | buildcontextmenu: function(player, controls, layers, media) { |
4748 | | |
4749 | | // create context menu |
4750 | | player.contextMenu = $('<div class="mejs-contextmenu"></div>') |
4751 | | .appendTo($('body')) |
4752 | | .hide(); |
4753 | | |
4754 | | // create events for showing context menu |
4755 | | player.container.bind('contextmenu', function(e) { |
4756 | | if (player.isContextMenuEnabled) { |
4757 | | e.preventDefault(); |
4758 | | player.renderContextMenu(e.clientX-1, e.clientY-1); |
4759 | | return false; |
4760 | | } |
4761 | | }); |
4762 | | player.container.bind('click', function() { |
4763 | | player.contextMenu.hide(); |
4764 | | }); |
4765 | | player.contextMenu.bind('mouseleave', function() { |
4766 | | |
4767 | | //console.log('context hover out'); |
4768 | | player.startContextMenuTimer(); |
4769 | | |
4770 | | }); |
4771 | | }, |
4772 | | |
4773 | | cleancontextmenu: function(player) { |
4774 | | player.contextMenu.remove(); |
4775 | | }, |
4776 | | |
4777 | | isContextMenuEnabled: true, |
4778 | | enableContextMenu: function() { |
4779 | | this.isContextMenuEnabled = true; |
4780 | | }, |
4781 | | disableContextMenu: function() { |
4782 | | this.isContextMenuEnabled = false; |
4783 | | }, |
4784 | | |
4785 | | contextMenuTimeout: null, |
4786 | | startContextMenuTimer: function() { |
4787 | | //console.log('startContextMenuTimer'); |
4788 | | |
4789 | | var t = this; |
4790 | | |
4791 | | t.killContextMenuTimer(); |
4792 | | |
4793 | | t.contextMenuTimer = setTimeout(function() { |
4794 | | t.hideContextMenu(); |
4795 | | t.killContextMenuTimer(); |
4796 | | }, 750); |
4797 | | }, |
4798 | | killContextMenuTimer: function() { |
4799 | | var timer = this.contextMenuTimer; |
4800 | | |
4801 | | //console.log('killContextMenuTimer', timer); |
4802 | | |
4803 | | if (timer != null) { |
4804 | | clearTimeout(timer); |
4805 | | delete timer; |
4806 | | timer = null; |
4807 | | } |
4808 | | }, |
4809 | | |
4810 | | hideContextMenu: function() { |
4811 | | this.contextMenu.hide(); |
4812 | | }, |
4813 | | |
4814 | | renderContextMenu: function(x,y) { |
4815 | | |
4816 | | // alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly |
4817 | | var t = this, |
4818 | | html = '', |
4819 | | items = t.options.contextMenuItems; |
4820 | | |
4821 | | for (var i=0, il=items.length; i<il; i++) { |
4822 | | |
4823 | | if (items[i].isSeparator) { |
4824 | | html += '<div class="mejs-contextmenu-separator"></div>'; |
4825 | | } else { |
4826 | | |
4827 | | var rendered = items[i].render(t); |
4828 | | |
4829 | | // render can return null if the item doesn't need to be used at the moment |
4830 | | if (rendered != null) { |
4831 | | html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>'; |
4832 | | } |
4833 | | } |
4834 | | } |
4835 | | |
4836 | | // position and show the context menu |
4837 | | t.contextMenu |
4838 | | .empty() |
4839 | | .append($(html)) |
4840 | | .css({top:y, left:x}) |
4841 | | .show(); |
4842 | | |
4843 | | // bind events |
4844 | | t.contextMenu.find('.mejs-contextmenu-item').each(function() { |
4845 | | |
4846 | | // which one is this? |
4847 | | var $dom = $(this), |
4848 | | itemIndex = parseInt( $dom.data('itemindex'), 10 ), |
4849 | | item = t.options.contextMenuItems[itemIndex]; |
4850 | | |
4851 | | // bind extra functionality? |
4852 | | if (typeof item.show != 'undefined') |
4853 | | item.show( $dom , t); |
4854 | | |
4855 | | // bind click action |
4856 | | $dom.click(function() { |
4857 | | // perform click action |
4858 | | if (typeof item.click != 'undefined') |
4859 | | item.click(t); |
4860 | | |
4861 | | // close |
4862 | | t.contextMenu.hide(); |
4863 | | }); |
4864 | | }); |
4865 | | |
4866 | | // stop the controls from hiding |
4867 | | setTimeout(function() { |
4868 | | t.killControlsTimer('rev3'); |
4869 | | }, 100); |
4870 | | |
4871 | | } |
4872 | | }); |
4873 | | |
4874 | | })(mejs.$); |
4875 | | /** |
4876 | | * Postroll plugin |
4877 | | */ |
4878 | | (function($) { |
4879 | | |
4880 | | $.extend(mejs.MepDefaults, { |
4881 | | postrollCloseText: mejs.i18n.t('Close') |
4882 | | }); |
4883 | | |
4884 | | // Postroll |
4885 | | $.extend(MediaElementPlayer.prototype, { |
4886 | | buildpostroll: function(player, controls, layers, media) { |
4887 | | var |
4888 | | t = this, |
4889 | | postrollLink = t.container.find('link[rel="postroll"]').attr('href'); |
4890 | | |
4891 | | if (typeof postrollLink !== 'undefined') { |
4892 | | player.postroll = |
4893 | | $('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">' + t.options.postrollCloseText + '</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(layers).hide(); |
4894 | | |
4895 | | t.media.addEventListener('ended', function (e) { |
4896 | | $.ajax({ |
4897 | | dataType: 'html', |
4898 | | url: postrollLink, |
4899 | | success: function (data, textStatus) { |
4900 | | layers.find('.mejs-postroll-layer-content').html(data); |
4901 | | } |
4902 | | }); |
4903 | | player.postroll.show(); |
4904 | | }, false); |
4905 | | } |
4906 | | } |
4907 | | }); |
4908 | | |
4909 | | })(mejs.$); |
4910 | | |
| 77 | */if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender; |
| 78 | (function(f){mejs.MepDefaults={poster:"",defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,defaultSeekBackwardInterval:function(a){return a.duration*0.05},defaultSeekForwardInterval:function(a){return a.duration*0.05},audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,autoRewind:true,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true,alwaysShowControls:false,hideVideoControlsOnLoad:false, |
| 79 | clickToPlayPause:true,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks","volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?b.play():b.pause()}},{keys:[38],action:function(a,b){b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a, |
| 80 | b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.max(b.currentTime-a.options.defaultSeekBackwardInterval(b),0);b.setCurrentTime(c)}}},{keys:[39,228],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.min(b.currentTime+a.options.defaultSeekForwardInterval(b),b.duration);b.setCurrentTime(c)}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen? |
| 81 | a.exitFullScreen():a.enterFullScreen()}}]};mejs.mepIndex=0;mejs.players={};mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);this.id="mep_"+mejs.mepIndex++;mejs.players[this.id]= |
| 82 | this;this.init();return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(e,g){a.meReady(e,g)},error:function(e){a.handleError(e)}}),d=a.media.tagName.toLowerCase();a.isDynamic=d!=="audio"&&d!=="video";a.isVideo=a.isDynamic?a.options.isVideo:d!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls", |
| 83 | "controls");if(b.isiPad&&a.media.getAttribute("autoplay")!==null){a.media.load();a.media.play()}}else if(!(b.isAndroid&&a.options.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.container=f('<div id="'+a.id+'" class="mejs-container '+(mejs.MediaFeatures.svg?"svg":"no-svg")+'"><div class="mejs-inner"><div class="mejs-mediaelement"></div><div class="mejs-layers"></div><div class="mejs-controls"></div><div class="mejs-clear"></div></div></div>').addClass(a.$media[0].className).insertBefore(a.$media); |
| 84 | a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=a.isVideo?"video":"audio";d=b.substring(0, |
| 85 | 1).toUpperCase()+b.substring(1);a.width=a.options[b+"Width"]>0||a.options[b+"Width"].toString().indexOf("%")>-1?a.options[b+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+d+"Width"];a.height=a.options[b+"Height"]>0||a.options[b+"Height"].toString().indexOf("%")>-1?a.options[b+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!== |
| 86 | null?a.$media.attr("height"):a.options["default"+d+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.height;c.pluginHeight=a.width}mejs.MediaElement(a.$media[0],c);typeof a.container!="undefined"&&a.container.trigger("controlsshown")},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true;b.container.trigger("controlsshown")});b.container.find(".mejs-control").css("visibility", |
| 87 | "visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility","visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true;b.container.trigger("controlsshown")}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(b.controlsAreVisible)if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display", |
| 88 | "block");b.controlsAreVisible=false;b.container.trigger("controlshidden")});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")}},controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"? |
| 89 | a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true},meReady:function(a,b){var c=this, |
| 90 | d=mejs.MediaFeatures,e=b.getAttribute("autoplay");e=!(typeof e=="undefined"||e===null||e==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(d.isAndroid&&c.options.AndroidUseNativeControls)&&!(d.isiPad&&c.options.iPadUseNativeControls)&&!(d.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){d=c.options.features[g]; |
| 91 | if(c["build"+d])try{c["build"+d](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);else c.controlsEnabled&&c.showControls(false)});else{c.media.addEventListener("click",function(){if(c.options.clickToPlayPause)c.media.paused?c.media.play():c.media.pause()});c.container.bind("mouseenter mouseover", |
| 92 | function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&&c.startControlsTimer(1E3)})}c.options.hideVideoControlsOnLoad&&c.hideControls(false);e&&!c.options.alwaysShowControls&& |
| 93 | c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(j){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(j.target.videoHeight)){c.setPlayerSize(j.target.videoWidth,j.target.videoHeight);c.setControlsSize();c.media.setVideoSize(j.target.videoWidth,j.target.videoHeight)}},false)}a.addEventListener("play",function(){for(var j in mejs.players){var l=mejs.players[j];l.id!=c.id&&c.options.pauseOtherPlayers&&!l.paused&&!l.ended&&l.pause(); |
| 94 | l.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){if(c.options.autoRewind)try{c.media.setCurrentTime(0)}catch(j){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",function(){c.updateDuration&&c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width, |
| 95 | c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);c.globalBind("resize",function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(e&&a.pluginType=="native"){a.load();a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media, |
| 96 | c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0||this.$node.css("max-width")==="100%"||this.$node[0].currentStyle&&this.$node[0].currentStyle.maxWidth==="100%"){var c=this.isVideo?this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth: |
| 97 | this.options.defaultAudioWidth,d=this.isVideo?this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight:this.options.defaultAudioHeight,e=this.container.parent().closest(":visible").width();c=this.isVideo||!this.options.autosizeProgress?parseInt(e*d/c,10):d;if(this.container.parent()[0].tagName.toLowerCase()==="body"){e=f(window).width();c=f(window).height()}if(c!=0&&e!=0){this.container.width(e).height(c);this.$media.add(this.container.find(".mejs-shim")).width("100%").height("100%"); |
| 98 | this.isVideo&&this.media.setVideoSize&&this.media.setVideoSize(e,c);this.layers.children(".mejs-layer").width("100%").height("100%")}}else{this.container.width(this.width).height(this.height);this.layers.children(".mejs-layer").width(this.width).height(this.height)}},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),d=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var e=c.siblings();if(this.options&& |
| 99 | !this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){e.each(function(){var g=f(this);if(g.css("position")!="absolute"&&g.is(":visible"))a+=f(this).outerWidth(true)});b=this.controls.width()-a-(c.outerWidth(true)-c.width())}c.width(b);d.width(b-(d.outerWidth(true)-d.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,d){var e=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster"); |
| 100 | if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):e.hide();d.addEventListener("play",function(){e.hide()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"),c=b.find("img");if(c.length==0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a)},buildoverlays:function(a,b,c,d){var e=this;if(a.isVideo){var g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c), |
| 101 | j=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).click(function(){if(e.options.clickToPlayPause)d.paused?d.play():d.pause()});d.addEventListener("play",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);d.addEventListener("playing",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);d.addEventListener("seeking",function(){g.show();b.find(".mejs-time-buffering").show()}, |
| 102 | false);d.addEventListener("seeked",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||j.show()},false);d.addEventListener("waiting",function(){g.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("loadeddata",function(){g.show();b.find(".mejs-time-buffering").show()},false);d.addEventListener("canplay",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);d.addEventListener("error",function(){g.hide(); |
| 103 | b.find(".mejs-time-buffering").hide();k.show();k.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,d){this.globalBind("keydown",function(e){if(a.hasFocus&&a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g<k;g++)for(var j=a.options.keyActions[g],l=0,q=j.keys.length;l<q;l++)if(e.keyCode==j.keys[l]){e.preventDefault();j.action(a,d,e.keyCode);return false}return true});this.globalBind("click",function(e){if(f(e.target).closest(".mejs-container").length== |
| 104 | 0)a.hasFocus=false})},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,d){d=f(d);a.tracks.push({srclang:d.attr("srclang")?d.attr("srclang").toLowerCase():"",src:d.attr("src"),kind:d.attr("kind"),label:d.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.media.play()},pause:function(){this.media.pause()}, |
| 105 | load:function(){this.media.load()},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime},setVolume:function(a){this.media.setVolume(a)},getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){var a,b;for(a in this.options.features){b=this.options.features[a];if(this["clean"+b])try{this["clean"+b](this)}catch(c){}}this.media.pluginType==="native"? |
| 106 | this.$media.prop("controls",true):this.media.remove();this.isDynamic||this.$node.insertBefore(this.container);delete mejs.players[this.id];this.container.remove();this.globalUnbind();delete this.node.player}};(function(){function a(c,d){var e={d:[],w:[]};f.each((c||"").split(" "),function(g,k){e[b.test(k)?"w":"d"].push(k+"."+d)});e.d=e.d.join(" ");e.w=e.w.join(" ");return e}var b=/^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/;mejs.MediaElementPlayer.prototype.globalBind= |
| 107 | function(c,d,e){c=a(c,this.id);c.d&&f(document).bind(c.d,d,e);c.w&&f(window).bind(c.w,d,e)};mejs.MediaElementPlayer.prototype.globalUnbind=function(c,d){c=a(c,this.id);c.d&&f(document).unbind(c.d,d);c.w&&f(window).unbind(c.w,d)}})();if(typeof jQuery!="undefined")jQuery.fn.mediaelementplayer=function(a){a===false?this.each(function(){var b=jQuery(this).data("mediaelementplayer");b&&b.remove();jQuery(this).removeData("mediaelementplayer")}):this.each(function(){jQuery(this).data("mediaelementplayer", |
| 108 | new mejs.MediaElementPlayer(this,a))});return this};f(document).ready(function(){f(".mejs-player").mediaelementplayer()});window.MediaElementPlayer=mejs.MediaElementPlayer})(mejs.$); |
| 109 | (function(f){f.extend(mejs.MepDefaults,{playpauseText:"Play/Pause"});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,d){var e=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'" aria-label="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();d.paused?d.play():d.pause();return false});d.addEventListener("play",function(){e.removeClass("mejs-play").addClass("mejs-pause")}, |
| 110 | false);d.addEventListener("playing",function(){e.removeClass("mejs-play").addClass("mejs-pause")},false);d.addEventListener("pause",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false);d.addEventListener("paused",function(){e.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$); |
| 111 | (function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,d){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'" aria-label="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){d.paused||d.pause();if(d.currentTime>0){d.setCurrentTime(0);d.pause();b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left", |
| 112 | "0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$); |
| 113 | (function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,d){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var e= |
| 114 | this,g=b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var k=b.find(".mejs-time-current"),j=b.find(".mejs-time-handle"),l=b.find(".mejs-time-float"),q=b.find(".mejs-time-float-current"),p=function(h){h=h.pageX;var m=g.offset(),r=g.outerWidth(true),n=0,o=n=0;if(d.duration){if(h<m.left)h=m.left;else if(h>r+m.left)h=r+m.left;o=h-m.left;n=o/r;n=n<=0.02?0:n*d.duration;t&&n!==d.currentTime&&d.setCurrentTime(n);if(!mejs.MediaFeatures.hasTouch){l.css("left",o);q.html(mejs.Utility.secondsToTimeCode(n)); |
| 115 | l.show()}}},t=false;g.bind("mousedown",function(h){if(h.which===1){t=true;p(h);e.globalBind("mousemove.dur",function(m){p(m)});e.globalBind("mouseup.dur",function(){t=false;l.hide();e.globalUnbind(".dur")});return false}}).bind("mouseenter",function(){e.globalBind("mousemove.dur",function(h){p(h)});mejs.MediaFeatures.hasTouch||l.show()}).bind("mouseleave",function(){if(!t){e.globalUnbind(".dur");l.hide()}});d.addEventListener("progress",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false); |
| 116 | d.addEventListener("timeupdate",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);e.loaded=c;e.total=g;e.current=k;e.handle=j},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1, |
| 117 | Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=Math.round(this.total.width()*this.media.currentTime/this.media.duration),b=a-Math.round(this.handle.outerWidth(true)/2);this.current.width(a);this.handle.css("left",b)}}})})(mejs.$); |
| 118 | (function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" <span> | </span> "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,d){f('<div class="mejs-time"><span class="mejs-currenttime">'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");d.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a, |
| 119 | b,c,d){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container"); |
| 120 | f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");d.addEventListener("timeupdate",function(){a.updateDuration()}, |
| 121 | false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){this.container.toggleClass("mejs-long-video",this.media.duration>3600);if(this.durationD&&(this.options.duration>0||this.media.duration))this.durationD.html(mejs.Utility.secondsToTimeCode(this.options.duration>0?this.options.duration: |
| 122 | this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$); |
| 123 | (function(f){f.extend(mejs.MepDefaults,{muteText:"Mute Toggle",hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,d){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var e=this,g=e.isVideo?e.options.videoVolume:e.options.audioVolume,k=g=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+e.id+'" title="'+e.options.muteText+ |
| 124 | '" aria-label="'+e.options.muteText+'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+e.id+'" title="'+e.options.muteText+'" aria-label="'+e.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b), |
| 125 | j=e.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),l=e.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),q=e.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),p=e.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),t=function(n,o){if(!j.is(":visible")&&typeof o=="undefined"){j.show();t(n,true);j.hide()}else{n=Math.max(0,n);n=Math.min(n,1);n==0?k.removeClass("mejs-mute").addClass("mejs-unmute"):k.removeClass("mejs-unmute").addClass("mejs-mute"); |
| 126 | if(g=="vertical"){var s=l.height(),u=l.position(),v=s-s*n;p.css("top",Math.round(u.top+v-p.height()/2));q.height(s-v);q.css("top",u.top+v)}else{s=l.width();u=l.position();s=s*n;p.css("left",Math.round(u.left+s-p.width()/2));q.width(Math.round(s))}}},h=function(n){var o=null,s=l.offset();if(g=="vertical"){o=l.height();parseInt(l.css("top").replace(/px/,""),10);o=(o-(n.pageY-s.top))/o;if(s.top==0||s.left==0)return}else{o=l.width();o=(n.pageX-s.left)/o}o=Math.max(0,o);o=Math.min(o,1);t(o);o==0?d.setMuted(true): |
| 127 | d.setMuted(false);d.setVolume(o)},m=false,r=false;k.hover(function(){j.show();r=true},function(){r=false;!m&&g=="vertical"&&j.hide()});j.bind("mouseover",function(){r=true}).bind("mousedown",function(n){h(n);e.globalBind("mousemove.vol",function(o){h(o)});e.globalBind("mouseup.vol",function(){m=false;e.globalUnbind(".vol");!r&&g=="vertical"&&j.hide()});m=true;return false});k.find("button").click(function(){d.setMuted(!d.muted)});d.addEventListener("volumechange",function(){if(!m)if(d.muted){t(0); |
| 128 | k.removeClass("mejs-mute").addClass("mejs-unmute")}else{t(d.volume);k.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(e.container.is(":visible")){t(a.options.startVolume);a.options.startVolume===0&&d.setMuted(true);d.pluginType==="native"&&d.setVolume(a.options.startVolume)}}}})})(mejs.$); |
| 129 | (function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:mejs.i18n.t("Fullscreen")});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,docStyleOverflow:null,isInIframe:false,buildfullscreen:function(a,b,c,d){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=function(){if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen= |
| 130 | false;a.exitFullScreen()}};mejs.MediaFeatures.hasMozNativeFullScreen?a.globalBind(mejs.MediaFeatures.fullScreenEventName,c):a.container.bind(mejs.MediaFeatures.fullScreenEventName,c)}var e=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+e.id+'" title="'+e.options.fullscreenText+'" aria-label="'+e.options.fullscreenText+'"></button></div>').appendTo(b);if(e.media.pluginType==="native"||!e.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&& |
| 131 | mejs.MediaFeatures.isFullScreen()||a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;if(function(){var h=document.createElement("x"),m=document.documentElement,r=window.getComputedStyle;if(!("pointerEvents"in h.style))return false;h.style.pointerEvents="auto";h.style.pointerEvents="x";m.appendChild(h);r=r&&r(h,"").pointerEvents==="auto";m.removeChild(h);return!!r}()&&!mejs.MediaFeatures.isOpera){var j=false,l=function(){if(j){for(var h in q)q[h].hide();g.css("pointer-events", |
| 132 | "");e.controls.css("pointer-events","");j=false}},q={};b=["top","left","right","bottom"];var p,t=function(){var h=g.offset().left-e.container.offset().left,m=g.offset().top-e.container.offset().top,r=g.outerWidth(true),n=g.outerHeight(true),o=e.container.width(),s=e.container.height();for(p in q)q[p].css({position:"absolute",top:0,left:0});q.top.width(o).height(m);q.left.width(h).height(n).css({top:m});q.right.width(o-h-r).height(n).css({top:m,left:h+r});q.bottom.width(o).height(s-n-m).css({top:m+ |
| 133 | n})};e.globalBind("resize",function(){t()});p=0;for(c=b.length;p<c;p+=1)q[b[p]]=f('<div class="mejs-fullscreen-hover" />').appendTo(e.container).mouseover(l).hide();g.mouseover(function(){if(!e.isFullScreen){var h=g.offset(),m=a.container.offset();d.positionFullscreenButton(h.left-m.left,h.top-m.top,false);g.css("pointer-events","none");e.controls.css("pointer-events","none");for(p in q)q[p].show();t();j=true}});d.addEventListener("fullscreenchange",function(){l()})}else g.mouseover(function(){if(k!== |
| 134 | null){clearTimeout(k);delete k}var h=g.offset(),m=a.container.offset();d.positionFullscreenButton(h.left-m.left,h.top-m.top,true)}).mouseout(function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){d.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;e.globalBind("keydown",function(h){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||e.isFullScreen)&&h.keyCode==27)a.exitFullScreen()})}},cleanfullscreen:function(a){a.exitFullScreen()},containerSizeTimeout:null, |
| 135 | enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){docStyleOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow="hidden";normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!== |
| 136 | screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},250);else{a.pause();window.open(b,a.id, |
| 137 | "top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");a.containerSizeTimeout=setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find(".mejs-shim").width("100%").height("100%");a.media.setVideoSize(f(window).width(),f(window).height())}a.layers.children("div").width("100%").height("100%"); |
| 138 | a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){clearTimeout(this.containerSizeTimeout);if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen();document.documentElement.style.overflow=docStyleOverflow; |
| 139 | this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find("object embed").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen");this.setControlsSize();this.isFullScreen=false}}})})(mejs.$); |
| 140 | (function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:"Captions/Subtitles",hideCaptionsButtonWhenEmpty:true,toggleCaptionsButtonWhenOnlyOne:false,slidesSelector:""});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,d){if(a.tracks.length!=0){a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide();a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide(); |
| 141 | a.captionsText=a.captions.find(".mejs-captions-text");a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'" aria-label="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">None</label></li></ul></div></div>').appendTo(b);for(b=c=0;b< |
| 142 | a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&c++;this.options.toggleCaptionsButtonWhenOnlyOne&&c==1?a.captionsButton.on("click",function(){a.setTrack(a.selectedTrack==null?a.tracks[0].srclang:"none")}):a.captionsButton.hover(function(){f(this).find(".mejs-captions-selector").css("visibility","visible")},function(){f(this).find(".mejs-captions-selector").css("visibility","hidden")}).on("click","input[type=radio]",function(){lang=this.value;a.setTrack(lang)});a.options.alwaysShowControls?a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"): |
| 143 | a.container.bind("controlsshown",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("controlshidden",function(){d.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")});a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(b=0;b<a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&a.addTrackButton(a.tracks[b].srclang,a.tracks[b].label);a.loadNextTrack();d.addEventListener("timeupdate",function(){a.displayCaptions()}, |
| 144 | false);if(a.options.slidesSelector!=""){a.slidesContainer=f(a.options.slidesSelector);d.addEventListener("timeupdate",function(){a.displaySlides()},false)}d.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility","visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&&!d.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden"); |
| 145 | f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},setTrack:function(a){var b;if(a=="none"){this.selectedTrack=null;this.captionsButton.removeClass("mejs-captions-enabled")}else for(b=0;b<this.tracks.length;b++)if(this.tracks[b].srclang==a){this.selectedTrack==null&&this.captionsButton.addClass("mejs-captions-enabled");this.selectedTrack=this.tracks[b];this.captions.attr("lang",this.selectedTrack.srclang);this.displayCaptions();break}}, |
| 146 | loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else{this.isLoadingTrack=false;this.checkForTracks()}},loadTrack:function(a){var b=this,c=b.tracks[a];f.ajax({url:c.src,dataType:"text",success:function(d){c.entries=typeof d=="string"&&/<tt\s+xml/ig.exec(d)?mejs.TrackFormatParser.dfxp.parse(d):mejs.TrackForma |