Jac*_*ack 17 javascript webforms youtube-api twitter-bootstrap
我遇到以下代码的问题,但我不确定问题出在哪里.
在我的母版页上,在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;
}
}
Run Code Online (Sandbox Code Playgroud)
并在用户控件上:
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();
});
});
Run Code Online (Sandbox Code Playgroud)
这可能是缺乏js专业知识,但我绝对卡住了.任何帮助将不胜感激.另外,作为参考,我得到的例外是
Uncaught TypeError: window.ctl100_phContent_ctl100player.playVideo is not a function
Run Code Online (Sandbox Code Playgroud)
所以问题是,playVideo()当YouTube API加载完视频元素时,视频才会获得该方法.此视频元素是异步加载的,因此代码执行将继续使用$(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>
Run Code Online (Sandbox Code Playgroud)
这给了我你描述的同样的错误.所以为了测试我的理论(并确保没有其他脚本错误)我这样做:
setTimeout(function() {
window.ctl100_phContent_ctl100player.playVideo()
}, 1000);
Run Code Online (Sandbox Code Playgroud)
这确实有效.所以这确实是问题所在.但是 - 我们不确定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;
}
}
Run Code Online (Sandbox Code Playgroud)
假设您使用代码生成来创建以下函数:
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();
}
Run Code Online (Sandbox Code Playgroud)
因此,这不是针对您的复制粘贴解决方案,但应该让您深入了解代码无法正常工作的原因.可能有更优雅的方法来实现你想要做的事情,但是现在让我们保持简单.
如果它有用或者您有任何其他问题,请告诉我.
| 归档时间: |
|
| 查看次数: |
4601 次 |
| 最近记录: |