事件处理程序中的 setTimeout
setTimout within event handler
我为一些视频构建了一个 iFrame 查看器 here。
效果很好,除非有人点击视频 A 的按钮,然后在视频 A 仍在播放时点击视频 B 的按钮。当视频 A 结束并切断视频 B 时,查看器将关闭。
我已经阅读了很多关于在其他函数中使用 setTimeout 的问题和答案。我认为问题在于 setTimeout 正在从视频 A 获取持续时间信息,并且在单击视频 B 时不更新,通常称为 'this' 问题。
我看了很多问答,也尝试了很多解决方案,但还是不行。这是我的第一个 javascript 项目,非常感谢您的帮助。这是代码的简化版本:
***
<body>
***
//The buttons contain data for the viewer, including the video's duration and the YouTube address. This is a sample button:
<div id="MovieButtons" class="MovieButtons">
<button class="MovieButton" data-MovieId="Memorial" data-MovieDur="2740000" data-MovieAdr="https://www.youtube.com/embed/sMVZbMxD-Xw?autoplay=1&controls=0&">Memorial Video</button>
</div> <!--End Moviebuttons-->
<script language="JavaScript" type="text/javascript" src="jquery_3.1.0.min.js"></script>
<script>
$(document).ready(function(){
//initial state has the viewer hidden. It appears when a movie is clicked.
$("#viewer").hide();
//declaring global variables -- the .val property will be assigned inside the function.
var MovieId = {};
var MovieDur = {};
var MovieAdr = {};
//When a movie is clicked, viewer gets its info from the button,
$(".MovieButton").on("click", function(){
MovieId.val= $(this).attr("data-MovieId");
MovieDur.val= Number($(this).attr("data-MovieDur"));
MovieAdr.val= $(this).attr("data-MovieAdr");
//shows the viewer
$("#viewer").show();
//viewer loads movie and plays
$("#viewer").html("<iframe src="+oMovieAdr.val+" width=\"560\" height=\"315\" style=\"position:relative; left: 22%; top:0%; frameborder=\"1\" allowfullscreen></iframe>");
//Reset mechanism closes the viewport and hides the stop button, also restores normal page look. This is where the problem is.
function reset(){
$("#viewer").hide();
$("#viewer").html("<iframe src= none></iframe>");
};
//Automatically closes viewport when the movie ends.
setTimeout(function(){
reset();}, oMovieDur.val);
}); //end of $(".oMovieButton").on("click", function(){
}); //end of $(document).ready(function(){
</script>
计时器不能"update"。如果 oMovieDur.val
是 3600000
,你将 3600000
传递给 setTimeout
,而不是 oMovieDur.val
引用,并且计时器将在一小时后触发,无论你稍后做 oMovieDur
.
您更应该确定您的计时器,如果它不再相关(即您开始了一部新电影并准备制作一个新计时器),则将其关闭。
var resetTimer = null;
// ...
clearTimeout(resetTimer);
resetTimer = setTimeout(function(){
reset();}, oMovieDur.val);
示例代码:
var timer = null;
$('button').click(function(evt) {
var name = $(this).data('name');
console.log("started", name, "(ending in 3s)");
if (timer) {
clearTimeout(timer);
console.log("aborted the previous", name);
}
timer = setTimeout(function() {
timer = null;
console.log("ended", name);
}, 3000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-name="A">start A</button>
<button data-name="B">start B</button>
这演示了清除计时器。
供将来参考,
Amadan 关闭一个计时器并启动另一个计时器的建议很好,但新计时器仍在事件计时器中使用原始视频持续时间。我找到的解决方案是使用 Ben Alman 的一个名为 doTimeout 的 jquery 插件:http://benalman.com/projects/jquery-dotimeout-plugin/
我重写了超时线,原来:
setTimeout(function(){
reset();}, oMovieDur.val);
如下('loop'只是一个id):
$.doTimeout( 'loop', oMovieDur.val, function(){
reset();
});
现在一切正常。感谢 Amadan 和 Ben Alman
我为一些视频构建了一个 iFrame 查看器 here。
效果很好,除非有人点击视频 A 的按钮,然后在视频 A 仍在播放时点击视频 B 的按钮。当视频 A 结束并切断视频 B 时,查看器将关闭。
我已经阅读了很多关于在其他函数中使用 setTimeout 的问题和答案。我认为问题在于 setTimeout 正在从视频 A 获取持续时间信息,并且在单击视频 B 时不更新,通常称为 'this' 问题。
我看了很多问答,也尝试了很多解决方案,但还是不行。这是我的第一个 javascript 项目,非常感谢您的帮助。这是代码的简化版本:
***
<body>
***
//The buttons contain data for the viewer, including the video's duration and the YouTube address. This is a sample button:
<div id="MovieButtons" class="MovieButtons">
<button class="MovieButton" data-MovieId="Memorial" data-MovieDur="2740000" data-MovieAdr="https://www.youtube.com/embed/sMVZbMxD-Xw?autoplay=1&controls=0&">Memorial Video</button>
</div> <!--End Moviebuttons-->
<script language="JavaScript" type="text/javascript" src="jquery_3.1.0.min.js"></script>
<script>
$(document).ready(function(){
//initial state has the viewer hidden. It appears when a movie is clicked.
$("#viewer").hide();
//declaring global variables -- the .val property will be assigned inside the function.
var MovieId = {};
var MovieDur = {};
var MovieAdr = {};
//When a movie is clicked, viewer gets its info from the button,
$(".MovieButton").on("click", function(){
MovieId.val= $(this).attr("data-MovieId");
MovieDur.val= Number($(this).attr("data-MovieDur"));
MovieAdr.val= $(this).attr("data-MovieAdr");
//shows the viewer
$("#viewer").show();
//viewer loads movie and plays
$("#viewer").html("<iframe src="+oMovieAdr.val+" width=\"560\" height=\"315\" style=\"position:relative; left: 22%; top:0%; frameborder=\"1\" allowfullscreen></iframe>");
//Reset mechanism closes the viewport and hides the stop button, also restores normal page look. This is where the problem is.
function reset(){
$("#viewer").hide();
$("#viewer").html("<iframe src= none></iframe>");
};
//Automatically closes viewport when the movie ends.
setTimeout(function(){
reset();}, oMovieDur.val);
}); //end of $(".oMovieButton").on("click", function(){
}); //end of $(document).ready(function(){
</script>
计时器不能"update"。如果 oMovieDur.val
是 3600000
,你将 3600000
传递给 setTimeout
,而不是 oMovieDur.val
引用,并且计时器将在一小时后触发,无论你稍后做 oMovieDur
.
您更应该确定您的计时器,如果它不再相关(即您开始了一部新电影并准备制作一个新计时器),则将其关闭。
var resetTimer = null;
// ...
clearTimeout(resetTimer);
resetTimer = setTimeout(function(){
reset();}, oMovieDur.val);
示例代码:
var timer = null;
$('button').click(function(evt) {
var name = $(this).data('name');
console.log("started", name, "(ending in 3s)");
if (timer) {
clearTimeout(timer);
console.log("aborted the previous", name);
}
timer = setTimeout(function() {
timer = null;
console.log("ended", name);
}, 3000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-name="A">start A</button>
<button data-name="B">start B</button>
这演示了清除计时器。
供将来参考,
Amadan 关闭一个计时器并启动另一个计时器的建议很好,但新计时器仍在事件计时器中使用原始视频持续时间。我找到的解决方案是使用 Ben Alman 的一个名为 doTimeout 的 jquery 插件:http://benalman.com/projects/jquery-dotimeout-plugin/
我重写了超时线,原来:
setTimeout(function(){
reset();}, oMovieDur.val);
如下('loop'只是一个id):
$.doTimeout( 'loop', oMovieDur.val, function(){
reset();
});
现在一切正常。感谢 Amadan 和 Ben Alman