我在以下代码中遇到了问题,但我不确定问题出在哪里。
在我的主页上,我用javascript定义了一个数组,用来保存我创建的YouTubePlayer
对象的列表。我还在这里加载了YouTube应用程序接口。
我还有(有时是几个) YouTube用户控件,它包含引导模式中的YouTube div。它还包含一个用于将新的YouTubePlayer
对象推送到主页js中的数组的JavaScript。最后,在用户控件上,我定义了在bootstrap模式的“显示”和“隐藏”事件上自动启动和停止视频的方法。
最后,为了(希望)解决要加载的文档和要加载的YouTube应用程序接口之间的竞争条件,我设置了两个布尔变量(一个用于文档,一个用于API),并在调用initVideos函数之前检查这两个变量是否都为真,该函数迭代YouTubePlayer
对象数组并对其进行初始化,从而在窗口中设置YT.Player
对象。我想,问题的一部分是我不能静态地设置window.player1
等,因为我永远不知道会加载多少YouTube用户控件。
无论何时触发引导模式事件,我从窗口检索的YT.Player
pauseVideo()
**.** 对象都不包含 playVideo()
和的方法,这是问题所在
在我的母版页上:
$(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
发布于 2015-04-30 02:21:08
所以问题是,视频只有在YouTube接口加载完视频元素后才会获得该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);
这确实起作用了。因此,这确实是问题所在。然而,我们不确定1000ms是否足以保证播放器被初始化。所以你可以做的是-如果你不想重构太多-开始监听播放器的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();
}
因此,这不是针对您的问题的复制-粘贴解决方案,而是应该让您深入了解代码无法工作的原因。可能有更优雅的方法来实现您想要做的事情,但让我们暂时保持修复的简单性。
让我知道它是否工作,或者如果你有任何其他问题。
https://stackoverflow.com/questions/29709320
复制相似问题