指定acceptNode时,createNodeIterator在IE9中失败

时间:2016-07-07 12:48:20

标签: javascript internet-explorer dom iterator treenode

目标

我想循环遍历DOM文本节点,按DOM中的顺序排序。此外,我想通过自定义逻辑过滤节点(例如,检查节点是否在特定元素内)。此外,所有这些都应该以最佳性能完成并在IE9 +中工作。

方法

满足上述所有要求

我不完全理解为什么这些类似的功能没有合并在一起。但是,由于createTreeWalker()有更多API方法,我已经开始使用它了。

然后我发现根据documentation,IE9不支持acceptNode过滤器功能。因此我根据documentation切换到createNodeIterator,但没有此限制。

这是我用来遍历元素的代码:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Test</title>
    </head>
<body>
    <div class="context">
      Root first
        <div>
          Child
        </div>
      Root second
    </div>

    <script type="text/javascript">
        var treeWalker = document.createNodeIterator(
            document.querySelector(".context"),
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function(){
                    return NodeFilter.FILTER_ACCEPT;
                }
          },
          false
        );

        var nodeList = [];
        var currentNode;
        while (currentNode = treeWalker.nextNode()){
            nodeList.push(currentNode);
        }

        console.log(nodeList);

    </script>
</body>
</html>

虽然在这种情况下循环实际上(几乎)没有,但在我的实际应用程序中它确实如此。所以请将此视为一个例子。

问题

问题是上面的内容在IE9中不起作用。似乎IE9中也不支持acceptNode的{​​{1}}过滤器回调属性。必须createNodeIterator才能正常工作。但是,正如文档所说它得到了支持,我希望它可以正常工作。

我的期望:

Expect

实际信息:

Actual

问题

这里有什么问题以及如何解决?请注意,我肯定需要循环。

2 个答案:

答案 0 :(得分:3)

我实际上在IE11中有完全相同的错误。

如果查看Document Object Model Level 2 Traversal and Range的W3C文档,更具体地说是关于ECMAScript Language Binding的附录C,NodeFilter对象定义如下:

  

这是ECMAScript函数参考。此方法返回一个数字。该参数是一个Node对象。

因此,如果您更新脚本以传递函数而不是具有键flight___的对象,那么您将获得预期的结果。

acceptNode

Firefox中的结果将是:

Firefox result

在Chrome中你会得到:

Chrome result

在IE中,您将拥有:

IE result

我没有修改你的循环或其他任何东西以获得这些结果所以我只发布了相关的部分。

答案 1 :(得分:-1)

我认为你实际拥有循环的部分是搞砸的地方。我确实理解你要做的事情,但我认为我认为你可以使用的方式仍能达到相同的效果:

 try{ 
       var treeWalker = document.createNodeIterator(
         document.querySelector(".context"),
         NodeFilter.SHOW_TEXT,
         { acceptNode: function(node)
              { return NodeFilter.FILTER_ACCEPT; }
         },
      false
      );
    //This will help you avoid the loop you currently have on your code, but you wold still need one if you want to have a wrapper task that you want to perform on your treelist items

     var nodeList = treeWalker.root.childNodes;

     console.log(nodeList [0]);
 }catch(e){
   console.log(e);
 }

//版本2

var nodeIterator = document.createNodeIterator(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    function(node) {
        return node.nodeName.toLowerCase() === 'p' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
    },
    false
);
var pars = [];
//what you were missing for it to work on IE
    var currentNode = "<p></p>";


while (currentNode = nodeIterator.nextNode()) {
  console.dir(currentNode); // or console wherever you want
  pars.push(currentNode);
}