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:

  1. 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

    ReplyDelete
  2. 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

    ReplyDelete
  3. 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.

    ReplyDelete
  4. 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).

    ReplyDelete
  5. 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.

    ReplyDelete
  6. 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.

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

    ReplyDelete
  8. 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!

    ReplyDelete
  9. 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

    ReplyDelete
  10. 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

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. 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

    ReplyDelete
  13. Thanks Even. Helped me fixing a bug.

    ReplyDelete
  14. 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);

    ReplyDelete