Wednesday, January 10, 2007

IE 7 appendChild bug

{

I'm working on t3rse::proper to allow custom shortcuts but discovered a bug with IE 7 when using the appendChild method of an element. It will take a bit more time to nail down specifics but try the following:

var tr = document.createElement("tr");
var tdchar = document.createElement("td");
var tdtext = document.createElement("td");
tdchar.appendChild(document.createTextNode('foo'));
tdtext.appendChild(document.createTextNode('bar'));
tr.appendChild(tdchar);
tr.appendChild(tdtext);
// you need some table with the id as testTable
document.getElementById("testTable").appendChild(tr);


Pretty straight forward and does _not_ work in IE 7. Check it out in Firefox and it works like a charm.

But the bug doesn't seem to be that simple; if you are called appendChild on a DIV or SPAN outside the context of a table, it works fine in both browsers.

// make a div with an id attribute of 'test'
document.getElementById('test').appendChild(
document.createElement('span').appendChild(document.createTextNode('foo'))
);

I'll dig into this a bit more - I see comments on similar things via Google search but nothing definitive. Unless AJ has answers... you always have answers...

}

14 comments:

AJ said...

Use innerHTML instead:

t = document.getElementByID('mytable');
tContent = t.innerHTML;
newRow = '<tr><td>foo</td><td>b</td></tr>';
t.innerHTML = tContent + newRow;

Plus, it should be WAY faster:

http://www.quirksmode.org/dom/innerhtml.html

AJ

AJ said...

Also, if you desperately want to use the DOM, it looks like the trick is that you have to append your row to a tbody element rather than the table element:

http://ncyoung.com/entry/494

I ran into a similiar problem a couple months back:

http://cephas.net/blog/2006/05/30/cant-add-hyperlink-with-onclick-to-ie-using-dom/

AJ

David Seruyange said...

Point #1 well taken; I thought about using innerHTML but I've been trying to stay on the 'web standards' tip by keeping everything I do within W3C DOM confines.

I've got to decide either to go for 'practical' rather than being a standards zealot and take the innerHTML approach.

What's your take on the "standards" stuff - these days I use DIVs + CSS a lot even when my natural instinct is to design with tables like I always have.

In the Javascript world I've been trying to ween myself of anything that isn't cross browser, but innerHTML seems to have good support.

AJ said...

I'm totally ignorant: what does keeping with within the W3C DOM confines gain you?

I guess I'm not a purist: if there's something that the majority of browsers support (ie: innerHTML), then I'm going to use it if it helps me get something done (not saying that you're not getting anything done, just that I'm not a purist).

David Seruyange said...

I think the philosophy I'm shooting for is akin to the "webstandards" folks; sticking with standards will not only allow my stuff to work on multiple platforms but also encourage browser makers to stay away from things that are proprietary. That being said, I agree with you that if something is supported by the important browsers it is probably okay to use.

The Kid Lunch said...

Grrr, I feel your pain. For me, appendChild() causes severe problems when trying to add to a node in another window (iFrame,popup, or parent).

The only, and I mean only, recourse was using innerHTML.

Makes me feel like I need to shower.

The Kid Lunch said...

(and yes, IE is the only browser that chokes on appendChild in a different window)

estelle said...

Thank you aaron!! I've been stuffing around for ages, if only I'd found out earlier that I just had to use a tbody element!

Sourabh Shankar said...

Append the child in "tbody" tag of table instead of appending it directly to table :) i'll work in IE7 and FF

http://desicode.blogspot.com

Even Simon said...

Here, try this, works perfect in all the browsers...

var tr = document.getElementById("testTable").insertRow(0);
var tdchar = document.createElement("td");
var tdtext = document.createElement("td");
tdchar.appendChild(document.createTextNode('foo'));
tdtext.appendChild(document.createTextNode('bar'));
tr.appendChild(tdchar);
tr.appendChild(tdtext);

Have fun,
Simon

olch said...
This comment has been removed by the author.
olch said...

You can use something like this

var tr = document.getElementById("testTable").insertRow(0);
var tdchar = tr.insertCell(0);
var tdtext = tr.insertCell(0);
tdchar.appendChild(document.createTextNode('foo'));
tdtext.appendChild(document.createTextNode('bar'));


But note that this code works very slow in Firefox. And innerHTML works very slow in IE

Unknown said...

Thanks Even. Helped me fixing a bug.

VBKesha said...

In IE table row must be in <TBODY> tags.
<table id="tbl_log" border="1">
<tr><th>id</th><th>msg</th></tr>
<tbody id="tbl_log_bd">
</tbody>
</table>

var t = document.getElementById('tbl_log_bd');
var tr, td;
tr = document.createElement('tr');
td = document.createElement('td');
td.innerHTML = '11';
tr.appendChild(td);
td = document.createElement('td');
td.innerHTML = '222';
tr.appendChild(td);
t.appendChild(tr);