This commit is contained in:
Rick Waldron 2011-08-23 13:51:07 -04:00
Родитель 47ce320a21
Коммит a94ca3be4b
4 изменённых файлов: 267 добавлений и 267 удалений

Просмотреть файл

@ -17,15 +17,15 @@
// These are considered to be "on" by being defined. Initialize to undefined
this.autoplay;
this.loop;
// List of events
this._events = {};
// The underlying player resource. May be <canvas>, <iframe>, <object>, array, etc
this._resource;
// The container div of the resource
this._container;
this.offsetWidth = this.width = 0;
this.offsetHeight = this.height = 0;
this.offsetLeft = 0;
@ -35,98 +35,98 @@
Popcorn.baseplayer.init.prototype = {
load: function() {},
play: function() {
this.paused = 0;
this.timeupdate();
},
pause: function() {
this.paused = 1;
},
timeupdate: function() {
// So we can refer to the instance when setTimeout is run
var self = this;
if( !this.paused ) {
this.currentTime += ( new Date() - this.baselineTime ) / 1000;
this.dispatchEvent( "timeupdate" );
}
this.baselineTime = new Date();
setTimeout(function() {
self.timeupdate.call( self );
}, 50 );
},
// By default, assumes this.resource is a DOM Element
// Changing the type of this.resource requires this method to be overridden
getBoundingClientRect: function() {
return Popcorn.position( this._resource || this._container );
},
// Add an event listener to the object
addEventListener: function( evtName, fn ) {
if ( !this._events[ evtName ] ) {
this._events[ evtName ] = [];
}
this._events[ evtName ].push( fn );
return fn;
},
// Can take event object or simple string
dispatchEvent: function( oEvent ) {
var evt,
self = this,
eventInterface,
eventName = oEvent.type;
// A string was passed, create event object
if ( !eventName ) {
eventName = oEvent;
eventInterface = Popcorn.events.getInterface( eventName );
if ( eventInterface ) {
evt = document.createEvent( eventInterface );
evt.initEvent( eventName, true, true, window, 1 );
}
}
Popcorn.forEach( this._events[ eventName ], function( val ) {
val.call( self, evt, self );
});
},
// Extracts values from container onto this object
extractContainerValues: function( id ) {
this._container = document.getElementById( id );
if ( !this._container ) {
return;
}
var bounds = this._container.getBoundingClientRect();
this.offsetWidth = this.width = this.getStyle( "width" ) || 0;
this.offsetHeight = this.height = this.getStyle( "height" ) || 0;
this.offsetLeft = bounds.left;
this.offsetTop = bounds.top;
this.offsetParent = this._container.offsetParent;
return this._container;
},
// By default, assumes this.resource is a DOM Element
// Changing the type of this.resource requires this method to be overridden
// Returns the computed value for CSS style 'prop' as computed by the browser
getStyle: function( prop ) {
var elem = this._resource || this._container;
if ( elem.currentStyle ) {
// IE syntax
return elem.currentStyle[ prop ];

Просмотреть файл

@ -120,7 +120,7 @@
*
* canPlayType() function
*/
// Trackers
var timeupdateInterval = 33,
timeCheckInterval = 0.25,
@ -128,11 +128,11 @@
floor = Math.floor,
round = Math.round,
registry = {};
function hasAllDependencies() {
return global.swfobject && global.soundcloud;
}
// Borrowed from: http://www.quirksmode.org/dom/getstyles.html
// Gets the style for the given element
function getStyle( elem, styleProp ) {
@ -144,68 +144,68 @@
return document.defaultView.getComputedStyle( elem, null ).getPropertyValue( styleProp );
}
}
function formatComment( comment ) {
// Calclate the difference between d and now, express as "n units ago"
function ago( d ) {
var diff = ( ( new Date() ).getTime() - d.getTime() )/1000;
function pluralize( value, unit ) {
return value + " " + unit + ( value > 1 ? "s" : "") + " ago";
}
if ( diff < 60 ) {
return pluralize( round( diff ), "second" );
}
}
diff /= 60;
if ( diff < 60 ) {
return pluralize( round( diff ), "minute" );
}
}
diff /= 60;
if ( diff < 24 ) {
return pluralize( round( diff ), "hour" );
}
diff /= 24;
// Rough approximation of months
if ( diff < 30 ) {
return pluralize( round( diff ), "day" );
}
if ( diff < 365 ) {
return pluralize( round( diff/30 ), "month" );
}
return pluralize( round( diff/365 ), "year" );
}
// Converts sec to min.sec
function timeToFraction ( totalSec ) {
var min = floor( totalSec / 60 ),
sec = round( totalSec % 60 );
return min + "." + ( sec < 10 ? "0" : "" ) + sec;
}
return '<div><a href="' + comment.user.profile + '">' +
'<img width="16px height="16px" src="' + comment.user.avatar + '"></img>' +
comment.user.name + '</a> at ' + timeToFraction( comment.start ) + ' ' +
ago( comment.date ) +
'<br />' + comment.text + '</span>';
}
function isReady( self ) {
if ( !hasAllDependencies() ) {
if ( !hasAllDependencies() ) {
setTimeout( function() {
isReady( self );
}, 15 );
return;
}
var flashvars = {
enable_api: true,
enable_api: true,
object_id: self._playerId,
url: self.src,
// Hide comments in player if showing them elsewhere
@ -221,82 +221,82 @@
name: self._playerId
},
actualTarget = document.createElement( 'div' );
actualTarget.setAttribute( "id", self._playerId );
self._container.appendChild( actualTarget );
swfobject.embedSWF( "http://player.soundcloud.com/player.swf", self._playerId, self.offsetWidth, self.height, "9.0.0", "expressInstall.swf", flashvars, params, attributes );
}
Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js" );
// Source file originally from 'https://github.com/soundcloud/Widget-JS-API/raw/master/soundcloud.player.api.js'
Popcorn.getScript( "http://popcornjs.org/code/players/soundcloud/lib/soundcloud.player.api.js", function() {
// Play event is fired twice when player is first started. Ignore second one
var ignorePlayEvt = 1;
// Register the wrapper's load event with the player
soundcloud.addEventListener( 'onPlayerReady', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.swfObj = object;
wrapper.duration = object.api_getTrackDuration();
wrapper.currentTime = object.api_getTrackPosition();
// This eliminates volumechangee event from firing on load
wrapper.volume = wrapper.previousVolume = object.api_getVolume()/100;
// The numeric id of the track for use with Soundcloud API
wrapper._mediaId = data.mediaId;
wrapper.dispatchEvent( 'load' );
wrapper.dispatchEvent( 'canplay' );
wrapper.dispatchEvent( 'durationchange' );
wrapper.timeupdate();
});
// Register events for when the flash player plays a track for the first time
soundcloud.addEventListener( 'onMediaStart', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.played = 1;
wrapper.dispatchEvent( 'playing' );
});
// Register events for when the flash player plays a track
soundcloud.addEventListener( 'onMediaPlay', function( object, data ) {
if ( ignorePlayEvt ) {
ignorePlayEvt = 0;
return;
}
var wrapper = registry[object.api_getFlashId()];
wrapper.dispatchEvent( 'play' );
});
// Register events for when the flash player pauses a track
soundcloud.addEventListener( 'onMediaPause', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.dispatchEvent( 'pause' );
});
// Register events for when the flash player is buffering
soundcloud.addEventListener( 'onMediaBuffering', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.dispatchEvent( 'progress' );
if ( wrapper.readyState === 0 ) {
if ( wrapper.readyState === 0 ) {
wrapper.readyState = 3;
wrapper.dispatchEvent( "readystatechange" );
}
});
// Register events for when the flash player is done buffering
soundcloud.addEventListener( 'onMediaDoneBuffering', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.dispatchEvent( 'canplaythrough' );
});
// Register events for when the flash player has finished playing
soundcloud.addEventListener( 'onMediaEnd', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
@ -304,52 +304,52 @@
//wrapper.pause();
wrapper.dispatchEvent( 'ended' );
});
// Register events for when the flash player has seeked
soundcloud.addEventListener( 'onMediaSeek', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.setCurrentTime( object.api_getTrackPosition() );
if ( wrapper.paused ) {
wrapper.dispatchEvent( "timeupdate" );
}
});
// Register events for when the flash player has errored
soundcloud.addEventListener( 'onPlayerError', function( object, data ) {
var wrapper = registry[object.api_getFlashId()];
wrapper.dispatchEvent( 'error' );
});
});
Popcorn.soundcloud = function( containerId, src, options ) {
return new Popcorn.soundcloud.init( containerId, src, options );
};
// A constructor, but we need to wrap it to allow for "static" functions
Popcorn.soundcloud.init = (function() {
function pullFromContainer( that ) {
function pullFromContainer( that ) {
var options = that._options,
container = that._container,
bounds = container.getBoundingClientRect(),
tmp,
undef;
that.width = options.width || getStyle( container, "width" ) || "100%";
that.height = options.height || getStyle( container, "height" ) || "81px";
that.src = options.src;
that.autoplay = options.autoplay;
if ( parseFloat( that.height, 10 ) !== 81 ) {
that.height = "81px";
}
that.offsetLeft = bounds.left;
that.offsetTop = bounds.top;
that.offsetHeight = parseFloat( that.height, 10 );
that.offsetWidth = parseFloat( that.width, 10 );
// Width and height may've been specified as a %, find the value now in case a plugin needs it (like subtitle)
if ( /[\d]+%/.test( that.width ) ) {
tmp = getStyle( container, "width" );
@ -357,7 +357,7 @@
that.offsetWidth = that._container.offsetWidth;
that._container.style.width = tmp;
}
if ( /[\d]+%/.test( that.height ) ) {
tmp = getStyle( container, "height" );
that._container.style.height = that.height;
@ -365,7 +365,7 @@
that._container.style.height = tmp;
}
}
// If container id is not supplied, assumed to be same as player id
var ctor = function ( containerId, src, options ) {
if ( !containerId ) {
@ -375,19 +375,19 @@
} else if ( /file/.test( location.protocol ) ) {
throw "Must run from a web server!";
}
var container = this._container = document.getElementById( containerId );
if ( !container ) {
throw "Could not find that container in the DOM!";
}
options = options || {};
options.api = options.api || {};
options.target = containerId;
options.src = src;
options.api.commentformat = options.api.commentformat || formatComment;
this._mediaId = 0;
this._listeners = {};
this._playerId = Popcorn.guid( options.target );
@ -395,9 +395,9 @@
this._options = options;
this._comments = [];
this._popcorn;
pullFromContainer( this );
this.duration = 0;
this.volume = 1;
this.currentTime = 0;
@ -405,33 +405,33 @@
this.paused = 1;
this.readyState = 0;
this.playbackRate = 1;
this.top = 0;
this.left = 0;
this.autoplay;
this.played = 0;
this.addEventListener( "load", function() {
var boundRect = this.getBoundingClientRect();
this.top = boundRect.top;
this.left = boundRect.left;
this.offsetWidth = this.swfObj.offsetWidth;
this.offsetHeight = this.swfObj.offsetHeight;
this.offsetLeft = this.swfObj.offsetLeft;
this.offsetTop = this.swfObj.offsetTop;
});
registry[ this._playerId ] = this;
isReady( this );
};
return ctor;
})();
Popcorn.soundcloud.init.prototype = Popcorn.soundcloud.prototype;
// Sequence object prototype
Popcorn.extend( Popcorn.soundcloud.prototype, {
// Set the volume as a value between 0 and 1
@ -439,16 +439,16 @@
if ( !val && val !== 0 ) {
return;
}
// Normalize in case outside range of expected values of 0 .. 1
if ( val < 0 ) {
val = -val;
}
if ( val > 1 ) {
val %= 1;
}
// HTML video expects to be 0.0 -> 1.0, Flash object expects 0-100
this.volume = this.previousVolume = val;
this.swfObj.api_setVolume( val*100 );
@ -459,10 +459,10 @@
if ( !time && time !== 0 ) {
return;
}
this.currentTime = this.previousCurrentTime = time;
this.ended = time >= this.duration;
// Fire events for seeking and time change
this.dispatchEvent( "seeked" );
},
@ -476,7 +476,7 @@
// No need to process if already playing
return;
}
this.paused = 0;
this.swfObj.api_play();
},
@ -490,7 +490,7 @@
// No need to process if already playing
return;
}
this.paused = 1;
this.swfObj.api_pause();
},
@ -502,10 +502,10 @@
this.addEventListener( "load", this.mute );
return;
}
if ( !this.muted() ) {
this.oldVol = this.volume;
if ( this.paused ) {
this.setVolume( 0 );
} else {
@ -529,7 +529,7 @@
this.addEventListener( "load", this.load );
return;
}
this.play();
this.pause();
},
@ -539,20 +539,20 @@
if ( !this._listeners[evt] ) {
this._listeners[evt] = [];
}
this._listeners[evt].push( fn );
return fn;
},
dispatchEvent: function( evt ) {
var self = this,
evtName = evt.type || evt;
// Manually triggered a UI event, have it invoke rather than just the event handlers
if ( evtName === "play" && this.paused || evtName === "pause" && !this.paused ) {
this[evtName]();
return;
}
Popcorn.forEach( this._listeners[evtName], function( fn ) {
fn.call( self );
});
@ -561,7 +561,7 @@
var self = this,
checkedVolume = this.swfObj.api_getVolume()/100,
seeked = 0;
// If has been changed through setting currentTime attribute
if ( abs( this.currentTime - this.previousCurrentTime ) > timeCheckInterval ) {
// Has programatically set the currentTime
@ -570,38 +570,38 @@
} else {
this.previousCurrentTime = this.currentTime = this.swfObj.api_getTrackPosition();
}
// If has been changed throughh volume attribute
if ( checkedVolume !== this.previousVolume ) {
this.setVolume( checkedVolume );
} else if ( this.volume !== this.previousVolume ) {
this.setVolume( this.volume );
}
if ( !this.paused ) {
this.dispatchEvent( 'timeupdate' );
}
if( !self.ended ) {
setTimeout( function() {
self.timeupdate.call( self );
}, timeupdateInterval);
}
},
getBoundingClientRect: function() {
var b,
self = this;
if ( this.swfObj ) {
b = this.swfObj.getBoundingClientRect();
return {
bottom: b.bottom,
left: b.left,
right: b.right,
top: b.top,
// These not guaranteed to be in there
width: b.width || ( b.right - b.left ),
height: b.height || ( b.bottom - b.top )
@ -609,7 +609,7 @@
} else {
//container = document.getElementById( this.playerId );
tmp = this._container.getBoundingClientRect();
// Update bottom, right for expected values once the container loads
return {
left: tmp.left,
@ -621,7 +621,7 @@
};
}
},
registerPopcornWithPlayer: function( popcorn ) {
if ( !this.swfObj ) {
this.addEventListener( "load", function() {
@ -629,14 +629,14 @@
});
return;
}
this._popcorn = popcorn;
var api = this._options.api;
if ( api.key && api.commentdiv ) {
var self = this;
Popcorn.xhr({
url: "http://api.soundcloud.com/tracks/" + self._mediaId + "/comments.js?consumer_key=" + api.key,
success: function( data ) {
@ -657,7 +657,7 @@
}
}
});
Popcorn.extend( Popcorn.soundcloud.prototype, {
addComment: function( obj, displayFn ) {
var self = this,
@ -674,13 +674,13 @@
return ( displayFn || self._options.api.commentformat )( comment );
}
};
this._comments.push( comment );
if ( !this._popcorn ) {
return;
}
this._popcorn.subtitle({
start: comment.start,
target: this._options.api.commentdiv,

Просмотреть файл

@ -101,21 +101,21 @@
* src
* startOffsetTime
*/
// Trackers
var timeupdateInterval = 33,
timeCheckInterval = 0.75,
abs = Math.abs,
registry = {};
// base object for DOM-related behaviour like events
var EventManager = function ( owner ) {
var evts = {};
function makeHandler( evtName ) {
if ( !evts[evtName] ) {
evts[evtName] = [];
// Create a wrapper function to all registered listeners
this["on"+evtName] = function( args ) {
Popcorn.forEach( evts[evtName], function( fn ) {
@ -126,25 +126,25 @@
};
}
}
return {
addEventListener: function( evtName, fn, doFire ) {
evtName = evtName.toLowerCase();
makeHandler.call( this, evtName );
evts[evtName].push( fn );
if ( doFire ) {
dispatchEvent( evtName );
}
return fn;
},
// Add many listeners for a single event
// Takes an event name and array of functions
addEventListeners: function( evtName, events ) {
evtName = evtName.toLowerCase();
makeHandler.call( this, evtName );
evts[evtName] = evts[evtName].concat( events );
},
@ -152,7 +152,7 @@
var evtArray = this.getEventListeners( evtName ),
i,
l;
// Find and remove from events array
for ( i = 0, l = evtArray.length; i < l; i++) {
if ( evtArray[i] === fn ) {
@ -169,7 +169,7 @@
return evts;
}
},
dispatchEvent: function( evt, args ) {
dispatchEvent: function( evt, args ) {
// If event object was passed in, toString will yield event type as string (timeupdate)
// If a string, toString() will return the string itself (timeupdate)
evt = "on"+evt.toString().toLowerCase();
@ -177,16 +177,16 @@
}
};
};
Popcorn.vimeo = function( mediaId, list, options ) {
return new Popcorn.vimeo.init( mediaId, list, options );
};
Popcorn.vimeo.onLoad = function( playerId ) {
var player = registry[ playerId ];
player.swfObj = document.getElementById( playerId );
// For calculating position relative to video (like subtitles)
player.offsetWidth = player.swfObj.offsetWidth;
player.offsetHeight = player.swfObj.offsetHeight;
@ -196,15 +196,15 @@
player.dispatchEvent( "load" );
};
Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js" );
// A constructor, but we need to wrap it to allow for "static" functions
Popcorn.vimeo.init = (function() {
var rPlayerUri = /^http:\/\/player\.vimeo\.com\/video\/[\d]+/i,
rWebUrl = /vimeo\.com\/[\d]+/,
hasAPILoaded = false;
// Extract the numeric video id from container uri: 'http://player.vimeo.com/video/11127501' or 'http://player.vimeo.com/video/4282282'
// Expect id to be a valid 32/64-bit unsigned integer
// Returns string, empty string if could not match
@ -212,11 +212,11 @@
if ( !uri ) {
return;
}
var matches = uri.match( rPlayerUri );
return matches ? matches[0].substr(30) : "";
}
// Extract the numeric video id from url: 'http://vimeo.com/11127501' or simply 'vimeo.com/4282282'
// Ignores protocol and subdomain, but one would expecct it to be http://www.vimeo.com/#######
// Expect id to be a valid 32/64-bit unsigned integer
@ -225,11 +225,11 @@
if ( !url ) {
return;
}
var matches = url.match( rWebUrl );
return matches ? matches[0].substr(10) : "";
}
function makeSwf( self, vidId, containerId ) {
if ( !window.swfobject ) {
setTimeout( function() {
@ -237,11 +237,11 @@
}, 1);
return;
}
var params,
flashvars,
attributes = {};
flashvars = {
clip_id: vidId,
show_portrait: 1,
@ -260,10 +260,10 @@
// This is so we can overlay html ontop o fFlash
wmode: 'transparent'
};
swfobject.embedSWF( "http://vimeo.com/moogaloop.swf", containerId, self.offsetWidth, self.offsetHeight, "9.0.0", "expressInstall.swf", flashvars, params, attributes );
}
// If container id is not supplied, assumed to be same as player id
var ctor = function ( containerId, videoUrl, options ) {
if ( !containerId ) {
@ -271,7 +271,7 @@
} else if ( /file/.test( location.protocol ) ) {
throw "Must run from a web server!";
}
var vidId,
that = this,
tmp;
@ -280,11 +280,11 @@
this._container.id = containerId + "object";
this._target = document.getElementById( containerId );
this._target.appendChild( this._container );
options = options || {};
options.css && Popcorn.extend( this._target.style, options.css );
this.addEventFn;
this.evtHolder;
this.paused = true;
@ -296,11 +296,11 @@
this.initialTime = 0;
this.played = 0;
this.readyState = 0;
this.previousCurrentTime = this.currentTime;
this.previousVolume = this.volume;
this.evtHolder = new EventManager( this );
// For calculating position relative to video (like subtitles)
this.width = this._target.style.width || "504px";
this.height = this._target.style.height || "340px";
@ -315,7 +315,7 @@
this.offsetWidth = this._target.offsetWidth;
this._target.style.width = tmp;
}
if ( !/[\d]%/.test( this.height ) ) {
this.offsetHeight = parseInt( this.height, 10 );
this._target.style.height = this.height + "px";
@ -326,48 +326,48 @@
this.offsetHeight = this._target.offsetHeight;
this._target.style.height = tmp;
}
this.offsetLeft = 0;
this.offsetTop = 0;
// Try and get a video id from a vimeo site url
// Try either from ctor param or from iframe itself
vidId = extractIdFromUrl( videoUrl ) || extractIdFromUri( videoUrl );
if ( !vidId ) {
throw "No video id";
}
registry[ this._container.id ] = this;
makeSwf( this, vidId, this._container.id );
// Set up listeners to internally track state as needed
this.addEventListener( "load", function() {
var hasLoaded = false;
that.duration = that.swfObj.api_getDuration();
that.evtHolder.dispatchEvent( "durationchange" );
that.evtHolder.dispatchEvent( "loadedmetadata" );
// Chain events and calls together so that this.currentTime reflects the current time of the video
// Done by Getting the Current Time while the video plays
that.addEventListener( "timeupdate", function() {
that.currentTime = that.swfObj.api_getCurrentTime();
});
// Add pause listener to keep track of playing state
that.addEventListener( "pause", function() {
that.paused = true;
});
// Add play listener to keep track of playing state
that.addEventListener( "playing", function() {
that.paused = false;
that.ended = 0;
});
// Add ended listener to keep track of playing state
that.addEventListener( "ended", function() {
if ( that.loop !== "loop" ) {
@ -375,7 +375,7 @@
that.ended = 1;
}
});
// Add progress listener to keep track of ready state
that.addEventListener( "progress", function( data ) {
if ( !hasLoaded ) {
@ -383,7 +383,7 @@
that.readyState = 3;
that.evtHolder.dispatchEvent( "readystatechange" );
}
// Check if fully loaded
if ( data.percent === 100 ) {
that.readyState = 4;
@ -395,9 +395,9 @@
};
return ctor;
})();
Popcorn.vimeo.init.prototype = Popcorn.vimeo.prototype;
// Sequence object prototype
Popcorn.extend( Popcorn.vimeo.prototype, {
// Do everything as functions instead of get/set
@ -405,7 +405,7 @@
if ( !val ) {
return;
}
this.loop = val;
var isLoop = val === "loop" ? 1 : 0;
// HTML convention says to loop if value is 'loop'
@ -416,16 +416,16 @@
if ( !val && val !== 0 ) {
return;
}
// Normalize in case outside range of expected values
if ( val < 0 ) {
val = -val;
}
if ( val > 1 ) {
val %= 1;
}
// HTML video expects to be 0.0 -> 1.0, Vimeo expects 0-100
this.volume = this.previousVolume = val;
this.swfObj.api_setVolume( val*100 );
@ -436,11 +436,11 @@
if ( !time && time !== 0 ) {
return;
}
this.currentTime = this.previousCurrentTime = time;
this.ended = time >= this.duration;
this.swfObj.api_seekTo( time );
// Fire events for seeking and time change
this.evtHolder.dispatchEvent( "seeked" );
this.evtHolder.dispatchEvent( "timeupdate" );
@ -452,13 +452,13 @@
this.addEventListener( "load", this.play );
return;
}
if ( !this.played ) {
this.played = 1;
this.startTimeUpdater();
this.evtHolder.dispatchEvent( "loadstart" );
}
this.evtHolder.dispatchEvent( "play" );
this.swfObj.api_play();
},
@ -469,7 +469,7 @@
this.addEventListener( "load", this.pause );
return;
}
this.swfObj.api_pause();
},
// Toggle video muting
@ -480,10 +480,10 @@
this.addEventListener( "load", this.mute );
return;
}
if ( !this.muted() ) {
this.oldVol = this.volume;
if ( this.paused ) {
this.setVolume( 0 );
} else {
@ -507,7 +507,7 @@
this.addEventListener( "load", this.load );
return;
}
this.play();
this.pause();
},
@ -517,9 +517,9 @@
this.addEventListener( "load", this.unload );
return;
}
this.pause();
this.swfObj.api_unload();
this.evtHolder.dispatchEvent( "abort" );
this.evtHolder.dispatchEvent( "emptied" );
@ -529,10 +529,10 @@
addEventListener: function( evt, fn ) {
var playerEvt,
that = this;
// In case event object is passed in
evt = evt.type || evt.toLowerCase();
// If it's an HTML media event supported by player, map
if ( evt === "seeked" ) {
playerEvt = "onSeek";
@ -548,11 +548,11 @@
// Direct mapping, CamelCase the event name as vimeo API expects
playerEvt = "on"+evt[0].toUpperCase() + evt.substr(1);
}
// Vimeo only stores 1 callback per event
// Have vimeo call internal collection of callbacks
this.evtHolder.addEventListener( evt, fn, false );
// Link manual event structure with Vimeo's if not already
if( playerEvt && this.evtHolder.getEventListeners( evt ).length === 1 ) {
// Setup global functions on Popcorn.vimeo to sync player events to an internal collection
@ -560,7 +560,7 @@
if ( playerEvt === "onSeek" || playerEvt === "onProgress" || playerEvt === "onLoading" ) {
Popcorn.vimeo[playerEvt] = function( arg1, arg2 ) {
var player = registry[arg2];
player.evtHolder.dispatchEvent( evt, arg1 );
};
} else {
@ -569,7 +569,7 @@
player.evtHolder.dispatchEvent( evt );
};
}
this.swfObj.api_addEventListener( playerEvt, "Popcorn.vimeo."+playerEvt );
}
},
@ -585,7 +585,7 @@
startTimeUpdater: function() {
var self = this,
seeked = 0;
if ( abs( this.currentTime - this.previousCurrentTime ) > timeCheckInterval ) {
// Has programatically set the currentTime
this.setCurrentTime( this.currentTime );
@ -593,15 +593,15 @@
} else {
this.previousCurrentTime = this.currentTime;
}
if ( this.volume !== this.previousVolume ) {
this.setVolume( this.volume );
}
if ( !self.paused || seeked ) {
this.dispatchEvent( 'timeupdate' );
}
if( !self.ended ) {
setTimeout( function() {
self.startTimeUpdater.call(self);

Просмотреть файл

@ -46,79 +46,79 @@ var onYouTubePlayerReady;
YOUTUBE_STATE_CUED = 5;
var urlRegex = /^.*[\/=](.{11})/;
// Collection of all Youtube players
var registry = {},
loadedPlayers = {};
var abs = Math.abs;
Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js" );
// Extract the id from a web url
function extractIdFromUrl( url ) {
if ( !url ) {
return;
}
var matches = urlRegex.exec( url );
var matches = urlRegex.exec( url );
// Return id, which comes after first equals sign
return matches ? matches[1] : "";
}
// Extract the id from a player url
function extractIdFromUri( url ) {
if ( !url ) {
return;
}
var matches = urlRegex.exec( url );
var matches = urlRegex.exec( url );
// Return id, which comes after first equals sign
return matches ? matches[1] : "";
}
function getPlayerAddress( vidId, playerId ) {
if( !vidId ) {
return;
}
return "http://www.youtube.com/e/" + id;
}
function makeSWF( url, container ) {
var bounds,
params,
flashvars,
attributes,
self = this;
if ( !window.swfobject ) {
setTimeout( function() {
makeSWF.call( self, url, container );
}, 1 );
return;
}
bounds = container.getBoundingClientRect();
// Determine width/height/etc based on container
this.width = container.style.width || 460;
this.height = container.style.height || 350;
// Just in case we got the attributes as strings. We'll need to do math with these later
this.width = parseFloat(this.width);
this.height = parseFloat(this.height);
// For calculating position relative to video (like subtitles)
this.offsetWidth = this.width;
this.offsetHeight = this.height;
this.offsetLeft = bounds.left;
this.offsetTop = bounds.top;
this.offsetParent = container.offsetParent;
flashvars = {
playerapiid: this.playerId,
controls: this.controls,
@ -130,29 +130,29 @@ var onYouTubePlayerReady;
allowfullscreen: 'true',
// This is so we can overlay html on top of Flash
wmode: 'transparent'
};
attributes = {
id: this.playerId
};
swfobject.embedSWF( "http://www.youtube.com/e/" + this.vidId +"?enablejsapi=1&playerapiid=" + this.playerId + "&version=3",
swfobject.embedSWF( "http://www.youtube.com/e/" + this.vidId +"?enablejsapi=1&playerapiid=" + this.playerId + "&version=3",
this.playerId, this.width, this.height, "8", null, flashvars, params, attributes );
}
// Called when a player is loaded
// Playerid must match the element id
onYouTubePlayerReady = function ( playerId ) {
var vid = registry[playerId];
loadedPlayers[playerId] = 1;
// Video hadn't loaded yet when ctor was called
vid.video = document.getElementById( playerId );
vid.duration = vid.video.getDuration();
// Issue load event
vid.dispatchEvent( 'load' );
vid.dispatchEvent( "durationchange" );
@ -168,11 +168,11 @@ var onYouTubePlayerReady;
} else if ( /file/.test( location.protocol ) ) {
throw "This must be run from a web server.";
}
options = options || {};
var self = this;
this.playerId = elementId + Popcorn.guid();
this.readyState = READY_STATE_HAVE_NOTHING;
this._eventListeners = {};
@ -180,18 +180,18 @@ var onYouTubePlayerReady;
this.loadedData = false;
this.fullyLoaded = false;
this.paused = false;
// If supplied as number, append 'px' on end
// If suppliied as '###' or '###px', convert to number and append 'px' back on end
options.width = options.width && (+options.width)+"px";
options.height = options.height && (+options.height)+"px";
// show controls on video. Integer value - 1 is for show, 0 is for hide
this.controls = +options.controls === 0 || +options.controls === 1 ? options.controls : 1;
this.controls = +options.controls === 0 || +options.controls === 1 ? options.controls : 1;
// show video annotations, 1 is show, 3 is hide
this.iv_load_policy = +options.annotations === 1 || +options.annotations === 3 ? options.annotations : 1;
this._target = document.getElementById( elementId );
this._container = document.createElement( "div" );
this._container.id = this.playerId;
@ -201,55 +201,55 @@ var onYouTubePlayerReady;
this.offsetHeight = +this._target.offsetHeight;
this.offsetWidth = +this._target.offsetWidth;
this.currentTime = this.previousCurrentTime = 0;
this.volume = this.previousVolume = this.preMuteVol = 1;
this.duration = 0;
this.vidId = extractIdFromUrl( url ) || extractIdFromUri( url );
if ( !this.vidId ) {
throw "Could not find video id";
}
this.addEventListener( "load", function() {
// For calculating position relative to video (like subtitles)
this.offsetWidth = this.video.offsetWidth;
this.offsetHeight = this.video.offsetHeight;
this.offsetParent = this.video.offsetParent;
// Set up stuff that requires the API to be loaded
this.registerYoutubeEventHandlers();
this.registerInternalEventHandlers();
});
(function() {
var hasBeenCalled = 0;
self.addEventListener( "playing", function() {
if (hasBeenCalled) {
return;
}
hasBeenCalled = 1;
self.duration = self.video.getDuration();
self.dispatchEvent( "durationchange" );
});
})();
if ( loadedPlayers[this.playerId] ) {
this.video = registry[this.playerId].video;
this.vidId = this.vidId || extractIdFromUrl( this._container.getAttribute( "src" ) ) || extractIdFromUri( this._container.getAttribute( "src" ) );
if (this.vidId !== registry[this.playerId].vidId ) {
this.video.cueVideoById( this.vidId );
} else {
// Same video, new ctor. Force a seek to the beginning
this.previousCurrentTime = 1;
}
this.dispatchEvent( 'load' );
} else if ( this._container ) {
makeSWF.call( this, url, this._container );
@ -257,15 +257,15 @@ var onYouTubePlayerReady;
// Container not yet loaded, get it on DOMDontentLoad
document.addEventListener( "DOMContentLoaded", function() {
self._container = document.getElementById( elementId );
if ( !self._container ) {
throw "Could not find container!";
}
makeSWF.call( self, url, self._container );
}, false);
}
registry[this.playerId] = this;
};
// end Popcorn.youtube.init
@ -278,7 +278,7 @@ var onYouTubePlayerReady;
var youcorn = this,
stateChangeHandler = 'Popcorn.youtube.stateChangeEventHandler',
errorHandler = 'Popcorn.youtube.errorEventHandler';
this.video.addEventListener( 'onStateChange', stateChangeHandler );
this.video.addEventListener( 'onError', errorHandler );
@ -288,9 +288,9 @@ var onYouTubePlayerReady;
*/
Popcorn.youtube.stateChangeEventHandler = function( state ) {
// In case ctor has been called many times for many ctors
// Only use latest ctor call for each player id
// Only use latest ctor call for each player id
var self = registry[youcorn.playerId];
if ( state === YOUTUBE_STATE_UNSTARTED ) {
self.readyState = READY_STATE_HAVE_METADATA;
self.dispatchEvent( 'loadedmetadata' );
@ -338,7 +338,7 @@ var onYouTubePlayerReady;
});
return;
}
this.dispatchEvent( 'play' );
this.video.playVideo();
},
@ -349,7 +349,7 @@ var onYouTubePlayerReady;
this.addEventListener( "load", this.pause );
return;
}
this.video.pauseVideo();
// pause event is raised by Youtube.
},
@ -362,12 +362,12 @@ var onYouTubePlayerReady;
});
return;
}
this.video.playVideo();
this.video.pauseVideo();
},
seekTo: function( time ) {
seekTo: function( time ) {
var playing = this.video.getPlayerState() == YOUTUBE_STATE_PLAYING;
this.video.seekTo( time, true );
@ -395,9 +395,9 @@ var onYouTubePlayerReady;
this.addEventListener( "load", this.mute );
return;
}
if ( this.volume !== 0 ) {
this.preMuteVol = this.volume;
this.preMuteVol = this.volume;
this.setVolume( 0 );
} else {
this.setVolume( this.preMuteVol );
@ -413,11 +413,11 @@ var onYouTubePlayerReady;
addEventListener: function( evt, func ) {
var evtName = evt.type || evt;
if ( !this._eventListeners[evtName] ) {
this._eventListeners[evtName] = [];
}
this._eventListeners[evtName].push( func );
},
@ -429,9 +429,9 @@ var onYouTubePlayerReady;
if ( !this._eventListeners[evtName] ) {
return;
}
var self = this;
Popcorn.forEach( this._eventListeners[evtName], function( evt ) {
evt.call( self, null );
});
@ -444,27 +444,27 @@ var onYouTubePlayerReady;
playbackRate: function( arg ) {
},
getBoundingClientRect: function() {
var b,
self = this;
if ( this.video ) {
b = this.video.getBoundingClientRect();
return {
bottom: b.bottom,
left: b.left,
right: b.right,
top: b.top,
// These not guaranteed to be in there
width: b.width || ( b.right - b.left ),
height: b.height || ( b.bottom - b.top )
};
} else {
b = self._container.getBoundingClientRect();
// Update bottom, right for expected values once the container loads
return {
left: b.left,
@ -476,12 +476,12 @@ var onYouTubePlayerReady;
};
}
},
startTimeUpdater: function() {
var state = typeof this.video.getPlayerState != "function" ? this.readyState : this.video.getPlayerState(),
self = this,
seeked = 0;
if ( abs( this.currentTime - this.previousCurrentTime ) > timeCheckInterval ) {
// Has programatically set the currentTime
this.previousCurrentTime = this.currentTime - timeCheckInterval;
@ -491,22 +491,22 @@ var onYouTubePlayerReady;
this.previousCurrentTime = this.currentTime;
this.currentTime = typeof this.video.getCurrentTime != "function" ? this.currentTime : this.video.getCurrentTime();
}
if ( this.volume !== this.previousVolume ) {
this.setVolume( this.volume );
}
if ( state !== YOUTUBE_STATE_ENDED && state !== YOUTUBE_STATE_PAUSED || seeked ) {
this.dispatchEvent( 'timeupdate' );
}
if( state !== YOUTUBE_STATE_ENDED ) {
setTimeout( function() {
self.startTimeUpdater.call(self);
}, timeupdateInterval);
}
},
startProgressUpdater: function() {
var bytesLoaded = this.video.getVideoBytesLoaded(),
bytesToLoad = this.video.getVideoBytesTotal(),
@ -532,7 +532,7 @@ var onYouTubePlayerReady;
}
this.dispatchEvent( 'progress' );
setTimeout( function() {
self.startProgressUpdater.call( self );
}, progressInterval);