tags:

views:

66

answers:

2

Hello. I have a question relative to this code. It should (and it does) display a list of items, where you can add and remove entries by clicking on the plus and minus.

<html><head><script src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
<script>
google.load("jquery", "1.3.2");

app={};
app.attachList = function() {        
        return {
            _current_id : 0,
            addFilterAfter : function(after_entry_id) {
                that = this;
                new_id = this._newId();
                jQuery("#entry_"+after_entry_id).after("<li id=\"entry_"
                                +new_id+"\"><a href=\"javascript:void(0);\" id=\"entry_"
                                +new_id+"_add\">(+)</a><a href=\"javascript:void(0);\">(-)</a> hello "
                                +new_id+"</li>"); 
                jQuery("#entry_"+new_id+"_add")
                      .bind("click", function() { 
                                     that.addFilterAfter(new_id); 
                                    }  
                           );
            },  
            show : function() {
                that = this;
                new_id = this._newId();
                jQuery("#list").children().remove();
                jQuery("#list").append("<li id=\"entry_"
                         +new_id+"\"><a href=\"javascript:void(0);\" id=\"entry_"
                         +new_id+"_add\">(+)</a> hello </li>");
                jQuery("#entry_"+new_id+"_add")
                         .bind("click", function() { 
                             alert(new_id); // HERE
                             that.addFilterAfter(new_id); 
                             }
                         );
            },  
            _newId : function() {
                this._current_id++;
                return this._current_id;
            },
        };
}       

app.main = function() { l = app.attachList(); l.show(); }
google.setOnLoadCallback(function() {  jQuery.noConflict(); jQuery(document).ready(app.main); });  
</script>
<ul id="list" /></ul>
</head>
</html>

My question is relative to what happens at the line marked HERE. Ideally, if I click the first item +, I would expect this code to continue adding just below the first item. This does not happen. It continues incrementing the new_id (as you can see from the alert) instead of keeping the original new_id it was granted.

Now, I have a suspect about what's going on, mostly involving the closure nature of javascript, but I want to hear it explained from someone more skilled.

As a side note, if I partition the logic for binding the event in a separate method, it works as expected... from this my suspect.

+4  A: 

The problem that is causing this behavior in your code is that you're missing the var statement when you assign a value to new_id.

In JavaScript when you make an assignment to an undeclared identifier (an identifier not reachable in the scope chain), it becomes global (window.new_id is created) and that's why it keeps incrementing.

CMS
ARGHHHHHHHHH! :D
Stefano Borini
thank you. I thought new_id was kept as a reference to this._current_id within the function. Instead, I was just referring to a damn global :). But then I don't understand why, when I isolated the bind() call in a different method routine, it worked correctly.
Stefano Borini
However, lesson learned. I won't forget `var` anymore in my javascript life.
Stefano Borini
A: 

This is just a quick response, but I'm wondering about the scope of the new_id variable you are using.

bn