2015-04-17 225 views
17

我遇到以下代码问题,但我不确定问题出在哪里。加载多个YouTube视频iFrame API

在我的母版页上,在javascript中,我定义了一个数组来定义我创建的YouTubePlayer对象的列表。我也在这里加载YouTube API。

我也有(有时是几个)YouTube用户控件包含YouTube div的引导模式。它还包含一个JavaScript,用于将新的YouTubePlayer对象推送到主页面js中的数组。最后,在用户控件上,我定义了用于在引导模式的“显示”和“隐藏”事件上自动启动和停止视频的方法。

最后,为了(希望)解决正在加载的文档和正在加载的YouTube API之间的竞争状态,我设置了两个bool变量(一个用于文档,一个用于API),并在调用init之前检查两个变量是否为true。函数,它遍历YouTubePlayer对象数组并初始化它们,在窗口中设置YT.Player对象。我认为问题的一部分是我无法静态设置window.player1等,因为我不知道将会加载多少YouTube用户控件。

的问题是每当引导模式的事件发生火灾,YT.Player对象我从窗口检索不包含playVideo()pauseVideo()方法。

在我的母版页:

$(document).ready(function() { 
    window.docReady = true; 

    if (window.apiReady) 
     initVideos(); 
}); 

function onYouTubeIframeAPIReady() { 
    window.apiReady = true; 

    if (window.docReady) 
     initVideos(); 

    initVideos(); 
} 

function initVideos() { 

    if (typeof ytPlayerList === 'undefined') 
     return; 

    for (var i = 0; i < ytPlayerList.length; i++) { 
     var player = ytPlayerList[i]; 
     var pl = new YT.Player(player.DivId, { 
      playerVars: { 
       'autoplay': '0', 
       'controls': '1', 
       'autohide': '2', 
       'modestbranding': '1', 
       'playsinline': '1', 
       'rel': '0', 
       'wmode': 'opaque' 
      }, 
      videoId: player.VideoId, 
      events: { 
       'onStateChange': player.StateChangeHandler 
      } 
     }); 

     window[player.Id] = pl; 
    } 
} 

而且用户控件:

window.ytPlayerList.push({ 
    Id: "<%=ClientID%>player", 
    DivId: "<%=ClientID%>player", 
    VideoId: "<%=VideoId%>", 
    StateChangeHandler: hide<%=ClientID%>Player 
}); 

function hide<%=ClientID %>Player(state) { 
    if (state.data == '0') { 
     hide<%=ClientID %>Video(); 
    } 
} 

function show<%=ClientID %>Video() { 
    $('#<%=ClientID %>video-modal').modal('show'); 
} 

function hide<%=ClientID %>Video() { 
    $('#<%=ClientID %>video-modal').modal('hide'); 
} 

$(document).ready(function() { 
    $("#<%=ClientID%>Video").click(function() { 
     show<%=ClientID%>Video(); 
    }); 

    $("#<%=ClientID %>video-modal").on('shown', function() { 
     window["<%=ClientID%>player"].playVideo(); 
    }); 

    $("#<%=ClientID %>video-modal").on('hide', function() { 
     window["<%=ClientID%>player"].pauseVideo(); 
    }); 
}); 

这可能是缺乏专业知识的js,但我绝对坚持。任何帮助将不胜感激。此外,作为参考,我得到的例外是

Uncaught TypeError: window.ctl100_phContent_ctl100player.playVideo is not a function 
+0

是否故意在'onYouTubeIframeAPIReady()'函数中激发'initVideos()'两次? –

+0

可能重复[.playVideo() - 不是一个函数?](http://stackoverflow.com/questions/2217543/cant-control-youtube-embed-even-with-document-getelementbyidxyz-playvideo)或[playVideo doesn 't work](http://stackoverflow.com/questions/9287170/youtube-player-iframe-api-playvideo-doesnt-work-on-firefox-9-0-1) –

+0

你可以粘贴一些生成的HTML请 ?这会让我更容易重现这个问题。 –

回答

8

所以问题是,视频仅获得,当YouTube的API已经完成加载视频元素playVideo()方法。这个视频元素是异步加载的,因此代码执行将继续执行$(document).ready(function() { jQuery代码,它将尝试附加当时的playVideo()函数 - 尚不存在。

我转载此错误在HTML/JS网页:

<!doctype html> 
<html class="no-js" lang=""> 
<head> 
    <meta charset="utf-8"> 
    <meta http-equiv="x-ua-compatible" content="ie=edge"> 
    <title></title> 
</head> 
<body> 
    <div id="ctl100_phContent_ctl100player" style="border:1px solid red;"></div> 
    <div id="ctl100_phContent_ctl101player" style="border:1px solid red;"></div> 
    <div id="ctl100_phContent_ctl102player" style="border:1px solid red;"></div> 

    <script src="https://www.youtube.com/iframe_api"></script> 
    <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.6.2.min.js"><\/script>')</script> 
    <script> 
     window.ytPlayerList = []; 
     window.players = []; 

     window.ytPlayerList.push({ Id: 'ctl100_phContent_ctl100player', DivId: 'ctl100_phContent_ctl100player', VideoId: 'IaHxPi9dM7o', StateChangeHandler: 'hide_player_1' }); 
     window.ytPlayerList.push({ Id: 'ctl100_phContent_ctl101player', DivId: 'ctl100_phContent_ctl101player', VideoId: 'IaHxPi9dM7o', StateChangeHandler: 'hide_player_2' }); 
     window.ytPlayerList.push({ Id: 'ctl100_phContent_ctl102player', DivId: 'ctl100_phContent_ctl102player', VideoId: 'IaHxPi9dM7o', StateChangeHandler: 'hide_player_3' }); 

     function onYouTubeIframeAPIReady() { 
      initVideos(); 
     } 

     function initVideos() { 
      for (var i = 0; i < ytPlayerList.length; i++) { 
       var player = ytPlayerList[i]; 
       var pl = new YT.Player(player.DivId, { 
        height: '390', 
        width: '640', 
        videoId: player.VideoId, 
       }); 
       window[player.Id] = pl; 
      } 
     } 

     window.ctl100_phContent_ctl100player.playVideo(); 
    </script> 
</body> 
</html> 

这给了我你所描述的同样的错误。所以为了测试我的理论(并确保没有其他脚本错误),我这样做了:

setTimeout(function() { 
     window.ctl100_phContent_ctl100player.playVideo() 
}, 1000); 

这确实奏效。所以这似乎确实是这个问题。但是 - 我们不确定1000毫秒是否足以保证玩家初始化。所以,你可以做些什么 - 如果你想不重构太多 - 是开始监听玩家的onready事件:

function initVideos() { 
     for (var i = 0; i < ytPlayerList.length; i++) { 
      var player = ytPlayerList[i]; 
      var pl = new YT.Player(player.DivId, { 
       height: '390', 
       width: '640', 
       videoId: player.VideoId, 
       events: { 
        'onReady': window[player.Id + '_ready'] 
       } 
      }); 
      window[player.Id] = pl; 
     } 
    } 

即假设你使用codegeneration创建类似的功能:

function ctl100_phContent_ctl100player_ready() { 
     // Hook up the hide()/onShow() and other behaviors here 
     // ... to prove that playVideo() is a function here, I'm calling it 
     window.ctl100_phContent_ctl100player.playVideo(); 
    } 
    function ctl100_phContent_ctl101player_ready() { 
     window.ctl100_phContent_ctl101player.playVideo(); 
    } 
    function ctl100_phContent_ctl102player_ready() { 
     window.ctl100_phContent_ctl102player.playVideo(); 
    } 

所以这不是针对你的问题的复制粘贴解决方案,但应该让你了解代码不工作的原因。有可能更优雅的方式来实现你想要做的事情,但让我们现在就保持简单。

让我知道它是否有效,或者如果您有任何其他问题。

+0

窗口在浏览器上不起作用 –