Merge branch '0.2' of github.com:annasob/popcorn-js into webpagePlugin

This commit is contained in:
Anna Sobiepanek 2010-12-05 12:56:25 -05:00
Родитель 1f3fd80851 9768f67d85
Коммит eb345146a0
6 изменённых файлов: 756 добавлений и 83 удалений

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

@ -97,7 +97,8 @@
}
return size;
}
},
nop: function () {}
});
// Simple Factory pattern to implement native
@ -108,7 +109,7 @@
Popcorn.extend(Popcorn.p, (function () {
// todo: play, pause, mute should toggle
var methods = "load play pause currentTime playbackRate mute volume",
var methods = "load play pause currentTime playbackRate mute volume duration",
ret = {};
// Build methods, store in object that is returned and passed to extend
@ -122,7 +123,10 @@
return this;
}
if ( arg ) {
if ( arg !== false && arg !== null && typeof arg !== "undefined" ) {
this.video[ name ] = arg;
return this;
@ -194,7 +198,7 @@
},
listen: function ( type, fn ) {
var self = this, hasEvents = true;
var self = this, hasEvents = true, ns = '';
if ( !this.data.events[type] ) {
this.data.events[type] = {};
@ -246,7 +250,86 @@
// Provides some sugar, but ultimately extends
// the definition into Popcorn.p
var plugin = {};
var natives = nativeEvents.split(/\s+/g),
reserved = [ "start", "end", "timeupdate" ],
plugin = {},
setup;
if ( typeof definition === "object" ) {
setup = definition;
if ( !( "timeupdate" in setup ) ) {
setup.timeupdate = Popcorn.nop;
}
definition = function ( options ) {
var self = this;
if ( !options ) {
return this;
}
// Checks for expected properties
if ( !( "start" in options ) ) {
options.start = 0;
}
if ( !( "end" in options ) ) {
options.end = this.duration();
}
// If a _setup was declared, then call it before
// the events commence
if ( "_setup" in setup && typeof setup._setup === "function" ) {
setup._setup.call(self, options);
}
// Plugin timeline handler
this.listen( "timeupdate", function( event ) {
if ( ~~self.currentTime() === options.start ||
self.currentTime() === options.start ) {
setup.start.call(self, event, options);
}
if ( self.currentTime() > options.start &&
self.currentTime() < options.end ) {
setup.timeupdate.call(self, event, options);
}
if ( ~~self.currentTime() === options.end ||
self.currentTime() === options.end ) {
setup.end.call(self, event, options);
}
});
// Future support for plugin event definitions
// for all of the native events
Popcorn.forEach( setup, function ( callback, type ) {
if ( reserved.indexOf(type) === -1 ) {
this.listen( type, callback );
}
}, this);
return this;
};
}
plugin[ name ] = definition;

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

@ -2,6 +2,40 @@
(function (Popcorn) {
Popcorn.plugin( "complicator", (function () {
//create your fucking dom elements here.
return {
start: function () {
},
end: function () {
},
timeupdate: function () {
}
};
})()
);
Popcorn.plugin( "subtitler" , function ( options ) {
var subtitles = [],
@ -12,12 +46,14 @@
if ( !div ) {
// if no existing frame, create it.
div = document.createElement("div");
div.id = "subtitle-container";
div.id = "subtitle-container";
context.parentNode.appendChild(div);
Popcorn.extend(div.style, {
//border: "1px solid red",
width: context.clientWidth + "px",
height: context.clientHeight + "px",
width: context.clientWidth + "px", //offsetWidth
height: context.clientHeight + "px", //offsetHeight
top: context.offsetTop + "px",
left: context.offsetLeft + "px",
position: "absolute",
@ -28,7 +64,7 @@
textAlign: "center"
});
context.parentNode.appendChild(div);
}
if ( typeof options === "object" && "join" in options ) {
@ -47,15 +83,18 @@
div.innerHTML = div.innerHTML + subtitle.html;
}
if ( this.currentTime() >= subtitle.end ) {
if ( temp.length ) {
Popcorn.forEach(temp, function ( title ) {
if ( temp.length && this.currentTime() >= subtitle.end ) {
Popcorn.forEach(temp, function ( title ) {
if ( title && title.style ) {
title.style.display = "none";
});
}
}
});
}
}, this);
});
});
@ -69,6 +108,9 @@ $(function () {
var p = Popcorn('#video');
p.play();
@ -107,6 +149,15 @@ $(function () {
}
]);
p.complicator({
start: 1,
end: 10,
wtf: "throws exception?"
});

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

@ -9,10 +9,10 @@
do not move - this must be called immediately prior to
popcorn-api-draft.js
-->
<script src="popcorn-api-draft-unit-setup.js"></script>
<script src="popcorn.unit.setup.js"></script>
<script src="../popcorn.js"></script>
<script src="popcorn-api-draft-unit.js"></script>
<script src="popcorn.unit.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn API</h1>

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

@ -71,66 +71,23 @@ test("Popcorn Object", function () {
});
test("Popcorn Plugin", function () {
// needs expectation
var popped = Popcorn("#video"),
methods = "load play pause currentTime mute volume";
Popcorn.plugin("subtitles", function ( ) {
var self = this;
// These ensure that a popcorn instance is the value of `this` inside a plugin definition
methods.split(/\s+/g).forEach(function (k,v) {
ok( k in self, "instance has method: " + k );
});
ok( "video" in this, "instance has `video` property" );
ok( Object.prototype.toString.call(popped.video) === "[object HTMLVideoElement]", "video property is a HTMLVideoElement" );
ok( "data" in this, "instance has `data` property" );
ok( Object.prototype.toString.call(popped.data) === "[object Object]", "data property is an object" );
ok( "tracks" in this.data, "instance has `tracks` property" );
ok( Object.prototype.toString.call(popped.data.tracks) === "[object Array]", "tracks property is an array" )
});
ok( "subtitles" in popped, "plugin is now available to instance" );
popped.subtitles();
ok( Popcorn.registry.length === 1, "One item in the registry");
});
test("Popcorn Events Stored By Type", function () {
QUnit.reset();
expect(6)
var p = Popcorn("#video"),
count = 0,
fired = 0
fired = 0,
wants = 4
;
function plus(){
if ( ++count == 4 ) {
if ( fired === 4 ) {
ok( true, fired + " callbacks fired from 1 handler" );
}
else {
ok( false, fired + " callbacks fired - CHECK HANDLERS" );
}
equals( fired, wants, "Number of callbacks fired from 1 handler" );
p.unlisten("play");
@ -146,34 +103,34 @@ test("Popcorn Events Stored By Type", function () {
p.listen("play", function () {
fired++;
ok(true, "Play fired");
ok(true, "Play fired " + fired);
plus();
});
p.listen("play", function () {
fired++;
ok(true, "Play fired");
ok(true, "Play fired " + fired);
plus();
});
p.listen("play", function () {
fired++;
ok(true, "Play fired");
ok(true, "Play fired " + fired);
plus();
});
p.listen("play", function () {
fired++;
ok(true, "Play fired");
ok(true, "Play fired " + fired);
plus();
});
p.trigger("play");
p.unlisten("play");
});
@ -225,7 +182,8 @@ test("Popcorn Events Simulated", function () {
test("Popcorn Events Real", function () {
QUnit.reset();
var p = Popcorn("#video"),
completed = [],
@ -235,7 +193,7 @@ test("Popcorn Events Real", function () {
events = eventtest.split(/\s+/g);
var expects = events.length,
var expects = 11,
count = 0;
//expect(expects);
@ -275,16 +233,100 @@ test("Popcorn Events Real", function () {
setTimeout(function() {
//console.log(completed);
start();
}, 5000);
});
test("Popcorn Plugin", function () {
QUnit.reset();
// needs expectation
var popped = Popcorn("#video"),
methods = "load play pause currentTime mute volume";
stop();
Popcorn.plugin("subtitles", function () {
var self = this;
// These ensure that a popcorn instance is the value of `this` inside a plugin definition
methods.split(/\s+/g).forEach(function (k,v) {
ok( k in self, "instance has method: " + k );
});
ok( "video" in this, "instance has `video` property" );
ok( Object.prototype.toString.call(popped.video) === "[object HTMLVideoElement]", "video property is a HTMLVideoElement" );
ok( "data" in this, "instance has `data` property" );
ok( Object.prototype.toString.call(popped.data) === "[object Object]", "data property is an object" );
ok( "tracks" in this.data, "instance has `tracks` property" );
ok( Object.prototype.toString.call(popped.data.tracks) === "[object Array]", "tracks property is an array" )
});
// Call plugin to test scope within
popped.subtitles();
ok( "subtitles" in popped, "subtitles plugin is now available to instance" );
ok( Popcorn.registry.length === 1, "One item in the registry");
Popcorn.plugin("complicator", {
start: function ( event ) {
equals( ~~this.currentTime(), 1, "~~this.currentTime() === 1");
var self = this;
// These ensure that a popcorn instance is the value of `this` inside a plugin definition
methods.split(/\s+/g).forEach(function (k,v) {
ok( k in self, "instance has method: " + k );
});
ok( "video" in this, "instance has `video` property" );
ok( Object.prototype.toString.call(popped.video) === "[object HTMLVideoElement]", "video property is a HTMLVideoElement" );
ok( "data" in this, "instance has `data` property" );
ok( Object.prototype.toString.call(popped.data) === "[object Object]", "data property is an object" );
ok( "tracks" in this.data, "instance has `tracks` property" );
ok( Object.prototype.toString.call(popped.data.tracks) === "[object Array]", "tracks property is an array" )
},
end: function () {
start();
},
timeupdate: function () {
}
});
ok( "complicator" in popped, "complicator plugin is now available to instance" );
ok( Popcorn.registry.length === 2, "Two items in the registry");
popped.currentTime(0);
popped.complicator({
start: 1,
end: 2
});
});

451
test/popcorn.unit.js Normal file
Просмотреть файл

@ -0,0 +1,451 @@
test("Popcorn API", function () {
var expects = 3,
count = 0;
expect(expects);
function plus(){ if ( ++count == expects ) start(); }
stop();
try {
ok( Popcorn, "Popcorn exists");
plus();
} catch (e) {};
try {
ok( typeof Popcorn === "function", "Popcorn is a function");
plus();
} catch (e) {};
try {
equals( Setup.getGlobalSize(), Setup.globalSize + 1 , "Popcorn API creates only 1 global reference");
plus();
} catch (e) {};
});
test("Popcorn Utility", function () {
equals( typeof Popcorn.forEach, "function" , "Popcorn.forEach is a provided utility function");
equals( typeof Popcorn.extend, "function" , "Popcorn.extend is a provided utility function");
});
test("Popcorn Object", function () {
var popped = Popcorn("#video"),
methods = "load play pause currentTime mute volume";
//console.log(popped);
popped.play();
methods.split(/\s+/g).forEach(function (k,v) {
ok( k in popped, "instance has method: " + k );
});
ok( "video" in popped, "instance has `video` property" );
ok( Object.prototype.toString.call(popped.video) === "[object HTMLVideoElement]", "video property is a HTMLVideoElement" );
ok( "data" in popped, "instance has `data` property" );
ok( Object.prototype.toString.call(popped.data) === "[object Object]", "data property is an object" );
ok( "tracks" in popped.data, "instance has `tracks` property" );
ok( Object.prototype.toString.call(popped.data.tracks) === "[object Array]", "tracks property is an array" )
});
test("Popcorn Events Stored By Type", function () {
QUnit.reset();
expect(6)
var p = Popcorn("#video"),
count = 0,
fired = 0,
wants = 4
;
function plus(){
if ( ++count == 4 ) {
equals( fired, wants, "Number of callbacks fired from 1 handler" );
p.unlisten("play");
ok( !p.data.events["play"], "play handlers removed" );
start();
}
}
stop();
p.listen("play", function () {
fired++;
ok(true, "Play fired " + fired);
plus();
});
p.listen("play", function () {
fired++;
ok(true, "Play fired " + fired);
plus();
});
p.listen("play", function () {
fired++;
ok(true, "Play fired " + fired);
plus();
});
p.listen("play", function () {
fired++;
ok(true, "Play fired " + fired);
plus();
});
p.trigger("play");
p.unlisten("play");
});
test("Popcorn Events Simulated", function () {
QUnit.reset();
var p = Popcorn("#video"),
completed = [];
var expects = Setup.events.length,
count = 0;
expect(expects);
function plus(){
if ( ++count == expects ) start();
}
stop();
Setup.events.forEach(function ( name ) {
p.listen( name, function (event) {
if ( completed.indexOf(name) === -1 ) {
ok(true, name + " fired");
plus();
completed.push(name);
}
});
});
Setup.events.forEach(function ( name ) {
p.trigger( name );
});
});
test("Popcorn Events Real", function () {
QUnit.reset();
var p = Popcorn("#video"),
completed = [];
var expects = 11,
count = 0;
//expect(expects);
// not in full use
function plus(){
if ( ++count == expects ) start();
}
stop();
Setup.events.forEach(function ( name ) {
p.listen( name, function (event) {
if ( completed.indexOf(name) === -1 ) {
ok(true, name + " fired");
plus();
completed.push(name);
}
});
});
p.pause();
p.mute(true);
p.play();
p.volume(0.9);
p.currentTime(49);
});
test("Popcorn Plugin", function () {
QUnit.reset();
// needs expectation
var popped = Popcorn("#video"),
methods = "load play pause currentTime mute volume";
stop();
Popcorn.plugin("subtitles", function () {
var self = this;
// These ensure that a popcorn instance is the value of `this` inside a plugin definition
methods.split(/\s+/g).forEach(function (k,v) {
ok( k in self, "instance has method: " + k );
});
ok( "video" in this, "instance has `video` property" );
ok( Object.prototype.toString.call(popped.video) === "[object HTMLVideoElement]", "video property is a HTMLVideoElement" );
ok( "data" in this, "instance has `data` property" );
ok( Object.prototype.toString.call(popped.data) === "[object Object]", "data property is an object" );
ok( "tracks" in this.data, "instance has `tracks` property" );
ok( Object.prototype.toString.call(popped.data.tracks) === "[object Array]", "tracks property is an array" )
});
// Call plugin to test scope within
popped.subtitles();
ok( "subtitles" in popped, "subtitles plugin is now available to instance" );
ok( Popcorn.registry.length === 1, "One item in the registry");
Popcorn.plugin("complicator", {
start: function ( event ) {
equals( ~~this.currentTime(), 1, "~~this.currentTime() === 1");
var self = this;
// These ensure that a popcorn instance is the value of `this` inside a plugin definition
methods.split(/\s+/g).forEach(function (k,v) {
ok( k in self, "instance has method: " + k );
});
ok( "video" in this, "instance has `video` property" );
ok( Object.prototype.toString.call(popped.video) === "[object HTMLVideoElement]", "video property is a HTMLVideoElement" );
ok( "data" in this, "instance has `data` property" );
ok( Object.prototype.toString.call(popped.data) === "[object Object]", "data property is an object" );
ok( "tracks" in this.data, "instance has `tracks` property" );
ok( Object.prototype.toString.call(popped.data.tracks) === "[object Array]", "tracks property is an array" )
},
end: function () {
//start();
},
timeupdate: function () {
}
});
ok( "complicator" in popped, "complicator plugin is now available to instance" );
ok( Popcorn.registry.length === 2, "Two items in the registry");
popped.currentTime(0);
popped.complicator({
start: 1,
end: 2
});
Popcorn.plugin("breaker", {
start: function () {
ok(true, "plugin:breaker started");
},
end: function () {
ok(true, "plugin:ended started");
start();
}
});
popped.currentTime(0);
popped.breaker({
start: 1,
end: 2
});
});
test("Popcorn Plugin Extended Events", function () {
//QUnit.reset();
// needs expectation
var popped = Popcorn("#video"),
expects = 11,
count = 0;
//expect(expects);
// not in full use
function plus(){
if ( ++count == expects ) start();
}
stop();
Popcorn.plugin("extendedEvents", (function () {
var pluginObj = {
start: function() {
},
end: function() {
}
};
$.each( Setup.events, function ( k, type ) {
pluginObj[type] = function (event, opts) {
ok( true, type + " fired!" );
plus();
};
});
return pluginObj;
})());
popped.extendedEvents({
start: 20,
end: 21
});
popped.currentTime(19).play();
});
/*
module("Popcorn Video Object")
test("wait()", function () {
//QUnit.reset();
// needs expectation
var popped = Popcorn("#video"),
startat = +new Date();
popped.play().wait(2).exec(function () {
console.log( +new Date() - startat );
ok(true)
}).pause();
});
*/

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

@ -0,0 +1,46 @@
(function (global) {
// Store the number of global properties that exist prior to Popcorn API definition
var Setup = {
globalSize: 0
};
Setup.getGlobalSize = function() {
var size = 0;
for( var p in window ) {
if ( p !== "_firebug" ) {
size++;
}
}
// account for self
size++;
// Store the number of global properties internally
if ( !Setup.globalSize ) {
Setup.globalSize = size;
}
return size;
};
Setup.eventset = "loadstart progress suspend emptied stalled play pause " +
"loadedmetadata loadeddata waiting playing canplay canplaythrough " +
"seeking seeked timeupdate ended ratechange durationchange volumechange";
Setup.events = Setup.eventset.split(/\s+/g);
global.Setup = Setup;
})(window);
Setup.getGlobalSize();