开发者

basic jquery looping question around 'click'

Basic question, but I have been pounding my head for a bit so thought id bring it here.

html looks like this (edit, fixed the closing quotes)

<span class='deleteimage-119'>delete</span>
<span class='deleteimage-120'>开发者_Go百科;delete</span>
<span class='deleteimage-121'>delete</span>
<span class='deleteimage-122'>delete</span>
<span class='deleteimage-123'>delete</span>

javascript/jquery looks like this

iids = ['119','120','121','122','123'];
for (i=0; i<iids.length; i++) {
        place = iids[i];
        $(".deleteimage-" + place).click(function () {
                alert(place);
             });
    }

The click functionality gets attached to each individual span, but the alert after clicking just shows the last item in the array.


You have a scoping issue. By the time the callback fires, place has the last value from the loop.

You need to create a new variable for the closure; one variable per iteration, each of which will then be "caught" by the closure and used in the callback.

It would be nice if the solution were this:

var iids = ['119','120','121','122','123']; // don't forget `var` please
for (var i=0; i<iids.length; i++) {
   var place = iids[i]; // local variable?
   $(".deleteimage-" + place).click(function () {
       alert(place);
   });
}

Alas, Javascript has no block scope so there's still only one variable here called place, and it keeps getting updated as the loop runs.

So, you have to use a function instead:

var iids = ['119','120','121','122','123'];

function f(place) {
   // NOW `place` is a local variable.
   $(".deleteimage-" + place).click(function () {
       alert(place);
   });
}

for (var i=0; i<iids.length; i++) {
   f(iids[i]);
}

There are neater ways to employ this function approach using closures and bound variables, and the other answers cover those neater ways quite well. My answer has focused on explaining the issue.


The issue is with scopes and closure. In JS the scope is @ function level and not block level.

Try this:

var iids = ['119','120','121','122','123']; 
for (i=0; i<iids.length; i++) {         
    place = iids[i];
    var clickFn = function(a){
        return function(){
         alert(a);
        }
    }(place);
    $(".deleteimage-" + place).click(clickFn );     
} 


This is because the click is occurring after the loop is completed, so you're alerting place = iids[iids.length - 1]. In order to achieve the result you're looking for you need to create a function closure and pass place in as a parameter:

iids = ['119', '120', '121', '122', '123'];
for (i = 0; i < iids.length; i++) {
    place = iids[i];
    (function(_place) {
        $(".deleteimage-" + _place).click(function() {
            alert(_place);
        });
    } (place));
}


Inside the loop, you are binding the click event to those span, but the events are fired only after the loop is complete. So, it will always show the last value.


As others have mentioned, you have a scoping issue. Unless all of those classes have a unique meaning, I'd move the place value to a data attribute and leave deleteimage as the class name. Something like:

<span class='deleteimage' data-place='119'>delete</span>
<span class='deleteimage' data-place='120'>delete</span>
<span class='deleteimage' data-place='121'>delete</span>
<span class='deleteimage' data-place='122'>delete</span>
<span class='deleteimage' data-place='123'>delete</span>

$(".deleteimage").click(function() {
    var place = $(this).data("place");
    alert(place);
});

If the place values aren't unique values, then this answer doesn't apply.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜