JavaScript / jQuery下拉列表更改事件,关闭不起作用

时间:2012-01-06 01:42:44

标签: javascript jquery closures

在我的示例代码中,我有2个下拉列表(但在实际代码中,数字因观察列表是动态创建而有所不同)而我想要做的是计算选择了多少下拉列表非零值即可。我使用闭包来跟踪具有非零选定值的下拉列表总数。我成功地做到了这一点(参考http://jsfiddle.net/annelagang/scxNp/9/)。

旧/工作代码

$("select[id*='ComboBox']").each(          
          function() {              
              $(this).change(
                  function() {
                      compute(this);
              });         
      });

    var compute = (function () {
    var total = 11; 
    var selectedDdl = [];

    $("#total").text(total);     
    return function (ctrl) {
         var id = $(ctrl).attr("id");
         var ddlMeal = document.getElementById(id);
         var found = jQuery.inArray(id, selectedDdl);

        if (ddlMeal.options[ddlMeal.selectedIndex].value != 0){
             if(found == -1){
                 total += 1; 
                 selectedDdl.push(id);        
             } 
             else{
                 total = total;
             }
         }
         else {
             total -= 1;
             var valueToRemove = id;
             selectedDdl = $.grep(selectedDdl, function(val) 
                                      { return val != valueToRemove; });
         }        

         $("#total").text(total); 
    };     
}());

注意:我用11初始化了总变量,因为正如我在实际代码中提到的,我可以有2个以上的下拉列表,我只想测试我的代码是否适用于2以上的值

当我尝试在.change()事件中转移闭包时,它不再有效(请参阅http://jsfiddle.net/annelagang/scxNp/12/)有人可以帮我解决这个问题吗?我一直在做这个代码几天了,而且变得非常令人沮丧。

新/非工作代码:

$("select[id*='ComboBox']").each(          
          function() {              
              $(this).change(
                  function() {
                     (function () {
                var total = 11; 
                var selectedDdl = [];

                $("#total").text(total);     
                return function (ctrl) {
                     var id = $(ctrl).attr("id");
                     var ddlMeal = document.getElementById(id);
                     var found = jQuery.inArray(id, selectedDdl);

                     if (ddlMeal.options[ddlMeal.selectedIndex].value != 0){
                         if(found == -1){
                             total += 1; 
                             selectedDdl.push(id);        
                         } 
                         else{
                             total = total;
                         }
                     }
                     else {
                         total -= 1;
                         var valueToRemove = id;
                         selectedDdl = $.grep(selectedDdl, function(val) 
                                           { return val != valueToRemove; });
                         }        
                    $("#total").text(total); 
                };     
        }());
          });         
      });

提前致谢。

P.S。我也愿意接受更简洁的解决方案。

3 个答案:

答案 0 :(得分:3)

问题

您正在从自执行匿名函数返回函数,但不在任何地方确定返回值。

简化您的代码,它看起来像是:

/* some code here */
$(this).click(function(){
    /** The following function is executed, returns result, but the
     *  result (a function) is not assigned to anything, nor returned
     */
    (function(){
        /* some code here */
        return function(ctrl){
            /* some code here */
        };
    }());
});
/* some code here */

解决方案

一般来说,您的代码非常难以理解,您应该为了自己的利益而改进它(并避免出现此类问题)。通过将参数传递给返回函数的函数(但没有调用它),可以快速解决上述问题。解决方案在这里:jsfiddle.net/scxNp/13/

解决方案:解释

我做的很简单 - 我发现你从第一个(工作)示例中将this传递给函数,但是你甚至没有在第二个(不正确的)示例中执行此函数。简化的解决方案如下所示:

/* some code here */
$(this).click(function(){
    /** Now the result of the following function is also executed, with
     *  parameter passed as in your working example
     */
    (function(){
        /* some code here */
        return function(ctrl){
            /* some code here */
        };
    }())(this);
});
/* some code here */

希望这是有道理的:)

聚苯乙烯。我还更新了我的第一个代码段,因此应该很容易发现更改:)

Ps.2。这只是一个 quickfix ,并且 - 如上所述 - 要使您的代码可读,还有很多工作要做。另外每个函数都用作闭包,所以不要过度使用你没有分配给任何东西的自执行(function(){/* your code */})();(它很有用,但是一个脚本应该足够一次)。而是使用现有的闭包

答案 1 :(得分:2)

我相信这应该有效:

$("select[id*='ComboBox']").change(function() {
    $("#total").text($("select[id*='ComboBox'][value!=0]").length);
});

http://jsfiddle.net/scxNp/15/

答案 2 :(得分:0)

怎么样?

HTML:

<select id="ComboBox1" class="howMany">
<option value="0">Value 0</option>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
<option value="3">Value 3</option>
</select>

<select id="ComboBox2" class="howMany">
<option value="0">Value 0</option>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
<option value="3">Value 3</option>
</select>

<div id="total"></div>

脚本:

$(".howMany").change(
function ()
{
    var nonZero = 0;
    $(".howMany").each(
        function ()
        {
            if ($(this).val() != '0')
                ++nonZero;
        }           
    );
    $("#total").text('There are '+nonZero+' options selected');       
}
);