Loop through all descendants of a div - JS only

2020-02-27 04:09发布

I've been using jQuery to do this:

$element.find("*").each(function() {
    var $this = $(this);

    $this.removeAttr("style width align");

    if ($this.is("embed")) {
        $element.append("<div class='video'></div>");
        $this.attr("width", 640).attr("height", 360).parent().appendTo("#" + element + " .video");
    };
});

But I've been reading that jQuery's .each() method is quite slow when compared to a simple for loop (jsPerf). My question is how can I mimic this with pure JS? Find all elements within a div, then loop through the nodes.

I've tried to search for this but all I can seem to find are jQuery answers - everywhere.

I've tried other things but this was as close as I got to selecting all descendants:

var children = document.getElementById('id').getElementsByTagName('*');

for( var i = 0; i<children.lengtth; i++){
    children[i].removeAttribute("style");
    console.log(children[i]);
}

4条回答
地球回转人心会变
2楼-- · 2020-02-27 04:37

could you just use something as simple as this?

    // get a handle to the div you want.
var div = document.getElementById('someID'),
    // get an array of child nodes
    divChildren = div.childNodes;

for (var i=0; i<divChildren.length; i++) {
    divChildren[i].style.width = null;
    divChildren[i].style.textAlign = null;
}
查看更多
够拽才男人
3楼-- · 2020-02-27 04:40

I commented in @Paul S.'s answer that you could can also clone the node and use a document fragment to add new embeds. Here is an example:

HTML:

<div>
    <div id="container">
        <div align="right">child</div>
        <div align="center">child</div>
        <embed src="" width="0" height="0" />
        <div align="center">child</div>
        <div style="width: 40px">child</div>
        <div style="font-size: 100px">child</div>
        <div width="60%">child</div>
        <embed src="" width="0" height="0"/>
        <div width="60%">child</div>
    </div>
</div>

JS:

var elm,
    clone,
    doc,
    next,
    fragment,
    live = document.getElementById("container");

if (live !== null) {
    fragment = document.createDocumentFragment();
    clone = live.cloneNode(true);
    next = clone.firstChild;
    while(next !== null) {
        if (next.nodeName !== "#text") {
            next.removeAttribute('style');
            next.removeAttribute('width');
            next.removeAttribute('align');

            if (next.tagName === 'EMBED') {
                doc = document.createElement('div');
                doc.setAttribute('class', 'video');
                doc.innerHTML = "EMBED detected, adding div...";
                fragment.appendChild(doc);
            }
        }
        next = next.nextSibling;
    }
    clone.appendChild(fragment);
    live.parentNode.replaceChild(clone, live);
}

You can see the demo here.

Cloning the node prevents the live modification of the DOM since the style attribute can have properties that cause the browser to repaint numerous times.

查看更多
时光不老,我们不散
4楼-- · 2020-02-27 04:47

You can use querySelectorAll's forEach function.

document.querySelectorAll('li').forEach(function(element) {
    console.log(element);
});
查看更多
欢心
5楼-- · 2020-02-27 04:58

You're already doing it right

var ancestor = document.getElementById('id'),
    descendents = ancestor.getElementsByTagName('*');
    // gets all descendent of ancestor

Now you just need to loop over children

var i, e, d;
for (i = 0; i < descendents.length; ++i) {
    e = descendents[i];
    e.removeAttribute('style');
    e.removeAttribute('width');
    e.removeAttribute('align');
    if (e.tagName === 'EMBED') {
        d = document.createElement('div');
        d.setAttribute('class', 'video');
        ancestor.appendChild(d);
    }
}

Depending on what you're doing, because you're using getElementsByTagName to get descendents, descendents is a live NodeList, so it's length will change as you add more Nodes to ancestor. If you need to avoid this, convert it to an Array before the loop

decendents = Array.prototype.slice.call(decendents);

See this gist for a reusable function.

查看更多
登录 后发表回答