javascript onChange event does not work in IE

R

rick

The following basic script works fine in firefox by not in IE. Can anyone
spot the problem? In IE I can only delete the first line but not the lines
created by javascript. Also, look at the HTML code for the first line
(click the Table HTML button:)) you will fine that the code displayed is not
the same as
was written. "onChange" was changed to "onchange" etc. Please help.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1250">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>testing tables</title>
<script type="text/javascript">
<!-- Begin Add Row to Itemlist Table
function addRowToTable(){
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
var row = tbl.insertRow(lastRow);

// qty cell
var qty2 = row.insertCell(0);
var el_qty = document.createElement('input');
el_qty.setAttribute('type', 'text');
el_qty.setAttribute('name', 'qty');
el_qty.setAttribute('size', '7');
el_qty.setAttribute('maxlength', '7');
el_qty.setAttribute('onChange', 'calc_total()');
qty2.appendChild(el_qty);

// price cell
var price2 = row.insertCell(1);
var el_price = document.createElement('input');
el_price.setAttribute('type', 'text');
el_price.setAttribute('name', 'cost');
el_price.setAttribute('size', '7');
el_price.setAttribute('maxlength', '7');
el_price.setAttribute('onChange', 'calc_total()');
price2.appendChild(el_price);

// remove me cell
var D = row.insertCell(2);
//D.innerHTML='<a href="javascript:removeRowFromTable(this)">-</a>'
D.setAttribute('onClick','removeRowFromTable(this)');
var el_txt = document.createTextNode("-");
D.appendChild(el_txt);
}
//
function getRowIndex (cell) {
return document.all ? cell.parentElement.rowIndex :
cell.parentNode.rowIndex;
}

//Remove a row from the table
function removeRowFromTable(cell){
//alert ("start function");
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
//alert (lastRow);
var rowToDelete = getRowIndex(cell);
//alert (rowToDelete);
if (lastRow > 2) tbl.deleteRow(rowToDelete);
}

// Calculate the total
function calc_total() {
//Do Nothing yet
}
function showtableinnerhtml(){
alert(document.getElementById('itemlist').innerHTML);
}
//-->
</script>
</head>
<body>
<form name="myform" method="post" action="myform.php">
<table id="itemlist" border="1">
<tr><th>Qty</th><th>Cost</th><th>-</th></tr>
<tr>
<td>
<input type="text" name="qty" size="7" maxlength="7"
onChange="calc_total()">
</td>
<td>
<input type="text" name="cost" size="7" maxlength="7"
onChange="calc_total()">
</td>
<td onClick="removeRowFromTable(this)">-</td>
</tr>
</table>
<hr>
<table id="totalcost" border="1">
<tr>
<td>
<input type="text" size="7" name="test" readonly>
</td>
<td>
<input type="text" size="7" name="total" readonly>
</td>
</tr>
</table>
<input type="button" value="TableHTML" onclick="showtableinnerhtml()">
<input type="button" value="Add" onclick="addRowToTable();">
</form>
</body>
</html>
 
L

Lasse Reichstein Nielsen

rick said:
The following basic script works fine in firefox by not in IE. Can anyone
spot the problem?

A guess:
function addRowToTable(){
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
var row = tbl.insertRow(lastRow);

// qty cell
var qty2 = row.insertCell(0);
var el_qty = document.createElement('input');
el_qty.setAttribute('type', 'text');

IE doesn't translate values set with setAttribute to operative values.
To make it work in IE, you should write
el_qty.type = "text";
It should also work for modern browsers, as long as the property is
part of the W3C DOM 2 HTML specification.

My guess at what goes wrong is that ...
D.setAttribute('onClick','removeRowFromTable(this)');

... it will definitly not recognize this one. Use this instead:
---
D.onclick = function(){removeRowFromTable(this);};
---
function getRowIndex (cell) {
return document.all ? cell.parentElement.rowIndex :
cell.parentNode.rowIndex;

You are using the existence of document.all to decide whether to use
cell.parentElement or cell.parentNode. What about non-IE browsers that
has document.all but not cell.perentElement (I don't know if there are
any, but I don't know that there isn't either).

Just test for the property you need, with a fallback if it isn't there:
 
R

rick

Lasse Reichstein Nielsen said:
IE doesn't translate values set with setAttribute to operative values.
To make it work in IE, you should write
el_qty.type = "text";
It should also work for modern browsers, as long as the property is
part of the W3C DOM 2 HTML specification.
I tried it but it does not work....but no error is generated.
Your suggested code does not display when I hit the 'TableHTML' button
so I think the properties is not being assigned.
My guess at what goes wrong is that ...


.. it will definitly not recognize this one. Use this instead:
This does not work either same reason I think? below is the
modified sample that tried.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1250">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>testing tables</title>
<script type="text/javascript">
<!-- Begin Add Row to Itemlist Table
function addRowToTable(){
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
var row = tbl.insertRow(lastRow);

// qty cell
var qty2 = row.insertCell(0);
var el_qty = document.createElement('input');
el_qty.type = "text";
el_qty.setAttribute('name', 'qty');
el_qty.setAttribute('size', '7');
el_qty.setAttribute('maxlength', '7');
el_qty.onChange = function(){calc_total();};
qty2.appendChild(el_qty);

// price cell
var price2 = row.insertCell(1);
var el_price = document.createElement('input');
el_price.setAttribute('type', 'text');
el_price.setAttribute('name', 'cost');
el_price.setAttribute('size', '7');
el_price.setAttribute('maxlength', '7');
el_price.setAttribute('onChange', 'calc_total()');
price2.appendChild(el_price);

// remove me cell
var D = row.insertCell(2);
//D.innerHTML='<a href="javascript:removeRowFromTable(this)">-</a>'
D.onClick = function(){removeRowFromTable(this);};
var el_txt = document.createTextNode("-");
D.appendChild(el_txt);
}
//
function getRowIndex (cell) {
return (cell.parentElement || cell.parentNode).rowIndex;
}

//Remove a row from the table
function removeRowFromTable(cell){
alert ("start function");
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
//alert (lastRow);
var rowToDelete = getRowIndex(cell);
//alert (rowToDelete);
if (lastRow > 2) tbl.deleteRow(rowToDelete);
}

// Calculate the total
function calc_total() {
//Do Nothing yet
}
function showtableinnerhtml(){
alert(document.getElementById('itemlist').innerHTML);
}
//-->
</script>
</head>
<body>
<form name="myform" method="post" action="myform.php">
<table id="itemlist" border="1">
<tr><th>Qty</th><th>Cost</th><th>-</th></tr>
<tr>
<td>
<input type="text" name="qty" size="7" maxlength="7"
onChange="calc_total()">
</td>
<td>
<input type="text" name="cost" size="7" maxlength="7"
onChange="calc_total()">
</td>
<td onClick="removeRowFromTable(this)">-</td>
</tr>
</table>
<hr>
<table id="totalcost" border="1">
<tr>
<td>
<input type="text" size="7" name="test" readonly>
</td>
<td>
<input type="text" size="7" name="total" readonly>
</td>
</tr>
</table>
<input type="button" value="TableHTML" onclick="showtableinnerhtml()">
<input type="button" value="Add" onclick="addRowToTable();">
</form>
</body>
</html>
 
R

Richard Cornford

rick said:
"Lasse Reichstein Nielsen" wrote:
This does not work either same reason I think? below is the
modified sample that tried.
el_qty.onChange = function(){calc_total();};
<snip>

The attribute names for intrinsic events are case insensitive in HTML
but the corresponding DOM object property names are traditionally (and
mostly implemented as) all lower case. The above assignment would be
expected to create an - onChange - property and assign a reference to
the function to that property, but the function will not be called in
response to change events.

Richard.
 
D

DU

rick said:
I tried it but it does not work....but no error is generated.
Your suggested code does not display when I hit the 'TableHTML' button
so I think the properties is not being assigned.


This does not work either same reason I think? below is the
modified sample that tried.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1250">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>testing tables</title>
<script type="text/javascript">
<!-- Begin Add Row to Itemlist Table
function addRowToTable(){
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
var row = tbl.insertRow(lastRow);

I recommend you use meaningful, self-explanatory variable identifiers
which are distinct from usual names found in HTML for code
maintainability+reviewing purposes.

MSIE 6 has problems with insertRow (at least in a loop) but has no
problem with
var objTRow = tbl.createElement("tr");

otherwise, I would drop var lastRow = tbl.rows.length; and use

var objTRow = objTable.insertRow(-1);

"If index is -1 or equal to the number of rows, the new row is appended."
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-39872903
// qty cell
var qty2 = row.insertCell(0);

You may have to use

var qty2 = document.createElement("td");

instead. Again, using insertCell with MSIE 6 should not cause problems
(except maybe when you're dynamically creating and inserting in a loop).
var el_qty = document.createElement('input');
el_qty.type = "text";
el_qty.setAttribute('name', 'qty');

Just like Lasse told you, best is to always avoid the setAttribute
method when there is a better, more reliable and more efficient way to
assign an attribute a value. Peter-Paul Koch recommends the same thing too.
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-89658498

el_qty.setAttribute('size', '7');

e._qty.size = 7;
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-79659438
el_qty.setAttribute('maxlength', '7');

e._qty.maxLength = 7;
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-54719353
el_qty.onChange = function(){calc_total();};

el_qty.onchange = function(evt) {calc_total();};

qty2.appendChild(el_qty);

// price cell
var price2 = row.insertCell(1);

You may have to use

var price2 = document.createElement("td");

and then later append it to the table row object. That's how I proceeded
in a demo file because MSIE 6 was giving me problems. I did not have
problems with insertCell and insertRow with MSIE 6 as long as I did not
use these methods in a loop.

Dynamically creating, populating and inserting a table
http://www10.brinkster.com/doctorunclear/HTMLJavascriptCSS/CreatingTable.html
var el_price = document.createElement('input');
el_price.setAttribute('type', 'text');
el_price.setAttribute('name', 'cost');
el_price.setAttribute('size', '7');
el_price.setAttribute('maxlength', '7');
el_price.setAttribute('onChange', 'calc_total()');
price2.appendChild(el_price);

// remove me cell
var D = row.insertCell(2);
//D.innerHTML='<a href="javascript:removeRowFromTable(this)">-</a>'
D.onClick = function(){removeRowFromTable(this);};

Again, a better variable identifier can be chosen (instead of D) and
setting an event attribute value must be done differently as Lasse
explained.
var el_txt = document.createTextNode("-");
D.appendChild(el_txt);
}
//
function getRowIndex (cell) {
return (cell.parentElement || cell.parentNode).rowIndex;

Here, it would help your code efficiency a bit if you code use
offsetParent (or just parentNode) instead. Or even just use

objTableCell.parentNode.rowIndex

http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-67347567

}

//Remove a row from the table
function removeRowFromTable(cell){
alert ("start function");
var tbl = document.getElementById('itemlist');
var lastRow = tbl.rows.length;
//alert (lastRow);
var rowToDelete = getRowIndex(cell);

How about
var rowToDelete = cell.offsetParent;
and then drop the getRowIndex entirely. Also, if there are discrepancies
in the offsetParent, then there should not be for parentNode. The only
possible immediate parentNode for a table cell is a <tr> and parentNode
is supported by MSIE 5+. So,

rowToDelete = cell.parentNode;

has to be working in MSIE 5+ and all other W3C DOM Core compliant browsers.

I'm sure there could be an even more powerful, efficient way to do this.

Something like

onclick="document.getElementById('itemlist').deleteRow(this.parentNode.rowIndex);"

(not tested but it should work).
If this single instruction works, then you replace with it some 6 lines,
2 functions, 1 function call and 3 local variables.

DU
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top