
ensayador
Tengo una tabla como esta:
<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>
y un método me devuelve lo siguiente después de una solicitud ajax:
<tr>
<td>data 1 new</td>
<td>data 2 new</td>
<td>data 3 new</td>
<td>data 4 new</td>
</tr>
Quiero cambiar el HTML interno como
document.getElementById('replaceMe').innerHTML = data.responseText;
Sin embargo, parece que IE no puede configurar innerHTML en <tbody>
. ¿Alguien puede ayudarme con una solución simple para este problema?

Cicuta
Eso es cierto, innerHTML en tbody elementos es de solo lectura en IE
La propiedad es de lectura/escritura para todos los objetos excepto los siguientes, para los cuales es de solo lectura: COL, COLGROUP, FRAMESET, HEAD, HTML, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR.
fuente: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
Puedes hacer algo como esto para evitarlo:
function setTBodyInnerHTML(tbody, html) {
var temp = tbody.ownerDocument.createElement('div');
temp.innerHTML = '<table>' + html + '</table>';
tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody);
}
Básicamente, crea un nodo temporal en el que inyectas un table
. Luego reemplaza el tbody
con el tbody
de lo inyectado table
. Si resulta ser lento, puede hacerlo más rápido almacenando en caché temp
en lugar de crearlo cada vez.

Juan Mendes
Cree un nodo temporal para almacenar una tabla, luego cópielos en el cuerpo
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);
}
Ambas respuestas anteriores parecen un poco confusas. Además, el div creado nunca se elimina, por lo que llamar a esas funciones repetidamente consume memoria. Prueba esto:
// 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;
Sin embargo, incluso con este código, MSIE no parece cambiar correctamente el tamaño de las celdas de la tabla en mi aplicación, pero estoy llenando una etiqueta tbody vacía con contenido generado variable, mientras que los valores colspan de las celdas principales se establecen en un valor fijo : el número máximo de celdas que puede haber en el cuerpo generado. Si bien el cuerpo de la tabla tiene 50 celdas de ancho, solo se muestran dos columnas. Tal vez si la tabla se llenara originalmente y las celdas se reemplazaran con la misma estructura interna, este método funcionaría. Chrome de Google hace un excelente trabajo al reconstruir la tabla, mientras que el navegador de escritorio de Opera puede cambiar el tamaño a más columnas sin problemas, pero si elimina columnas, los anchos de columna restantes permanecen tan estrechos como antes; sin embargo, con Opera, al ocultar la tabla (display=none) y luego volver a mostrarla (display=table), las celdas del cuerpo de la tabla generada se dimensionan correctamente. Me he dado por vencido con Firefox. Es el MSIE-6 de 2012: una pesadilla para desarrollar, para el cual se debe agregar un marcado adicional solo para que los diseños HTML-CSS funcionen porque no se ajusta a los estándares que incluso MSIE ahora hace. Así que no he probado el funcionamiento de tbody.innerHTML en Firefox.
Esto se puede arreglar creando un shim/polyfill para .innerHTML. Esto podría ayudarlo (a usted, querido lector) a comenzar:
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)
http://jsfiddle.net/DLLbc/9/
<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>
.
además, usar una biblioteca como jQuery NO es una opción.
– probador
18 ene.