jQuery / javaScript – click / onclick事件监听器尽管关闭但在循环内部无效

我和我的循环再次…我正在尝试在几个div运行for循环,每个div都在类“ tooltipBox ”中但具有不同的id 。 在每个div都有一个带有类“ tttFalloutOrder ”的输入文本字段。 我想在for循环中做的是在每个.tttFalloutOrder输入字段上附加一个click-event-listener。

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

 function installListener(elementId) { $( "div#" + elementId + " > .tttFalloutOrder" ).on("click", function() { alert("clicked on " + elementId); }); } function runSimulation() { alert("running simulation..."); $( "#lContent h2" ).html("Simulation in progress..."); var agents = $( "div.tooltipBox" ); var rFOs = $( ".rFO" ); var i, j = 0; for(i = 0, j = 0; i < agents.length, j  .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 complete"); } 

正如你所看到的,我正在使用一个闭包,甚至委派了将监听器附加到另一个函数的实际任务,在阅读了几个与循环中的事件监听器相关的SO-Answer之后,这将有所帮助……尽管我真的不喜欢我们完全可以看出这会有什么不同。 无论如何,点击听众仍然不会开火,坦率地说我不明白这是什么 – 或者说什么不是 – 发生在这里。

提前谢谢 – 你们这些人总是找到一种方法,让像我这样的不知名的灵魂指向正确的方向,我真的很感激。

更新案例由于我自己的愚蠢而关闭……首先,是的,我有一个未定义的成员坐在我的installListener()函数中。 其次,jQuery选择器$( "div#" + elementId + " > .tttFalloutOrder" )返回undefined,因为>运算符选择第二个元素,它将第一个元素作为直接父元素。 但是,由于.tttFalloutOrder是一个位于

标签内的输入字段,情况并非如此……

我现在废弃了函数installListener()并使用以下代码解决了该问题:

 function runSimulation() { alert("running simulation..."); $( "#lContent h2" ).html("Simulation in progress..."); var agents = $( "div.tooltipBox" ); var rFOs = $( ".rFO" ); var waitUntilEvaluate = 0; var i, j = 0; for(i = 0, j = 0; i < agents.length, j  div.offlineCover").fadeIn(500); }, ttl*1000); waitUntilEvaluate = waitUntilEvaluate + ttl * 1000; })(i, ttl); } } console.log(waitUntilEvaluate); setTimeout(function() { $( "#lContent h2" ).html("Simulation complete"); evaluate(); }, waitUntilEvaluate); } 

您会发现使用jQuery.each()而不是for()循环更容易。 .each()回调函数将自动捕获您需要的var,因此不需要创建另一个内部闭包。

阻止Click处理程序工作的最可能的事情是listenerKind 。 如果不存在此类成员,则将引发错误并且事件线程将死亡。

您最大的问题是知道何时将“进行中”消息更改为“完成”。 就目前而言,消息将立即更改回来,而无需等待任何setTimeout完成,更不用说所有这些了。

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

 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 in progress..."); $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 complete");//Signify complete when all parts are complete } }, ttl*1000); }); } 

未经测试

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

还有其他方法可以做这种事情,特别是利用Deferreds / promises和jQuery.when() ,但上面的代码(适当调试)应该足够了。