2013-01-10 13:06:12 -08:00
/ * *
* @ fileoverview VideoJS - SWF - Custom Flash Player with HTML5 - ish API
* https : //github.com/zencoder/video-js-swf
* Not using setupTriggers . Using global onEvent func to distribute events
* /
2012-12-31 15:25:56 -08:00
/ * *
* HTML5 Media Controller - Wrapper for HTML5 Media API
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-31 15:25:56 -08:00
* @ param { Object = } options
* @ param { Function = } ready
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . Flash = function ( player , options , ready ) {
2012-12-31 15:25:56 -08:00
goog . base ( this , player , options , ready ) ;
2013-01-17 20:45:22 -05:00
var source = options [ 'source' ] ,
2012-12-31 15:25:56 -08:00
// Which element to embed in
2013-01-17 20:45:22 -05:00
parentEl = options [ 'parentEl' ] ,
2012-12-31 15:25:56 -08:00
// Create a temporary element to be replaced by swf object
2013-01-10 13:06:12 -08:00
placeHolder = this . el _ = vjs . createEl ( 'div' , { id : player . id ( ) + '_temp_flash' } ) ,
2012-12-31 15:25:56 -08:00
// Generate ID for swf object
2013-01-10 13:06:12 -08:00
objId = player . id ( ) + '_flash_api' ,
2012-12-31 15:25:56 -08:00
// Store player options in local var for optimization
2013-01-04 16:58:23 -08:00
// TODO: switch to using player methods instead of options
// e.g. player.autoplay();
2013-01-17 21:03:25 -05:00
playerOptions = player . options _ ,
2012-12-31 15:25:56 -08:00
// Merge default flashvars with ones passed in to init
2013-01-25 17:36:40 -08:00
flashVars = vjs . obj . merge ( {
2012-12-31 15:25:56 -08:00
// SWF Callback Functions
2013-01-10 13:06:12 -08:00
'readyFunction' : 'videojs.Flash.onReady' ,
'eventProxyFunction' : 'videojs.Flash.onEvent' ,
'errorEventProxyFunction' : 'videojs.Flash.onError' ,
2012-12-31 15:25:56 -08:00
// Player Settings
2013-01-04 16:58:23 -08:00
'autoplay' : playerOptions . autoplay ,
'preload' : playerOptions . preload ,
'loop' : playerOptions . loop ,
'muted' : playerOptions . muted
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
} , options [ 'flashVars' ] ) ,
2012-12-31 15:25:56 -08:00
// Merge default parames with ones passed in
2013-01-25 17:36:40 -08:00
params = vjs . obj . merge ( {
2013-01-10 13:06:12 -08:00
'wmode' : 'opaque' , // Opaque is needed to overlay controls, but can affect playback performance
'bgcolor' : '#000000' // Using bgcolor prevents a white flash when the object is loading
2013-01-04 16:58:23 -08:00
} , options [ 'params' ] ) ,
2012-12-31 15:25:56 -08:00
// Merge default attributes with ones passed in
2013-01-25 17:36:40 -08:00
attributes = vjs . obj . merge ( {
2013-01-04 16:58:23 -08:00
'id' : objId ,
'name' : objId , // Both ID and Name needed or swf to identifty itself
2012-12-31 15:25:56 -08:00
'class' : 'vjs-tech'
2013-01-04 16:58:23 -08:00
} , options [ 'attributes' ] )
2012-12-31 15:25:56 -08:00
;
// If source was supplied pass as a flash var.
if ( source ) {
2013-01-04 16:58:23 -08:00
flashVars [ 'src' ] = encodeURIComponent ( vjs . getAbsoluteURL ( source . src ) ) ;
2012-12-31 15:25:56 -08:00
}
// Add placeholder to player div
2013-01-04 16:58:23 -08:00
vjs . insertFirst ( placeHolder , parentEl ) ;
2012-12-31 15:25:56 -08:00
// Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
// This allows resetting the playhead when we catch the reload
2013-01-17 20:45:22 -05:00
if ( options [ 'startTime' ] ) {
2012-12-31 15:25:56 -08:00
this . ready ( function ( ) {
this . load ( ) ;
this . play ( ) ;
2013-01-17 20:45:22 -05:00
this . currentTime ( options [ 'startTime' ] ) ;
2012-12-31 15:25:56 -08:00
} ) ;
}
// Flash iFrame Mode
// In web browsers there are multiple instances where changing the parent element or visibility of a plugin causes the plugin to reload.
// - Firefox just about always. https://bugzilla.mozilla.org/show_bug.cgi?id=90268 (might be fixed by version 13)
// - Webkit when hiding the plugin
// - Webkit and Firefox when using requestFullScreen on a parent element
// Loading the flash plugin into a dynamically generated iFrame gets around most of these issues.
// Issues that remain include hiding the element and requestFullScreen in Firefox specifically
// There's on particularly annoying issue with this method which is that Firefox throws a security error on an offsite Flash object loaded into a dynamically created iFrame.
// Even though the iframe was inserted into a page on the web, Firefox + Flash considers it a local app trying to access an internet file.
// I tried mulitple ways of setting the iframe src attribute but couldn't find a src that worked well. Tried a real/fake source, in/out of domain.
// Also tried a method from stackoverflow that caused a security error in all browsers. http://stackoverflow.com/questions/2486901/how-to-set-document-domain-for-a-dynamically-generated-iframe
// In the end the solution I found to work was setting the iframe window.location.href right before doing a document.write of the Flash object.
// The only downside of this it seems to trigger another http request to the original page (no matter what's put in the href). Not sure why that is.
// NOTE (2012-01-29): Cannot get Firefox to load the remote hosted SWF into a dynamically created iFrame
// Firefox 9 throws a security error, unleess you call location.href right before doc.write.
// Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page.
// Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop.
2013-01-17 20:45:22 -05:00
if ( options [ 'iFrameMode' ] === true && ! vjs . IS _FIREFOX ) {
2012-12-31 15:25:56 -08:00
// Create iFrame with vjs-tech class so it's 100% width/height
2013-01-10 13:06:12 -08:00
var iFrm = vjs . createEl ( 'iframe' , {
'id' : objId + '_iframe' ,
'name' : objId + '_iframe' ,
'className' : 'vjs-tech' ,
'scrolling' : 'no' ,
2013-01-04 16:58:23 -08:00
'marginWidth' : 0 ,
'marginHeight' : 0 ,
'frameBorder' : 0
2012-12-31 15:25:56 -08:00
} ) ;
// Update ready function names in flash vars for iframe window
2013-01-10 13:06:12 -08:00
flashVars [ 'readyFunction' ] = 'ready' ;
flashVars [ 'eventProxyFunction' ] = 'events' ;
flashVars [ 'errorEventProxyFunction' ] = 'errors' ;
2012-12-31 15:25:56 -08:00
// Tried multiple methods to get this to work in all browsers
// Tried embedding the flash object in the page first, and then adding a place holder to the iframe, then replacing the placeholder with the page object.
// The goal here was to try to load the swf URL in the parent page first and hope that got around the firefox security error
2013-01-17 20:45:22 -05:00
// var newObj = vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
2012-12-31 15:25:56 -08:00
// (in onload)
2013-01-10 13:06:12 -08:00
// var temp = vjs.createEl('a', { id:'asdf', innerHTML: 'asdf' } );
2012-12-31 15:25:56 -08:00
// iDoc.body.appendChild(temp);
// Tried embedding the flash object through javascript in the iframe source.
// This works in webkit but still triggers the firefox security error
2013-01-17 20:45:22 -05:00
// iFrm.src = 'javascript: document.write('"+vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes)+"');";
2012-12-31 15:25:56 -08:00
// Tried an actual local iframe just to make sure that works, but it kills the easiness of the CDN version if you require the user to host an iframe
// We should add an option to host the iframe locally though, because it could help a lot of issues.
// iFrm.src = "iframe.html";
// Wait until iFrame has loaded to write into it.
2013-01-10 13:06:12 -08:00
vjs . on ( iFrm , 'load' , vjs . bind ( this , function ( ) {
2012-12-31 15:25:56 -08:00
2013-01-10 13:06:12 -08:00
var iDoc ,
iWin = iFrm . contentWindow ;
2012-12-31 15:25:56 -08:00
// The one working method I found was to use the iframe's document.write() to create the swf object
// This got around the security issue in all browsers except firefox.
2013-01-10 13:06:12 -08:00
// I did find a hack where if I call the iframe's window.location.href='', it would get around the security error
2012-12-31 15:25:56 -08:00
// However, the main page would look like it was loading indefinitely (URL bar loading spinner would never stop)
// Plus Firefox 3.6 didn't work no matter what I tried.
2013-01-10 13:06:12 -08:00
// if (vjs.USER_AGENT.match('Firefox')) {
// iWin.location.href = '';
2012-12-31 15:25:56 -08:00
// }
// Get the iFrame's document depending on what the browser supports
iDoc = iFrm . contentDocument ? iFrm . contentDocument : iFrm . contentWindow . document ;
// Tried ensuring both document domains were the same, but they already were, so that wasn't the issue.
// Even tried adding /. that was mentioned in a browser security writeup
2013-01-10 13:06:12 -08:00
// document.domain = document.domain+'/.';
// iDoc.domain = document.domain+'/.';
2012-12-31 15:25:56 -08:00
// Tried adding the object to the iframe doc's innerHTML. Security error in all browsers.
// iDoc.body.innerHTML = swfObjectHTML;
// Tried appending the object to the iframe doc's body. Security error in all browsers.
// iDoc.body.appendChild(swfObject);
// Using document.write actually got around the security error that browsers were throwing.
// Again, it's a dynamically generated (same domain) iframe, loading an external Flash swf.
// Not sure why that's a security issue, but apparently it is.
2013-01-04 16:58:23 -08:00
iDoc . write ( vjs . Flash . getEmbedCode ( options [ 'swf' ] , flashVars , params , attributes ) ) ;
2012-12-31 15:25:56 -08:00
// Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers
// So far no issues with swf ready event being called before it's set on the window.
2013-01-16 20:24:38 -05:00
iWin [ 'player' ] = this . player _ ;
2012-12-31 15:25:56 -08:00
// Create swf ready function for iFrame window
2013-01-16 20:24:38 -05:00
iWin [ 'ready' ] = vjs . bind ( this . player _ , function ( currSwf ) {
2012-12-31 15:25:56 -08:00
var el = iDoc . getElementById ( currSwf ) ,
player = this ,
tech = player . tech ;
// Update reference to playback technology element
2013-01-16 20:24:38 -05:00
tech . el _ = el ;
2012-12-31 15:25:56 -08:00
// Now that the element is ready, make a click on the swf play the video
2013-01-10 13:06:12 -08:00
vjs . on ( el , 'click' , tech . bind ( tech . onClick ) ) ;
2012-12-31 15:25:56 -08:00
// Make sure swf is actually ready. Sometimes the API isn't actually yet.
2013-01-04 16:58:23 -08:00
vjs . Flash . checkReady ( tech ) ;
2012-12-31 15:25:56 -08:00
} ) ;
// Create event listener for all swf events
2013-01-16 20:24:38 -05:00
iWin [ 'events' ] = vjs . bind ( this . player _ , function ( swfID , eventName ) {
2012-12-31 15:25:56 -08:00
var player = this ;
2013-01-10 13:06:12 -08:00
if ( player && player . techName === 'flash' ) {
2013-01-04 16:58:23 -08:00
player . trigger ( eventName ) ;
2012-12-31 15:25:56 -08:00
}
} ) ;
// Create error listener for all swf errors
2013-01-16 20:24:38 -05:00
iWin [ 'errors' ] = vjs . bind ( this . player _ , function ( swfID , eventName ) {
2013-01-10 13:06:12 -08:00
vjs . log ( 'Flash Error' , eventName ) ;
2012-12-31 15:25:56 -08:00
} ) ;
} ) ) ;
// Replace placeholder with iFrame (it will load now)
placeHolder . parentNode . replaceChild ( iFrm , placeHolder ) ;
// If not using iFrame mode, embed as normal object
} else {
2013-01-04 16:58:23 -08:00
vjs . Flash . embed ( options [ 'swf' ] , placeHolder , flashVars , params , attributes ) ;
2012-12-31 15:25:56 -08:00
}
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . Flash , vjs . MediaTechController ) ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . dispose = function ( ) {
goog . base ( this , 'dispose' ) ;
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . play = function ( ) {
this . el _ . vjs _play ( ) ;
2013-01-10 13:06:12 -08:00
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . pause = function ( ) {
this . el _ . vjs _pause ( ) ;
2013-01-10 13:06:12 -08:00
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . src = function ( src ) {
// Make sure source URL is abosolute.
src = vjs . getAbsoluteURL ( src ) ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
this . el _ . vjs _src ( src ) ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
// Currently the SWF doesn't autoplay if you load a source later.
// e.g. Load player w/ no source, wait 2s, set src.
2013-01-16 20:24:38 -05:00
if ( this . player _ . autoplay ( ) ) {
2013-01-04 16:58:23 -08:00
var tech = this ;
setTimeout ( function ( ) { tech . play ( ) ; } , 0 ) ;
}
2013-01-10 13:06:12 -08:00
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . load = function ( ) {
this . el _ . vjs _load ( ) ;
2013-01-10 13:06:12 -08:00
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . poster = function ( ) {
2013-01-10 13:06:12 -08:00
this . el _ . vjs _getProperty ( 'poster' ) ;
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . buffered = function ( ) {
2013-01-10 13:06:12 -08:00
return vjs . createTimeRange ( 0 , this . el _ . vjs _getProperty ( 'buffered' ) ) ;
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . supportsFullScreen = function ( ) {
return false ; // Flash does not allow fullscreen through javascript
2013-01-10 13:06:12 -08:00
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . prototype . enterFullScreen = function ( ) {
return false ;
2013-01-10 13:06:12 -08:00
} ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
// Create setters and getters for attributes
var api = vjs . Flash . prototype ,
2013-01-10 13:06:12 -08:00
readWrite = 'preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted' . split ( ',' ) ,
readOnly = 'error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks' . split ( ',' ) ;
2013-01-04 16:58:23 -08:00
// Overridden: buffered
2013-01-10 13:06:12 -08:00
/ * *
* @ this { * }
* /
var createSetter = function ( attr ) {
var attrUpper = attr . charAt ( 0 ) . toUpperCase ( ) + attr . slice ( 1 ) ;
api [ 'set' + attrUpper ] = function ( val ) { return this . el _ . vjs _setProperty ( attr , val ) ; } ;
} ;
/ * *
* @ this { * }
* /
var createGetter = function ( attr ) {
api [ attr ] = function ( ) { return this . el _ . vjs _getProperty ( attr ) ; } ;
} ;
2012-12-31 15:25:56 -08:00
2013-01-25 17:36:40 -08:00
( function ( ) {
var i ;
// Create getter and setters for all read/write attributes
for ( i = 0 ; i < readWrite . length ; i ++ ) {
createGetter ( readWrite [ i ] ) ;
createSetter ( readWrite [ i ] ) ;
}
2012-12-31 15:25:56 -08:00
2013-01-25 17:36:40 -08:00
// Create getters for read-only attributes
for ( i = 0 ; i < readOnly . length ; i ++ ) {
createGetter ( readOnly [ i ] ) ;
}
} ) ( ) ;
2012-12-31 15:25:56 -08:00
/* Flash Support Testing -------------------------------------------------------- */
2013-01-04 16:58:23 -08:00
vjs . Flash . isSupported = function ( ) {
return vjs . Flash . version ( ) [ 0 ] >= 10 ;
2013-01-10 13:06:12 -08:00
// return swfobject.hasFlashPlayerVersion('10');
2012-12-31 15:25:56 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . Flash . canPlaySource = function ( srcObj ) {
2013-04-09 13:18:55 -07:00
if ( srcObj . type in vjs . Flash . formats ) { return 'maybe' ; }
2012-12-31 15:25:56 -08:00
} ;
2013-04-09 13:18:55 -07:00
vjs . Flash . formats = {
'video/flv' : 'FLV' ,
'video/x-flv' : 'FLV' ,
'video/mp4' : 'MP4' ,
'video/m4v' : 'MP4'
2012-12-31 15:25:56 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . Flash [ 'onReady' ] = function ( currSwf ) {
var el = vjs . el ( currSwf ) ;
2012-12-31 15:25:56 -08:00
// Get player from box
// On firefox reloads, el might already have a player
2013-01-16 20:24:38 -05:00
var player = el [ 'player' ] || el . parentNode [ 'player' ] ,
2012-12-31 15:25:56 -08:00
tech = player . tech ;
// Reference player on tech element
2013-01-16 20:24:38 -05:00
el [ 'player' ] = player ;
2012-12-31 15:25:56 -08:00
// Update reference to playback technology element
2013-01-04 16:58:23 -08:00
tech . el _ = el ;
2012-12-31 15:25:56 -08:00
// Now that the element is ready, make a click on the swf play the video
2013-01-10 13:06:12 -08:00
tech . on ( 'click' , tech . onClick ) ;
2012-12-31 15:25:56 -08:00
2013-01-04 16:58:23 -08:00
vjs . Flash . checkReady ( tech ) ;
2012-12-31 15:25:56 -08:00
} ;
// The SWF isn't alwasy ready when it says it is. Sometimes the API functions still need to be added to the object.
// If it's not ready, we set a timeout to check again shortly.
2013-01-04 16:58:23 -08:00
vjs . Flash . checkReady = function ( tech ) {
2012-12-31 15:25:56 -08:00
// Check if API property exists
2013-01-10 13:06:12 -08:00
if ( tech . el ( ) . vjs _getProperty ) {
2012-12-31 15:25:56 -08:00
// If so, tell tech it's ready
tech . triggerReady ( ) ;
// Otherwise wait longer.
} else {
setTimeout ( function ( ) {
2013-01-04 16:58:23 -08:00
vjs . Flash . checkReady ( tech ) ;
2012-12-31 15:25:56 -08:00
} , 50 ) ;
}
} ;
// Trigger events from the swf on the player
2013-01-04 16:58:23 -08:00
vjs . Flash [ 'onEvent' ] = function ( swfID , eventName ) {
2013-01-16 20:24:38 -05:00
var player = vjs . el ( swfID ) [ 'player' ] ;
2013-01-04 16:58:23 -08:00
player . trigger ( eventName ) ;
2012-12-31 15:25:56 -08:00
} ;
// Log errors from the swf
2013-01-04 16:58:23 -08:00
vjs . Flash [ 'onError' ] = function ( swfID , err ) {
2013-01-16 20:24:38 -05:00
var player = vjs . el ( swfID ) [ 'player' ] ;
2013-01-10 13:06:12 -08:00
player . trigger ( 'error' ) ;
vjs . log ( 'Flash Error' , err , swfID ) ;
2012-12-31 15:25:56 -08:00
} ;
// Flash Version Check
2013-01-04 16:58:23 -08:00
vjs . Flash . version = function ( ) {
2012-12-31 15:25:56 -08:00
var version = '0,0,0' ;
// IE
try {
2013-01-10 13:06:12 -08:00
version = new window . ActiveXObject ( 'ShockwaveFlash.ShockwaveFlash' ) . GetVariable ( '$version' ) . replace ( /\D+/g , ',' ) . match ( /^,?(.+),?$/ ) [ 1 ] ;
2012-12-31 15:25:56 -08:00
// other browsers
} catch ( e ) {
try {
2013-01-10 13:06:12 -08:00
if ( navigator . mimeTypes [ 'application/x-shockwave-flash' ] . enabledPlugin ) {
version = ( navigator . plugins [ 'Shockwave Flash 2.0' ] || navigator . plugins [ 'Shockwave Flash' ] ) . description . replace ( /\D+/g , ',' ) . match ( /^,?(.+),?$/ ) [ 1 ] ;
2012-12-31 15:25:56 -08:00
}
2013-01-10 13:06:12 -08:00
} catch ( err ) { }
2012-12-31 15:25:56 -08:00
}
2013-01-10 13:06:12 -08:00
return version . split ( ',' ) ;
2012-12-31 15:25:56 -08:00
} ;
// Flash embedding method. Only used in non-iframe mode
2013-01-04 16:58:23 -08:00
vjs . Flash . embed = function ( swf , placeHolder , flashVars , params , attributes ) {
var code = vjs . Flash . getEmbedCode ( swf , flashVars , params , attributes ) ,
2012-12-31 15:25:56 -08:00
// Get element by embedding code and retrieving created element
2013-01-10 13:06:12 -08:00
obj = vjs . createEl ( 'div' , { innerHTML : code } ) . childNodes [ 0 ] ,
2012-12-31 15:25:56 -08:00
par = placeHolder . parentNode
;
placeHolder . parentNode . replaceChild ( obj , placeHolder ) ;
// IE6 seems to have an issue where it won't initialize the swf object after injecting it.
2013-01-10 13:06:12 -08:00
// This is a dumb fix
var newObj = par . childNodes [ 0 ] ;
setTimeout ( function ( ) {
newObj . style . display = 'block' ;
} , 1000 ) ;
2012-12-31 15:25:56 -08:00
return obj ;
} ;
2013-01-04 16:58:23 -08:00
vjs . Flash . getEmbedCode = function ( swf , flashVars , params , attributes ) {
2012-12-31 15:25:56 -08:00
var objTag = '<object type="application/x-shockwave-flash"' ,
flashVarsString = '' ,
paramsString = '' ,
attrsString = '' ;
// Convert flash vars to string
if ( flashVars ) {
2013-01-25 17:36:40 -08:00
vjs . obj . each ( flashVars , function ( key , val ) {
2013-01-10 13:06:12 -08:00
flashVarsString += ( key + '=' + val + '&' ) ;
2012-12-31 15:25:56 -08:00
} ) ;
}
// Add swf, flashVars, and other default params
2013-01-25 17:36:40 -08:00
params = vjs . obj . merge ( {
2013-01-04 16:58:23 -08:00
'movie' : swf ,
'flashvars' : flashVarsString ,
2013-01-10 13:06:12 -08:00
'allowScriptAccess' : 'always' , // Required to talk to swf
'allowNetworking' : 'all' // All should be default, but having security issues.
2012-12-31 15:25:56 -08:00
} , params ) ;
// Create param tags string
2013-01-25 17:36:40 -08:00
vjs . obj . each ( params , function ( key , val ) {
2012-12-31 15:25:56 -08:00
paramsString += '<param name="' + key + '" value="' + val + '" />' ;
} ) ;
2013-01-25 17:36:40 -08:00
attributes = vjs . obj . merge ( {
2012-12-31 15:25:56 -08:00
// Add swf to attributes (need both for IE and Others to work)
2013-01-04 16:58:23 -08:00
'data' : swf ,
2012-12-31 15:25:56 -08:00
// Default to 100% width/height
2013-01-10 13:06:12 -08:00
'width' : '100%' ,
'height' : '100%'
2012-12-31 15:25:56 -08:00
} , attributes ) ;
// Create Attributes string
2013-01-25 17:36:40 -08:00
vjs . obj . each ( attributes , function ( key , val ) {
2012-12-31 15:25:56 -08:00
attrsString += ( key + '="' + val + '" ' ) ;
} ) ;
return objTag + attrsString + '>' + paramsString + '</object>' ;
} ;