JW Player – sendEvent is not a function
Posted by scotti3g
Ok, I’ve spent a whole friggin day on this problem so hopefully this post will help save some people some time…
We’ve been working on a video site recently that uses the fantastic JW Player to play the .flv flash files. For some reason, there were some issues with using a tabbed interface we’d made in conjunction with the JW Player.
After changing from a tab with a text page back to the video page, the following error was coming up:
Error: $("#player1")[0].sendEvent is not a function
The code causing this error was a little routine to load a different video into the player when someone clicks on a different tab:
$('#player1')[0].sendEvent('LOAD',obj);
After a whole day of trial and error and putting alerts all over my JS code, I finally worked out what the hell was going on.
Even though my JS code was waiting until the document had been loaded (through jQuery’s $(document).ready(function() { blah..blah), the JW Player wasn’t loading in that time. It turns out even though our tabbed pages were powered by simple show/hide CSS, going from the video tab to a non-video tab and back made the JW Player have to load again.
The sendEvent is not a function error was simply because the JW Player hadn’t loaded yet, so the player1 object didn’t exist yet!
The solution? A simple delay:
setTimeout(function() { $('#player1')[0].sendEvent('LOAD',obj); }, 200);
Now this is not a pretty solution at all. Maybe 200 ms is enough time for the player to load on my computer, but what about on another set up? Newer versions of the JW Player automatically call a particular function when it finishes loading (playerReady()), but I wasn’t able to find a quick and easy way to check the player was loaded.
If anyone knows how to get playerReady() working nicely with jQuery’s $(document).ready() I’d love to hear about it. From the comments on the JW Player site, it seems the playerReady() function is a little flakey in any case. But is a setTimeout any better? Hmm…
You should be able to do something like this:
$(document).ready(function(){
var player = $('#player1')[0];
while (typeof player.sendEvent != 'function'){
// wait for sendEvent to be available
}
});
@shadowhand – thanks for such a speedy reply!! :)
Unfortunately I tried your code and it produced the same result as when I tried to make the playerReady() function set a “ready” variable. Firefox freezes then comes up with:
A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete.
But thanks for the suggestion :)
I worked on the A Real Guitar website and had the same problem. I ended up spoofing the videos by hiding them 2000px above the browser. Using the display:none/block causes the refresh, but if you change their position, it doesn’t. So when a user clicks on a video, we do all the jQuery animations for loading the windows, then re-position the video into the appropriate area and trigger our sendEvent.
Hope this helps.. check out the code at arealguitar.com (in the general.js file).
@Some Guy – A Real Guitar is a very nice site you’ve developed there!! :)
It’s a shame we have to resort to tricks like using CSS to move elements off the page instead of being able to hide them. I’m sure there must be a way to hook into the playerReady() function and have everything “behave”. If I work on another video site soon that uses JW Player I’ll see if I can work it out and post the code :)
No idea if this is still of interest but here is how I solved the problem (which is that when the playerReady() is fired it doesn’t mean that the JS API is ready to receive) with prototype.js and swfobject.js:
function playerReady(player) {
if ($(player).addModelListener) {
$(player).addModelListener('STATE', 'playerStateChange');
}
else {
setTimeout('playerReady("player")', 100);
}
}
document.observe("dom:loaded", function() {
var flashvars = { file: "/xyz.flv", image: "/xyz.jpg", autostart: "true" };
var params = { allowfullscreen: "true", allowscriptaccess: "always" };
var attributes = { id: "player", name: "player" };
swfobject.embedSWF("/swf/player.swf", "player_container", "480", "380", "9.0.115", "/swf/expressInstall.swf", flashvars, params, attributes);
});
This runs on all browsers tested, partially except Konqueror where playerReady() never gets called for a yet unknown to me reason but player displays anyway. (opera, arora, firefox, internet explorer, konqueror, safari)
Just checking out your site. You say interesting things and have some good ideas.