Javascript 无法在 IE 中的 tbody 上设置 innerHTML
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4729644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can't set innerHTML on tbody in IE
提问by tester
I have a table like this:
我有一张这样的表:
<table>
<thead>
<tr>
<th colspan="1">a</th>
<th colspan="3">b</th>
</tr>
</thead>
<tbody id="replaceMe">
<tr>
<td>data 1</td>
<td>data 2</td>
<td>data 3</td>
<td>data 4</td>
</tr>
</tbody>
</table>
and a method returns me the following after an ajax request:
一个方法在ajax请求后返回以下内容:
<tr>
<td>data 1 new</td>
<td>data 2 new</td>
<td>data 3 new</td>
<td>data 4 new</td>
</tr>
I want to change the innerHTML like
我想改变innerHTML
document.getElementById('replaceMe').innerHTML = data.responseText;
However, it seems that IE can't set innerHTML on <tbody>
. Can anyone help me with a simple workaround for this issue?
但是,IE 似乎无法在<tbody>
. 任何人都可以帮助我解决此问题的简单解决方法吗?
回答by Hemlock
That is true, innerHTML on tbody elements is readOnly in IE
确实如此,tbody 元素上的 innerHTML 在 IE 中是只读的
The property is read/write for all objects except the following, for which it is read-only: COL, COLGROUP, FRAMESET, HEAD, HTML, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR.
除以下对象外,该属性对于所有对象都是可读/可写的:COL、COLGROUP、FRAMESET、HEAD、HTML、STYLE、TABLE、TBODY、TFOOT、THEAD、TITLE、TR。
source: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
来源:http: //msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
You can do something like this to work around it:
你可以做这样的事情来解决它:
function setTBodyInnerHTML(tbody, html) {
var temp = tbody.ownerDocument.createElement('div');
temp.innerHTML = '<table>' + html + '</table>';
tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody);
}
Basically it creates a temporary node into which you inject a full table
. Then it replaces the tbody
with the tbody
from the injected table
. If it proves to be slow, you could make it faster by caching temp
instead of creating it each time.
基本上它会创建一个临时节点,您可以在其中注入完整的table
. 然后,它取代了tbody
与tbody
从注入table
。如果证明它很慢,您可以通过缓存temp
而不是每次都创建它来使其更快。
回答by Juan Mendes
Create a temp node to store a table in, then copy them to the tbody
创建一个临时节点来存储表,然后将它们复制到 tbody
var tempNode = document.createElement('div');
tempNode.innerHTML = "<table>" + responseText+ "</table>";
var tempTable = tempNode.firstChild;
var tbody = // get a reference to the tbody
for (var i=0, tr; tr = tempTable.rows[i]; i++) {
tbody.appendChild(tr);
}
回答by Web Master
Both the answers above seem a bit unclear. Plus, the created div is never removed, so calling those functions repeatedly eats memory. Try this:
上面的两个答案似乎都有些不清楚。另外,创建的 div 永远不会被删除,因此重复调用这些函数会占用内存。尝试这个:
// this function must come before calling it to properly set “temp”
function MSIEsetTBodyInnerHTML(tbody, html) { //fix MS Internet Exploder's lameness
var temp = MSIEsetTBodyInnerHTML.temp;
temp.innerHTML = '<table><tbody>' + html + '</tbody></table>';
tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody); }
MSIEsetTBodyInnerHTML.temp = document.createElement('div');
if (navigator && navigator.userAgent.match( /MSIE/i ))
MSIEsetTBodyInnerHTML(tbody, html);
else //by specs, you can not use “innerHTML” until after the page is fully loaded
tbody.innerHTML=html;
Even with this code, though, MSIE does not seem to properly re-size the table cells in my application, but I'm filling an empty tbody tag with variable generated content, while the thead cells' colspan values are set to a fixed value: the maximum number of cells that may be in the generated tbody. While the table tbody is 50 cells wide, only two columns show. Perhaps if the table was originally filled, and the cells were replaced with the same internal structure, this method would work. Google's Chrome does an excellent job of rebuilding the table, while Opera's desktop browser can resize to more columns just fine, but if you remove columns, the remaining column widths remain as narrow as they were; however with Opera, by hiding the table (display=none) then re-showing it (display=table), the generated table tbody cells then size properly. I've given up with Firefox. It's the MSIE-6 of 2012 - a nightmare to develop for which must have additional markup added just to make HTML-CSS layouts work because it does not conform to standards that even MSIE now does. So I haven't tested the tbody.innerHTML workings in Firefox.
尽管如此,即使使用此代码,MSIE 似乎也无法正确调整应用程序中表格单元格的大小,但我正在使用可变生成内容填充空 tbody 标记,而 thead 单元格的 colspan 值设置为固定值: 生成的 tbody 中可能包含的最大单元格数。虽然表 tbody 有 50 个单元格宽,但只显示了两列。或许,如果表格原本是填满的,而单元格被替换为相同的内部结构,这种方法会奏效。Google 的 Chrome 在重建表格方面做得非常出色,而 Opera 的桌面浏览器可以很好地调整到更多列的大小,但是如果您删除列,剩余的列宽仍然保持原来的窄;但是对于 Opera,通过隐藏表格 (display=none) 然后重新显示它 (display=table),生成的表格 tbody 单元格大小合适。我已经放弃了 Firefox。这是 2012 年的 MSIE-6 - 一个开发的噩梦,必须添加额外的标记才能使 HTML-CSS 布局工作,因为它不符合甚至 MSIE 现在所做的标准。所以我还没有在 Firefox 中测试 tbody.innerHTML 的工作原理。
回答by Agamemnus
This can be fixed by creating a shim/polyfill for .innerHTML. This could get you (you, dear reader) started:
这可以通过为 .innerHTML 创建一个 shim/polyfill 来解决。这可以让你(你,亲爱的读者)开始:
if (/(msie|trident)/i.test(navigator.userAgent)) {
var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
get: function () {return innerhtml_get.call (this)},
set: function(new_html) {
var childNodes = this.childNodes
for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
this.removeChild (childNodes[0])
}
innerhtml_set.call (this, new_html)
}
})
}
var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)
document.body.innerHTML = ""
console.log (mydiv.innerHTML)
回答by Hua Chen
<table id="table">
<thead>
<tr>
<th colspan="1">a</th>
<th colspan="3">b</th>
</tr>
</thead>
<tbody id="replaceMe">
<tr>
<td>data 1</td>
<td>data 2</td>
<td>data 3</td>
<td>data 4</td>
</tr>
</tbody>
</table>
<button type="button" onclick="replaceTbody()">replaceTbody</button>
<script>
function $(id){
return document.getElementById(id);
}
function replaceTbody(){
var table = $('table');
table.removeChild($('replaceMe'));
var tbody = document.createElement("tbody");
tbody.setAttribute("id","replaceMe");
table.appendChild(tbody);
var tr = document.createElement('tr');
for(var i=1;i<5;i++){
var td = document.createElement('td');
td.innerHTML = 'newData' + i;
tr.appendChild(td);
}
tbody.appendChild(tr);
}
</script>