YouTube onPlayerStateChange事件在重新加载的页面上未在Internet Explorer中触发

时间:2012-10-30 19:37:39

标签: javascript-events youtube-api youtube-javascript-api

因此,我们有一个包含YouTube视频的Facebook标签应用程序(可能不相关)。

第一次从空缓存加载页面时,一切正常。但是,在后续页面加载时,一旦视频停止加载,onStateChange处理程序就不会在Internet Explorer中触发。

在Chrome和Firefox中一切正常,这个问题似乎只影响IE,奇怪的是,只发生在非空缓存中。它看起来与gdata-issues #2942非常相似,只是问题有Status: Fixed

我们的代码的相关块如下:

<!DOCTYPE html>

...

<div class="player-surround">
   <div id="ytplayer">
       You need Flash player 9+ and JavaScript enabled to view this video.
   </div>
</div>

...

<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script type="text/javascript">
var params = { allowScriptAccess: "always" };
var atts = { id: "ytplayer" };
// YouTube video ID redacted here
swfobject.embedSWF("http://www.youtube.com/v/XXXXXXXXXXXXXX?enablejsapi=1&playerapiid=ytplayer&version=3",
   "ytplayer", "587", "330", "8", null, null, params, atts);
</script>
<script src="//www.youtube.com/player_api"></script>

包含的JavaScript

MFA.onPlayerStateChange = function(evt) {
    var state = this.getPlayerState();
    log('158: STATE CHANGED: ' + state);

    // Then do some stuff, but the `log` call above doesn't fire
}

MFA.getPlayerState = function() {
    var playerState;

    if (this.ytplayer) {
        playerState = this.ytplayer.getPlayerState();

        switch (playerState) {
            case 5:  return 'video cued';
            case 3:  return 'buffering';
            case 2:  return 'paused';
            case 1:  return 'playing';
            case 0:  return 'ended';
            case -1: return 'unstarted';
            default: return 'Status uncertain';
        }
    }
};

(显然,我从这个问题中错过了一堆不相关的代码。)

有没有人有任何想法为什么一切都会正常工作,除非IE之前看过这个页面?我可以理解它是否永远在IE中工作,但是当缓存为空时它可以正常工作,但是当你重新加载页面时它会失败。

感谢所有的想法。谢谢!


修改

Greg Schechter指出我的代码示例使用的是swfobject.embedSWF代码,而不是iframe embed code

我们最初使用iframe嵌入代码:

var s = {
   playerHeight: '330',
   playerWidth: '587',
   playerVars: { 'rel': 0 },
   videos: {
      stage1: 'XXXXXXXXXXXXXX', // ...
   }
};

window.onYouTubePlayerAPIReady = function() {
   MFA.ytplayer = new YT.Player('ytplayer', {
      height: s.playerHeight,
      width: s.playerWidth,
      videoId: s.videos.stage1,
      playerVars: s.playerVars,
      events: {
         'onReady': $.proxy(MFA.onPlayerReady, MFA),
         'onStateChange': $.proxy(MFA.onPlayerStateChange, MFA),
         'onError': $.proxy(MFA.onPlayerError, MFA)
      }
   });
} 

,但这表现出同样的问题。随后添加了swfobject.embedSWF代码作为解决问题的尝试,因为我们之前已经看到IE在跨iframe的域中进行API访问时过度偏执的问题。

2 个答案:

答案 0 :(得分:0)

您的代码示例看起来有些偏差。您似乎正在swfobject.embedSwf使用//www.youtube.com/player_api//www.youtube.com/player_api脚本仅适用于iframe嵌入。如果你使用iframe嵌入它应该解决你的问题。

详细信息可以在这里找到。 https://developers.google.com/youtube/iframe_api_reference

答案 1 :(得分:0)

所以我不得不放下这个并回到另一个项目,但我的一位同事设法找到了解决方案。其余的答案直接来自他给我的电子邮件。

所以这里是我们如何修复这个(非常讨厌!)IE问题的长版本...事实证明这是改变在default.aspx页面中调用YouTube Player API的方式。

我们取代了这个:

<script src="//www.youtube.com/player_api"></script>

<script>标记中使用以下JavaScript:

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

(这就是API reference中指定的方式)。

我还注意到Google指定了iframe_api,但我们使用的是player_api。这可能会使问题复杂化,但只是改变它并没有解决它。

[我们的技术总监]向我解释的方式是,第一次加载页面时原始方式很好,因为所有内容都是新加载的,并且在API初始化之前,YouTube API有足够的时间加载。

但是当你重新加载页面时,在API准备好之前,init.js被缓存并且可能加载太快,因此在尝试触发onYouTubePlayerReady时失败。以上述方式执行仍然从init.js开始,但也开始同时加载iframe_api(通过有效地将其作为列表中的第一个脚本标记插入)。它也可能与known issue with IE9 where AJAX calls can create a memory leak略有关联,但不确定。

我在其他浏览器上间歇性地看到同样的错误(非常),我认为这与此处与Google API连接的数据中心之间的RTDs之间存在波动。如果在{API}准备就绪之前init.js已经足够同步,那么onYouTubePlayerReady将失败。但是,简单的刷新就能解决它。

有趣的是,仅将YouTube API作为第一个脚本标记并没有什么区别!

所以我想我们的教训是,当我们处理第三方API,iframe和Internet Explorer时,我们需要确保为所有第三方API使用异步加载,特别是如果涉及到YouTube和Facebook