Skip to content

Commit

Permalink
Fix a few issues with how we listen for ready
Browse files Browse the repository at this point in the history
  • Loading branch information
screeley committed Dec 30, 2013
1 parent ddbd4f3 commit de864df
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 36 deletions.
110 changes: 109 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Install
Player.js is hosted on Embedly's CDN.
::

<script type="text/javascript" src="//cdn.embed.ly/player-0.0.4.min.js"></script>
<script type="text/javascript" src="//cdn.embed.ly/player-0.0.5.min.js"></script>


Ready
Expand All @@ -47,6 +47,48 @@ ready is called.
});


Timing
------
The timing between when the iframe is added and when the ready event is fired
is important. Sadly we cannot fire the ready event till the iframe is loaded,
but there is no concrete way of telling when postmessage is available to us.

The best way is to do one of the following.

Create the iframe via JavaScript
""""""""""""""""""""""""""""""""
::

var iframe = document.createElement('iframe');
iframe.src = 'https://example.com/iframe';
document.body.appendChild(iframe);

var player = new playerjs.Player(iframe);

In this case, Player.js will listen to the onload event of the iframe and only
try to communicate when ready.

Wait for the document to be ready.
""""""""""""""""""""""""""""""""""
::

<iframe src="//example.com/iframe"></iframe>

<script>
$(document).on('ready', function(){
$('iframes').each(function(){
var player = new playerjs.Player(this);
player.on('ready', funciton(){
player.play();
});
});
});
</script>

At this point we can reasonably assume that the iframe's been loaded and the
ready. Player.js will take care of listening for ready events that were fired
before the player is set up.


Methods
-------
Expand Down Expand Up @@ -170,3 +212,69 @@ Events that can be listened to.

``error``
fires when an error occurs.


Receiver
--------
If you are looking to implement the Player.js spec, we include a Receiver that
will allow you to easily listen to events and takes care of the house keeping.

::

var receiver = new playerjs.Receiver();

receiver.on('play', function(){
video.play();
receiver.emit('play');
});

receiver.on('pause', function(){
video.pause();
receiver.emit('pause');
});

receiver.on('getDuration', function(callback){
callback(video.duration);
});

video.addEventListener('timeupdate', function(){
receiver.emit('timeupdate', {
seconds: video.currentTime,
duration: video.duration
});
});

receiver.ready();


Methods
-------

``on``
Requests an event from the video. The above player methods should be
implemented. If the event expects a return value a callback will be passed
into the function call::

receiver.on('getDuration', function(callback){
callback(video.duration);
});

Otherwise you can safely ignore any inputs::

receiver.on('play', function(callback){
video.play();
});

``emit``
Sends events to the parent as long as someone is listing. The above player
events should be implemented. If a value is expected, it should be passed in
as the second argument::

receiver.emit('timeupdate', {seconds:20, duration:40});

``ready``
Once everything is in place and you are ready to start responding to events,
call this method. It performs some house keeping, along with emitting
``ready``::

receiver.ready();
65 changes: 38 additions & 27 deletions SPEC.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ postMessage.

This is based heavily off the HTML5 Video `Spec
<http://dev.w3.org/html5/spec-author-view/video.html>`_, Vimeo's `JavaScript
API<https://developer.vimeo.com/player/js-api>`_, Soundclouds `Widget API
API <https://developer.vimeo.com/player/js-api>`_, Soundclouds `Widget API
<http://developers.soundcloud.com/docs/api/html5-widget>`_ and YouTube's
`Player API https://developers.google.com/youtube/iframe_api_reference>`_.
`Player API <https://developers.google.com/youtube/iframe_api_reference>`_.


Why
Expand All @@ -23,6 +23,15 @@ make this available via a common set of json that is passed back between the
parent and the child.


License
-------
This specification is licensed under the Creative Commons Attribution License.
You can learn more about the license `here
<http://creativecommons.org/licenses/by-nd/4.0/>`_. The more people that refine
this Spec, the better, so we tried to pick the least restrictive license we
could.


Support
-------
Currently the following browsers support postMessage and hence can use this:
Expand Down Expand Up @@ -67,6 +76,7 @@ They have a common format::

If the method is a getter, i.e. ``getDuration`` the child frame will send the
following message to the parent.
::

{
event: 'methodName',
Expand All @@ -81,7 +91,7 @@ The child frame will often fire a number of events, such as ``play``,
``finish`` and ``playProgress``. This defines what is passed back.

No events should be passed back unless the parent explicitly asks for them. To
add a listener we send the following message.
add a listener we send the following message::

{
method: 'addEventListener',
Expand All @@ -101,37 +111,38 @@ When the event is fired, the parent will receive the following event data::
Client
------
It's helpful to have a quick example of the JavaScript before moving forward.
::

// Play the video
document.getElementById('#iframe').contentWindow.postMessage(
JSON.stringify({
method: 'play'
})
);
// Play the video
document.getElementById('#iframe').contentWindow.postMessage(
JSON.stringify({
method: 'play'
})
);

// Set up an event listener.
// Set up an event listener.

var iframe = document.getElementById('#iframe'),
origin = iframe.src.split('/', 3).join('/');
var iframe = document.getElementById('#iframe'),
origin = iframe.src.split('/', 3).join('/');

var play = function(){
console.log('play);
};
var play = function(){
console.log('play);
};

window.addEventListener('message', function(){
if (e.origin === origin){
if (e.event === play){
played();
window.addEventListener('message', function(){
if (e.origin === origin){
if (e.event === play){
played();
}
}
}
});
});

iframe.contentWindow.postMessage(
JSON.stringify({
method: 'addEventListener',
value: 'event'
})
);
iframe.contentWindow.postMessage(
JSON.stringify({
method: 'addEventListener',
value: 'event'
})
);


Methods
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "Player.js",
"name": "Player.js",
"version": "0.0.4",
"version": "0.0.5",
"homepage": "http://github.com/embedly/player.js",
"author": {
"name": "Embedly"
Expand Down
32 changes: 27 additions & 5 deletions src/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ playerjs.METHODS = [
'addEventListener'
];

playerjs.READIED = [];

playerjs.Player.prototype.init = function(elem, options){

Expand Down Expand Up @@ -66,11 +67,16 @@ playerjs.Player.prototype.init = function(elem, options){
} else {
playerjs.log('Post Message is not Available.');
}
// Try the onload event, just lets us give another test.
this.elem.onload = function(){

// See if we caught the src event first, otherwise assume we haven't loaded
if (playerjs.READIED.indexOf(elem.src) > -1){
self.loaded = true;
};
} else {
// Try the onload event, just lets us give another test.
this.elem.onload = function(){
self.loaded = true;
};
}
};

playerjs.Player.prototype.send = function(data, callback, ctx){
Expand All @@ -93,7 +99,7 @@ playerjs.Player.prototype.send = function(data, callback, ctx){
}

playerjs.log('Player.send', data, this.origin);

if (this.loaded === true){
this.elem.contentWindow.postMessage(JSON.stringify(data), this.origin);
}
Expand Down Expand Up @@ -271,3 +277,19 @@ playerjs.Player.prototype.getLoop = function(callback, ctx){
};

window.playerjs = playerjs;

// We need to catch all ready events in case the iframe is ready before the
// player is invoked.
playerjs.addEvent(window, 'message', function(e){
var data;
try {
data = JSON.parse(e.data);
} catch (err){
return false;
}

// We need to determine if we are ready.
if (data.event === 'ready' && data.value.src){
playerjs.READIED.push(data.value.src);
}
});
9 changes: 7 additions & 2 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ for (var f in FRAMES){
iframe.height = 200;

document.body.appendChild(iframe);

loadPlayers();

// we want to load the players a couple of different ways.
if ( f % 2 === 1){
loadPlayers();
} else {
iframe.onload = loadPlayers;
}
}

0 comments on commit de864df

Please sign in to comment.