dynamically adding a row to a table (portability issue)

S

Scott

Hi all,

The following Javascript to dynamically add a row to a table works
fine on IE, but I am not able to find a way to make it work on Firefox
(v3.5.5).

My problem is that childNodes[0].type is undefined for the <select>
element. (So the newly added row has a default value of "United
States" instead of "India".) I added a “case” to catch undefined & set
selectedIndex=0, but it didn’t work.

Any suggestions would be muchly appreciated?

Scott. :)

<HTML>
<HEAD>
<TITLE> Add dynamic rows in HTML table </TITLE>
<SCRIPT language="javascript">
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;

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

var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[0].cells.innerHTML;
switch(newcell.childNodes[0].type) {
case "text":
newcell.childNodes[0].value = "";
break;
case "checkbox":
newcell.childNodes[0].checked = false;
break;
case "select-one":
alert("This doesn't appears on Firefox!");
newcell.childNodes[0].selectedIndex = 0;
break;
}
}
}
</SCRIPT>
</HEAD>
<BODY>
<INPUT type="button" value="Add Row" onclick="addRow('dataTable')" />
<TABLE id="dataTable" width="350px" border="1">
<TR>
<TD><INPUT type="checkbox" name="chk"/></TD>
<TD><INPUT type="text" name="txt"/></TD>
<TD>
<SELECT name="country">
<OPTION value="in">India</OPTION>
<OPTION value="de">Germany</OPTION>

<OPTION value="fr">France</OPTION>
<OPTION value="us" selected>United States</OPTION>
<OPTION value="ch">Switzerland</OPTION>
</SELECT>
</TD>
</TR>
</TABLE>

</BODY>
</HTML>
 
T

Thomas 'PointedEars' Lahn

Scott said:
The following Javascript to dynamically add a row to a table works
fine on IE, but I am not able to find a way to make it work on Firefox
(v3.5.5).

Once you stopped thinking in terms of different browsers and start thinking
in terms of different layout engines, you will understand a lot better what
really happens when working with the client-side DOM.
My problem is that childNodes[0].type is undefined for the <select>
element. (So the newly added row has a default value of "United
States" instead of "India".) I added a “case†to catch undefined & set
selectedIndex=0, but it didn’t work.

"Does not work" is a useless error description. [psf 4.11]

Any suggestions would be muchly appreciated?

<http://www.catb.org/~esr/faqs/smart-questions.html>

I do not know if you appreciate any suggestion, however here is one:

You have not considered white-space text nodes; you are most certainly
accessing one with childNodes[0] in a Gecko-based browser, and such objects
do not have a built-in `type' property (as a result, the value retrieved is
`undefined' which causes your script to "not work"). MSHTML silently
discards white-space text nodes occasionally (there really seems to be no
pattern), while other layout engines do not. Often discussed, often
resolved before. See above.

Your markup also is far from being Valid, which does not bode well for your
script code to work reliably in the first place. (Also not news here.)

Evidently now, you have taken the fourth step in the Web development
learning curve (DOM Scripting) before the first one (HTML); a recipe for
disaster.

<http://validator.w3.org/>


PointedEars
 
R

RobG

Hi all,

The following Javascript to dynamically add a row to a table works
fine on IE, but I am not able to find a way to make it work on Firefox
(v3.5.5).

My problem is that childNodes[0].type is undefined for the <select>
element.

As Thomas said - it is likely a text node, not an element, and does
not hav a type property.

(So the newly added row has a default value of "United
States" instead of "India".) I added a “case” to catch undefined & set
selectedIndex=0, but it didn’t work.

Better to address the cause than the symptoms.

Any suggestions would be muchly appreciated?

Scott. :)

<HTML>
<HEAD>
<TITLE> Add dynamic rows in HTML table </TITLE>
<SCRIPT language="javascript">

The language attribute has been deprecated long ago, type is required:

function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);

If you want to add a new row as the last row, you can use:

var row = table.insertRow(-1);

var colCount = table.rows[0].cells.length;

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

var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[0].cells.innerHTML;
switch(newcell.childNodes[0].type) {
case "text":
newcell.childNodes[0].value = "";
break;
case "checkbox":
newcell.childNodes[0].checked = false;
break;
case "select-one":
alert("This doesn't appears on Firefox!");
newcell.childNodes[0].selectedIndex = 0;
break;
}
}
}


Consider instead cloning the row, iterating over the cells and
updating the internals using a function that recurses over the child
nodes, e.g.

<script type="text/javascript">

function addRow(tableID) {

var table = document.getElementById(tableID),
lastRow = table.rows[table.rows.length - 1];
row = table.rows[0].cloneNode(true),
cells = row.cells;

for (var i=0, iLen=cells.length; i<iLen; i++) {
updateCell(cells);
}

lastRow.parentNode.appendChild(row);
}


function updateCell(cell) {

var nodes = cell.childNodes,
node,
nodeType;

for (var i=0, iLen=nodes.length; i<iLen; i++) {
node = nodes;
nodeType = node.type;

if (node.childNodes) {
updateCell(node);
}

switch (nodeType) {

case "text":
node.value = "";
break;

case "checkbox":
node.checked = false;
break;

case "select-one":
node.selectedIndex = 0;
break;
}
}
}
</script>
<div>
<input type="button" value="Add Row" onclick="addRow('dataTable')">
</div>
<table id="dataTable" width="350px" border="1">
<tr>
<td><input type="checkbox" name="chk">
<td><input type="text" name="txt">
<td><select name="country">
<option value="in">India
<option value="de">Germany
<option value="fr">France
<option value="us" selected>United States
<option value="ch">Switzerland
</select>
</table>
 
S

Scott

In the unlikely event that someone else is interested in this, here is
a solution:

Ignore whitespace nodes by applying the switch statement to ALL the
child nodes:

for (var j = 0; j < newcell.childNodes.length; j++)
{
switch (newcell.childNodes[j].type) {
case "text":
.....
}

Scott. :)
 
T

Thomas 'PointedEars' Lahn

Scott said:
In the unlikely event that someone else is interested in this, here is
a solution:

Ignore whitespace nodes by applying the switch statement to ALL the
child nodes:

you could simply remove the whitespace after the start tag, as in

<td><select ...>...

Or you could simply address the SELECT element by its name, as in

document.getElementsByName("country")[0]

or if the SELECT element would be descendant of a FORM element like it
should (for the form to degrade gracefully):

document.forms[...].elements["country"]

All of this is described in the FAQ of this newsgroup that I had referred
you to.
for (var j = 0; j < newcell.childNodes.length; j++)
{
switch (newcell.childNodes[j].type) {
case "text":
.....
}

What an unnecessary, inefficient piece of junk. Didn't I recommend that you
take step 1 first?


PointedEars
 
S

Scott

Consider instead cloning the row, iterating over the cells and
updating the internals using a function that recurses over the child
nodes

Even better!

Thanks Rob.

Scott. :)
 

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,765
Messages
2,569,568
Members
45,042
Latest member
icassiem

Latest Threads

Top