15

I'm trying to load YouTube's iframe API. So far, all I'm trying to do is make and load the player. It seems to load the API, but then not recognize "YT.Player()" as a constructor. The exact error I'm getting at that line, in the chrome js console, is:

    Uncaught TypeError: undefined is not a function 

So... What in the world am I doing wrong? I've thrown console.log statements all over this thing, and tried rewriting it in a few ways. I've tried copying the api into a local file. I've tried loading it with regular script tags. I've tried loading it with the wacky DOM Modification they used in the api reference at https://developers.google.com/youtube/iframe_api_reference. I'm pretty sure the code below should work:

    function youtubeAPIReady(script, textStatus, jqXHR)
    {
        player = new YT.Player('player', {
            height: '390',
            width: '640',
            videoId: 'CxTtN0dCDaY'
        });
    }

    function readyFunction()
    {
        $.getScript("https://www.youtube.com/iframe_api", youtubeAPIReady);
    }

    jQuery(document).ready(readyFunction);

Any help?

6 Answers 6

14

You can borrow the technique used in YouTube Direct Lite to defer loading the JavaScript until it's explicitly needed:

var player = {
  playVideo: function(container, videoId) {
    if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
      window.onYouTubeIframeAPIReady = function() {
        player.loadPlayer(container, videoId);
      };

      $.getScript('//www.youtube.com/iframe_api');
    } else {
      player.loadPlayer(container, videoId);
    }
  },

  loadPlayer: function(container, videoId) {
    new YT.Player(container, {
      videoId: videoId,
      width: 356,
      height: 200,
      playerVars: {
        autoplay: 1,
        controls: 0,
        modestbranding: 1,
        rel: 0,
        showInfo: 0
      }
    });
  }
};
Sign up to request clarification or add additional context in comments.

2 Comments

I feel like this might end up calling getScript a few too many times.
but according to the source control repository this is a google owned project. wouldn't they know what they're doing?
9

poor man's solution, but ...

function readyYoutube(){
    if((typeof YT !== "undefined") && YT && YT.Player){
        player = new YT.Player('player', {
            ...
        });
    }else{
        setTimeout(readyYoutube, 100);
    }
}

1 Comment

This is great solution. YT wasn't being defined for me however so I did this: if(typeof YT !== "undefined" && YT && YT.Player){
8

Quote from http://api.jquery.com/jQuery.getScript/

The callback is fired once the script has been loaded but not necessarily executed.

The API probably hasn't run by the time you call YT.Player()

1 Comment

The iframe_api JS has loaded and executed, but it is probably just an asynchronous loader for the player itself. The player isn't ready immediately, and you have to use code from one of the other answers to delay your use of YT.Player.
4

I can't speak for the jQuery solution, but try using the stock standard javascript. In any case you won't have to wait for the document to be loaded (this code should sit outside $(document).ready())

// Load the YouTube API asynchronously
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// Create the player object when API is ready
var player;
window.onYouTubeIframeAPIReady = function () {
    player = new YT.Player('player', {
        height: '390',
        width: '640',
        videoId: 'CxYyN0dCDaY'
    });
};

4 Comments

Quote from api.jquery.com/jQuery.getScript: The callback is fired once the script has been loaded but not necessarily executed. The API probably hasn't run by the time you call YT.Player()
So, all I really needed to do was use the onYouTubeAPIFrameReady function. I still want to use getScript to load the data, because that DOM Modification is silly, but if you submit that comment as a separate answer I'll mark it as correct.
Also, I'm now getting: """Blocked a frame with origin "youtube.com" from accessing a frame with origin "danhakimi.com". The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.""" What's that about?
This is a known chromium issue, see code.google.com/p/chromium/issues/detail?id=17325
0

I've solved this issue by combining approaches of Simon and user151496.

The code:

<script>
    // load API
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    // define player
    var player;
    function onYouTubeIframeAPIReady() {
        player = new YT.Player('player', {
            height: '360',
            width: '640'
        });
    }

    $(function () {

       // load video and add event listeners
       function loadVideo(id, start, end) {
          // check if player is defined
          if ((typeof player !== "undefined")) {
            // listener for player state change
            player.addEventListener('onStateChange', function (event) {
                if (event.data == YT.PlayerState.ENDED) {
                    // do something
                }
            });
            // listener if player is ready (including methods, like loadVideoById
            player.addEventListener('onReady', function(event){
                event.target.loadVideoById({
                    videoId: id,
                    startSeconds: start,
                    endSeconds: end
                });
                // pause player (my specific needs)
                event.target.pauseVideo();
            });
        }
        // if player is not defined, wait and try again
        else {
            setTimeout(loadVideo, 100, id, start, end);
        }
      }

      // somewhere in the code
      loadVideo('xxxxxxxx', 0, 3);
      player.playVideo();
   });
</script>

Comments

-1

Remove the add block from your browser and try again. Its worked for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.