зеркало из https://github.com/mozilla/popcorn-js.git
Merge remote-tracking branch 'wmm/master'
This commit is contained in:
Коммит
423aec6e25
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* popcorn.js version @VERSION
|
||||
* http://popcornjs.org
|
||||
*
|
||||
* Copyright 2011, Mozilla Foundation
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
|
25
Makefile
25
Makefile
|
@ -55,6 +55,9 @@ POPCORN_COMPLETE_LIST := --js ${POPCORN_SRC} \
|
|||
POPCORN_COMPLETE_DIST = ${DIST_DIR}/popcorn-complete.js
|
||||
POPCORN_COMPLETE_MIN = ${DIST_DIR}/popcorn-complete.min.js
|
||||
|
||||
# Create a versioned license header for js files we ship: arg1=source arg2=dest
|
||||
add_license = cat ${PREFIX}/LICENSE_HEADER | sed -e 's/@VERSION/${VERSION}/' > $(2) ; \
|
||||
cat $(1) >> $(2)
|
||||
|
||||
all: lint lint-plugins lint-parsers lint-players popcorn plugins parsers players complete min
|
||||
@@echo "Popcorn build complete."
|
||||
|
@ -66,23 +69,27 @@ popcorn: ${POPCORN_DIST}
|
|||
|
||||
${POPCORN_DIST}: ${POPCORN_SRC} | ${DIST_DIR}
|
||||
@@echo "Building" ${POPCORN_DIST}
|
||||
@@cat ${POPCORN_SRC} | sed -e 's/@VERSION/${VERSION}/' > ${POPCORN_DIST}
|
||||
@@$(call add_license, $(POPCORN_SRC), $(POPCORN_DIST))
|
||||
|
||||
min: ${POPCORN_MIN} ${PLUGINS_MIN} ${PARSERS_MIN} ${PLAYERS_MIN} ${POPCORN_COMPLETE_MIN}
|
||||
|
||||
${POPCORN_MIN}: ${POPCORN_DIST}
|
||||
@@echo "Building" ${POPCORN_MIN}
|
||||
$(call compile, --js ${POPCORN_DIST}, ${POPCORN_MIN})
|
||||
@@$(call compile, --js ${POPCORN_DIST}, ${POPCORN_MIN}.tmp)
|
||||
@@$(call add_license, ${POPCORN_MIN}.tmp, ${POPCORN_MIN})
|
||||
@@rm ${POPCORN_MIN}.tmp
|
||||
|
||||
${POPCORN_COMPLETE_MIN}: ${POPCORN_SRC} ${PLUGINS_SRC} ${PARSERS_SRC} ${DIST_DIR}
|
||||
@@echo "Building" ${POPCORN_COMPLETE_MIN}
|
||||
@@$(call compile, ${POPCORN_COMPLETE_LIST}, ${POPCORN_COMPLETE_MIN})
|
||||
@@$(call compile, ${POPCORN_COMPLETE_LIST}, ${POPCORN_COMPLETE_MIN}.tmp)
|
||||
@@$(call add_license, ${POPCORN_COMPLETE_MIN}.tmp, ${POPCORN_COMPLETE_MIN})
|
||||
@@rm ${POPCORN_COMPLETE_MIN}.tmp
|
||||
|
||||
plugins: ${PLUGINS_DIST}
|
||||
|
||||
${PLUGINS_MIN}: ${PLUGINS_DIST}
|
||||
@@echo "Building" ${PLUGINS_MIN}
|
||||
$(call compile, $(shell for js in ${PLUGINS_SRC} ; do echo --js $$js ; done), ${PLUGINS_MIN})
|
||||
@@$(call compile, $(shell for js in ${PLUGINS_SRC} ; do echo --js $$js ; done), ${PLUGINS_MIN})
|
||||
|
||||
${PLUGINS_DIST}: ${PLUGINS_SRC} ${DIST_DIR}
|
||||
@@echo "Building ${PLUGINS_DIST}"
|
||||
|
@ -92,7 +99,7 @@ parsers: ${PARSERS_DIST}
|
|||
|
||||
${PARSERS_MIN}: ${PARSERS_DIST}
|
||||
@@echo "Building" ${PARSERS_MIN}
|
||||
$(call compile, $(shell for js in ${PARSERS_SRC} ; do echo --js $$js ; done), ${PARSERS_MIN})
|
||||
@@$(call compile, $(shell for js in ${PARSERS_SRC} ; do echo --js $$js ; done), ${PARSERS_MIN})
|
||||
|
||||
${PARSERS_DIST}: ${PARSERS_SRC} ${DIST_DIR}
|
||||
@@echo "Building ${PARSERS_DIST}"
|
||||
|
@ -102,15 +109,17 @@ players: ${PLAYERS_DIST}
|
|||
|
||||
${PLAYERS_MIN}: ${PLAYERS_DIST}
|
||||
@@echo "Building" ${PLAYERS_MIN}
|
||||
$(call compile, $(shell for js in ${PLAYERS_SRC} ; do echo --js $$js ; done), ${PLAYERS_MIN})
|
||||
@@$(call compile, $(shell for js in ${PLAYERS_SRC} ; do echo --js $$js ; done), ${PLAYERS_MIN})
|
||||
|
||||
${PLAYERS_DIST}: ${PLAYERS_SRC} ${DIST_DIR}
|
||||
@@echo "Building ${PLAYERS_DIST}"
|
||||
@@cat ${PLAYERS_SRC} > ${PLAYERS_DIST}
|
||||
|
||||
complete: ${POPCORN_SRC} ${PARSERS_SRC} ${PLUGINS_SRC} ${PLAYERS_SRC} ${DIST_DIR}
|
||||
@@echo "Building popcorn + plugins + parsers + players"
|
||||
@@cat ${POPCORN_SRC} ${PLUGINS_SRC} ${PARSERS_SRC} ${PLAYERS_SRC} | sed -e 's/@VERSION/${VERSION}/' > ${POPCORN_COMPLETE_DIST}
|
||||
@@echo "Building popcorn + plugins + parsers + players..."
|
||||
@@cat ${POPCORN_SRC} ${PLUGINS_SRC} ${PARSERS_SRC} ${PLAYERS_SRC} > ${POPCORN_COMPLETE_DIST}.tmp
|
||||
@@$(call add_license, ${POPCORN_COMPLETE_DIST}.tmp, ${POPCORN_COMPLETE_DIST})
|
||||
@@rm ${POPCORN_COMPLETE_DIST}.tmp
|
||||
|
||||
lint:
|
||||
@@echo "Checking Popcorn against JSLint..."
|
||||
|
|
|
@ -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":"audio-iframe-container",
|
||||
"src":"http://json.org"
|
||||
}
|
||||
},
|
||||
{
|
||||
"footnote": {
|
||||
"start":"0.23530116023787565",
|
||||
"end":"2.0193976413772767",
|
||||
"target":"audio-footnote-container",
|
||||
"text":"I invented JSON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"googlemap": {
|
||||
"start":"0.09096385771969716",
|
||||
"end":"8.617349362660605",
|
||||
"target":"audio-map-container",
|
||||
"type":"ROADMAP",
|
||||
"lat":37.7749295,
|
||||
"lng":-122.4194155,
|
||||
"location":"San Francisco, CA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"webpage": {
|
||||
"start":"2.073975956009095",
|
||||
"end":"10.278915922325776",
|
||||
"target":"audio-iframe-container",
|
||||
"src":"http://jslint.org"
|
||||
}
|
||||
},
|
||||
{
|
||||
"footnote": {
|
||||
"start":2.145542172351516,
|
||||
"end":10.145542172351513,
|
||||
"target":"audio-footnote-container",
|
||||
"text":"I wrote JSLint"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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":"video-iframe-container",
|
||||
"src":"http://json.org"
|
||||
}
|
||||
},
|
||||
{
|
||||
"footnote": {
|
||||
"start":"0.23530116023787565",
|
||||
"end":"2.0193976413772767",
|
||||
"target":"video-footnote-container",
|
||||
"text":"I invented JSON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"googlemap": {
|
||||
"start":"0.09096385771969716",
|
||||
"end":"8.617349362660605",
|
||||
"target":"video-map-container",
|
||||
"type":"ROADMAP",
|
||||
"lat":37.7749295,
|
||||
"lng":-122.4194155,
|
||||
"location":"San Francisco, CA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"webpage": {
|
||||
"start":"2.073975956009095",
|
||||
"end":"10.278915922325776",
|
||||
"target":"video-iframe-container",
|
||||
"src":"http://jslint.org"
|
||||
}
|
||||
},
|
||||
{
|
||||
"footnote": {
|
||||
"start":2.145542172351516,
|
||||
"end":10.145542172351513,
|
||||
"target":"video-footnote-container",
|
||||
"text":"I wrote JSLint"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -41,14 +41,26 @@
|
|||
<p>Your user agent does not support the HTML5 Video element.</p>
|
||||
|
||||
</video>
|
||||
|
||||
<audio id='audio' src="../../test/italia.ogg" data-timeline-sources="data/audio.json" controls>
|
||||
</audio>
|
||||
|
||||
<style>
|
||||
.displays {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
<div class="displays" id="iframe-container"></div>
|
||||
<div class="displays" id="map-container"></div>
|
||||
<div class="displays" id="footnote-container"></div>
|
||||
<hr>
|
||||
<div style="width:300px;float:left">
|
||||
<div class="displays" id="video-iframe-container"></div>
|
||||
<div class="displays" id="video-map-container"></div>
|
||||
<div class="displays" id="video-footnote-container"></div>
|
||||
</div>
|
||||
<div style="width:300px;float:left">
|
||||
<div class="displays" id="audio-iframe-container"></div>
|
||||
<div class="displays" id="audio-map-container"></div>
|
||||
<div class="displays" id="audio-footnote-container"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,18 +7,15 @@ test("Popcorn 0.3 JSON Parser Plugin", function () {
|
|||
finished = false,
|
||||
trackData,
|
||||
trackEvents,
|
||||
interval,
|
||||
poppercorn = Popcorn( "#video" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
// clean up added events after tests
|
||||
clearInterval( interval );
|
||||
}
|
||||
}
|
||||
|
||||
poppercorn.parseJSON("data/data.json");
|
||||
poppercorn.parseJSON("data/video.json");
|
||||
|
||||
expect(expects);
|
||||
|
||||
|
@ -29,14 +26,17 @@ test("Popcorn 0.3 JSON Parser Plugin", function () {
|
|||
trackEvents = trackData.trackEvents;
|
||||
|
||||
Popcorn.xhr({
|
||||
url: 'data/data.json',
|
||||
url: 'data/video.json',
|
||||
success: function( data ) {
|
||||
|
||||
var idx = 0;
|
||||
|
||||
Popcorn.forEach( data.json.data, function (dataObj) {
|
||||
Popcorn.forEach( dataObj, function ( obj, key ) {
|
||||
//console.log( data );
|
||||
|
||||
Popcorn.forEach( data.json.data, function (dataObj) {
|
||||
|
||||
//console.log( dataObj );
|
||||
Popcorn.forEach( dataObj, function ( obj, key ) {
|
||||
|
||||
equals( trackData.history[idx].indexOf(key), 0, "history item '" + trackData.history[idx] + "' matches data key '"+ key+ "' at correct index" );
|
||||
plus();
|
||||
|
@ -59,11 +59,11 @@ test("Popcorn 0.3 JSON Parser Plugin", function () {
|
|||
plus();
|
||||
|
||||
|
||||
equals( $("#iframe-container").children().length, 2, '$("#iframe-container").children().length' )
|
||||
equals( $("#video-iframe-container").children().length, 2, '$("#video-iframe-container").children().length' )
|
||||
plus();
|
||||
equals( $("#map-container").children().length, 1, '$("#map-container").children().length' );
|
||||
equals( $("#video-map-container").children().length, 1, '$("#video-map-container").children().length' );
|
||||
plus();
|
||||
equals( $("#footnote-container").children().length, 2, '$("#footnote-container").children().length' );
|
||||
equals( $("#video-footnote-container").children().length, 2, '$("#video-footnote-container").children().length' );
|
||||
plus();
|
||||
|
||||
this.pause();
|
||||
|
@ -80,3 +80,87 @@ test("Popcorn 0.3 JSON Parser Plugin", function () {
|
|||
}, 500);
|
||||
|
||||
});
|
||||
|
||||
test("Popcorn 0.3 JSON Parser Plugin - AUDIO", function () {
|
||||
|
||||
var expects = 9,
|
||||
count = 0,
|
||||
timeOut = 0,
|
||||
numLoadingEvents = 5,
|
||||
finished = false,
|
||||
trackData,
|
||||
trackEvents,
|
||||
interval,
|
||||
audiocorn = Popcorn.getInstanceById("audio");
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
// clean up added events after tests
|
||||
clearInterval( interval );
|
||||
}
|
||||
}
|
||||
|
||||
expect(expects);
|
||||
|
||||
stop( 5000 );
|
||||
|
||||
|
||||
trackData = audiocorn.data;
|
||||
trackEvents = trackData.trackEvents;
|
||||
|
||||
|
||||
Popcorn.xhr({
|
||||
url: 'data/audio.json',
|
||||
success: function( data ) {
|
||||
|
||||
var idx = 0;
|
||||
|
||||
Popcorn.forEach( data.json.data, function (dataObj) {
|
||||
Popcorn.forEach( dataObj, function ( obj, key ) {
|
||||
|
||||
|
||||
equals( trackData.history[idx].indexOf(key), 0, "history item '" + trackData.history[idx] + "' matches data key '"+ key+ "' at correct index" );
|
||||
plus();
|
||||
|
||||
idx++;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
audiocorn.listen("timeupdate", function ( event ) {
|
||||
|
||||
|
||||
if ( Math.round( this.currentTime()) === 3 && !finished ) {
|
||||
|
||||
finished = true;
|
||||
|
||||
equals( trackEvents.byStart.length, numLoadingEvents + 2 , "trackEvents.byStart.length === (5 loaded, 2 padding) " );
|
||||
plus();
|
||||
|
||||
|
||||
equals( $("#audio-iframe-container").children().length, 2, '$("#audio-iframe-container").children().length' )
|
||||
plus();
|
||||
equals( $("#audio-map-container").children().length, 1, '$("#audio-map-container").children().length' );
|
||||
plus();
|
||||
equals( $("#audio-footnote-container").children().length, 2, '$("#audio-footnote-container").children().length' );
|
||||
plus();
|
||||
|
||||
this.pause();
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
setTimeout(function () {
|
||||
|
||||
audiocorn.currentTime(0).play()
|
||||
|
||||
}, 500);
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Base Player Example</title>
|
||||
<style>
|
||||
body > div {
|
||||
width: 100%;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
div div {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
#player_1 {
|
||||
position: absolute;
|
||||
left: 250px;
|
||||
top: 20px;
|
||||
width: 300px;
|
||||
height: 150px;
|
||||
background: #FFAAAA;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script type="text/javascript" src="popcorn.baseplayer.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
//On document ready
|
||||
document.addEventListener( "DOMContentLoaded", function() {
|
||||
var ticks = 0,
|
||||
player = Popcorn.baseplayer(),
|
||||
dimensions,
|
||||
popcorn;
|
||||
|
||||
document.getElementById( "btnPlay" ).addEventListener( "click", function() { popcorn.play(); }, false );
|
||||
document.getElementById( "btnPause" ).addEventListener( "click", function() { popcorn.pause(); }, false );
|
||||
|
||||
player._resource = document.getElementById('player_1');
|
||||
|
||||
player._resource.innerHTML += '<br />Width and Height: '+player.getStyle( 'width' ) + ' by ' + player.getStyle( 'height' )
|
||||
+ '<br /> Positioned at: '+player.getStyle( 'left' ) + ',' + player.getStyle( 'top' );
|
||||
|
||||
dimensions = player.getBoundingClientRect();
|
||||
document.getElementById( "playerTop" ).innerHTML = dimensions.top;
|
||||
document.getElementById( "playerLeft" ).innerHTML = dimensions.left;
|
||||
document.getElementById( "playerBottom" ).innerHTML = dimensions.bottom;
|
||||
document.getElementById( "playerRight" ).innerHTML = dimensions.right;
|
||||
document.getElementById( "playerWidth" ).innerHTML = dimensions.width;
|
||||
document.getElementById( "playerHeight" ).innerHTML = dimensions.height;
|
||||
|
||||
popcorn = Popcorn( player )
|
||||
.listen( "timeupdate", function() {
|
||||
document.getElementById( "playerTicks" ).innerHTML = ++ticks;
|
||||
document.getElementById( "playerMs" ).innerHTML = popcorn.currentTime().toFixed(5);
|
||||
})
|
||||
.exec( 2, function() {
|
||||
document.getElementById( "playerOutput" ).innerHTML = "2 seconds reached";
|
||||
});
|
||||
|
||||
// The ready state and resource selection would be handled by the player extending this base player
|
||||
player.readyState = 2;
|
||||
popcorn.play();
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Ticks: <span id="playerTicks" ></span><br />
|
||||
Seconds: <span id="playerMs" ></span><br />
|
||||
Event Output: <span id="playerOutput" ></span><br />
|
||||
<button class="simple" id="btnPlay">Play</button>
|
||||
<button class="simple" id="btnPause">Pause</button><br r/>
|
||||
Top: <span id="playerTop" ></span><br />
|
||||
Left: <span id="playerLeft" ></span><br />
|
||||
Bottom: <span id="playerBottom" ></span><br />
|
||||
Right: <span id="playerRight" ></span><br />
|
||||
Width: <span id="playerWidth" ></span><br />
|
||||
Height: <span id="playerHeight" ></span><br />
|
||||
</div>
|
||||
|
||||
<span id="player_1">This is a container for the player, auto-sized for testing purposes. It displays CSS values.</span>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
This demo showcases basic functionality of a player. It is a shell of an HTMLMediaElement with basic timing routines.<br />
|
||||
At 2 seconds, the phrase "2 seconds reached" will appear beside 'Event Output'<br />
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,167 @@
|
|||
(function( global, doc ) {
|
||||
Popcorn.baseplayer = function() {
|
||||
return new Popcorn.baseplayer.init();
|
||||
};
|
||||
|
||||
Popcorn.baseplayer.init = function() {
|
||||
this.readyState = 0;
|
||||
this.currentTime = 0;
|
||||
this.duration = 0;
|
||||
this.paused = 1;
|
||||
this.ended = 0;
|
||||
this.volume = 1;
|
||||
this.muted = 0;
|
||||
this.playbackRate = 1;
|
||||
|
||||
// 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;
|
||||
this.offsetTop = 0;
|
||||
this.offsetParent;
|
||||
};
|
||||
|
||||
Popcorn.baseplayer.init.prototype = {
|
||||
load: function() {},
|
||||
|
||||
play: function() {
|
||||
this.paused = 0;
|
||||
this.timeupdate();
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
this.paused = 1;
|
||||
},
|
||||
|
||||
timeupdate: function() {
|
||||
// The player was paused since the last time update
|
||||
if ( this.paused ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// So we can refer to the instance when setTimeout is run
|
||||
var self = this;
|
||||
this.currentTime += 0.015;
|
||||
|
||||
this.dispatchEvent( "timeupdate" );
|
||||
setTimeout( function() {
|
||||
self.timeupdate.call( self );
|
||||
}, 15 );
|
||||
},
|
||||
|
||||
// By default, assumes this.resource is a DOM Element
|
||||
// Changing the type of this.resource requires this method to be overridden
|
||||
getBoundingClientRect: function() {
|
||||
var b,
|
||||
self = this;
|
||||
|
||||
if ( this._resource ) {
|
||||
b = this._resource.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
bottom: Math.ceil( b.bottom ),
|
||||
left: Math.ceil( b.left ),
|
||||
right: Math.ceil( b.right ),
|
||||
top: Math.ceil( 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 = this._container.getBoundingClientRect();
|
||||
|
||||
// Update bottom, right for expected values once the container loads
|
||||
return {
|
||||
left: b.left,
|
||||
top: b.top,
|
||||
width: self.offsetWidth,
|
||||
height: self.offsetHeight,
|
||||
bottom: b.top + this.width,
|
||||
right: b.top + this.height
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// 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 = container.getAttribute( "width" ) || getStyle( "width" ) || 0;
|
||||
this.offsetHeight = this.height = container.getAttribute( "height" ) || getStyle( "height" ) || 0;
|
||||
this.offsetLeft = bounds.left;
|
||||
this.offsetTop = bound.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;
|
||||
|
||||
if ( elem.currentStyle ) {
|
||||
// IE syntax
|
||||
return elem.currentStyle[prop];
|
||||
} else if ( global.getComputedStyle ) {
|
||||
// Firefox, Chrome et. al
|
||||
return doc.defaultView.getComputedStyle( elem, null ).getPropertyValue( prop );
|
||||
} else {
|
||||
// Fallback, just in case
|
||||
return elem.style[prop];
|
||||
}
|
||||
}
|
||||
};
|
||||
})( window, document );
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Base Player Plugin</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
<!--
|
||||
do not move - this must be called immediately prior to
|
||||
popcorn-api-draft.js
|
||||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
|
||||
<script src="popcorn.baseplayer.unit.js"></script>
|
||||
<script src="popcorn.baseplayer.js"></script>
|
||||
|
||||
<style>
|
||||
body > div {
|
||||
width: 100%;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
div div {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
#player_1 {
|
||||
position: absolute;
|
||||
left: 220px;
|
||||
top: 260px;
|
||||
width: 300px;
|
||||
height: 250px;
|
||||
background: #FFAAAA;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Base Player Plugin</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>
|
||||
|
||||
<span id="player_1">This is a container for the player, auto-sized for testing purposes.</span>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,176 @@
|
|||
module( "Popcorn Base Player" );
|
||||
test( "API", function () {
|
||||
|
||||
var expects = 0,
|
||||
count = 0,
|
||||
player = Popcorn.baseplayer(),
|
||||
members = {
|
||||
// HTMLMediaElement members
|
||||
'readyState' : 'number',
|
||||
'currentTime' : 'number',
|
||||
'duration' : 'number',
|
||||
'paused' : 'number',
|
||||
'ended' : 'number',
|
||||
'volume' : 'number',
|
||||
'muted' : 'number',
|
||||
'playbackRate' : 'number',
|
||||
'autoplay' : 'undefined',
|
||||
'loop' : 'undefined',
|
||||
'load' : 'function',
|
||||
'play' : 'function',
|
||||
'pause' : 'function',
|
||||
'timeupdate' : 'function',
|
||||
|
||||
// DOMElement members
|
||||
'addEventListener' : 'function',
|
||||
'dispatchEvent' : 'function',
|
||||
'getBoundingClientRect' : 'function',
|
||||
'width' : 'number',
|
||||
'height' : 'number',
|
||||
'offsetWidth' : 'number',
|
||||
'offsetHeight' : 'number',
|
||||
'offsetTop' : 'number',
|
||||
'offsetLeft' : 'number',
|
||||
'offsetParent' : 'undefined',
|
||||
|
||||
// Helper functions and members
|
||||
'_events' : 'object',
|
||||
'_resource' : 'undefined',
|
||||
'_container' : 'undefined',
|
||||
'getStyle' : 'function',
|
||||
'extractContainerValues' : 'function'
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
Popcorn.forEach( members, function () {
|
||||
expects++;
|
||||
});
|
||||
|
||||
expect( expects );
|
||||
stop( 10000 );
|
||||
|
||||
Popcorn.forEach( members, function ( type, prop ) {
|
||||
ok( typeof player[prop] === type, "player." + prop + " is type: " + type );
|
||||
plus();
|
||||
});
|
||||
});
|
||||
|
||||
test( "Default Functionality", function () {
|
||||
var expects = 7,
|
||||
count = 0,
|
||||
player = Popcorn.baseplayer(),
|
||||
dimensions,
|
||||
expectedVals = {
|
||||
left: 220,
|
||||
top: 260,
|
||||
width: 300,
|
||||
height: 250
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
player._resource = document.getElementById('player_1');
|
||||
dimensions = player.getBoundingClientRect();
|
||||
|
||||
Popcorn.forEach( expectedVals, function() {
|
||||
expects+= 2;
|
||||
});
|
||||
|
||||
expect( expects );
|
||||
stop( 1000 );
|
||||
|
||||
Popcorn.forEach( expectedVals, function( val, prop ) {
|
||||
equals( player.getStyle( prop ), val+'px', "Style '" + prop + "' correctly got" );
|
||||
plus();
|
||||
|
||||
equals( dimensions[prop], val, "Bounding Client " + prop + " works" );
|
||||
plus();
|
||||
});
|
||||
|
||||
equals( dimensions.right, expectedVals.left + expectedVals.width, "Bounding Client right works" );
|
||||
plus();
|
||||
equals( dimensions.bottom, expectedVals.top + expectedVals.height, "Bounding Client bottom works" );
|
||||
plus();
|
||||
|
||||
player.addEventListener( 'timeupdate', function( evt, caller ) {
|
||||
ok( true, "Time update called" );
|
||||
plus();
|
||||
|
||||
equals( player, this, "'this' is kept as player" );
|
||||
plus();
|
||||
|
||||
equals( player, caller, "caller is kept as player" );
|
||||
plus();
|
||||
|
||||
ok( evt instanceof window.Event, "Event object passed in" );
|
||||
plus();
|
||||
|
||||
ok( evt.type === 'timeupdate', "Event object is type 'timeupdate'" );
|
||||
plus();
|
||||
|
||||
player.pause();
|
||||
});
|
||||
|
||||
player.play();
|
||||
});
|
||||
|
||||
test( "Extension and Method Overriding", function () {
|
||||
var expects = 4,
|
||||
count = 0,
|
||||
player = Popcorn.baseplayer(),
|
||||
playerForPopcorn = Popcorn.baseplayer(),
|
||||
popcorn;
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
expect(expects);
|
||||
stop( 4000 );
|
||||
|
||||
Popcorn.extend( player, {
|
||||
load: function() {
|
||||
ok( true, "Load overridden" );
|
||||
plus();
|
||||
},
|
||||
timeupdate: function() {
|
||||
ok( true, "Timeupdate overridden" );
|
||||
plus();
|
||||
|
||||
// Must dispatch event so event listeners can work!
|
||||
this.dispatchEvent("timeupdate");
|
||||
|
||||
// We don't want to cue custom timing loop using setTimeout because we only want this to run once
|
||||
}
|
||||
});
|
||||
|
||||
player.addEventListener( "timeupdate", function() {
|
||||
ok( true, "Timeupdate event dispatched!" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popcorn = Popcorn( playerForPopcorn )
|
||||
.exec( 2, function() {
|
||||
ok( true, "Exec triggereed from popcorn after 2 seconds" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.load();
|
||||
player.play();
|
||||
|
||||
// Each player will define its own criteria for when readyState should be changed
|
||||
// No logic in base player for this, so we must do it manually so popcorn will be able to cue track events
|
||||
playerForPopcorn.readyState = 2;
|
||||
popcorn.play();
|
||||
});
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* JavaScript interface for the SoundCloud Player widget
|
||||
* Author: Matas Petrikas, matas@soundcloud.com
|
||||
* Copyright (c) 2009 SoundCloud Ltd.
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
(function(){
|
||||
var isIE = (/msie/i).test(navigator.userAgent) && !(/opera/i).test(navigator.userAgent);
|
||||
|
||||
var soundcloud = window.soundcloud = {
|
||||
version: "0.1",
|
||||
debug: false,
|
||||
_listeners: [],
|
||||
// re-dispatches widget events in the DOM, using JS library support, the events also should bubble up the DOM
|
||||
_redispatch: function(eventType, flashId, data) {
|
||||
var playerNode,
|
||||
lsnrs = this._listeners[eventType] || [],
|
||||
// construct the custom eventType e.g. 'soundcloud:onPlayerReady'
|
||||
customEventType = 'soundcloud:' + eventType;
|
||||
|
||||
try{
|
||||
// find the flash player, might throw an exception
|
||||
playerNode = this.getPlayer(flashId);
|
||||
}catch(e){
|
||||
if(this.debug && window.console){
|
||||
console.error('unable to dispatch widget event ' + eventType + ' for the widget id ' + flashId, data, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// re-dispatch SoundCloud events up in the DOM
|
||||
if(window.jQuery){
|
||||
// if jQuery is available, trigger the custom event
|
||||
jQuery(playerNode).trigger(customEventType, [data]);
|
||||
}else if(window.Prototype){
|
||||
// if Prototype.js is available, fire the custom event
|
||||
$(playerNode).fire(customEventType, data);
|
||||
}else{
|
||||
// TODO add more JS libraries that support custom DOM events
|
||||
}
|
||||
// if there are any listeners registered to this event, trigger them all
|
||||
for(var i = 0, l = lsnrs.length; i < l; i += 1) {
|
||||
lsnrs[i].apply(playerNode, [playerNode, data]);
|
||||
}
|
||||
// log the events in debug mode
|
||||
if(this.debug && window.console){
|
||||
console.log(customEventType, eventType, flashId, data);
|
||||
}
|
||||
|
||||
},
|
||||
// you can add multiple listeners to a certain event
|
||||
// e.g. soundcloud.addEventListener('onPlayerReady', myFunctionOne);
|
||||
// soundcloud.addEventListener('onPlayerReady', myFunctionTwo);
|
||||
addEventListener: function(eventType, callback) {
|
||||
if(!this._listeners[eventType]){
|
||||
this._listeners[eventType] = [];
|
||||
}
|
||||
this._listeners[eventType].push(callback);
|
||||
},
|
||||
// you can also remove the function listener if e.g you want to trigger it only once
|
||||
// soundcloud.removeEventListener('onMediaPlay', myFunctionOne);
|
||||
removeEventListener: function(eventType, callback) {
|
||||
var lsnrs = this._listeners[eventType] || [];
|
||||
for(var i = 0, l = lsnrs.length; i < l; i += 1) {
|
||||
if(lsnrs[i] === callback){
|
||||
lsnrs.splice(i, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
// get widget node based on its id (if object tag) or name (if embed tag)
|
||||
// if you're using SWFObject or other dynamic Flash generators, please make sure that you set the id parameter
|
||||
// only if the DOM has an id/name it's possible to call player's methods.
|
||||
// Important!: because of the bug in Opera browser, the Flash can't get its own id
|
||||
// so the generator should set it additionally through flashvars parameter 'object_id'
|
||||
getPlayer: function(id){
|
||||
var flash;
|
||||
try{
|
||||
if(!id){
|
||||
throw "The SoundCloud Widget DOM object needs an id atribute, please refer to SoundCloud Widget API documentation.";
|
||||
}
|
||||
flash = isIE ? window[id] : document[id];
|
||||
if(flash){
|
||||
if(flash.api_getFlashId){
|
||||
return flash;
|
||||
}else{
|
||||
throw "The SoundCloud Widget External Interface is not accessible. Check that allowscriptaccess is set to 'always' in embed code";
|
||||
}
|
||||
}else{
|
||||
throw "The SoundCloud Widget with an id " + id + " couldn't be found";
|
||||
}
|
||||
}catch(e){
|
||||
if (console && console.error) {
|
||||
console.error(e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
// fired when widget has loaded its data and is ready to accept calls from outside
|
||||
// the widget will call these functions only if in it's flashvars there's a parameter enable_api=true
|
||||
// @flashId: the widget id, basically the Flash node should be accessible to JS with soundcloud.getPlayer(flashId)
|
||||
// @data: an object containing .mediaUri (eg. 'http://api.soundcloud.com/tracks/49931') .mediaId (e.g. '4532')
|
||||
// in buffering events data contains also .percent = (e.g. '99')
|
||||
onPlayerReady: function(flashId, data) {
|
||||
this._redispatch('onPlayerReady', flashId, data);
|
||||
},
|
||||
// fired when widget starts playing current track (fired only once per track)
|
||||
onMediaStart : function(flashId, data) {
|
||||
this._redispatch('onMediaStart', flashId, data);
|
||||
},
|
||||
// fired when the track/playlist has finished playing
|
||||
onMediaEnd : function(flashId, data) {
|
||||
this._redispatch('onMediaEnd', flashId, data);
|
||||
},
|
||||
// fired when widget starts playing current track (fired on every play, seek)
|
||||
onMediaPlay : function(flashId, data) {
|
||||
this._redispatch('onMediaPlay', flashId, data);
|
||||
},
|
||||
// fired when track was paused
|
||||
onMediaPause : function(flashId, data) {
|
||||
this._redispatch('onMediaPause', flashId, data);
|
||||
},
|
||||
// fired when the widget is still buffering, means you can't seek in the track fully yet
|
||||
onMediaBuffering : function(flashId, data) {
|
||||
this._redispatch('onMediaBuffering', flashId, data);
|
||||
},
|
||||
// fired when the user seeks in the track
|
||||
onMediaSeek : function(flashId, data) {
|
||||
this._redispatch('onMediaSeek', flashId, data);
|
||||
},
|
||||
// fired when the widget is done buffering and the whole track length is seekable
|
||||
onMediaDoneBuffering : function(flashId, data) {
|
||||
this._redispatch('onMediaDoneBuffering', flashId, data);
|
||||
},
|
||||
// fired when the widget can't get the requested data from the server (the resource is removed, hidden, etc.)
|
||||
onPlayerError : function(flashId, data) {
|
||||
this._redispatch('onPlayerError', flashId, data);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
|
@ -0,0 +1,241 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Soundcloud Player Example</title>
|
||||
<style>
|
||||
#media_1{
|
||||
width: 80%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script type="text/javascript" src="popcorn.soundcloud.js"></script>
|
||||
|
||||
<!-- Plugins for demo purposes -->
|
||||
<script src="../../plugins/footnote/popcorn.footnote.js"></script>
|
||||
<script src="../../plugins/flickr/popcorn.flickr.js"></script>
|
||||
<script src="../../plugins/attribution/popcorn.attribution.js"></script>
|
||||
<script src="../../plugins/webpage/popcorn.webpage.js"></script>
|
||||
<script src="../../plugins/googlefeed/popcorn.googlefeed.js"></script>
|
||||
<script src="../../plugins/image/popcorn.image.js"></script>
|
||||
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
|
||||
<script src="../../plugins/twitter/popcorn.twitter.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
//On document ready
|
||||
document.addEventListener( "DOMContentLoaded", function() {
|
||||
var popcorn;
|
||||
|
||||
document.getElementById( "btnPlay" ).addEventListener( "click", function() {
|
||||
popcorn.play();
|
||||
}, false);
|
||||
|
||||
document.getElementById( "btnPause" ).addEventListener( "click", function() {
|
||||
popcorn.pause();
|
||||
}, false);
|
||||
|
||||
document.getElementById( "btnSeek" ).addEventListener( "click", function() {
|
||||
popcorn.currentTime( 30 );
|
||||
}, false);
|
||||
|
||||
document.getElementById( "btnVolume" ).addEventListener( "click", function() {
|
||||
if ( popcorn.volume() >= 0.5 ) {
|
||||
popcorn.volume( popcorn.volume()/2 );
|
||||
this.innerHTML = "Double Volume";
|
||||
} else {
|
||||
popcorn.volume( popcorn.volume()*2 );
|
||||
this.innerHTML = "Halve Volume";
|
||||
}
|
||||
}, false);
|
||||
|
||||
document.getElementById( "btnMute" ).addEventListener( "click", function() {
|
||||
popcorn.mute();
|
||||
}, false);
|
||||
|
||||
popcorn = Popcorn( Popcorn.soundcloud( "media_1", "http://soundcloud.com/forss/flickermood", {
|
||||
width: "50%",
|
||||
/*
|
||||
This demo contains an api key used for retrieving comments from Soundcloud's API
|
||||
It is to be used for demonstration purposes only, and for only this demo
|
||||
*/
|
||||
api: {
|
||||
key: "PRaNFlda6Bhf5utPjUsptg",
|
||||
commentdiv: "commentDisplay"/*,
|
||||
commentformat: (function() {
|
||||
var count = 0;
|
||||
|
||||
return function( comment ) {
|
||||
return "<div>Comment # " + ( count++ ) + "<br />"
|
||||
+ "<em>" + comment.user.name + "</em>: " + comment.text +"</div>";
|
||||
}
|
||||
})()*/
|
||||
}
|
||||
}) );
|
||||
|
||||
popcorn.listen( "load", function() {
|
||||
|
||||
document.getElementById( "media_duration" ).innerHTML = popcorn.duration();
|
||||
document.getElementById( "media_volume" ).innerHTML = popcorn.volume();
|
||||
document.getElementById( "media_currentTime" ).innerHTML = popcorn.currentTime();
|
||||
document.getElementById( "media_readyState" ).innerHTML = popcorn.video.readyState;
|
||||
|
||||
popcorn.listen( "timeupdate", function() {
|
||||
document.getElementById( "media_currentTime" ).innerHTML = popcorn.currentTime();
|
||||
});
|
||||
|
||||
popcorn.video.addEventListener( "readystatechange", function() {
|
||||
document.getElementById( "media_readyState" ).innerHTML = popcorn.video.readyState;
|
||||
});
|
||||
|
||||
popcorn.listen( "volumechange", function() {
|
||||
document.getElementById( "media_volume" ).innerHTML = popcorn.volume();
|
||||
});
|
||||
|
||||
popcorn.trigger( "play" );
|
||||
});
|
||||
|
||||
// Empty for the purposes of allowing popcorn.trigger("play");
|
||||
popcorn.listen( "play", function() {
|
||||
|
||||
});
|
||||
|
||||
popcorn.subtitle({
|
||||
start: 5, // seconds
|
||||
end: 15, // seconds
|
||||
text: 'This is overlaid on top of the audio visualization. You can hightlight it!',
|
||||
display: 'inline',
|
||||
language: "en"
|
||||
});
|
||||
|
||||
popcorn.footnote({
|
||||
start: 5, // seconds
|
||||
end: 40, // seconds
|
||||
text: 'The song is "Flickermood", by Forss',
|
||||
target: 'footnotediv'
|
||||
})
|
||||
.flickr({
|
||||
start: 20, // seconds
|
||||
end: 40, // seconds
|
||||
tags: 'georgia',
|
||||
numberofimages: '8',
|
||||
target: 'flickrdiv'
|
||||
})
|
||||
.twitter({
|
||||
start: 20, // seconds
|
||||
end: 45, // seconds
|
||||
title: 'Oil Spill',
|
||||
src: '#oilspill',
|
||||
target: 'twitterdiv'
|
||||
})
|
||||
.attribution({
|
||||
start: 5, // seconds
|
||||
end: 60, // seconds
|
||||
nameofwork: "Flickermood",
|
||||
nameofworkurl:"http://soundcloud.com/forss/flickermood",
|
||||
copyrightholder:"Eric Wahlforss",
|
||||
target: 'attribdiv'
|
||||
})
|
||||
.webpage({
|
||||
id: "webpages-a",
|
||||
start: 0, // seconds
|
||||
end: 15, // seconds
|
||||
src: 'http://webmademovies.org/',
|
||||
target: 'webpagediv'
|
||||
})
|
||||
.googlefeed({
|
||||
start: 0, // seconds
|
||||
end: 15, // seconds
|
||||
target: "feeddiv",
|
||||
url: "http://zenit.senecac.on.ca/~chris.tyler/planet/rss20.xml",
|
||||
title: "Planet Feed",
|
||||
orientation: "Vertical"
|
||||
})
|
||||
.image({
|
||||
start: 5, // seconds
|
||||
end: 15, // seconds
|
||||
href: 'http://www.drumbeat.org/',
|
||||
src: 'https://www.drumbeat.org/media//images/drumbeat-logo-splash.png',
|
||||
target: 'imagediv'
|
||||
})
|
||||
.video.registerPopcornWithPlayer( popcorn );
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="media_1" ></div><br />
|
||||
|
||||
<div>
|
||||
<button class="simple" id="btnPlay">Play</button>
|
||||
<button class="simple" id="btnPause">Pause</button>
|
||||
<button class="seek" id="btnSeek">Seek to 30</button>
|
||||
<button class="volume" id="btnVolume">Toggle Volume</button>
|
||||
<button class="volume" id="btnMute">Mute</button><br />
|
||||
|
||||
<div style="float: left;">
|
||||
Current Time (s): <span id="media_currentTime"></span>
|
||||
<br />Duration (s): <span id="media_duration"></span>
|
||||
<br />Volume (0-1): <span id="media_volume"></span>
|
||||
<br />Ready State: <span id="media_readyState">0</span>
|
||||
</div>
|
||||
<div style="position: absolute; left: 350px;">
|
||||
<strong>Comment Area</strong>
|
||||
<div id="commentDisplay"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="float:right; width: 100%;">
|
||||
<h3>Description</h3>
|
||||
<p>
|
||||
This demo will showcase how a player for Popcorn.js may be powered by Soundcloud's Flash audio player. This is done by making the flash audio player masquerade as HTML 5 media element.<br />
|
||||
Due to the Flash security model, this demo must be run from a web server<br />
|
||||
<hr >
|
||||
Custom controls have been developed and tied into their player for demo purposes.<br />
|
||||
Clicking play/pause or seeking in either the Soundcloud player or via custom controls will cause the other to update.<br />
|
||||
The Soundcloud audio can be specified in the HTML source by giving the Soundcloud song url to either the Popcorn.soundcloud constructor or as the div data-src attribute.<br/>
|
||||
Specifying the source in the constructor will override any source specified on the container element.<br/>
|
||||
Player width/height can be specified as container attributes (data-width, data-height), or as styles (width, height). Styles can be inline or CSS.<br/>
|
||||
If no width or height are given, they default to '100%' and '81px' respectively.<br/>
|
||||
Width/height precendence is in this order: constructor, container attributes, natural (manually given inline/CSS styles), default<br/>
|
||||
</p>
|
||||
<h4>Expected Events</h4>
|
||||
<ul>
|
||||
<li>Throughout the track, user comments from Soundcloud will appear below 'Comment Area'.</li>
|
||||
<li>From 0 to 15 seconds, the site 'http://webmademovies.org/' will appear below 'Web Page Area'.</li>
|
||||
<li>From 0 to 20 seconds, blogs from 'http://zenit.senecac.on.ca/~chris.tyler/planet/rss20.xml' will appear below 'Google Feed Area'.</li>
|
||||
<li>From 5 to 15 seconds, the subtitle 'This is overlaid on top of the audio visualization. You can hightlight it!' will be overlaid on the Soundcloud player.</li>
|
||||
<li>From 5 to 15 seconds, the Mozilla Drumbeat logo will appear below 'Image Area'.</li>
|
||||
<li>From 5 to 40 seconds, the footnote 'The song is "Flickermood", by Forss' will appear below 'Footnote Area'.</li>
|
||||
<li>From 5 to 60 seconds, the 'Flickermood, Eric Wahlforss' will appear below 'Attributions Area'.</li>
|
||||
<li>From 20 to 40 seconds, the a flickr stream of 8 images tagged 'georgia' will appear below 'Flickr Area'.</li>
|
||||
<li>From 20 to 45 seconds, tweets tagged #oilspill will appear below 'Twitter Area'.</li>
|
||||
</ul>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<div id="footnotediv" width="50%" height="50%">
|
||||
<strong>Footnote Area</strong><br />
|
||||
</div>
|
||||
<div id="attribdiv" width="50%" height="50%">
|
||||
<strong>Attributions Area</strong><br />
|
||||
</div>
|
||||
<div id="flickrdiv" width="50%" height="50%">
|
||||
<strong>Flickr Area</strong><br />
|
||||
</div>
|
||||
<div id="twitterdiv" width="50%" height="50%">
|
||||
<strong>Twitter Area</strong><br />
|
||||
</div>
|
||||
<div id="imagediv" width="50%" height="50%">
|
||||
<strong>Image Area</strong><br />
|
||||
</div>
|
||||
<div id="feeddiv" width="50%" height="50%">
|
||||
<strong>Google Feed Area</strong><br />
|
||||
</div>
|
||||
<div id="webpagediv" width="100px" height="50px">
|
||||
<strong>Web Page Area</strong><br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,693 @@
|
|||
// Popcorn Soundcloud Player Wrapper
|
||||
( function( Popcorn, global ) {
|
||||
/**
|
||||
* Soundcloud wrapper for Popcorn.
|
||||
* This player adds enables Popcorn.js to handle Soundcloud audio. It does so by masking an embedded Soundcloud Flash object
|
||||
* as a video and implementing the HTML5 Media Element interface.
|
||||
*
|
||||
* You can configure the video source and dimensions in two ways:
|
||||
* 1. Use the embed code path supplied by Soundcloud the id of the desired location into a new Popcorn.soundcloud object.
|
||||
* Width and height can be configured throughh CSS.
|
||||
*
|
||||
* <div id="player_1" style="width: 500px; height: 81px"></div>
|
||||
* <script type="text/javascript">
|
||||
* document.addEventListener("DOMContentLoaded", function() {
|
||||
* var popcorn = Popcorn( Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" ));
|
||||
* }, false);
|
||||
* </script>
|
||||
*
|
||||
* 2. Width and height may also be configured directly with the player; this will override any CSS. This is useful for
|
||||
* when different sizes are desired. for multiple players within the same parent container.
|
||||
*
|
||||
* <div id="player_1"></div>
|
||||
* <script type="text/javascript">
|
||||
* document.addEventListener("DOMContentLoaded", function() {
|
||||
* var popcorn = Popcorn( Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood", {
|
||||
* width: "500", // Optional, will default to CSS values
|
||||
* height: "81" // Optional, will default to CSS values
|
||||
* }));
|
||||
* }, false);
|
||||
* </script>
|
||||
*
|
||||
* The player can be further configured to integrate with the SoundCloud API:
|
||||
*
|
||||
* var popcorn = Popcorn( Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood", {
|
||||
* width: "100%", // Optional, the width for the player. May also be as '##px'
|
||||
* // Defaults to the maximum possible width
|
||||
* height: "81px", // Optional, the height for the player. May also be as '###%'
|
||||
* // Defaults to 81px
|
||||
* api: { // Optional, information for Soundcloud API interaction
|
||||
* key: "abcdefsdfsdf", // Required for API interaction. The Soundcloud API key
|
||||
* commentdiv: "divId_for_output", // Required for comment retrieval, the Div Id for outputting comments.
|
||||
* commentformat: function( comment ) {} // Optional, a function to format a comment. Returns HTML string
|
||||
* }
|
||||
* }));
|
||||
*
|
||||
* Comments are retrieved from Soundcloud when the player is registered with Popcorn by calling the registerWithPopcorn()
|
||||
* function. For this to work, the api_key and commentdiv attributes must be set. Comments are output by default similar to
|
||||
* how Soundcloud formats them in-player, but a custom formatting function may be supplied. It receives a comment object and
|
||||
* the current date. A comment object has:
|
||||
*
|
||||
* var comment = {
|
||||
* start: 0, // Required. Start time in ms.
|
||||
* date: new Date(), // Required. Date comment wasa posted.
|
||||
* text: "", // Required. Comment text
|
||||
* user: { // Required. Describes the user who posted the comment
|
||||
* name: "", // Required. User name
|
||||
* profile: "", // Required. User profile link
|
||||
* avatar: "" // Required. User avatar link
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* These events are completely custom-implemented and may be subscribed to at any time:
|
||||
* canplaythrough
|
||||
* durationchange
|
||||
* load
|
||||
* loadedmetadata
|
||||
* loadstart
|
||||
* play
|
||||
* readystatechange
|
||||
* volumechange
|
||||
*
|
||||
* These events are related to player functionality and must be subscribed to during or after the load event:
|
||||
* canplay
|
||||
* ended
|
||||
* error
|
||||
* pause
|
||||
* playing
|
||||
* progress
|
||||
* seeked
|
||||
* timeupdate
|
||||
*
|
||||
* These events are not supported:
|
||||
* abort
|
||||
* emptied
|
||||
* loadeddata
|
||||
* ratechange
|
||||
* seeking
|
||||
* stalled
|
||||
* suspend
|
||||
* waiting
|
||||
*
|
||||
* Supported media attributes:
|
||||
* autoplay ( via Popcorn )
|
||||
* currentTime
|
||||
* defaultPlaybackRate ( get only )
|
||||
* duration ( get only )
|
||||
* ended ( get only )
|
||||
* initialTime ( get only, always 0 )
|
||||
* loop ( get only, set by calling setLoop() )
|
||||
* muted ( get only )
|
||||
* paused ( get only )
|
||||
* playbackRate ( get only )
|
||||
* played ( get only, 0/1 only )
|
||||
* readyState ( get only )
|
||||
* src ( get only )
|
||||
* volume
|
||||
*
|
||||
* load() function
|
||||
* mute() function ( toggles on/off )
|
||||
* play() function
|
||||
* pause() function
|
||||
*
|
||||
* Unsupported media attributes:
|
||||
* buffered
|
||||
* networkState
|
||||
* preload
|
||||
* seekable
|
||||
* seeking
|
||||
* startOffsetTime
|
||||
*
|
||||
* canPlayType() function
|
||||
*/
|
||||
|
||||
// Trackers
|
||||
var timeupdateInterval = 33,
|
||||
timeCheckInterval = 0.25,
|
||||
abs = Math.abs,
|
||||
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 ) {
|
||||
if ( elem.currentStyle ) {
|
||||
// IE way
|
||||
return elem.currentStyle[styleProp];
|
||||
} else if ( global.getComputedStyle ) {
|
||||
// Firefox, Chrome, et. al
|
||||
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() ) {
|
||||
setTimeout( function() {
|
||||
isReady( self );
|
||||
}, 15 );
|
||||
return;
|
||||
}
|
||||
|
||||
var flashvars = {
|
||||
enable_api: true,
|
||||
object_id: self._playerId,
|
||||
url: self.src,
|
||||
// Hide comments in player if showing them elsewhere
|
||||
show_comments: !self._options.api.key && !self._options.api.commentdiv
|
||||
},
|
||||
params = {
|
||||
allowscriptaccess: "always",
|
||||
// This is so we can overlay html ontop of Flash
|
||||
wmode: 'transparent'
|
||||
},
|
||||
attributes = {
|
||||
id: self._playerId,
|
||||
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( "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 ) {
|
||||
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()];
|
||||
wrapper.paused = 1;
|
||||
//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 ) {
|
||||
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" );
|
||||
that._container.style.width = that.width;
|
||||
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;
|
||||
that.offsetHeight = that._container.offsetHeight;
|
||||
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 ) {
|
||||
throw "Must supply an id!";
|
||||
} else if ( !src ) {
|
||||
throw "Must supply a source!";
|
||||
} 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 );
|
||||
this._containerId = options.target;
|
||||
this._options = options;
|
||||
this._comments = [];
|
||||
this._popcorn;
|
||||
|
||||
pullFromContainer( this );
|
||||
|
||||
this.duration = 0;
|
||||
this.volume = 1;
|
||||
this.currentTime = 0;
|
||||
this.ended = 0;
|
||||
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
|
||||
setVolume: function( val ) {
|
||||
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 );
|
||||
this.dispatchEvent( "volumechange" );
|
||||
},
|
||||
// Seeks the video
|
||||
setCurrentTime: function ( time ) {
|
||||
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" );
|
||||
},
|
||||
// Play the video
|
||||
play: function() {
|
||||
// In case someone is cheeky enough to try this before loaded
|
||||
if ( !this.swfObj ) {
|
||||
this.addEventListener( "load", this.play );
|
||||
return;
|
||||
} else if ( !this.paused ) {
|
||||
// No need to process if already playing
|
||||
return;
|
||||
}
|
||||
|
||||
this.paused = 0;
|
||||
this.swfObj.api_play();
|
||||
},
|
||||
// Pause the video
|
||||
pause: function() {
|
||||
// In case someone is cheeky enough to try this before loaded
|
||||
if ( !this.swfObj ) {
|
||||
this.addEventListener( "load", this.pause );
|
||||
return;
|
||||
} else if ( this.paused ) {
|
||||
// No need to process if already playing
|
||||
return;
|
||||
}
|
||||
|
||||
this.paused = 1;
|
||||
this.swfObj.api_pause();
|
||||
},
|
||||
// Toggle video muting
|
||||
// Unmuting will leave it at the old value
|
||||
mute: function() {
|
||||
// In case someone is cheeky enough to try this before loaded
|
||||
if ( !this.swfObj ) {
|
||||
this.addEventListener( "load", this.mute );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !this.muted() ) {
|
||||
this.oldVol = this.volume;
|
||||
|
||||
if ( this.paused ) {
|
||||
this.setVolume( 0 );
|
||||
} else {
|
||||
this.volume = 0;
|
||||
}
|
||||
} else {
|
||||
if ( this.paused ) {
|
||||
this.setVolume( this.oldVol );
|
||||
} else {
|
||||
this.volume = this.oldVol;
|
||||
}
|
||||
}
|
||||
},
|
||||
muted: function() {
|
||||
return this.volume === 0;
|
||||
},
|
||||
// Force loading by playing the player. Pause afterwards
|
||||
load: function() {
|
||||
// In case someone is cheeky enough to try this before loaded
|
||||
if ( !this.swfObj ) {
|
||||
this.addEventListener( "load", this.load );
|
||||
return;
|
||||
}
|
||||
|
||||
this.play();
|
||||
this.pause();
|
||||
},
|
||||
// Hook an event listener for the player event into internal event system
|
||||
// Stick to HTML conventions of add event listener and keep lowercase, without prepending "on"
|
||||
addEventListener: function( evt, fn ) {
|
||||
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 );
|
||||
});
|
||||
},
|
||||
timeupdate: function() {
|
||||
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
|
||||
this.swfObj.api_seekTo( this.currentTime );
|
||||
seeked = 1;
|
||||
} 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 )
|
||||
};
|
||||
} else {
|
||||
//container = document.getElementById( this.playerId );
|
||||
tmp = this._container.getBoundingClientRect();
|
||||
|
||||
// Update bottom, right for expected values once the container loads
|
||||
return {
|
||||
left: tmp.left,
|
||||
top: tmp.top,
|
||||
width: self.offsetWidth,
|
||||
height: self.offsetHeight,
|
||||
bottom: tmp.top + this.width,
|
||||
right: tmp.top + this.height
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
registerPopcornWithPlayer: function( popcorn ) {
|
||||
if ( !this.swfObj ) {
|
||||
this.addEventListener( "load", function() {
|
||||
this.registerPopcornWithPlayer( popcorn );
|
||||
});
|
||||
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 ) {
|
||||
Popcorn.forEach( data.json, function ( obj ) {
|
||||
self.addComment({
|
||||
start: obj.timestamp/1000,
|
||||
date: new Date( obj.created_at ),
|
||||
text: obj.body,
|
||||
user: {
|
||||
name: obj.user.username,
|
||||
profile: obj.user.permalink_url,
|
||||
avatar: obj.user.avatar_url
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Popcorn.extend( Popcorn.soundcloud.prototype, {
|
||||
addComment: function( obj, displayFn ) {
|
||||
var self = this,
|
||||
comment = {
|
||||
start: obj.start || 0,
|
||||
date: obj.date || new Date(),
|
||||
text: obj.text || "",
|
||||
user: {
|
||||
name: obj.user.name || "",
|
||||
profile: obj.user.profile || "",
|
||||
avatar: obj.user.avatar || ""
|
||||
},
|
||||
display: function() {
|
||||
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,
|
||||
display: 'inline',
|
||||
language: 'en',
|
||||
text: comment.display()
|
||||
});
|
||||
}
|
||||
});
|
||||
})( Popcorn, window );
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Soundcloud Player</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
<!--
|
||||
do not move - this must be called immediately prior to
|
||||
popcorn-api-draft.js
|
||||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
|
||||
<script src="popcorn.soundcloud.unit.js"></script>
|
||||
<script src="popcorn.soundcloud.js"></script>
|
||||
|
||||
<style>
|
||||
.soundcloudPlayer {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
#player_1 {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
#player_2 {
|
||||
width: 70%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Soundcloud 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="commentOutput" />
|
||||
<div class="soundcloudPlayer" id="player_1" ></div>
|
||||
<div class="soundcloudPlayer" id="player_2" ></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,402 @@
|
|||
module( "Popcorn Soundcloud Player" );
|
||||
test( "API", function () {
|
||||
|
||||
var expects = 0,
|
||||
count = 0,
|
||||
player = Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" ),
|
||||
members = {
|
||||
// HTMLMediaElement members
|
||||
'readyState' : 'number',
|
||||
'currentTime' : 'number',
|
||||
'duration' : 'number',
|
||||
'paused' : 'number',
|
||||
'ended' : 'number',
|
||||
'volume' : 'number',
|
||||
'muted' : 'function',
|
||||
'playbackRate' : 'number',
|
||||
'autoplay' : 'undefined',
|
||||
'loop' : 'undefined',
|
||||
'load' : 'function',
|
||||
'play' : 'function',
|
||||
'pause' : 'function',
|
||||
'timeupdate' : 'function',
|
||||
'src' : 'string',
|
||||
|
||||
// DOMElement members
|
||||
'addEventListener' : 'function',
|
||||
'dispatchEvent' : 'function',
|
||||
'getBoundingClientRect' : 'function',
|
||||
'width' : 'string',
|
||||
'height' : 'string',
|
||||
'top' : 'number',
|
||||
'left' : 'number',
|
||||
'offsetLeft' : 'number',
|
||||
'offsetTop' : 'number',
|
||||
'offsetHeight' : 'number',
|
||||
'offsetWidth' : 'number',
|
||||
|
||||
// Helper functions and members
|
||||
'setVolume' : 'function',
|
||||
'setCurrentTime' : 'function',
|
||||
'timeupdate' : 'function',
|
||||
'registerPopcornWithPlayer' : 'function'
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
Popcorn.forEach( members, function () {
|
||||
expects++;
|
||||
});
|
||||
|
||||
expect( expects );
|
||||
stop( 10000 );
|
||||
|
||||
Popcorn.forEach( members, function ( type, prop ) {
|
||||
ok( typeof player[prop] === type, "player." + prop + " is type: '" + player[prop] + "', should be '" + type + "'" );
|
||||
plus();
|
||||
});
|
||||
});
|
||||
|
||||
test( "Default Attribute Functionality", function () {
|
||||
var expects = 5,
|
||||
count = 0,
|
||||
playerDefault,
|
||||
playerOverride,
|
||||
members = {
|
||||
// HTMLMediaElement members
|
||||
'currentTime' : 0,
|
||||
'readyState' : 0,
|
||||
'duration' : 0,
|
||||
'volume' : 1,
|
||||
'paused' : 1,
|
||||
'ended' : 0,
|
||||
'muted' : false,
|
||||
'playbackRate' : 1,
|
||||
'src' : 'http://soundcloud.com/forss/flickermood',
|
||||
|
||||
// DOMElement members
|
||||
'height' : '81px',
|
||||
'top' : 0,
|
||||
'left' : 0,
|
||||
'offsetHeight' : 81,
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
Popcorn.forEach( members, function () {
|
||||
expects++;
|
||||
});
|
||||
|
||||
expect( expects );
|
||||
stop( 10000 );
|
||||
|
||||
playerDefault = Popcorn.soundcloud( "player_2", "http://soundcloud.com/forss/flickermood" );
|
||||
playerOverride = Popcorn.soundcloud( "player_2", "http://soundcloud.com/forss/journeyman", {
|
||||
height: "100px",
|
||||
width: '90%'
|
||||
});
|
||||
|
||||
playerDefault.addEventListener( "load", function() {
|
||||
equals( playerDefault.duration, 213.89, "Duration updated" );
|
||||
plus();
|
||||
});
|
||||
|
||||
Popcorn.forEach( members, function ( val, prop ) {
|
||||
var actual = playerDefault[prop];
|
||||
|
||||
if ( typeof playerDefault[prop] === 'function' ) {
|
||||
actual = playerDefault[prop]();
|
||||
}
|
||||
|
||||
equals( actual, val, "player." + prop + " should have default value: '" + val + "'" );
|
||||
plus();
|
||||
});
|
||||
|
||||
equals( document.getElementById( "player_2" ).children.length, 2, "The container has 2 players" );
|
||||
plus();
|
||||
|
||||
equals( playerDefault.width, playerDefault.offsetWidth+"px", "Width is stringified version of offsetWidth" );
|
||||
plus();
|
||||
|
||||
equals( playerOverride.width, "90%", "Width has been overridden" );
|
||||
plus();
|
||||
|
||||
equals( playerOverride.height, "81px", "Height has been overridden to 100px, but set back again to 81px" );
|
||||
plus();
|
||||
});
|
||||
|
||||
test( "Player Volume Control", function () {
|
||||
var expects = 3,
|
||||
count = 0,
|
||||
player = Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" ),
|
||||
targetVolume,
|
||||
startVolume;
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
expect(expects);
|
||||
stop( 50000 );
|
||||
|
||||
player.addEventListener( "load", function() {
|
||||
// VolumeChange is fired shortly after load when the volume is retrieved from the player
|
||||
// Defer volume tests until after that has run
|
||||
player.addEventListener( "volumechange", function() {
|
||||
if ( count >= expects ) {
|
||||
return;
|
||||
}
|
||||
|
||||
equals( player.volume, targetVolume, "Volume change set correctly" );
|
||||
plus();
|
||||
|
||||
if ( targetVolume !== 0 ) {
|
||||
targetVolume = 0;
|
||||
player.mute();
|
||||
} else {
|
||||
targetVolume = startVolume;
|
||||
// Unmute
|
||||
player.mute();
|
||||
}
|
||||
});
|
||||
|
||||
player.volume = targetVolume = startVolume = ( player.volume === 1 ? 0.5 : 1 );
|
||||
});
|
||||
});
|
||||
|
||||
test( "Testing Comments", function() {
|
||||
var expects = 0,
|
||||
count = 0,
|
||||
cmtDate = new Date(),
|
||||
comment,
|
||||
players = {
|
||||
player1: Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" ),
|
||||
player2: Popcorn.soundcloud( "player_2", "http://soundcloud.com/forss/flickermood", {
|
||||
api: {
|
||||
commentdiv: "commentOutput",
|
||||
commentformat: function( comment ) {
|
||||
return comment.text
|
||||
}
|
||||
}
|
||||
}),
|
||||
player3: Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" )
|
||||
}
|
||||
// Expecteed comment output
|
||||
commentOutput = {
|
||||
player1: function() {
|
||||
return '<div><a href="Hyperlink">'
|
||||
+ '<img width="16px height="16px" src="Image"></img>'
|
||||
+ 'User 1</a> at 0.03 1 hour ago'
|
||||
+ '<br />Hi</span>';
|
||||
},
|
||||
player2: function() {
|
||||
return "Hi";
|
||||
},
|
||||
player3: function() {
|
||||
return "User 1 @ 3: Hi";
|
||||
}
|
||||
};
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
// Set comment date to 1 hour ago
|
||||
cmtDate.setTime( cmtDate.getTime() - 3600000 );
|
||||
|
||||
comment = {
|
||||
start: 3,
|
||||
date: cmtDate,
|
||||
text: "Hi",
|
||||
user: {
|
||||
name: "User 1",
|
||||
profile: "Hyperlink",
|
||||
avatar: "Image"
|
||||
}
|
||||
};
|
||||
|
||||
players["player1"].addComment( comment );
|
||||
players["player2"].addComment( comment );
|
||||
players["player3"].addComment( comment, function( comment ) {
|
||||
return comment.user.name + " @ " + comment.start + ": "+ comment.text;
|
||||
});
|
||||
|
||||
Popcorn.forEach( players, function () {
|
||||
// 1 comment per player
|
||||
expects++;
|
||||
});
|
||||
|
||||
expect( expects );
|
||||
stop( 5000 );
|
||||
|
||||
Popcorn.forEach( players, function ( player, name ) {
|
||||
equals( player._comments[0].display(), commentOutput[name](), name + " formatted as expected" );
|
||||
plus();
|
||||
});
|
||||
});
|
||||
|
||||
test( "Popcorn Integration", function () {
|
||||
var expects = 4,
|
||||
count = 0,
|
||||
player = Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" );
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
expect(expects);
|
||||
stop( 20000 );
|
||||
|
||||
player.addEventListener( "load", function() {
|
||||
ok( true, "Listen works (load event)" );
|
||||
plus();
|
||||
|
||||
player.addEventListener( "play", function() {
|
||||
ok( true, "Play triggered by popcorn.trigger" );
|
||||
plus();
|
||||
|
||||
player.pause();
|
||||
});
|
||||
|
||||
player.addEventListener( "pause", function() {
|
||||
ok( true, "Pause explicitly called" );
|
||||
plus();
|
||||
|
||||
player.volume = ( player.volume === 1 ? 0.5 : 1 );
|
||||
});
|
||||
|
||||
player.addEventListener( "volumechange", function() {
|
||||
ok( true, "Volume changed explicitly called" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.play();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test( "Events and Player Control", function () {
|
||||
var expects = 14,
|
||||
count = 0,
|
||||
player = Popcorn.soundcloud( "player_1", "http://soundcloud.com/forss/flickermood" ),
|
||||
targetVolume;
|
||||
|
||||
function plus() {
|
||||
if ( ++count === expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
expect(expects);
|
||||
stop( 300000 );
|
||||
|
||||
player.addEventListener( "load", function() {
|
||||
ok( true, "Load was fired" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.addEventListener( "playing", function() {
|
||||
ok( true, "Playing was fired" );
|
||||
plus();
|
||||
|
||||
equals( player.paused, 0, "Paused is unset" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.addEventListener( "play", ( function() {
|
||||
var hasFired = 0;
|
||||
|
||||
return function() {
|
||||
if ( hasFired ) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasFired = 1;
|
||||
|
||||
ok( true, "Play was fired" );
|
||||
plus();
|
||||
}
|
||||
})());
|
||||
|
||||
player.addEventListener( "durationchange", function() {
|
||||
ok( true, "DurationChange was fired" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.addEventListener( "readystatechange", function() {
|
||||
ok( true, "ReadyStateChange was fired" );
|
||||
plus();
|
||||
|
||||
equals( player.readyState, 3, "Ready State is now 3" );
|
||||
plus();
|
||||
|
||||
player.pause();
|
||||
});
|
||||
|
||||
player.addEventListener( "pause", function() {
|
||||
ok( true, "Pause was fired by dispatch" );
|
||||
plus();
|
||||
|
||||
equals( player.paused, 1, "Paused is set" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.addEventListener( "timeupdate", ( function() {
|
||||
var hasFired = 0;
|
||||
|
||||
return function() {
|
||||
if ( hasFired ) {
|
||||
return;
|
||||
}
|
||||
hasFired = 1;
|
||||
|
||||
ok( true, "Timeupdate was fired by dispatch" );
|
||||
plus();
|
||||
}
|
||||
})());
|
||||
|
||||
player.addEventListener( "volumechange", function() {
|
||||
ok( true, "volumechange was fired by dispatch" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.addEventListener( "canplaythrough", function() {
|
||||
ok( true, "Can play through" );
|
||||
plus();
|
||||
|
||||
// Will trigger a "seeked" event to near end
|
||||
player.currentTime = player.duration - 1;
|
||||
});
|
||||
|
||||
player.addEventListener( "seeked", function() {
|
||||
ok( true, "Seeked was fired" );
|
||||
plus();
|
||||
|
||||
player.dispatchEvent( "play" );
|
||||
});
|
||||
|
||||
player.addEventListener( "ended", function() {
|
||||
ok( true, "Media is done playing" );
|
||||
plus();
|
||||
|
||||
equals( player.paused, 1, "Paused is set on end" );
|
||||
plus();
|
||||
});
|
||||
|
||||
player.play();
|
||||
});
|
|
@ -22,7 +22,6 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script type="text/javascript" src="popcorn.vimeo.js"></script>
|
||||
<script src="../../plugins/footnote/popcorn.footnote.js"></script>
|
||||
|
@ -102,7 +101,10 @@
|
|||
|
||||
//On document ready
|
||||
document.addEventListener( "DOMContentLoaded", function() {
|
||||
var player = Popcorn( Popcorn.vimeo( "player_1" ) )
|
||||
var player = Popcorn( Popcorn.vimeo( "player_1", "http://player.vimeo.com/video/11127501", {
|
||||
width: 500,
|
||||
height: 281
|
||||
}) )
|
||||
.footnote({
|
||||
start: 5, // seconds
|
||||
end: 40, // seconds
|
||||
|
@ -178,7 +180,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div id="player_1" width="500" height="281" src="http://player.vimeo.com/video/11127501" ></div><br />
|
||||
<div id="player_1" ></div><br />
|
||||
<button class="simple" id="btnPlay">Play</button>
|
||||
<button class="simple" id="btnPause">Pause</button>
|
||||
<button class="seek" id="btnSeek">Seek to 30</button>
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -23,6 +23,6 @@
|
|||
<ol id="qunit-tests"></ol>
|
||||
<div id="qunit-fixture"> </div>
|
||||
|
||||
<div id="player_1" width="500" height="281"></div>
|
||||
<div id="player_1"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
var paused = true,
|
||||
popcorn;
|
||||
|
||||
popcorn = Popcorn( Popcorn.youtube( 'video', 'http://www.youtube.com/watch?v=9oar9glUCL0' ) );
|
||||
popcorn = Popcorn( Popcorn.youtube( 'video', 'http://www.youtube.com/watch?v=9oar9glUCL0', { width: 400 } ) );
|
||||
|
||||
popcorn = popcorn
|
||||
.footnote({
|
||||
|
@ -140,7 +140,7 @@
|
|||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div id="video" width="360" height="300" ></div><br />
|
||||
<div id="video" style="width: 360px; height: 300px;" ></div><br />
|
||||
<button class="simple" id="btn-play-pause">Play</button>
|
||||
<button class="seek" id="btn-seek">Seek to 30</button>
|
||||
<button class="volume" id="btn-volume">Toggle Volume</button>
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -28,8 +28,8 @@
|
|||
Therefore, if failures occur for the first time, just run it again. Likely,
|
||||
failures would disappear the second time.
|
||||
</p>
|
||||
<div id="video" width="360" height="300" src="http://www.youtube.com/e/ac7KhViaVqc" ></div>
|
||||
<div id="video2" width="360" height="300" src="http://www.youtube.com/e/ac7KhViaVqc" ></div>
|
||||
<div id="video" style="width: 360px; height: 300px" ></div>
|
||||
<div id="video2" style="width: 360px; height: 300px" ></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -1,41 +1,6 @@
|
|||
var ytReady = false,
|
||||
popcorn = Popcorn( Popcorn.youtube( 'video' ) );
|
||||
|
||||
popcorn.listen( "load", function onYouTubePlayerReady() {
|
||||
ytReady = true;
|
||||
});
|
||||
|
||||
test( "Popcorn YouTube Plugin Startup", function() {
|
||||
var time = 0,
|
||||
wait = 100,
|
||||
timeout = 10000;
|
||||
|
||||
// wait for YouTube to start
|
||||
stop( timeout + wait );
|
||||
|
||||
// run in an interval check if YouTube has started
|
||||
var interval = setInterval(function() {
|
||||
time += wait;
|
||||
|
||||
if ( ytReady ) {
|
||||
start();
|
||||
ok( true, "YouTube has started." );
|
||||
clearInterval( interval );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( time > timeout ) {
|
||||
ok( false, "YouTube cannot be started." );
|
||||
clearInterval( interval );
|
||||
}
|
||||
}, wait);
|
||||
});
|
||||
|
||||
test( "Popcorn YouTube Plugin Event Tests", function() {
|
||||
if ( !ytReady ) {
|
||||
ok( false, "YouTube did not start." );
|
||||
return;
|
||||
}
|
||||
|
||||
var popcorn = Popcorn( Popcorn.youtube( 'video', "http://www.youtube.com/e/ac7KhViaVqc" ) );
|
||||
|
||||
function plus(){
|
||||
if ( ++count == expects ) {
|
||||
|
@ -219,4 +184,4 @@ test( "Popcorn YouTube Plugin Url and Duration Tests", function() {
|
|||
});
|
||||
|
||||
popcorn.play();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,13 +2,24 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Popcorn Flickr Plug-in Demo</title>
|
||||
<!--
|
||||
ATTENTION
|
||||
|
||||
This demo uses an API key obtained for testing the Flickr Popcorn.js
|
||||
plugin. Please do not use it for other purposes.
|
||||
-->
|
||||
<script src="../../popcorn.js"></script>
|
||||
<script src="../../test/jquery.js"></script>
|
||||
<script src="popcorn.flickr.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var p = Popcorn('#video')
|
||||
.flickr({
|
||||
start: 0, // seconds
|
||||
end: 5, // seconds
|
||||
username: 'AniaSob',
|
||||
apikey: 'd1d249260dd1673ec8810c8ce5150ae1',
|
||||
target: 'flickrdiv'
|
||||
} )
|
||||
.flickr({
|
||||
start: 5, // seconds
|
||||
end: 15, // seconds
|
||||
|
@ -37,8 +48,8 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Flickr Plug-in Demo</h1>
|
||||
<p>This plugin requires jquery</p>
|
||||
<p>Flickr images by '35034346917@N01' will appear at 5 seconds and disappear at 15 seconds.
|
||||
<p>Flickr images by 'AniaSob' will appear at 0 seconds and disappear at 5 seconds.
|
||||
<br />Flickr images by '35034346917@N01' will appear at 5 seconds and disappear at 15 seconds.
|
||||
<br />Flickr images tagged 'georgia' will appear at 20 seconds and disappear at 30 seconds.
|
||||
<br />Flickr images by '35034346917@N01' and tagged 'georgia' will appear at 35 seconds and disappear at 45 seconds.</p>
|
||||
<div>
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
// PLUGIN: FLICKR
|
||||
|
||||
// PLUGIN: Flickr
|
||||
(function (Popcorn) {
|
||||
|
||||
/**
|
||||
* Flickr popcorn plug-in
|
||||
* Appends a users Flickr images to an element on the page.
|
||||
* Options parameter will need a start, end, target and userid.
|
||||
* Options parameter will need a start, end, target and userid or username and api_key.
|
||||
* Optional parameters are numberofimages, height, width, padding, and border
|
||||
* Start is the time that you want this plug-in to execute
|
||||
* End is the time that you want this plug-in to stop executing
|
||||
* Userid is the id of who's Flickr images you wish to show
|
||||
* Tags is a mutually exclusive list of image descriptor tags
|
||||
* Username is the username of who's Flickr images you wish to show
|
||||
* using both userid and username is redundant
|
||||
* an api_key is required when using username
|
||||
* Apikey is your own api key provided by Flickr
|
||||
* Target is the id of the document element that the images are
|
||||
* appended to, this target element must exist on the DOM
|
||||
* Numberofimages specify the number of images to retreive from flickr, defaults to 8
|
||||
* Height the height of the component, defaults to '50px'
|
||||
* Width the width of the component, defaults to '50px'
|
||||
* Numberofimages specify the number of images to retreive from flickr, defaults to 4
|
||||
* Height the height of the image, defaults to '50px'
|
||||
* Width the width of the image, defaults to '50px'
|
||||
* Padding number of pixels between images, defaults to '5px'
|
||||
* Border border size in pixels around images, defaults to '0px'
|
||||
*
|
||||
|
@ -36,96 +40,128 @@
|
|||
} )
|
||||
*
|
||||
*/
|
||||
Popcorn.plugin( "flickr" , {
|
||||
Popcorn.plugin( "flickr" , function( options ) {
|
||||
var containerDiv,
|
||||
_userid,
|
||||
_uri,
|
||||
_link,
|
||||
_image,
|
||||
_count = options.numberofimages || 4 ,
|
||||
_height = options.height || "50px",
|
||||
_width = options.width || "50px",
|
||||
_padding = options.padding || "5px",
|
||||
_border = options.border || "0px",
|
||||
i;
|
||||
|
||||
manifest: {
|
||||
about:{
|
||||
name: "Popcorn Flickr Plugin",
|
||||
version: "0.1.1",
|
||||
author: "Scott Downe, Steven Weerdenburg",
|
||||
website: "http://scottdowne.wordpress.com/"
|
||||
},
|
||||
options:{
|
||||
start : {elem:'input', type:'number', label:'In'},
|
||||
end : {elem:'input', type:'number', label:'Out'},
|
||||
userid : {elem:'input', type:'text', label:'Source'},
|
||||
tags : {elem:'input', type:'text', label:'Tags'},
|
||||
target : 'Flickr-container',
|
||||
height : {elem:'input', type:'text', label:'Height'},
|
||||
width : {elem:'input', type:'text', label:'Width'},
|
||||
padding : {elem:'input', type:'text', label:'Padding'},
|
||||
border : {elem:'input', type:'text', label:'Border'},
|
||||
numberofimages : {elem:'input', type:'text', label:'Number of Images'}
|
||||
}
|
||||
},
|
||||
|
||||
_setup: function( options ) {
|
||||
options.container = document.createElement( 'div' );
|
||||
options.container.style.display = "none";
|
||||
|
||||
if ( document.getElementById( options.target ) ) {
|
||||
document.getElementById( options.target ).appendChild( options.container );
|
||||
}
|
||||
|
||||
var height = options.height || "50px",
|
||||
width = options.width || "50px",
|
||||
count = options.numberofimages || 4,
|
||||
padding = options.padding || "5px",
|
||||
tags = options.tags || "",
|
||||
userid = options.userid || "",
|
||||
border = options.border || "0px",
|
||||
uri = "http://api.flickr.com/services/feeds/photos_public.gne?";
|
||||
|
||||
if ( userid ) {
|
||||
uri += "id="+userid+"&";
|
||||
}
|
||||
|
||||
if ( tags ) {
|
||||
uri += "tags="+tags+"&";
|
||||
}
|
||||
|
||||
uri += "lang=en-us&format=json&jsoncallback=flickr";
|
||||
|
||||
Popcorn.xhr.getJSONP( uri, function( data ) {
|
||||
options.container.innerHTML = "<p style='padding:" + padding + ";'>" + data.title + "<p/>";
|
||||
|
||||
Popcorn.forEach( data.items, function ( item, i ) {
|
||||
if ( i < count ) {
|
||||
var link = document.createElement('a');
|
||||
link.setAttribute( 'href', item.link );
|
||||
link.setAttribute( "target", "_blank" );
|
||||
var image = document.createElement( 'img' );
|
||||
image.setAttribute( 'src', item.media.m );
|
||||
image.setAttribute( 'height', height );
|
||||
image.setAttribute( 'width', width );
|
||||
image.setAttribute( 'style', 'border:' + border + ';padding:' + padding );
|
||||
link.appendChild( image );
|
||||
|
||||
options.container.appendChild( link );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// create a new div this way anything in the target div is left intact
|
||||
// this is later populated with Flickr images
|
||||
containerDiv = document.createElement( "div" );
|
||||
containerDiv.id = "flickr"+ i;
|
||||
containerDiv.style.width = "100%";
|
||||
containerDiv.style.height = "100%";
|
||||
containerDiv.style.display = "none";
|
||||
i++;
|
||||
|
||||
// ensure the target container the user chose exists
|
||||
if ( document.getElementById( options.target ) ) {
|
||||
document.getElementById( options.target ).appendChild( containerDiv );
|
||||
} else {
|
||||
throw ( "flickr target container doesn't exist" );
|
||||
}
|
||||
|
||||
// get the userid from Flickr API by using the username and apikey
|
||||
var isUserIDReady = function() {
|
||||
if ( !_userid ) {
|
||||
_uri = "http://api.flickr.com/services/rest/?method=flickr.people.findByUsername&";
|
||||
_uri += "username=" + options.username + "&api_key=" + options.apikey + "&format=json&jsoncallback=flickr";
|
||||
Popcorn.xhr.getJSONP( _uri, function(data) {
|
||||
_userid = data.user.nsid;
|
||||
getFlickrData();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @member Flickr
|
||||
* The start function will be executed when the currentTime
|
||||
* of the video reaches the start time provided by the
|
||||
* options variable
|
||||
*/
|
||||
start: function( event, options ) {
|
||||
options.container.style.display = "inline";
|
||||
},
|
||||
/**
|
||||
* @member Flickr
|
||||
* The end function will be executed when the currentTime
|
||||
* of the video reaches the end time provided by the
|
||||
* options variable
|
||||
*/
|
||||
end: function( event, options ) {
|
||||
options.container.style.display = "none";
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
isUserIDReady();
|
||||
}, 5);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
// get the photos from Flickr API by using the user_id and/or tags
|
||||
var getFlickrData = function() {
|
||||
_uri = "http://api.flickr.com/services/feeds/photos_public.gne?";
|
||||
_uri += "id=" + _userid + "&";
|
||||
if ( options.tags ) {
|
||||
_uri += "tags=" + options.tags + "&";
|
||||
}
|
||||
_uri += "lang=en-us&format=json&jsoncallback=flickr";
|
||||
|
||||
Popcorn.xhr.getJSONP( _uri, function( data ) {
|
||||
containerDiv.innerHTML = "<p style='padding:" + _padding + ";'>" + data.title + "<p/>";
|
||||
|
||||
Popcorn.forEach( data.items, function ( item, i ) {
|
||||
if ( i < _count ) {
|
||||
_link = document.createElement( 'a' );
|
||||
_link.setAttribute( 'href', item.link );
|
||||
_link.setAttribute( "target", "_blank" );
|
||||
_image = document.createElement( 'img' );
|
||||
_image.setAttribute( 'src', item.media.m );
|
||||
_image.setAttribute( 'height',_height );
|
||||
_image.setAttribute( 'width', _width );
|
||||
_image.setAttribute( 'style', 'border:' + _border + ';padding:' + _padding );
|
||||
_link.appendChild( _image );
|
||||
containerDiv.appendChild( _link );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
if ( options.userid ) {
|
||||
_userid = options.userid;
|
||||
getFlickrData();
|
||||
|
||||
} else if ( options.username && options.apikey ) {
|
||||
isUserIDReady();
|
||||
}
|
||||
return {
|
||||
/**
|
||||
* @member flickr
|
||||
* The start function will be executed when the currentTime
|
||||
* of the video reaches the start time provided by the
|
||||
* options variable
|
||||
*/
|
||||
start: function( event, options ){
|
||||
containerDiv.style.display = "inline";
|
||||
},
|
||||
/**
|
||||
* @member flickr
|
||||
* The end function will be executed when the currentTime
|
||||
* of the video reaches the end time provided by the
|
||||
* options variable
|
||||
*/
|
||||
end: function( event, options ){
|
||||
containerDiv.style.display = "none";
|
||||
}
|
||||
};
|
||||
},
|
||||
{
|
||||
about:{
|
||||
name: "Popcorn Flickr Plugin",
|
||||
version: "0.2",
|
||||
author: "Scott Downe, Steven Weerdenburg, Annasob",
|
||||
website: "http://scottdowne.wordpress.com/"
|
||||
},
|
||||
options:{
|
||||
start : {elem:'input', type:'number', label:'In'},
|
||||
end : {elem:'input', type:'number', label:'Out'},
|
||||
userid : {elem:'input', type:'text', label:'UserID'},
|
||||
tags : {elem:'input', type:'text', label:'Tags'},
|
||||
username : {elem:'input', type:'text', label:'Username'},
|
||||
apikey : {elem:'input', type:'text', label:'Api_key'},
|
||||
target : 'Flickr-container',
|
||||
height : {elem:'input', type:'text', label:'Height'},
|
||||
width : {elem:'input', type:'text', label:'Width'},
|
||||
padding : {elem:'input', type:'text', label:'Padding'},
|
||||
border : {elem:'input', type:'text', label:'Border'},
|
||||
numberofimages : {elem:'input', type:'text', label:'Number of Images'}
|
||||
}
|
||||
});
|
||||
})( Popcorn );
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn API</title>
|
||||
<title>Popcorn Flickr</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
<!--
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
test("Popcorn Flickr Plugin", function () {
|
||||
|
||||
var popped = Popcorn("#video"),
|
||||
expects = 5,
|
||||
expects = 7,
|
||||
count = 0,
|
||||
flickrdiv = document.getElementById('flickrdiv');
|
||||
|
||||
|
@ -27,7 +27,15 @@ test("Popcorn Flickr Plugin", function () {
|
|||
userid: '35034346917@N01',
|
||||
numberofimages: '1',
|
||||
target: 'flickrdiv'
|
||||
} );
|
||||
} )
|
||||
.flickr({
|
||||
start: 4, // seconds
|
||||
end: 7, // seconds
|
||||
username: 'AniaSob',
|
||||
apikey: 'd1d249260dd1673ec8810c8ce5150ae1',
|
||||
numberofimages: '1',
|
||||
target: 'flickrdiv'
|
||||
} );;
|
||||
|
||||
popped.exec( 2, function() {
|
||||
ok( /display: inline;/.test( flickrdiv.innerHTML ), "Div contents are displayed" );
|
||||
|
@ -35,8 +43,15 @@ test("Popcorn Flickr Plugin", function () {
|
|||
ok( /img/.test( flickrdiv.innerHTML ), "An image exists" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.exec( 5, function() {
|
||||
ok( /display: inline;/.test( flickrdiv.innerHTML ), "Div contents are displayed" );
|
||||
plus();
|
||||
ok( /img/.test( flickrdiv.innerHTML ), "An image exists" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.exec( 4, function() {
|
||||
popped.exec( 7, function() {
|
||||
ok( /display: none;/.test( flickrdiv.innerHTML ), "Div contents are hidden again" );
|
||||
plus();
|
||||
});
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
(function (Popcorn) {
|
||||
|
||||
var i = 1,
|
||||
scriptLoaded = false,
|
||||
callBack = function( data ) {
|
||||
scriptLoading = false,
|
||||
scriptLoaded = false,
|
||||
callBack = function( data ) {
|
||||
|
||||
if ( typeof google !== 'undefined' && google.load ) {
|
||||
|
||||
|
@ -17,17 +18,6 @@
|
|||
}
|
||||
};
|
||||
|
||||
Popcorn.getScript( "http://www.google.com/jsapi", callBack );
|
||||
Popcorn.getScript( "http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js" );
|
||||
|
||||
//Doing this because I cannot find something similar to getScript() for css files
|
||||
var head = document.getElementsByTagName("head")[0];
|
||||
var css = document.createElement('link');
|
||||
css.type = "text/css";
|
||||
css.rel = "stylesheet";
|
||||
css.href = "http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css";
|
||||
head.insertBefore( css, head.firstChild );
|
||||
|
||||
/**
|
||||
* googlefeed popcorn plug-in
|
||||
* Adds a feed from the specified blog url at the target div
|
||||
|
@ -81,6 +71,22 @@
|
|||
}
|
||||
};
|
||||
|
||||
if ( !scriptLoading ) {
|
||||
|
||||
scriptLoading = true;
|
||||
|
||||
Popcorn.getScript( "http://www.google.com/jsapi", callBack );
|
||||
Popcorn.getScript( "http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js" );
|
||||
|
||||
//Doing this because I cannot find something similar to getScript() for css files
|
||||
var head = document.getElementsByTagName("head")[0];
|
||||
var css = document.createElement('link');
|
||||
css.type = "text/css";
|
||||
css.rel = "stylesheet";
|
||||
css.href = "http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css";
|
||||
head.insertBefore( css, head.firstChild );
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
||||
return {
|
||||
|
|
|
@ -2,6 +2,37 @@
|
|||
var googleCallback;
|
||||
(function (Popcorn) {
|
||||
|
||||
var i = 1,
|
||||
_mapFired = false,
|
||||
_mapLoaded = false,
|
||||
geocoder,
|
||||
loadMaps;
|
||||
//google api callback
|
||||
googleCallback = function( data ) {
|
||||
// ensure all of the maps functions needed are loaded
|
||||
// before setting _maploaded to true
|
||||
if ( typeof google !== "undefined" && google.maps && google.maps.Geocoder && google.maps.LatLng ) {
|
||||
geocoder = new google.maps.Geocoder();
|
||||
_mapLoaded = true;
|
||||
} else {
|
||||
setTimeout( function() {
|
||||
googleCallback( data );
|
||||
}, 1);
|
||||
}
|
||||
};
|
||||
// function that loads the google api
|
||||
loadMaps = function () {
|
||||
// for some reason the Google Map API adds content to the body
|
||||
if ( document.body ) {
|
||||
_mapFired = true;
|
||||
Popcorn.getScript( "http://maps.google.com/maps/api/js?sensor=false&callback=googleCallback" );
|
||||
} else {
|
||||
setTimeout( function() {
|
||||
loadMaps( );
|
||||
}, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* googlemap popcorn plug-in
|
||||
* Adds a map to the target div centered on the location specified by the user
|
||||
|
@ -31,67 +62,60 @@ var googleCallback;
|
|||
} )
|
||||
*
|
||||
*/
|
||||
|
||||
var newdiv,
|
||||
i = 1,
|
||||
_mapFired = false,
|
||||
_mapLoaded = false;
|
||||
|
||||
// callback function fires when the script is run
|
||||
googleCallback = function() {
|
||||
_mapLoaded = true;
|
||||
};
|
||||
// insert google api script once
|
||||
if (!_mapFired) {
|
||||
_mapFired = true;
|
||||
Popcorn.getScript("http://maps.google.com/maps/api/js?sensor=false&callback=googleCallback");
|
||||
}
|
||||
|
||||
|
||||
Popcorn.plugin( "googlemap" , function( options ) {
|
||||
var newdiv,
|
||||
map,
|
||||
location;
|
||||
|
||||
// create a new div this way anything in the target div
|
||||
// this is later passed on to the maps api
|
||||
newdiv = document.createElement("div");
|
||||
newdiv.id = "actualmap" + i;
|
||||
newdiv.style.width = "100%";
|
||||
newdiv.style.height = "100%";
|
||||
i++;
|
||||
if (document.getElementById(options.target)) {
|
||||
document.getElementById(options.target).appendChild(newdiv);
|
||||
|
||||
// if this is the firest time running the plugins
|
||||
// call the function that gets the sctipt
|
||||
if ( !_mapFired ) {
|
||||
loadMaps();
|
||||
}
|
||||
|
||||
// If there is no lat/lng, and there is location, geocode the location
|
||||
// you can only do this once google.maps exists
|
||||
var isGeoReady = function() {
|
||||
if ( !_mapLoaded ) {
|
||||
setTimeout(function () {
|
||||
isGeoReady();
|
||||
}, 5);
|
||||
} else {
|
||||
if (options.location) {
|
||||
var geocoder = new google.maps.Geocoder();
|
||||
// calls an anonymous function called on separate thread
|
||||
geocoder.geocode({ "address": options.location}, function(results, status) {
|
||||
if (status === google.maps.GeocoderStatus.OK) {
|
||||
// create a new div this way anything in the target div is left intact
|
||||
// this is later passed on to the maps api
|
||||
newdiv = document.createElement( "div" );
|
||||
newdiv.id = "actualmap" + i;
|
||||
newdiv.style.width = "100%";
|
||||
newdiv.style.height = "100%";
|
||||
i++;
|
||||
|
||||
// ensure the target container the user chose exists
|
||||
if ( document.getElementById( options.target ) ) {
|
||||
document.getElementById(options.target).appendChild(newdiv);
|
||||
} else {
|
||||
throw ( "map target container doesn't exist" );
|
||||
}
|
||||
|
||||
// ensure that google maps and its functions are loaded
|
||||
// before setting up the map parameters
|
||||
var isMapReady = function() {
|
||||
if ( _mapLoaded ) {
|
||||
if ( options.location ) {
|
||||
// calls an anonymous google function called on separate thread
|
||||
geocoder.geocode( { "address": options.location }, function( results, status ) {
|
||||
if ( status === google.maps.GeocoderStatus.OK ) {
|
||||
options.lat = results[0].geometry.location.lat();
|
||||
options.lng = results[0].geometry.location.lng();
|
||||
location = new google.maps.LatLng(options.lat, options.lng);
|
||||
map = new google.maps.Map(newdiv, {mapTypeId: google.maps.MapTypeId[options.type] || google.maps.MapTypeId.HYBRID });
|
||||
location = new google.maps.LatLng( options.lat, options.lng );
|
||||
map = new google.maps.Map( newdiv, { mapTypeId: google.maps.MapTypeId[ options.type ] || google.maps.MapTypeId.HYBRID } );
|
||||
map.getDiv().style.display = "none";
|
||||
}
|
||||
});
|
||||
} );
|
||||
} else {
|
||||
location = new google.maps.LatLng(options.lat, options.lng);
|
||||
map = new google.maps.Map(newdiv, {mapTypeId: google.maps.MapTypeId[options.type] || google.maps.MapTypeId.HYBRID });
|
||||
location = new google.maps.LatLng( options.lat, options.lng );
|
||||
map = new google.maps.Map( newdiv, { mapTypeId: google.maps.MapTypeId[ options.type ] || google.maps.MapTypeId.HYBRID } );
|
||||
map.getDiv().style.display = "none";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
isMapReady();
|
||||
}, 5);
|
||||
}
|
||||
};
|
||||
isGeoReady();
|
||||
|
||||
isMapReady();
|
||||
|
||||
return {
|
||||
/**
|
||||
|
@ -101,13 +125,9 @@ var googleCallback;
|
|||
* options variable
|
||||
*/
|
||||
start: function(event, options){
|
||||
// dont do anything if the information didn't come back from google map
|
||||
var isReady = function () {
|
||||
if (!map) {
|
||||
setTimeout(function () {
|
||||
isReady();
|
||||
}, 13);
|
||||
} else {
|
||||
// ensure the map has been initialized in the setup function above
|
||||
var isMapSetup = function () {
|
||||
if ( map ) {
|
||||
map.getDiv().style.display = "block";
|
||||
// reset the location and zoom just in case the user plaid with the map
|
||||
map.setCenter(location);
|
||||
|
@ -139,16 +159,20 @@ var googleCallback;
|
|||
position: location,
|
||||
pov: {
|
||||
heading: options.heading = options.heading || 0,
|
||||
pitch: options.pitch = options.pitch || 0,
|
||||
pitch: options.pitch = options.pitch || 0,
|
||||
zoom: options.zoom
|
||||
}
|
||||
})
|
||||
} )
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setTimeout( function () {
|
||||
isMapSetup();
|
||||
}, 13);
|
||||
}
|
||||
};
|
||||
|
||||
isReady();
|
||||
isMapSetup();
|
||||
},
|
||||
/**
|
||||
* @member webpage
|
||||
|
@ -162,6 +186,11 @@ var googleCallback;
|
|||
if (map) {
|
||||
map.getDiv().style.display = "none";
|
||||
}
|
||||
},
|
||||
_teardown: function( options ) {
|
||||
// the map must be manually removed
|
||||
document.getElementById( options.target ).removeChild( newdiv );
|
||||
newdiv = map = location = null;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
test("Popcorn Google Map Plugin", function () {
|
||||
|
||||
var popped = Popcorn("#video"),
|
||||
expects = 10,
|
||||
count = 0;
|
||||
expects = 11,
|
||||
count = 0,
|
||||
setupId;
|
||||
|
||||
expect(expects);
|
||||
|
||||
|
@ -31,7 +32,7 @@ test("Popcorn Google Map Plugin", function () {
|
|||
lat: 43.665429,
|
||||
lng: -79.403323,
|
||||
zoom: 10
|
||||
} )
|
||||
})
|
||||
.googlemap({
|
||||
start: 0, // seconds
|
||||
end: 5, // seconds
|
||||
|
@ -39,9 +40,20 @@ test("Popcorn Google Map Plugin", function () {
|
|||
target: 'map2',
|
||||
location:'boston',
|
||||
zoom: 15
|
||||
} )
|
||||
})
|
||||
.volume(0);
|
||||
|
||||
popped.googlemap({
|
||||
start: 0, // seconds
|
||||
end: 10, // seconds
|
||||
type: 'SATELLITE',
|
||||
target: 'map2',
|
||||
location:'toronto',
|
||||
zoom: 15
|
||||
});
|
||||
|
||||
setupId = popped.getLastTrackEventId();
|
||||
|
||||
popped.exec( 4, function() {
|
||||
ok(google.maps, "Google maps is available");
|
||||
plus();
|
||||
|
@ -62,7 +74,13 @@ test("Popcorn Google Map Plugin", function () {
|
|||
|
||||
popped.exec( 6, function() {
|
||||
ok (document.getElementById('actualmap2').style.display === "none" &&
|
||||
document.getElementById('actualmap1').style.display === "none", "Both maps are no lnger visible" );
|
||||
document.getElementById('actualmap1').style.display === "none", "Both maps are no longer visible" );
|
||||
plus();
|
||||
popped.pause();
|
||||
|
||||
popped.removeTrackEvent( setupId );
|
||||
|
||||
ok( !document.getElementById('actualmap3'), "removed map was properly destroyed" );
|
||||
plus();
|
||||
});
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
(function (Popcorn) {
|
||||
|
||||
var scriptLoaded = false,
|
||||
scriptLoading = false,
|
||||
callBack = function( data ) {
|
||||
|
||||
if ( typeof google !== 'undefined' && google.load ) {
|
||||
|
@ -17,8 +18,6 @@
|
|||
}
|
||||
};
|
||||
|
||||
Popcorn.getScript( "http://www.google.com/jsapi", callBack );
|
||||
|
||||
/**
|
||||
* Google News popcorn plug-in
|
||||
* Displays Google News information on a topic in a targeted div.
|
||||
|
@ -59,6 +58,12 @@
|
|||
}
|
||||
},
|
||||
_setup : function( options ) {
|
||||
|
||||
if ( !scriptLoading ) {
|
||||
|
||||
scriptLoading = true;
|
||||
Popcorn.getScript( "http://www.google.com/jsapi", callBack );
|
||||
}
|
||||
|
||||
options.container = document.createElement( 'div' );
|
||||
if ( document.getElementById( options.target ) ) {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Google News Plug-in Test</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
<!--
|
||||
do not move - this must be called immediately prior to
|
||||
popcorn-api-draft.js
|
||||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
|
||||
<script src="popcorn.googlenews.js"></script>
|
||||
<script src="popcorn.googlenews.unit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Google News Plugin</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'
|
||||
controls preload='none'
|
||||
width= '250px'
|
||||
poster="../../test/poster.png">
|
||||
|
||||
<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"'>
|
||||
|
||||
<p>Your user agent does not support the HTML5 Video element.</p>
|
||||
|
||||
</video>
|
||||
<div id="googlenewsdiv"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
test( "Popcorn google news Plugin", function () {
|
||||
|
||||
var popped = Popcorn( "#video" ),
|
||||
expects = 7,
|
||||
count = 0,
|
||||
googlenewsdiv = document.getElementById( "googlenewsdiv" );
|
||||
|
||||
expect(expects);
|
||||
|
||||
function plus() {
|
||||
if ( ++count===expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
stop();
|
||||
|
||||
ok ( "googlenews" in popped, "googlenews is a method of the popped instance" );
|
||||
plus();
|
||||
|
||||
equals ( googlenewsdiv.innerHTML, "", "initially, there is nothing inside the googlenewsdiv" );
|
||||
plus();
|
||||
|
||||
popped.googlenews({
|
||||
start: 0, // seconds
|
||||
end: 5, // seconds
|
||||
topic: "Oil Spill",
|
||||
target: "googlenewsdiv"
|
||||
})
|
||||
.googlenews({
|
||||
start: 3, // seconds
|
||||
end: 10, // seconds
|
||||
topic: "Village Telco",
|
||||
target: "googlenewsdiv"
|
||||
})
|
||||
.volume( 0 );
|
||||
|
||||
popped.exec( 1, function() {
|
||||
equals( googlenewsdiv.childElementCount, 2, "googlenewsdiv now has two inner elements" );
|
||||
plus();
|
||||
equals( googlenewsdiv.children[0].style.display , "inline", "first googlenews is visible on the page" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.exec( 4, function() {
|
||||
equals( googlenewsdiv.children[1].style.display , "inline", "second googlenews is visible on the page" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.exec( 11, function() {
|
||||
equals( googlenewsdiv.children[1].style.display , "none", "second googlenews is no longer visible on the page" );
|
||||
plus();
|
||||
equals( googlenewsdiv.children[0].style.display , "none", "first googlenews is no longer visible on the page" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.play();
|
||||
|
||||
});
|
|
@ -15,10 +15,11 @@
|
|||
end: 15, // seconds
|
||||
href: 'http://www.drumbeat.org/',
|
||||
src: 'https://www.drumbeat.org/media//images/drumbeat-logo-splash.png',
|
||||
text: 'DRUMBEAT',
|
||||
target: 'imagediv'
|
||||
} )
|
||||
.image({
|
||||
start: 20, // seconds
|
||||
start: 5, // seconds
|
||||
end: 45, // seconds
|
||||
// no href
|
||||
src: 'http://patriciabergeron.net/wp-content/uploads/web.made_.movie_marquee.gif',
|
||||
|
@ -31,8 +32,9 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Image Plug-in Demo</h1>
|
||||
<p> An image will appear at 5 seconds and disappear at 15 seconds.</p>
|
||||
<p> An image will appear at 20 seconds and disappear at 45 seconds.</p>
|
||||
<p> Two images will appear at 5 seconds.</p>
|
||||
<p> First one (with an overlayed text) will disappear at 15 seconds.</p>
|
||||
<p> Second one (without an overlayed text) will disappear at 45 seconds.</p>
|
||||
<div>
|
||||
<video id='video'
|
||||
controls
|
||||
|
@ -51,7 +53,8 @@
|
|||
|
||||
</video>
|
||||
</div>
|
||||
<div id="imagediv">
|
||||
</div>
|
||||
<div style="width:400px; height:400px" id="imagediv">
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
* Options parameter will need a start, end, href, target and src.
|
||||
* Start is the time that you want this plug-in to execute
|
||||
* End is the time that you want this plug-in to stop executing
|
||||
* href is the url of the destination of a link
|
||||
* href is the url of the destination of a link - optional
|
||||
* Target is the id of the document element that the iframe needs to be attached to,
|
||||
* this target element must exist on the DOM
|
||||
* Src is the url of the image that you want to display
|
||||
* text is the overlayed text on the image - optional
|
||||
*
|
||||
* @param {Object} options
|
||||
*
|
||||
|
@ -22,6 +23,7 @@
|
|||
end: 15, // seconds
|
||||
href: 'http://www.drumbeat.org/',
|
||||
src: 'http://www.drumbeat.org/sites/default/files/domain-2/drumbeat_logo.png',
|
||||
text: 'DRUMBEAT',
|
||||
target: 'imagediv'
|
||||
} )
|
||||
*
|
||||
|
@ -40,27 +42,52 @@
|
|||
end : {elem:'input', type:'number', label:'Out'},
|
||||
href : {elem:'input', type:'text', label:'Link URL'},
|
||||
target : 'Image-container',
|
||||
src : {elem:'input', type:'text', label:'Source URL'}
|
||||
src : {elem:'input', type:'text', label:'Source URL'},
|
||||
text: {elem:'input', type:'text', label:'TEXT'}
|
||||
}
|
||||
},
|
||||
|
||||
_setup: function( options ) {
|
||||
|
||||
options.link = document.createElement( 'a' );
|
||||
options.link.style.display = "none"; // display none by default
|
||||
if ( options.href ) {
|
||||
options.link.href = options.href;
|
||||
}
|
||||
options.link.target = "_blank";
|
||||
if ( document.getElementById( options.target ) ) {
|
||||
document.getElementById( options.target ).appendChild( options.link ); // add the widget's div to the target div
|
||||
}
|
||||
var img = document.createElement( 'img' );
|
||||
img.src = options.src;
|
||||
img.style.borderStyle = "none"; // borders look really bad, if someone wants it they can put it on their div target
|
||||
options.link.style.position = "relative";
|
||||
options.link.style.textDecoration = "none";
|
||||
|
||||
options.link.appendChild( img );
|
||||
|
||||
var img = document.createElement( 'img' );
|
||||
img.addEventListener( "load", function() {
|
||||
img.style.borderStyle = "none"; // borders look really bad, if someone wants it they can put it on their div target
|
||||
|
||||
if ( options.href ) {
|
||||
options.link.href = options.href;
|
||||
}
|
||||
options.link.target = "_blank";
|
||||
if ( document.getElementById( options.target ) ) {
|
||||
document.getElementById( options.target ).appendChild( options.link ); // add the widget's div to the target div
|
||||
}
|
||||
|
||||
var fontHeight = ( img.height / 12 ) + "px";
|
||||
|
||||
var divText = document.createElement( 'div' );
|
||||
divTextStyle = {
|
||||
position: "relative",
|
||||
width: img.width + "px",
|
||||
textAlign: "center",
|
||||
fontSize: fontHeight,
|
||||
color: "black",
|
||||
fontWeight : "bold",
|
||||
zIndex: "10"
|
||||
};
|
||||
for ( var st in divTextStyle ) {
|
||||
divText.style[ st ] = divTextStyle[ st ];
|
||||
}
|
||||
|
||||
divText.innerHTML = options.text || "";
|
||||
options.link.appendChild( divText );
|
||||
options.link.appendChild( img );
|
||||
divText.style.top = ( img.height / 2 ) - ( divText.offsetHeight / 2 ) + "px";
|
||||
options.link.style.display = "none";
|
||||
}, false );
|
||||
img.src = options.src;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -70,7 +97,7 @@
|
|||
* options variable
|
||||
*/
|
||||
start: function( event, options ) {
|
||||
options.link.style.display = "inline";
|
||||
options.link.style.display = "block";
|
||||
},
|
||||
/**
|
||||
* @member image
|
||||
|
|
|
@ -26,20 +26,21 @@ test("Popcorn Image Plugin", function () {
|
|||
end: 3, // seconds
|
||||
href: 'http://www.drumbeat.org/',
|
||||
src: 'https://www.drumbeat.org/media//images/drumbeat-logo-splash.png',
|
||||
text: 'DRUMBEAT',
|
||||
target: 'imagediv'
|
||||
} );
|
||||
});
|
||||
|
||||
popped.exec( 2, function() {
|
||||
ok( /display: inline;/.test( imagediv.innerHTML ), "Div contents are displayed" );
|
||||
plus();
|
||||
ok( /img/.test( imagediv.innerHTML ), "An image exists" );
|
||||
plus();
|
||||
ok( /display: block;/.test( imagediv.innerHTML ), "Div contents are displayed" );
|
||||
plus();
|
||||
ok( /img/.test( imagediv.innerHTML ), "An image exists" );
|
||||
plus();
|
||||
});
|
||||
|
||||
|
||||
popped.exec( 4, function() {
|
||||
ok( /display: none;/.test( imagediv.innerHTML ), "Div contents are hidden again" );
|
||||
plus();
|
||||
ok( /display: none;/.test( imagediv.innerHTML ), "Div contents are hidden again" );
|
||||
plus();
|
||||
});
|
||||
popped.volume(0).play();
|
||||
popped.volume(0).play();
|
||||
|
||||
});
|
||||
|
|
|
@ -14,15 +14,18 @@
|
|||
<li><a onclick="clearEvents();" target="out" href="footnote/popcorn.footnote.unit.html">footnote</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="googlemap/popcorn.googlemap.unit.html">googlemap</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="googlenews/popcorn.googlenews.unit.html">googlenews</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="googlefeed/popcorn.googlefeed.unit.html">googlefeed</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="image/popcorn.image.unit.html">image</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="lastfm/popcorn.lastfm.unit.html">lastfm</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="lowerthird/popcorn.lowerthird.unit.html">lowerthird</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="mustache/popcorn.mustache.unit.html">mustache</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="openmap/popcorn.openmap.unit.html">openmap</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="subtitle/popcorn.subtitle.unit.html">subtitle</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="tagthisperson/popcorn.tagthisperson.unit.html">tagthisperson</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="twitter/popcorn.twitter.unit.html">twitter</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="webpage/popcorn.webpage.unit.html">webpage</a></li>
|
||||
<li><a onclick="clearEvents();" target="out" href="wikipedia/popcorn.wikipedia.unit.html">wikipedia</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<iframe id="out" name="out" style="position:absolute;top:0px;left:150px;height:100%;width:100%"></iframe>
|
||||
|
@ -30,12 +33,13 @@
|
|||
var eventList = [];
|
||||
function runAllTests(){
|
||||
var testUrl = [ "attribution", "code", "flickr", "footnote", "googlemap",
|
||||
"googlenews", "image", "lastfm", "lowerthird", "mustache",
|
||||
"subtitle", "tagthisperson", "twitter", "webpage", "wikipedia" ];
|
||||
//googlenews and lowerthird tests do not exist, therefore their test time is set to 0
|
||||
"googlenews", "googlefeed", "image", "lastfm", "lowerthird",
|
||||
"mustache", "openmap", "subtitle", "tagthisperson", "twitter",
|
||||
"webpage", "wikipedia"];
|
||||
var testDur = [ 17000, 20000, 10000, 20000, 11000,
|
||||
0, 10000, 10000, 0, 15000,
|
||||
25000, 21000, 10000, 21000, 21000 ];
|
||||
13000, 13000, 10000, 10000, 13000,
|
||||
15000, 13000, 25000, 21000, 10000,
|
||||
21000, 21000 ];
|
||||
|
||||
var setTest = function( index ) {
|
||||
var url = function( str ) {
|
||||
|
|
|
@ -30,22 +30,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// just a little tool function
|
||||
// calculates the top and left position of an element
|
||||
var offset = function(elem) {
|
||||
if ( !elem ) { elem = this; }
|
||||
|
||||
var x = elem.offsetLeft;
|
||||
var y = elem.offsetTop;
|
||||
|
||||
while ( !!( elem = elem.offsetParent ) ) {
|
||||
x += elem.offsetLeft;
|
||||
y += elem.offsetTop;
|
||||
}
|
||||
|
||||
return { left: x, top: y };
|
||||
};
|
||||
|
||||
Popcorn.plugin( "lowerthird" , {
|
||||
|
||||
manifest: {
|
||||
|
@ -80,7 +64,7 @@
|
|||
|
||||
// the video element must have height and width defined
|
||||
this.container.style.width = this.video.offsetWidth + "px";
|
||||
this.container.style.left = offset( this.video ).left + "px";
|
||||
this.container.style.left = this.position().left + "px";
|
||||
|
||||
this.video.parentNode.appendChild( this.container );
|
||||
}
|
||||
|
@ -103,7 +87,7 @@
|
|||
*/
|
||||
start: function(event, options){
|
||||
options.container.innerHTML = ( options.salutation ? options.salutation + " " : "" ) + options.name + ( options.role ? "<br />" + options.role : "" );
|
||||
this.container.style.top = offset( this.video ).top + this.video.offsetHeight - ( 40 + this.container.offsetHeight ) + "px";
|
||||
this.container.style.top = this.position().top + this.video.offsetHeight - ( 40 + this.container.offsetHeight ) + "px";
|
||||
},
|
||||
/**
|
||||
* @member lowerthird
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn Lower Third Plug-in Test</title>
|
||||
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
|
||||
<script src="../../test/qunit/qunit.js"></script>
|
||||
<!--
|
||||
do not move - this must be called immediately prior to
|
||||
popcorn-api-draft.js
|
||||
-->
|
||||
|
||||
<script src="../../popcorn.js"></script>
|
||||
|
||||
<script src="popcorn.lowerthird.js"></script>
|
||||
<script src="popcorn.lowerthird.unit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn Lower Third Plugin</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'
|
||||
controls preload='none'
|
||||
width= '250px'
|
||||
poster="../../test/poster.png">
|
||||
|
||||
<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"'>
|
||||
|
||||
<p>Your user agent does not support the HTML5 Video element.</p>
|
||||
|
||||
</video>
|
||||
<div id="lowerthirddiv"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,64 @@
|
|||
test( "Popcorn lower third Plugin", function () {
|
||||
|
||||
var popped = Popcorn( "#video" ),
|
||||
expects = 7,
|
||||
count = 0,
|
||||
lowerthirddiv = document.getElementById( "lowerthirddiv" );
|
||||
|
||||
expect(expects);
|
||||
|
||||
function plus() {
|
||||
if ( ++count===expects ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
stop();
|
||||
|
||||
ok ( "lowerthird" in popped, "lowerthird is a method of the popped instance" );
|
||||
plus();
|
||||
|
||||
equals ( lowerthirddiv.innerHTML, "", "initially, there is nothing inside the lowerthirddiv" );
|
||||
plus();
|
||||
|
||||
ok( !popped.container, "initially, there is no default div" );
|
||||
plus();
|
||||
|
||||
|
||||
popped.lowerthird({
|
||||
start: 0, // seconds
|
||||
end: 5, // seconds
|
||||
salutation: "Mr",
|
||||
name: "Hyde",
|
||||
role: "Monster"
|
||||
} )
|
||||
.lowerthird({
|
||||
start: 3, // seconds
|
||||
end: 10, // seconds
|
||||
target: "lowerthirddiv",
|
||||
salutation: "Dr",
|
||||
name: "Jekyll",
|
||||
role: "Person"
|
||||
} )
|
||||
.volume(0);
|
||||
|
||||
popped.exec( 1, function() {
|
||||
equals ( popped.container.innerHTML, "Mr Hyde<br>Monster", "first lowerthird is visible" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.exec( 4, function() {
|
||||
equals ( lowerthirddiv.innerHTML, "Dr Jekyll<br>Person", "second lowerthird is visible" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.exec( 11, function() {
|
||||
equals ( popped.container.innerHTML, "", "first lowerthird is empty" );
|
||||
plus();
|
||||
equals ( lowerthirddiv.innerHTML, "", "second lowerthird is empty" );
|
||||
plus();
|
||||
});
|
||||
|
||||
popped.play();
|
||||
|
||||
});
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
(function (Popcorn) {
|
||||
|
||||
Popcorn.getScript('https://github.com/janl/mustache.js/raw/master/mustache.js');
|
||||
|
||||
/**
|
||||
* Mustache Popcorn Plug-in
|
||||
*
|
||||
|
@ -87,6 +85,9 @@
|
|||
*/
|
||||
|
||||
Popcorn.plugin( 'mustache' , function( options ) {
|
||||
|
||||
Popcorn.getScript('https://github.com/janl/mustache.js/raw/master/mustache.js');
|
||||
|
||||
var getData, data, getTemplate, template;
|
||||
|
||||
var shouldReload = !!options.dynamic,
|
||||
|
|
|
@ -41,15 +41,6 @@ var openmapCallback;
|
|||
_mapFired = false,
|
||||
_mapLoaded = false;
|
||||
|
||||
// insert openlayers api script once
|
||||
if ( !_mapFired ) {
|
||||
_mapFired = true;
|
||||
Popcorn.getScript('http://openlayers.org/api/OpenLayers.js',
|
||||
function() {
|
||||
_mapLoaded = true;
|
||||
} );
|
||||
}
|
||||
|
||||
Popcorn.plugin( "openmap" , function( options ){
|
||||
var newdiv,
|
||||
map,
|
||||
|
@ -60,6 +51,15 @@ var openmapCallback;
|
|||
selectControl,
|
||||
popup;
|
||||
|
||||
// insert openlayers api script once
|
||||
if ( !_mapFired ) {
|
||||
_mapFired = true;
|
||||
Popcorn.getScript('http://openlayers.org/api/OpenLayers.js',
|
||||
function() {
|
||||
_mapLoaded = true;
|
||||
} );
|
||||
}
|
||||
|
||||
// create a new div within the target div
|
||||
// this is later passed on to the maps api
|
||||
newdiv = document.createElement( 'div' );
|
||||
|
|
|
@ -68,23 +68,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// just a little tool function
|
||||
// calculates the top and left position of an element
|
||||
var offset = function(obj) {
|
||||
var left, top;
|
||||
left = top = 0;
|
||||
if (obj.offsetParent) {
|
||||
do {
|
||||
left += obj.offsetLeft;
|
||||
top += obj.offsetTop;
|
||||
} while ( !!(obj = obj.offsetParent) );
|
||||
}
|
||||
return {
|
||||
left : left,
|
||||
top : top
|
||||
};
|
||||
};
|
||||
|
||||
// translates whatever is in options.container into selected language
|
||||
var translate = function( options, text ) {
|
||||
|
||||
|
@ -128,9 +111,9 @@
|
|||
this.container.style.textAlign = "center";
|
||||
|
||||
// the video element must have height and width defined
|
||||
this.container.style.width = this.video.offsetWidth + "px";
|
||||
this.container.style.top = offset( this.video ).top + this.video.offsetHeight - 65 + "px";
|
||||
this.container.style.left = offset( this.video ).left + "px";
|
||||
this.container.style.width = this.media.offsetWidth + "px";
|
||||
this.container.style.top = this.position().top + this.media.offsetHeight - 65 + "px";
|
||||
this.container.style.left = this.position().left + "px";
|
||||
|
||||
document.body.appendChild( this.container );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// PLUGIN: TWITTER
|
||||
|
||||
(function (Popcorn) {
|
||||
var scriptLoading = false;
|
||||
|
||||
/**
|
||||
* Twitter popcorn plug-in
|
||||
|
@ -30,10 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
if ( !window.TWTR ) {
|
||||
Popcorn.getScript("http://widgets.twimg.com/j/2/widget.js");
|
||||
}
|
||||
|
||||
Popcorn.plugin( "twitter" , {
|
||||
|
||||
manifest: {
|
||||
|
@ -55,6 +52,11 @@
|
|||
|
||||
_setup: function( options ) {
|
||||
|
||||
if ( !window.TWTR && !scriptLoading ) {
|
||||
scriptLoading = true;
|
||||
Popcorn.getScript("http://widgets.twimg.com/j/2/widget.js");
|
||||
}
|
||||
|
||||
// setup widget div that is unique per track
|
||||
options.container = document.createElement( 'div' ); // create the div to store the widget
|
||||
options.container.setAttribute('id', Popcorn.guid()); // use this id to connect it to the widget
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
*/
|
||||
start: function(event, options){
|
||||
// make the iframe visible
|
||||
options._iframe.src = options.src;
|
||||
options._iframe.style.display = 'inline';
|
||||
},
|
||||
/**
|
||||
|
|
325
popcorn.js
325
popcorn.js
|
@ -1,11 +1,3 @@
|
|||
/*
|
||||
* popcorn.js version @VERSION
|
||||
* http://popcornjs.org
|
||||
*
|
||||
* Copyright 2011, Mozilla Foundation
|
||||
* Licensed under the MIT license
|
||||
*/
|
||||
|
||||
(function(global, document) {
|
||||
|
||||
// Cache refs to speed up calls to native utils
|
||||
|
@ -13,6 +5,7 @@
|
|||
forEach = Array.prototype.forEach,
|
||||
hasOwn = Object.prototype.hasOwnProperty,
|
||||
slice = Array.prototype.slice,
|
||||
toString = Object.prototype.toString,
|
||||
|
||||
// ID string matching
|
||||
rIdExp = /^(#([\w\-\_\.]+))$/,
|
||||
|
@ -25,9 +18,9 @@
|
|||
|
||||
// Declare constructor
|
||||
// Returns an instance object.
|
||||
Popcorn = function( entity ) {
|
||||
Popcorn = function( entity, options ) {
|
||||
// Return new Popcorn object
|
||||
return new Popcorn.p.init( entity );
|
||||
return new Popcorn.p.init( entity, options || null );
|
||||
};
|
||||
|
||||
// Instance caching
|
||||
|
@ -55,9 +48,9 @@
|
|||
Popcorn.addInstance = function( instance ) {
|
||||
|
||||
var instanceLen = Popcorn.instances.length,
|
||||
instanceId = instance.video.id && instance.video.id;
|
||||
instanceId = instance.media.id && instance.media.id;
|
||||
|
||||
// If the video element has its own `id` use it, otherwise provide one
|
||||
// If the media element has its own `id` use it, otherwise provide one
|
||||
// Ensure that instances have unique ids and unique entries
|
||||
// Uses `in` operator to avoid false positives on 0
|
||||
instance.id = !( instanceId in Popcorn.instanceIds ) && instanceId ||
|
||||
|
@ -87,7 +80,7 @@
|
|||
// the new prototype for our Popcorn constructor
|
||||
Popcorn.p = Popcorn.prototype = {
|
||||
|
||||
init: function( entity ) {
|
||||
init: function( entity, options ) {
|
||||
|
||||
var matches;
|
||||
|
||||
|
@ -139,14 +132,18 @@
|
|||
// Check if entity is a valid string id
|
||||
matches = rIdExp.exec( entity );
|
||||
|
||||
// Get video element by id or object reference
|
||||
this.video = matches && matches.length && matches[ 2 ] ?
|
||||
// Get media element by id or object reference
|
||||
this.media = matches && matches.length && matches[ 2 ] ?
|
||||
document.getElementById( matches[ 2 ] ) :
|
||||
entity;
|
||||
|
||||
// Create an audio or video element property reference
|
||||
this[ ( this.media.tagName && this.media.tagName.toLowerCase() ) || "video" ] = this.media;
|
||||
|
||||
// Register new instance
|
||||
Popcorn.addInstance( this );
|
||||
|
||||
this.options = options || { };
|
||||
this.data = {
|
||||
history: [],
|
||||
events: {},
|
||||
|
@ -168,20 +165,20 @@
|
|||
// Wrap true ready check
|
||||
var isReady = function( that ) {
|
||||
|
||||
if ( that.video.readyState >= 2 ) {
|
||||
if ( that.media.readyState >= 2 ) {
|
||||
// Adding padding to the front and end of the arrays
|
||||
// this is so we do not fall off either end
|
||||
|
||||
var duration = that.video.duration;
|
||||
// Check for no duration info (NaN)
|
||||
var videoDurationPlus = duration != duration ? Number.MAX_VALUE : duration + 1;
|
||||
var duration = that.media.duration,
|
||||
// Check for no duration info (NaN)
|
||||
videoDurationPlus = duration != duration ? Number.MAX_VALUE : duration + 1;
|
||||
|
||||
Popcorn.addTrackEvent( that, {
|
||||
start: videoDurationPlus,
|
||||
end: videoDurationPlus
|
||||
});
|
||||
|
||||
that.video.addEventListener( "timeupdate", function( event ) {
|
||||
that.media.addEventListener( "timeupdate", function( event ) {
|
||||
|
||||
var currentTime = this.currentTime,
|
||||
previousTime = that.data.trackEvents.previousUpdateTime,
|
||||
|
@ -312,7 +309,7 @@
|
|||
// A Few reusable utils, memoized onto Popcorn
|
||||
Popcorn.extend( Popcorn, {
|
||||
error: function( msg ) {
|
||||
throw msg;
|
||||
throw new Error( msg );
|
||||
},
|
||||
guid: function( prefix ) {
|
||||
Popcorn.guid.counter++;
|
||||
|
@ -327,7 +324,39 @@
|
|||
|
||||
return size;
|
||||
},
|
||||
nop: function () {}
|
||||
isArray: Array.isArray || function( array ) {
|
||||
return toString.call( array ) === "[object Array]";
|
||||
},
|
||||
|
||||
nop: function () {},
|
||||
|
||||
position: function( elem ) {
|
||||
|
||||
var clientRect = elem.getBoundingClientRect(),
|
||||
bounds = {},
|
||||
doc = elem.ownerDocument,
|
||||
docElem = document.documentElement,
|
||||
body = document.body,
|
||||
clientTop, clientLeft, scrollTop, scrollLeft, top, left;
|
||||
|
||||
// Determine correct clientTop/Left
|
||||
clientTop = docElem.clientTop || body.clientTop || 0;
|
||||
clientLeft = docElem.clientLeft || body.clientLeft || 0;
|
||||
|
||||
// Determine correct scrollTop/Left
|
||||
scrollTop = ( global.pageYOffset && docElem.scrollTop || body.scrollTop );
|
||||
scrollLeft = ( global.pageXOffset && docElem.scrollLeft || body.scrollLeft );
|
||||
|
||||
// Temp top/left
|
||||
top = Math.ceil( clientRect.top + scrollTop - clientTop );
|
||||
left = Math.ceil( clientRect.left + scrollLeft - clientLeft );
|
||||
|
||||
for ( var p in clientRect ) {
|
||||
bounds[ p ] = Math.round( clientRect[ p ] );
|
||||
}
|
||||
|
||||
return Popcorn.extend({}, bounds, { top: top, left: left });
|
||||
}
|
||||
});
|
||||
|
||||
// Memoized GUID Counter
|
||||
|
@ -347,8 +376,8 @@
|
|||
|
||||
ret[ name ] = function( arg ) {
|
||||
|
||||
if ( typeof this.video[name] === "function" ) {
|
||||
this.video[ name ]();
|
||||
if ( typeof this.media[name] === "function" ) {
|
||||
this.media[ name ]();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -356,12 +385,12 @@
|
|||
|
||||
if ( arg !== false && arg !== null && typeof arg !== "undefined" ) {
|
||||
|
||||
this.video[ name ] = arg;
|
||||
this.media[ name ] = arg;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.video[ name ];
|
||||
return this.media[ name ];
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -374,7 +403,7 @@
|
|||
|
||||
// Rounded currentTime
|
||||
roundTime: function () {
|
||||
return -~this.video.currentTime;
|
||||
return -~this.media.currentTime;
|
||||
},
|
||||
|
||||
// Attach an event to a single point in time
|
||||
|
@ -393,6 +422,9 @@
|
|||
});
|
||||
|
||||
return this;
|
||||
},
|
||||
position: function() {
|
||||
return Popcorn.position( this.media );
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -456,7 +488,7 @@
|
|||
var evt = document.createEvent( eventInterface );
|
||||
evt.initEvent(type, true, true, global, 1);
|
||||
|
||||
this.video.dispatchEvent(evt);
|
||||
this.media.dispatchEvent(evt);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -487,7 +519,7 @@
|
|||
// only attach one event of any type
|
||||
if ( !hasEvents && Popcorn.events.all.indexOf( type ) > -1 ) {
|
||||
|
||||
this.video.addEventListener( type, function( event ) {
|
||||
this.media.addEventListener( type, function( event ) {
|
||||
|
||||
Popcorn.forEach( self.data.events[type], function ( obj, key ) {
|
||||
if ( typeof obj === "function" ) {
|
||||
|
@ -541,6 +573,9 @@
|
|||
track._natives.end = track._natives.end || Popcorn.nop;
|
||||
}
|
||||
|
||||
track.start = Popcorn.util.toSeconds( track.start, obj.options.framerate );
|
||||
track.end = Popcorn.util.toSeconds( track.end, obj.options.framerate );
|
||||
|
||||
// Store this definition in an array sorted by times
|
||||
obj.data.trackEvents.byStart.push( track );
|
||||
obj.data.trackEvents.byEnd.push( track );
|
||||
|
@ -569,8 +604,9 @@
|
|||
|
||||
// remove plugin reference from registry
|
||||
for ( registryIdx = 0; registryIdx < registryLen; registryIdx++ ) {
|
||||
if ( Popcorn.registry[ registryIdx ].type === name ) {
|
||||
if ( Popcorn.registry[ registryIdx ].name === name ) {
|
||||
Popcorn.registry.splice( registryIdx, 1 );
|
||||
delete Popcorn.registryByName[ name ];
|
||||
|
||||
// delete the plugin
|
||||
delete obj[ name ];
|
||||
|
@ -633,6 +669,7 @@
|
|||
// Capture the position of the track being removed.
|
||||
if ( o._id === trackId ) {
|
||||
indexWasAt = i;
|
||||
o._natives._teardown && o._natives._teardown.call( obj, o );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -707,6 +744,7 @@
|
|||
Popcorn.manifest = {};
|
||||
// Plugins are registered
|
||||
Popcorn.registry = [];
|
||||
Popcorn.registryByName = {};
|
||||
// An interface for extending Popcorn
|
||||
// with plugin functionality
|
||||
Popcorn.plugin = function( name, definition, manifest ) {
|
||||
|
@ -804,15 +842,109 @@
|
|||
Popcorn.extend( Popcorn.p, plugin );
|
||||
|
||||
// Push into the registry
|
||||
var entry = {
|
||||
fn: plugin[ name ],
|
||||
definition: definition,
|
||||
base: definition,
|
||||
parents: [],
|
||||
name: name
|
||||
};
|
||||
Popcorn.registry.push(
|
||||
Popcorn.extend( plugin, {
|
||||
Popcorn.extend( plugin, entry, {
|
||||
type: name
|
||||
})
|
||||
);
|
||||
);
|
||||
Popcorn.registryByName[ name ] = entry;
|
||||
|
||||
return plugin;
|
||||
};
|
||||
|
||||
// Popcorn Plugin Inheritance Helper Methods
|
||||
// Internal use only
|
||||
Popcorn.plugin.getDefinition = function( name ) {
|
||||
|
||||
var registry = Popcorn.registryByName;
|
||||
|
||||
if ( registry[ name ] ) {
|
||||
return registry[ name ];
|
||||
}
|
||||
|
||||
Popcorn.error( "Cannot inherit from "+ name +"; Object does not exist" );
|
||||
};
|
||||
|
||||
// Internal use only
|
||||
Popcorn.plugin.delegate = function( instance, name, plugins ) {
|
||||
|
||||
return function() {
|
||||
var args = arguments;
|
||||
plugins.forEach( function( plugin ) {
|
||||
// The new plugin simply calls the delegated methods on
|
||||
// all of its parents in the order they were specified.
|
||||
plugin[ name ] && plugin[ name ].apply( instance, args );
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
// Plugin inheritance
|
||||
Popcorn.plugin.inherit = function( name, parents, definition, manifest ) {
|
||||
|
||||
|
||||
// Get the names of all of the ancestor classes, in the order that
|
||||
// we will be calling them. The override is for the class we're
|
||||
// currently defining, since it's not in the registry yet.
|
||||
var ancestors = [],
|
||||
pluginFn, entry;
|
||||
|
||||
function getAncestors( name, override ) {
|
||||
var parents = override || Popcorn.plugin.getDefinition( name ).parents;
|
||||
for ( var i in parents ) {
|
||||
if ( hasOwn.call( parents, i ) ) {
|
||||
var p = parents[ i ];
|
||||
getAncestors( p );
|
||||
if ( ancestors.indexOf( p ) === -1 ) {
|
||||
ancestors.push( p );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getAncestors( name, Popcorn.isArray( parents ) ? parents : [ parents ] );
|
||||
ancestors.push( name );
|
||||
|
||||
// Now create the requested plugin under the reqested name.
|
||||
pluginFn = Popcorn.plugin( name, function( options ) {
|
||||
|
||||
var self = this,
|
||||
plugins;
|
||||
|
||||
function instantiate( definition ) {
|
||||
return definition.call && definition.call( self, options ) || definition;
|
||||
}
|
||||
|
||||
// When the newly-defined plugin is instantiated, it must
|
||||
// explicitly instantiate all of its ancestors.
|
||||
plugins = ancestors.map( function( name ) {
|
||||
return instantiate( Popcorn.plugin.getDefinition( name ).base );
|
||||
});
|
||||
|
||||
return {
|
||||
_setup: Popcorn.plugin.delegate( self, "_setup", plugins ),
|
||||
start: Popcorn.plugin.delegate( self, "start", plugins ),
|
||||
end: Popcorn.plugin.delegate( self, "end", plugins )
|
||||
};
|
||||
|
||||
}, manifest || definition.manifest );
|
||||
|
||||
entry = Popcorn.plugin.getDefinition( name );
|
||||
entry.base = definition;
|
||||
entry.parents = parents;
|
||||
|
||||
return pluginFn;
|
||||
};
|
||||
|
||||
// Augment Popcorn;
|
||||
Popcorn.inherit = Popcorn.plugin.inherit;
|
||||
|
||||
// stores parsers keyed on filetype
|
||||
Popcorn.parsers = {};
|
||||
|
||||
|
@ -922,14 +1054,16 @@
|
|||
|
||||
Popcorn.xhr = function ( options ) {
|
||||
|
||||
options.dataType = options.dataType && options.dataType.toLowerCase() || null;
|
||||
|
||||
if ( options.dataType &&
|
||||
( options.dataType.toLowerCase() === "jsonp" ||
|
||||
options.dataType.toLowerCase() === "script" ) ) {
|
||||
( options.dataType === "jsonp" ||
|
||||
options.dataType === "script" ) ) {
|
||||
|
||||
Popcorn.xhr.getJSONP(
|
||||
options.url,
|
||||
options.success,
|
||||
options.dataType.toLowerCase() === "script"
|
||||
options.dataType === "script"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -939,10 +1073,6 @@
|
|||
// Create new XMLHttpRequest object
|
||||
settings.ajax = settings.xhr();
|
||||
|
||||
// Normalize dataType
|
||||
settings.dataType = settings.dataType.toLowerCase();
|
||||
|
||||
|
||||
if ( settings.ajax ) {
|
||||
|
||||
if ( settings.type === "GET" && settings.data ) {
|
||||
|
@ -1058,25 +1188,25 @@
|
|||
|
||||
script.onload = script.onreadystatechange = function() {
|
||||
|
||||
if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) {
|
||||
if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) {
|
||||
|
||||
// Handling remote script loading callbacks
|
||||
if ( isScript ) {
|
||||
// Handling remote script loading callbacks
|
||||
if ( isScript ) {
|
||||
|
||||
// getScript
|
||||
success && success();
|
||||
}
|
||||
// getScript
|
||||
success && success();
|
||||
}
|
||||
|
||||
// Executing for JSONP requests
|
||||
if ( isFired ) {
|
||||
// Executing for JSONP requests
|
||||
if ( isFired ) {
|
||||
|
||||
// Garbage collect the callback
|
||||
delete window[ callback ];
|
||||
// Garbage collect the callback
|
||||
delete window[ callback ];
|
||||
|
||||
// Garbage collect the script resource
|
||||
head.removeChild( script );
|
||||
}
|
||||
}
|
||||
// Garbage collect the script resource
|
||||
head.removeChild( script );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
script.src = url;
|
||||
|
@ -1093,37 +1223,90 @@
|
|||
return Popcorn.xhr.getJSONP( url, success, true );
|
||||
};
|
||||
|
||||
Popcorn.util = {
|
||||
// Simple function to parse a timestamp into seconds
|
||||
// Acceptable formats are:
|
||||
// HH:MM:SS.MMM
|
||||
// HH:MM:SS;FF
|
||||
// Hours and minutes are optional. They default to 0
|
||||
toSeconds: function( timeStr, framerate ) {
|
||||
//Hours and minutes are optional
|
||||
//Seconds must be specified
|
||||
//Seconds can be followed by milliseconds OR by the frame information
|
||||
var validTimeFormat = /^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,
|
||||
errorMessage = "Invalid time format";
|
||||
|
||||
if ( typeof timeStr === "number" ) {
|
||||
return timeStr;
|
||||
} else if ( typeof timeStr === "string" ) {
|
||||
if ( ! validTimeFormat.test( timeStr ) ) {
|
||||
Popcorn.error( errorMessage );
|
||||
}
|
||||
} else {
|
||||
Popcorn.error( errorMessage );
|
||||
}
|
||||
|
||||
var t = timeStr.split( ":" ),
|
||||
lastIndex = t.length - 1,
|
||||
lastElement = t[ lastIndex ];
|
||||
|
||||
//Fix last element:
|
||||
if ( lastElement.indexOf( ";" ) > -1 ) {
|
||||
var frameInfo = lastElement.split( ";" ),
|
||||
frameTime = 0;
|
||||
|
||||
if ( framerate && ( typeof framerate === "number" ) ) {
|
||||
frameTime = parseFloat( frameInfo[ 1 ], 10 ) / framerate;
|
||||
}
|
||||
|
||||
t[ lastIndex ] =
|
||||
parseInt( frameInfo[ 0 ], 10 ) + frameTime;
|
||||
}
|
||||
|
||||
if ( t.length === 1 ) {
|
||||
return parseFloat( t[ 0 ], 10 );
|
||||
} else if ( t.length === 2 ) {
|
||||
return ( parseInt( t[ 0 ], 10 ) * 60 ) + parseFloat( t[ 1 ], 10 );
|
||||
} else if ( t.length === 3 ) {
|
||||
return ( parseInt( t[ 0 ], 10 ) * 3600 ) +
|
||||
( parseInt( t[ 1 ], 10 ) * 60 ) +
|
||||
parseFloat( t[ 2 ], 10 );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Exposes Popcorn to global context
|
||||
global.Popcorn = Popcorn;
|
||||
|
||||
document.addEventListener( "DOMContentLoaded", function () {
|
||||
document.addEventListener( "DOMContentLoaded", function() {
|
||||
|
||||
var videos = document.getElementsByTagName( "video" );
|
||||
// Supports non-specific elements
|
||||
var dataAttr = "data-timeline-sources",
|
||||
medias = document.querySelectorAll( "[" + dataAttr + "]" );
|
||||
|
||||
Popcorn.forEach( videos, function ( iter, key ) {
|
||||
Popcorn.forEach( medias, function( idx, key ) {
|
||||
|
||||
var video = videos[ key ],
|
||||
var media = medias[ key ],
|
||||
hasDataSources = false,
|
||||
dataSources, data, popcornVideo;
|
||||
dataSources, data, popcornMedia;
|
||||
|
||||
// Ensure that the DOM has an id
|
||||
if ( !video.id ) {
|
||||
if ( !media.id ) {
|
||||
|
||||
video.id = Popcorn.guid( "__popcorn" );
|
||||
media.id = Popcorn.guid( "__popcorn" );
|
||||
|
||||
}
|
||||
|
||||
// Ensure we're looking at a dom node
|
||||
if ( video.nodeType && video.nodeType === 1 ) {
|
||||
if ( media.nodeType && media.nodeType === 1 ) {
|
||||
|
||||
popcornVideo = Popcorn( "#" + video.id );
|
||||
popcornMedia = Popcorn( "#" + media.id );
|
||||
|
||||
dataSources = ( video.getAttribute( "data-timeline-sources" ) || "" ).split(",");
|
||||
dataSources = ( media.getAttribute( dataAttr ) || "" ).split(",");
|
||||
|
||||
if ( dataSources[ 0 ] ) {
|
||||
|
||||
Popcorn.forEach( dataSources, function ( source ) {
|
||||
Popcorn.forEach( dataSources, function( source ) {
|
||||
|
||||
// split the parser and data as parser:file
|
||||
data = source.split( ":" );
|
||||
|
@ -1137,20 +1320,20 @@
|
|||
|
||||
}
|
||||
|
||||
// If the video has data sources and the correct parser is registered, continue to load
|
||||
if ( dataSources[ 0 ] && popcornVideo[ data[ 0 ] ] ) {
|
||||
// If the media has data sources and the correct parser is registered, continue to load
|
||||
if ( dataSources[ 0 ] && popcornMedia[ data[ 0 ] ] ) {
|
||||
|
||||
// Set up the video and load in the datasources
|
||||
popcornVideo[ data[ 0 ] ]( data[ 1 ] );
|
||||
// Set up the media and load in the datasources
|
||||
popcornMedia[ data[ 0 ] ]( data[ 1 ] );
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Only play the video if it was specified to do so
|
||||
if ( !!popcornVideo.autoplay ) {
|
||||
popcornVideo.play();
|
||||
// Only play the media if it was specified to do so
|
||||
if ( !!popcornMedia.autoplay ) {
|
||||
popcornMedia.play();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
$(document).ready(function(){
|
||||
var video = document.getElementById('video');
|
||||
var popcorn = new Popcorn('#video');
|
||||
|
||||
var pluginResults;
|
||||
var pluginOptions;
|
||||
var manifest = {
|
||||
about: {name: 'test', version: '0.1', author: 'Bobby Richter', website: 'http://robothaus.org'},
|
||||
options: {
|
||||
start : {elem:'input', type:'text', label:'In'},
|
||||
end : {elem:'input', type:'text', label:'Out'},
|
||||
target : 'test-target',
|
||||
}
|
||||
};
|
||||
var plugin = (Popcorn.plugin('test',{
|
||||
manifest: manifest,
|
||||
_setup:function(options){pluginOptions = options; pluginResults='_setup';},
|
||||
start:function(options){pluginResults='start'},
|
||||
end:function(options){pluginResults='end'}
|
||||
}));
|
||||
var pluginInstance = popcorn['test']({start: 1, end: 2});
|
||||
|
||||
module("Popcorn");
|
||||
var tests = [
|
||||
{
|
||||
title: 'Popcorn.registry',
|
||||
test: function() {
|
||||
ok(Popcorn.registry, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.getTrackEvents',
|
||||
test: function() {
|
||||
ok(Popcorn.getTrackEvents, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.getTrackEvents(popcorn) returns correct results',
|
||||
test: function() {
|
||||
expect(2);
|
||||
var results = Popcorn.getTrackEvents(popcorn);
|
||||
equals(results[0].start, 1, 'start is 1');
|
||||
equals(results[0].end, 2, 'end is 2');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.getTrackEvents exists',
|
||||
test: function() {
|
||||
ok(Popcorn.getTrackEvents, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Valid plugins are addressable as p[pluginName]',
|
||||
test: function() {
|
||||
ok(popcorn['test'], 'popcorn[\'test\'] exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Invalid plugin names yield undefined using p[invalidName]',
|
||||
test: function() {
|
||||
ok(popcorn['notValid'] === undefined, 'is undefined');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'p[validPluginName] is expected plugin',
|
||||
test: function() {
|
||||
equals(popcorn['test'],plugin['test'], 'popcorn[\'test\'] == plugin[\'test\']');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.registry must be a list',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(Popcorn.registry, 'registry exists');
|
||||
equals(typeof(Popcorn.registry), 'object', 'Popcorn.registry is an object');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.registry must contain plugins',
|
||||
test: function() {
|
||||
equals(Popcorn.registry[0], plugin, 'Popcorn.registry contains test plugin');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'plugin.type must exist',
|
||||
test: function() {
|
||||
ok(plugin.type, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plugin instance options._natives must exist',
|
||||
test: function() {
|
||||
ok(pluginOptions._natives, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plugin instance options.target should exist',
|
||||
test: function() {
|
||||
ok(pluginOptions.target, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.manifest be a list',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(Popcorn.manifest, 'Popcorn.manifest exists');
|
||||
equals(typeof(Popcorn.manifest), 'object', 'Popcorn.manifest is an object');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.manifest must contain plugin manifests',
|
||||
test: function() {
|
||||
equals(Popcorn.manifest['test'], manifest);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plugin manifest must contain options property',
|
||||
test: function() {
|
||||
ok(Popcorn.manifest['test'].options, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video exists',
|
||||
test: function() {
|
||||
ok(popcorn.video, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.currentTime exists',
|
||||
test: function() {
|
||||
ok(popcorn.video.currentTime !== undefined, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.play exists',
|
||||
test: function() {
|
||||
ok(popcorn.video.play, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.pause exists',
|
||||
test: function() {
|
||||
ok(popcorn.video.pause, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.volume exists',
|
||||
test: function() {
|
||||
ok(popcorn.video.volume, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.duration exists',
|
||||
test: function() {
|
||||
ok(popcorn.video.duration !== undefined, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.readyState exists',
|
||||
test: function() {
|
||||
ok(popcorn.video.readyState !== undefined, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data exists',
|
||||
test: function() {
|
||||
ok(popcorn.data, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data.trackEvents exists',
|
||||
test: function() {
|
||||
ok(popcorn.data.trackEvents, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data.trackEvents.byStart exists',
|
||||
test: function() {
|
||||
ok(popcorn.data.trackEvents.byStart, 'exists');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data.history must be a list',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(popcorn.data.history, 'history exists');
|
||||
equals(typeof(popcorn.data.history), 'object', 'history in an object');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.getLastTrackEventId exists and works',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(popcorn.getLastTrackEventId, 'exists');
|
||||
ok(popcorn.getLastTrackEventId(), 'works');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.getTrackEvents exists and works',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(popcorn.getTrackEvents, 'exists');
|
||||
ok(popcorn.getTrackEvents(), 'works');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.getTrackEvents === Popcorn.getTrackEvents(popcorn)',
|
||||
test: function() {
|
||||
expect(2);
|
||||
var tracks1 = popcorn.getTrackEvents();
|
||||
var tracks2 = Popcorn.getTrackEvents(popcorn);
|
||||
equals(tracks1.length, tracks2.length, 'lengths are equal');
|
||||
equals(tracks1[0], tracks2[0], 'objects are equal');
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.listen exists && works',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(popcorn.listen, 'exists');
|
||||
popcorn.listen('ended', function(){});
|
||||
for (var i in popcorn.data.events['ended']) {
|
||||
ok(popcorn.data.events['ended'][i], 'works');
|
||||
break;
|
||||
} //for
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.removeTrackEvent exists and works',
|
||||
test: function() {
|
||||
expect(2);
|
||||
ok(popcorn.removeTrackEvent, 'exists');
|
||||
popcorn.removeTrackEvent(popcorn.getLastTrackEventId());
|
||||
equals(popcorn.getTrackEvents().length, 0, 'works');
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
for (var i=0; i<tests.length; ++i) {
|
||||
test(tests[i].title, tests[i].test);
|
||||
} //for
|
||||
});
|
|
@ -2,386 +2,97 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Popcorn Butter Test</title>
|
||||
<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen">
|
||||
<style>
|
||||
body {
|
||||
background-color: #a8a8a8;
|
||||
font: 12pt Arial,sans-serif;
|
||||
margin: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: 180%;
|
||||
text-align: center;
|
||||
h3 {
|
||||
margin: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
width: 600px;
|
||||
margin: auto;
|
||||
h2 {
|
||||
display: inline;
|
||||
margin: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
.pass {
|
||||
color: #33FF00;
|
||||
}
|
||||
|
||||
#test-content {
|
||||
border: 3px solid #0a0a0a;
|
||||
border-radius: 10px;
|
||||
.expect {
|
||||
color: #2d2d2d;
|
||||
}
|
||||
.fail {
|
||||
color: #FF0000;
|
||||
}
|
||||
</style>
|
||||
<script src="jquery.js"></script>
|
||||
<script src="qunit/qunit.js"></script>
|
||||
<script src="../popcorn.js"></script>
|
||||
<script src="butter.unit.js"></script>
|
||||
|
||||
.test-item {
|
||||
padding: 3px;
|
||||
}
|
||||
<script>
|
||||
(function( Popcorn, $ ) {
|
||||
|
||||
.test-status {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.test-info {
|
||||
font-size: 70%;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.test-title:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#video-container {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="../popcorn.js"></script>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function() {
|
||||
var video = document.getElementById('video');
|
||||
var popcorn = new Popcorn('#video');
|
||||
|
||||
var pluginResults;
|
||||
var pluginOptions;
|
||||
var manifest = {
|
||||
about: {name: 'test', version: '0.1', author: 'Bobby Richter', website: 'http://robothaus.org'},
|
||||
options: {
|
||||
start : {elem:'input', type:'text', label:'In'},
|
||||
end : {elem:'input', type:'text', label:'Out'},
|
||||
target : 'test-target',
|
||||
}
|
||||
var results = {
|
||||
pass: 0,
|
||||
fail: 0,
|
||||
expect: 40
|
||||
};
|
||||
var plugin = (Popcorn.plugin('test',{
|
||||
manifest: manifest,
|
||||
_setup:function(options){pluginOptions = options; pluginResults='_setup';},
|
||||
start:function(options){pluginResults='start'},
|
||||
end:function(options){pluginResults='end'}
|
||||
}));
|
||||
var pluginInstance = popcorn['test']({start: 1, end: 2});
|
||||
|
||||
var tests = [
|
||||
{
|
||||
title: 'Popcorn.registry',
|
||||
test: function() {
|
||||
return Popcorn.registry !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.getTrackEvents',
|
||||
test: function() {
|
||||
return Popcorn.getTrackEvents !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.getTrackEvents(popcorn) returns correct results',
|
||||
test: function() {
|
||||
var results = Popcorn.getTrackEvents(popcorn);
|
||||
for (var i in results) {
|
||||
if (results[i].start === 1 && results[i].end === 2) {
|
||||
return true;
|
||||
} //if
|
||||
} //for
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.getTrackEvents exists',
|
||||
test: function() {
|
||||
return Popcorn.getTrackEvents !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Valid plugins are addressable as p[pluginName]',
|
||||
test: function() {
|
||||
return popcorn['test'] !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Invalid plugin names yield undefined using p[invalidName]',
|
||||
test: function() {
|
||||
return popcorn['notValid'] === undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'p[validPluginName] is expected plugin',
|
||||
test: function() {
|
||||
return popcorn['test'] === plugin['test'];
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.registry must be a list',
|
||||
test: function() {
|
||||
return Popcorn.registry !== undefined && typeof(Popcorn.registry) === 'object';
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.registry must contain plugins',
|
||||
test: function() {
|
||||
for (var i in Popcorn.registry) {
|
||||
if (Popcorn.registry[i] === plugin) {
|
||||
return true;
|
||||
} //if
|
||||
} //for
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'plugin.type must exist',
|
||||
test: function() {
|
||||
return plugin.type !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plugin instance options._natives must exist',
|
||||
test: function() {
|
||||
return pluginOptions._natives !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plugin instance options.target should exist',
|
||||
test: function() {
|
||||
return pluginOptions.target !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.manifest be a list',
|
||||
test: function() {
|
||||
return Popcorn.manifest !== undefined && typeof(Popcorn.manifest) === 'object';
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Valid manifests are addressable as p[pluginName]',
|
||||
test: function() {
|
||||
return popcorn['test'] !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Invalid manifests names yield undefined using p[invalidName]',
|
||||
test: function() {
|
||||
return popcorn['notValid'] === undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Popcorn.manifest must contain plugin manifests',
|
||||
test: function() {
|
||||
for (var i in Popcorn.manifest) {
|
||||
if (Popcorn.manifest[i] === manifest) {
|
||||
return true;
|
||||
} //if
|
||||
} //for
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Plugin manifest must contain options property',
|
||||
test: function() {
|
||||
return Popcorn.manifest['test'].options !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video exists',
|
||||
test: function() {
|
||||
return popcorn.video !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.currentTime exists',
|
||||
test: function() {
|
||||
return popcorn.video.currentTime !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.play exists',
|
||||
test: function() {
|
||||
return popcorn.video.play !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.pause exists',
|
||||
test: function() {
|
||||
return popcorn.video.pause !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.volume exists',
|
||||
test: function() {
|
||||
return popcorn.video.volume !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.duration exists',
|
||||
test: function() {
|
||||
return popcorn.video.duration !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.video.readyState exists',
|
||||
test: function() {
|
||||
return popcorn.video.readyState !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data exists',
|
||||
test: function() {
|
||||
return popcorn.data !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data.trackEvents exists',
|
||||
test: function() {
|
||||
return popcorn.data.trackEvents !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data.trackEvents.byStart exists',
|
||||
test: function() {
|
||||
return popcorn.data.trackEvents.byStart !== undefined;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.data.history must be a list',
|
||||
test: function() {
|
||||
return popcorn.data.history !== undefined && typeof(popcorn.data.history) === 'object';
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.getLastTrackEventId exists and works',
|
||||
test: function() {
|
||||
var exists = popcorn.getLastTrackEventId !== undefined;
|
||||
var works = popcorn.getLastTrackEventId() !== undefined;
|
||||
return exists && works;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.getTrackEvents exists and works',
|
||||
test: function() {
|
||||
var exists = popcorn.getTrackEvents !== undefined;
|
||||
var works = popcorn.getTrackEvents();
|
||||
return exists && works;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.getTrackEvents === Popcorn.getTrackEvents(popcorn)',
|
||||
test: function() {
|
||||
var exists = popcorn.getTrackEvents !== undefined;
|
||||
var tracks1 = popcorn.getTrackEvents();
|
||||
var tracks2 = Popcorn.getTrackEvents(popcorn);
|
||||
var works = tracks1.length === tracks2.length && tracks1[0] === tracks2[0];
|
||||
return exists && works;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.listen exists && works',
|
||||
test: function() {
|
||||
var exists = popcorn.listen !== undefined;
|
||||
popcorn.listen('ended', function(){});
|
||||
for (var i in popcorn.data.events['ended']) {
|
||||
return exists && true;
|
||||
} //for
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'popcorn.removeTrackEvent exists and works',
|
||||
test: function() {
|
||||
var exists = popcorn.removeTrackEvent !== undefined;
|
||||
popcorn.removeTrackEvent(popcorn.getLastTrackEventId());
|
||||
var works = popcorn.getTrackEvents().length === 0;
|
||||
return exists && works;
|
||||
}
|
||||
},
|
||||
];
|
||||
$(function() {
|
||||
|
||||
var content = document.getElementById('test-content');
|
||||
for (var i=0; i<tests.length; ++i) {
|
||||
var testItem = tests[i];
|
||||
var testElement = testItem.element = document.createElement('div');
|
||||
var testTitle = document.createElement('span');
|
||||
var testStatus = testItem.statusElement = document.createElement('span');
|
||||
var testInfo = testItem.infoElement = document.createElement('div');
|
||||
testElement.className = 'test-item';
|
||||
testElement.style.position = 'relative';
|
||||
testTitle.innerHTML = testItem.title;
|
||||
testTitle.className = 'test-title';
|
||||
testStatus.className = 'test-status';
|
||||
testStatus.style.position = 'absolute';
|
||||
testStatus.style.right = '6px';
|
||||
testStatus.innerHTML = '?';
|
||||
testInfo.innerHTML = testItem.test.toString();
|
||||
testInfo.className = 'test-info';
|
||||
testElement.appendChild(testTitle);
|
||||
testElement.appendChild(testStatus);
|
||||
testElement.appendChild(document.createElement('br'));
|
||||
testElement.appendChild(testInfo);
|
||||
content.appendChild(testElement);
|
||||
function isComplete( callback ) {
|
||||
|
||||
(function(){
|
||||
var ti = testInfo;
|
||||
var tt = testTitle;
|
||||
$(ti).hide();
|
||||
$(tt).click(function() {
|
||||
$(ti).toggle('fast');
|
||||
});
|
||||
})();
|
||||
} //for
|
||||
if ( !QUnit.config.queue.length ) {
|
||||
// is complete
|
||||
|
||||
var scoreDiv = document.createElement('div');
|
||||
scoreDiv.className = 'test-item';
|
||||
scoreDiv.innerHTML = 'Score: N/A';
|
||||
scoreDiv.style.fontWeight = 'bold';
|
||||
content.appendChild(document.createElement('br'));
|
||||
content.appendChild(scoreDiv);
|
||||
callback && callback( QUnit.config.stats );
|
||||
|
||||
var testIndex = 0;
|
||||
var score = 0;
|
||||
var waitTime = 50;
|
||||
function runNextTest() {
|
||||
var test = tests[testIndex];
|
||||
try {
|
||||
var result = test.test();
|
||||
test.statusElement.innerHTML = result ? '✓' : '✗';
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
isComplete( callback );
|
||||
}, 10 );
|
||||
}
|
||||
catch (e) {
|
||||
test.statusElement.innerHTML = '!';
|
||||
test.infoElement.innerHTML += '<br /><b>Error:</b> ' + e.message;
|
||||
} //try
|
||||
++testIndex;
|
||||
if (testIndex < tests.length) {
|
||||
setTimeout(runNextTest, waitTime);
|
||||
} //if
|
||||
score += (result ? 1 : 0);
|
||||
}
|
||||
|
||||
scoreDiv.innerHTML = 'Score: ' + score + '/' + tests.length;
|
||||
} //runNextTest
|
||||
isComplete(function( qResults ) {
|
||||
|
||||
setTimeout(runNextTest, waitTime);
|
||||
// Hack together the results as used in ready.html
|
||||
results.pass = qResults.all - qResults.bad;
|
||||
results.fail = qResults.bad;
|
||||
results.expect = qResults.all;
|
||||
|
||||
$.each( results, function( name, value ) {
|
||||
$("#qunit-header").before(
|
||||
$("<h2>", {
|
||||
className: name,
|
||||
html: name + ": " + value
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
})( Popcorn, jQuery );
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main-container">
|
||||
<div id="title">
|
||||
Butter Dependency Test
|
||||
</div>
|
||||
<div id="test-content">
|
||||
</div>
|
||||
<h3>Butter Dependencies<h3>
|
||||
|
||||
<h1 id="qunit-header">Butter Popcorn Dependencies</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-container">
|
||||
<div id="video-container" style="display:none">
|
||||
<video id="video" />
|
||||
</div>
|
||||
<div id="test-target">
|
||||
<div id="test-target" style="display:none">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"data": [
|
||||
{
|
||||
"testAudioParser": {
|
||||
"start": 5,
|
||||
"end": 6
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
<script src="qunit/qunit.js"></script>
|
||||
|
||||
<!--
|
||||
do not move - this must be called immediately prior to
|
||||
popcorn-api-draft.js
|
||||
|
@ -17,7 +18,13 @@
|
|||
<script src="popcorn.unit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Popcorn API</h1>
|
||||
<h1 id="qunit-header">
|
||||
Popcorn.js API
|
||||
<iframe id="butter-tests" data-src="butter_test.html" style="width:325px;height:60px;float:right;border:0px;margin:-10px 20px 0 -10px;background:#fff" ></iframe>
|
||||
|
||||
<iframe id="ready-tests" data-src="ready.html" style="width:325px;height:60px;float:right;border:0px;margin:-10px 20px 0 -10px;background:#fff" ></iframe>
|
||||
|
||||
</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
|
@ -30,7 +37,8 @@
|
|||
|
||||
</div>
|
||||
|
||||
<video id='video'style="display:"
|
||||
<video id='video'
|
||||
style="display:;width:300px"
|
||||
controls
|
||||
poster="poster.png">
|
||||
|
||||
|
@ -44,6 +52,64 @@
|
|||
|
||||
<p>Your user agent does not support the HTML5 Video element.</p>
|
||||
|
||||
</video>
|
||||
</video>
|
||||
|
||||
<audio id='audio' src="italia.ogg" data-timeline-sources="data/parserData.json" controls>
|
||||
</audio>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Position Tests Adapted From jQuery offsets/dimensions Tests -->
|
||||
<style type="text/css" media="screen">
|
||||
#position-tests { display:none;margin:0; position: fixed;top:0px;left:0px; }
|
||||
|
||||
div.absolute { position: absolute; margin: 0px; width: 100px; height: 100px; background: #fff; }
|
||||
#absolute-1 { top: 0; left: 0; }
|
||||
#absolute-1-1 { top: 1px; left: 1px; }
|
||||
#absolute-1-1-1 { top: 1px; left: 1px; }
|
||||
#absolute-2 { top: 19px; left: 19px; }
|
||||
|
||||
div.relative { position: relative; top: 0; left: 0; width: 100px; height: 100px; background: #fff; overflow: hidden; }
|
||||
#relative-2 { top: 20px; left: 20px; }
|
||||
|
||||
div.fixed { position: fixed; width: 100px; height: 100px; background: #fff; overflow: hidden; }
|
||||
#fixed-1 { top: 0; left: 0; }
|
||||
#fixed-2 { top: 20px; left: 20px; }
|
||||
|
||||
div.static { position: static; top: 0; left: 0; width: 100px; height: 100px; background: #fff; overflow: hidden; }
|
||||
#static-2 { top: 20px; left: 20px; }
|
||||
|
||||
</style>
|
||||
|
||||
<div id="position-tests">
|
||||
<div id="absolute-1" class="absolute"><video id="vid-absolute-1" src="trailer.ogv" style="visibility:hidden"></video>
|
||||
<div id="absolute-1-1" class="absolute"><video id="vid-absolute-1-1"" src="trailer.ogv" style="visibility:hidden"></video>
|
||||
<div id="absolute-1-1-1" class="absolute"><video id="vid-absolute-1-1-1" src="trailer.ogv" style="visibility:hidden"></video></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="absolute-2" class="absolute"><video id="vid-absolute-2" src="trailer.ogv" style="visibility:hidden"></video></div>
|
||||
|
||||
<div id="relative-1" class="relative"><video id="vid-relative-1" src="trailer.ogv" style="visibility:hidden"></video>
|
||||
<div id="relative-1-1" class="relative"><video id="vid-relative-1-1" src="trailer.ogv" style="visibility:hidden"></video>
|
||||
<div id="relative-1-1-1" class="relative"><video id="vid-relative-1-1-1" src="trailer.ogv" style="visibility:hidden"></video></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="relative-2" class="relative"><video id="vid-relative-2" src="trailer.ogv" style="visibility:hidden"></video></div>
|
||||
|
||||
|
||||
<div id="fixed-1" class="fixed"><video id="vid-fixed-1" src="trailer.ogv" style="visibility:hidden"></video></div>
|
||||
<div id="fixed-2" class="fixed"><video id="vid-fixed-2" src="trailer.ogv" style="visibility:hidden"></video></div>
|
||||
|
||||
<div id="static-1" class="static"><video id="vid-static-1" src="trailer.ogv" style="visibility:hidden">
|
||||
<div id="static-1-1" class="static"><video id="vid-static-1-1" src="trailer.ogv" style="visibility:hidden">
|
||||
<div id="static-1-1-1" class="static"><video id="vid-static-1-1-1" src="trailer.ogv" style="visibility:hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="static-2" class="static"><video id="vid-static-2" src="trailer.ogv" style="visibility:hidden"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
102
test/ready.html
102
test/ready.html
|
@ -1,45 +1,103 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Popcorn API</title>
|
||||
<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen">
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
h3 {
|
||||
margin: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
h2 {
|
||||
display: inline;
|
||||
margin: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
.pass {
|
||||
color: #33FF00;
|
||||
}
|
||||
.expect {
|
||||
color: #2d2d2d;
|
||||
}
|
||||
.fail {
|
||||
color: #FF0000;
|
||||
}
|
||||
</style>
|
||||
<script src="jquery.js"></script>
|
||||
<script src="../popcorn.js"></script>
|
||||
<script>
|
||||
|
||||
Popcorn(function (e) {
|
||||
(function( Popcorn, $ ) {
|
||||
|
||||
console.log("Popcorn(function() { /../ }) 1");
|
||||
|
||||
var p = Popcorn("#video");
|
||||
|
||||
|
||||
p.exec( 4, function () {
|
||||
var readyCalled = 0,
|
||||
readyOrder = [],
|
||||
readyComposed = "Ready Callback 1,Ready Callback 2",
|
||||
results = {
|
||||
pass: 0,
|
||||
fail: 0,
|
||||
expect: 2
|
||||
};
|
||||
|
||||
|
||||
$(function() {
|
||||
readyCalled++;
|
||||
});
|
||||
|
||||
}).play();
|
||||
|
||||
});
|
||||
Popcorn(function (e) {
|
||||
|
||||
readyCalled++;
|
||||
readyOrder.push("Ready Callback 1");
|
||||
|
||||
Popcorn("#video").exec( 1, function () {
|
||||
|
||||
results[
|
||||
( readyCalled === 3 ? "pass" : "fail" )
|
||||
]++;
|
||||
|
||||
if ( readyOrder.join(",") === readyComposed ) {
|
||||
results.pass++;
|
||||
}
|
||||
|
||||
$.each( results, function( name, value ) {
|
||||
$("video").before(
|
||||
$("<h2>", {
|
||||
className: name,
|
||||
html: name + ": " + value
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
}).play().volume(0);
|
||||
|
||||
});
|
||||
|
||||
Popcorn(function () {
|
||||
|
||||
readyCalled++;
|
||||
readyOrder.push("Ready Callback 2");
|
||||
|
||||
});
|
||||
})( Popcorn, jQuery );
|
||||
|
||||
Popcorn(function () {
|
||||
|
||||
console.log("Popcorn(function() { /../ }) 2");
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<video id='video'style="display:"
|
||||
<h3>Popcorn(/* DOM Ready */)<h3>
|
||||
|
||||
<video id='video'style="display:none"
|
||||
controls
|
||||
poster="http://media.w3.org/2010/05/sintel/poster.png">
|
||||
poster="poster.png">
|
||||
|
||||
<source id='mp4'
|
||||
src="http://media.w3.org/2010/05/sintel/trailer.mp4"
|
||||
src="trailer.mp4"
|
||||
type='video/mp4; codecs="avc1, mp4a"'>
|
||||
|
||||
<source id='ogv'
|
||||
src="http://media.w3.org/2010/05/sintel/trailer.ogv"
|
||||
src="trailer.ogv"
|
||||
type='video/ogg; codecs="theora, vorbis"'>
|
||||
|
||||
<p>Your user agent does not support the HTML5 Video element.</p>
|
||||
|
|
Загрузка…
Ссылка в новой задаче