I am having a small issue, and it would be very nice if some of you could realize about what kind of logic is missing here, since I cannot seem to find it:
I have an array with the results of some previous operation. Let's say that the array is:
var results = [0, 1];
And then I have a bunch of code where I create some buttons, and inside a for
loop I assign a different function to those buttons, depending on the position of the array. The problem is that for some reason, all the buttons created (two in this case) come out with the function assigned to the last value of the array (in this case, both would come out as one, instead of the first with 0 and the second with 1)
This is the code:
for (var i = 0; i < results.length; i++) {
var br2 = b.document.createElement("br");
var reslabel = b.document.createTextNode(Nom[results[i]].toString());
var card = document.createElement("input");
card.type = "button";
id = results[i]; // this is the problematic value.
card.onclick = newcard; // this function will use the above value.
card.value = "Show card";
divcontainer.appendChild(br2);
divcontainer.appendChild(reslabel);
divcontainer.appendChild(card);
}
As it is, this code produces as many buttons as elements in the array, each with its proper label (it retrieves labels from another array). Everything is totally fine. Then, I click the button. All the buttons should run the newcard
function. That function needs the id
variable, so in this case it should be:
- First button: runs
newcard
using variableid
with value 0 - Second button: runs
newcard
using variableid
with value 1
But both buttons run using id
as 1... why is that?
It might be very simple, or maybe is just that in my timezone is pretty late already :-) Anyways, I would appreciate any comment. I am learning a lot around here...
Thanks!
Edit to add the definition of newcard:
function newcard() {
id = id;
var toerase = window.document.getElementById("oldcard");
toerase.innerHTML = "";
generate();
}
the function generate
will generate some content using id
. Nothing wrong with it, it generates the content fine, is just that id
is always set to the last item in the array.
Answer
Your id
is a global variable, and when the loop ends it is set to the last value on the array. When the event handler code runs and asks for the value of id
, it will get that last value.
You need to create a closure to capture the current results[i]
and pass it along (this is a very common pitfal, see Javascript infamous Loop problem?). Since newcard
is very simple, and id
is actually used in generate
, you could modify generate
to take the id as a parameter. Then you won't need newcard
anymore, you can do this instead:
card.onclick = (function(id) {
return function() {
window.document.getElementById("oldcard").innerHTML = "";
generate(id);
};
}(results[i]));
What this does is define and immediately invoke a function that is passed the current results[i]
. It returns another function, which will be your actual onclick
handler. That function has access to the id
parameter of the outer function (that's called a closure). On each iteration of the loop, a new closure will be created, trapping each separate id
for its own use.
No comments:
Post a Comment