2011-11-29 11:40:05 -08:00
/ * P l a y b a c k T e c h n o l o g y - B a s e c l a s s f o r p l a y b a c k t e c h n o l o g i e s
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
_V _ . PlaybackTech = _V _ . Component . extend ( {
init : function ( player , options ) {
// this._super(player, options);
// Make playback element clickable
// _V_.addEvent(this.el, "click", _V_.proxy(this, _V_.PlayToggle.prototype.onClick));
2012-01-05 23:25:09 -08:00
// this.addEvent("click", this.proxy(this.onClick));
2011-11-29 11:40:05 -08:00
// player.triggerEvent("techready");
2012-01-05 23:25:09 -08:00
} ,
2012-01-02 13:02:04 -08:00
// destroy: function(){},
2011-12-07 22:02:40 -08:00
// createElement: function(){},
2012-01-05 23:25:09 -08:00
onClick : function ( ) {
if ( this . player . options . controls ) {
_V _ . PlayToggle . prototype . onClick . call ( this ) ;
}
}
2011-11-29 11:40:05 -08:00
} ) ;
2011-12-07 22:02:40 -08:00
// Create placeholder methods for each that warn when a method isn't supported by the current playback technology
2011-12-01 16:48:06 -08:00
_V _ . apiMethods = "play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted" . split ( "," ) ;
2011-11-29 11:40:05 -08:00
_V _ . each ( _V _ . apiMethods , function ( methodName ) {
_V _ . PlaybackTech . prototype [ methodName ] = function ( ) {
throw new Error ( "The '" + method + "' method is not available on the playback technology's API" ) ;
}
} ) ;
/ * H T M L 5 P l a y b a c k T e c h n o l o g y - W r a p p e r f o r H T M L 5 M e d i a A P I
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2011-12-07 21:03:12 -08:00
_V _ . html5 = _V _ . PlaybackTech . extend ( {
2011-11-29 11:40:05 -08:00
2011-12-01 15:47:12 -08:00
init : function ( player , options , ready ) {
2011-11-29 11:40:05 -08:00
this . player = player ;
this . el = this . createElement ( ) ;
2011-12-01 15:47:12 -08:00
this . ready ( ready ) ;
2012-01-05 23:25:09 -08:00
this . addEvent ( "click" , this . proxy ( this . onClick ) ) ;
2011-11-29 11:40:05 -08:00
var source = options . source ;
2011-12-01 15:47:12 -08:00
// If the element source is already set, we may have missed the loadstart event, and want to trigger it.
// We don't want to set the source again and interrupt playback.
if ( source && this . el . currentSrc == source . src ) {
2011-11-29 11:40:05 -08:00
player . triggerEvent ( "loadstart" ) ;
2011-12-01 15:47:12 -08:00
// Otherwise set the source if one was provided.
} else if ( source ) {
this . el . src = source . src ;
2011-11-29 11:40:05 -08:00
}
2011-12-01 15:47:12 -08:00
// Chrome and Safari both have issues with autoplay.
// In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
// In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
// This fixes both issues. Need to wait for API, so it updates displays correctly
player . ready ( function ( ) {
2011-11-29 11:40:05 -08:00
if ( this . options . autoplay && this . paused ( ) ) {
2011-12-01 15:47:12 -08:00
this . tag . poster = null ; // Chrome Fix. Fixed in Chrome v16.
2011-11-29 11:40:05 -08:00
this . play ( ) ;
}
} ) ;
2012-01-02 13:02:04 -08:00
this . setupTriggers ( ) ;
2011-12-01 15:47:12 -08:00
this . triggerReady ( ) ;
2011-11-29 11:40:05 -08:00
} ,
2012-01-20 17:34:18 -08:00
2012-01-02 13:02:04 -08:00
destroy : function ( ) {
this . player . tag = false ;
2012-01-05 23:25:09 -08:00
this . removeTriggers ( ) ;
2012-01-02 13:02:04 -08:00
this . el . parentNode . removeChild ( this . el ) ;
} ,
2011-11-29 11:40:05 -08:00
createElement : function ( ) {
2011-12-07 21:03:12 -08:00
var html5 = _V _ . html5 ,
2011-11-30 13:06:32 -08:00
player = this . player ,
2011-11-29 11:40:05 -08:00
2012-01-02 13:02:04 -08:00
// If possible, reuse original tag for HTML5 playback technology element
2011-11-30 13:06:32 -08:00
el = player . tag ,
newEl ;
2011-11-29 11:40:05 -08:00
// Check if this browser supports moving the element into the box.
// On the iPhone video will break if you move the element,
// So we have to create a brand new element.
2012-01-05 23:25:09 -08:00
if ( ! el || this . support . movingElementInDOM === false ) {
2012-01-02 13:02:04 -08:00
// If the original tag is still there, remove it.
2012-01-20 17:34:18 -08:00
if ( el ) {
2012-01-02 13:02:04 -08:00
player . el . removeChild ( el ) ;
}
2011-11-30 13:06:32 -08:00
newEl = _V _ . createElement ( "video" , {
2012-01-02 13:02:04 -08:00
id : el . id || player . el . id + "_html5_api" ,
className : el . className || "vjs-tech"
2011-11-29 11:40:05 -08:00
} ) ;
el = newEl ;
2011-12-01 15:47:12 -08:00
_V _ . insertFirst ( el , player . el ) ;
2011-11-29 11:40:05 -08:00
}
// Update tag settings, in case they were overridden
2012-01-02 16:57:17 -08:00
_V _ . each ( [ "autoplay" , "preload" , "loop" , "muted" ] , function ( attr ) { // ,"poster"
2011-11-30 13:06:32 -08:00
el [ attr ] = player . options [ attr ] ;
2011-11-29 11:40:05 -08:00
} , this ) ;
return el ;
} ,
2012-01-05 23:25:09 -08:00
// Make video events trigger player events
// May seem verbose here, but makes other APIs possible.
2011-11-29 11:40:05 -08:00
setupTriggers : function ( ) {
2012-01-05 23:25:09 -08:00
_V _ . each . call ( this , _V _ . html5 . events , function ( type ) {
_V _ . addEvent ( this . el , type , _V _ . proxy ( this . player , this . eventHandler ) ) ;
} ) ;
} ,
removeTriggers : function ( ) {
_V _ . each . call ( this , _V _ . html5 . events , function ( type ) {
_V _ . removeEvent ( this . el , type , _V _ . proxy ( this . player , this . eventHandler ) ) ;
} ) ;
} ,
eventHandler : function ( e ) {
e . stopPropagation ( ) ;
this . triggerEvent ( e ) ;
2011-11-29 11:40:05 -08:00
} ,
play : function ( ) { this . el . play ( ) ; } ,
pause : function ( ) { this . el . pause ( ) ; } ,
paused : function ( ) { return this . el . paused ; } ,
currentTime : function ( ) { return this . el . currentTime ; } ,
setCurrentTime : function ( seconds ) {
2011-12-05 11:28:18 -08:00
try {
this . el . currentTime = seconds ;
} catch ( e ) {
_V _ . log ( e , "Video isn't ready. (VideoJS)" ) ;
2011-11-29 11:40:05 -08:00
// this.warning(VideoJS.warnings.videoNotReady);
}
} ,
duration : function ( ) { return this . el . duration || 0 ; } ,
buffered : function ( ) { return this . el . buffered ; } ,
volume : function ( ) { return this . el . volume ; } ,
setVolume : function ( percentAsDecimal ) { this . el . volume = percentAsDecimal ; } ,
muted : function ( ) { return this . el . muted ; } ,
setMuted : function ( muted ) { this . el . muted = muted } ,
width : function ( ) { return this . el . offsetWidth ; } ,
height : function ( ) { return this . el . offsetHeight ; } ,
supportsFullScreen : function ( ) {
2011-12-01 16:29:52 -08:00
if ( typeof this . el . webkitEnterFullScreen == 'function' ) {
2011-12-07 22:02:40 -08:00
2011-11-29 11:40:05 -08:00
// Seems to be broken in Chromium/Chrome && Safari in Leopard
if ( ! navigator . userAgent . match ( "Chrome" ) && ! navigator . userAgent . match ( "Mac OS X 10.5" ) ) {
return true ;
}
2011-12-07 22:02:40 -08:00
}
2012-01-05 23:25:09 -08:00
return false ;
2011-11-29 11:40:05 -08:00
} ,
2012-01-05 23:25:09 -08:00
2011-11-29 11:40:05 -08:00
enterFullScreen : function ( ) {
2011-12-01 15:24:34 -08:00
try {
this . el . webkitEnterFullScreen ( ) ;
} catch ( e ) {
if ( e . code == 11 ) {
// this.warning(VideoJS.warnings.videoNotReady);
_V _ . log ( "VideoJS: Video not ready." )
}
2011-11-29 11:40:05 -08:00
}
} ,
src : function ( src ) { this . el . src = src ; } ,
load : function ( ) { this . el . load ( ) ; } ,
currentSrc : function ( ) { return this . el . currentSrc ; } ,
preload : function ( ) { return this . el . preload ; } ,
setPreload : function ( val ) { this . el . preload = val ; } ,
autoplay : function ( ) { return this . el . autoplay ; } ,
setAutoplay : function ( val ) { this . el . autoplay = val ; } ,
loop : function ( ) { return this . el . loop ; } ,
setLoop : function ( val ) { this . el . loop = val ; } ,
error : function ( ) { return this . el . error ; } ,
2012-01-20 17:42:38 -08:00
// networkState: function(){ return this.el.networkState; },
// readyState: function(){ return this.el.readyState; },
2011-11-29 11:40:05 -08:00
seeking : function ( ) { return this . el . seeking ; } ,
2012-01-20 17:42:38 -08:00
// initialTime: function(){ return this.el.initialTime; },
// startOffsetTime: function(){ return this.el.startOffsetTime; },
// played: function(){ return this.el.played; },
// seekable: function(){ return this.el.seekable; },
2011-11-29 11:40:05 -08:00
ended : function ( ) { return this . el . ended ; } ,
2012-01-20 17:42:38 -08:00
// videoTracks: function(){ return this.el.videoTracks; },
// audioTracks: function(){ return this.el.audioTracks; },
// videoWidth: function(){ return this.el.videoWidth; },
// videoHeight: function(){ return this.el.videoHeight; },
// textTracks: function(){ return this.el.textTracks; },
// defaultPlaybackRate: function(){ return this.el.defaultPlaybackRate; },
// playbackRate: function(){ return this.el.playbackRate; },
// mediaGroup: function(){ return this.el.mediaGroup; },
// controller: function(){ return this.el.controller; },
2011-11-29 11:40:05 -08:00
controls : function ( ) { return this . player . options . controls ; } ,
defaultMuted : function ( ) { return this . el . defaultMuted ; }
} ) ;
/* HTML5 Support Testing -------------------------------------------------------- */
2011-12-07 21:03:12 -08:00
_V _ . html5 . isSupported = function ( ) {
2011-11-29 11:40:05 -08:00
return ! ! document . createElement ( "video" ) . canPlayType ;
} ;
2011-12-07 21:03:12 -08:00
_V _ . html5 . canPlaySource = function ( srcObj ) {
2011-12-01 15:47:12 -08:00
return ! ! document . createElement ( "video" ) . canPlayType ( srcObj . type ) ;
2011-11-29 11:40:05 -08:00
// TODO: Check Type
// If no Type, check ext
// Check Media Type
} ;
// List of all HTML5 events (various uses).
2011-12-07 21:03:12 -08:00
_V _ . html5 . events = "loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange" . split ( "," ) ;
2011-11-29 11:40:05 -08:00
/* HTML5 Device Fixes ---------------------------------------------------------- */
2012-01-05 23:25:09 -08:00
_V _ . html5 . prototype . support = {
2012-01-20 17:34:18 -08:00
2012-01-05 23:25:09 -08:00
// Support for tech specific full screen. (webkitEnterFullScreen, not requestFullscreen)
// http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLVideoElementClassReference/HTMLVideoElement/HTMLVideoElement.html
// Seems to be broken in Chromium/Chrome && Safari in Leopard
fullscreen : ( typeof _V _ . testVid . webkitEnterFullScreen !== undefined ) ? ( ! _V _ . ua . match ( "Chrome" ) && ! _V _ . ua . match ( "Mac OS X 10.5" ) ? true : false ) : false ,
// In iOS, if you move a video element in the DOM, it breaks video playback.
movingElementInDOM : ! _V _ . isIOS ( )
} ;
2011-11-29 11:40:05 -08:00
// Android
if ( _V _ . isAndroid ( ) ) {
// Override Android 2.2 and less canPlayType method which is broken
if ( _V _ . androidVersion ( ) < 3 ) {
document . createElement ( "video" ) . constructor . prototype . canPlayType = function ( type ) {
return ( type && type . toLowerCase ( ) . indexOf ( "video/mp4" ) != - 1 ) ? "maybe" : "" ;
} ;
}
}
2012-01-28 18:56:28 -08:00
/* VideoJS-SWF - Custom Flash Player with HTML5-ish API - https:/ / github . com / zencoder / video - js - swf
2011-11-29 11:40:05 -08:00
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2011-12-07 21:03:12 -08:00
_V _ . flash = _V _ . PlaybackTech . extend ( {
2011-11-29 11:40:05 -08:00
init : function ( player , options ) {
this . player = player ;
2012-01-02 13:02:04 -08:00
var source = options . source ,
2012-01-28 18:56:28 -08:00
// Which element to embed in
2012-01-02 13:02:04 -08:00
parentEl = options . parentEl ,
2012-01-28 18:56:28 -08:00
// Create a temporary element to be replaced by swf object
2012-01-02 13:02:04 -08:00
placeHolder = this . el = _V _ . createElement ( "div" , { id : parentEl . id + "_temp_flash" } ) ,
2012-01-28 18:56:28 -08:00
// Generate ID for swf object
2011-12-07 21:03:12 -08:00
objId = player . el . id + "_flash_api" ,
2011-11-29 11:40:05 -08:00
2012-01-28 18:56:28 -08:00
// Store player options in local var for optimization
playerOptions = player . options ,
// Merge default flashvars with ones passed in to init
2011-12-07 21:29:21 -08:00
flashVars = _V _ . merge ( {
// SWF Callback Functions
2012-01-20 17:42:38 -08:00
readyFunction : "_V_.flash.onReady" ,
eventProxyFunction : "_V_.flash.onEvent" ,
errorEventProxyFunction : "_V_.flash.onError" ,
2011-12-07 21:29:21 -08:00
// Player Settings
2011-11-30 13:06:32 -08:00
autoplay : playerOptions . autoplay ,
preload : playerOptions . preload ,
loop : playerOptions . loop ,
2011-12-01 15:47:12 -08:00
muted : playerOptions . muted
2011-12-07 21:29:21 -08:00
} , options . flashVars ) ,
2011-11-29 11:40:05 -08:00
2012-01-28 18:56:28 -08:00
// Merge default parames with ones passed in
2011-12-07 22:02:40 -08:00
params = _V _ . merge ( {
2012-01-28 18:56:28 -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
2011-12-07 22:02:40 -08:00
} , options . params ) ,
2011-11-29 11:40:05 -08:00
2012-01-28 18:56:28 -08:00
// Merge default attributes with ones passed in
2011-12-07 22:02:40 -08:00
attributes = _V _ . merge ( {
2011-11-29 11:40:05 -08:00
id : objId ,
2012-01-28 18:56:28 -08:00
name : objId , // Both ID and Name needed or swf to identifty itself
2011-11-29 11:40:05 -08:00
'class' : 'vjs-tech'
2012-01-28 18:56:28 -08:00
} , options . attributes )
;
2011-11-29 11:40:05 -08:00
2011-11-30 13:06:32 -08:00
// If source was supplied pass as a flash var.
if ( source ) {
2012-01-18 23:24:02 +09:00
flashVars . src = encodeURIComponent ( source . src ) ;
2011-11-30 13:06:32 -08:00
}
2012-01-28 18:56:28 -08:00
// Add placeholder to player div
2012-01-02 13:02:04 -08:00
_V _ . insertFirst ( placeHolder , parentEl ) ;
2011-11-29 11:40:05 -08:00
2012-01-28 18:56:28 -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
2012-01-05 23:25:09 -08:00
if ( options . startTime ) {
this . ready ( function ( ) {
this . load ( ) ;
this . play ( ) ;
this . currentTime ( options . startTime ) ;
} ) ;
}
2012-01-20 17:34:18 -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.
2012-01-29 20:03:44 -08:00
// 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.
2012-01-29 20:04:58 -08:00
if ( options . iFrameMode == true && ! _V _ . isFF ) {
2012-01-20 17:34:18 -08:00
// Create iFrame with vjs-tech class so it's 100% width/height
var iFrm = _V _ . createElement ( "iframe" , {
id : objId + "_iframe" ,
2012-01-29 20:03:44 -08:00
name : objId + "_iframe" ,
2012-01-20 17:34:18 -08:00
className : "vjs-tech" ,
scrolling : "no" ,
marginWidth : 0 ,
marginHeight : 0 ,
frameBorder : 0
} ) ;
2012-01-29 20:03:44 -08:00
// Update ready function names in flash vars for iframe window
flashVars . readyFunction = "ready" ;
flashVars . eventProxyFunction = "events" ;
flashVars . errorEventProxyFunction = "errors" ;
// 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
// var newObj = _V_.flash.embed(options.swf, placeHolder, flashVars, params, attributes);
// (in onload)
// var temp = _V_.createElement("a", { id:"asdf", innerHTML: "asdf" } );
// 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
// iFrm.src = "javascript: document.write('"+_V_.flash.getEmbedCode(options.swf, flashVars, params, attributes)+"');";
// 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";
2012-01-20 17:34:18 -08:00
// Wait until iFrame has loaded to write into it.
_V _ . addEvent ( iFrm , "load" , _V _ . proxy ( this , function ( ) {
var iDoc , objTag , swfLoc ,
iWin = iFrm . contentWindow ,
varString = "" ;
2012-01-29 20:03:44 -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.
// I did find a hack where if I call the iframe's window.location.href="", it would get around the security error
// 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.
// if (_V_.ua.match("Firefox")) {
// iWin.location.href = "";
// }
2012-01-20 17:34:18 -08:00
2012-01-28 18:56:28 -08:00
// Get the iFrame's document depending on what the browser supports
2012-01-20 17:34:18 -08:00
iDoc = iFrm . contentDocument ? iFrm . contentDocument : iFrm . contentWindow . document ;
2012-01-29 20:03:44 -08:00
// 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
// document.domain = document.domain+"/.";
// iDoc.domain = document.domain+"/.";
// 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);
2012-01-20 17:34:18 -08:00
2012-01-29 20:03:44 -08:00
// 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.
2012-01-28 18:56:28 -08:00
iDoc . write ( _V _ . flash . getEmbedCode ( options . swf , flashVars , params , attributes ) ) ;
2012-01-20 17:34:18 -08:00
2012-01-28 18:56:28 -08:00
// Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers
2012-01-20 17:34:18 -08:00
// So far no issues with swf ready event being called before it's set on the window.
iWin . player = this . player ;
2012-01-28 18:56:28 -08:00
// Create swf ready function for iFrame window
2012-01-20 17:34:18 -08:00
iWin . ready = _V _ . proxy ( this . player , function ( currSwf ) {
var el = iDoc . getElementById ( currSwf ) ,
player = this ,
tech = player . tech ;
// Update reference to playback technology element
tech . el = el ;
// Now that the element is ready, make a click on the swf play the video
2012-01-28 18:56:28 -08:00
_V _ . addEvent ( el , "click" , tech . proxy ( tech . onClick ) ) ;
2012-01-20 17:34:18 -08:00
2012-01-28 18:56:28 -08:00
// Make sure swf is actually ready. Sometimes the API isn't actually yet.
2012-01-20 17:34:18 -08:00
_V _ . flash . checkReady ( tech ) ;
} ) ;
2012-01-28 18:56:28 -08:00
// Create event listener for all swf events
2012-01-20 17:34:18 -08:00
iWin . events = _V _ . proxy ( this . player , function ( swfID , eventName , other ) {
2012-01-29 20:03:44 -08:00
var player = this ;
if ( player && player . techName == "flash" ) {
player . triggerEvent ( eventName ) ;
2012-01-20 17:34:18 -08:00
}
} ) ;
2012-01-28 18:56:28 -08:00
// Create error listener for all swf errors
2012-01-20 17:34:18 -08:00
iWin . errors = _V _ . proxy ( this . player , function ( swfID , eventName ) {
_V _ . log ( "Flash Error" , eventName ) ;
} ) ;
} ) ) ;
2012-01-29 20:03:44 -08:00
// Replace placeholder with iFrame (it will load now)
2012-01-20 17:34:18 -08:00
placeHolder . parentNode . replaceChild ( iFrm , placeHolder ) ;
2012-01-28 18:56:28 -08:00
// If not using iFrame mode, embed as normal object
2012-01-20 17:34:18 -08:00
} else {
2012-01-23 14:55:06 -08:00
_V _ . flash . embed ( options . swf , placeHolder , flashVars , params , attributes ) ;
2012-01-20 17:34:18 -08:00
}
2011-11-29 11:40:05 -08:00
} ,
2012-01-20 17:34:18 -08:00
2012-01-02 13:02:04 -08:00
destroy : function ( ) {
this . el . parentNode . removeChild ( this . el ) ;
2011-11-29 11:40:05 -08:00
} ,
2012-01-20 17:42:38 -08:00
// setupTriggers: function(){}, // Using global onEvent func to distribute events
2012-01-02 13:02:04 -08:00
2011-11-29 11:40:05 -08:00
play : function ( ) { this . el . vjs _play ( ) ; } ,
pause : function ( ) { this . el . vjs _pause ( ) ; } ,
2011-12-07 22:02:40 -08:00
src : function ( src ) {
2011-12-01 15:47:12 -08:00
this . el . vjs _src ( src ) ;
// Currently the SWF doesn't autoplay if you load a source later.
// e.g. Load player w/ no source, wait 2s, set src.
if ( this . player . autoplay ) {
2011-12-01 16:48:06 -08:00
var tech = this ;
setTimeout ( function ( ) { tech . play ( ) ; } , 0 ) ;
2011-12-01 15:47:12 -08:00
}
} ,
2011-11-30 14:05:28 -08:00
load : function ( ) { this . el . vjs _load ( ) ; } ,
2011-11-29 11:40:05 -08:00
poster : function ( ) { this . el . vjs _getProperty ( "poster" ) ; } ,
buffered : function ( ) {
2012-01-09 12:18:08 -08:00
return _V _ . createTimeRange ( 0 , this . el . vjs _getProperty ( "buffered" ) ) ;
2011-11-29 11:40:05 -08:00
} ,
supportsFullScreen : function ( ) {
return false ; // Flash does not allow fullscreen through javascript
} ,
2011-12-07 22:02:40 -08:00
enterFullScreen : function ( ) {
return false ;
2011-11-29 11:40:05 -08:00
}
} ) ;
// Create setters and getters for attributes
( function ( ) {
2012-01-28 18:56:28 -08:00
2011-12-07 21:03:12 -08:00
var api = _V _ . flash . prototype ,
2011-11-30 13:06:32 -08:00
readWrite = "preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted" . split ( "," ) ,
2011-11-29 11:40:05 -08:00
readOnly = "error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks" . split ( "," ) ,
callOnly = "load,play,pause" . split ( "," ) ;
// Overridden: buffered
createSetter = function ( attr ) {
var attrUpper = attr . charAt ( 0 ) . toUpperCase ( ) + attr . slice ( 1 ) ;
api [ "set" + attrUpper ] = function ( val ) { return this . el . vjs _setProperty ( attr , val ) ; } ;
} ,
createGetter = function ( attr ) {
api [ attr ] = function ( ) { return this . el . vjs _getProperty ( attr ) ; } ;
2012-01-28 18:56:28 -08:00
}
;
2011-11-29 11:40:05 -08:00
// Create getter and setters for all read/write attributes
_V _ . each ( readWrite , function ( attr ) {
createGetter ( attr ) ;
createSetter ( attr ) ;
} ) ;
// Create getters for read-only attributes
_V _ . each ( readOnly , function ( attr ) {
createGetter ( attr ) ;
} ) ;
2012-01-28 18:56:28 -08:00
2011-11-29 11:40:05 -08:00
} ) ( ) ;
/* Flash Support Testing -------------------------------------------------------- */
2011-12-07 21:03:12 -08:00
_V _ . flash . isSupported = function ( ) {
2012-01-30 10:58:26 -08:00
return _V _ . flash . version ( ) [ 0 ] >= 10 ;
// return swfobject.hasFlashPlayerVersion("10");
2011-11-29 11:40:05 -08:00
} ;
2011-12-07 21:03:12 -08:00
_V _ . flash . canPlaySource = function ( srcObj ) {
2012-01-05 23:25:09 -08:00
if ( srcObj . type in _V _ . flash . prototype . support . formats ) { return "maybe" ; }
2011-11-29 11:40:05 -08:00
} ;
2012-01-05 23:25:09 -08:00
_V _ . flash . prototype . support = {
formats : {
2011-11-29 11:40:05 -08:00
"video/flv" : "FLV" ,
"video/x-flv" : "FLV" ,
"video/mp4" : "MP4" ,
"video/m4v" : "MP4"
} ,
// Optional events that we can manually mimic with timers
2012-01-05 23:25:09 -08:00
progressEvent : false ,
timeupdateEvent : false ,
2012-01-20 17:34:18 -08:00
// Resizing plugins using request fullscreen reloads the plugin
2012-01-05 23:25:09 -08:00
fullscreenResize : false ,
// Resizing plugins in Firefox always reloads the plugin (e.g. full window mode)
parentResize : ! ( _V _ . ua . match ( "Firefox" ) )
2011-11-29 11:40:05 -08:00
} ;
2012-01-20 17:42:38 -08:00
_V _ . flash . onReady = function ( currSwf ) {
2011-12-07 22:02:40 -08:00
2011-12-21 17:59:36 -08:00
var el = _V _ . el ( currSwf ) ;
2011-11-29 11:40:05 -08:00
2011-12-21 17:59:36 -08:00
// Get player from box
// On firefox reloads, el might already have a player
var player = el . player || el . parentNode . player ,
2012-01-02 13:02:04 -08:00
tech = player . tech ;
2011-11-29 11:40:05 -08:00
2011-12-21 17:59:36 -08:00
// Reference player on tech element
el . player = player ;
2011-11-29 11:40:05 -08:00
2011-12-21 17:59:36 -08:00
// Update reference to playback technology element
tech . el = el ;
2011-11-29 11:40:05 -08:00
2012-01-05 23:25:09 -08:00
// Now that the element is ready, make a click on the swf play the video
tech . addEvent ( "click" , tech . onClick ) ;
2012-01-02 16:57:17 -08:00
2011-12-21 17:59:36 -08:00
_V _ . flash . checkReady ( tech ) ;
} ;
2011-11-29 11:40:05 -08:00
2011-12-21 17:59:36 -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.
_V _ . flash . checkReady = function ( tech ) {
2012-01-28 18:56:28 -08:00
// Check if API property exists
2011-12-21 17:59:36 -08:00
if ( tech . el . vjs _getProperty ) {
2012-01-28 18:56:28 -08:00
// If so, tell tech it's ready
2011-12-21 17:59:36 -08:00
tech . triggerReady ( ) ;
2012-01-28 18:56:28 -08:00
// Otherwise wait longer.
2011-12-21 17:59:36 -08:00
} else {
2012-01-28 18:56:28 -08:00
2011-12-21 17:59:36 -08:00
setTimeout ( function ( ) {
_V _ . flash . checkReady ( tech ) ;
} , 50 ) ;
2012-01-28 18:56:28 -08:00
2011-11-29 11:40:05 -08:00
}
} ;
2011-12-07 22:02:40 -08:00
2012-01-28 18:56:28 -08:00
// Trigger events from the swf on the player
_V _ . flash . onEvent = function ( swfID , eventName ) {
var player = _V _ . el ( swfID ) . player ;
player . triggerEvent ( eventName ) ;
2011-11-29 11:40:05 -08:00
} ;
2012-01-28 18:56:28 -08:00
// Log errors from the swf
_V _ . flash . onError = function ( swfID , err ) {
_V _ . log ( "Flash Error" , err , swfID ) ;
2011-11-29 11:40:05 -08:00
} ;
2012-01-20 18:20:00 -08:00
// Flash Version Check
_V _ . flash . version = function ( ) {
var version = '0,0,0'
2012-01-28 18:56:28 -08:00
2012-01-20 18:20:00 -08:00
// IE
try {
version = new ActiveXObject ( 'ShockwaveFlash.ShockwaveFlash' ) . GetVariable ( '$version' ) . replace ( /\D+/g , ',' ) . match ( /^,?(.+),?$/ ) [ 1 ] ;
2012-01-28 18:56:28 -08:00
2012-01-20 18:20:00 -08:00
// other browsers
} catch ( e ) {
try {
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 ] ;
}
} catch ( e ) { }
}
return version . split ( "," ) ;
2012-01-23 14:55:06 -08:00
}
2012-01-28 18:56:28 -08:00
// Flash embedding method. Only used in non-iframe mode
2012-01-23 14:55:06 -08:00
_V _ . flash . embed = function ( swf , placeHolder , flashVars , params , attributes ) {
2012-01-28 18:56:28 -08:00
var code = _V _ . flash . getEmbedCode ( swf , flashVars , params , attributes ) ,
// Get element by embedding code and retrieving created element
obj = _V _ . createElement ( "div" , { innerHTML : code } ) . childNodes [ 0 ] ,
par = placeHolder . parentNode
;
2012-01-23 14:55:06 -08:00
placeHolder . parentNode . replaceChild ( obj , placeHolder ) ;
// IE6 seems to have an issue where it won't initialize the swf object after injecting it.
// This is a dumb temporary fix
2012-01-28 18:56:28 -08:00
if ( _V _ . isIE ( ) ) {
var newObj = par . childNodes [ 0 ] ;
setTimeout ( function ( ) {
newObj . style . display = "block" ;
} , 1000 ) ;
}
2012-01-29 20:03:44 -08:00
return obj ;
2012-01-23 14:55:06 -08:00
} ;
_V _ . flash . getEmbedCode = function ( swf , flashVars , params , attributes ) {
var objTag = '<object type="application/x-shockwave-flash"' ,
flashVarsString = '' ,
paramsString = ''
attrsString = '' ;
// Convert flash vars to string
if ( flashVars ) {
2012-01-28 18:56:28 -08:00
_V _ . eachProp ( flashVars , function ( key , val ) {
2012-01-23 14:55:06 -08:00
flashVarsString += ( key + "=" + val + "&" ) ;
} ) ;
}
// Add swf, flashVars, and other default params
params = _V _ . merge ( {
movie : swf ,
flashvars : flashVarsString ,
2012-01-29 20:03:44 -08:00
allowScriptAccess : "always" , // Required to talk to swf
allowNetworking : "all" // All should be default, but having security issues.
2012-01-23 14:55:06 -08:00
} , params ) ;
2012-01-28 18:56:28 -08:00
// Create param tags string
_V _ . eachProp ( params , function ( key , val ) {
2012-01-23 14:55:06 -08:00
paramsString += '<param name="' + key + '" value="' + val + '" />' ;
} ) ;
2012-01-28 18:56:28 -08:00
attributes = _V _ . merge ( {
// Add swf to attributes (need both for IE and Others to work)
data : swf ,
// Default to 100% width/height
width : "100%" ,
height : "100%"
2012-01-23 14:55:06 -08:00
} , attributes ) ;
2012-01-29 20:03:44 -08:00
2012-01-28 18:56:28 -08:00
// Create Attributes string
_V _ . eachProp ( attributes , function ( key , val ) {
2012-01-23 14:55:06 -08:00
attrsString += ( key + '="' + val + '" ' ) ;
} ) ;
return objTag + attrsString + '>' + paramsString + '</object>' ;
2012-01-28 17:27:45 -08:00
}