javascript 中的变量范围 - 未被事件侦听器拾取

Variable scope in javascript - not being picked up by event listener

我有一个问题,一开始是一个实用的问题,因为我想要一个包含视频的元素在视频结束时折叠,为此我需要添加一个事件侦听器,但由于它不起作用,我开始做一些正在测试,我不明白 JavaScript 是如何访问变量的。

好的,所以在我的项目中,我在 iframe 中有一个视频,如下所示:

html

    <p> ...some tex... 
<span id="clickable" class="link">click me to watch video</span>.<span><iframe  id="frame" class="rect" src="iframe.html" scrolling="no" marginwidth=0 marginheight=0></iframe></span>
 ...some more tex...</p>

iframe 只有一个视频

iframe:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="script2.js"></script>
    <link rel="stylesheet" type="text/css" href="styles.css">   
</head>
<body>
    <video id="myVid" width="350" height="200" >
       <source src="someVideo.mp4" type="video/mp4">
    </video>
</body>
</html> 

JavaScript是这样的:

$(document).ready(function(){


    $("#clickable").click(function(){

        var rect = $(this).next().find('.rect');

        if (rect.hasClass( "open" )){

            rect.removeClass("open");

            rect.contents().find("#myVid").get(0).pause();

        } else {

        rect.addClass("open");

        rect.contents().find("#myVid").get(0).play();
        }
     });

和css

.rect{
    float: left;
    height: 0px;
    width: 350px;
    display: block;
    margin: 0px;
    padding: 0px;
    opacity: 0;

    transition-property: all;
    transition-duration: 2s;
    transition-timing-function: ease-in-out;
}

.open {
    height: 200px;
    width: 350px;
    opacity: 1;
    padding-bottom: 10px;
    padding-top: 10px;
}

好的,这样就可以了。当我单击 link "clickable" 时,javascript 将 class "open" 添加到 iframe,使高度从 0 变为 200px,因此视频幻灯片打开。然后,当我再次单击时,视频关闭。 所以我想做的是添加一个功能,当视频完成此功能时,该功能也会关闭视频:

    $('#myVid').on('ended',function(){
         rect.removeClass("open");
         alert('finished');
    });

这是问题开始的时候。问题是把这个功能放在哪里。如果我将它放在 "clickable" 函数之外,它会在视频结束时触发(出现警告框),但视频不会崩溃,所以我断定它无法到达视频。然后我像这样修改了事件监听器:

  $('#rickieVid').on('ended',function(){

      if ($(rect).hasClass("open")){alert('has class')}
      else {alert('has not');}   
    });

并且警告框显示:"has not"。所以这真的让我感到困惑,因为 class "open" 显然是与 "clickable" 事件一起添加的。有人可以帮我理解为什么这不起作用吗?非常感谢 P

===================================编辑========= =========================

我也许应该提到我确实尝试将 "rect" 变量放在 "clickable" 函数之外以使其成为全局变量,如下所示:

$(document).ready(function(){

    var rect;

    $("#rickie").click(function(){

        rect = $(this).next().find('.rect');

etc...

然后像这样修改我的函数来访问全局变量:

$('#rickieVid').on('ended',function(){

if (rect.hasClass("open")){alert('has class')}

else {alert('has not');}   

});

由于出现以下错误,仍然无法正常工作:

TypeError: undefined is not an object (evaluating 'rect.hasClass')

您可以通过将加载事件处理程序附加到 iframe jquery 对象来实现此目的,因为主文档已准备就绪,即使 iframe 源正在其中加载,有时视频控件也需要时间加载,因为出色地。

无论如何,在那种情况下,您需要设置全局播放器对象并将结束的事件处理程序附加到播放器。

jQuery 使用代码:

$(document).ready(function(){

        var frame = $("#frame");
        var player;

        frame.bind("load", function () {
            player = $(this).contents().find("#myVid");
            player.on('ended', function () {
                frame.removeClass("open");
                alert('finished');
            });
        });

        $("#clickable").click(function(){
            if (frame.hasClass("open")) 
            {
                frame.removeClass("open");
                player[0].pause();
            } 
            else {
                frame.addClass("open");
                player[0].play();
            }
        });
    });

这里要注意一件事。如果 iframe 源是跨域 url 那么 .contents() 将抛出安全错误。这仅在 iframe 源页面位于同一域内时有效。