Reputation: 1
I'm trying to add event handlers to a series of divs using a for loop. What should happen is that when I click a #containingThumbs div, its corresponding #content div should be displayed. At first, I ran into the issue where assigning event handlers in a for loop meant that no matter what #containingThumbs div I clicked, only the last #content div would appear.
I fixed that, by calling to an external function instead of defining one in the event handler itself, but now for some reason, all the event handlers on every #containingThumbs div fires as soon as the page is loaded. After that, clicking on the divs does nothing whatsoever.
Here's my HTML:
<div id="containingThumbs">
<div><img src="1.png"></div>
<div><img src="2.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
<div><img src="9.png"></div>
<div><img src="10.png"></div>
<div><img src="11.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
</div>
<div id="content">
<div><img src="1.png"></div>
<div><img src="2.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
<div><img src="9.png"></div>
<div><img src="10.png"></div>
<div><img src="11.png"></div>
<div><img src="3.png"></div>
<div><img src="4.png"></div>
<div><img src="5.png"></div>
<div><img src="6.png"></div>
<div><img src="7.png"></div>
<div><img src="8.png"></div>
</div>
and here's the relevant JS/JQuery code:
function expandDiv(j){
//first hide all content that is currently displayed, if any
$("#content div").css("display","none");
//then display only the right content div
$("#content div:nth-child("+j+")").css("display","inherit");
}
function makeInteractive(){
for (var i = 0;i<$("#containingThumbs").children().length;i++){
$("#containingThumbs").on("click","div",expandDiv(i));
}
}
Upvotes: 0
Views: 118
Reputation: 1074258
This line:
$("#containingThumbs").on("click","div",expandDiv(i));
calls expandDiv
and passes its return value into on
, exactly the way foo(bar())
calls bar
and passes the result into foo
. What you pass into on
should be a function reference.
Several ways to correct that code:
If you just want i
because you want to know which div was clicked, you don't need it; within the call to expandTab
, this
will refer to the DOM element for the div. So if you change expandTab
to use this
, you can just remove the (i)
after expandTab
:
function makeInteractive(){
for (var i = 0;i<$("#containingThumbs").children().length;i++){
$("#containingThumbs").on("click","div",expandTab);
// No (i) ---------------------------------------^
}
}
Again, you'd have to change expandTab
to use this
for the div.
You can pass i
using a closure:
function makeInteractive(){
for (var i = 0;i<$("#containingThumbs").children().length;i++){
$("#containingThumbs").on("click","div",makeHandler(i));
}
function makeHandler(index) {
return expandDiv(index);
}
}
That assumes expandTab
is expecting to see that index as its first argument, and isn't using the event object.
Or if you want to change expandDiv
a bit, you can handle it by having jQuery pass you the extra argument as event data:
function makeInteractive(){
for (var i = 0;i<$("#containingThumbs").children().length;i++){
$("#containingThumbs").on("click", "div", i, expandDiv);
// Note the `i` --------------------------^ ^--- no ()
}
}
expandDiv
would use event.data
as the index.
Upvotes: 2