Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Youtube iFrame (with javascript API) loads the first time, but not the second one. Why?

I am using the iFrame Youtube API with the following code. I call this view with Ajax to render it and append it in a div.yt-player within my page. It works the first time I call the view, but after I close the video (it empties the div.yt-player) and click on another link that calls my view, the video doesn't load at all (blank). I've been struggling and still don't see why it happens, especially that it works the first time. Any kind of help would be much appreciated.. Thanks.

PS: Both the html and the javascript are rendered by the view.

Html
<div id="player"></div>

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

  var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      height: '486',
      width: '864',
      videoId: '#{@media['youtube_url']}',
      events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
      },
      playerVars: {
        'showinfo': 0,
        'iv_load_policy': 3,
        'color': 'white',
        'fs': 1,
        'autoplay': 1,
        'vq': 'hd720'
      }
    });
  }

  function onPlayerReady(event) {
    event.target.playVideo();
  }

  var done = false;
  function onPlayerStateChange(event) {
    if (event.data == YT.PlayerState.PLAYING && !done) {
      setTimeout(stopVideo, 6000);
      done = true;
    }
  }
  function stopVideo() {
    player.stopVideo();
  }
like image 620
user1011444 Avatar asked Apr 11 '13 10:04

user1011444


Video Answer


2 Answers

Just check if the script has been defined.

if(document.getElementById('iframe_api') === null){
            var tag = document.createElement('script');
            tag.src = "https://www.youtube.com/iframe_api";
            tag.id = "iframe_api";
            var firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
        }
else
    runPlayer();

function runPlayer(){
            var player;
            player = new YT.Player(element.children()[0], {
                playerVars: {
                    autoplay: 1,
                    html5: 1,
                    controls: 1,
                    showsearch: 0,
                    showinfo: 0
                },
                height: scope.height,
                width: scope.width,
                videoId: scope.videoid,
                events: {
                    onStateChange: function (event) {
                        if (event.data == YT.PlayerState.ENDED) {
                            scope.$emit('VideoEnded');
                        }
                    }
                }
            });
        }
$window.onYouTubeIframeAPIReady = function () {
    runPlayer();
};
like image 140
Eli Koder Avatar answered Nov 13 '22 20:11

Eli Koder


I debugged the problem. onYouTubeIframeAPIReady() is called only the first time the YouTube API is loaded (when the user refreshes the page and clicks on the link to the view for example), and because I'm calling my views in Ajax, it didn't get fired up the following times.

So I replaced the first block of code by wrapping it in a conditional:

  if (typeof youtube_api_init == 'undefined') {
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  } 

and

if (typeof youtube_api_init != 'undefined') {
  onYouTubeIframeAPIReady();
}

and at the end of the script, I set the youtube_api_init for the browser to remember the YouTube API has already been loaded:

var youtube_api_init = 1;

PS: the first time I tried, I called my variable yt_api_init instead of youtube_api_init, and it didn't work cause it happens that's a name YouTube already uses in its api...

like image 22
user1011444 Avatar answered Nov 13 '22 22:11

user1011444