I\'m currently trying to use the YouTube API as part of a jQuery plugin and I\'ve run into a bit of a problem.
The way the YT api works is that you load the flash pl
I had this same problem and tried the accepted answer. This didn't work for me; the playerState() function was never called. However, it put me on the right path. What I ended up doing was this:
// Within my mediaController "class"
window["dynamicYouTubeEventHandler" + playerID] = function(state) { onYouTubePlayerStateChange(state, playerID); }
embedElement.addEventListener("onStateChange", "dynamicYouTubeEventHandler" + playerID);
// End mediaController class
// Global YouTube event handler
function onYouTubePlayerStateChange(state, playerID) {
var mediaController = GetMediaControllerFromYouTubeEmbedID(playerID);
mediaController.OnYouTubePlayerStateChange(state);
}
It's fairly nasty, but so is the current state of the YouTube JavaScript API.
Here is some other helpful/nasty code if you are using any kind of advanced prototyping patterns. This basically allows you to retrieve a "class" instance from the YouTube player ID:
// Within my mediaController "class"
// The containerJQElement is the jQuery wrapped parent element of the player ID
// Its ID is the same as the player ID minus "YouTubeEmbed".
var _self = this;
containerJQElement.data('mediaController', _self);
// End mediaController class
// Global YouTube specific functions
function GetMediaControllerFromYouTubeEmbedID(embedID) {
var containerID = embedID.replace('YouTubeEmbed', '');
var containerJQObject = $("#" + containerID);
return containerJQObject.data('mediaController');
}
function onYouTubePlayerReady(playerId) {
var mediaController = GetMediaControllerFromYouTubeEmbedID(playerId);
mediaController.OnYouTubeAPIReady();
}
Im Using Jquery SWFobject plugin, SWFobject
It is important to add &enablejsapi=1 at the end of video
HTML:
<div id="embedSWF"></div>
Jquery:
$('#embedSWF').flash({
swf: 'http://www.youtube.com/watch/v/siBoLc9vxac',
params: { allowScriptAccess: "always"},
flashvars: {enablejsapi: '1', autoplay: '0', allowScriptAccess: "always", id: 'ytPlayer' },
height: 450, width: 385 });
function onYouTubePlayerReady(playerId) {
$('#embedSWF').flash(function(){this.addEventListener("onStateChange", "onPlayerStateChange")});
}
function onPlayerStateChange(newState) {
alert(newState);
}
onYouTubePlayerReady must be outside of $(document).ready(function() to get fired
Edit:
Apparently calling addEventListener
on the player
object causes the script to be used as a string in an XML property that's passed to the flash object - this rules out closures and the like, so it's time for an old-school ugly hack:
function onYouTubePlayerReady(playerId) {
var player = $('#'+playerId)[0];
player.addEventListener('onStateChange', '(function(state) { return playerState(state, "' + playerId + '"); })' );
}
function playerState(state, playerId) {
console.log(state);
console.log(playerId);
}
Tested & working!
Here's a nice article that goes through creating a class to wrap an individual player, including dispatching events to individual objects using a similar approach to that mentioned in a previous answer.
http://blog.jcoglan.com/2008/05/22/dispatching-youtube-api-events-to-individual-javascript-objects/
How about something like so:
var closureFaker = function (func, scope) {
var functionName = 'closureFake_' + (((1+Math.random())*0x10000000)|0).toString(16);
window[functionName] = function () {
func.apply(scope || window, arguments);
};
console.log('created function:', functionName, window[functionName]);
return functionName;
};
ytplayer.addEventListener("onStateChange", closureFaker(function () {
//place your logic here
console.log('state change', arguments)
}));