【发布时间】:2010-12-21 03:11:39
【问题描述】:
我一直在网上搜索,我很确定我已经知道答案(“否”),但我想检查一下:
IE 还支持 importNode() 吗?有比遍历 DOM 和创建节点更好的选择吗? (我见过the clasic article by Anthony Holdener,但它现在已有一年多的历史了,我希望 IE 已经进化,或者有人有另一种解决方法)
谢谢。
【问题讨论】:
标签: javascript internet-explorer dom
我一直在网上搜索,我很确定我已经知道答案(“否”),但我想检查一下:
IE 还支持 importNode() 吗?有比遍历 DOM 和创建节点更好的选择吗? (我见过the clasic article by Anthony Holdener,但它现在已有一年多的历史了,我希望 IE 已经进化,或者有人有另一种解决方法)
谢谢。
【问题讨论】:
标签: javascript internet-explorer dom
Internet Explorer 9 DOM API 中有一个函数 document.importNode()。但是,IE9在调用时会抛出脚本错误
SCRIPT16386:不支持此类接口
还需要定义源节点的命名空间(例如,当我们要导入 SVG 时 - In IE9, Imported nodes do not seem to be recognized as SVG Elements)
Phrogz 建议 this 有用的解决方法。但是,当我们导入具有特殊命名空间的元素(在 xmlns 属性中声明,例如<svg xmlns="http://www.w3.org/2000/svg" …>…</svg>)时,clone.setAttributeNS(a.namespaceURI,a.nodeName,a.nodeValue) 会出现错误,因为属性 xmlns 的 namespaceURI 为空。
有适合我的解决方法:
var newNode;
try {
newNode = document.importNode(sourceDocumentElement, true);
}
catch(e) {
newNode = importNode(sourceDocumentElement, true);
}
function importNode(node, allChildren) {
switch (node.nodeType) {
case document.ELEMENT_NODE:
var newNode = document.createElementNS(node.namespaceURI, node.nodeName);
if(node.attributes && node.attributes.length > 0)
for(var i = 0, il = node.attributes.length; i < il; i++)
newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i].nodeName));
if(allChildren && node.childNodes && node.childNodes.length > 0)
for(var i = 0, il = node.childNodes.length; i < il; i++)
newNode.appendChild(importNode(node.childNodes[i], allChildren));
return newNode;
break;
case document.TEXT_NODE:
case document.CDATA_SECTION_NODE:
case document.COMMENT_NODE:
return document.createTextNode(node.nodeValue);
break;
}
}
【讨论】:
我还没有听说这已经改变了,在 John Resig 的 recent post 中,他说:
Internet Explorer 不支持importNode 或adoptNode
另请参阅cross-browser importnode() 上的 A List Apart 文章,因为它包含 Internet Explorer 的特定解决方法。
为后人引用,
解决我所有问题的方法毕竟是不使用 DOM 方法,而是使用我自己的实现。这是我以跨浏览器兼容的方式编码的 importNode() 问题的最终解决方案:(换行标记为 » —Ed.)
if (!document.ELEMENT_NODE) {
document.ELEMENT_NODE = 1;
document.ATTRIBUTE_NODE = 2;
document.TEXT_NODE = 3;
document.CDATA_SECTION_NODE = 4;
document.ENTITY_REFERENCE_NODE = 5;
document.ENTITY_NODE = 6;
document.PROCESSING_INSTRUCTION_NODE = 7;
document.COMMENT_NODE = 8;
document.DOCUMENT_NODE = 9;
document.DOCUMENT_TYPE_NODE = 10;
document.DOCUMENT_FRAGMENT_NODE = 11;
document.NOTATION_NODE = 12;
}
document._importNode = function(node, allChildren) {
switch (node.nodeType) {
case document.ELEMENT_NODE:
var newNode = document.createElement(node »
.nodeName);
/* does the node have any attributes to add? */
if (node.attributes && node.attributes »
.length > 0)
for (var i = 0; il = node.attributes.length;i < il)
newNode.setAttribute(node.attributes[i].nodeName,
node.getAttribute(node.attributes[i++].nodeName));
/* are we going after children too, and does the node have any? */
if (allChildren && node.childNodes && node.childNodes.length > 0)
for (var i = 0; il = node.childNodes.length; i < il)
newNode.appendChild(document._importNode(node.childNodes[i++], allChildren));
return newNode;
break;
case document.TEXT_NODE:
case document.CDATA_SECTION_NODE:
case document.COMMENT_NODE:
return document.createTextNode(node.nodeValue);
break;
}
};
这里正在使用:
var newNode = null, importedNode = null;
newNode = xhrResponse.responseXML.getElementsByTagName('title')[0].childNodes[0];
if (newNode.nodeType != document.ELEMENT_NODE)
newNode = newNode.nextSibling;
if (newNode) {
importedNode = document._importNode(newNode, true);
document.getElementById('divTitleContainer').appendChild(importedNode);
if (!document.importNode)
document.getElementById('divTitleContainer').innerHTML = document.getElementById('divTitleContainer').innerHTML;
}
【讨论】:
document.createComment 来响应COMMENT_NODE;把它变成一个文本节点可能不是一个好主意。不幸的是,在 IE 的 HTML 元素上使用getAttribute/setAttribute 也有很多问题;如果您正在克隆表单,name 可能是个问题,并且onX 属性和内联styles 不会以有用的方式工作(最好避免使用它们)。此外,任何<script> 元素在附加到任何父节点时都会重新执行。
对于更轻量级的解决方案(只要您不介意添加依赖项),您始终可以使用 jQuery:
$(dom_to_import_into).find('element-to-import-into').append($(dom_to_import).clone());
这将在'element-to-import-into' 的末尾添加dom_to_import。
【讨论】: