Por que o IE dá erros inesperados ao definir innerhtml
-
03-07-2019 - |
Pergunta
Tentei definir o InnerHTML em um elemento no Firefox e funcionou bem, tentei no IE e obtive erros inesperados sem motivo óbvio.
Por exemplo, se você tentar definir o inerhtml de uma tabela como "Hi From Stu", falhará, porque a tabela deve ser seguida por uma sequência.
Solução
"Aparentemente, o Firefox não é tão exigente" ==> Aparentemente, o Firefox é tão buggy, que não registra essa violação óbvia das regras básicas de ninho em HTML ...
Como alguém apontou em outro fórum, o Firefox aceitará, que você anexa um documento HTML inteiro como criança de um campo de forma ou mesmo uma imagem,-((
Outras dicas
Você está vendo esse comportamento porque o InnerHTML é somente leitura para elementos da tabela no IE. Do MSDN's Propriedade Innerhtml documentação:
A propriedade é lida/gravação para todos os objetos, exceto o seguinte, para os quais é somente leitura: Col, Colgroup, FrameSet, Head, HTML, Style, Table, Tbody, Tfoot, Thead, Title, Tr.
Não sei por que você está sendo moderado para a pergunta Stu, pois isso é algo que resolvi recentemente. O truque é 'esguichar' o html em um elemento DOM que atualmente não está anexado à árvore de documentos. Aqui está o trecho de código que faz isso:
// removing the scripts to avoid any 'Permission Denied' errors in IE
var cleaned = html.replace(/<script(.|\s)*?\/script>/g, "");
// IE is stricter on malformed HTML injecting direct into DOM. By injecting into
// an element that's not yet part of DOM it's more lenient and will clean it up.
if (jQuery.browser.msie)
{
var tempElement = document.createElement("DIV");
tempElement.innerHTML = cleaned;
cleaned = tempElement.innerHTML;
tempElement = null;
}
// now 'cleaned' is ready to use...
Observe que estamos usando apenas o uso do jQuery neste snippet aqui para testar se o navegador é o IE, não há dura dependência do jQuery.
Verifique o escopo do elemento que você está tentando definir o InnerHTML. Como FF e IE lidam com isso de uma maneira diferente
Eu tenho lutado com o problema da substituição de uma lista de links em uma tabela com uma lista de links.Como acima, o problema vem com o IE e a propriedade só de leitura de elementos da tabela.
Acrescentar para mim não era uma opção, então eu (finalmente) trabalhou fora isso (que funciona para Pc, o FF e o IE 8.0 (que ainda tenta, mas estou esperançoso)).
replaceInReadOnly(document.getElementById("links"), "<a href>........etc</a>");
function replaceInReadOnly(element, content){
var newNode = document.createElement();
newNode.innerHTML = content;
var oldNode = element.firstChild;
var output = element.replaceChild(newNode, oldNode);
}
Trabalha para mim - eu espero que ele funciona para você
Você já tentou definição innerText e/ou textContent?Alguns de nós (como tags de SCRIPT) não se comportar conforme o esperado quando você tenta alterar sua innerHTML no IE.Mais aqui sobre innerText versus textContent:
http://blog.coderlab.us/2006/04/18/the-textcontent-and-innertext-properties/
Você está definindo um completamente diferente innerHTML ou a substituição de um padrão na innerHTML?Eu pergunto porque se você está tentando fazer um trivial procurar/substituir, através do "poder" de innerHTML, você vai encontrar alguns tipos de elemento não jogar no IE.
Isso pode ser remediado com cautela por volta da sua tentativa em um try/catch e borbulhando o DOM através parentNode até você conseguir fazê-lo.
Mas isso não vai ser adequado se você está a inserir novo conteúdo.
Você pode modificar o comportamento.Aqui está um código que impede que a coleta de lixo não-referenciados elementos no IE:
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)
Eu só descobri que se você tentar definir innerHTML em um elemento no-IE que não é logicamente correta, ele irá gerar este erro.Por exemplo, se você tentar definir o innerHTML de uma mesa para " oi a partir de stu "ele vai falhar, porque a tabela tem de ser seguido por uma sequência.Aparentemente, o firefox não é esta exigente.Espero que ajude.