I've got an ajax call that collects XML, and based on that data creates a number of divs on which I attach click() jquery listeners. When clicked, I want those divs to call a function and to pass a parameter into that function. However, by the time the click is called the value of the parameter has changed. Here's an example from a jsfiddle I built to demonstrate the problem:
$(document).ready(function() {
function x() {
$.ajax({
type: "POST",
url: "/echo/xml/",
dataType: "xml",
data: {
xml: "<the>xml</the>"
},
success: function(xml) {
console.log('success');
$('#test').show();
var text = "CORRECT";
$('#test').click(function() {
insertText(text);
console.log(text);
});
text = "WRONG";
}
});
}
x();
});
function insertText(t) {
$('#test').html(t);
}
I want the text to show up as CORRECT, not WRONG.
I know this is a bit of a convoluted example but I'm trying to simulate my actual code as much as possible in terms of scope and what is going on. By the time the click()
function gets called based on a click, the value of text
has changed. Is there some way to 'bake' the value of text
into the click()
call at the time I create it? I'll be creating a number of these through a for
loop as it runs through the XML and don't want to hang on to all that data into variables for use later.
The easiest way is probably to create a function that attaches the handler. In this way, the parameter within the function is unchanged.
var text = "CORRECT";
bindClick("test", text);
// ...
function bindClick(id, text){
$('#' + id).click(function() {
insertText(text);
console.log(text);
});
}
Like this -- you bind it to a local variable in a closure form.
(function(text){
$('#test').click(function() {
insertText(text);
console.log(text);
});
})(text);
The click
function isn't called until after the text = "WRONG"
assignment gets called, so of course the function uses the "incorrect" value of text
. If you want to, as you say, bake the value of text
into your function at definition time, you can use an immediately-invoked anonymous function like so:
(function(bakedText) {
$('#test').click( function() {
insertText(bakedText);
console.log(bakedText);
}
})(text);
See demonstration here: http://jsfiddle.net/H4DpV/