» in my experience...

» home | about | contact | résumé
» archives | donate | rss syndication

»
»
Do we need more professional offices in the area?


Communiblog Communiblog expressed as RSS 2.0
Here at IMX
Memes R' Us
freetheaudio2.jpg
SuperNova 1987A from 1994 to 2003
GarageBand

What do you think of your firstChild?
[ Posted by Dan on October 03, 2003 | 4 Comments ]

I've discovered an inconsistancy and/or a bug in Mozilla's DOM implementation. Consider this simple unassuming HTML table which has it's id set to "ourTable"...

_Row_1_Cell_1_ _Row_1_Cell_2_ _Row_1_Cell_3_
_Row_2_Cell_1_ _Row_2_Cell_2_ _Row_2_Cell_3_
_Row_3_Cell_1_ _Row_3_Cell_2_ _Row_3_Cell_3_


The source of that table isn't anything weird and certainly isn't malformed HTML. Here's what the source of that table looks like...

<table border="1" width="50%" cellspacing="1" cellpadding="5" id="ourTable">
	<tr id="_Row_1_">
		<td id="_Row_1_Cell_1_">_Row_1_Cell_1_</td>
		<td id="_Row_1_Cell_2_">_Row_1_Cell_2_</td>
		<td id="_Row_1_Cell_3_">_Row_1_Cell_3_</td>
	</tr>
	<tr id="_Row_2_">
		<td id="_Row_2_Cell_1_">_Row_2_Cell_1_</td>
		<td id="_Row_2_Cell_2_">_Row_2_Cell_2_</td>
		<td id="_Row_2_Cell_3_">_Row_2_Cell_3_</td>
	</tr>
	<tr id="_Row_3_">
		<td id="_Row_3_Cell_1_">_Row_3_Cell_1_</td>
		<td id="_Row_3_Cell_2_">_Row_3_Cell_2_</td>
		<td id="_Row_3_Cell_3_">_Row_3_Cell_3_</td>
	</tr>
</table>



Now, using some JavaScript, let's start alerting things so we can see where Mozilla goes wrong (well, it does something different than Safari and Internet Explorer and I think it's incorrect). what we are going to do is alert the firstChild of the first row of the table. We do that in JavaScript by saying...
function whatIsThis(item) {

var myTable = document.getElementById("ourTable");

alert(myTable.rows[0].firstChild);

}
And then we call that function and pass in the name of the table we want to interrogate. In Mozilla you will get an alert box that says "[Object TEXT]" where as in Safari and Internet Explorer (I tested on my Win2k box for IE) you get "[Object TD]" and "[Object]" respectively.

If you go back up to the source of the table, and look at the firstChild of the first row, you very clearly see that there's a table cell there, and not the text contents of a random container. And for the record, accessing the table row thru getElementById and asking for it's firstChild returns the same result everywhere.

"Why is this important?" you ask. Well, if you want to use the DOM tools available to you for tracing around the DOM without knowing the ID's of everything, you can't do that with firstChilsd in Mozilla. That's bad. In my case, in a web application I'm working on, I have some HTML being written by a component in a very standardized way, and using ID's in everything is for more cumbersome than just grabbing the stuff that's in the firstChild of the firstChild of a table row. When we get "[Object TEXT]" back from Mozilla, there are no more firstChild[ren] available to us.

"So?" you ask, "why not use the cells[] array to trace into those table cells?" Well, the cell[] array is broken in Safari, and I'm trying to NOT write hopelessly forked (fucked?) JavaScript code for the sake of maintainability and editability by those who are more JavaScript challeneged than I am.

IMHO, Mozilla is obviously broken here.

 

So I don't necessarily dispute that this is "broken" behavior, but a couple of suggestions.

Mozilla treats whitespace as dom elements. More details here, including a library to deal with it:
http://www.mozilla.org/docs/dom/technote/whitespace/

A handy workaround, and potentially more robust technique, is to use getElementsByTagName from the table cell to access the rows.

var table = document.getElementById("mytable");
var rows = document.getElementByTagName("tr");
var firstrow = rows.item(0);

This would work for td as well. Another caveat is not to forget about the implicit tbody tag that is the first descendant of every table.

hth

-Posted by AndyEd on October 3, 2003 10:28 AM

Doh! I did not know about that whitespace issue at all. MANY thanks for the pointer.

-Posted by Dan on October 3, 2003 10:41 AM

Mozilla is not broken. The first child element is in fact the text (the carraige return, line feed, and tab). What you should be doing is looping through the children while checking element types, for reasons you have just discovered are essential. It may seem silly that it treats whitespace as text, or text as an element, but it would be a bigger problem if Mozilla forbade you to use whitespace in a document, or prevented you from accessing text between tags.

Don't worry, you are hardly alone, I doubt there are even many programmers who didn't stumble with this when playing with XML parsing.

-Posted by Eric on October 3, 2003 05:43 PM

Whoops, typo in my code, the idea is to get ElementsByTagName from the specific table as a root node:

var table = document.getElementById("mytable");
var rows = table.getElementByTagName("tr"); // note table.get...
var firstrow = rows.item(0);

-Posted by AndyEd on October 3, 2003 07:09 PM




Comment posting has been turned off because I don't have enough time and will to deal with the constant comment spamming. I'm very sorry and will fix this sometime soon (soon = before 2004 ends).

MovableType AmphetaDesk
NetNewsWire BlogTree Subscribe with Bloglines RSS Feed
Copyright © 2001 - 2003 by Daniel Kapusta