Elements added to DOM tree via `appendChild`don't show up in IE6/7 (also `onclick` events not firing)
Consider the following JavaScript code, meant to create an 8x8 table inside of a container div with id="c"
:
//first, two shortcut functions
function $id(a){return(a&&a.nodeType)?a:document.getElementById(a);}
function $cr8(a){return document.createElement(a);}
//now the meat
var ct = $id('c'),
t = $cr8('table'),
tr, td,
row = 8, cols = 8,
tdclkfn = function () { alert('row: '+this.i+' col: '+this.j); }
for(var i=0;i<row;i++) {
tr = $cr8('tr');
for(var j=0;j<cols;j++) {
td = $cr8('td');
td.i = i;
td.j = j;
td.onclick = tdclkfn;
tr.appendChild(td);
}
t.appendChild(tr);
}
ct.appendChild(t);
This works as expected in Firefox, Chrome, and IE8. Not so much in IE6/IE7. As you can see in this live example, it's as if the table markup isn't there.
If you poke around under the hood using either Firebug Lite or the IE Developer Toolbar, you can discover tha开发者_如何学编程t the DOM elements are actually there, they're just not displayed for some reason. Anybody know why?
I decided to see what would happen if I added ct.innerHTML += '<div/>'
to the tail end of the above JavaScript. Presto, it shows up (see this updated live example). Why does this fix the problem?
Additionally, the function I've attached to the onclick
event handler for each <td>
? Apparently it doesn't fire at all. It's attached, you can trigger it by a manual call, but clicking on the cell? Nope, not in IE6/7. Why?
I'm aware I can get around this by using a nicely-behaved JS/DOM framework, but I'd really be curious to find out what's going on here.
table
elements can't directly contain tr
elements; IE and other browsers are happy to handle it for you when parsing markup (inserting the tbody
automatically; see below), but apparently IE is more finicky when you're manipulating the DOM directly.
If you put a tbody
in there, IE6 and IE7 are happy (the boxes show up, the click handlers work):
var ct = $id('c'),
t = $cr8('table'),
tbody = $cr8('tbody'),
tr, td,
row = 8, cols = 8,
tdclkfn = function () {
alert('row: '+this.i+' col: '+this.j);
}
for(var i=0;i<row;i++) {
tr = $cr8('tr');
for(var j=0;j<cols;j++) {
td = $cr8('td');
td.i = i;
td.j = j;
td.onclick = tdclkfn;
tr.appendChild(td);
}
tbody.appendChild(tr);
}
t.appendChild(tbody);
ct.appendChild(t);
Live copy (on jsbin.com; I don't seem to have much luck with IE6 and IE7 and jsfiddle.net). Your original code here for comparison on the same site.
Regarding inserting the tbody
for you automatically, you can see that in action:
HTML:
<table id='theTable'><tr><td>Test</td></tr></table>
(Note no tbody
.)
JavaScript:
window.onload = function() {
var elm, markup;
elm = document.getElementById('theTable');
markup = ["<ol>"];
walk(elm);
markup.push("</ol>");
display(markup.join(""));
function walk(node) {
var child;
markup.push("<li>");
markup.push(node.nodeName);
if (node.nodeType === 1 ||
node.nodeType === 9 ||
node.nodeType === 11) {
markup.push("<ol>");
for (child = node.firstChild;
child;
child = child.nextSibling) {
walk(child);
}
markup.push("</ol>");
}
markup.push("</li>");
}
function display(markup) {
var div = document.createElement('div');
div.innerHTML = markup;
document.body.appendChild(div);
}
};
Output:
- TABLE
- TBODY
- TR
- TD
- #text
- TD
- TR
- TBODY
Note the tbody
in there.
Live copy
精彩评论