views:

541

answers:

4

Hi All,

I have a series of divs in a pattern of header/body, where a click on the header will show the body in question.

This all happens with .click initialized on page ready...

Rather than doing this (which works fine, but is a pain):

$('#show_fold_ping').click(function(){ ShowArea('#fold_ping') });
$('#show_fold_http').click(function(){ ShowArea('#fold_http') });
$('#show_fold_smtp').click(function(){ ShowArea('#fold_smtp') });
$('#show_fold_pop3').click(function(){ ShowArea('#fold_pop3') });
...

I am trying to do this:

var Areas = ['ping','http', 'smtp', 'pop3'];

for( var i in Areas ){
    Area = '#show_fold_'+Areas[i];
    $(Area).click(function(){ alert(Area); /* ShowArea(Area); */ });
}

The problem I'm having is that ALL of them seem to be initialized to the last one. IE: If pop3 is the last one, a click on #show_fold_[any] will alert '#show_fold_pop3'.

This seems like it should be really simple. Am I missing something obvious, or is there an issue with passing a string to jQuery that I don't know about?

Edit:

Hey, these are all great. I have read up a bit on closures and self-invoking functions, and (kindasorta) get it.

So far, I have this, but the click doesn't seem to be binding correctly. Area will alert with the correct value, but no click bind. Am I still having scope issues with Area, or am I just totally off mark?

$(function(){

 Areas = ['ping','http', 'smtp', 'pop3', 'imap', 'ftp', 'dns', 'tcp', 'database', 'seo'];

 for( var i = 0; i < Areas.length; i++ ){
  (function (Area) {
                            alert(Area);
   $("#show_fold_"+Area).click(function(){ alert('x'); });
  })(Areas[i]);
 }
});
+1  A: 

Check the scope of your "Area" variable. You're basically assigning a global variable so on the last iteration "Area" is scoped outside of the loop.

Typeoneerror
+2  A: 

It's a JavaScript thing; it's not jQuery related. What you're doing is creating a closure, but you're not understanding properly how they work.

You might want to read up on http://blog.morrisjohns.com/javascript_closures_for_dummies, especially Examples 5, 6, and 7.

Ben Alpert
A: 

be sure that you added the click event handling after the DOM has been loaded you can include this on the head element:

var Areas = ['ping','http', 'smtp', 'pop3'];

$(document)
        .ready(function() {
for (var Area in Areas)
{
Area = '#show_fold_'+Areas[i];
$(Area).click(function() { alert(Area); })
}
}
Marwan Aouida
You might want to edit that script. var Area in Areas and Area = ... + Areas[i]?
geowa4
+2  A: 

Yes, I have run into this problem all too often. Area is a global variable since it does not have var before it. Also, don't use a for...in construct.

But you might still run into a similar problem. God knows how many scripts I've debugged because of a similar bug. Doing the following guarantees proper scoping:

var Areas = ['ping','http', 'smtp', 'pop3'];

for( var i = 0; i < Areas.length; i++ ){
  (function(area) {
    $(area).click(function(){ alert(area); /* ShowArea(area); */ });
  })(Areas[i]);
}
geowa4