【问题标题】:IE support for DOM importNodeIE 对 DOM importNode 的支持
【发布时间】:2010-12-21 03:11:39
【问题描述】:

我一直在网上搜索,我很确定我已经知道答案(“否”),但我想检查一下:

IE 还支持 importNode() 吗?有比遍历 DOM 和创建节点更好的选择吗? (我见过the clasic article by Anthony Holdener,但它现在已有一年多的历史了,我希望 IE 已经进化,或者有人有另一种解决方法)

谢谢。

【问题讨论】:

标签: javascript internet-explorer dom


【解决方案1】:

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;
  }
}

【讨论】:

  • 这对我很有用,但我遇到了一个问题,即 元素显示为损坏的图像(在 IE9 中)。知道为什么会发生这种情况吗?我已经验证图像 URL 是有效的,所以这绝对不是问题。谢谢!
  • 如果有人感兴趣,我solved the problem.
【解决方案2】:

我还没有听说这已经改变了,在 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 不会以有用的方式工作(最好避免使用它们)。此外,任何&lt;script&gt; 元素在附加到任何父节点时都会重新执行。
  • @bobince:关于评论节点的精彩观点。 get/setAttribute 有时在 IE6 上可能会出现问题,但我没有注意到 IE7+ 上的特定功能对存在重大问题(尽管有很多要抱怨的地方)。
  • 为了也支持命名空间属性,使用 setAttributeNS 和 getAttributeNS 代替 setAttribute 和 getAttribute。
【解决方案3】:

对于更轻量级的解决方案(只要您不介意添加依赖项),您始终可以使用 jQuery:

$(dom_to_import_into).find('element-to-import-into').append($(dom_to_import).clone());

这将在'element-to-import-into' 的末尾添加dom_to_import

【讨论】:

  • 可能无法在 IE 中使用。取决于你想要做什么。我怀疑原始海报正在使用 importNode,因为他/她正在从外部文档(例如 iframe 或 window.open)复制。因此,在 IE 上使用 jQuery 的 append() 仍然会失败。 HierarchyRequestError.
猜你喜欢
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多