Netscape and IE show different number of child nodes for table?

K

kaeli

Can anyone explain this to me? It's driving me insane.

Save this and run it in IE or Opera and then in Mozilla or Netscape 6+.
In IE/Opera, I get the expected 4 alerts.
In Mozilla/Netscape, I get *9*.
In the example table, there are 4 rows with 4 columns each in the tbody.
I'd expect 4 child nodes for the table body with 4 children each. I get
those 4 plus 5 [object Text] alerts in Mozilla/Netscape. I get only
those 4 in IE and Opera. Note that trying to alert the innerHTML shows
null for the Text objects.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title> New Document </title>
<script type="text/javascript">
function checkIt()
{
if (! document.getElementById)
{
alert("Sorry, your browser doesn't support this.");
return;
}

var T = document.getElementById("tb");
for (var i=0; i<T.childNodes.length; i++)
{
alert(T.childNodes);
}
return;
}
</script>

</head>

<body>
<table id="t1" border="1" cellpadding="5" cellspacing="0">
<tbody id="tb">
<tr>
<td><p>R1 C1</p></td>
<td><p>R1 C2</p></td>
<td><p>R1 C3</p></td>
<td><p>R1 C4</p></td>
</tr>
<tr>
<td><p>R2 C1</p></td>
<td><p>R2 C2</p></td>
<td><p>R2 C3</p></td>
<td><p>R2 C4</p></td>
</tr>
<tr>
<td><p>R3 C1</p></td>
<td><p>R3 C2</p></td>
<td><p>R3 C3</p></td>
<td><p>R3 C4</p></td>
</tr>
<tr>
<td><p>R4 C1</p></td>
<td><p>R4 C2</p></td>
<td><p>R4 C3</p></td>
<td><p>R4 C4</p></td>
</tr>
</tbody>
</table>
<form id="f1" name="f1">
<input type="button" name="b1" value="Try It" onClick="checkIt()">
</form>

</body>
</html>

--
 
M

Martin Honnen

kaeli said:
Can anyone explain this to me? It's driving me insane.

Let's try to save you from insanity then. Your test is already showing
you the difference the browsers have.

In IE/Opera, I get the expected 4 alerts.
In Mozilla/Netscape, I get *9*.
In the example table, there are 4 rows with 4 columns each in the tbody.
I'd expect 4 child nodes for the table body with 4 children each. I get
those 4 plus 5 [object Text] alerts in Mozilla/Netscape. I get only
those 4 in IE and Opera. Note that trying to alert the innerHTML shows
null for the Text objects.

If you have your markup as below then
<tbody id="tb">
here the first child of the <tbody> element you have a text node with
white space with a line break which Opera and Mozilla/Netscape model in
the DOM
<tr>
<td><p>R1 C1</p></td>
<td><p>R1 C2</p></td>
<td><p>R1 C3</p></td>
<td><p>R1 C4</p></td>
</tr>

Here is the next child text node with white space, a line break.

IE ignores those white space text nodes which most authors insert to
have their markup more readable e.g. you have written
<tbody>
<tr>
and not
<tbody><tr>
If you wrote all markup without white space between tags Mozilla, Opera
and IE would give you the same result for the child nodes.

The example doesn't show what you want to do, if you are looking for an
element consider using getElementsByTagName and loop through the result
instead of looping through childNodes as with getElementsByTagName you
get the same result in the browser independent of the white space text
node handling.
If you are really interested in the child nodes then you need to test
nodeType to decide what to do with a node, you get 1 for element nodes
and 3 for text nodes.
 
K

kaeli

[email protected] enlightened said:
If you wrote all markup without white space between tags Mozilla, Opera
and IE would give you the same result for the child nodes.

Oh, holy mother of God.
Whose bright idea was that?!?!

Now I either have to exchange readable code with the
getElementsByTagName, which I didn't want to use (too clunky), or make
unreadable code.
*sighs*

I guess it's getElementsByTagName. I'm addicted to white space.

Thanks!
I wouldn't have ever thought of that. Not in a million years.
The example doesn't show what you want to do,

I know. The full code will replace a (specified) table cell, which would
have been much prettier just using the childNodes. The full code isn't
as easy to see the problem with as this, though it not huge or anything.

*grumbles*
That's gonna change one nice line of code into multiple lines to find
the right cell to replace.
*sigh*
Oh, well.

--
 
L

Lasse Reichstein Nielsen

[IE omits all-whitespace text nodes]
Oh, holy mother of God.
Whose bright idea was that?!?!

Microsoft. As usual.
Now I either have to exchange readable code with the
getElementsByTagName, which I didn't want to use (too clunky), or make
unreadable code.
*sighs*

Or use:

var T = document.getElementById("tb");
for (var i=0; i<T.rows.length; i++) {
alert(T.rows);
}
I guess it's getElementsByTagName. I'm addicted to white space.

Both table elements and row-group elements (thead, tbody and tfoot)
have a "rows" collection of the table rows inside them. And it's
W3C DOM compliant *and* works in IE, so no reason not to use it.
I know. The full code will replace a (specified) table cell, which would
have been much prettier just using the childNodes. The full code isn't
as easy to see the problem with as this, though it not huge or anything.

Table rows also have a "cells" collection, so you can access row i and
column j as:
T.rows.cells[j]


Good luck
/L
 
K

kaeli

[email protected] enlightened us said:
Table rows also have a "cells" collection, so you can access row i and
column j as:
T.rows.cells[j]


I tried that before and it didn't work in Netscape. Worked fine in IE.
But that was due to my original syntax, which referenced the table, not
the tbody.
var T = document.getElementById("t1"); // the table
alert(T.firstChild.rows.cells[j].innerHTML); // firstChild
expected to reference tbody, doesn't with the white space issue in NN

Changing it to reference the tbody instead works in both.
var T = document.getElementById("t1");
alert(T.firstChild.rows.cells[j].innerHTML);

On this whole issue, I'm preferring MSIE. I've gotten this to work at
least 7 different ways in IE and only 1 (well, 2 now) in NN.

Thanks for the alternative, though.
I think I like it better than what I ended up with...

--
 
K

kaeli

[email protected] enlightened us said:
Table rows also have a "cells" collection, so you can access row i and
column j as:
T.rows.cells[j]


Oh, before I go changing things from getElementsByTagName...
Is the rows/cells thing as cross-browser as getElementsByTagName (if you
know)?


--
 
M

Martin Honnen

kaeli said:
[email protected] enlightened us said:
Table rows also have a "cells" collection, so you can access row i and
column j as:
T.rows.cells[j]



Oh, before I go changing things from getElementsByTagName...
Is the rows/cells thing as cross-browser as getElementsByTagName (if you
know)?


I think so (I am sure for Mozilla, Netscape 6/7, Opera 7 although I
can't give you details for Konqueror and Safari now off the top of my
head) but as the W3C DOM Level 2 HTML module in
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-64060425
specifies the properties
rows
tHead
tFoot
tBodies
for <table> elements and the
rows
property for table section elements (<thead>, <tbody>, <tfoot>) as well
as the
cells
property for table cells elements (<th>, <td>) any modern browser needs
to implement that.
And IE's object model knows these properties too since IE 4 I think so
browsers like Safari and Konqueror have two reasons to implement them,
W3C DOM compatibility and IE DOM compatibility.
 
C

Clarence Gardner

kaeli said:
Can anyone explain this to me? It's driving me insane.

Save this and run it in IE or Opera and then in Mozilla or Netscape 6+.
In IE/Opera, I get the expected 4 alerts.
In Mozilla/Netscape, I get *9*.

There are various kinds of nodes in the W3C DOM: Element is only
one of them. Every tag in your HTML document results in an ELEMENT_NODE.
But the text between the tags is a TEXT_NODE (sometimes more than one)
and there are other kinds too.

Mozilla includes the TEXT_NODEs in the DOM that you see. The extras
in your example are your whitespace, e.g., between <tbody> and <tr>,
and between </tr> and <tr>. Another place you might need to be aware
of this is if you have an event object for a Click event, and you
look at the attribute that shows what node the event happened to.
If you click on text in your page, Mozilla will show that the
event's target is the TEXT node, while IE will show it as the
ELEMENT node (named P, TD, etc) that contains the text (because
IE has no TEXT nodes).
 
I

Ivo

IE ignores those white space text nodes which most authors insert to
have their markup more readable e.g. you have written
<tbody>
<tr>
and not
<tbody><tr>
If you wrote all markup without white space between tags Mozilla, Opera
and IE would give you the same result for the child nodes.

You can also run this function (with the root html element as starting node)
onload:

function noemptytextnodes(node) {
// removes empty text nodes so DOMs get crossbrowser
for (var x = 0; x < node.childNodes.length; x++) {
var child = node.childNodes[x];
if ((child.nodeType == 3)&&(!/\S/.test(child.nodeValue))) {
node.removeChild(node.childNodes[x]);
x--;
} else if (child.nodeType == 1) {
noemptytextnodes(child);
}
}
}

HTH
Ivo
 
M

Martin Honnen

Ivo said:
IE ignores those white space text nodes which most authors insert to
have their markup more readable e.g. you have written
<tbody>
<tr>
and not
<tbody><tr>
If you wrote all markup without white space between tags Mozilla, Opera
and IE would give you the same result for the child nodes.


You can also run this function (with the root html element as starting node)
onload:

function noemptytextnodes(node) {
// removes empty text nodes so DOMs get crossbrowser
for (var x = 0; x < node.childNodes.length; x++) {
var child = node.childNodes[x];
if ((child.nodeType == 3)&&(!/\S/.test(child.nodeValue))) {
node.removeChild(node.childNodes[x]);
x--;
} else if (child.nodeType == 1) {
noemptytextnodes(child);
}
}
}

One could do that if the only aim is to have the same number of child
nodes in IE and Mozilla/Opera but generally I think there are other
issues why I don't think doing that is a good idea, there are reasons
those white space text nodes are in the DOM, for instance they are
needed if someone uses CSS white-space: pre; and then throwing out white
space text nodes with script would change the intended representation.
 
T

Thomas 'PointedEars' Lahn

Lasse said:
[IE omits all-whitespace text nodes]

Actually, to my observation IE does not omit all all-whitespace text nodes,
only those following a start tag. But that does not make it any better.


PointedEars
 
I

Ivo

Lasse said:
[IE omits all-whitespace text nodes]

Actually, to my observation IE does not omit all all-whitespace text nodes,
only those following a start tag. But that does not make it any better.

That would make it a bit better, which is quite something already, but
regrettably my observation differs. Mozilla treats the whiteline you may put
between an end </tr> and the next <tr> as a serious textnode, while IE
doesn't, so you can loop nextSiblings over them.
Ivo
 
L

Lasse Reichstein Nielsen

Thomas 'PointedEars' Lahn said:
Lasse said:
[IE omits all-whitespace text nodes]

Actually, to my observation IE does not omit all all-whitespace text nodes,
only those following a start tag. But that does not make it any better.

Well, consistency isn't IE's defining characteristic. If I add the
following to a page (with innerHTML):
<div id="foo"> <span> <span> x </span> </span> </div>
and get it out again with whitespace visible as:
document.all.foo.outerHTML.replace(/\s/g,"_")
then the result is:
__<DIV_id=foo><SPAN><SPAN>x_</SPAN>_</SPAN></DIV>

That is, IE removes most of the whitespace, but not all all-whitespace
nodes, and not only all-whitespace nodes.

/L
 

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,754
Messages
2,569,525
Members
44,997
Latest member
mileyka

Latest Threads

Top