mediaelement_rails 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MediaelementRails #
2
2
 
3
- This neat project brings the cool [MediaElement.js](http://mediaelementjs.com/) (HTML5/Flash/Silverlight video player) to the Rails asset pipeline.
3
+ This neat project brings the cool [MediaElement.js](http://mediaelementjs.com/) (HTML5/Flash/Silverlight video player) to the Rails asset pipeline. __*NOTE:*__ This gem requires jquery, which shouldn't be an issue.
4
4
 
5
5
  ## All you have to do is: ##
6
6
 
@@ -0,0 +1 @@
1
+ <?xml version="1.0" standalone="no"?>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" standalone="no"?>
@@ -1,3 +1,2 @@
1
- //= require jquery
2
1
  //= require ./rails
3
2
  //= require ./mediaelementplayer
@@ -8,150 +8,173 @@
8
8
  * Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
9
9
  *
10
10
  * Copyright 2010-2012, John Dyer (http://j.hn)
11
- * Dual licensed under the MIT or GPL Version 2 licenses.
11
+ * License: MIT
12
12
  *
13
13
  */
14
- // Namespace
15
- var mejs = mejs || {};
16
-
17
- // version number
18
- mejs.version = '2.9.1';
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/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']}
34
- ],
35
- vimeo: [
36
- {version: null, types: ['video/vimeo']}
37
- ]
14
+ // Namespace
15
+ var mejs = mejs || {};
16
+
17
+ // version number
18
+ mejs.version = '2.10.3';
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']}
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
+ path = '',
60
+ name = '',
61
+ script,
62
+ scripts = document.getElementsByTagName('script'),
63
+ il = scripts.length,
64
+ jl = scriptNames.length;
65
+
66
+ for (; i < il; i++) {
67
+ script = scripts[i].src;
68
+ for (j = 0; j < jl; j++) {
69
+ name = scriptNames[j];
70
+ if (script.indexOf(name) > -1) {
71
+ path = script.substring(0, script.indexOf(name));
72
+ break;
73
+ }
74
+ }
75
+ if (path !== '') {
76
+ break;
77
+ }
78
+ }
79
+ return path;
80
+ },
81
+ secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
82
+ //add framecount
83
+ if (typeof showFrameCount == 'undefined') {
84
+ showFrameCount=false;
85
+ } else if(typeof fps == 'undefined') {
86
+ fps = 25;
87
+ }
88
+
89
+ var hours = Math.floor(time / 3600) % 24,
90
+ minutes = Math.floor(time / 60) % 60,
91
+ seconds = Math.floor(time % 60),
92
+ frames = Math.floor(((time % 1)*fps).toFixed(3)),
93
+ result =
94
+ ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
95
+ + (minutes < 10 ? '0' + minutes : minutes) + ':'
96
+ + (seconds < 10 ? '0' + seconds : seconds)
97
+ + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
98
+
99
+ return result;
100
+ },
101
+
102
+ timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
103
+ if (typeof showFrameCount == 'undefined') {
104
+ showFrameCount=false;
105
+ } else if(typeof fps == 'undefined') {
106
+ fps = 25;
107
+ }
108
+
109
+ var tc_array = hh_mm_ss_ff.split(":"),
110
+ tc_hh = parseInt(tc_array[0], 10),
111
+ tc_mm = parseInt(tc_array[1], 10),
112
+ tc_ss = parseInt(tc_array[2], 10),
113
+ tc_ff = 0,
114
+ tc_in_seconds = 0;
115
+
116
+ if (showFrameCount) {
117
+ tc_ff = parseInt(tc_array[3])/fps;
118
+ }
119
+
120
+ tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
121
+
122
+ return tc_in_seconds;
123
+ },
124
+
125
+
126
+ convertSMPTEtoSeconds: function (SMPTE) {
127
+ if (typeof SMPTE != 'string')
128
+ return false;
129
+
130
+ SMPTE = SMPTE.replace(',', '.');
131
+
132
+ var secs = 0,
133
+ decimalLen = (SMPTE.indexOf('.') != -1) ? SMPTE.split('.')[1].length : 0,
134
+ multiplier = 1;
135
+
136
+ SMPTE = SMPTE.split(':').reverse();
137
+
138
+ for (var i = 0; i < SMPTE.length; i++) {
139
+ multiplier = 1;
140
+ if (i > 0) {
141
+ multiplier = Math.pow(60, i);
142
+ }
143
+ secs += Number(SMPTE[i]) * multiplier;
144
+ }
145
+ return Number(secs.toFixed(decimalLen));
146
+ },
147
+
148
+ /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
149
+ removeSwf: function(id) {
150
+ var obj = document.getElementById(id);
151
+ if (obj && obj.nodeName == "OBJECT") {
152
+ if (mejs.MediaFeatures.isIE) {
153
+ obj.style.display = "none";
154
+ (function(){
155
+ if (obj.readyState == 4) {
156
+ mejs.Utility.removeObjectInIE(id);
157
+ } else {
158
+ setTimeout(arguments.callee, 10);
159
+ }
160
+ })();
161
+ } else {
162
+ obj.parentNode.removeChild(obj);
163
+ }
164
+ }
165
+ },
166
+ removeObjectInIE: function(id) {
167
+ var obj = document.getElementById(id);
168
+ if (obj) {
169
+ for (var i in obj) {
170
+ if (typeof obj[i] == "function") {
171
+ obj[i] = null;
172
+ }
173
+ }
174
+ obj.parentNode.removeChild(obj);
175
+ }
176
+ }
38
177
  };
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
- path = '',
60
- name = '',
61
- script,
62
- scripts = document.getElementsByTagName('script'),
63
- il = scripts.length,
64
- jl = scriptNames.length;
65
-
66
- for (; i < il; i++) {
67
- script = scripts[i].src;
68
- for (j = 0; j < jl; j++) {
69
- name = scriptNames[j];
70
- if (script.indexOf(name) > -1) {
71
- path = script.substring(0, script.indexOf(name));
72
- break;
73
- }
74
- }
75
- if (path !== '') {
76
- break;
77
- }
78
- }
79
- return path;
80
- },
81
- secondsToTimeCode: function(time, forceHours, showFrameCount, fps) {
82
- //add framecount
83
- if (typeof showFrameCount == 'undefined') {
84
- showFrameCount=false;
85
- } else if(typeof fps == 'undefined') {
86
- fps = 25;
87
- }
88
-
89
- var hours = Math.floor(time / 3600) % 24,
90
- minutes = Math.floor(time / 60) % 60,
91
- seconds = Math.floor(time % 60),
92
- frames = Math.floor(((time % 1)*fps).toFixed(3)),
93
- result =
94
- ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '')
95
- + (minutes < 10 ? '0' + minutes : minutes) + ':'
96
- + (seconds < 10 ? '0' + seconds : seconds)
97
- + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : '');
98
-
99
- return result;
100
- },
101
-
102
- timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){
103
- if (typeof showFrameCount == 'undefined') {
104
- showFrameCount=false;
105
- } else if(typeof fps == 'undefined') {
106
- fps = 25;
107
- }
108
-
109
- var tc_array = hh_mm_ss_ff.split(":"),
110
- tc_hh = parseInt(tc_array[0], 10),
111
- tc_mm = parseInt(tc_array[1], 10),
112
- tc_ss = parseInt(tc_array[2], 10),
113
- tc_ff = 0,
114
- tc_in_seconds = 0;
115
-
116
- if (showFrameCount) {
117
- tc_ff = parseInt(tc_array[3])/fps;
118
- }
119
-
120
- tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff;
121
-
122
- return tc_in_seconds;
123
- },
124
-
125
- /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */
126
- removeSwf: function(id) {
127
- var obj = document.getElementById(id);
128
- if (obj && obj.nodeName == "OBJECT") {
129
- if (mejs.MediaFeatures.isIE) {
130
- obj.style.display = "none";
131
- (function(){
132
- if (obj.readyState == 4) {
133
- mejs.Utility.removeObjectInIE(id);
134
- } else {
135
- setTimeout(arguments.callee, 10);
136
- }
137
- })();
138
- } else {
139
- obj.parentNode.removeChild(obj);
140
- }
141
- }
142
- },
143
- removeObjectInIE: function(id) {
144
- var obj = document.getElementById(id);
145
- if (obj) {
146
- for (var i in obj) {
147
- if (typeof obj[i] == "function") {
148
- obj[i] = null;
149
- }
150
- }
151
- obj.parentNode.removeChild(obj);
152
- }
153
- }
154
- };
155
178
 
156
179
 
157
180
  // Core detector, plugins are added below
@@ -280,6 +303,10 @@ mejs.MediaFeatures = {
280
303
  t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit;
281
304
  t.isOpera = (ua.match(/opera/gi) !== null);
282
305
  t.hasTouch = ('ontouchstart' in window);
306
+
307
+ // borrowed from Modernizr
308
+ t.svg = !! document.createElementNS &&
309
+ !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect;
283
310
 
284
311
  // create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
285
312
  for (i=0; i<html5Elements.length; i++) {
@@ -350,7 +377,6 @@ mejs.MediaFeatures = {
350
377
  };
351
378
  mejs.MediaFeatures.init();
352
379
 
353
-
354
380
  /*
355
381
  extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
356
382
  */
@@ -395,6 +421,7 @@ mejs.HtmlMediaElement = {
395
421
  media = url[i];
396
422
  if (this.canPlayType(media.type)) {
397
423
  this.src = media.src;
424
+ break;
398
425
  }
399
426
  }
400
427
  }
@@ -414,6 +441,7 @@ mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
414
441
  this.pluginType = pluginType;
415
442
  this.src = mediaUrl;
416
443
  this.events = {};
444
+ this.attributes = {};
417
445
  };
418
446
 
419
447
  // JavaScript values and ExternalInterface methods that match HTML5 video properties methods
@@ -542,6 +570,7 @@ mejs.PluginMediaElement.prototype = {
542
570
  if (this.canPlayType(media.type)) {
543
571
  this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
544
572
  this.src = mejs.Utility.absolutizeUrl(url);
573
+ break;
545
574
  }
546
575
  }
547
576
  }
@@ -654,7 +683,6 @@ mejs.PluginMediaElement.prototype = {
654
683
  // end: fake events
655
684
 
656
685
  // fake DOM attribute methods
657
- attributes: {},
658
686
  hasAttribute: function(name){
659
687
  return (name in this.attributes);
660
688
  },
@@ -721,9 +749,6 @@ mejs.MediaPluginBridge = {
721
749
  bufferedTime,
722
750
  pluginMediaElement = this.pluginMediaElements[id];
723
751
 
724
- pluginMediaElement.ended = false;
725
- pluginMediaElement.paused = true;
726
-
727
752
  // fake event object to mimic real HTML media event.
728
753
  e = {
729
754
  type: eventName,
@@ -774,6 +799,8 @@ mejs.MediaElementDefaults = {
774
799
  pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
775
800
  // name of flash file
776
801
  flashName: 'flashmediaelement.swf',
802
+ // streamer for RTMP streaming
803
+ flashStreamer: '',
777
804
  // turns on the smoothing filter in Flash
778
805
  enablePluginSmoothing: false,
779
806
  // name of silverlight file
@@ -874,7 +901,8 @@ mejs.HtmlMediaElementShim = {
874
901
  pluginName,
875
902
  pluginVersions,
876
903
  pluginInfo,
877
- dummy;
904
+ dummy,
905
+ media;
878
906
 
879
907
  // STEP 1: Get URL and type from <video src> or <source src>
880
908
 
@@ -904,7 +932,11 @@ mejs.HtmlMediaElementShim = {
904
932
  if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
905
933
  src = n.getAttribute('src');
906
934
  type = this.formatType(src, n.getAttribute('type'));
907
- mediaFiles.push({type:type, url:src});
935
+ media = n.getAttribute('media');
936
+
937
+ if (!media || !window.matchMedia || (window.matchMedia && window.matchMedia(media).matches)) {
938
+ mediaFiles.push({type:type, url:src});
939
+ }
908
940
  }
909
941
  }
910
942
  }
@@ -1035,24 +1067,28 @@ mejs.HtmlMediaElementShim = {
1035
1067
  },
1036
1068
 
1037
1069
  getTypeFromFile: function(url) {
1070
+ url = url.split('?')[0];
1038
1071
  var ext = url.substring(url.lastIndexOf('.') + 1);
1039
1072
  return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext);
1040
1073
  },
1041
1074
 
1042
1075
  getTypeFromExtension: function(ext) {
1043
- var ext_types = {
1044
- 'mp4': ['mp4','m4v'],
1045
- 'ogg': ['ogg','ogv','oga'],
1046
- 'webm': ['webm','webmv','webma']
1047
- };
1048
- var r = ext;
1049
- $.each(ext_types, function(key, value) {
1050
- if (value.indexOf(ext) > -1) {
1051
- r = key;
1052
- return;
1053
- }
1054
- });
1055
- return r;
1076
+
1077
+ switch (ext) {
1078
+ case 'mp4':
1079
+ case 'm4v':
1080
+ return 'mp4';
1081
+ case 'webm':
1082
+ case 'webma':
1083
+ case 'webmv':
1084
+ return 'webm';
1085
+ case 'ogg':
1086
+ case 'oga':
1087
+ case 'ogv':
1088
+ return 'ogg';
1089
+ default:
1090
+ return ext;
1091
+ }
1056
1092
  },
1057
1093
 
1058
1094
  createErrorMessage: function(playback, options, poster) {
@@ -1069,7 +1105,7 @@ mejs.HtmlMediaElementShim = {
1069
1105
 
1070
1106
  errorContainer.innerHTML = (poster !== '') ?
1071
1107
  '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' :
1072
- '<a href="' + playback.url + '"><span>Download File</span></a>';
1108
+ '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>';
1073
1109
 
1074
1110
  htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
1075
1111
  htmlMediaElement.style.display = 'none';
@@ -1148,6 +1184,7 @@ mejs.HtmlMediaElementShim = {
1148
1184
  'width=' + width,
1149
1185
  'startvolume=' + options.startVolume,
1150
1186
  'timerrate=' + options.timerRate,
1187
+ 'flashstreamer=' + options.flashStreamer,
1151
1188
  'height=' + height];
1152
1189
 
1153
1190
  if (playback.url !== null) {
@@ -1248,6 +1285,9 @@ mejs.HtmlMediaElementShim = {
1248
1285
 
1249
1286
  pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1);
1250
1287
 
1288
+ container.innerHTML ='<iframe src="http://player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?portrait=0&byline=0&title=0" width="' + width +'" height="' + height +'" frameborder="0"></iframe>';
1289
+
1290
+ /*
1251
1291
  container.innerHTML =
1252
1292
  '<object width="' + width + '" height="' + height + '">' +
1253
1293
  '<param name="allowfullscreen" value="true" />' +
@@ -1256,7 +1296,8 @@ mejs.HtmlMediaElementShim = {
1256
1296
  '<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" />' +
1257
1297
  '<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 + '"></embed>' +
1258
1298
  '</object>';
1259
-
1299
+ */
1300
+
1260
1301
  break;
1261
1302
  }
1262
1303
  // hide original element
@@ -1482,7 +1523,7 @@ mejs.YouTubeApi = {
1482
1523
  // load the youtube video
1483
1524
  player.cueVideoById(settings.videoId);
1484
1525
 
1485
- var callbackName = settings.containerId + '_callback'
1526
+ var callbackName = settings.containerId + '_callback';
1486
1527
 
1487
1528
  window[callbackName] = function(e) {
1488
1529
  mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement);
@@ -1542,3 +1583,224 @@ function onYouTubePlayerReady(id) {
1542
1583
  window.mejs = mejs;
1543
1584
  window.MediaElement = mejs.MediaElement;
1544
1585
 
1586
+ /*!
1587
+ * Adds Internationalization and localization to objects.
1588
+ *
1589
+ * What is the concept beyond i18n?
1590
+ * http://en.wikipedia.org/wiki/Internationalization_and_localization
1591
+ *
1592
+ *
1593
+ * This file both i18n methods and locale which is used to translate
1594
+ * strings into other languages.
1595
+ *
1596
+ * Default translations are not available, you have to add them
1597
+ * through locale objects which are named exactly as the langcode
1598
+ * they stand for. The default language is always english (en).
1599
+ *
1600
+ *
1601
+ * Wrapper built to be able to attach the i18n object to
1602
+ * other objects without changing more than one line.
1603
+ *
1604
+ *
1605
+ * LICENSE:
1606
+ *
1607
+ * The i18n file uses methods from the Drupal project (drupal.js):
1608
+ * - i18n.methods.t() (modified)
1609
+ * - i18n.methods.checkPlain() (full copy)
1610
+ * - i18n.methods.formatString() (full copy)
1611
+ *
1612
+ * The Drupal project is (like mediaelementjs) licensed under GPLv2.
1613
+ * - http://drupal.org/licensing/faq/#q1
1614
+ * - https://github.com/johndyer/mediaelement
1615
+ * - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
1616
+ *
1617
+ *
1618
+ * @author
1619
+ * Tim Latz (latz.tim@gmail.com)
1620
+ *
1621
+ * @see
1622
+ * me-i18n-locale.js
1623
+ *
1624
+ * @params
1625
+ * - $ - zepto || jQuery ..
1626
+ * - context - document, iframe ..
1627
+ * - exports - CommonJS, window ..
1628
+ *
1629
+ */
1630
+ ;(function($, context, exports, undefined) {
1631
+ "use strict";
1632
+ var i18n = {
1633
+ "locale": {
1634
+ "strings" : {}
1635
+ },
1636
+ "methods" : {}
1637
+ };
1638
+ // start i18n
1639
+
1640
+
1641
+ /**
1642
+ * Get the current browser's language
1643
+ *
1644
+ * @see: i18n.methods.t()
1645
+ */
1646
+ i18n.locale.getLanguage = function () {
1647
+ return {
1648
+ "language" : navigator.language
1649
+ };
1650
+ };
1651
+
1652
+ /**
1653
+ * Store the language the locale object was initialized with
1654
+ */
1655
+ i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage();
1656
+
1657
+
1658
+ /**
1659
+ * Encode special characters in a plain-text string for display as HTML.
1660
+ */
1661
+ i18n.methods.checkPlain = function (str) {
1662
+ var character, regex,
1663
+ replace = {
1664
+ '&': '&amp;',
1665
+ '"': '&quot;',
1666
+ '<': '&lt;',
1667
+ '>': '&gt;'
1668
+ };
1669
+ str = String(str);
1670
+ for (character in replace) {
1671
+ if (replace.hasOwnProperty(character)) {
1672
+ regex = new RegExp(character, 'g');
1673
+ str = str.replace(regex, replace[character]);
1674
+ }
1675
+ }
1676
+ return str;
1677
+ };
1678
+
1679
+ /**
1680
+ * Replace placeholders with sanitized values in a string.
1681
+ *
1682
+ * @param str
1683
+ * A string with placeholders.
1684
+ * @param args
1685
+ * An object of replacements pairs to make. Incidences of any key in this
1686
+ * array are replaced with the corresponding value. Based on the first
1687
+ * character of the key, the value is escaped and/or themed:
1688
+ * - !variable: inserted as is
1689
+ * - @variable: escape plain text to HTML (i18n.methods.checkPlain)
1690
+ * - %variable: escape text and theme as a placeholder for user-submitted
1691
+ * content (checkPlain + <em class="placeholder" > )
1692
+ *
1693
+ * @see i18n.methods.t()
1694
+ */
1695
+ i18n.methods.formatString = function(str, args) {
1696
+ // Transform arguments before inserting them.
1697
+ for (var key in args) {
1698
+ switch (key.charAt(0)) {
1699
+ // Escaped only.
1700
+ case '@':
1701
+ args[key] = i18n.methods.checkPlain(args[key]);
1702
+ break;
1703
+ // Pass-through.
1704
+ case '!':
1705
+ break;
1706
+ // Escaped and placeholder.
1707
+ case '%':
1708
+ default:
1709
+ args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>';
1710
+ break;
1711
+ }
1712
+ str = str.replace(key, args[key]);
1713
+ }
1714
+ return str;
1715
+ };
1716
+
1717
+ /**
1718
+ * Translate strings to the page language or a given language.
1719
+ *
1720
+ * See the documentation of the server-side t() function for further details.
1721
+ *
1722
+ * @param str
1723
+ * A string containing the English string to translate.
1724
+ * @param args
1725
+ * An object of replacements pairs to make after translation. Incidences
1726
+ * of any key in this array are replaced with the corresponding value.
1727
+ * See i18n.methods.formatString().
1728
+ *
1729
+ * @param options
1730
+ * - 'context' (defaults to the default context): The context the source string
1731
+ * belongs to.
1732
+ *
1733
+ * @return
1734
+ * The translated string.
1735
+ */
1736
+ i18n.methods.t = function (str, args, options) {
1737
+
1738
+ // Fetch the localized version of the string.
1739
+ if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) {
1740
+ str = i18n.locale.strings[options.context][str];
1741
+ }
1742
+
1743
+ if (args) {
1744
+ str = i18n.methods.formatString(str, args);
1745
+ }
1746
+ return str;
1747
+ };
1748
+
1749
+
1750
+ /**
1751
+ * Wrapper for i18n.methods.t()
1752
+ *
1753
+ * @see i18n.methods.t()
1754
+ * @throws InvalidArgumentException
1755
+ */
1756
+ i18n.t = function(str, args, options) {
1757
+
1758
+ if (typeof str === 'string' && str.length > 0) {
1759
+
1760
+ // check every time due languge can change for
1761
+ // different reasons (translation, lang switcher ..)
1762
+ var lang = i18n.locale.getLanguage();
1763
+
1764
+ options = options || {
1765
+ "context" : lang.language
1766
+ };
1767
+
1768
+ return i18n.methods.t(str, args, options);
1769
+ }
1770
+ else {
1771
+ throw {
1772
+ "name" : 'InvalidArgumentException',
1773
+ "message" : 'First argument is either not a string or empty.'
1774
+ }
1775
+ }
1776
+ };
1777
+
1778
+ // end i18n
1779
+ exports.i18n = i18n;
1780
+ }(jQuery, document, mejs));
1781
+ /*!
1782
+ * This is a i18n.locale language object.
1783
+ *
1784
+ *<de> German translation by Tim Latz, latz.tim@gmail.com
1785
+ *
1786
+ * @author
1787
+ * Tim Latz (latz.tim@gmail.com)
1788
+ *
1789
+ * @see
1790
+ * me-i18n.js
1791
+ *
1792
+ * @params
1793
+ * - exports - CommonJS, window ..
1794
+ */
1795
+ ;(function(exports, undefined) {
1796
+
1797
+ "use strict";
1798
+
1799
+ exports.de = {
1800
+ "Fullscreen" : "Vollbild",
1801
+ "Go Fullscreen" : "Vollbild an",
1802
+ "Turn off Fullscreen" : "Vollbild aus",
1803
+ "Close" : "Schließen"
1804
+ };
1805
+
1806
+ }(mejs.i18n.locale.strings));