I see Klaus posted a very clean solution, but just to help you understand what went wrong...
 
Pretend you are the _javascript_ interpreter, executing the code inside your click handler function after a click. You encounter the variable name "i" and need to find its value. Since "i" isn't defined in the innermost function, you look outside and find the "i" that was used as the loop variable in your outer function.
 
But the for loop has already finished executing at this point! What's the value of "i" after the for loop is done? 30.
 
If Klaus's solution didn't work for any reason, or if you ever need a solution that will work in any _javascript_ environment, you can simply wrap your code inside a function to capture the value of "i" each time through the loop:
 
    (function( i ) {
        $("##id_" + i).click(
            function(){
                foo(i,ConstantArgument);
            }
        );
    })( i );

Now when you pretend to be the _javascript_ interpreter and find a value for "i" in that inner foo() call, you'll find the "i" in this wrapper function - and that's a new "i" each time because this wrapper function get called separately each time through the loop.
 
It doesn't have to be an anonymous function - it's probably more readable to break it out as a separate named function. While we're at it, let me show you another way to write your code that builds the HTML string.
 
    function add( i ) {
        $('#MyContainerID').append([
            '<span id="id_', i, '" class="MyClass" value="', i, '">',
                i,
            '</span>'
        ].join(''));
        $('#id_' + i).click( function(){
            foo(i,ConstantArgument);
        });
    }
 
Call add(i) in your for loop and you are golden. Place the add() function definition inside the same function as the for loop, so it can pick up the constantArgument.
 
But watch out for page load time when you are setting up this many event handlers. I was doing this for a poup calendar widget, and the load time was noticeable on a slow machine. I ended up installing a single event handler for the entire calendar and doing my own hit testing on the click and other mouse events. It was more work, but it makes the calendar open faster.
 
(Note that none of the code above is tested! But it should be pretty close.)
 
-Mike


From: Christopher Jordan

I've got a function that builds several elements on a page with a certain class. I've successfully used jQuery to add mouseover and mouseout events to all the elements with that certain class, and it works beautifully. I couldn't be happier. :0)

So, now I need to add a click event to each of those elements. The trouble is, that not each of those click events will be exactly the same. Each will call the same function but with slightly different arguments (one constant and one variable). After playing with a couple of ideas on how to use jQuery to accomplish this, I ended up with the following:

... inside a JS for loop with a counter 'i' ...


    $("##MyContainerID").append("<span id=\"id_" + i + "\" class=\"MyClass\" value=\"" + i + "\">" + i + "</span>");
    $("##id_" + i).click(
        function(){
            foo(i,ConstantArgument);
        }
    );

... end loop ...

The loop creates each of these elements on the page and I was hoping it would then assign a click event to each element (made unique with the id), and this seemed to work. However when I click on each of the elements in turn I can see that they are each calling the function (foo) with the same arguments (30,40). While 40 is the constant argument and is correct, the other argument was supposed to range from 1 - 29 (the number of elements in this particular list).

I'm a bit confused I thought this should work. Can anyone shed any light on what I may be doing wrong? Is there a different approach i need to take? Is there a better jQueryie-type way to accomplish this task that will make life easier?
_______________________________________________
jQuery mailing list
[email protected]
http://jquery.com/discuss/

Reply via email to