0

I am using the YouTube API to embed a video on a page. I call swfobject.embedSWF which embeds the video on the page, it works. When it is done loading, the API is supposed to call onYouTubePlayerReady. My question though is where do I have to place the callback in my class to get the function called?

Here is the code that I have tried, but that does not work.

class YouTube

    constructor: (@uid) ->
        youtube_video_container =   $('<div/>', {
              id: 'ytapiplayer'
        }).appendTo(main);

        params = { allowScriptAccess: "always" };
        atts = { id: "myytplayer" };

        swfobject.embedSWF("http://www.youtube.com/apiplayer?video_id=d9NF2edxy-M&version=3&enablejsapi=1", "ytapiplayer", "1280", "720", "8", null, null, params, atts);

    onYouTubePlayerReady: (playerId) ->
           alert "ready"
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Alexis
  • 23,545
  • 19
  • 104
  • 143

3 Answers3

4

From the fine manual:

In addition, any HTML page that contains the YouTube player must implement a JavaScript function named onYouTubePlayerReady. The API will call this function when the player is fully loaded and the API is ready to receive calls.

and onYouTubePlayerReady:

onYouTubePlayerReady(playerid)

Called when the player is fully loaded and the API is ready to receive calls. If a playerapiid is passed into the player via URL arguments, then it will be passed to this function.

So if you include &playerapiid=X in the URL's CGI parameters, then that X will be the playerid when onYouTubePlayerReady is called.

All of that indicates that onYouTubePlayerReady is a global function rather than a method on an object of your choice or a callback that you can specify as you please. To make a global function with CoffeeScript, create a property on window:

window.onYouTubePlayerReady = (playerid) ->
    alert 'Ready'

You'd have to use the playerid to backtrack to the specific object that created the player through some globally accessible playerid-to-object map.

Even the addEventListener interface is based on names rather than callbacks so you're stuck polluting the global namespace and routing things yourself.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • Wow. Thanks for the great help. Yup, thanks for the tip on that `addEventListener` needing a string also. I tried doing some `@onPlayerStateChanged` for another callback but it didn't work. But everything works when I do `window.onytplayerStateChange`. Overall, the YouTube JS is not designed very well. – Alexis Apr 19 '12 at 18:30
  • @AlexisK: Yeah, the API smells a bit old and musty. – mu is too short Apr 19 '12 at 18:37
  • ah, `window.onYouTubePlayerReady` was just what i needed, thanks! – pruett Jul 11 '12 at 14:31
  • @AlexisK can you kindly drop an example of how you got `ytplayer.addEventListener` to work ? I can't seem to get the `onStateChange` function to fire... – pruett Jul 11 '12 at 15:05
  • @pruett: Do you have an example (perhaps on http://jsfiddle.net/) of what you're doing? – mu is too short Jul 11 '12 at 17:58
  • @muistooshort i ended up using this wrapper https://github.com/AnuragMishra/YoutubePlayer which seems to work very nicely. thanks for you help...i was having trouble calling their methods correctly when not writing inline javascript – pruett Jul 12 '12 at 16:26
0

I think replacing the embedSWF call for the following code could work:

swfobject.embedSWF("http://www.youtube.com/apiplayer?video_id=d9NF2edxy-M&version=3&enablejsapi=1", "ytapiplayer", "1280", "720", "8", null, null, params, atts, this.onYouTubePlayerReady);

Give it shot and let me know if it works.

The modification just means that you're passing it as the last parameter the function that you want it to consider as the callback function.

txominpelu
  • 1,067
  • 1
  • 6
  • 11
  • Hmm... didn't work. The issue is that it is hard coded in the API to call the `onYouTubePlayerReady` https://developers.google.com/youtube/js_api_reference#GettingReference – Alexis Apr 19 '12 at 17:53
0

I think I found a good solution for getting a callback to work in the swfObject library that is very similar to txominpelu's suggestion. Seems like using -> callbackFn works nicely, basically creating an anonymous function and returning the callback? I'd appreciate anyone setting me straight on why that might be all wrong. (I'm usually wrong the first time around)

I'm using swfobject.embedSWF with a callbackFn that works fine in my hand coded JavaScript file where I use function callbackFn() {} to define it. Now I'm trying to move over to CoffeeScript, which is so nice. So CoffeeScript will compile callbackFn = function() {}; instead. My original swfObject.embedSWF doesn't work with the CoffeeScript compiled version of my callback.

// original javascript file approach
swfobject.embedSWF( "swf/flashContent.swf", "site-content", 
                    "100%", "100%", "10.0.0", false, 
                    flashvars, params, attributes, callbackFn );

// original javascript callback
function callbackFn() {
  log( "--> callbackFn invoked ");
  // ... do stuff
}

I'm new to CoffeeScript and I think the only time you get named functions is with a class

I started by trying an anonymous function in place of the optional callback parameter that's detailed on the swfObject wiki. Then I figured I might be able to get something like that to work with the CoffeeScript version. Here's where I ended up.

# part of .coffee file
swfobject.embedSWF "swf/flashContent.swf", "site-content", 
                   "100%", "100%", "10.0.0", false, 
                    flashvars, params, attributes, -> callbackFn()

callbackFn = (evt) ->
  console.log "--> callbackFn invoked #{evt}"
  # do other stuff


# part compiled .js file
swfobject.embedSWF("swf/flashContent.swf", "site-content",  
                   "100%", "100%", "10.0.0.", false, 
                   flashvars, params, attributes, function() {
                     return callbackFn();
                   });

callbackFn = function() { ... }

I also looked at passing the event through the callbackFn too and that looks like it works.

# .coffee file swf
@swfobject.embedSWF "swf/flashContent.swf", "site-content", 
                    "100%", "100%", "10.0.0.", false, 
                    flashvars, params, attributes, -> callbackFn(@swfobject)

callbackFn = (evt) ->
  console.log "--> callbackFn invoked #{evt}"
  # do other stuff
Community
  • 1
  • 1
kaplan
  • 4,109
  • 6
  • 30
  • 35