Forum Moderators: open

Message Too Old, No Replies

Create New Table Row IE6/Firefox

trying to get rows[i].cells.length

         

vol7ron

7:35 pm on Dec 7, 2009 (gmt 0)

10+ Year Member



Check out the code below:
[pre]
var tr1 = document.createElement("tr");
var td1 = document.createElement("td");
var td2 = document.createElement("td");

td1.appendChild(document.createTextNode('test1'));
td2.appendChild(document.createTextNode('test2'));

tr1.appendChild(td1);
tr1.appendChild(td2);[/pre]

If I then try to call:

[size=1]alert(tr1.cells.length);[/size]

IE6 gives an error, whereas Firefox gives me the proper value.

I know why this occurs, that is, this happens because the table cells are not appended to the table row until I apply the table row to the table. I have to perform something like:

[size=1]getElementById(TableID).tBodies[0].appendChild(tr1);[/size]

The question is, is there a way to obtain the number of cells in the tr1, without actually applying tr1 to the table.

I know I can append the tr1 to the table body and set the display style to none, but I don't want to do that.

Thank you for your help,
vol7ron

Fotiman

9:11 pm on Dec 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I would think you could do something like this:

var i, n, result = 0;
for (i = 0, n = tr1.childNodes.length; i < n; i++) {
// Count only the td elements
if (tr1.childNodes.item(i).nodeType == 1 &&
tr1.childNodes.item(i).tagName == 'TD') {
result++;
}
}

That is, step through the child nodes of tr1, and for each element (nodeType = 1) that is a "TD" element, increment a counter. At the end, result will have the count.
Note, I did not actually test this, but I think it will work. :)

vol7ron

9:23 pm on Dec 7, 2009 (gmt 0)

10+ Year Member



I will have to try this. This all hinges on if the childNodes collection is created; the cells collection was not.

I think this might be obvious, but down the road, I will want to get the value of each cell specifically.

Just to show where I'm coming from, I'm dynamically creating a table. I want each record in the table to be unique (the concatenated key is made up of three of the cells' values). If there already exists a record, then the row will be updated, rather than a new row inserted into the table.

If I can get the childNodes, I can more than likely get the innerHTML of the object, otherwise this web application will have to be FireFox only :(

vol7ron

9:56 pm on Dec 7, 2009 (gmt 0)

10+ Year Member



Fotiman++

You have just made my month. I started writing a cross-browser package before and when I got to this point, I had to stop. I didn't even know how to ask the question. A few years later and here I am needing to do more work with dynamic table creation. This time I didn't want to settle for using Regular Expressions on innerHTML values.

As you correctly pointed out, the childNodes collection is created in IE, no need to have to attach the row to the body. I didn't go too much into what you created above (just a simple tr1.childNodes[0].innerHTML) gives me what I needed. I wrote some recursive functions to strip incorrect childNodes (whitespace) from the Dom before. Looking more into what you wrote, I'd suspect you don't even need the nodeType comparison.
I'm curious if a var cnt = tr1.childNodes.getElementsByTagName('tr'); cnt.length; might also work.

Just so you know, you have significantly saved me lots of time and I am in your debt.

Thank you so much,
vol7ron

Fotiman

1:36 am on Dec 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I was doing to nodeType check to ensure that it got an element (vs. getting an attribute of tr and/or getting extra text nodes in some browsers). I suspect that you could probably do this:

var tds = tr1.getElementsByTagName('td');
var cnt = tds.length;

That would probably be much more efficient and easier to maintain. I bet that would work too. :)

vol7ron

3:36 pm on Dec 9, 2009 (gmt 0)

10+ Year Member



I think you are right on again. I didn't try, but some things you just don't need to :)

I think my last statement above was a typo. I think the 'tr' was supposed to be a 'td' when I wrote:
var cnt = tr1.childNodes.getElementsByTagName('tr');

I also thing that you shouldn't take the variable name literally, I wasn't being descriptive. 'cnt' was just shorthand for container, since getElementsByTagName returns an array, I would have probably made a variable called aTd or aRows.

In any case, I started making this first work in FireFox, since Firebug makes exploring the DOM easy. I will get this working in IE too afterwards, using the method described above.

Thank you much,
vol7ron

Fotiman

3:40 pm on Dec 9, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Glad you got it sorted. :)

vol7ron

6:52 pm on Jan 27, 2010 (gmt 0)

10+ Year Member



It's been over a month, but I needed to come back to this again. I found my last post confusing and horribly written - too many "I think"s. To clarify, the post I submitted was an explanation of typing errors; the code that I provided in the statement was not meant to be code that works. To be more specific:

Given: var tr = document.createElement("tr");

The following will NOT work:

alert(tr.childNodes.getElementsByTagName('td').length);

As Fotiman pointed out it should be:

alert(tr.getElementsByTagName('td').length);

This is because the getElementsByTagName function does not belong to the childNodes collection, however although tr.cells.length does not work in IE (because the table row/cells have not yet been added to the table in the dom), the tags do still exist. So the function can be used on the dynamically created tr object.

After the tr is appended to the tBody/table, then tr.cells.length can be used, as normal (and as found in Firefox).

vol7ron