mediaelement_rails 0.2
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.
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +97 -0
- data/MIT-LICENSE +20 -0
- data/README.md +29 -0
- data/Rakefile +39 -0
- data/app/assets/flash/mediaelement_rails/flashmediaelement.swf +0 -0
- data/app/assets/images/mediaelement_rails/background.png +0 -0
- data/app/assets/images/mediaelement_rails/bigplay.png +0 -0
- data/app/assets/images/mediaelement_rails/controls-ted.png +0 -0
- data/app/assets/images/mediaelement_rails/controls-wmp-bg.png +0 -0
- data/app/assets/images/mediaelement_rails/controls-wmp.png +0 -0
- data/app/assets/images/mediaelement_rails/controls.png +0 -0
- data/app/assets/images/mediaelement_rails/loading.gif +0 -0
- data/app/assets/javascripts/mediaelement_rails/index.js +3 -0
- data/app/assets/javascripts/mediaelement_rails/mediaelement.js +943 -0
- data/app/assets/javascripts/mediaelement_rails/mediaelementplayer.js +1703 -0
- data/app/assets/javascripts/mediaelement_rails/rails.js.erb +5 -0
- data/app/assets/silverlight/mediaelement_rails/silverlightmediaelement.xap +0 -0
- data/app/assets/stylesheets/mediaelement_rails/index.css +1 -0
- data/app/assets/stylesheets/mediaelement_rails/mediaelementplayer.css.erb +571 -0
- data/app/assets/stylesheets/mediaelement_rails/mejs-skins.css.erb +283 -0
- data/app/controllers/mediaelement_rails/application_controller.rb +4 -0
- data/app/helpers/mediaelement_rails/application_helper.rb +4 -0
- data/app/views/layouts/application.html.erb +14 -0
- data/app/views/layouts/mediaelement_rails/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/lib/generators/mediaelement_update/USAGE +7 -0
- data/lib/generators/mediaelement_update/mediaelement_update_generator.rb +46 -0
- data/lib/mediaelement_rails/engine.rb +5 -0
- data/lib/mediaelement_rails/version.rb +3 -0
- data/lib/mediaelement_rails.rb +4 -0
- data/lib/tasks/mediaelement_rails_tasks.rake +4 -0
- data/mediaelement_rails.gemspec +20 -0
- data/script/rails +6 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +9 -0
- data/test/dummy/app/assets/stylesheets/application.css +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +24 -0
- data/test/dummy/config/environments/production.rb +51 -0
- data/test/dummy/config/environments/test.rb +34 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/mediaelement_rails_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +170 -0
@@ -0,0 +1,943 @@
|
|
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-2011, John Dyer (http://j.hn)
|
11
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
12
|
+
*
|
13
|
+
*/
|
14
|
+
// Namespace
|
15
|
+
var mejs = mejs || {};
|
16
|
+
|
17
|
+
// version number
|
18
|
+
mejs.version = '2.1.9';
|
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']}
|
30
|
+
//,{version: [11,0], types: ['video/webm']} // for future reference
|
31
|
+
]
|
32
|
+
};
|
33
|
+
|
34
|
+
/*
|
35
|
+
Utility methods
|
36
|
+
*/
|
37
|
+
mejs.Utility = {
|
38
|
+
encodeUrl: function(url) {
|
39
|
+
return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
|
40
|
+
},
|
41
|
+
escapeHTML: function(s) {
|
42
|
+
return s.toString().split('&').join('&').split('<').join('<').split('"').join('"');
|
43
|
+
},
|
44
|
+
absolutizeUrl: function(url) {
|
45
|
+
var el = document.createElement('div');
|
46
|
+
el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
|
47
|
+
return el.firstChild.href;
|
48
|
+
},
|
49
|
+
getScriptPath: function(scriptNames) {
|
50
|
+
var
|
51
|
+
i = 0,
|
52
|
+
j,
|
53
|
+
path = '',
|
54
|
+
name = '',
|
55
|
+
script,
|
56
|
+
scripts = document.getElementsByTagName('script');
|
57
|
+
|
58
|
+
for (; i < scripts.length; i++) {
|
59
|
+
script = scripts[i].src;
|
60
|
+
for (j = 0; j < scriptNames.length; j++) {
|
61
|
+
name = scriptNames[j];
|
62
|
+
if (script.indexOf(name) > -1) {
|
63
|
+
path = script.substring(0, script.indexOf(name));
|
64
|
+
break;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
if (path !== '') {
|
68
|
+
break;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return path;
|
72
|
+
},
|
73
|
+
secondsToTimeCode: function(seconds,forceHours) {
|
74
|
+
seconds = Math.round(seconds);
|
75
|
+
var hours,
|
76
|
+
minutes = Math.floor(seconds / 60);
|
77
|
+
if (minutes >= 60) {
|
78
|
+
hours = Math.floor(minutes / 60);
|
79
|
+
minutes = minutes % 60;
|
80
|
+
}
|
81
|
+
hours = hours === undefined ? "00" : (hours >= 10) ? hours : "0" + hours;
|
82
|
+
minutes = (minutes >= 10) ? minutes : "0" + minutes;
|
83
|
+
seconds = Math.floor(seconds % 60);
|
84
|
+
seconds = (seconds >= 10) ? seconds : "0" + seconds;
|
85
|
+
return ((hours > 0 || forceHours === true) ? hours + ":" :'') + minutes + ":" + seconds;
|
86
|
+
},
|
87
|
+
timeCodeToSeconds: function(timecode){
|
88
|
+
var tab = timecode.split(':');
|
89
|
+
return tab[0]*60*60 + tab[1]*60 + parseFloat(tab[2].replace(',','.'));
|
90
|
+
}
|
91
|
+
};
|
92
|
+
|
93
|
+
|
94
|
+
// Core detector, plugins are added below
|
95
|
+
mejs.PluginDetector = {
|
96
|
+
|
97
|
+
// main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
|
98
|
+
hasPluginVersion: function(plugin, v) {
|
99
|
+
var pv = this.plugins[plugin];
|
100
|
+
v[1] = v[1] || 0;
|
101
|
+
v[2] = v[2] || 0;
|
102
|
+
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;
|
103
|
+
},
|
104
|
+
|
105
|
+
// cached values
|
106
|
+
nav: window.navigator,
|
107
|
+
ua: window.navigator.userAgent.toLowerCase(),
|
108
|
+
|
109
|
+
// stored version numbers
|
110
|
+
plugins: [],
|
111
|
+
|
112
|
+
// runs detectPlugin() and stores the version number
|
113
|
+
addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
|
114
|
+
this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
|
115
|
+
},
|
116
|
+
|
117
|
+
// get the version number from the mimetype (all but IE) or ActiveX (IE)
|
118
|
+
detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
|
119
|
+
|
120
|
+
var version = [0,0,0],
|
121
|
+
description,
|
122
|
+
i,
|
123
|
+
ax;
|
124
|
+
|
125
|
+
// Firefox, Webkit, Opera
|
126
|
+
if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
|
127
|
+
description = this.nav.plugins[pluginName].description;
|
128
|
+
if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
|
129
|
+
version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
|
130
|
+
for (i=0; i<version.length; i++) {
|
131
|
+
version[i] = parseInt(version[i].match(/\d+/), 10);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
// Internet Explorer / ActiveX
|
135
|
+
} else if (typeof(window.ActiveXObject) != 'undefined') {
|
136
|
+
try {
|
137
|
+
ax = new ActiveXObject(activeX);
|
138
|
+
if (ax) {
|
139
|
+
version = axDetect(ax);
|
140
|
+
}
|
141
|
+
}
|
142
|
+
catch (e) { }
|
143
|
+
}
|
144
|
+
return version;
|
145
|
+
}
|
146
|
+
};
|
147
|
+
|
148
|
+
// Add Flash detection
|
149
|
+
mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
|
150
|
+
// adapted from SWFObject
|
151
|
+
var version = [],
|
152
|
+
d = ax.GetVariable("$version");
|
153
|
+
if (d) {
|
154
|
+
d = d.split(" ")[1].split(",");
|
155
|
+
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
156
|
+
}
|
157
|
+
return version;
|
158
|
+
});
|
159
|
+
|
160
|
+
// Add Silverlight detection
|
161
|
+
mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
|
162
|
+
// Silverlight cannot report its version number to IE
|
163
|
+
// but it does have a isVersionSupported function, so we have to loop through it to get a version number.
|
164
|
+
// adapted from http://www.silverlightversion.com/
|
165
|
+
var v = [0,0,0,0],
|
166
|
+
loopMatch = function(ax, v, i, n) {
|
167
|
+
while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
|
168
|
+
v[i]+=n;
|
169
|
+
}
|
170
|
+
v[i] -= n;
|
171
|
+
};
|
172
|
+
loopMatch(ax, v, 0, 1);
|
173
|
+
loopMatch(ax, v, 1, 1);
|
174
|
+
loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
|
175
|
+
loopMatch(ax, v, 2, 1000);
|
176
|
+
loopMatch(ax, v, 2, 100);
|
177
|
+
loopMatch(ax, v, 2, 10);
|
178
|
+
loopMatch(ax, v, 2, 1);
|
179
|
+
loopMatch(ax, v, 3, 1);
|
180
|
+
|
181
|
+
return v;
|
182
|
+
});
|
183
|
+
// add adobe acrobat
|
184
|
+
/*
|
185
|
+
PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
|
186
|
+
var version = [],
|
187
|
+
d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
|
188
|
+
|
189
|
+
if (d) {
|
190
|
+
version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
191
|
+
}
|
192
|
+
return version;
|
193
|
+
});
|
194
|
+
*/
|
195
|
+
// necessary detection (fixes for <IE9)
|
196
|
+
mejs.MediaFeatures = {
|
197
|
+
init: function() {
|
198
|
+
var
|
199
|
+
nav = mejs.PluginDetector.nav,
|
200
|
+
ua = mejs.PluginDetector.ua.toLowerCase(),
|
201
|
+
i,
|
202
|
+
v,
|
203
|
+
html5Elements = ['source','track','audio','video'];
|
204
|
+
|
205
|
+
// detect browsers (only the ones that have some kind of quirk we need to work around)
|
206
|
+
this.isiPad = (ua.match(/ipad/i) !== null);
|
207
|
+
this.isiPhone = (ua.match(/iphone/i) !== null);
|
208
|
+
this.isAndroid = (ua.match(/android/i) !== null);
|
209
|
+
this.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
|
210
|
+
this.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
|
211
|
+
this.isChrome = (ua.match(/chrome/gi) !== null);
|
212
|
+
this.isFirefox = (ua.match(/firefox/gi) !== null);
|
213
|
+
|
214
|
+
// create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
|
215
|
+
for (i=0; i<html5Elements.length; i++) {
|
216
|
+
v = document.createElement(html5Elements[i]);
|
217
|
+
}
|
218
|
+
|
219
|
+
// detect native JavaScript fullscreen (Safari only, Chrome fails)
|
220
|
+
this.hasNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
|
221
|
+
if (this.isChrome) {
|
222
|
+
this.hasNativeFullScreen = false;
|
223
|
+
}
|
224
|
+
// OS X 10.5 can't do this even if it says it can :(
|
225
|
+
if (this.hasNativeFullScreen && ua.match(/mac os x 10_5/i)) {
|
226
|
+
this.hasNativeFullScreen = false;
|
227
|
+
}
|
228
|
+
}
|
229
|
+
};
|
230
|
+
mejs.MediaFeatures.init();
|
231
|
+
|
232
|
+
|
233
|
+
/*
|
234
|
+
extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
|
235
|
+
*/
|
236
|
+
mejs.HtmlMediaElement = {
|
237
|
+
pluginType: 'native',
|
238
|
+
isFullScreen: false,
|
239
|
+
|
240
|
+
setCurrentTime: function (time) {
|
241
|
+
this.currentTime = time;
|
242
|
+
},
|
243
|
+
|
244
|
+
setMuted: function (muted) {
|
245
|
+
this.muted = muted;
|
246
|
+
},
|
247
|
+
|
248
|
+
setVolume: function (volume) {
|
249
|
+
this.volume = volume;
|
250
|
+
},
|
251
|
+
|
252
|
+
// for parity with the plugin versions
|
253
|
+
stop: function () {
|
254
|
+
this.pause();
|
255
|
+
},
|
256
|
+
|
257
|
+
// This can be a url string
|
258
|
+
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
259
|
+
setSrc: function (url) {
|
260
|
+
if (typeof url == 'string') {
|
261
|
+
this.src = url;
|
262
|
+
} else {
|
263
|
+
var i, media;
|
264
|
+
|
265
|
+
for (i=0; i<url.length; i++) {
|
266
|
+
media = url[i];
|
267
|
+
if (this.canPlayType(media.type)) {
|
268
|
+
this.src = media.src;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
},
|
273
|
+
|
274
|
+
setVideoSize: function (width, height) {
|
275
|
+
this.width = width;
|
276
|
+
this.height = height;
|
277
|
+
}
|
278
|
+
};
|
279
|
+
|
280
|
+
/*
|
281
|
+
Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
|
282
|
+
*/
|
283
|
+
mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
|
284
|
+
this.id = pluginid;
|
285
|
+
this.pluginType = pluginType;
|
286
|
+
this.src = mediaUrl;
|
287
|
+
this.events = {};
|
288
|
+
};
|
289
|
+
|
290
|
+
// JavaScript values and ExternalInterface methods that match HTML5 video properties methods
|
291
|
+
// http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
|
292
|
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
293
|
+
mejs.PluginMediaElement.prototype = {
|
294
|
+
|
295
|
+
// special
|
296
|
+
pluginElement: null,
|
297
|
+
pluginType: '',
|
298
|
+
isFullScreen: false,
|
299
|
+
|
300
|
+
// not implemented :(
|
301
|
+
playbackRate: -1,
|
302
|
+
defaultPlaybackRate: -1,
|
303
|
+
seekable: [],
|
304
|
+
played: [],
|
305
|
+
|
306
|
+
// HTML5 read-only properties
|
307
|
+
paused: true,
|
308
|
+
ended: false,
|
309
|
+
seeking: false,
|
310
|
+
duration: 0,
|
311
|
+
error: null,
|
312
|
+
|
313
|
+
// HTML5 get/set properties, but only set (updated by event handlers)
|
314
|
+
muted: false,
|
315
|
+
volume: 1,
|
316
|
+
currentTime: 0,
|
317
|
+
|
318
|
+
// HTML5 methods
|
319
|
+
play: function () {
|
320
|
+
if (this.pluginApi != null) {
|
321
|
+
this.pluginApi.playMedia();
|
322
|
+
this.paused = false;
|
323
|
+
}
|
324
|
+
},
|
325
|
+
load: function () {
|
326
|
+
if (this.pluginApi != null) {
|
327
|
+
this.pluginApi.loadMedia();
|
328
|
+
this.paused = false;
|
329
|
+
}
|
330
|
+
},
|
331
|
+
pause: function () {
|
332
|
+
if (this.pluginApi != null) {
|
333
|
+
this.pluginApi.pauseMedia();
|
334
|
+
this.paused = true;
|
335
|
+
}
|
336
|
+
},
|
337
|
+
stop: function () {
|
338
|
+
if (this.pluginApi != null) {
|
339
|
+
this.pluginApi.stopMedia();
|
340
|
+
this.paused = true;
|
341
|
+
}
|
342
|
+
},
|
343
|
+
canPlayType: function(type) {
|
344
|
+
var i,
|
345
|
+
j,
|
346
|
+
pluginInfo,
|
347
|
+
pluginVersions = mejs.plugins[this.pluginType];
|
348
|
+
|
349
|
+
for (i=0; i<pluginVersions.length; i++) {
|
350
|
+
pluginInfo = pluginVersions[i];
|
351
|
+
|
352
|
+
// test if user has the correct plugin version
|
353
|
+
if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
|
354
|
+
|
355
|
+
// test for plugin playback types
|
356
|
+
for (j=0; j<pluginInfo.types.length; j++) {
|
357
|
+
// find plugin that can play the type
|
358
|
+
if (type == pluginInfo.types[j]) {
|
359
|
+
return true;
|
360
|
+
}
|
361
|
+
}
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
return false;
|
366
|
+
},
|
367
|
+
|
368
|
+
// custom methods since not all JavaScript implementations support get/set
|
369
|
+
|
370
|
+
// This can be a url string
|
371
|
+
// or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
|
372
|
+
setSrc: function (url) {
|
373
|
+
if (typeof url == 'string') {
|
374
|
+
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
|
375
|
+
this.src = mejs.Utility.absolutizeUrl(url);
|
376
|
+
} else {
|
377
|
+
var i, media;
|
378
|
+
|
379
|
+
for (i=0; i<url.length; i++) {
|
380
|
+
media = url[i];
|
381
|
+
if (this.canPlayType(media.type)) {
|
382
|
+
this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
|
383
|
+
this.src = mejs.Utility.absolutizeUrl(url);
|
384
|
+
}
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
},
|
389
|
+
setCurrentTime: function (time) {
|
390
|
+
if (this.pluginApi != null) {
|
391
|
+
this.pluginApi.setCurrentTime(time);
|
392
|
+
this.currentTime = time;
|
393
|
+
}
|
394
|
+
},
|
395
|
+
setVolume: function (volume) {
|
396
|
+
if (this.pluginApi != null) {
|
397
|
+
this.pluginApi.setVolume(volume);
|
398
|
+
this.volume = volume;
|
399
|
+
}
|
400
|
+
},
|
401
|
+
setMuted: function (muted) {
|
402
|
+
if (this.pluginApi != null) {
|
403
|
+
this.pluginApi.setMuted(muted);
|
404
|
+
this.muted = muted;
|
405
|
+
}
|
406
|
+
},
|
407
|
+
|
408
|
+
// additional non-HTML5 methods
|
409
|
+
setVideoSize: function (width, height) {
|
410
|
+
if ( this.pluginElement.style) {
|
411
|
+
this.pluginElement.style.width = width + 'px';
|
412
|
+
this.pluginElement.style.height = height + 'px';
|
413
|
+
}
|
414
|
+
if (this.pluginApi != null) {
|
415
|
+
this.pluginApi.setVideoSize(width, height);
|
416
|
+
}
|
417
|
+
},
|
418
|
+
|
419
|
+
setFullscreen: function (fullscreen) {
|
420
|
+
if (this.pluginApi != null) {
|
421
|
+
this.pluginApi.setFullscreen(fullscreen);
|
422
|
+
}
|
423
|
+
},
|
424
|
+
|
425
|
+
// start: fake events
|
426
|
+
addEventListener: function (eventName, callback, bubble) {
|
427
|
+
this.events[eventName] = this.events[eventName] || [];
|
428
|
+
this.events[eventName].push(callback);
|
429
|
+
},
|
430
|
+
removeEventListener: function (eventName, callback) {
|
431
|
+
if (!eventName) { this.events = {}; return true; }
|
432
|
+
var callbacks = this.events[eventName];
|
433
|
+
if (!callbacks) return true;
|
434
|
+
if (!callback) { this.events[eventName] = []; return true; }
|
435
|
+
for (i = 0; i < callbacks.length; i++) {
|
436
|
+
if (callbacks[i] === callback) {
|
437
|
+
this.events[eventName].splice(i, 1);
|
438
|
+
return true;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
return false;
|
442
|
+
},
|
443
|
+
dispatchEvent: function (eventName) {
|
444
|
+
var i,
|
445
|
+
args,
|
446
|
+
callbacks = this.events[eventName];
|
447
|
+
|
448
|
+
if (callbacks) {
|
449
|
+
args = Array.prototype.slice.call(arguments, 1);
|
450
|
+
for (i = 0; i < callbacks.length; i++) {
|
451
|
+
callbacks[i].apply(null, args);
|
452
|
+
}
|
453
|
+
}
|
454
|
+
}
|
455
|
+
// end: fake events
|
456
|
+
};
|
457
|
+
|
458
|
+
|
459
|
+
// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
|
460
|
+
mejs.MediaPluginBridge = {
|
461
|
+
|
462
|
+
pluginMediaElements:{},
|
463
|
+
htmlMediaElements:{},
|
464
|
+
|
465
|
+
registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
|
466
|
+
this.pluginMediaElements[id] = pluginMediaElement;
|
467
|
+
this.htmlMediaElements[id] = htmlMediaElement;
|
468
|
+
},
|
469
|
+
|
470
|
+
// when Flash/Silverlight is ready, it calls out to this method
|
471
|
+
initPlugin: function (id) {
|
472
|
+
|
473
|
+
var pluginMediaElement = this.pluginMediaElements[id],
|
474
|
+
htmlMediaElement = this.htmlMediaElements[id];
|
475
|
+
|
476
|
+
// find the javascript bridge
|
477
|
+
switch (pluginMediaElement.pluginType) {
|
478
|
+
case "flash":
|
479
|
+
pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
|
480
|
+
break;
|
481
|
+
case "silverlight":
|
482
|
+
pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
|
483
|
+
pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
|
484
|
+
break;
|
485
|
+
}
|
486
|
+
|
487
|
+
if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
|
488
|
+
pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
|
489
|
+
}
|
490
|
+
},
|
491
|
+
|
492
|
+
// receives events from Flash/Silverlight and sends them out as HTML5 media events
|
493
|
+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
|
494
|
+
fireEvent: function (id, eventName, values) {
|
495
|
+
|
496
|
+
var
|
497
|
+
e,
|
498
|
+
i,
|
499
|
+
bufferedTime,
|
500
|
+
pluginMediaElement = this.pluginMediaElements[id];
|
501
|
+
|
502
|
+
pluginMediaElement.ended = false;
|
503
|
+
pluginMediaElement.paused = true;
|
504
|
+
|
505
|
+
// fake event object to mimic real HTML media event.
|
506
|
+
e = {
|
507
|
+
type: eventName,
|
508
|
+
target: pluginMediaElement
|
509
|
+
};
|
510
|
+
|
511
|
+
// attach all values to element and event object
|
512
|
+
for (i in values) {
|
513
|
+
pluginMediaElement[i] = values[i];
|
514
|
+
e[i] = values[i];
|
515
|
+
}
|
516
|
+
|
517
|
+
// fake the newer W3C buffered TimeRange (loaded and total have been removed)
|
518
|
+
bufferedTime = values.bufferedTime || 0;
|
519
|
+
|
520
|
+
e.target.buffered = e.buffered = {
|
521
|
+
start: function(index) {
|
522
|
+
return 0;
|
523
|
+
},
|
524
|
+
end: function (index) {
|
525
|
+
return bufferedTime;
|
526
|
+
},
|
527
|
+
length: 1
|
528
|
+
};
|
529
|
+
|
530
|
+
pluginMediaElement.dispatchEvent(e.type, e);
|
531
|
+
}
|
532
|
+
};
|
533
|
+
|
534
|
+
/*
|
535
|
+
Default options
|
536
|
+
*/
|
537
|
+
mejs.MediaElementDefaults = {
|
538
|
+
// allows testing on HTML5, flash, silverlight
|
539
|
+
// auto: attempts to detect what the browser can do
|
540
|
+
// native: forces HTML5 playback
|
541
|
+
// shim: disallows HTML5, will attempt either Flash or Silverlight
|
542
|
+
// none: forces fallback view
|
543
|
+
mode: 'auto',
|
544
|
+
// remove or reorder to change plugin priority and availability
|
545
|
+
plugins: ['flash','silverlight'],
|
546
|
+
// shows debug errors on screen
|
547
|
+
enablePluginDebug: false,
|
548
|
+
// overrides the type specified, useful for dynamic instantiation
|
549
|
+
type: '',
|
550
|
+
// path to Flash and Silverlight plugins
|
551
|
+
pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
|
552
|
+
// name of flash file
|
553
|
+
flashName: 'flashmediaelement.swf',
|
554
|
+
// turns on the smoothing filter in Flash
|
555
|
+
enablePluginSmoothing: false,
|
556
|
+
// name of silverlight file
|
557
|
+
silverlightName: 'silverlightmediaelement.xap',
|
558
|
+
// default if the <video width> is not specified
|
559
|
+
defaultVideoWidth: 480,
|
560
|
+
// default if the <video height> is not specified
|
561
|
+
defaultVideoHeight: 270,
|
562
|
+
// overrides <video width>
|
563
|
+
pluginWidth: -1,
|
564
|
+
// overrides <video height>
|
565
|
+
pluginHeight: -1,
|
566
|
+
// rate in milliseconds for Flash and Silverlight to fire the timeupdate event
|
567
|
+
// larger number is less accurate, but less strain on plugin->JavaScript bridge
|
568
|
+
timerRate: 250,
|
569
|
+
success: function () { },
|
570
|
+
error: function () { }
|
571
|
+
};
|
572
|
+
|
573
|
+
/*
|
574
|
+
Determines if a browser supports the <video> or <audio> element
|
575
|
+
and returns either the native element or a Flash/Silverlight version that
|
576
|
+
mimics HTML5 MediaElement
|
577
|
+
*/
|
578
|
+
mejs.MediaElement = function (el, o) {
|
579
|
+
return mejs.HtmlMediaElementShim.create(el,o);
|
580
|
+
};
|
581
|
+
|
582
|
+
mejs.HtmlMediaElementShim = {
|
583
|
+
|
584
|
+
create: function(el, o) {
|
585
|
+
var
|
586
|
+
options = mejs.MediaElementDefaults,
|
587
|
+
htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
|
588
|
+
isVideo = (htmlMediaElement.tagName.toLowerCase() == 'video'),
|
589
|
+
supportsMediaTag = (typeof(htmlMediaElement.canPlayType) != 'undefined'),
|
590
|
+
playback = {method:'', url:''},
|
591
|
+
poster = htmlMediaElement.getAttribute('poster'),
|
592
|
+
autoplay = htmlMediaElement.getAttribute('autoplay'),
|
593
|
+
preload = htmlMediaElement.getAttribute('preload'),
|
594
|
+
controls = htmlMediaElement.getAttribute('controls'),
|
595
|
+
prop;
|
596
|
+
|
597
|
+
// extend options
|
598
|
+
for (prop in o) {
|
599
|
+
options[prop] = o[prop];
|
600
|
+
}
|
601
|
+
|
602
|
+
// check for real poster
|
603
|
+
poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
|
604
|
+
preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
|
605
|
+
autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
|
606
|
+
controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
|
607
|
+
|
608
|
+
// test for HTML5 and plugin capabilities
|
609
|
+
playback = this.determinePlayback(htmlMediaElement, options, isVideo, supportsMediaTag);
|
610
|
+
|
611
|
+
if (playback.method == 'native') {
|
612
|
+
// second fix for android
|
613
|
+
if (mejs.MediaFeatures.isBustedAndroid) {
|
614
|
+
htmlMediaElement.src = playback.url;
|
615
|
+
htmlMediaElement.addEventListener('click', function() {
|
616
|
+
htmlMediaElement.play();
|
617
|
+
}, true);
|
618
|
+
}
|
619
|
+
|
620
|
+
// add methods to native HTMLMediaElement
|
621
|
+
return this.updateNative( htmlMediaElement, options, autoplay, preload, playback);
|
622
|
+
} else if (playback.method !== '') {
|
623
|
+
// create plugin to mimic HTMLMediaElement
|
624
|
+
return this.createPlugin( htmlMediaElement, options, isVideo, playback.method, (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '', poster, autoplay, preload, controls);
|
625
|
+
} else {
|
626
|
+
// boo, no HTML5, no Flash, no Silverlight.
|
627
|
+
this.createErrorMessage( htmlMediaElement, options, (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '', poster );
|
628
|
+
}
|
629
|
+
},
|
630
|
+
|
631
|
+
determinePlayback: function(htmlMediaElement, options, isVideo, supportsMediaTag) {
|
632
|
+
var
|
633
|
+
mediaFiles = [],
|
634
|
+
i,
|
635
|
+
j,
|
636
|
+
k,
|
637
|
+
l,
|
638
|
+
n,
|
639
|
+
type,
|
640
|
+
result = { method: '', url: ''},
|
641
|
+
src = htmlMediaElement.getAttribute('src'),
|
642
|
+
pluginName,
|
643
|
+
pluginVersions,
|
644
|
+
pluginInfo;
|
645
|
+
|
646
|
+
// clean up src attr
|
647
|
+
if (src == 'undefined' || src == '' || src === null)
|
648
|
+
src = null;
|
649
|
+
|
650
|
+
// STEP 1: Get URL and type from <video src> or <source src>
|
651
|
+
|
652
|
+
// supplied type overrides all HTML
|
653
|
+
if (typeof (options.type) != 'undefined' && options.type !== '') {
|
654
|
+
mediaFiles.push({type:options.type, url:src});
|
655
|
+
|
656
|
+
// test for src attribute first
|
657
|
+
} else if (src !== null) {
|
658
|
+
type = this.checkType(src, htmlMediaElement.getAttribute('type'), isVideo);
|
659
|
+
mediaFiles.push({type:type, url:src});
|
660
|
+
|
661
|
+
// then test for <source> elements
|
662
|
+
} else {
|
663
|
+
// test <source> types to see if they are usable
|
664
|
+
for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
|
665
|
+
n = htmlMediaElement.childNodes[i];
|
666
|
+
if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
|
667
|
+
src = n.getAttribute('src');
|
668
|
+
type = this.checkType(src, n.getAttribute('type'), isVideo);
|
669
|
+
mediaFiles.push({type:type, url:src});
|
670
|
+
}
|
671
|
+
}
|
672
|
+
}
|
673
|
+
|
674
|
+
// STEP 2: Test for playback method
|
675
|
+
|
676
|
+
// special case for Android which sadly doesn't implement the canPlayType function (always returns '')
|
677
|
+
if (mejs.MediaFeatures.isBustedAndroid) {
|
678
|
+
htmlMediaElement.canPlayType = function(type) {
|
679
|
+
return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
|
680
|
+
};
|
681
|
+
}
|
682
|
+
|
683
|
+
|
684
|
+
// test for native playback first
|
685
|
+
if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'native')) {
|
686
|
+
for (i=0; i<mediaFiles.length; i++) {
|
687
|
+
// normal check
|
688
|
+
if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
|
689
|
+
// special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
|
690
|
+
|| htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
|
691
|
+
result.method = 'native';
|
692
|
+
result.url = mediaFiles[i].url;
|
693
|
+
return result;
|
694
|
+
}
|
695
|
+
}
|
696
|
+
}
|
697
|
+
|
698
|
+
// if native playback didn't work, then test plugins
|
699
|
+
if (options.mode === 'auto' || options.mode === 'shim') {
|
700
|
+
for (i=0; i<mediaFiles.length; i++) {
|
701
|
+
type = mediaFiles[i].type;
|
702
|
+
|
703
|
+
// test all plugins in order of preference [silverlight, flash]
|
704
|
+
for (j=0; j<options.plugins.length; j++) {
|
705
|
+
|
706
|
+
pluginName = options.plugins[j];
|
707
|
+
|
708
|
+
// test version of plugin (for future features)
|
709
|
+
pluginVersions = mejs.plugins[pluginName];
|
710
|
+
for (k=0; k<pluginVersions.length; k++) {
|
711
|
+
pluginInfo = pluginVersions[k];
|
712
|
+
|
713
|
+
// test if user has the correct plugin version
|
714
|
+
if (mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
|
715
|
+
|
716
|
+
// test for plugin playback types
|
717
|
+
for (l=0; l<pluginInfo.types.length; l++) {
|
718
|
+
// find plugin that can play the type
|
719
|
+
if (type == pluginInfo.types[l]) {
|
720
|
+
result.method = pluginName;
|
721
|
+
result.url = mediaFiles[i].url;
|
722
|
+
return result;
|
723
|
+
}
|
724
|
+
}
|
725
|
+
}
|
726
|
+
}
|
727
|
+
}
|
728
|
+
}
|
729
|
+
}
|
730
|
+
|
731
|
+
// what if there's nothing to play? just grab the first available
|
732
|
+
if (result.method === '') {
|
733
|
+
result.url = mediaFiles[0].url;
|
734
|
+
}
|
735
|
+
|
736
|
+
return result;
|
737
|
+
},
|
738
|
+
|
739
|
+
checkType: function(url, type, isVideo) {
|
740
|
+
var ext;
|
741
|
+
|
742
|
+
// if no type is supplied, fake it with the extension
|
743
|
+
if (url && !type) {
|
744
|
+
ext = url.substring(url.lastIndexOf('.') + 1);
|
745
|
+
return ((isVideo) ? 'video' : 'audio') + '/' + ext;
|
746
|
+
} else {
|
747
|
+
// only return the mime part of the type in case the attribute contains the codec
|
748
|
+
// see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
|
749
|
+
// `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
|
750
|
+
|
751
|
+
if (type && ~type.indexOf(';')) {
|
752
|
+
return type.substr(0, type.indexOf(';'));
|
753
|
+
} else {
|
754
|
+
return type;
|
755
|
+
}
|
756
|
+
}
|
757
|
+
},
|
758
|
+
|
759
|
+
createErrorMessage: function(htmlMediaElement, options, downloadUrl, poster) {
|
760
|
+
var errorContainer = document.createElement('div');
|
761
|
+
errorContainer.className = 'me-cannotplay';
|
762
|
+
|
763
|
+
try {
|
764
|
+
errorContainer.style.width = htmlMediaElement.width + 'px';
|
765
|
+
errorContainer.style.height = htmlMediaElement.height + 'px';
|
766
|
+
} catch (e) {}
|
767
|
+
|
768
|
+
errorContainer.innerHTML = (poster !== '') ?
|
769
|
+
'<a href="' + downloadUrl + '"><img src="' + poster + '" /></a>' :
|
770
|
+
'<a href="' + downloadUrl + '"><span>Download File</span></a>';
|
771
|
+
|
772
|
+
htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
|
773
|
+
htmlMediaElement.style.display = 'none';
|
774
|
+
|
775
|
+
options.error(htmlMediaElement);
|
776
|
+
},
|
777
|
+
|
778
|
+
createPlugin:function(htmlMediaElement, options, isVideo, pluginType, mediaUrl, poster, autoplay, preload, controls) {
|
779
|
+
var width = 1,
|
780
|
+
height = 1,
|
781
|
+
pluginid = 'me_' + pluginType + '_' + (mejs.meIndex++),
|
782
|
+
pluginMediaElement = new mejs.PluginMediaElement(pluginid, pluginType, mediaUrl),
|
783
|
+
container = document.createElement('div'),
|
784
|
+
specialIEContainer,
|
785
|
+
node,
|
786
|
+
initVars;
|
787
|
+
|
788
|
+
// check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
|
789
|
+
node = htmlMediaElement.parentNode;
|
790
|
+
while (node !== null && node.tagName.toLowerCase() != 'body') {
|
791
|
+
if (node.parentNode.tagName.toLowerCase() == 'p') {
|
792
|
+
node.parentNode.parentNode.insertBefore(node, node.parentNode);
|
793
|
+
break;
|
794
|
+
}
|
795
|
+
node = node.parentNode;
|
796
|
+
}
|
797
|
+
|
798
|
+
if (isVideo) {
|
799
|
+
width = (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
|
800
|
+
height = (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
|
801
|
+
} else {
|
802
|
+
if (options.enablePluginDebug) {
|
803
|
+
width = 320;
|
804
|
+
height = 240;
|
805
|
+
}
|
806
|
+
}
|
807
|
+
|
808
|
+
// register plugin
|
809
|
+
pluginMediaElement.success = options.success;
|
810
|
+
mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
|
811
|
+
|
812
|
+
// add container (must be added to DOM before inserting HTML for IE)
|
813
|
+
container.className = 'me-plugin';
|
814
|
+
htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
|
815
|
+
|
816
|
+
// flash/silverlight vars
|
817
|
+
initVars = [
|
818
|
+
'id=' + pluginid,
|
819
|
+
'isvideo=' + ((isVideo) ? "true" : "false"),
|
820
|
+
'autoplay=' + ((autoplay) ? "true" : "false"),
|
821
|
+
'preload=' + preload,
|
822
|
+
'width=' + width,
|
823
|
+
'startvolume=' + options.startVolume,
|
824
|
+
'timerrate=' + options.timerRate,
|
825
|
+
'height=' + height];
|
826
|
+
|
827
|
+
if (mediaUrl !== null) {
|
828
|
+
if (pluginType == 'flash') {
|
829
|
+
initVars.push('file=' + mejs.Utility.encodeUrl(mediaUrl));
|
830
|
+
} else {
|
831
|
+
initVars.push('file=' + mediaUrl);
|
832
|
+
}
|
833
|
+
}
|
834
|
+
if (options.enablePluginDebug) {
|
835
|
+
initVars.push('debug=true');
|
836
|
+
}
|
837
|
+
if (options.enablePluginSmoothing) {
|
838
|
+
initVars.push('smoothing=true');
|
839
|
+
}
|
840
|
+
if (controls) {
|
841
|
+
initVars.push('controls=true'); // shows controls in the plugin if desired
|
842
|
+
}
|
843
|
+
|
844
|
+
switch (pluginType) {
|
845
|
+
case 'silverlight':
|
846
|
+
container.innerHTML =
|
847
|
+
'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '">' +
|
848
|
+
'<param name="initParams" value="' + initVars.join(',') + '" />' +
|
849
|
+
'<param name="windowless" value="true" />' +
|
850
|
+
'<param name="background" value="black" />' +
|
851
|
+
'<param name="minRuntimeVersion" value="3.0.0.0" />' +
|
852
|
+
'<param name="autoUpgrade" value="true" />' +
|
853
|
+
'<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
|
854
|
+
'</object>';
|
855
|
+
break;
|
856
|
+
|
857
|
+
case 'flash':
|
858
|
+
|
859
|
+
if (mejs.MediaFeatures.isIE) {
|
860
|
+
specialIEContainer = document.createElement('div');
|
861
|
+
container.appendChild(specialIEContainer);
|
862
|
+
specialIEContainer.outerHTML =
|
863
|
+
'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
|
864
|
+
'id="' + pluginid + '" width="' + width + '" height="' + height + '">' +
|
865
|
+
'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
|
866
|
+
'<param name="flashvars" value="' + initVars.join('&') + '" />' +
|
867
|
+
'<param name="quality" value="high" />' +
|
868
|
+
'<param name="bgcolor" value="#000000" />' +
|
869
|
+
'<param name="wmode" value="transparent" />' +
|
870
|
+
'<param name="allowScriptAccess" value="always" />' +
|
871
|
+
'<param name="allowFullScreen" value="true" />' +
|
872
|
+
'</object>';
|
873
|
+
|
874
|
+
} else {
|
875
|
+
|
876
|
+
container.innerHTML =
|
877
|
+
'<embed id="' + pluginid + '" name="' + pluginid + '" ' +
|
878
|
+
'play="true" ' +
|
879
|
+
'loop="false" ' +
|
880
|
+
'quality="high" ' +
|
881
|
+
'bgcolor="#000000" ' +
|
882
|
+
'wmode="transparent" ' +
|
883
|
+
'allowScriptAccess="always" ' +
|
884
|
+
'allowFullScreen="true" ' +
|
885
|
+
'type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" ' +
|
886
|
+
'src="' + options.pluginPath + options.flashName + '" ' +
|
887
|
+
'flashvars="' + initVars.join('&') + '" ' +
|
888
|
+
'width="' + width + '" ' +
|
889
|
+
'height="' + height + '"></embed>';
|
890
|
+
}
|
891
|
+
break;
|
892
|
+
}
|
893
|
+
// hide original element
|
894
|
+
htmlMediaElement.style.display = 'none';
|
895
|
+
|
896
|
+
// FYI: options.success will be fired by the MediaPluginBridge
|
897
|
+
|
898
|
+
return pluginMediaElement;
|
899
|
+
},
|
900
|
+
|
901
|
+
updateNative: function(htmlMediaElement, options, autoplay, preload, playback) {
|
902
|
+
// add methods to video object to bring it into parity with Flash Object
|
903
|
+
for (var m in mejs.HtmlMediaElement) {
|
904
|
+
htmlMediaElement[m] = mejs.HtmlMediaElement[m];
|
905
|
+
}
|
906
|
+
|
907
|
+
/*
|
908
|
+
Chrome now supports preload="none"
|
909
|
+
if (mejs.MediaFeatures.isChrome) {
|
910
|
+
|
911
|
+
// special case to enforce preload attribute (Chrome doesn't respect this)
|
912
|
+
if (preload === 'none' && !autoplay) {
|
913
|
+
|
914
|
+
// forces the browser to stop loading (note: fails in IE9)
|
915
|
+
htmlMediaElement.src = '';
|
916
|
+
htmlMediaElement.load();
|
917
|
+
htmlMediaElement.canceledPreload = true;
|
918
|
+
|
919
|
+
htmlMediaElement.addEventListener('play',function() {
|
920
|
+
if (htmlMediaElement.canceledPreload) {
|
921
|
+
htmlMediaElement.src = playback.url;
|
922
|
+
htmlMediaElement.load();
|
923
|
+
htmlMediaElement.play();
|
924
|
+
htmlMediaElement.canceledPreload = false;
|
925
|
+
}
|
926
|
+
}, false);
|
927
|
+
// for some reason Chrome forgets how to autoplay sometimes.
|
928
|
+
} else if (autoplay) {
|
929
|
+
htmlMediaElement.load();
|
930
|
+
htmlMediaElement.play();
|
931
|
+
}
|
932
|
+
}
|
933
|
+
*/
|
934
|
+
|
935
|
+
// fire success code
|
936
|
+
options.success(htmlMediaElement, htmlMediaElement);
|
937
|
+
|
938
|
+
return htmlMediaElement;
|
939
|
+
}
|
940
|
+
};
|
941
|
+
|
942
|
+
window.mejs = mejs;
|
943
|
+
window.MediaElement = mejs.MediaElement;
|