зеркало из https://github.com/mozilla/popcorn-js.git
Merge branch 'develop' of git://github.com/cadecairos/popcorn-js into 1.2
* 'develop' of git://github.com/cadecairos/popcorn-js: [#911] Rewrites bulk of Popcorn.removeTrackEvent(), improves performance, fixes byEnd event issue. [#911] Don't assume a sequential index reference for track events. [#911] Failing tests. http://gyazo.com/66c76333dd7173e3fab1001d3ea0c8fc.png?1328905037 [#904] fixed whitespace, comma and file moved back to proper location [#904] moved parser into modules, updated tests, etc. [#904] removed popcorn.player.html. It does not make sense. [#904] removed player from archaic test [#904] moved player into modules, tests, updated all touching files Extended timeout for subtitle unit tests [#871] Removed popcorn.timeline.css [#879]
This commit is contained in:
Коммит
5c686806ab
demos/semantic_video
modules
parsers
parserJSON
parserSBV
parserSRT
parserSSA
parserTTML
parserTTXT
parserVTT
parserXML
players
soundcloud
vimeo
youtube
plugins
popcorn.jstest
|
@ -5,6 +5,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<script src="http://code.jquery.com/jquery.js"></script>
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="../../plugins/webpage/popcorn.webpage.js"></script>
|
||||
<script src="../../plugins/googlemap/popcorn.googlemap.js"></script>
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
(function( Popcorn ) {
|
||||
|
||||
var
|
||||
|
||||
AP = Array.prototype,
|
||||
OP = Object.prototype,
|
||||
|
||||
forEach = AP.forEach,
|
||||
slice = AP.slice,
|
||||
hasOwn = OP.hasOwnProperty,
|
||||
toString = OP.toString;
|
||||
|
||||
// stores parsers keyed on filetype
|
||||
Popcorn.parsers = {};
|
||||
|
||||
// An interface for extending Popcorn
|
||||
// with parser functionality
|
||||
Popcorn.parser = function( name, type, definition ) {
|
||||
|
||||
if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
|
||||
Popcorn.error( "'" + name + "' is a protected function name" );
|
||||
return;
|
||||
}
|
||||
|
||||
// fixes parameters for overloaded function call
|
||||
if ( typeof type === "function" && !definition ) {
|
||||
definition = type;
|
||||
type = "";
|
||||
}
|
||||
|
||||
if ( typeof definition !== "function" || typeof type !== "string" ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Provides some sugar, but ultimately extends
|
||||
// the definition into Popcorn.p
|
||||
|
||||
var natives = Popcorn.events.all,
|
||||
parseFn,
|
||||
parser = {};
|
||||
|
||||
parseFn = function( filename, callback ) {
|
||||
|
||||
if ( !filename ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
|
||||
Popcorn.xhr({
|
||||
url: filename,
|
||||
dataType: type,
|
||||
success: function( data ) {
|
||||
|
||||
var tracksObject = definition( data ),
|
||||
tracksData,
|
||||
tracksDataLen,
|
||||
tracksDef,
|
||||
idx = 0;
|
||||
|
||||
tracksData = tracksObject.data || [];
|
||||
tracksDataLen = tracksData.length;
|
||||
tracksDef = null;
|
||||
|
||||
// If no tracks to process, return immediately
|
||||
if ( !tracksDataLen ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create tracks out of parsed object
|
||||
for ( ; idx < tracksDataLen; idx++ ) {
|
||||
|
||||
tracksDef = tracksData[ idx ];
|
||||
|
||||
for ( var key in tracksDef ) {
|
||||
|
||||
if ( hasOwn.call( tracksDef, key ) && !!that[ key ] ) {
|
||||
|
||||
that[ key ]( tracksDef[ key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( callback ) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// Assign new named definition
|
||||
parser[ name ] = parseFn;
|
||||
|
||||
// Extend Popcorn.p with new named definition
|
||||
Popcorn.extend( Popcorn.p, parser );
|
||||
|
||||
// keys the function name by filetype extension
|
||||
//Popcorn.parsers[ name ] = true;
|
||||
|
||||
return parser;
|
||||
};
|
||||
})( Popcorn );
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Module: Timeline-Sources</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="popcorn.parser.js"></script>
|
||||
<script src="popcorn.parser.unit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Module: player</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<div id="qunit-fixture"> </div>
|
||||
|
||||
<video id="video"
|
||||
style="display:;width:300px"
|
||||
controls
|
||||
preload="auto">
|
||||
|
||||
<source id="mp4"
|
||||
src="../../test/trailer.mp4"
|
||||
type='video/mp4; codecs="avc1, mp4a"'>
|
||||
|
||||
<source id="ogv"
|
||||
src="../../test/trailer.ogv"
|
||||
type='video/ogg; codecs="theora, vorbis"'>
|
||||
|
||||
<source id="webm"
|
||||
src="../../test/trailer.webm"
|
||||
type='video/webm; codecs="vp8, vorbis"'>
|
||||
|
||||
<p>Your user agent does not support the HTML5 Video element.</p>
|
||||
|
||||
</video>
|
||||
|
||||
<audio id="audio" data-timeline-sources="data/parserData.json" controls>
|
||||
<source src="../../test/italia.mp4" type='audio/mp4; codecs="mp4a.40.2"'>
|
||||
<source src="../../test/italia.ogg" type='audio/ogg; codecs="vorbis"'>
|
||||
</audio>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,162 @@
|
|||
module( "Popcorn Parser" );
|
||||
|
||||
test( "Parsing Functions", function() {
|
||||
|
||||
var expects = 3,
|
||||
count = 0,
|
||||
popperly = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop( 10000 );
|
||||
|
||||
ok( typeof Popcorn.parser === "function", "Popcorn.parser is a function" );
|
||||
plus();
|
||||
|
||||
Popcorn.parser( "parseJSON" , "json", function( data ){
|
||||
return data;
|
||||
});
|
||||
|
||||
ok( typeof popperly.parseJSON === "function", "Popcorn.parser created a parseJSON function" );
|
||||
plus();
|
||||
|
||||
ok( typeof popperly.parseJSON().parseJSON( "data/test.js" ).parseJSON === "function" , "parseJSON function is chainable" );
|
||||
plus();
|
||||
});
|
||||
|
||||
test( "Parsing Integrity", function() {
|
||||
|
||||
var expects = 6,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
poppercore = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
// clean up added events after tests
|
||||
Popcorn.removePlugin( "parserTest" );
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop( 10000 );
|
||||
|
||||
Popcorn.parser( "parseJSON2", function( data ){
|
||||
ok( typeof data.json === "object", "data.json exists" );
|
||||
plus();
|
||||
return data.json;
|
||||
});
|
||||
|
||||
Popcorn.parser( "parseJSON3" , "json", function( data ){
|
||||
ok( typeof data === "object", "data exists" );
|
||||
plus();
|
||||
return data;
|
||||
});
|
||||
|
||||
Popcorn.plugin( "parserTest", {
|
||||
|
||||
start: function() {
|
||||
ok( true, "parserTest started" );
|
||||
plus();
|
||||
},
|
||||
end: function() {
|
||||
ok( true, "parserTest ended" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
poppercore.parseJSON2( "data/parserData.json", function() {
|
||||
|
||||
poppercore.parseJSON3( "data/parserData.json", function() {
|
||||
poppercore.currentTime( 5 ).play();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test( "Parsing Handler - References unavailable plugin", function() {
|
||||
|
||||
var expects = 1,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
interval,
|
||||
poppercore = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
// clean up added events after tests
|
||||
clearInterval( interval );
|
||||
poppercore.removePlugin( "parserTest" );
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop();
|
||||
|
||||
Popcorn.parser( "parseJson", function( data ){
|
||||
|
||||
return data.json;
|
||||
});
|
||||
|
||||
poppercore.parseJson( "data/parseMissing.json" );
|
||||
|
||||
// interval used to wait for data to be parsed
|
||||
interval = setInterval( function() {
|
||||
poppercore.currentTime( 5 ).play().currentTime( 6 );
|
||||
|
||||
ok( true, "Ignored call to missing plugin " );
|
||||
plus();
|
||||
}, 2000 );
|
||||
});
|
||||
|
||||
test( "Parser Support - audio", function() {
|
||||
|
||||
var expects = 3,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
interval,
|
||||
audiocorn = Popcorn( "#audio" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
|
||||
Popcorn.removePlugin( "testAudioParser" );
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
stop( 5000 );
|
||||
|
||||
Popcorn.plugin( "testAudioParser", {
|
||||
|
||||
start: function() {
|
||||
ok( true, "testAudioParser started: " + Math.round( this.currentTime() ) );
|
||||
plus();
|
||||
},
|
||||
end: function() {
|
||||
ok( true, "testAudioParser ended: " + Math.round( this.currentTime() ) );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
Popcorn.parser( "parseAudio", function( data ){
|
||||
ok( typeof data.json === "object", "data.json exists");
|
||||
plus();
|
||||
return data.json;
|
||||
});
|
||||
|
||||
audiocorn.parseAudio( "data/parserAudio.json", function() {
|
||||
|
||||
audiocorn.currentTime( 4 ).play();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,235 @@
|
|||
(function( Popcorn ) {
|
||||
|
||||
Popcorn.player = function( name, player ) {
|
||||
|
||||
// ID string matching
|
||||
var rIdExp = /^(#([\w\-\_\.]+))$/;
|
||||
|
||||
player = player || {};
|
||||
|
||||
var playerFn = function( target, src, options ) {
|
||||
|
||||
options = options || {};
|
||||
|
||||
// List of events
|
||||
var date = new Date() / 1000,
|
||||
baselineTime = date,
|
||||
currentTime = 0,
|
||||
volume = 1,
|
||||
muted = false,
|
||||
events = {},
|
||||
|
||||
// The container div of the resource
|
||||
container = document.getElementById( rIdExp.exec( target ) && rIdExp.exec( target )[ 2 ] ) ||
|
||||
document.getElementById( target ) ||
|
||||
target,
|
||||
basePlayer = {},
|
||||
timeout,
|
||||
popcorn;
|
||||
|
||||
// copies a div into the media object
|
||||
for( var val in container ) {
|
||||
|
||||
if ( typeof container[ val ] === "object" ) {
|
||||
|
||||
basePlayer[ val ] = container[ val ];
|
||||
} else if ( typeof container[ val ] === "function" ) {
|
||||
|
||||
basePlayer[ val ] = (function( value ) {
|
||||
|
||||
// this is a stupid ugly kludgy hack in honour of Safari
|
||||
// in Safari a NodeList is a function, not an object
|
||||
if ( "length" in container[ value ] && !container[ value ].call ) {
|
||||
|
||||
return container[ value ];
|
||||
} else {
|
||||
|
||||
return function() {
|
||||
|
||||
return container[ value ].apply( container, arguments );
|
||||
};
|
||||
}
|
||||
}( val ));
|
||||
} else {
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, val, {
|
||||
get: (function( value ) {
|
||||
|
||||
return function() {
|
||||
|
||||
return container[ value ];
|
||||
};
|
||||
}( val )),
|
||||
set: Popcorn.nop,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var timeupdate = function() {
|
||||
|
||||
date = new Date() / 1000;
|
||||
|
||||
if ( !basePlayer.paused ) {
|
||||
|
||||
basePlayer.currentTime = basePlayer.currentTime + ( date - baselineTime );
|
||||
basePlayer.dispatchEvent( "timeupdate" );
|
||||
timeout = setTimeout( timeupdate, 10 );
|
||||
}
|
||||
|
||||
baselineTime = date;
|
||||
};
|
||||
|
||||
basePlayer.play = function() {
|
||||
|
||||
this.paused = false;
|
||||
|
||||
if ( basePlayer.readyState >= 4 ) {
|
||||
|
||||
baselineTime = new Date() / 1000;
|
||||
basePlayer.dispatchEvent( "play" );
|
||||
timeupdate();
|
||||
}
|
||||
};
|
||||
|
||||
basePlayer.pause = function() {
|
||||
|
||||
this.paused = true;
|
||||
basePlayer.dispatchEvent( "pause" );
|
||||
};
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, "currentTime", {
|
||||
get: function() {
|
||||
|
||||
return currentTime;
|
||||
},
|
||||
set: function( val ) {
|
||||
|
||||
// make sure val is a number
|
||||
currentTime = +val;
|
||||
basePlayer.dispatchEvent( "timeupdate" );
|
||||
|
||||
return currentTime;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, "volume", {
|
||||
get: function() {
|
||||
|
||||
return volume;
|
||||
},
|
||||
set: function( val ) {
|
||||
|
||||
// make sure val is a number
|
||||
volume = +val;
|
||||
basePlayer.dispatchEvent( "volumechange" );
|
||||
return volume;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, "muted", {
|
||||
get: function() {
|
||||
|
||||
return muted;
|
||||
},
|
||||
set: function( val ) {
|
||||
|
||||
// make sure val is a number
|
||||
muted = +val;
|
||||
basePlayer.dispatchEvent( "volumechange" );
|
||||
return muted;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
// Adds an event listener to the object
|
||||
basePlayer.addEventListener = function( evtName, fn ) {
|
||||
|
||||
if ( !events[ evtName ] ) {
|
||||
|
||||
events[ evtName ] = [];
|
||||
}
|
||||
|
||||
events[ evtName ].push( fn );
|
||||
return fn;
|
||||
};
|
||||
|
||||
// Can take event object or simple string
|
||||
basePlayer.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( events[ eventName ], function( val ) {
|
||||
|
||||
val.call( self, evt, self );
|
||||
});
|
||||
};
|
||||
|
||||
// Attempt to get src from playerFn parameter
|
||||
basePlayer.src = src || "";
|
||||
basePlayer.readyState = 0;
|
||||
basePlayer.duration = 0;
|
||||
basePlayer.paused = true;
|
||||
basePlayer.ended = 0;
|
||||
|
||||
if ( player._setup ) {
|
||||
|
||||
player._setup.call( basePlayer, options );
|
||||
} else {
|
||||
|
||||
// there is no setup, which means there is nothing to load
|
||||
basePlayer.readyState = 4;
|
||||
basePlayer.dispatchEvent( "load" );
|
||||
basePlayer.dispatchEvent( "loadeddata" );
|
||||
}
|
||||
|
||||
// when a custom player is loaded, load basePlayer state into custom player
|
||||
basePlayer.addEventListener( "load", function() {
|
||||
|
||||
// if a player is not ready before currentTime is called, this will set it after it is ready
|
||||
basePlayer.currentTime = currentTime;
|
||||
|
||||
// same as above with volume and muted
|
||||
basePlayer.volume = volume;
|
||||
basePlayer.muted = muted;
|
||||
});
|
||||
|
||||
basePlayer.addEventListener( "loadeddata", function() {
|
||||
|
||||
// if play was called before player ready, start playing video
|
||||
!basePlayer.paused && basePlayer.play();
|
||||
});
|
||||
|
||||
popcorn = new Popcorn.p.init( basePlayer, options );
|
||||
|
||||
return popcorn;
|
||||
};
|
||||
|
||||
Popcorn[ name ] = Popcorn[ name ] || playerFn;
|
||||
};
|
||||
|
||||
Popcorn.player.defineProperty = Object.defineProperty || function( object, description, options ) {
|
||||
|
||||
object.__defineGetter__( description, options.get || Popcorn.nop );
|
||||
object.__defineSetter__( description, options.set || Popcorn.nop );
|
||||
};
|
||||
|
||||
})( Popcorn );
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Module: Timeline-Sources</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="popcorn.player.js"></script>
|
||||
<script src="popcorn.player.unit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Module: player</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<div id="qunit-fixture"> </div>
|
||||
|
||||
<div id='video'></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,189 @@
|
|||
module( "Popcorn Player" );
|
||||
|
||||
test( "Base player methods", function() {
|
||||
|
||||
var expects = 2;
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop( 10000 );
|
||||
|
||||
ok( Popcorn.player, "Popcorn.player function exists" );
|
||||
|
||||
Popcorn.player( "newplayer" );
|
||||
ok( Popcorn.newplayer, "Popcorn.player registers new players" );
|
||||
|
||||
start();
|
||||
});
|
||||
|
||||
test( "Base player functionality", function() {
|
||||
|
||||
Popcorn.player( "baseplayer" );
|
||||
|
||||
//QUnit.reset();
|
||||
|
||||
var p2 = Popcorn.baseplayer( "#video" ),
|
||||
expects = 12,
|
||||
count = 0,
|
||||
execCount = 0,
|
||||
// These make sure events are only fired once
|
||||
// any second call will produce a failed test
|
||||
forwardStart = false,
|
||||
forwardEnd = false,
|
||||
backwardStart = false,
|
||||
backwardEnd = false,
|
||||
wrapperRunning = {
|
||||
one: false,
|
||||
two: false
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
// clean up added events after tests
|
||||
Popcorn.removePlugin( "forwards" );
|
||||
Popcorn.removePlugin( "backwards" );
|
||||
Popcorn.removePlugin( "wrapper" );
|
||||
p2.removePlugin( "exec" );
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
// These tests come close to 10 seconds on chrome, increasing to 15
|
||||
stop( 15000 );
|
||||
|
||||
Popcorn.plugin( "forwards", function() {
|
||||
return {
|
||||
start: function( event, options ) {
|
||||
|
||||
if ( !options.startFired ) {
|
||||
|
||||
options.startFired = true;
|
||||
forwardStart = !forwardStart;
|
||||
ok( forwardStart, "forward's start fired" );
|
||||
plus();
|
||||
}
|
||||
},
|
||||
end: function( event, options ) {
|
||||
|
||||
if ( !options.endFired ) {
|
||||
|
||||
options.endFired = true;
|
||||
forwardEnd = !forwardEnd;
|
||||
p2.currentTime( 1 ).play();
|
||||
ok( forwardEnd, "forward's end fired" );
|
||||
plus();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
p2.forwards({
|
||||
start: 3,
|
||||
end: 4
|
||||
});
|
||||
|
||||
Popcorn.plugin( "backwards", function() {
|
||||
return {
|
||||
start: function( event, options ) {
|
||||
|
||||
if ( !options.startFired ) {
|
||||
|
||||
options.startFired = true;
|
||||
backwardStart = !backwardStart;
|
||||
p2.currentTime( 0 ).play();
|
||||
ok( true, "backward's start fired" );
|
||||
plus();
|
||||
}
|
||||
},
|
||||
end: function( event, options ) {
|
||||
|
||||
if ( !options.endFired ) {
|
||||
|
||||
options.endFired = true;
|
||||
backwardEnd = !backwardEnd;
|
||||
ok( backwardEnd, "backward's end fired" );
|
||||
plus();
|
||||
p2.currentTime( 5 ).play();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
p2.backwards({
|
||||
start: 1,
|
||||
end: 2
|
||||
});
|
||||
|
||||
Popcorn.plugin( "wrapper", {
|
||||
start: function( event, options ) {
|
||||
|
||||
wrapperRunning[ options.wrapper ] = true;
|
||||
},
|
||||
end: function( event, options ) {
|
||||
|
||||
wrapperRunning[ options.wrapper ] = false;
|
||||
}
|
||||
});
|
||||
|
||||
// second instance of wrapper is wrapping the first
|
||||
p2.wrapper({
|
||||
start: 6,
|
||||
end: 7,
|
||||
wrapper: "one"
|
||||
})
|
||||
.wrapper({
|
||||
start: 5,
|
||||
end: 8,
|
||||
wrapper: "two"
|
||||
})
|
||||
// checking wrapper 2's start
|
||||
.exec( 5, function() {
|
||||
|
||||
if ( execCount === 0 ) {
|
||||
|
||||
execCount++;
|
||||
ok( wrapperRunning.two, "wrapper two is running at second 5" );
|
||||
plus();
|
||||
ok( !wrapperRunning.one, "wrapper one is stopped at second 5" );
|
||||
plus();
|
||||
}
|
||||
})
|
||||
// checking wrapper 1's start
|
||||
.exec( 6, function() {
|
||||
|
||||
if ( execCount === 1 ) {
|
||||
|
||||
execCount++;
|
||||
ok( wrapperRunning.two, "wrapper two is running at second 6" );
|
||||
plus();
|
||||
ok( wrapperRunning.one, "wrapper one is running at second 6" );
|
||||
plus();
|
||||
}
|
||||
})
|
||||
// checking wrapper 1's end
|
||||
.exec( 7, function() {
|
||||
|
||||
if ( execCount === 2 ) {
|
||||
|
||||
execCount++;
|
||||
ok( wrapperRunning.two, "wrapper two is running at second 7" );
|
||||
plus();
|
||||
ok( !wrapperRunning.one, "wrapper one is stopped at second 7" );
|
||||
plus();
|
||||
}
|
||||
})
|
||||
// checking wrapper 2's end
|
||||
.exec( 8, function() {
|
||||
|
||||
if ( execCount === 3 ) {
|
||||
|
||||
execCount++;
|
||||
ok( !wrapperRunning.two, "wrapper two is stopped at second 9" );
|
||||
plus();
|
||||
ok( !wrapperRunning.one, "wrapper one is stopped at second 9" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
p2.currentTime( 3 ).play();
|
||||
});
|
|
@ -6,6 +6,7 @@
|
|||
<script src="../../test/qunit/qunit.js"></script>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../parser/popcorn.parser.js"></script>
|
||||
<script src="popcorn.timeline-sources.js"></script>
|
||||
<script src="popcorn.timeline-sources.unit.js"></script>
|
||||
<script src="../../parsers/parserJSON/popcorn.parserJSON.js"></script>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"title":"Crockford Lives!",
|
||||
"remote":"http://dl.dropbox.com/u/3531958/crockford.ogv",
|
||||
"data": [
|
||||
{
|
||||
"webpage": {
|
||||
"start":"0.0897589878863602",
|
||||
"end":"2.001204869833337",
|
||||
"target":"iframe-container",
|
||||
"src":"http://json.org"
|
||||
}
|
||||
},
|
||||
{
|
||||
"footnote": {
|
||||
"start":"0.23530116023787565",
|
||||
"end":"2.0193976413772767",
|
||||
"target":"footnote-container",
|
||||
"text":"I invented JSON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"googlemap": {
|
||||
"start":"0.09096385771969716",
|
||||
"end":"8.617349362660605",
|
||||
"target":"map-container",
|
||||
"type":"ROADMAP",
|
||||
"lat":37.7749295,
|
||||
"lng":-122.4194155,
|
||||
"location":"San Francisco, CA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"webpage": {
|
||||
"start":"2.073975956009095",
|
||||
"end":"10.278915922325776",
|
||||
"target":"iframe-container",
|
||||
"src":"http://jslint.org"
|
||||
}
|
||||
},
|
||||
{
|
||||
"footnote": {
|
||||
"start":2.145542172351516,
|
||||
"end":10.145542172351513,
|
||||
"target":"footnote-container",
|
||||
"text":"I wrote JSLint"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 JSON parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../modules/timeline-sources/popcorn.timeline-sources.js"></script>
|
||||
<script src="../../plugins/webpage/popcorn.webpage.js"></script>
|
||||
<script src="../../plugins/footnote/popcorn.footnote.js"></script>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<script src="../../test/jquery.js"></script>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../modules/timeline-sources/popcorn.timeline-sources.js"></script>
|
||||
<script src="../../plugins/webpage/popcorn.webpage.js"></script>
|
||||
<script src="../../plugins/footnote/popcorn.footnote.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 SBV parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserSBV.js"></script>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserSBV.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 SRT parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserSRT.js"></script>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ popcorn-api-draft.js
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="popcorn.parserSRT.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 SSA parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserSSA.js"></script>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserSSA.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 TTML parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserTTML.js"></script>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserTTML.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 TTXT parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserTTXT.js"></script>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="popcorn.parserTTXT.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 WebSRT/VTT parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="popcorn.parserVTT.js"></script>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ popcorn-api-draft.js
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="popcorn.parserVTT.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<title>Popcorn 1.0 parser Plug-in Demo</title>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
<script src="../../modules/timeline-sources/popcorn.timeline-sources.js"></script>
|
||||
<script src="../../plugins/flickr/popcorn.flickr.js"></script>
|
||||
<script src="popcorn.parserXML.js"></script>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/parser/popcorn.parser.js"></script>
|
||||
|
||||
<script src="popcorn.parserXML.js"></script>
|
||||
<script src="popcorn.parserXML.unit.js"></script>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
</style>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/player/popcorn.player.js"></script>
|
||||
<script type="text/javascript" src="popcorn.soundcloud.js"></script>
|
||||
|
||||
<!-- Plugins for demo purposes -->
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/player/popcorn.player.js"></script>
|
||||
|
||||
<script src="popcorn.soundcloud.unit.js"></script>
|
||||
<script src="popcorn.soundcloud.js"></script>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
</style>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/player/popcorn.player.js"></script>
|
||||
<script type="text/javascript" src="popcorn.vimeo.js"></script>
|
||||
<script src="../../plugins/footnote/popcorn.footnote.js"></script>
|
||||
<script src="../../plugins/flickr/popcorn.flickr.js"></script>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/player/popcorn.player.js"></script>
|
||||
|
||||
<script src="popcorn.vimeo.unit.js"></script>
|
||||
<script src="popcorn.vimeo.js"></script>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<title>Popcorn Youtube Player Example</title>
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/player/popcorn.player.js"></script>
|
||||
<script type="text/javascript" src="popcorn.youtube.js"></script>
|
||||
<script src="../../plugins/footnote/popcorn.footnote.js"></script>
|
||||
<script src="../../plugins/flickr/popcorn.flickr.js"></script>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
do not move - this must be called immediately prior to popcorn.js.
|
||||
-->
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../modules/player/popcorn.player.js"></script>
|
||||
<script src="popcorn.youtube.js"></script>
|
||||
<script src="popcorn.youtube.unit.js"></script>
|
||||
<script src="../../test/inject.js"></script>
|
||||
|
|
|
@ -17,7 +17,7 @@ test( "Popcorn Subtitle Plugin", function() {
|
|||
}
|
||||
}
|
||||
|
||||
stop( 12000 );
|
||||
stop( 15000 );
|
||||
|
||||
ok( "subtitle" in popped, "subtitle is a method of the popped instance" );
|
||||
plus();
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#big {
|
||||
font-size:24px;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
#mid {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
|
431
popcorn.js
431
popcorn.js
|
@ -9,7 +9,7 @@
|
|||
var methods = ( "removeInstance addInstance getInstanceById removeInstanceById " +
|
||||
"forEach extend effects error guid sizeOf isArray nop position disable enable destroy" +
|
||||
"addTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId " +
|
||||
"timeUpdate plugin removePlugin compose effect parser xhr getJSONP getScript player" ).split(/\s+/);
|
||||
"timeUpdate plugin removePlugin compose effect xhr getJSONP getScript" ).split(/\s+/);
|
||||
|
||||
while ( methods.length ) {
|
||||
global.Popcorn[ methods.shift() ] = function() {};
|
||||
|
@ -929,55 +929,83 @@
|
|||
return obj;
|
||||
};
|
||||
|
||||
Popcorn.removeTrackEvent = function( obj, trackId ) {
|
||||
Popcorn.removeTrackEvent = function( obj, removeId ) {
|
||||
|
||||
var historyLen = obj.data.history.length,
|
||||
var start, end, animate,
|
||||
historyLen = obj.data.history.length,
|
||||
length = obj.data.trackEvents.byStart.length,
|
||||
index = 0,
|
||||
indexWasAt = 0,
|
||||
byStart = [],
|
||||
byEnd = [],
|
||||
animating = [],
|
||||
history = [];
|
||||
|
||||
Popcorn.forEach( obj.data.trackEvents.byStart, function( o, i, context ) {
|
||||
// Preserve the original start/end trackEvents
|
||||
if ( !o._id ) {
|
||||
byStart.push( obj.data.trackEvents.byStart[i] );
|
||||
byEnd.push( obj.data.trackEvents.byEnd[i] );
|
||||
while ( --length > -1 ) {
|
||||
start = obj.data.trackEvents.byStart[ index ];
|
||||
end = obj.data.trackEvents.byEnd[ index ];
|
||||
|
||||
// Padding events will not have _id properties.
|
||||
// These should be safely pushed onto the front and back of the
|
||||
// track event array
|
||||
if ( !start._id ) {
|
||||
byStart.push( start );
|
||||
byEnd.push( end );
|
||||
}
|
||||
|
||||
// Filter for user track events (vs system track events)
|
||||
if ( o._id ) {
|
||||
if ( start._id ) {
|
||||
|
||||
// Filter for the trackevent to remove
|
||||
if ( o._id !== trackId ) {
|
||||
byStart.push( obj.data.trackEvents.byStart[i] );
|
||||
byEnd.push( obj.data.trackEvents.byEnd[i] );
|
||||
// If not a matching start event for removal
|
||||
if ( start._id !== removeId ) {
|
||||
byStart.push( start );
|
||||
}
|
||||
|
||||
// Capture the position of the track being removed.
|
||||
if ( o._id === trackId ) {
|
||||
indexWasAt = i;
|
||||
o._natives._teardown && o._natives._teardown.call( obj, o );
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if ( obj.data.trackEvents.animating.length ) {
|
||||
Popcorn.forEach( obj.data.trackEvents.animating, function( o, i, context ) {
|
||||
// Preserve the original start/end trackEvents
|
||||
if ( !o._id ) {
|
||||
animating.push( obj.data.trackEvents.animating[i] );
|
||||
// If not a matching end event for removal
|
||||
if ( end._id !== removeId ) {
|
||||
byEnd.push( end );
|
||||
}
|
||||
|
||||
// Filter for user track events (vs system track events)
|
||||
if ( o._id ) {
|
||||
// Filter for the trackevent to remove
|
||||
if ( o._id !== trackId ) {
|
||||
animating.push( obj.data.trackEvents.animating[i] );
|
||||
// If the _id is matched, capture the current index
|
||||
if ( start._id === removeId ) {
|
||||
indexWasAt = index;
|
||||
|
||||
// If a _teardown function was defined,
|
||||
// enforce for track event removals
|
||||
if ( start._natives._teardown ) {
|
||||
start._natives._teardown.call( obj, start );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Increment the track index
|
||||
index++;
|
||||
}
|
||||
|
||||
// Reset length to be used by the condition below to determine
|
||||
// if animating track events should also be filtered for removal.
|
||||
// Reset index below to be used by the reverse while as an
|
||||
// incrementing counter
|
||||
length = obj.data.trackEvents.animating.length;
|
||||
index = 0;
|
||||
|
||||
if ( length ) {
|
||||
while ( --length > -1 ) {
|
||||
animate = obj.data.trackEvents.animating[ index ];
|
||||
|
||||
// Padding events will not have _id properties.
|
||||
// These should be safely pushed onto the front and back of the
|
||||
// track event array
|
||||
if ( !animate._id ) {
|
||||
animating.push( animate );
|
||||
}
|
||||
|
||||
// If not a matching animate event for removal
|
||||
if ( animate._id && animate._id !== removeId ) {
|
||||
animating.push( animate );
|
||||
}
|
||||
// Increment the track index
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Update
|
||||
|
@ -994,7 +1022,7 @@
|
|||
obj.data.trackEvents.animating = animating;
|
||||
|
||||
for ( var i = 0; i < historyLen; i++ ) {
|
||||
if ( obj.data.history[ i ] !== trackId ) {
|
||||
if ( obj.data.history[ i ] !== removeId ) {
|
||||
history.push( obj.data.history[ i ] );
|
||||
}
|
||||
}
|
||||
|
@ -1003,12 +1031,12 @@
|
|||
obj.data.history = history;
|
||||
|
||||
// Update track event references
|
||||
Popcorn.removeTrackEvent.ref( obj, trackId );
|
||||
Popcorn.removeTrackEvent.ref( obj, removeId );
|
||||
};
|
||||
|
||||
// Internal Only - Removes track event references from instance object's trackRefs hash table
|
||||
Popcorn.removeTrackEvent.ref = function( obj, trackId ) {
|
||||
delete obj.data.trackRefs[ trackId ];
|
||||
Popcorn.removeTrackEvent.ref = function( obj, removeId ) {
|
||||
delete obj.data.trackRefs[ removeId ];
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
@ -1594,335 +1622,6 @@
|
|||
|
||||
Popcorn.plugin.effect = Popcorn.effect = Popcorn.compose;
|
||||
|
||||
// stores parsers keyed on filetype
|
||||
Popcorn.parsers = {};
|
||||
|
||||
// An interface for extending Popcorn
|
||||
// with parser functionality
|
||||
Popcorn.parser = function( name, type, definition ) {
|
||||
|
||||
if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) {
|
||||
Popcorn.error( "'" + name + "' is a protected function name" );
|
||||
return;
|
||||
}
|
||||
|
||||
// fixes parameters for overloaded function call
|
||||
if ( typeof type === "function" && !definition ) {
|
||||
definition = type;
|
||||
type = "";
|
||||
}
|
||||
|
||||
if ( typeof definition !== "function" || typeof type !== "string" ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Provides some sugar, but ultimately extends
|
||||
// the definition into Popcorn.p
|
||||
|
||||
var natives = Popcorn.events.all,
|
||||
parseFn,
|
||||
parser = {};
|
||||
|
||||
parseFn = function( filename, callback ) {
|
||||
|
||||
if ( !filename ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
|
||||
Popcorn.xhr({
|
||||
url: filename,
|
||||
dataType: type,
|
||||
success: function( data ) {
|
||||
|
||||
var tracksObject = definition( data ),
|
||||
tracksData,
|
||||
tracksDataLen,
|
||||
tracksDef,
|
||||
idx = 0;
|
||||
|
||||
tracksData = tracksObject.data || [];
|
||||
tracksDataLen = tracksData.length;
|
||||
tracksDef = null;
|
||||
|
||||
// If no tracks to process, return immediately
|
||||
if ( !tracksDataLen ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create tracks out of parsed object
|
||||
for ( ; idx < tracksDataLen; idx++ ) {
|
||||
|
||||
tracksDef = tracksData[ idx ];
|
||||
|
||||
for ( var key in tracksDef ) {
|
||||
|
||||
if ( hasOwn.call( tracksDef, key ) && !!that[ key ] ) {
|
||||
|
||||
that[ key ]( tracksDef[ key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( callback ) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// Assign new named definition
|
||||
parser[ name ] = parseFn;
|
||||
|
||||
// Extend Popcorn.p with new named definition
|
||||
Popcorn.extend( Popcorn.p, parser );
|
||||
|
||||
// keys the function name by filetype extension
|
||||
//Popcorn.parsers[ name ] = true;
|
||||
|
||||
return parser;
|
||||
};
|
||||
|
||||
Popcorn.player = function( name, player ) {
|
||||
|
||||
player = player || {};
|
||||
|
||||
var playerFn = function( target, src, options ) {
|
||||
|
||||
options = options || {};
|
||||
|
||||
// List of events
|
||||
var date = new Date() / 1000,
|
||||
baselineTime = date,
|
||||
currentTime = 0,
|
||||
volume = 1,
|
||||
muted = false,
|
||||
events = {},
|
||||
|
||||
// The container div of the resource
|
||||
container = document.getElementById( rIdExp.exec( target ) && rIdExp.exec( target )[ 2 ] ) ||
|
||||
document.getElementById( target ) ||
|
||||
target,
|
||||
basePlayer = {},
|
||||
timeout,
|
||||
popcorn;
|
||||
|
||||
// copies a div into the media object
|
||||
for( var val in container ) {
|
||||
|
||||
if ( typeof container[ val ] === "object" ) {
|
||||
|
||||
basePlayer[ val ] = container[ val ];
|
||||
} else if ( typeof container[ val ] === "function" ) {
|
||||
|
||||
basePlayer[ val ] = (function( value ) {
|
||||
|
||||
// this is a stupid ugly kludgy hack in honour of Safari
|
||||
// in Safari a NodeList is a function, not an object
|
||||
if ( "length" in container[ value ] && !container[ value ].call ) {
|
||||
|
||||
return container[ value ];
|
||||
} else {
|
||||
|
||||
return function() {
|
||||
|
||||
return container[ value ].apply( container, arguments );
|
||||
};
|
||||
}
|
||||
}( val ));
|
||||
} else {
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, val, {
|
||||
get: (function( value ) {
|
||||
|
||||
return function() {
|
||||
|
||||
return container[ value ];
|
||||
};
|
||||
}( val )),
|
||||
set: Popcorn.nop,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var timeupdate = function() {
|
||||
|
||||
date = new Date() / 1000;
|
||||
|
||||
if ( !basePlayer.paused ) {
|
||||
|
||||
basePlayer.currentTime = basePlayer.currentTime + ( date - baselineTime );
|
||||
basePlayer.dispatchEvent( "timeupdate" );
|
||||
timeout = setTimeout( timeupdate, 10 );
|
||||
}
|
||||
|
||||
baselineTime = date;
|
||||
};
|
||||
|
||||
basePlayer.play = function() {
|
||||
|
||||
this.paused = false;
|
||||
|
||||
if ( basePlayer.readyState >= 4 ) {
|
||||
|
||||
baselineTime = new Date() / 1000;
|
||||
basePlayer.dispatchEvent( "play" );
|
||||
timeupdate();
|
||||
}
|
||||
};
|
||||
|
||||
basePlayer.pause = function() {
|
||||
|
||||
this.paused = true;
|
||||
basePlayer.dispatchEvent( "pause" );
|
||||
};
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, "currentTime", {
|
||||
get: function() {
|
||||
|
||||
return currentTime;
|
||||
},
|
||||
set: function( val ) {
|
||||
|
||||
// make sure val is a number
|
||||
currentTime = +val;
|
||||
basePlayer.dispatchEvent( "timeupdate" );
|
||||
return currentTime;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, "volume", {
|
||||
get: function() {
|
||||
|
||||
return volume;
|
||||
},
|
||||
set: function( val ) {
|
||||
|
||||
// make sure val is a number
|
||||
volume = +val;
|
||||
basePlayer.dispatchEvent( "volumechange" );
|
||||
return volume;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Popcorn.player.defineProperty( basePlayer, "muted", {
|
||||
get: function() {
|
||||
|
||||
return muted;
|
||||
},
|
||||
set: function( val ) {
|
||||
|
||||
// make sure val is a number
|
||||
muted = !!val;
|
||||
basePlayer.dispatchEvent( "volumechange" );
|
||||
return muted;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Popcorn.forEach( [ "offsetWidth", "offsetHeight" ], function( prop ) {
|
||||
Popcorn.player.defineProperty( basePlayer, prop, {
|
||||
|
||||
get: function() {
|
||||
return +container[ prop ];
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
// Adds an event listener to the object
|
||||
basePlayer.addEventListener = function( evtName, fn ) {
|
||||
|
||||
if ( !events[ evtName ] ) {
|
||||
|
||||
events[ evtName ] = [];
|
||||
}
|
||||
|
||||
events[ evtName ].push( fn );
|
||||
return fn;
|
||||
};
|
||||
|
||||
// Can take event object or simple string
|
||||
basePlayer.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( events[ eventName ], function( val ) {
|
||||
|
||||
val.call( self, evt, self );
|
||||
});
|
||||
};
|
||||
|
||||
// Attempt to get src from playerFn parameter
|
||||
basePlayer.src = src || "";
|
||||
basePlayer.readyState = 0;
|
||||
basePlayer.duration = 0;
|
||||
basePlayer.paused = true;
|
||||
basePlayer.ended = 0;
|
||||
|
||||
if ( player._setup ) {
|
||||
|
||||
player._setup.call( basePlayer, options );
|
||||
} else {
|
||||
|
||||
// there is no setup, which means there is nothing to load
|
||||
basePlayer.readyState = 4;
|
||||
basePlayer.dispatchEvent( "load" );
|
||||
basePlayer.dispatchEvent( "loadeddata" );
|
||||
}
|
||||
|
||||
// when a custom player is loaded, load basePlayer state into custom player
|
||||
basePlayer.addEventListener( "load", function() {
|
||||
|
||||
// if a player is not ready before currentTime is called, this will set it after it is ready
|
||||
basePlayer.currentTime = currentTime;
|
||||
|
||||
// same as above with volume and muted
|
||||
basePlayer.volume = volume;
|
||||
basePlayer.muted = muted;
|
||||
});
|
||||
|
||||
basePlayer.addEventListener( "loadeddata", function() {
|
||||
|
||||
// if play was called before player ready, start playing video
|
||||
!basePlayer.paused && basePlayer.play();
|
||||
});
|
||||
|
||||
popcorn = new Popcorn.p.init( basePlayer, options );
|
||||
|
||||
return popcorn;
|
||||
};
|
||||
|
||||
Popcorn[ name ] = Popcorn[ name ] || playerFn;
|
||||
};
|
||||
|
||||
Popcorn.player.defineProperty = Object.defineProperty || function( object, description, options ) {
|
||||
|
||||
object.__defineGetter__( description, options.get || Popcorn.nop );
|
||||
object.__defineSetter__( description, options.set || Popcorn.nop );
|
||||
};
|
||||
|
||||
// Cache references to reused RegExps
|
||||
var rparams = /\?/,
|
||||
// XHR Setup object
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var methodsString = "removeInstance addInstance getInstanceById removeInstanceById " +
|
||||
"forEach extend effects error guid sizeOf isArray nop position disable enable destroy" +
|
||||
"addTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId " +
|
||||
"timeUpdate plugin removePlugin compose effect parser xhr getJSONP getScript player";
|
||||
"timeUpdate plugin removePlugin compose effect xhr getJSONP getScript";
|
||||
|
||||
module("Core");
|
||||
test("Dummy", function () {
|
||||
|
|
|
@ -183,6 +183,132 @@ test( "Popcorn.getTrackEvent", function() {
|
|||
|
||||
});
|
||||
|
||||
test( "Popcorn.removeTrackEvent", function() {
|
||||
|
||||
var pop = Popcorn( "#video" ),
|
||||
count = 0,
|
||||
aId, bId, cId, dId, byStart, byEnd;
|
||||
|
||||
expect( 5 );
|
||||
|
||||
Popcorn.plugin( "a", {
|
||||
_setup: function( options ) {},
|
||||
start: function( event, options ) {},
|
||||
end: function( event, options ) {},
|
||||
_teardown: function( options ) {}
|
||||
});
|
||||
|
||||
Popcorn.plugin( "b", {
|
||||
_setup: function( options ) {},
|
||||
start: function( event, options ) {},
|
||||
end: function( event, options ) {},
|
||||
_teardown: function( options ) {}
|
||||
});
|
||||
|
||||
Popcorn.plugin( "c", {
|
||||
_setup: function( options ) {},
|
||||
start: function( event, options ) {},
|
||||
end: function( event, options ) {},
|
||||
_teardown: function( options ) {}
|
||||
});
|
||||
|
||||
Popcorn.plugin( "d", {
|
||||
_setup: function( options ) {},
|
||||
start: function( event, options ) {},
|
||||
end: function( event, options ) {},
|
||||
_teardown: function( options ) {}
|
||||
});
|
||||
|
||||
pop.a({
|
||||
start: 1,
|
||||
end: 5
|
||||
});
|
||||
|
||||
// Store track event id for "plugin a"
|
||||
aId = pop.getLastTrackEventId();
|
||||
|
||||
pop.b({
|
||||
start: 3,
|
||||
end: 4
|
||||
});
|
||||
|
||||
// Store track event id for "plugin b"
|
||||
bId = pop.getLastTrackEventId();
|
||||
|
||||
pop.c({
|
||||
start: 0,
|
||||
end: 3
|
||||
});
|
||||
|
||||
// Store track event id for "plugin c"
|
||||
cId = pop.getLastTrackEventId();
|
||||
|
||||
pop.d({
|
||||
start: 1,
|
||||
end: 2
|
||||
});
|
||||
|
||||
// Store track event id for "plugin d"
|
||||
dId = pop.getLastTrackEventId();
|
||||
|
||||
// Capture the pre-removal track event count
|
||||
count = pop.data.trackEvents.byStart.length;
|
||||
|
||||
// Remove the first track event for "plugin a"
|
||||
pop.removeTrackEvent( aId );
|
||||
|
||||
// Shorthand references
|
||||
byStart = pop.data.trackEvents.byStart;
|
||||
byEnd = pop.data.trackEvents.byEnd;
|
||||
|
||||
equal( byStart.length, count - 1, "One less track event" );
|
||||
|
||||
// Iterate all byStart track events to prove that _only_ track events
|
||||
// created by "plugin b" have survived
|
||||
Popcorn.forEach( byStart, function( start ) {
|
||||
if ( start._id ) {
|
||||
// This condition should NEVER evaluate to true
|
||||
if ( start._id === aId ) {
|
||||
ok( false, "No byStart track events with " + aId + " should exist" );
|
||||
}
|
||||
// This condition should ALWAYS evaluate to true
|
||||
if ( start._id === bId ) {
|
||||
ok( true, "Only byStart track events with " + bId + " should exist" );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Iterate all byEnd track events to prove that _only_ track events
|
||||
// created by "plugin b" have survived
|
||||
Popcorn.forEach( byEnd, function( end ) {
|
||||
if ( end._id ) {
|
||||
// This condition should NEVER evaluate to true
|
||||
if ( end._id === aId ) {
|
||||
ok( false, "No byEnd track events with " + aId + " should exist" );
|
||||
}
|
||||
// This condition should ALWAYS evaluate to true
|
||||
if ( end._id === bId ) {
|
||||
ok( true, "Only byEnd track events with " + bId + " should exist" );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// after the removal, byStart's first element is c
|
||||
// console.log( byStart );
|
||||
|
||||
// after the removal, byEnd's first element should be d (if c, then broken)
|
||||
// console.log( byEnd );
|
||||
|
||||
// Test to ensure order was preserved
|
||||
equal( byStart[1]._id, cId, "byStart[1]._id matches cId" );
|
||||
equal( byEnd[1]._id, dId, "byEnd[1]._id matches dId" );
|
||||
|
||||
|
||||
Popcorn.forEach([ "a", "b", "c", "d" ], function( name ) {
|
||||
Popcorn.removePlugin( name );
|
||||
});
|
||||
});
|
||||
|
||||
test( "Popcorn.forEach", function() {
|
||||
|
||||
expect( 3 );
|
||||
|
@ -3803,7 +3929,6 @@ test( "XML Response", function() {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
test( "dataType: XML Response", function() {
|
||||
|
||||
var expects = 2,
|
||||
|
@ -3835,317 +3960,6 @@ test( "dataType: XML Response", function() {
|
|||
});
|
||||
});
|
||||
|
||||
module( "Popcorn Player" );
|
||||
|
||||
test( "Base player methods", function() {
|
||||
|
||||
var expects = 2;
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop( 10000 );
|
||||
|
||||
ok( Popcorn.player, "Popcorn.player function exists" );
|
||||
|
||||
Popcorn.player( "newplayer" );
|
||||
ok( Popcorn.newplayer, "Popcorn.player registers new players" );
|
||||
|
||||
start();
|
||||
});
|
||||
|
||||
test( "Base player functionality", function() {
|
||||
|
||||
Popcorn.player( "baseplayer" );
|
||||
|
||||
//QUnit.reset();
|
||||
|
||||
var p2 = Popcorn.baseplayer( "#video" ),
|
||||
expects = 12,
|
||||
count = 0,
|
||||
execCount = 0,
|
||||
// These make sure events are only fired once
|
||||
// any second call will produce a failed test
|
||||
forwardStart = false,
|
||||
forwardEnd = false,
|
||||
backwardStart = false,
|
||||
backwardEnd = false,
|
||||
wrapperRunning = {
|
||||
one: false,
|
||||
two: false
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
// clean up added events after tests
|
||||
Popcorn.removePlugin( "forwards" );
|
||||
Popcorn.removePlugin( "backwards" );
|
||||
Popcorn.removePlugin( "wrapper" );
|
||||
p2.removePlugin( "exec" );
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
// These tests come close to 10 seconds on chrome, increasing to 15
|
||||
stop( 15000 );
|
||||
|
||||
Popcorn.plugin( "forwards", function() {
|
||||
return {
|
||||
start: function( event, options ) {
|
||||
|
||||
if ( !options.startFired ) {
|
||||
|
||||
options.startFired = true;
|
||||
forwardStart = !forwardStart;
|
||||
ok( forwardStart, "forward's start fired" );
|
||||
plus();
|
||||
}
|
||||
},
|
||||
end: function( event, options ) {
|
||||
|
||||
if ( !options.endFired ) {
|
||||
|
||||
options.endFired = true;
|
||||
forwardEnd = !forwardEnd;
|
||||
p2.currentTime( 1 ).play();
|
||||
ok( forwardEnd, "forward's end fired" );
|
||||
plus();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
p2.forwards({
|
||||
start: 3,
|
||||
end: 4
|
||||
});
|
||||
|
||||
Popcorn.plugin( "backwards", function() {
|
||||
return {
|
||||
start: function( event, options ) {
|
||||
|
||||
if ( !options.startFired ) {
|
||||
|
||||
options.startFired = true;
|
||||
backwardStart = !backwardStart;
|
||||
p2.currentTime( 0 ).play();
|
||||
ok( true, "backward's start fired" );
|
||||
plus();
|
||||
}
|
||||
},
|
||||
end: function( event, options ) {
|
||||
|
||||
if ( !options.endFired ) {
|
||||
|
||||
options.endFired = true;
|
||||
backwardEnd = !backwardEnd;
|
||||
ok( backwardEnd, "backward's end fired" );
|
||||
plus();
|
||||
p2.currentTime( 5 ).play();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
p2.backwards({
|
||||
start: 1,
|
||||
end: 2
|
||||
});
|
||||
|
||||
Popcorn.plugin( "wrapper", {
|
||||
start: function( event, options ) {
|
||||
|
||||
wrapperRunning[ options.wrapper ] = true;
|
||||
},
|
||||
end: function( event, options ) {
|
||||
|
||||
wrapperRunning[ options.wrapper ] = false;
|
||||
}
|
||||
});
|
||||
|
||||
// second instance of wrapper is wrapping the first
|
||||
p2.wrapper({
|
||||
start: 6,
|
||||
end: 7,
|
||||
wrapper: "one"
|
||||
})
|
||||
.wrapper({
|
||||
start: 5,
|
||||
end: 8,
|
||||
wrapper: "two"
|
||||
})
|
||||
// checking wrapper 2's start
|
||||
.exec( 5, function() {
|
||||
|
||||
if ( execCount === 0 ) {
|
||||
|
||||
execCount++;
|
||||
ok( wrapperRunning.two, "wrapper two is running at second 5" );
|
||||
plus();
|
||||
ok( !wrapperRunning.one, "wrapper one is stopped at second 5" );
|
||||
plus();
|
||||
}
|
||||
})
|
||||
// checking wrapper 1's start
|
||||
.exec( 6, function() {
|
||||
|
||||
if ( execCount === 1 ) {
|
||||
|
||||
execCount++;
|
||||
ok( wrapperRunning.two, "wrapper two is running at second 6" );
|
||||
plus();
|
||||
ok( wrapperRunning.one, "wrapper one is running at second 6" );
|
||||
plus();
|
||||
}
|
||||
})
|
||||
// checking wrapper 1's end
|
||||
.exec( 7, function() {
|
||||
|
||||
if ( execCount === 2 ) {
|
||||
|
||||
execCount++;
|
||||
ok( wrapperRunning.two, "wrapper two is running at second 7" );
|
||||
plus();
|
||||
ok( !wrapperRunning.one, "wrapper one is stopped at second 7" );
|
||||
plus();
|
||||
}
|
||||
})
|
||||
// checking wrapper 2's end
|
||||
.exec( 8, function() {
|
||||
|
||||
if ( execCount === 3 ) {
|
||||
|
||||
execCount++;
|
||||
ok( !wrapperRunning.two, "wrapper two is stopped at second 9" );
|
||||
plus();
|
||||
ok( !wrapperRunning.one, "wrapper one is stopped at second 9" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
p2.currentTime( 3 ).play();
|
||||
});
|
||||
|
||||
module( "Popcorn Parser" );
|
||||
|
||||
test( "Parsing Functions", function() {
|
||||
|
||||
var expects = 3,
|
||||
count = 0,
|
||||
popperly = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop( 10000 );
|
||||
|
||||
ok( typeof Popcorn.parser === "function", "Popcorn.parser is a function" );
|
||||
plus();
|
||||
|
||||
Popcorn.parser( "parseJSON" , "json", function( data ){
|
||||
return data;
|
||||
});
|
||||
|
||||
ok( typeof popperly.parseJSON === "function", "Popcorn.parser created a parseJSON function" );
|
||||
plus();
|
||||
|
||||
ok( typeof popperly.parseJSON().parseJSON( "data/test.js" ).parseJSON === "function" , "parseJSON function is chainable" );
|
||||
plus();
|
||||
});
|
||||
|
||||
test( "Parsing Integrity", function() {
|
||||
|
||||
var expects = 6,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
poppercore = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
// clean up added events after tests
|
||||
Popcorn.removePlugin( "parserTest" );
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop( 10000 );
|
||||
|
||||
Popcorn.parser( "parseJSON2", function( data ){
|
||||
ok( typeof data.json === "object", "data.json exists" );
|
||||
plus();
|
||||
return data.json;
|
||||
});
|
||||
|
||||
Popcorn.parser( "parseJSON3" , "json", function( data ){
|
||||
ok( typeof data === "object", "data exists" );
|
||||
plus();
|
||||
return data;
|
||||
});
|
||||
|
||||
Popcorn.plugin( "parserTest", {
|
||||
|
||||
start: function() {
|
||||
ok( true, "parserTest started" );
|
||||
plus();
|
||||
},
|
||||
end: function() {
|
||||
ok( true, "parserTest ended" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
poppercore.parseJSON2( "data/parserData.json", function() {
|
||||
|
||||
poppercore.parseJSON3( "data/parserData.json", function() {
|
||||
poppercore.currentTime( 5 ).play();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test( "Parsing Handler - References unavailable plugin", function() {
|
||||
|
||||
var expects = 1,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
interval,
|
||||
poppercore = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
// clean up added events after tests
|
||||
clearInterval( interval );
|
||||
poppercore.removePlugin( "parserTest" );
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
|
||||
stop();
|
||||
|
||||
Popcorn.parser( "parseJson", function( data ){
|
||||
|
||||
return data.json;
|
||||
});
|
||||
|
||||
poppercore.parseJson( "data/parseMissing.json" );
|
||||
|
||||
// interval used to wait for data to be parsed
|
||||
interval = setInterval( function() {
|
||||
poppercore.currentTime( 5 ).play().currentTime( 6 );
|
||||
|
||||
ok( true, "Ignored call to missing plugin " );
|
||||
plus();
|
||||
}, 2000 );
|
||||
});
|
||||
|
||||
module( "Audio" );
|
||||
test( "Basic Audio Support (timeupdate)", function() {
|
||||
|
||||
|
@ -4290,49 +4104,6 @@ test( "Basic Audio Support (frameAnimation)", function() {
|
|||
});
|
||||
});
|
||||
|
||||
test( "Parser Support", function() {
|
||||
|
||||
var expects = 3,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
interval,
|
||||
audiocorn = Popcorn( "#audio" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
|
||||
Popcorn.removePlugin( "testAudioParser" );
|
||||
}
|
||||
}
|
||||
|
||||
expect( expects );
|
||||
stop( 5000 );
|
||||
|
||||
Popcorn.plugin( "testAudioParser", {
|
||||
|
||||
start: function() {
|
||||
ok( true, "testAudioParser started: " + Math.round( this.currentTime() ) );
|
||||
plus();
|
||||
},
|
||||
end: function() {
|
||||
ok( true, "testAudioParser ended: " + Math.round( this.currentTime() ) );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
Popcorn.parser( "parseAudio", function( data ){
|
||||
ok( typeof data.json === "object", "data.json exists");
|
||||
plus();
|
||||
return data.json;
|
||||
});
|
||||
|
||||
audiocorn.parseAudio( "data/parserAudio.json", function() {
|
||||
|
||||
audiocorn.currentTime( 4 ).play();
|
||||
});
|
||||
});
|
||||
|
||||
module( "Popcorn Test Runner End" );
|
||||
test( "Last Check", function() {
|
||||
// Trigger follow-up tests to run in iframes
|
||||
|
|
Загрузка…
Ссылка в новой задаче