2013-07-23 7 views
13

Ich habe jQuery benutze dies zu tun:Schleife durch alle Nachkommen eines div - JS nur

$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"); 
    }; 
}); 

Aber ich habe gelesen, dass .each() Methode jQuery ist ziemlich langsam, wenn für Schleife auf einen einfachen Vergleich (jsPerf). Meine Frage ist, wie kann ich das mit reinem JS nachahmen? Finden Sie alle Elemente innerhalb einer div, dann durchlaufen Sie die Knoten.

Ich habe versucht, dies zu suchen, aber alles, was ich finden kann, sind jQuery Antworten - überall.

Ich habe andere Dinge ausprobiert, aber das war so nah, wie ich auf die Auswahl alle Nachkommen bekam:

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

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

der Grund für die Existenz von jquery ist genau dies ... es langsamer sein kann (wie cares ...), aber es wird auf allen Browsern ... wollen Sie wirklich den dom iterieren Baum und machen es in allen Browsern funktionieren? – Rufinus

+0

[] .slice.call (elm.children) gibt Ihnen ein Array von untergeordneten Elementen, während [] .slice.call (elm.childNodes) Textknoten enthält.getElementsByTagName() wird tiefer gehen als direkte Kinder, wenn Sie das möchten. – dandavis

+1

Was ist los mit Ihrer Vanilla JS-Lösung? –

Antwort

19

Sie tun es schon richtig

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

Jetzt müssen Sie nur eine Schleife über 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); 
    } 
} 

Je nachdem, was Sie tun, weil Sieverwendendescendents zu bekommen, ist descendents ein LiveNodeList, so ist es Länge ändert sich, wie Sie mehr Knoten-ancestor hinzufügen. Wenn Sie dies vermeiden müssen, wandelt es in einen Array vor der Schleife

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

Siehe this gist für eine wiederverwendbare Funktion.

+0

LOL meine Antwort ist (was: P) praktisch identisch mit deiner –

+0

@LightStyle außer meiner enthält ein 'i'mprovised' e'xplosive 'd'evice 8-) –

+0

Da es eine Live-Liste ist, muss ich in Array konvertieren oder kann ich die Länge gerade noch rechtzeitig speichern, wenn ich mit dem Looping beginne? –

3

könnten Sie einfach so einfach wie dieses verwenden?

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

kommentierte ich in @ Paul S. Antwort, die Sie auch den Knoten klonen und ein Dokumentfragment neue bettet hinzufügen können könnte. Hier ein Beispiel:

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

können Sie die Demo sehen here.

Klonen der Knoten verhindert, dass die Live-Modifikation der DOM seit dem Attribut style kann Eigenschaften haben, die den Browser veranlassen zu re Malen Sie mehrmals.

1

Sie können die forEach-Funktion von querySelectorAll verwenden.

document.querySelectorAll('li').forEach(function(element) { 
    console.log(element); 
}); 
Verwandte Themen