[jQuery] I need help with the jQuery .click event

[jQuery] I need help with the jQuery .click event

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=us-ascii">
<META content="MSHTML 6.00.2900.2963" name=GENERATOR></HEAD>
<BODY text=#000000 bgColor=#ffffff>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>I see Klaus posted a very clean solution, but just to help
you understand what went wrong...</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>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.</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>But the for loop has already finished executing at this
point! What's the value of "i" after the for loop is done?
30.</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>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:</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><FONT face="Courier New" color=#000000>   
(function( i ) {<BR>        $("##id_" +
i).click(<BR>           
function(){<BR>       
       
foo(i,ConstantArgument);<BR>   
        }<BR>   
    );<BR>    })( i
);</FONT><BR></FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>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.</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2> </DIV></FONT></SPAN>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>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.</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><FONT face="Courier New" color=#000000>   
function add( i ) {<BR>       
$('#MyContainerID').append([</FONT></FONT></SPAN></FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><FONT face="Courier New"
color=#000000>           
'<span id="id_', i, '" class="MyClass" value="', i,
'">',</FONT></FONT></SPAN></FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><FONT face="Courier New"
color=#000000>              
 i,</FONT></FONT></SPAN></FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><FONT face="Courier New"
color=#000000>            '</span>'</FONT></FONT></SPAN></FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2><FONT face="Courier New"
color=#000000>       
].join(''));<BR>        $('#id_' + i).click(
function(){<BR>           
foo(i,ConstantArgument);<BR>        });<BR>   
}</FONT></DIV></FONT></SPAN></FONT></SPAN>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>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.</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>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.</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2></FONT></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>(Note that none of the code above is tested! But it should
be pretty close.)</FONT></SPAN></DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006></SPAN> </DIV>
<DIV dir=ltr align=left><SPAN class=468423920-25102006><FONT face=Verdana
color=#0000ff size=2>-Mike</FONT></SPAN></DIV><BR>
<BLOCKQUOTE
style="PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #0000ff 2px solid; MARGIN-RIGHT: 0px">
<DIV class=OutlookMessageHeader lang=en-us dir=ltr align=left>
<HR tabIndex=-1>
<FONT face=Tahoma size=2><B>From:</B> Christopher Jordan<BR></FONT></DIV><FONT
size=-1><FONT face="Courier New, Courier, monospace"><BR>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)<BR><BR>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:<BR><BR>... inside a JS for
loop with a counter 'i' ...<BR><BR><BR>   
$("##MyContainerID").append("<span id=\"id_" + i + "\" class=\"MyClass\"
value=\"" + i + "\">" + i + "</span>");<BR>   
$("##id_" + i).click(<BR>       
function(){<BR>           
foo(i,ConstantArgument);<BR>       
}<BR>    );<BR><BR>... end loop ...<BR><BR>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).<BR><BR>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?</BLOCKQUOTE></FONT></FONT></BODY></HTML>
_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/