简体   繁体   English

如何使用javascript创建html dom的叶节点数组

[英]How to create an array of leaf nodes of an html dom using javascript

So my question is basically this, how can I return an array of all the leaf nodes of an html document using a javascript function. 所以我的问题基本上是这样,如何使用javascript函数返回html文档的所有叶节点的数组。 I need to perform operations on that list later. 稍后,我需要对该列表执行操作。 for example if I have html: 例如,如果我有html:

<body>
   <div>
      <div>
         <p id="para1"></p>
      </div>
   </div>
   <p id="para2"></p>
</body>

then the function should return a array containing the two nodes with id para1 and para2. 然后函数应返回一个数组,其中包含ID为para1和para2的两个节点。

Note: I want the nodes themselves not their id. 注意:我想要节点本身而不是它们的ID。 Although given the id i can extract the nodes so its not a big issue. 尽管给出了ID,但我可以提取节点,所以这不是一个大问题。

Here's a simple function to get leafNodes where you look at all nodes, including text nodes (this means it won't ever return an element that contains text nodes): 这是一个获取leafNodes的简单函数,您可以在其中查看所有节点,包括文本节点(这意味着它将永远不会返回包含文本节点的元素):

function getLeafNodes(master) {
    var nodes = Array.prototype.slice.call(master.getElementsByTagName("*"), 0);
    var leafNodes = nodes.filter(function(elem) {
        return !elem.hasChildNodes();
    });
    return leafNodes;
}

Working demo: http://jsfiddle.net/jfriend00/e9D5n/ 工作演示: http : //jsfiddle.net/jfriend00/e9D5n/

FYI, the .filter() method requires IE9. 仅供参考, .filter()方法需要IE9。 If you want to use this method with earlier versions of IE, you can install a polyfill for .filter() or change to a manual iteration of the array. 如果要在早期版本的IE中使用此方法,则可以为.filter()安装.filter()或更改为数组的手动迭代。


And, here's a version if you don't want to consider text nodes, so you're looking for the leaf elements, even if they have text nodes in them: 而且,如果您不想考虑文本节点,那么这里是一个版本,因此您正在寻找叶子元素,即使它们中包含文本节点也是如此:

function getLeafNodes(master) {
    var nodes = Array.prototype.slice.call(master.getElementsByTagName("*"), 0);
    var leafNodes = nodes.filter(function(elem) {
        if (elem.hasChildNodes()) {
            // see if any of the child nodes are elements
            for (var i = 0; i < elem.childNodes.length; i++) {
                if (elem.childNodes[i].nodeType == 1) {
                    // there is a child element, so return false to not include
                    // this parent element
                    return false;
                }
            }
        }
        return true;
    });
    return leafNodes;
}

Working demo: http://jsfiddle.net/jfriend00/xu7rv/ 工作演示: http : //jsfiddle.net/jfriend00/xu7rv/


And, here's a recursive solution that ignores text nodes: 而且,这是一个忽略文本节点的递归解决方案:

function getLeafNodes(master) {
    var results = [];
    var children = master.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].nodeType == 1) {
            var childLeafs = getLeafNodes(children[i]);
            if (childLeafs.length) {
                // if we had child leafs, then concat them onto our current results
                results = results.concat(childLeafs);
            } else {
                // if we didn't have child leafs, then this must be a leaf
                results.push(children[i]);
            }
        }
    }
    // if we didn't find any leaves at this level, then this must be a leaf
    if (!results.length) {
        results.push(master);
    }
    return results;
}

Working demo: http://jsfiddle.net/jfriend00/jNn8H/ 工作演示: http : //jsfiddle.net/jfriend00/jNn8H/

I assume by "leaf node", you mean an element with no children. 我假设“叶节点”是指没有子元素的元素。 In that case, you can get all elements, and then iterate through each one, check if it has any children, and if not add it to an array: 在这种情况下,您可以获取所有元素,然后遍历每个元素,检查它是否有任何子元素,如果没有,则将其添加到数组中:

var leaves = new Array();
var els = document.body.getElementsByTagName("*");
for (var i = 0; i < els.length; i++) {
    if (els[i].children.length === 0) {
        leaves.push(els[i]);
    }
}

Perhaps the following will work? 也许以下方法会起作用?

var paraEl=new Array();
for(i=0;i<document.getElementsByTagName("p").length;i++){
    paraEl[i]=document.getElementsByTagName("p")[i];
}

But you know, document.getElementsByTagName("p") is already an array, right? 但是您知道,document.getElementsByTagName(“ p”)已经是一个数组,对吗?

So, it seems you are wondering how to add the nodes to the array and return the array. 因此,您似乎想知道如何将节点添加到数组并返回数组。 Simply always return an array from the function and merge them: 只需始终从函数返回数组并合并它们:

function getLeaves(element) {
    if (element.children.length === 0) {
        return [element];
    }
    var leaves = [];
    for (var i = 0, l = element.children.length; i < l; i++) {
        leaves.push.apply(leaves, getLeaves(element.children[i]));
    }
    return leaves;
}

DEMO 演示

Alternatively, you can pass an array down and when the element is a leave, it just adds itself to it: 另外,您可以向下传递一个数组,当元素为假时,它只是将自身添加到其中:

function getLeaves(element, arr) {
    // create an array if none is passed. This happens in the first call.
    arr = arr || [];
    if (element.children.length === 0) {
        arr.push(element);
    }
    var leaves = [];
    for (var i = 0, l = element.children.length; i < l; i++) {
        getLeaves(element.children[i], arr);
    }
    return arr;
}

DEMO 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM