1

I have the following code, necessary to track an embedded Youtube video in my page using their Javascript API:

function onYouTubePlayerReady(playerId) {
      var youtubeplayer = document.getElementById('youtubeplayer');
      youtubeplayer.addEventListener("onStateChange", "onytplayerStateChange");
      youtubeplayer.setPlaybackQuality('large');
      }

function onytplayerStateChange(newState) {
    //Make it autoplay on page load
    if (newState == -1) {
        youtubeplayer.playVideo();
        }

    var tiempo = youtubeplayer.getCurrentTime();
    //Rounds to 2 decimals
    var tiempo = Math.round(tiempo*100)/100;
    alert(tiempo);
    }

(The details related to the Youtube API aren't important, but if you are curious, they are at my previous question Youtube Javascript API: not working in IE).

Now, my problem is that the onYoutubePlayerReady() function declares "youtubeplayer", which is a reference to a DOM object, and I need to access that variable from the other function onytplayerstateChange() too... but "youtubeplayer" is being declared as a local variable. This works in IE 8, Safari..., but doesn't work in Firefox 12. Of course, I could get a reference to "youtubeplayer" in the following way instead, without the "var":

youtubeplayer = document.getElementById('youtubeplayer');

And in fact, that is how it looks in Youtube's sample code, but if I write it this way, the code doesn't work in IE 8 (while it does work in Firefox 12; see my previous question for more details).

...All of which brings me to: is there a way to declare a global variable from inside a function (like "youtubeplayer" above), so that it can be accessed by other functions too? Something that works in all browsers?

Community
  • 1
  • 1
PaulJ
  • 1,646
  • 5
  • 33
  • 52
  • 1
    why don't you just declare your variable outside the function? – Conrad Frix May 15 '12 at 20:49
  • 1
    possible duplicate of [define Global variable in javascript function](http://stackoverflow.com/questions/5786851/define-global-variable-in-javascript-function) – Diodeus - James MacFarlane May 15 '12 at 20:51
  • Why don't I declare the variable outside the function? Because Youtube's API won't let me. The way it's structured, when the video player object is loaded, it calls a callback function named "onYouTubePlayerReady()", which sets everything else up. – PaulJ May 15 '12 at 20:57
  • Thanks for the link to the other question, BTW. I've got good ideas from there, which I'll test as soon as I can. – PaulJ May 15 '12 at 21:14

2 Answers2

3

Another way to declare globals is to create it as an extra property to the global "window" object-- so do

window.youtubeplayer = document.getElementById('youtubeplayer'); 

This should be accessible to anything else on the page. So your complete code would look like this;

function onYouTubePlayerReady(playerId) {
  window.youtubeplayer = document.getElementById('youtubeplayer');
  window.youtubeplayer.addEventListener("onStateChange", "onytplayerStateChange");
  window.youtubeplayer.setPlaybackQuality('large');
}

function onytplayerStateChange(newState) {
  //Make it autoplay on page load
  if (newState == -1) {
    window.youtubeplayer.playVideo();
  }

  var tiempo = window.youtubeplayer.getCurrentTime();
  //Rounds to 2 decimals
  var tiempo = Math.round(tiempo*100)/100;
  alert(tiempo);
}
Shawson
  • 1,858
  • 2
  • 24
  • 38
2

Instead of passing a string reference to your onytplayerStateChange function to the event listener, you can create an event handler within the ready function and pass that in directly, like so:

function onYouTubePlayerReady(playerId) {
    var youtubeplayer = document.getElementById('youtubeplayer');
    var stateChangeHandler = function (newState) {
        //Make it autoplay on page load
        if (newState == -1) {
            youtubeplayer.playVideo();
        }
        var tiempo = youtubeplayer.getCurrentTime();
        //Rounds to 2 decimals
        var tiempo = Math.round(tiempo*100)/100;
        alert(tiempo);
    };
    youtubeplayer.addEventListener("onStateChange", stateChangeHandler);
    youtubeplayer.setPlaybackQuality('large');
}

Or even pass in an anonymous function directly:

function onYouTubePlayerReady(playerId) {
    var youtubeplayer = document.getElementById('youtubeplayer');
    youtubeplayer.addEventListener("onStateChange", function (newState) {
        //Make it autoplay on page load
        if (newState == -1) {
            youtubeplayer.playVideo();
        }
        var tiempo = youtubeplayer.getCurrentTime();
        //Rounds to 2 decimals
        var tiempo = Math.round(tiempo*100)/100;
        alert(tiempo);
    });
    youtubeplayer.setPlaybackQuality('large');
}

This preserves the scope of the youtubeplayer variable inside of the "onYouTubePlayerReady" function and bypasses the need to establish a global variable.

Jesse Proulx
  • 821
  • 7
  • 13
  • Mmmm... I don't know whether Youtube's API supports this. Their documentation shows the second parameter in addEventListener() as a string, not a function. Neverthless, I'll take note of this tip for some other occasion :-) – PaulJ May 15 '12 at 21:41
  • 1
    Ahh, I see that instead of emulating the normal addEventListener, this API only allows string references that are passed to a flash interface. It looks like there is a way to pass in [an anonymous function as a string to be eval'd](http://stackoverflow.com/questions/786380/using-youtubes-javascript-api-with-jquery) however. – Jesse Proulx May 15 '12 at 22:36