jQuery / javaScript - click / onclick事件侦听器不工作在循环内尽管关闭 [英] jQuery / javaScript - click / onclick event listener not working inside loop despite closure

查看:144
本文介绍了jQuery / javaScript - click / onclick事件侦听器不工作在循环内尽管关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我和我的循环...
我试图运行循环跨多个 div s,每个都在类 tooltipBox 中,但使用不同的 id 。在这些 div 中的每一个是具有类 tttFalloutOrder 的输入文本字段。我想在for循环中做的是在每个 .tttFalloutOrder 输入字段上附加一个点击事件监听器。

Me and my loops again... I'm trying to run a for loop across several divs, each being in the class "tooltipBox" but with different ids. In each of these divs is an input text field with class "tttFalloutOrder". What I want to do in the for loop is to attach a click-event-listener on each .tttFalloutOrder input field.

这是我的代码到目前为止:

This is my code so far:

function installListener(elementId) {
    $( "div#" + elementId + " > .tttFalloutOrder" ).on("click", function() {
        alert("clicked on " + elementId);
    });
}

function runSimulation() {
    alert("running simulation...");

    $( "#lContent h2" ).html("Simulation <b>in progress...</b>");

    var agents = $( "div.tooltipBox" );
    var rFOs = $( ".rFO" );

    var i, j = 0;

    for(i = 0, j = 0; i < agents.length, j < rFOs.length; i++, j++) {
        var ttl = rFOs[j].value;

        if((ttl == "undefined") || (ttl == "n")) {
            continue;
        } else {
            // function-factory als gscheite closure,
            // siehe http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
            // und http://stackoverflow.com/questions/3572480/please-explain-the-use-of-javascript-closures-in-loops?answertab=votes#tab-top
            (function(i, ttl) {
                var agentId = agents[i].id;

                installListener(agentId);

                /*
                $( "div#" + agentId + " > .tttFalloutOrder" ).on("change keypress paste focus textInput input", function() {
                    alert(agentId + "just got changed!");
                });
                */
                setTimeout(function() {
                    $("div#" + agentId + " > div.offlineCover").fadeIn(500);
                }, ttl*1000);
            })(i, ttl);
        }
    }
    $( "#lContent h2" ).html("Simulation <b>complete</b>");
}



如你所见,我使用了一个闭包,甚至委托实际任务将监听器附加到另一个函数,在阅读了几个与事件监听器相关的SO答案后,这将有助于...虽然我真的不太明白这将如何使任何差异。无论如何,点击听众仍然不会开火,坦白地说我不明白这里是什么 - 或者不是什么 - 发生在这里。

As you can see, I am using a closure and even delegated the actual task of attaching the listener to another function, after reading in several SO-answers related to event-listeners in loops that this would help...though I honestly don't quite see how that would make any difference. Anyway, the click listeners still won't fire and frankly I don't understand what is - or rather what is not - happening here.

提前感谢 - 你的人

更新 $ b $ b case关闭由于我自己的愚蠢...
首先,是的,我有一个未定义的成员坐在我的 installListener()函数。
其次,jQuery选择器 $(div#+ elementId +> .tttFalloutOrder)返回未定义,因为 ; 运算符选择第二个元素,它有第一个元素作为直接父类。然而,由于 .tttFalloutOrder 是位于< form> 标签内的输入字段,因此不是这样。 ..

Update Case closed due to my own stupidity... First off, yes, I had an undefined member sitting in my installListener() function. Second, the jQuery selector $( "div#" + elementId + " > .tttFalloutOrder" ) returned undefined, since the > operator selects the second element, which has the first element as a direct parent. However, since .tttFalloutOrder is an input field sitting inside a <form> tag, that is not the case...

我现在已废除函数 installListener(),并解决了以下代码的问题:

I now scrapped the function installListener() and solved the issue with the following code:

function runSimulation() {
    alert("running simulation...");

    $( "#lContent h2" ).html("Simulation <b>in progress...</b>");

    var agents = $( "div.tooltipBox" );
    var rFOs = $( ".rFO" );

    var waitUntilEvaluate = 0;

    var i, j = 0;

    for(i = 0, j = 0; i < agents.length, j < rFOs.length; i++, j++) {
        var ttl = rFOs[j].value;

        if((ttl == "undefined") || (ttl == "n")) {
            continue;
        } else {
            // function-factory als gscheite closure,
            // siehe http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
            // und http://stackoverflow.com/questions/3572480/please-explain-the-use-of-javascript-closures-in-loops?answertab=votes#tab-top
            (function(i, ttl) {
                var agentId = agents[i].id;

                $( "div#" + agentId + " .tttFalloutOrder" ).on("input", function() {
                    alert(agentId + "just got changed!");
                    $( "div#" + agentId + " .wasChanged" ).prop("checked", true);
                });

                setTimeout(function() {
                    $("div#" + agentId + " > div.offlineCover").fadeIn(500);
                }, ttl*1000);

                waitUntilEvaluate = waitUntilEvaluate + ttl * 1000;
            })(i, ttl);
        }
    }

    console.log(waitUntilEvaluate);
    setTimeout(function() {
        $( "#lContent h2" ).html("Simulation <b>complete</b>");
        evaluate();
    }, waitUntilEvaluate);
}


推荐答案

使用 jQuery.each()而不是 for()循环。 .each()回调函数会自动捕获你需要的var,所以没有必要再做另一个内部闭包。

You will find it easier to loop with jQuery.each() rather than for(). The .each() callback function will automatically trap the var you need, so there's no need to make another, inner closure.

阻止点击处理程序工作的最可能的事情是 listenerKind 。如果没有这样的成员,那么将抛出一个错误,并且事件线程将死。

The most likely thing that's preventing the click handler from working is listenerKind. If no such member exists, then an error will be thrown and the event thread will die.

你最大的问题是知道什么时候将进行中完成。因为它是,消息将立即改变回来,而不等待任何setTimeouts完成,更不用说所有的。

Your biggest issue is knowing when to change the "in progress" message to "complete". As it stands, the message will change back immediately without waiting for any of the setTimeouts to complete, let alone all of them.

就我个人而言,我会这样做(见代码中的评论):

Personally, I would do something like this (see comments in code) :

function runSimulation() {
    var $agents = $("div.tooltipBox"),
        $rFOs = $(".rFO"),
        $message = $("#lContent h2");
    if($agents.filter('.running').length > 0) {
        //Inhibit simulation if any part of an earlier simulation is still running.
        return;
    }
    $message.html("Simulation <b>in progress...</b>");
    $agents.each(function(i, agent) {
        var ttl, $agent;
        if(i >= $rFOs.length) {
            return false;//break out of .each()
        }
        ttl = Number($rFOs.eq(i).val());//Any failure to cast as Number will result in NaN.
        if(isNaN(ttl)) {
            return true;//continue with .each()
        }
        $agent = $(agent).addClass('running');//Provide a testable state (see below and above)
        $agent.children(".tttFalloutOrder").on('click.sim', function() {//Note: namespaced click event allows .off('click.sim') without affecting any other click handlers that might be attached.
            alert("click on " + $agent.attr('id'));
        });
        setTimeout(function() {
            $agent.children(".tttFalloutOrder").off('click.sim');//detach the handler attached with .on('click.sim') .
            $agent.removeClass('running').children(".offlineCover").fadeIn(500);
            if($agents.filter('.running').length == 0) {//if neither this nor any other agent is "running"
                $message.html("Simulation <b>complete</b>");//Signify complete when all parts are complete
            }
        }, ttl*1000);
    });
}

未经测试

如果点击操作仍然不起作用,那么我会怀疑 $ agent.children(。tttFalloutOrder)选择器不正确。

If it the click actions still don't work, then I would suspect the $agent.children(".tttFalloutOrder") selector to be incorrect.

有其他方法来处理这类事情,特别是利用Deferreds / promise和 jQuery.when(),但上述代码(适当调试)应该足够了。

There are other ways of doing this type of thing, notably ways that exploit Deferreds/promises and jQuery.when(), but the above code (suitably debugged) should suffice.

这篇关于jQuery / javaScript - click / onclick事件侦听器不工作在循环内尽管关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆