Confusing behavior setting up onclick handlers

G

garey

Hello -

I have the following function

function write_hdcp_select() {

var myDiv = document.getElementById("myDiv");

myDiv.innerHTML = "";
var title = document.createElement("h3");
title.appendChild(document.createTextNode("Select the number"));
myDiv.appendChild(title);


for(var i = 0;i < 10;i++) {

var nh = i;
var loc = "http://localhost/cgi-bin/myCgi.cgi?num_args=" + nh;

var but = document.createElement("button");
but.appendChild(document.createTextNode(nh));
but.onclick = function() {
window.location = loc; };
myDiv.appendChild(but);
}

}


The idea of the function is to generate a set of buttons, and when any
of the buttons is clicked, it calls a cgi with a numeric argument.
Debugging, I can see that loc contains the correct value before each
onclick assignment, and the buttons show up with the correct number
displayed. But every button's onclick handler ends up with the highest
numeric value as the argument to the CGI script. What's going on?

Any help appreciated;

Garey Mills
 
J

Joost Diepenmaat

garey said:
The idea of the function is to generate a set of buttons, and when any
of the buttons is clicked, it calls a cgi with a numeric argument.
Debugging, I can see that loc contains the correct value before each
onclick assignment, and the buttons show up with the correct number
displayed. But every button's onclick handler ends up with the highest
numeric value as the argument to the CGI script. What's going on?

you're creating a closure in the onclick assignment that refers to the
loc variable in the outer function. that loc variable's value will be 10
at the end of the for() loop.

you want to create an additional scope (function) to capture the value
at the time of assignment, like this:

(function (l) {
but.onclick = function() { window.location = l };
})(loc);

or

(function () {
var l = loc;
but.onclick = function() { window.location = l };
})();

Stylistically, I prefer the first version, I think the the second one is
little easier to read.
 
T

T.J. Crowder

Hello -

I have the following function

function write_hdcp_select() {

var myDiv = document.getElementById("myDiv");

myDiv.innerHTML = "";
var title = document.createElement("h3");
title.appendChild(document.createTextNode("Select the number"));
myDiv.appendChild(title);

for(var i = 0;i < 10;i++) {

var nh = i;
var loc = "http://localhost/cgi-bin/myCgi.cgi?num_args=" + nh;

var but = document.createElement("button");
but.appendChild(document.createTextNode(nh));
but.onclick = function() {
window.location = loc; };
myDiv.appendChild(but);
}

}

The idea of the function is to generate a set of buttons, and when any
of the buttons is clicked, it calls a cgi with a numeric argument.
Debugging, I can see that loc contains the correct value before each
onclick assignment, and the buttons show up with the correct number
displayed. But every button's onclick handler ends up with the highest
numeric value as the argument to the CGI script. What's going on?

Any help appreciated;

Garey Mills

Hi,

The function you're using for your onclick handler uses the value of
'loc' when it's *executed*, not when it's assigned to the onclick,
which is why the handlers are all using the highest value. (Yes, the
handler -- which is a "closure" -- really does keep a reference to
'loc' even after your write_hdcp_select() function returns.)

Closures can seem complicated at first, but they're actually quite
simple. I wrote up a reasonably thorough discussion of them last
month which may be helpful:
http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html

Hope this helps,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top