最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - YouTube API - FirefoxIE return error "X is not a function" for any 'player.' requ

programmeradmin0浏览0评论

I've been pulling my hair out trying to get a fairly simple YouTube api integration working in FF/IE and have had no luck so far.

It sounds like either a scope issue or a call being made before the player is initialized but everything I've tried suggests it's not one of those two things. Also of note, everything works perfectly in (only) Chrome.

// Async api load per YT documentation...
var tag = document.createElement('script');
tag.src = "//www.youtube/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// Declare player and set basic functions...
var player

playVideo = function() { player.playVideo(); }
stopVideo = function() { player.stopVideo(); }

// YT Api ready function...
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    videoId: "TkJcg4bmAYs",
    events: {
      'onStateChange': onPlayerStateChange
    }
  });

  // After player object created, bind popup function to page anchors...
  var popup = $('#video-popup')
  ,   popupFrame = $(popup).children('.center')
  ;

  $('a[data-vid]').click(function(e){
    e.preventDefault ? e.preventDefault() : e.returnValue = false;

    var clicked = $(e.target).closest('a')
    ,   videoID = $(clicked).attr('data-vid')
    ;

    if (!$(popup).hasClass('working')){
      // If popup isn't already working, cue video and animate popup in... 
      player.cueVideoById({videoId:videoID});

      $(popup).addClass('working');
      $(popup).css('display','block').animate({
        opacity: '1'
      }, 200, function(){
        playVideo();
        $(popup).removeClass('working');
      });
    }
  });
}

Link to test page with the api and popup code, working in Chrome but not in other browsers. /

I've been pulling my hair out trying to get a fairly simple YouTube api integration working in FF/IE and have had no luck so far.

It sounds like either a scope issue or a call being made before the player is initialized but everything I've tried suggests it's not one of those two things. Also of note, everything works perfectly in (only) Chrome.

// Async api load per YT documentation...
var tag = document.createElement('script');
tag.src = "//www.youtube./iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// Declare player and set basic functions...
var player

playVideo = function() { player.playVideo(); }
stopVideo = function() { player.stopVideo(); }

// YT Api ready function...
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    videoId: "TkJcg4bmAYs",
    events: {
      'onStateChange': onPlayerStateChange
    }
  });

  // After player object created, bind popup function to page anchors...
  var popup = $('#video-popup')
  ,   popupFrame = $(popup).children('.center')
  ;

  $('a[data-vid]').click(function(e){
    e.preventDefault ? e.preventDefault() : e.returnValue = false;

    var clicked = $(e.target).closest('a')
    ,   videoID = $(clicked).attr('data-vid')
    ;

    if (!$(popup).hasClass('working')){
      // If popup isn't already working, cue video and animate popup in... 
      player.cueVideoById({videoId:videoID});

      $(popup).addClass('working');
      $(popup).css('display','block').animate({
        opacity: '1'
      }, 200, function(){
        playVideo();
        $(popup).removeClass('working');
      });
    }
  });
}

Link to test page with the api and popup code, working in Chrome but not in other browsers. http://www.crackin./dev/regions/pathBuild/

Share Improve this question edited May 9, 2013 at 3:37 relic asked May 8, 2013 at 18:35 relicrelic 1,7041 gold badge16 silver badges26 bronze badges 3
  • 1 Is it possible that you are having a timing issue? You may be trying to execute code before the dom element you need has rendered. – Dropzilla Commented May 8, 2013 at 19:03
  • Also, could you have a cached file in Chrome and that is the only reason it is working, if you clear your cache does it still work in Chrome? The error suggest that some of the player code is not being loaded correctly. Do you see any other javascript errors in the chrome inspector console tab or firefox developer tools error console? – Dropzilla Commented May 8, 2013 at 19:05
  • @Mike - I tried wrapping my popup binder in a 5 second delay, but didn't seem to help. I've also triple checked caching by clearing both browsers and refreshing multiple times. Chrome continues to shine while FF and IE continue to puke... I've updated the description with a link to a stripped down version of the page that includes just the api and popup code. – relic Commented May 9, 2013 at 3:36
Add a ment  | 

2 Answers 2

Reset to default 9

After imbedding half of my keyboard keys into my forehead, I finally stumbled across the frustratingly simple root of the problem... It's nothing but a visibility issue! ARRGG!!! Apparently, FireFox and IE do not have access to the player object if it is initialized while set to display:none;, but Chrome is smart enough to still initialize and target it even hidden.

The fix, in my particular case, was to load the popup as display:block with opacity:0, THEN initialize the api, THEN set the popup to display:none inside the YT api init function. Something like this:

First, CSS...

#video-popup { display: block; opacity: 0; }

.. then javascript...

var player
,   popup = $('#video-popup')
;

function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        videoId: "TkJcg4bmAYs"
    });
    $(popup).css('display','none');
}

Now I need to go get drunk.


ADDITIONAL STUFF: After finally figuring out the root of the problem, I was able to isolate some additional IE browser problems and work out solutions. These are just in case somebody else is having a similar issue, they may be able to carve out their own solution from this. My solution might be a bit situation-specific, but if anybody else is putting youtube videos in popups and needs IE support, this might help.

The fix above (setting display:none in the YT ready function) didn't seem to work perfectly for IE8, but was quickly fixed by wrapping it in a brief timeout:

function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        videoId: "TkJcg4bmAYs"
    });
    setTimeout(function(){
        $(popup).css('display','none');
    }, 500);
}

IE7 was a bit trickier, as it seems that if the player is EVER hidden using display:none, it immediately bees unavailable regardless of whether it's been initialized or not.

Using conditional ments to apply classes to the tag, you can add some IE specific css to keep the popup "visible" but hide it offscreen instead.

#video-popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; opacity: 0; }
.ie7Detect #video-popup { display: block; left: -101% }
#video-popup.open { left:0 !important; }

There is also an issue where in both IE7 and 8 the youtube player is still visible even when the parent container is set to opacity 0 (which happens while page is still loading). I tried adding rules to further target the contents of the popup and set their opacity also, but didn't work and wasn't super clean either. What I settled on was using a loading class.

So the popup has a loading class:

<div id="video-popup" class="loading">
    <!-- bunch of stuff in here -->
</div>

And function is updated...

function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        videoId: "TkJcg4bmAYs",
    });
    setTimeout(function(){
        $(popup).removeClass('loading');
    }, 500);
}

CSS looks something like this...

#video-popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; opacity: 0; }
.ie7Detect #video-popup, #video-popup.loading { display: block; left: -100% }
#video-popup.open { left:0 !important; }

The last piece of the puzzle would be to incorporate a classname 'open' for your popup function when it's actually suppose to be visible.

Hope that helps somebody avoid some potential headaches in the future. On the downside, you may not be QUITE as enthusiastic to get drunk after addressing these issues as you might have otherwise been.

Peace, yo.

First off, thanks for figuring this out. Like you, I think I tried every solution I could find to no avail.

Second, I'm writing because although my issue was very similar in nature, I was trying to load a video via the bxSlider jQuery plugin and I wanted to post my solution in hopes it could save someone else some time.

I simply just called a function on the onSliderLoad method. Here's what the function looks like:

function()
{
  if ($('.slideshow-item-video').length > 0) {

    $('.slideshow-item-video').each(function()
    {
      $(this).css('display', 'block');

      setTimeout(function()
      {
        $(this).css('display', 'none');
      }, 500);
    });
  }
}

I'm simply giving slides that contain a video a specific class and making them visible so the API can access the element, then setting a timeout to hide the element again.

This solution works in Firefox and IE8+. I have not figured out a solution for IE7, but, it's IE7.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论