By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
437,600 Members | 1,887 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 437,600 IT Pros & Developers. It's quick & easy.

Question: How to force a function to use the value of a variable when it's given rather than the current value of it

P: n/a
OK, this is kind of hard to explain, so I'll do my best:
I have a form where I have a row where there could be multiple entries,
so I have a link where it will dynamically add another row like it, and
this can happen as many times as you click on the link. This row
consists of 2 drop-down boxes. Depending on the selection of the first
drop-down box, the second drop-down box is either disabled or enabled.
The problem is on these dynamically created rows. Here is the code for
the dynamically created first drop-down:

var cell = row.insertCell(0);
var elSelect = document.createElement('select');
elSelect.setAttribute('name','country[' + regionNumber + ']');
elSelect.setAttribute('id','country[' + regionNumber + ']');
elSelect.setAttribute('onchange','changeCountry(re gionNumber)');

regionNumber is a variable that gets 1 added to it every time this
function runs.
As you can see, there is an onchange event handler. The problem is if I
make the onchange occur, it uses the current value of regionNumber, but
I want it to use the value that regionNumber was when that setAttribute
code ran.
Can anyone help me? If I need to further explain, please tell me so.

Sep 28 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
ASM
joltman a écrit :

regionNumber is a variable that gets 1 added to it every time this
function runs.
As you can see, there is an onchange event handler. The problem is if I
make the onchange occur, it uses the current value of regionNumber, but
I want it to use the value that regionNumber was when that setAttribute
code ran.
Can anyone help me? If I need to further explain, please tell me so.


var cell = row.insertCell(0);
var elSelect = document.createElement('select');

I ask myself if it wouldn't be better this way :

elSelect.setAttribute('name',country[regionNumber]);
elSelect.setAttribute('id',country[regionNumber]);
elSelect.setAttribute('onchange','changeCountry('+ regionNumber+')');

or
var selName = country[regionNumber];
elSelect.setAttribute('name',selName);
elSelect.setAttribute('id',selName);
elSelect.onchange = 'changeCountry('+regionNumber+');';
--
Stephane Moriaux et son [moins] vieux Mac
Sep 28 '05 #2

P: n/a
joltman wrote:
OK, this is kind of hard to explain, so I'll do my best:
I have a form where I have a row where there could be multiple entries,
so I have a link where it will dynamically add another row like it, and
this can happen as many times as you click on the link. This row
consists of 2 drop-down boxes. Depending on the selection of the first
drop-down box, the second drop-down box is either disabled or enabled.
The problem is on these dynamically created rows. Here is the code for
the dynamically created first drop-down:

var cell = row.insertCell(0);
var elSelect = document.createElement('select');
elSelect.setAttribute('name','country[' + regionNumber + ']');
elSelect.setAttribute('id','country[' + regionNumber + ']');
elSelect.setAttribute('onchange','changeCountry(re gionNumber)');

regionNumber is a variable that gets 1 added to it every time this
function runs.
As you can see, there is an onchange event handler. The problem is if I
make the onchange occur, it uses the current value of regionNumber, but
I want it to use the value that regionNumber was when that setAttribute
code ran.
Can anyone help me? If I need to further explain, please tell me so.


What you have discovered are closures, there is an article on them here:

<URL:http://www.jibbering.com/faq/faq_notes/closures.html>

Essentially what is happening is that regionNumber in the onclick event
keeps a reference back to regionNumber in the function rather than
inserting the value.

You can 'fix' the issue by getting the regionNumber from the element id,
or by adding the onclick outside the scope of the current function:

elSelect.name = 'country[' + regionNumber + ']';
addOnchange(elSelect, regionNumber);
...

and addChange() goes something like:

function addChange(el, n)
{
el.onchange = function() {changeCountry(n);};
}
I don't pretend to fully understand closures, but below is an example of
how they work. addTable() uses a loop to create some rows in a table
using a counter 'i'.

'i' is used to generate a unique ID for each row, but also in an
anonymous function attached to the onclick attribute. When setting the
value of the ID attribute, the value of i is appended to the ID and
'sticks'. But when it is used in the anonymous function, it retains its
reference back to the original i in the addTable() function.

You can 'fix' this by adding the anonymous function outside the scope of
the addTable() function - addTable2() (which is virtually identical to
addTable()) does that by using the addClick() function. It passes an
element reference and the value of i which is then taken beyond the
scope of the original addTable2() function.

The addClick adds a function that is identical to the one added by
addTable(), but the scope of i is different.

There are probably better ways to do this.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Closure demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<style type="text/css">

..tRed { border: 1px solid red;}
..tBlue {border: 1px solid blue;}

</style>
<script type="text/javascript">

function addTable(elID)
{
var el = document.getElementById(elID);
if ( !el ) return;

var oTable = document.createElement('table');
var oTbody = document.createElement('tbody');
var oTR, oTD;
for (var i=0; i<3; i++ ){
oTR = document.createElement('tr');
oTD = document.createElement('td');
oTD.id = 'cell-' + i;
oTD.onclick = function() {
alert('The id is ' + this.id
+ '\nthe value of i is ' + i);
};
oTD.appendChild(document.createTextNode(oTD.id));
oTR.appendChild(oTD);
oTbody.appendChild(oTR);
}
oTable.className = 'tRed';
oTable.appendChild(oTbody);
el.appendChild(oTable);
}

function addTable2(elID)
{
var el = document.getElementById(elID);
if ( !el ) return;

var oTable = document.createElement('table');
var oTbody = document.createElement('tbody');
var oTR, oTD;
for (var i=0; i<3; i++ ){
oTR = document.createElement('tr');
oTD = document.createElement('td');
oTD.id = 'cell-' + i;
addClick(oTD, i);
oTD.appendChild(document.createTextNode(oTD.id));
oTR.appendChild(oTD);
oTbody.appendChild(oTR);
}
oTable.className = 'tBlue';
oTable.appendChild(oTbody);
el.appendChild(oTable);
}

function addClick( el, i)
{
el.onclick = function() {
alert('The id is ' + this.id
+ '\nthe value of i is ' + i);
};
}

</script>
</head>
<body>
<input type="button" value="Add table red" onclick="
addTable('xx');
">
<input type="button" value="Add table 2 blue" onclick="
addTable2('xx');
">

</div>
<div id="xx"></div>

</body></html>

--
Rob
Sep 29 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.