rsence-pre 3.0.0.10 → 3.0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/client/conf/client_pkg.yaml +17 -1
  4. data/client/ext/Rakefile +42 -12
  5. data/client/js/comm/transporter/transporter.js +1 -0
  6. data/client/js/controls/numerictextcontrol/numerictextcontrol.coffee +10 -11
  7. data/client/js/controls/searchfield/themes/default/searchfield.css +56 -91
  8. data/client/js/controls/searchfield/themes/default/searchfield.html +10 -10
  9. data/client/js/controls/textcontrol/textcontrol.coffee +71 -65
  10. data/client/js/core/elem/elem.coffee +5 -0
  11. data/client/js/datetime/datepicker/datepicker.coffee +1 -0
  12. data/client/js/datetime/momentjs/momentjs.js +12 -4
  13. data/client/js/foundation/control/eventresponder/eventresponder.js +14 -0
  14. data/client/js/foundation/json_renderer/json_renderer.js +12 -12
  15. data/client/js/foundation/view/view.js +13 -4
  16. data/client/js/lists/radiobuttonlist/radiobuttonlist.js +9 -8
  17. data/client/js/media/mediaelement/mediaelement.js +1890 -0
  18. data/client/js/media/mediaelement_defaults/mediaelement_defaults.coffee +1 -0
  19. data/client/js/media/mediaelement_resources/mediaelement_resources.js +1 -0
  20. data/client/js/media/mediaelement_resources/themes/mejs/flashmediaelement.swf +0 -0
  21. data/client/js/media/mediaelement_resources/themes/mejs/mediaelement_resources.css +0 -0
  22. data/client/js/media/mediaelement_resources/themes/mejs/mediaelement_resources.html +0 -0
  23. data/client/js/media/mediaelement_resources/themes/mejs/silverlightmediaelement.xap +0 -0
  24. data/client/js/menus/combobox/combobox.coffee +6 -1
  25. data/client/js/menus/menuitem/themes/default/menuitem.css +5 -8
  26. data/client/js/menus/minimenu/minimenu.js +2 -2
  27. data/client/js/menus/minimenu/themes/default/minimenu.css +6 -22
  28. data/client/js/menus/minimenuitem/themes/default/minimenuitem.css +5 -8
  29. data/client/js/menus/popupmenu/themes/default/popupmenu.css +6 -27
  30. data/plugins/client_pkg/lib/client_pkg_build.rb +5 -1
  31. metadata +8 -1
@@ -0,0 +1,1890 @@
1
+ /*!
2
+ * MediaElement.js
3
+ * HTML5 <video> and <audio> shim and player
4
+ * http://mediaelementjs.com/
5
+ *
6
+ * Creates a JavaScript object that mimics HTML5 MediaElement API
7
+ * for browsers that don't understand HTML5 or can't play the provided codec
8
+ * Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
9
+ *
10
+ * Copyright 2010-2013, John Dyer (http://j.hn)
11
+ * License: MIT
12
+ *
13
+ */
14
+ // Namespace
15
+ var mejs = mejs || {};
16
+
17
+ // version number
18
+ mejs.version = '2.12.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
+ Utility methods
42
+ */
43
+ mejs.Utility = {
44
+ encodeUrl: function(url) {
45
+ return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
46
+ },
47
+ escapeHTML: function(s) {
48
+ return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
49
+ },
50
+ absolutizeUrl: function(url) {
51
+ var el = document.createElement('div');
52
+ el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
53
+ return el.firstChild.href;
54
+ },
55
+ getScriptPath: function(scriptNames) {
56
+ var
57
+ i = 0,
58
+ j,
59
+ codePath = '',
60
+ testname = '',
61
+ slashPos,
62
+ filenamePos,
63
+ scriptUrl,
64
+ scriptPath,
65
+ scriptFilename,
66
+ scripts = document.getElementsByTagName('script'),
67
+ il = scripts.length,
68
+ jl = scriptNames.length;
69
+
70
+ // go through all <script> tags
71
+ for (; i < il; i++) {
72
+ scriptUrl = scripts[i].src;
73
+ slashPos = scriptUrl.lastIndexOf('/');
74
+ if (slashPos > -1) {
75
+ scriptFilename = scriptUrl.substring(slashPos + 1);
76
+ scriptPath = scriptUrl.substring(0, slashPos + 1);
77
+ } else {
78
+ scriptFilename = scriptUrl;
79
+ scriptPath = '';
80
+ }
81
+
82
+ // see if any <script> tags have a file name that matches the
83
+ for (j = 0; j < jl; j++) {
84
+ testname = scriptNames[j];
85
+ filenamePos = scriptFilename.indexOf(testname);
86
+ if (filenamePos > -1) {
87
+ codePath = scriptPath;
88
+ break;
89
+ }
90
+ }
91
+
92
+ // if we found a path, then break and return it
93
+ if (codePath !== '') {
94
+ break;
95
+ }
96
+ }
97
+
98
+ // send the best path back
99
+ return codePath;
100
+ },
101
+ secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
102
+ //add framecount
103
+ if (typeof showFrameCount == 'undefined') {
104
+ showFrameCount=false;
105
+ } else if(typeof fps == 'undefined') {
106
+ fps = 25;
107
+ }
108
+
109
+ var hours = Math.floor(time / 3600) % 24,
110
+ minutes = Math.floor(time / 60) % 60,
111
+ seconds = Math.floor(time % 60),
112
+ frames = Math.floor(((time % 1)*fps).toFixed(3)),
113
+ result =
114
+ ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
115
+ + (minutes < 10 ? '0' + minutes : minutes) + ':'
116
+ + (seconds < 10 ? '0' + seconds : seconds)
117
+ + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
118
+
119
+ return result;
120
+ },
121
+
122
+ timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
123
+ if (typeof showFrameCount == 'undefined') {
124
+ showFrameCount=false;
125
+ } else if(typeof fps == 'undefined') {
126
+ fps = 25;
127
+ }
128
+
129
+ var tc_array = hh_mm_ss_ff.split(":"),
130
+ tc_hh = parseInt(tc_array[0], 10),
131
+ tc_mm = parseInt(tc_array[1], 10),
132
+ tc_ss = parseInt(tc_array[2], 10),
133
+ tc_ff = 0,
134
+ tc_in_seconds = 0;
135
+
136
+ if (showFrameCount) {
137
+ tc_ff = parseInt(tc_array[3])/fps;
138
+ }
139
+
140
+ tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
141
+
142
+ return tc_in_seconds;
143
+ },
144
+
145
+
146
+ convertSMPTEtoSeconds: function (SMPTE) {
147
+ if (typeof SMPTE != 'string')
148
+ return false;
149
+
150
+ SMPTE = SMPTE.replace(',', '.');
151
+
152
+ var secs = 0,
153
+ decimalLen = (SMPTE.indexOf('.') != -1) ? SMPTE.split('.')[1].length : 0,
154
+ multiplier = 1;
155
+
156
+ SMPTE = SMPTE.split(':').reverse();
157
+
158
+ for (var i = 0; i < SMPTE.length; i++) {
159
+ multiplier = 1;
160
+ if (i > 0) {
161
+ multiplier = Math.pow(60, i);
162
+ }
163
+ secs += Number(SMPTE[i]) * multiplier;
164
+ }
165
+ return Number(secs.toFixed(decimalLen));
166
+ },
167
+
168
+ /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
169
+ removeSwf: function(id) {
170
+ var obj = document.getElementById(id);
171
+ if (obj && /object|embed/i.test(obj.nodeName)) {
172
+ if (mejs.MediaFeatures.isIE) {
173
+ obj.style.display = "none";
174
+ (function(){
175
+ if (obj.readyState == 4) {
176
+ mejs.Utility.removeObjectInIE(id);
177
+ } else {
178
+ setTimeout(arguments.callee, 10);
179
+ }
180
+ })();
181
+ } else {
182
+ obj.parentNode.removeChild(obj);
183
+ }
184
+ }
185
+ },
186
+ removeObjectInIE: function(id) {
187
+ var obj = document.getElementById(id);
188
+ if (obj) {
189
+ for (var i in obj) {
190
+ if (typeof obj[i] == "function") {
191
+ obj[i] = null;
192
+ }
193
+ }
194
+ obj.parentNode.removeChild(obj);
195
+ }
196
+ }
197
+ };
198
+
199
+
200
+ // Core detector, plugins are added below
201
+ mejs.PluginDetector = {
202
+
203
+ // main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
204
+ hasPluginVersion: function(plugin, v) {
205
+ var pv = this.plugins[plugin];
206
+ v[1] = v[1] || 0;
207
+ v[2] = v[2] || 0;
208
+ 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;
209
+ },
210
+
211
+ // cached values
212
+ nav: window.navigator,
213
+ ua: window.navigator.userAgent.toLowerCase(),
214
+
215
+ // stored version numbers
216
+ plugins: [],
217
+
218
+ // runs detectPlugin() and stores the version number
219
+ addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
220
+ this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
221
+ },
222
+
223
+ // get the version number from the mimetype (all but IE) or ActiveX (IE)
224
+ detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
225
+
226
+ var version = [0,0,0],
227
+ description,
228
+ i,
229
+ ax;
230
+
231
+ // Firefox, Webkit, Opera
232
+ if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
233
+ description = this.nav.plugins[pluginName].description;
234
+ if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
235
+ version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
236
+ for (i=0; i<version.length; i++) {
237
+ version[i] = parseInt(version[i].match(/\d+/), 10);
238
+ }
239
+ }
240
+ // Internet Explorer / ActiveX
241
+ } else if (typeof(window.ActiveXObject) != 'undefined') {
242
+ try {
243
+ ax = new ActiveXObject(activeX);
244
+ if (ax) {
245
+ version = axDetect(ax);
246
+ }
247
+ }
248
+ catch (e) { }
249
+ }
250
+ return version;
251
+ }
252
+ };
253
+
254
+ // Add Flash detection
255
+ mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
256
+ // adapted from SWFObject
257
+ var version = [],
258
+ d = ax.GetVariable("$version");
259
+ if (d) {
260
+ d = d.split(" ")[1].split(",");
261
+ version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
262
+ }
263
+ return version;
264
+ });
265
+
266
+ // Add Silverlight detection
267
+ mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
268
+ // Silverlight cannot report its version number to IE
269
+ // but it does have a isVersionSupported function, so we have to loop through it to get a version number.
270
+ // adapted from http://www.silverlightversion.com/
271
+ var v = [0,0,0,0],
272
+ loopMatch = function(ax, v, i, n) {
273
+ while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
274
+ v[i]+=n;
275
+ }
276
+ v[i] -= n;
277
+ };
278
+ loopMatch(ax, v, 0, 1);
279
+ loopMatch(ax, v, 1, 1);
280
+ loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
281
+ loopMatch(ax, v, 2, 1000);
282
+ loopMatch(ax, v, 2, 100);
283
+ loopMatch(ax, v, 2, 10);
284
+ loopMatch(ax, v, 2, 1);
285
+ loopMatch(ax, v, 3, 1);
286
+
287
+ return v;
288
+ });
289
+ // add adobe acrobat
290
+ /*
291
+ PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
292
+ var version = [],
293
+ d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
294
+
295
+ if (d) {
296
+ version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
297
+ }
298
+ return version;
299
+ });
300
+ */
301
+ // necessary detection (fixes for <IE9)
302
+ mejs.MediaFeatures = {
303
+ init: function() {
304
+ var
305
+ t = this,
306
+ d = document,
307
+ nav = mejs.PluginDetector.nav,
308
+ ua = mejs.PluginDetector.ua.toLowerCase(),
309
+ i,
310
+ v,
311
+ html5Elements = ['source','track','audio','video'];
312
+
313
+ // detect browsers (only the ones that have some kind of quirk we need to work around)
314
+ t.isiPad = (ua.match(/ipad/i) !== null);
315
+ t.isiPhone = (ua.match(/iphone/i) !== null);
316
+ t.isiOS = t.isiPhone || t.isiPad;
317
+ t.isAndroid = (ua.match(/android/i) !== null);
318
+ t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
319
+ t.isBustedNativeHTTPS = (location.protocol === 'https:' && (ua.match(/android [12]\./) !== null || ua.match(/macintosh.* version.* safari/) !== null));
320
+ t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
321
+ t.isChrome = (ua.match(/chrome/gi) !== null);
322
+ t.isFirefox = (ua.match(/firefox/gi) !== null);
323
+ t.isWebkit = (ua.match(/webkit/gi) !== null);
324
+ t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
325
+ t.isOpera = (ua.match(/opera/gi) !== null);
326
+ t.hasTouch = ('ontouchstart' in window);
327
+
328
+ // borrowed from Modernizr
329
+ t.svg = !! document.createElementNS &&
330
+ !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect;
331
+
332
+ // create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
333
+ for (i=0; i<html5Elements.length; i++) {
334
+ v = document.createElement(html5Elements[i]);
335
+ }
336
+
337
+ t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid);
338
+
339
+ // Fix for IE9 on Windows 7N / Windows 7KN (Media Player not installer)
340
+ try{
341
+ v.canPlayType("video/mp4");
342
+ }catch(e){
343
+ t.supportsMediaTag = false;
344
+ }
345
+
346
+ // detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails)
347
+
348
+ // iOS
349
+ t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined');
350
+
351
+ // Webkit/firefox
352
+ t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
353
+ t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined');
354
+
355
+ t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen);
356
+ t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen;
357
+ if (t.hasMozNativeFullScreen) {
358
+ t.nativeFullScreenEnabled = v.mozFullScreenEnabled;
359
+ }
360
+
361
+
362
+ if (this.isChrome) {
363
+ t.hasSemiNativeFullScreen = false;
364
+ }
365
+
366
+ if (t.hasTrueNativeFullScreen) {
367
+ t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange';
368
+
369
+
370
+ t.isFullScreen = function() {
371
+ if (v.mozRequestFullScreen) {
372
+ return d.mozFullScreen;
373
+ } else if (v.webkitRequestFullScreen) {
374
+ return d.webkitIsFullScreen;
375
+ }
376
+ }
377
+
378
+ t.requestFullScreen = function(el) {
379
+
380
+ if (t.hasWebkitNativeFullScreen) {
381
+ el.webkitRequestFullScreen();
382
+ } else if (t.hasMozNativeFullScreen) {
383
+ el.mozRequestFullScreen();
384
+ }
385
+ }
386
+
387
+ t.cancelFullScreen = function() {
388
+ if (t.hasWebkitNativeFullScreen) {
389
+ document.webkitCancelFullScreen();
390
+ } else if (t.hasMozNativeFullScreen) {
391
+ document.mozCancelFullScreen();
392
+ }
393
+ }
394
+
395
+ }
396
+
397
+
398
+ // OS X 10.5 can't do this even if it says it can :(
399
+ if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) {
400
+ t.hasNativeFullScreen = false;
401
+ t.hasSemiNativeFullScreen = false;
402
+ }
403
+
404
+ }
405
+ };
406
+ mejs.MediaFeatures.init();
407
+
408
+ /*
409
+ extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
410
+ */
411
+ mejs.HtmlMediaElement = {
412
+ pluginType: 'native',
413
+ isFullScreen: false,
414
+
415
+ setCurrentTime: function (time) {
416
+ this.currentTime = time;
417
+ },
418
+
419
+ setMuted: function (muted) {
420
+ this.muted = muted;
421
+ },
422
+
423
+ setVolume: function (volume) {
424
+ this.volume = volume;
425
+ },
426
+
427
+ // for parity with the plugin versions
428
+ stop: function () {
429
+ this.pause();
430
+ },
431
+
432
+ // This can be a url string
433
+ // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
434
+ setSrc: function (url) {
435
+
436
+ // Fix for IE9 which can't set .src when there are <source> elements. Awesome, right?
437
+ var
438
+ existingSources = this.getElementsByTagName('source');
439
+ while (existingSources.length > 0){
440
+ this.removeChild(existingSources[0]);
441
+ }
442
+
443
+ if (typeof url == 'string') {
444
+ this.src = url;
445
+ } else {
446
+ var i, media;
447
+
448
+ for (i=0; i<url.length; i++) {
449
+ media = url[i];
450
+ if (this.canPlayType(media.type)) {
451
+ this.src = media.src;
452
+ break;
453
+ }
454
+ }
455
+ }
456
+ },
457
+
458
+ setVideoSize: function (width, height) {
459
+ this.width = width;
460
+ this.height = height;
461
+ }
462
+ };
463
+
464
+ /*
465
+ Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
466
+ */
467
+ mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
468
+ this.id = pluginid;
469
+ this.pluginType = pluginType;
470
+ this.src = mediaUrl;
471
+ this.events = {};
472
+ this.attributes = {};
473
+ };
474
+
475
+ // JavaScript values and ExternalInterface methods that match HTML5 video properties methods
476
+ // http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
477
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
478
+ mejs.PluginMediaElement.prototype = {
479
+
480
+ // special
481
+ pluginElement: null,
482
+ pluginType: '',
483
+ isFullScreen: false,
484
+
485
+ // not implemented :(
486
+ playbackRate: -1,
487
+ defaultPlaybackRate: -1,
488
+ seekable: [],
489
+ played: [],
490
+
491
+ // HTML5 read-only properties
492
+ paused: true,
493
+ ended: false,
494
+ seeking: false,
495
+ duration: 0,
496
+ error: null,
497
+ tagName: '',
498
+
499
+ // HTML5 get/set properties, but only set (updated by event handlers)
500
+ muted: false,
501
+ volume: 1,
502
+ currentTime: 0,
503
+
504
+ // HTML5 methods
505
+ play: function () {
506
+ if (this.pluginApi != null) {
507
+ if (this.pluginType == 'youtube') {
508
+ this.pluginApi.playVideo();
509
+ } else {
510
+ this.pluginApi.playMedia();
511
+ }
512
+ this.paused = false;
513
+ }
514
+ },
515
+ load: function () {
516
+ if (this.pluginApi != null) {
517
+ if (this.pluginType == 'youtube') {
518
+ } else {
519
+ this.pluginApi.loadMedia();
520
+ }
521
+
522
+ this.paused = false;
523
+ }
524
+ },
525
+ pause: function () {
526
+ if (this.pluginApi != null) {
527
+ if (this.pluginType == 'youtube') {
528
+ this.pluginApi.pauseVideo();
529
+ } else {
530
+ this.pluginApi.pauseMedia();
531
+ }
532
+
533
+
534
+ this.paused = true;
535
+ }
536
+ },
537
+ stop: function () {
538
+ if (this.pluginApi != null) {
539
+ if (this.pluginType == 'youtube') {
540
+ this.pluginApi.stopVideo();
541
+ } else {
542
+ this.pluginApi.stopMedia();
543
+ }
544
+ this.paused = true;
545
+ }
546
+ },
547
+ canPlayType: function(type) {
548
+ var i,
549
+ j,
550
+ pluginInfo,
551
+ pluginVersions = mejs.plugins[this.pluginType];
552
+
553
+ for (i=0; i<pluginVersions.length; i++) {
554
+ pluginInfo = pluginVersions[i];
555
+
556
+ // test if user has the correct plugin version
557
+ if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
558
+
559
+ // test for plugin playback types
560
+ for (j=0; j<pluginInfo.types.length; j++) {
561
+ // find plugin that can play the type
562
+ if (type == pluginInfo.types[j]) {
563
+ return 'probably';
564
+ }
565
+ }
566
+ }
567
+ }
568
+
569
+ return '';
570
+ },
571
+
572
+ positionFullscreenButton: function(x,y,visibleAndAbove) {
573
+ if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) {
574
+ this.pluginApi.positionFullscreenButton(Math.floor(x),Math.floor(y),visibleAndAbove);
575
+ }
576
+ },
577
+
578
+ hideFullscreenButton: function() {
579
+ if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) {
580
+ this.pluginApi.hideFullscreenButton();
581
+ }
582
+ },
583
+
584
+
585
+ // custom methods since not all JavaScript implementations support get/set
586
+
587
+ // This can be a url string
588
+ // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
589
+ setSrc: function (url) {
590
+ if (typeof url == 'string') {
591
+ this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
592
+ this.src = mejs.Utility.absolutizeUrl(url);
593
+ } else {
594
+ var i, media;
595
+
596
+ for (i=0; i<url.length; i++) {
597
+ media = url[i];
598
+ if (this.canPlayType(media.type)) {
599
+ this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
600
+ this.src = mejs.Utility.absolutizeUrl(url);
601
+ break;
602
+ }
603
+ }
604
+ }
605
+
606
+ },
607
+ setCurrentTime: function (time) {
608
+ if (this.pluginApi != null) {
609
+ if (this.pluginType == 'youtube') {
610
+ this.pluginApi.seekTo(time);
611
+ } else {
612
+ this.pluginApi.setCurrentTime(time);
613
+ }
614
+
615
+
616
+
617
+ this.currentTime = time;
618
+ }
619
+ },
620
+ setVolume: function (volume) {
621
+ if (this.pluginApi != null) {
622
+ // same on YouTube and MEjs
623
+ if (this.pluginType == 'youtube') {
624
+ this.pluginApi.setVolume(volume * 100);
625
+ } else {
626
+ this.pluginApi.setVolume(volume);
627
+ }
628
+ this.volume = volume;
629
+ }
630
+ },
631
+ setMuted: function (muted) {
632
+ if (this.pluginApi != null) {
633
+ if (this.pluginType == 'youtube') {
634
+ if (muted) {
635
+ this.pluginApi.mute();
636
+ } else {
637
+ this.pluginApi.unMute();
638
+ }
639
+ this.muted = muted;
640
+ this.dispatchEvent('volumechange');
641
+ } else {
642
+ this.pluginApi.setMuted(muted);
643
+ }
644
+ this.muted = muted;
645
+ }
646
+ },
647
+
648
+ // additional non-HTML5 methods
649
+ setVideoSize: function (width, height) {
650
+
651
+ //if (this.pluginType == 'flash' || this.pluginType == 'silverlight') {
652
+ if ( this.pluginElement.style) {
653
+ this.pluginElement.style.width = width + 'px';
654
+ this.pluginElement.style.height = height + 'px';
655
+ }
656
+ if (this.pluginApi != null && this.pluginApi.setVideoSize) {
657
+ this.pluginApi.setVideoSize(width, height);
658
+ }
659
+ //}
660
+ },
661
+
662
+ setFullscreen: function (fullscreen) {
663
+ if (this.pluginApi != null && this.pluginApi.setFullscreen) {
664
+ this.pluginApi.setFullscreen(fullscreen);
665
+ }
666
+ },
667
+
668
+ enterFullScreen: function() {
669
+ if (this.pluginApi != null && this.pluginApi.setFullscreen) {
670
+ this.setFullscreen(true);
671
+ }
672
+
673
+ },
674
+
675
+ exitFullScreen: function() {
676
+ if (this.pluginApi != null && this.pluginApi.setFullscreen) {
677
+ this.setFullscreen(false);
678
+ }
679
+ },
680
+
681
+ // start: fake events
682
+ addEventListener: function (eventName, callback, bubble) {
683
+ this.events[eventName] = this.events[eventName] || [];
684
+ this.events[eventName].push(callback);
685
+ },
686
+ removeEventListener: function (eventName, callback) {
687
+ if (!eventName) { this.events = {}; return true; }
688
+ var callbacks = this.events[eventName];
689
+ if (!callbacks) return true;
690
+ if (!callback) { this.events[eventName] = []; return true; }
691
+ for (i = 0; i < callbacks.length; i++) {
692
+ if (callbacks[i] === callback) {
693
+ this.events[eventName].splice(i, 1);
694
+ return true;
695
+ }
696
+ }
697
+ return false;
698
+ },
699
+ dispatchEvent: function (eventName) {
700
+ var i,
701
+ args,
702
+ callbacks = this.events[eventName];
703
+
704
+ if (callbacks) {
705
+ args = Array.prototype.slice.call(arguments, 1);
706
+ for (i = 0; i < callbacks.length; i++) {
707
+ callbacks[i].apply(null, args);
708
+ }
709
+ }
710
+ },
711
+ // end: fake events
712
+
713
+ // fake DOM attribute methods
714
+ hasAttribute: function(name){
715
+ return (name in this.attributes);
716
+ },
717
+ removeAttribute: function(name){
718
+ delete this.attributes[name];
719
+ },
720
+ getAttribute: function(name){
721
+ if (this.hasAttribute(name)) {
722
+ return this.attributes[name];
723
+ }
724
+ return '';
725
+ },
726
+ setAttribute: function(name, value){
727
+ this.attributes[name] = value;
728
+ },
729
+
730
+ remove: function() {
731
+ mejs.Utility.removeSwf(this.pluginElement.id);
732
+ mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id);
733
+ }
734
+ };
735
+
736
+ // Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
737
+ mejs.MediaPluginBridge = {
738
+
739
+ pluginMediaElements:{},
740
+ htmlMediaElements:{},
741
+
742
+ registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
743
+ this.pluginMediaElements[id] = pluginMediaElement;
744
+ this.htmlMediaElements[id] = htmlMediaElement;
745
+ },
746
+
747
+ unregisterPluginElement: function (id) {
748
+ delete this.pluginMediaElements[id];
749
+ delete this.htmlMediaElements[id];
750
+ },
751
+
752
+ // when Flash/Silverlight is ready, it calls out to this method
753
+ initPlugin: function (id) {
754
+
755
+ var pluginMediaElement = this.pluginMediaElements[id],
756
+ htmlMediaElement = this.htmlMediaElements[id];
757
+
758
+ if (pluginMediaElement) {
759
+ // find the javascript bridge
760
+ switch (pluginMediaElement.pluginType) {
761
+ case "flash":
762
+ pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
763
+ break;
764
+ case "silverlight":
765
+ pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
766
+ pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
767
+ break;
768
+ }
769
+
770
+ if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
771
+ pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
772
+ }
773
+ }
774
+ },
775
+
776
+ // receives events from Flash/Silverlight and sends them out as HTML5 media events
777
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
778
+ fireEvent: function (id, eventName, values) {
779
+
780
+ var
781
+ e,
782
+ i,
783
+ bufferedTime,
784
+ pluginMediaElement = this.pluginMediaElements[id];
785
+
786
+ // fake event object to mimic real HTML media event.
787
+ e = {
788
+ type: eventName,
789
+ target: pluginMediaElement
790
+ };
791
+
792
+ // attach all values to element and event object
793
+ for (i in values) {
794
+ pluginMediaElement[i] = values[i];
795
+ e[i] = values[i];
796
+ }
797
+
798
+ // fake the newer W3C buffered TimeRange (loaded and total have been removed)
799
+ bufferedTime = values.bufferedTime || 0;
800
+
801
+ e.target.buffered = e.buffered = {
802
+ start: function(index) {
803
+ return 0;
804
+ },
805
+ end: function (index) {
806
+ return bufferedTime;
807
+ },
808
+ length: 1
809
+ };
810
+
811
+ pluginMediaElement.dispatchEvent(e.type, e);
812
+ }
813
+ };
814
+
815
+ /*
816
+ Default options
817
+ */
818
+ mejs.MediaElementDefaults = {
819
+ // allows testing on HTML5, flash, silverlight
820
+ // auto: attempts to detect what the browser can do
821
+ // auto_plugin: prefer plugins and then attempt native HTML5
822
+ // native: forces HTML5 playback
823
+ // shim: disallows HTML5, will attempt either Flash or Silverlight
824
+ // none: forces fallback view
825
+ mode: 'auto',
826
+ // remove or reorder to change plugin priority and availability
827
+ plugins: ['flash','silverlight','youtube','vimeo'],
828
+ // shows debug errors on screen
829
+ enablePluginDebug: false,
830
+ // overrides the type specified, useful for dynamic instantiation
831
+ type: '',
832
+ // path to Flash and Silverlight plugins
833
+ pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
834
+ // name of flash file
835
+ flashName: 'flashmediaelement.swf',
836
+ // streamer for RTMP streaming
837
+ flashStreamer: '',
838
+ // turns on the smoothing filter in Flash
839
+ enablePluginSmoothing: false,
840
+ // enabled pseudo-streaming (seek) on .mp4 files
841
+ enablePseudoStreaming: false,
842
+ // start query parameter sent to server for pseudo-streaming
843
+ pseudoStreamingStartQueryParam: 'start',
844
+ // name of silverlight file
845
+ silverlightName: 'silverlightmediaelement.xap',
846
+ // default if the <video width> is not specified
847
+ defaultVideoWidth: 480,
848
+ // default if the <video height> is not specified
849
+ defaultVideoHeight: 270,
850
+ // overrides <video width>
851
+ pluginWidth: -1,
852
+ // overrides <video height>
853
+ pluginHeight: -1,
854
+ // additional plugin variables in 'key=value' form
855
+ pluginVars: [],
856
+ // rate in milliseconds for Flash and Silverlight to fire the timeupdate event
857
+ // larger number is less accurate, but less strain on plugin->JavaScript bridge
858
+ timerRate: 250,
859
+ // initial volume for player
860
+ startVolume: 0.8,
861
+ success: function () { },
862
+ error: function () { }
863
+ };
864
+
865
+ /*
866
+ Determines if a browser supports the <video> or <audio> element
867
+ and returns either the native element or a Flash/Silverlight version that
868
+ mimics HTML5 MediaElement
869
+ */
870
+ mejs.MediaElement = function (el, o) {
871
+ return mejs.HtmlMediaElementShim.create(el,o);
872
+ };
873
+
874
+ mejs.HtmlMediaElementShim = {
875
+
876
+ create: function(el, o) {
877
+ var
878
+ options = mejs.MediaElementDefaults,
879
+ htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
880
+ tagName = htmlMediaElement.tagName.toLowerCase(),
881
+ isMediaTag = (tagName === 'audio' || tagName === 'video'),
882
+ src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'),
883
+ poster = htmlMediaElement.getAttribute('poster'),
884
+ autoplay = htmlMediaElement.getAttribute('autoplay'),
885
+ preload = htmlMediaElement.getAttribute('preload'),
886
+ controls = htmlMediaElement.getAttribute('controls'),
887
+ playback,
888
+ prop;
889
+
890
+ // extend options
891
+ for (prop in o) {
892
+ options[prop] = o[prop];
893
+ }
894
+
895
+ // clean up attributes
896
+ src = (typeof src == 'undefined' || src === null || src == '') ? null : src;
897
+ poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
898
+ preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
899
+ autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
900
+ controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
901
+
902
+ // test for HTML5 and plugin capabilities
903
+ playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src);
904
+ playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '';
905
+
906
+ if (playback.method == 'native') {
907
+ // second fix for android
908
+ if (mejs.MediaFeatures.isBustedAndroid) {
909
+ htmlMediaElement.src = playback.url;
910
+ htmlMediaElement.addEventListener('click', function() {
911
+ htmlMediaElement.play();
912
+ }, false);
913
+ }
914
+
915
+ // add methods to native HTMLMediaElement
916
+ return this.updateNative(playback, options, autoplay, preload);
917
+ } else if (playback.method !== '') {
918
+ // create plugin to mimic HTMLMediaElement
919
+
920
+ return this.createPlugin( playback, options, poster, autoplay, preload, controls);
921
+ } else {
922
+ // boo, no HTML5, no Flash, no Silverlight.
923
+ this.createErrorMessage( playback, options, poster );
924
+
925
+ return this;
926
+ }
927
+ },
928
+
929
+ determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) {
930
+ var
931
+ mediaFiles = [],
932
+ i,
933
+ j,
934
+ k,
935
+ l,
936
+ n,
937
+ type,
938
+ result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')},
939
+ pluginName,
940
+ pluginVersions,
941
+ pluginInfo,
942
+ dummy,
943
+ media;
944
+
945
+ // STEP 1: Get URL and type from <video src> or <source src>
946
+
947
+ // supplied type overrides <video type> and <source type>
948
+ if (typeof options.type != 'undefined' && options.type !== '') {
949
+
950
+ // accept either string or array of types
951
+ if (typeof options.type == 'string') {
952
+ mediaFiles.push({type:options.type, url:src});
953
+ } else {
954
+
955
+ for (i=0; i<options.type.length; i++) {
956
+ mediaFiles.push({type:options.type[i], url:src});
957
+ }
958
+ }
959
+
960
+ // test for src attribute first
961
+ } else if (src !== null) {
962
+ type = this.formatType(src, htmlMediaElement.getAttribute('type'));
963
+ mediaFiles.push({type:type, url:src});
964
+
965
+ // then test for <source> elements
966
+ } else {
967
+ // test <source> types to see if they are usable
968
+ for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
969
+ n = htmlMediaElement.childNodes[i];
970
+ if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
971
+ src = n.getAttribute('src');
972
+ type = this.formatType(src, n.getAttribute('type'));
973
+ media = n.getAttribute('media');
974
+
975
+ if (!media || !window.matchMedia || (window.matchMedia && window.matchMedia(media).matches)) {
976
+ mediaFiles.push({type:type, url:src});
977
+ }
978
+ }
979
+ }
980
+ }
981
+
982
+ // in the case of dynamicly created players
983
+ // check for audio types
984
+ if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) {
985
+ result.isVideo = false;
986
+ }
987
+
988
+
989
+ // STEP 2: Test for playback method
990
+
991
+ // special case for Android which sadly doesn't implement the canPlayType function (always returns '')
992
+ if (mejs.MediaFeatures.isBustedAndroid) {
993
+ htmlMediaElement.canPlayType = function(type) {
994
+ return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
995
+ };
996
+ }
997
+
998
+
999
+ // test for native playback first
1000
+ if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native') && !(mejs.MediaFeatures.isBustedNativeHTTPS)) {
1001
+
1002
+ if (!isMediaTag) {
1003
+
1004
+ // create a real HTML5 Media Element
1005
+ dummy = document.createElement( result.isVideo ? 'video' : 'audio');
1006
+ htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement);
1007
+ htmlMediaElement.style.display = 'none';
1008
+
1009
+ // use this one from now on
1010
+ result.htmlMediaElement = htmlMediaElement = dummy;
1011
+ }
1012
+
1013
+ for (i=0; i<mediaFiles.length; i++) {
1014
+ // normal check
1015
+ if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
1016
+ // special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
1017
+ || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
1018
+ result.method = 'native';
1019
+ result.url = mediaFiles[i].url;
1020
+ break;
1021
+ }
1022
+ }
1023
+
1024
+ if (result.method === 'native') {
1025
+ if (result.url !== null) {
1026
+ htmlMediaElement.src = result.url;
1027
+ }
1028
+
1029
+ // if `auto_plugin` mode, then cache the native result but try plugins.
1030
+ if (options.mode !== 'auto_plugin') {
1031
+ return result;
1032
+ }
1033
+ }
1034
+ }
1035
+
1036
+ // if native playback didn't work, then test plugins
1037
+ if (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'shim') {
1038
+ for (i=0; i<mediaFiles.length; i++) {
1039
+ type = mediaFiles[i].type;
1040
+
1041
+ // test all plugins in order of preference [silverlight, flash]
1042
+ for (j=0; j<options.plugins.length; j++) {
1043
+
1044
+ pluginName = options.plugins[j];
1045
+
1046
+ // test version of plugin (for future features)
1047
+ pluginVersions = mejs.plugins[pluginName];
1048
+
1049
+ for (k=0; k<pluginVersions.length; k++) {
1050
+ pluginInfo = pluginVersions[k];
1051
+
1052
+ // test if user has the correct plugin version
1053
+
1054
+ // for youtube/vimeo
1055
+ if (pluginInfo.version == null ||
1056
+
1057
+ mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
1058
+
1059
+ // test for plugin playback types
1060
+ for (l=0; l<pluginInfo.types.length; l++) {
1061
+ // find plugin that can play the type
1062
+ if (type == pluginInfo.types[l]) {
1063
+ result.method = pluginName;
1064
+ result.url = mediaFiles[i].url;
1065
+ return result;
1066
+ }
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+ }
1072
+ }
1073
+
1074
+ // at this point, being in 'auto_plugin' mode implies that we tried plugins but failed.
1075
+ // if we have native support then return that.
1076
+ if (options.mode === 'auto_plugin' && result.method === 'native') {
1077
+ return result;
1078
+ }
1079
+
1080
+ // what if there's nothing to play? just grab the first available
1081
+ if (result.method === '' && mediaFiles.length > 0) {
1082
+ result.url = mediaFiles[0].url;
1083
+ }
1084
+
1085
+ return result;
1086
+ },
1087
+
1088
+ formatType: function(url, type) {
1089
+ var ext;
1090
+
1091
+ // if no type is supplied, fake it with the extension
1092
+ if (url && !type) {
1093
+ return this.getTypeFromFile(url);
1094
+ } else {
1095
+ // only return the mime part of the type in case the attribute contains the codec
1096
+ // see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
1097
+ // `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
1098
+
1099
+ if (type && ~type.indexOf(';')) {
1100
+ return type.substr(0, type.indexOf(';'));
1101
+ } else {
1102
+ return type;
1103
+ }
1104
+ }
1105
+ },
1106
+
1107
+ getTypeFromFile: function(url) {
1108
+ url = url.split('?')[0];
1109
+ var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
1110
+ return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext);
1111
+ },
1112
+
1113
+ getTypeFromExtension: function(ext) {
1114
+
1115
+ switch (ext) {
1116
+ case 'mp4':
1117
+ case 'm4v':
1118
+ return 'mp4';
1119
+ case 'webm':
1120
+ case 'webma':
1121
+ case 'webmv':
1122
+ return 'webm';
1123
+ case 'ogg':
1124
+ case 'oga':
1125
+ case 'ogv':
1126
+ return 'ogg';
1127
+ default:
1128
+ return ext;
1129
+ }
1130
+ },
1131
+
1132
+ createErrorMessage: function(playback, options, poster) {
1133
+ var
1134
+ htmlMediaElement = playback.htmlMediaElement,
1135
+ errorContainer = document.createElement('div');
1136
+
1137
+ errorContainer.className = 'me-cannotplay';
1138
+
1139
+ try {
1140
+ errorContainer.style.width = htmlMediaElement.width + 'px';
1141
+ errorContainer.style.height = htmlMediaElement.height + 'px';
1142
+ } catch (e) {}
1143
+
1144
+ if (options.customError) {
1145
+ errorContainer.innerHTML = options.customError;
1146
+ } else {
1147
+ errorContainer.innerHTML = (poster !== '') ?
1148
+ '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
1149
+ '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>';
1150
+ }
1151
+
1152
+ htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
1153
+ htmlMediaElement.style.display = 'none';
1154
+
1155
+ options.error(htmlMediaElement);
1156
+ },
1157
+
1158
+ createPlugin:function(playback, options, poster, autoplay, preload, controls) {
1159
+ var
1160
+ htmlMediaElement = playback.htmlMediaElement,
1161
+ width = 1,
1162
+ height = 1,
1163
+ pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++),
1164
+ pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url),
1165
+ container = document.createElement('div'),
1166
+ specialIEContainer,
1167
+ node,
1168
+ initVars;
1169
+
1170
+ // copy tagName from html media element
1171
+ pluginMediaElement.tagName = htmlMediaElement.tagName
1172
+
1173
+ // copy attributes from html media element to plugin media element
1174
+ for (var i = 0; i < htmlMediaElement.attributes.length; i++) {
1175
+ var attribute = htmlMediaElement.attributes[i];
1176
+ if (attribute.specified == true) {
1177
+ pluginMediaElement.setAttribute(attribute.name, attribute.value);
1178
+ }
1179
+ }
1180
+
1181
+ // check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
1182
+ node = htmlMediaElement.parentNode;
1183
+ while (node !== null && node.tagName.toLowerCase() != 'body') {
1184
+ if (node.parentNode.tagName.toLowerCase() == 'p') {
1185
+ node.parentNode.parentNode.insertBefore(node, node.parentNode);
1186
+ break;
1187
+ }
1188
+ node = node.parentNode;
1189
+ }
1190
+
1191
+ if (playback.isVideo) {
1192
+ width = (options.pluginWidth > 0) ? options.pluginWidth : (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
1193
+ height = (options.pluginHeight > 0) ? options.pluginHeight : (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
1194
+
1195
+ // in case of '%' make sure it's encoded
1196
+ width = mejs.Utility.encodeUrl(width);
1197
+ height = mejs.Utility.encodeUrl(height);
1198
+
1199
+ } else {
1200
+ if (options.enablePluginDebug) {
1201
+ width = 320;
1202
+ height = 240;
1203
+ }
1204
+ }
1205
+
1206
+ // register plugin
1207
+ pluginMediaElement.success = options.success;
1208
+ mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
1209
+
1210
+ // add container (must be added to DOM before inserting HTML for IE)
1211
+ container.className = 'me-plugin';
1212
+ container.id = pluginid + '_container';
1213
+
1214
+ if (playback.isVideo) {
1215
+ htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
1216
+ } else {
1217
+ document.body.insertBefore(container, document.body.childNodes[0]);
1218
+ }
1219
+
1220
+ // flash/silverlight vars
1221
+ initVars = [
1222
+ 'id=' + pluginid,
1223
+ 'isvideo=' + ((playback.isVideo) ? "true" : "false"),
1224
+ 'autoplay=' + ((autoplay) ? "true" : "false"),
1225
+ 'preload=' + preload,
1226
+ 'width=' + width,
1227
+ 'startvolume=' + options.startVolume,
1228
+ 'timerrate=' + options.timerRate,
1229
+ 'flashstreamer=' + options.flashStreamer,
1230
+ 'height=' + height,
1231
+ 'pseudostreamstart=' + options.pseudoStreamingStartQueryParam];
1232
+
1233
+ if (playback.url !== null) {
1234
+ if (playback.method == 'flash') {
1235
+ initVars.push('file=' + mejs.Utility.encodeUrl(playback.url));
1236
+ } else {
1237
+ initVars.push('file=' + playback.url);
1238
+ }
1239
+ }
1240
+ if (options.enablePluginDebug) {
1241
+ initVars.push('debug=true');
1242
+ }
1243
+ if (options.enablePluginSmoothing) {
1244
+ initVars.push('smoothing=true');
1245
+ }
1246
+ if (options.enablePseudoStreaming) {
1247
+ initVars.push('pseudostreaming=true');
1248
+ }
1249
+ if (controls) {
1250
+ initVars.push('controls=true'); // shows controls in the plugin if desired
1251
+ }
1252
+ if (options.pluginVars) {
1253
+ initVars = initVars.concat(options.pluginVars);
1254
+ }
1255
+
1256
+ switch (playback.method) {
1257
+ case 'silverlight':
1258
+ container.innerHTML =
1259
+ '<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
1260
+ '<param name="initParams" value="' + initVars.join(',') + '" />' +
1261
+ '<param name="windowless" value="true" />' +
1262
+ '<param name="background" value="black" />' +
1263
+ '<param name="minRuntimeVersion" value="3.0.0.0" />' +
1264
+ '<param name="autoUpgrade" value="true" />' +
1265
+ '<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
1266
+ '</object>';
1267
+ break;
1268
+
1269
+ case 'flash':
1270
+
1271
+ if (mejs.MediaFeatures.isIE) {
1272
+ specialIEContainer = document.createElement('div');
1273
+ container.appendChild(specialIEContainer);
1274
+ specialIEContainer.outerHTML =
1275
+ '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
1276
+ 'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' +
1277
+ '<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
1278
+ '<param name="flashvars" value="' + initVars.join('&amp;') + '" />' +
1279
+ '<param name="quality" value="high" />' +
1280
+ '<param name="bgcolor" value="#000000" />' +
1281
+ '<param name="wmode" value="transparent" />' +
1282
+ '<param name="allowScriptAccess" value="always" />' +
1283
+ '<param name="allowFullScreen" value="true" />' +
1284
+ '</object>';
1285
+
1286
+ } else {
1287
+
1288
+ container.innerHTML =
1289
+ '<embed id="' + pluginid + '" name="' + pluginid + '" ' +
1290
+ 'play="true" ' +
1291
+ 'loop="false" ' +
1292
+ 'quality="high" ' +
1293
+ 'bgcolor="#000000" ' +
1294
+ 'wmode="transparent" ' +
1295
+ 'allowScriptAccess="always" ' +
1296
+ 'allowFullScreen="true" ' +
1297
+ 'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' +
1298
+ 'src="' + options.pluginPath + options.flashName + '" ' +
1299
+ 'flashvars="' + initVars.join('&') + '" ' +
1300
+ 'width="' + width + '" ' +
1301
+ 'height="' + height + '" ' +
1302
+ 'class="mejs-shim"></embed>';
1303
+ }
1304
+ break;
1305
+
1306
+ case 'youtube':
1307
+
1308
+
1309
+ var
1310
+ videoId = playback.url.substr(playback.url.lastIndexOf('=')+1);
1311
+ youtubeSettings = {
1312
+ container: container,
1313
+ containerId: container.id,
1314
+ pluginMediaElement: pluginMediaElement,
1315
+ pluginId: pluginid,
1316
+ videoId: videoId,
1317
+ height: height,
1318
+ width: width
1319
+ };
1320
+
1321
+ if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) {
1322
+ mejs.YouTubeApi.createFlash(youtubeSettings);
1323
+ } else {
1324
+ mejs.YouTubeApi.enqueueIframe(youtubeSettings);
1325
+ }
1326
+
1327
+ break;
1328
+
1329
+ // DEMO Code. Does NOT work.
1330
+ case 'vimeo':
1331
+ //console.log('vimeoid');
1332
+
1333
+ pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
1334
+
1335
+ 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>';
1336
+
1337
+ /*
1338
+ container.innerHTML =
1339
+ '<object width="' + width + '" height="' + height + '" class="mejs-shim">' +
1340
+ '<param name="allowfullscreen" value="true" />' +
1341
+ '<param name="allowscriptaccess" value="always" />' +
1342
+ '<param name="flashvars" value="api=1" />' +
1343
+ '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" />' +
1344
+ '<embed src="//vimeo.com/moogaloop.swf?api=1&amp;clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '" class="mejs-shim"></embed>' +
1345
+ '</object>';
1346
+ */
1347
+
1348
+ break;
1349
+ }
1350
+ // hide original element
1351
+ htmlMediaElement.style.display = 'none';
1352
+
1353
+ // FYI: options.success will be fired by the MediaPluginBridge
1354
+
1355
+ return pluginMediaElement;
1356
+ },
1357
+
1358
+ updateNative: function(playback, options, autoplay, preload) {
1359
+
1360
+ var htmlMediaElement = playback.htmlMediaElement,
1361
+ m;
1362
+
1363
+
1364
+ // add methods to video object to bring it into parity with Flash Object
1365
+ for (m in mejs.HtmlMediaElement) {
1366
+ htmlMediaElement[m] = mejs.HtmlMediaElement[m];
1367
+ }
1368
+
1369
+ /*
1370
+ Chrome now supports preload="none"
1371
+ if (mejs.MediaFeatures.isChrome) {
1372
+
1373
+ // special case to enforce preload attribute (Chrome doesn't respect this)
1374
+ if (preload === 'none' && !autoplay) {
1375
+
1376
+ // forces the browser to stop loading (note: fails in IE9)
1377
+ htmlMediaElement.src = '';
1378
+ htmlMediaElement.load();
1379
+ htmlMediaElement.canceledPreload = true;
1380
+
1381
+ htmlMediaElement.addEventListener('play',function() {
1382
+ if (htmlMediaElement.canceledPreload) {
1383
+ htmlMediaElement.src = playback.url;
1384
+ htmlMediaElement.load();
1385
+ htmlMediaElement.play();
1386
+ htmlMediaElement.canceledPreload = false;
1387
+ }
1388
+ }, false);
1389
+ // for some reason Chrome forgets how to autoplay sometimes.
1390
+ } else if (autoplay) {
1391
+ htmlMediaElement.load();
1392
+ htmlMediaElement.play();
1393
+ }
1394
+ }
1395
+ */
1396
+
1397
+ // fire success code
1398
+ options.success(htmlMediaElement, htmlMediaElement);
1399
+
1400
+ return htmlMediaElement;
1401
+ }
1402
+ };
1403
+
1404
+ /*
1405
+ - test on IE (object vs. embed)
1406
+ - determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE)
1407
+ - fullscreen?
1408
+ */
1409
+
1410
+ // YouTube Flash and Iframe API
1411
+ mejs.YouTubeApi = {
1412
+ isIframeStarted: false,
1413
+ isIframeLoaded: false,
1414
+ loadIframeApi: function() {
1415
+ if (!this.isIframeStarted) {
1416
+ var tag = document.createElement('script');
1417
+ tag.src = "//www.youtube.com/player_api";
1418
+ var firstScriptTag = document.getElementsByTagName('script')[0];
1419
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
1420
+ this.isIframeStarted = true;
1421
+ }
1422
+ },
1423
+ iframeQueue: [],
1424
+ enqueueIframe: function(yt) {
1425
+
1426
+ if (this.isLoaded) {
1427
+ this.createIframe(yt);
1428
+ } else {
1429
+ this.loadIframeApi();
1430
+ this.iframeQueue.push(yt);
1431
+ }
1432
+ },
1433
+ createIframe: function(settings) {
1434
+
1435
+ var
1436
+ pluginMediaElement = settings.pluginMediaElement,
1437
+ player = new YT.Player(settings.containerId, {
1438
+ height: settings.height,
1439
+ width: settings.width,
1440
+ videoId: settings.videoId,
1441
+ playerVars: {controls:0},
1442
+ events: {
1443
+ 'onReady': function() {
1444
+
1445
+ // hook up iframe object to MEjs
1446
+ settings.pluginMediaElement.pluginApi = player;
1447
+
1448
+ // init mejs
1449
+ mejs.MediaPluginBridge.initPlugin(settings.pluginId);
1450
+
1451
+ // create timer
1452
+ setInterval(function() {
1453
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
1454
+ }, 250);
1455
+ },
1456
+ 'onStateChange': function(e) {
1457
+
1458
+ mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement);
1459
+
1460
+ }
1461
+ }
1462
+ });
1463
+ },
1464
+
1465
+ createEvent: function (player, pluginMediaElement, eventName) {
1466
+ var obj = {
1467
+ type: eventName,
1468
+ target: pluginMediaElement
1469
+ };
1470
+
1471
+ if (player && player.getDuration) {
1472
+
1473
+ // time
1474
+ pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime();
1475
+ pluginMediaElement.duration = obj.duration = player.getDuration();
1476
+
1477
+ // state
1478
+ obj.paused = pluginMediaElement.paused;
1479
+ obj.ended = pluginMediaElement.ended;
1480
+
1481
+ // sound
1482
+ obj.muted = player.isMuted();
1483
+ obj.volume = player.getVolume() / 100;
1484
+
1485
+ // progress
1486
+ obj.bytesTotal = player.getVideoBytesTotal();
1487
+ obj.bufferedBytes = player.getVideoBytesLoaded();
1488
+
1489
+ // fake the W3C buffered TimeRange
1490
+ var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration;
1491
+
1492
+ obj.target.buffered = obj.buffered = {
1493
+ start: function(index) {
1494
+ return 0;
1495
+ },
1496
+ end: function (index) {
1497
+ return bufferedTime;
1498
+ },
1499
+ length: 1
1500
+ };
1501
+
1502
+ }
1503
+
1504
+ // send event up the chain
1505
+ pluginMediaElement.dispatchEvent(obj.type, obj);
1506
+ },
1507
+
1508
+ iFrameReady: function() {
1509
+
1510
+ this.isLoaded = true;
1511
+ this.isIframeLoaded = true;
1512
+
1513
+ while (this.iframeQueue.length > 0) {
1514
+ var settings = this.iframeQueue.pop();
1515
+ this.createIframe(settings);
1516
+ }
1517
+ },
1518
+
1519
+ // FLASH!
1520
+ flashPlayers: {},
1521
+ createFlash: function(settings) {
1522
+
1523
+ this.flashPlayers[settings.pluginId] = settings;
1524
+
1525
+ /*
1526
+ settings.container.innerHTML =
1527
+ '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' +
1528
+ 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
1529
+ '<param name="allowScriptAccess" value="always">' +
1530
+ '<param name="wmode" value="transparent">' +
1531
+ '</object>';
1532
+ */
1533
+
1534
+ var specialIEContainer,
1535
+ youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0';
1536
+
1537
+ if (mejs.MediaFeatures.isIE) {
1538
+
1539
+ specialIEContainer = document.createElement('div');
1540
+ settings.container.appendChild(specialIEContainer);
1541
+ specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
1542
+ 'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' +
1543
+ '<param name="movie" value="' + youtubeUrl + '" />' +
1544
+ '<param name="wmode" value="transparent" />' +
1545
+ '<param name="allowScriptAccess" value="always" />' +
1546
+ '<param name="allowFullScreen" value="true" />' +
1547
+ '</object>';
1548
+ } else {
1549
+ settings.container.innerHTML =
1550
+ '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' +
1551
+ 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' +
1552
+ '<param name="allowScriptAccess" value="always">' +
1553
+ '<param name="wmode" value="transparent">' +
1554
+ '</object>';
1555
+ }
1556
+
1557
+ },
1558
+
1559
+ flashReady: function(id) {
1560
+ var
1561
+ settings = this.flashPlayers[id],
1562
+ player = document.getElementById(id),
1563
+ pluginMediaElement = settings.pluginMediaElement;
1564
+
1565
+ // hook up and return to MediaELementPlayer.success
1566
+ pluginMediaElement.pluginApi =
1567
+ pluginMediaElement.pluginElement = player;
1568
+ mejs.MediaPluginBridge.initPlugin(id);
1569
+
1570
+ // load the youtube video
1571
+ player.cueVideoById(settings.videoId);
1572
+
1573
+ var callbackName = settings.containerId + '_callback';
1574
+
1575
+ window[callbackName] = function(e) {
1576
+ mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
1577
+ }
1578
+
1579
+ player.addEventListener('onStateChange', callbackName);
1580
+
1581
+ setInterval(function() {
1582
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate');
1583
+ }, 250);
1584
+ },
1585
+
1586
+ handleStateChange: function(youTubeState, player, pluginMediaElement) {
1587
+ switch (youTubeState) {
1588
+ case -1: // not started
1589
+ pluginMediaElement.paused = true;
1590
+ pluginMediaElement.ended = true;
1591
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata');
1592
+ //createYouTubeEvent(player, pluginMediaElement, 'loadeddata');
1593
+ break;
1594
+ case 0:
1595
+ pluginMediaElement.paused = false;
1596
+ pluginMediaElement.ended = true;
1597
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended');
1598
+ break;
1599
+ case 1:
1600
+ pluginMediaElement.paused = false;
1601
+ pluginMediaElement.ended = false;
1602
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play');
1603
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing');
1604
+ break;
1605
+ case 2:
1606
+ pluginMediaElement.paused = true;
1607
+ pluginMediaElement.ended = false;
1608
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause');
1609
+ break;
1610
+ case 3: // buffering
1611
+ mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress');
1612
+ break;
1613
+ case 5:
1614
+ // cued?
1615
+ break;
1616
+
1617
+ }
1618
+
1619
+ }
1620
+ }
1621
+ // IFRAME
1622
+ function onYouTubePlayerAPIReady() {
1623
+ mejs.YouTubeApi.iFrameReady();
1624
+ }
1625
+ // FLASH
1626
+ function onYouTubePlayerReady(id) {
1627
+ mejs.YouTubeApi.flashReady(id);
1628
+ }
1629
+
1630
+ window.mejs = mejs;
1631
+ window.MediaElement = mejs.MediaElement;
1632
+
1633
+ /*!
1634
+ * Adds Internationalization and localization to objects.
1635
+ *
1636
+ * What is the concept beyond i18n?
1637
+ * http://en.wikipedia.org/wiki/Internationalization_and_localization
1638
+ *
1639
+ *
1640
+ * This file both i18n methods and locale which is used to translate
1641
+ * strings into other languages.
1642
+ *
1643
+ * Default translations are not available, you have to add them
1644
+ * through locale objects which are named exactly as the langcode
1645
+ * they stand for. The default language is always english (en).
1646
+ *
1647
+ *
1648
+ * Wrapper built to be able to attach the i18n object to
1649
+ * other objects without changing more than one line.
1650
+ *
1651
+ *
1652
+ * LICENSE:
1653
+ *
1654
+ * The i18n file uses methods from the Drupal project (drupal.js):
1655
+ * - i18n.methods.t() (modified)
1656
+ * - i18n.methods.checkPlain() (full copy)
1657
+ * - i18n.methods.formatString() (full copy)
1658
+ *
1659
+ * The Drupal project is (like mediaelementjs) licensed under GPLv2.
1660
+ * - http://drupal.org/licensing/faq/#q1
1661
+ * - https://github.com/johndyer/mediaelement
1662
+ * - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
1663
+ *
1664
+ *
1665
+ * @author
1666
+ * Tim Latz (latz.tim@gmail.com)
1667
+ *
1668
+ * @see
1669
+ * me-i18n-locale.js
1670
+ *
1671
+ * @params
1672
+ * - context - document, iframe ..
1673
+ * - exports - CommonJS, window ..
1674
+ *
1675
+ */
1676
+ ;(function(context, exports, undefined) {
1677
+ "use strict";
1678
+ var i18n = {
1679
+ "locale": {
1680
+ "strings" : {}
1681
+ },
1682
+ "methods" : {}
1683
+ };
1684
+ // start i18n
1685
+
1686
+
1687
+ /**
1688
+ * Get the current browser's language
1689
+ *
1690
+ * @see: i18n.methods.t()
1691
+ */
1692
+ i18n.locale.getLanguage = function () {
1693
+ return i18n.locale || {
1694
+ "language" : navigator.language
1695
+ };
1696
+ };
1697
+
1698
+ /**
1699
+ * Store the language the locale object was initialized with
1700
+ */
1701
+ i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage();
1702
+
1703
+
1704
+ /**
1705
+ * Encode special characters in a plain-text string for display as HTML.
1706
+ */
1707
+ i18n.methods.checkPlain = function (str) {
1708
+ var character, regex,
1709
+ replace = {
1710
+ '&': '&amp;',
1711
+ '"': '&quot;',
1712
+ '<': '&lt;',
1713
+ '>': '&gt;'
1714
+ };
1715
+ str = String(str);
1716
+ for (character in replace) {
1717
+ if (replace.hasOwnProperty(character)) {
1718
+ regex = new RegExp(character, 'g');
1719
+ str = str.replace(regex, replace[character]);
1720
+ }
1721
+ }
1722
+ return str;
1723
+ };
1724
+
1725
+ /**
1726
+ * Replace placeholders with sanitized values in a string.
1727
+ *
1728
+ * @param str
1729
+ * A string with placeholders.
1730
+ * @param args
1731
+ * An object of replacements pairs to make. Incidences of any key in this
1732
+ * array are replaced with the corresponding value. Based on the first
1733
+ * character of the key, the value is escaped and/or themed:
1734
+ * - !variable: inserted as is
1735
+ * - @variable: escape plain text to HTML (i18n.methods.checkPlain)
1736
+ * - %variable: escape text and theme as a placeholder for user-submitted
1737
+ * content (checkPlain + <em class="placeholder" > )
1738
+ *
1739
+ * @see i18n.methods.t()
1740
+ */
1741
+ i18n.methods.formatString = function(str, args) {
1742
+ // Transform arguments before inserting them.
1743
+ for (var key in args) {
1744
+ switch (key.charAt(0)) {
1745
+ // Escaped only.
1746
+ case '@':
1747
+ args[key] = i18n.methods.checkPlain(args[key]);
1748
+ break;
1749
+ // Pass-through.
1750
+ case '!':
1751
+ break;
1752
+ // Escaped and placeholder.
1753
+ case '%':
1754
+ default:
1755
+ args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>';
1756
+ break;
1757
+ }
1758
+ str = str.replace(key, args[key]);
1759
+ }
1760
+ return str;
1761
+ };
1762
+
1763
+ /**
1764
+ * Translate strings to the page language or a given language.
1765
+ *
1766
+ * See the documentation of the server-side t() function for further details.
1767
+ *
1768
+ * @param str
1769
+ * A string containing the English string to translate.
1770
+ * @param args
1771
+ * An object of replacements pairs to make after translation. Incidences
1772
+ * of any key in this array are replaced with the corresponding value.
1773
+ * See i18n.methods.formatString().
1774
+ *
1775
+ * @param options
1776
+ * - 'context' (defaults to the default context): The context the source string
1777
+ * belongs to.
1778
+ *
1779
+ * @return
1780
+ * The translated string.
1781
+ */
1782
+ i18n.methods.t = function (str, args, options) {
1783
+
1784
+ // Fetch the localized version of the string.
1785
+ if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) {
1786
+ str = i18n.locale.strings[options.context][str];
1787
+ }
1788
+
1789
+ if (args) {
1790
+ str = i18n.methods.formatString(str, args);
1791
+ }
1792
+ return str;
1793
+ };
1794
+
1795
+
1796
+ /**
1797
+ * Wrapper for i18n.methods.t()
1798
+ *
1799
+ * @see i18n.methods.t()
1800
+ * @throws InvalidArgumentException
1801
+ */
1802
+ i18n.t = function(str, args, options) {
1803
+
1804
+ if (typeof str === 'string' && str.length > 0) {
1805
+
1806
+ // check every time due languge can change for
1807
+ // different reasons (translation, lang switcher ..)
1808
+ var lang = i18n.locale.getLanguage();
1809
+
1810
+ options = options || {
1811
+ "context" : lang.language
1812
+ };
1813
+
1814
+ return i18n.methods.t(str, args, options);
1815
+ }
1816
+ else {
1817
+ throw {
1818
+ "name" : 'InvalidArgumentException',
1819
+ "message" : 'First argument is either not a string or empty.'
1820
+ }
1821
+ }
1822
+ };
1823
+
1824
+ // end i18n
1825
+ exports.i18n = i18n;
1826
+ }(document, mejs));
1827
+
1828
+ ;(function(exports, undefined) {
1829
+
1830
+ "use strict";
1831
+
1832
+ if ( mejs.i18n.locale.language && mejs.i18n.locale.strings ) {
1833
+ exports[mejs.i18n.locale.language] = mejs.i18n.locale.strings;
1834
+ }
1835
+
1836
+ }(mejs.i18n.locale.strings));
1837
+
1838
+ /*!
1839
+ * This is a i18n.locale language object.
1840
+ *
1841
+ *<de> German translation by Tim Latz, latz.tim@gmail.com
1842
+ *
1843
+ * @author
1844
+ * Tim Latz (latz.tim@gmail.com)
1845
+ *
1846
+ * @see
1847
+ * me-i18n.js
1848
+ *
1849
+ * @params
1850
+ * - exports - CommonJS, window ..
1851
+ */
1852
+ ;(function(exports, undefined) {
1853
+
1854
+ "use strict";
1855
+
1856
+ exports.de = {
1857
+ "Fullscreen" : "Vollbild",
1858
+ "Go Fullscreen" : "Vollbild an",
1859
+ "Turn off Fullscreen" : "Vollbild aus",
1860
+ "Close" : "Schließen"
1861
+ };
1862
+
1863
+ }(mejs.i18n.locale.strings));
1864
+ /*!
1865
+ * This is a i18n.locale language object.
1866
+ *
1867
+ *<de> Traditional chinese translation by Tim Latz, latz.tim@gmail.com
1868
+ *
1869
+ * @author
1870
+ * Tim Latz (latz.tim@gmail.com)
1871
+ *
1872
+ * @see
1873
+ * me-i18n.js
1874
+ *
1875
+ * @params
1876
+ * - exports - CommonJS, window ..
1877
+ */
1878
+ ;(function(exports, undefined) {
1879
+
1880
+ "use strict";
1881
+
1882
+ exports.zh = {
1883
+ "Fullscreen" : "全螢幕",
1884
+ "Go Fullscreen" : "全屏模式",
1885
+ "Turn off Fullscreen" : "退出全屏模式",
1886
+ "Close" : "關閉"
1887
+ };
1888
+
1889
+ }(mejs.i18n.locale.strings));
1890
+