我遇到以下代码的问题,但我不确定问题出在哪里。
在我的母版页上,在javascript中,我定义了一个数组来保存我创建的YouTubePlayer
个对象的列表。我也在这里加载了YouTube API。
我还有(有时几个)YouTube用户控件,其中包含引导模式中的YouTube div。它还包含一个JavaScript,用于将新的YouTubePlayer
对象推送到母版页js中的数组。最后,在用户控件上,我定义了在bootstrap模式的“显示”和“隐藏”事件上自动启动和停止视频的方法。
最后,为了(希望)解决正在加载的文档和正在加载的YouTube API之间的竞争条件,我设置了两个bool变量(一个用于文档,一个用于API),并在调用initVideos函数之前检查两者是否为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 :(得分: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;
}
}
假设您使用代码生成来创建如下函数:
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();
}
因此,这不是针对您的问题的复制粘贴解决方案,但应该让您深入了解代码无法正常工作的原因。可能有更优雅的方法来实现你想要做的事情,但是现在让我们保持简单的修复。
让我知道它是否有效或是否有任何其他问题。