【问题标题】:Variables going beyond scope?变量超出范围?
【发布时间】:2010-01-09 12:13:44
【问题描述】:

我的代码:

<html>

<head>

<script type="text/JavaScript" src="jquery-1.3.2.min.js"></script>
<script type="text/JavaScript" src="jquery.center.js"></script>
<script type="text/JavaScript">
    $(document).ready(function(){
        $('a').click(function(){
            popup_AskYN("Want me to tell you what 1 + 1 is?",function(){
                //popup_Info("It's 2, silly!");
            },function(){
                //popup_Info("I didn't want to, anyway!");
            });
        });
    });

    function popup_AskYN(msg,yes_fn,no_fn){
        $('body').append("<div id='popup'><p>"+msg+"</p><a id='popup_yes' href='#'>Yes!</a><a href='#' id='popup_no'>No.</a></div>");
        var yes_button = $('#popup_yes:last');
        var no_button = $('#popup_no:last');
        var popup = $('#popup:last');
        popup.center();

        yes_button.click(yes_fn);
        no_button.click(no_fn);

        yes_button.click(function(){
            popup.fadeOut('fast').remove();
        });
        no_button.click(function(){
            popup.fadeOut('fast').remove();
        });
    }

    function popup_Info(msg,callback){
        $('body').append("<div id='popup'><p>"+msg+"</p><a id='popup_ok' href='#'>Ok.</a></div>");
        var ok_button = $('#popup_ok:last');
        var popup = $('#popup:last');
        popup.center();

        ok_button.click(callback);

        ok_button.click(function(){
            popup.fadeOut('fast',function(){ $(self).remove(); });
        });
    }


</script>

<style type="text/css">
#popup {
    position:absolute;
    border:1px solid black;
}
#popup a {
    margin:10px;
}
</style>

</head>

<body>
<a href="#">Launch the popup!</a>
</body>

现在这很好用..除了我有多个弹出窗口时。我将其范围缩小到当我创建一个新的弹出窗口时,它会更改 yes_button、no_button、ok_button 和弹出窗口的值。因此,当前一个弹出窗口尝试使用这些变量时,它们都指向新的弹出窗口,而不是当前的。由于所有弹出窗口都具有相同的 ID,因此我没有任何“唯一”来识别每个窗口。我想简单地存储选择器就足够了,但这不起作用。我可以在这里做什么?

已编辑,添加了正确的 ID,但仍然无法正常工作...:

<html>

    <head>
    <title>Call backs</title>

    <script type="text/JavaScript" src="jquery-1.3.2.min.js"></script>
    <script type="text/JavaScript" src="jquery.center.js"></script>
    <script type="text/JavaScript">
        $(document).ready(function(){
            $('a').click(function(){
                popup_AskYN("Want me to tell you what 1 + 1 is?",function(){
                    //popup_Info("It's 2, silly!");
                },function(){
                    //popup_Info("I didn't want to, anyway!");
                });
            });
        });

        var popup_AskYNId = 0;
        var popup_InfoId = 0;
        function popup_AskYN(msg,yes_fn,no_fn){
            popup_AskYNId = popup_AskYNId + 1;
            $('body').append("<div class='popup' id='"+popup_AskYNId+"popup_AskYN'><div class='popup_inner'><p>"+msg+"</p></div><div class='popup_options'><a class='popup_yes' id='"+popup_AskYNId+"popup_yes_AskYN' href='#'>Yes!</a><a href='#' class='popup_no' id='"+popup_AskYNId+"popup_no_AskYN' >No.</a></div></div>");
            popup = $('#'+popup_AskYNId+'popup_AskYN');
            yes_button = $('#'+popup_AskYNId+'popup_yes_AskYN');
            no_button = $('#'+popup_AskYNId+'popup_no_AskYN');

            popup.center();

            yes_button.click(yes_fn);
            no_button.click(no_fn);

            yes_button.click(function(){
                popup.fadeOut('fast').remove();
            });
            no_button.click(function(){
                popup.fadeOut('fast').remove();
            });
        }

        function popup_Info(msg,callback){
            $('body').append("<div id='popup'><div id='popup_inner'><p>"+msg+"</p></div><div id='popup_options'><a id='popup_ok' href='#'>Ok.</a></div></div>");
            ok_button = $('#popup_ok:last');
            popup = $('#popup:last');
            popup.center();

            ok_button.click(callback);

            ok_button.click(function(){
                popup.fadeOut('fast',function(){ $(self).remove(); });
            });
        }


    </script>

    <style type="text/css">

    .popup {
        position:absolute;
        border:1px solid black;
        padding:3px;
    }
    .popup_inner {
        border:1px solid black;
        padding:10px;
    }
    .popup_options {
        margin:0 auto;
    }
    .popup_options a {

        border:1px solid black;

        margin-top:3px;
        margin-left:3px;
        height:15px;
        width:75px;
        float:right;

        text-align:center;
        font-family:tahoma;
        font-size:0.8em;
        text-decoration:none;
        line-height:14px;
    }

    </style>

    </head>

    <body>
    <a href="#">Launch the popup!</a>
    </body>

</html>

找到了解决方案,但我对其进行了一些修改,以便像旧版本一样接受和不接受功能..

    $(function() {
  $('a').click(function(e) {
    e.preventDefault();

    var num1 = Math.floor(Math.random()*11),
    num2 = Math.floor(Math.random()*11);

    popup_AskYN(
        "Want me to tell you what 1 + 1 is?",
        function(){
            $('body').append('its 2');
        },function(){
            $('body').append('Fine.');
        });;
  });

  $('.popup_yes').live('click', function(e) {
    e.preventDefault();

    $(this).closest('.popup').fadeOut('fast', function() {
      $(this).remove();
    });
  });
  $('.popup_no').live('click', function(e) {
    e.preventDefault();

    $(this).closest('.popup').fadeOut('fast', function() {
      $(this).remove();
    });
  });

});

function popup_AskYN(msg, yes, no){
  $('body').append("<div class='popup'><div class='popup_inner'><p>"+msg+"</p></div><div class='popup_options'><a class='popup_yes' href='#'>Yes!</a><a href='#' class='popup_no'>No.</a></div></div>");
  var yes_button = $('.popup_yes:last');
  var no_button = $('.popup_no:last');
  var popup = $('.popup:last');

  yes_button.click(yes);

  no_button.click(no);
}

【问题讨论】:

    标签: javascript jquery scope


    【解决方案1】:

    如果我只是将所有 ID 更改为类,这对我来说很好。但是,如果您想要的是,将弹出窗口绝对放在屏幕上并不适合拥有多个弹出窗口实例。我必须注释掉居中/定位代码才能看到它正在工作。

    我还建议,当有人单击弹出窗口中的“是”或“否”链接时,答案会替换原始弹出窗口的内容,而不是创建新的弹出窗口。我看到您试图在答案出现之前让问题淡出,但请注意,在您当前的实现中,原始弹出问题在动画完成之前被删除,因此删除问题并创建新的弹出窗口没有任何优势带有答案的窗口,而不是仅仅替换内容。

    如果您希望问题在答案出现之前淡出,一种选择是仅在动画完成后删除问题弹出窗口,您可以使用fadeOut的第二个参数来做到这一点,这是动画时要执行的回调完成。同样,这并不适合拥有多个弹出问题实例。原因是答案弹出窗口与问题弹出窗口与您删除问题并将答案附加到正文的方法无关。这也可以通过简单地用答案替换问题来解决。如果您仍然想要相同的淡入淡出效果,您可以淡出弹出窗口,然后更改其内容,然后再淡入淡出。

    这是您的代码的一个版本,可以按照我的建议运行和更改:

    <html>
    <head>
      <script type="text/JavaScript" src="http://code.jquery.com/jquery.js"></script>
      <script type="text/JavaScript">
        $(function() {
          $('a').click(function(e) {
            e.preventDefault();
    
            var num1 = Math.floor(Math.random()*11),
            num2 = Math.floor(Math.random()*11);
    
            popup_AskYN(
              "Want me to tell you what " + num1 + " + " + num2 + " is?",
              "It's " + (num1 + num2) + ", silly!",
              "I didn't want to, anyway!"
            );
          });
    
          $('.popup_ok').live('click', function(e) {
            e.preventDefault();
    
            $(this).closest('.popup').fadeOut('fast', function() {
              $(this).remove();
            });
          });
        });
    
        function popup_AskYN(msg, yes, no){
          $('body').append("<div class='popup'><p>"+msg+"</p><a class='popup_yes' href='#'>Yes!</a><a href='#' class='popup_no'>No.</a></div>");
          var yes_button = $('.popup_yes:last');
          var no_button = $('.popup_no:last');
          var popup = $('.popup:last');
    
          yes_button.click(function() {
            popup.html('<p>' + yes + '<a class="popup_ok" href="#">Ok.</a>');
          });
    
          no_button.click(function() {
            popup.html('<p>' + no + '<a class="popup_ok" href="#">Ok.</a>');
          });
        }
      </script>
    
      <style type="text/css">
      .popup {
        border:1px solid black;
        margin-bottom: 10px;
      }
      .popup a {
        margin:10px;
      }
      </style>
    </head>
    
    <body>
      <a href="#">Launch the popup!</a>
    </body>
    

    【讨论】:

    • 我刚试过,同样的问题仍然存在。我将弹出窗口的 ID 打印到弹出窗口中,停止居中并使其位置:相对,因此它们被放置在不同的行中。无论我按下哪个按钮,最后一个弹出窗口,只有最后一个会消失。
    • 我在原始答案中添加了代码,以向您展示我的意思。使用 ID 不起作用,因为正如 slebetman 所指出的,每个 ID 都必须是唯一的。事实证明,这里不需要 ID,因此只需将它们更改为类即可。
    • 好吧,我仍然无法弄清楚我做错了什么。呵呵。这里的解决方案是我正在寻找的。必须对其进行一些修改,以便它仍然可以接受传递是和否的函数。我已经将这个的固定版本添加到我的帖子中,供任何想要它的人使用。谢谢队友
    • 我想传递函数的原因是因为我将使用弹出窗口来不仅仅是显示这样的答案。你的建议是有道理的(如果这是它的唯一目的,它会使脚本更有效率),但我也计划将它用于其他东西。为什么,我还不太确定。但我想保持你的选择开放总是好的。此外,它很好玩。
    • 叹息 - 在进一步摆弄它之后,我仍然得到错误。在您的示例中,字符串被集中然后发送到函数。我们现在知道 num1 + num2 的值。但是,我所做的是对于 yes 函数,我输入了 $('body').append('its '+num3); (其中 num3 只是 num1+num2,在此 fn 内计算)。因此,当我创建一个新的弹出窗口而不回答第一个是或否时,num1 和 num2 的值会发生变化。然后当我在第一个弹出窗口上单击“是”时,它使用新的 num1 和 num2 的值,而不是旧的值..
    【解决方案2】:

    我看到您一直在文档中添加一个 div,其中 id=popup 以及许多其他带有硬编码 ID 的内容。在 HTML 中,ID 在整个文档中必须是唯一的,并且特定的 ID(例如“弹出窗口”)必须仅出现 一次。当两个元素共享同一个 ID 并且浏览器可以返回浏览器的开发人员认为的任何内容时会发生什么。

    所以您的查询 $('#popup:last') 并没有达到您认为的意思。

    在这种情况下,常规的 DOM 方法比 jQuery-ism 工作得更好:

    // shortcut. I hate typing document...
    function newElement (tag, spec) {
        var el = document.createElement(tag);
        for (var n in spec) {
            el[n] = spec[n];
        }
        return el;
    } 
    
    function popup_AskYN(msg,yes_fn,no_fn){
        // because we get the references directly we don't need to
        // assign ids and therefore avoid id collisions:
    
        var popup = $(newElement('div')).append($(newElement('p')).append(msg));
        var yes_button = $(newElement('a',{href:'#'})).append('Yes!');
        var no_button = $(newElement('a',{href:'#'})).append('No.');
    
        popup.append(yes_button).append(no_button);
        popup.center();
    
        yes_button.click(yes_fn);
        no_button.click(no_fn);
    
        yes_button.click(function(){
            popup.fadeOut('fast').remove();
        });
        no_button.click(function(){
            popup.fadeOut('fast').remove();
        });
    
        $('body').append(popup);
    }
    

    【讨论】:

    • 啊...抱歉,忘记添加$('body').append(popup)
    【解决方案3】:

    您可以使用现有弹出窗口的数量创建唯一标识符。

    var popupId =  $("#popup").size();
    

    然后使用 id 创建新的弹出窗口并为按钮引用它。

    $('body').append("<div id='" + popupId + "'><p>"+msg+"</p><a id='popup_ok' href='#'>Ok.</a></div>");
    

    【讨论】:

    • 但我已经创建并删除了弹出窗口。所以它们的数量会发生变化。
    • 存储并增加一个值然后... var id = $("body").data(popupID); $("body").data(popupID, id++);
    • 我已将我现在所拥有的内容添加到我的第一篇文章中。当有多个弹出窗口时,按钮仍然会塞满。每当我单击按钮时,它似乎正在做的是使用选择器的 popup_AskYNId 的当前值。我知道这一点是因为当我有 2 个弹出窗口时,弹出窗口 2 可以正常工作,但不是 1。当我有 5 个时,5 可以正常工作,但其他人则不行。
    猜你喜欢
    • 2016-04-30
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2020-12-24
    • 2013-10-26
    • 2016-01-09
    • 2018-09-19
    相关资源
    最近更新 更多