2010-03-12 7 views
17

Ich fragte ursprünglich nach einer eleganten Möglichkeit, die Array.concat() Funktionalität auf die Ergebnisse der getElementsByTagName Funktion in IE oder älteren Browsern zu simulieren, weil es schien, dass concat nicht unterstützt wurde. Nur natürlich - der Grund, warum das zurückgegebene Objekt dies nicht unterstützt, ist, dass es kein Array ist. Hoppla!Javascript - Verkettung mehrerer NodeLists zusammen

getElementsByTagName gibt tatsächlich eine NodeList zurück. Die wirkliche Frage ist also: Was ist eine gute Möglichkeit, um eine einzige Liste aller Formularelemente in einem Dokument (Eingabe, Auswahl, Textbereich, Schaltfläche) zu erhalten, um sie durchzulaufen? Ein Array ist nicht erforderlich ... eine einzige NodeList wäre auch perfekt.

Beachten Sie, dass ich IE6 verwende, wie dies für ein Firmenintranet (bald IE8 obwohl) ist.

Die Antwort, die ich kam mit war:

  • es einfacher geworden ist und ausgeführt wahrscheinlich besser, nur den Code in eine separate Funktion gesetzt und dreimal mit den verschiedenen Nodelisten zu nennen, anstatt zu befürchten ein guter Weg, sie zu einem zusammenzuflicken.

  • Ich wechselte schließlich zu MooTools (nach mehreren Stunden Lesen von Vergleichen aller verschiedenen Frameworks). Jetzt ist es sehr einfach, ein Array mit den gewünschten Elementen zu erhalten. Ich empfehle, ein JavaScript-Framework wie dieses zu verwenden, anstatt Leute, die ihre Gehirne heraus prügeln, die versuchen, den besten Weg zu finden, Sachen zu tun. Natürlich bin ich nur dafür, die rohe Sprache zu lernen (weshalb ich mich so lange auf ein Framework beschränkt habe), aber es ist nicht immer der schnellste Weg, Dinge in Gang zu bringen, was in einem Unternehmen oft so wichtig ist als Verbesserung der Fähigkeiten des Coders mit der Sprache.

Update: fast 2 Jahre später würde ich nur jQuery verwenden und damit fertig sein!

+2

IE unterstützt dies, können Sie die Frage ein wenig klären? –

+0

Mit jQuery ist definitiv der Weg zu gehen. In einem Fall, in dem ich keinen Zugriff auf jQuery hatte, stieß ich jedoch darauf. Am Ende habe ich ein Array von Element-Tags erstellt, auf denen ich agieren und es durchlaufen wollte, indem ich getElementsByTagName für jedes Element aufruft. Ich frage mich, ob das mehr oder weniger effizient ist als die beste Antwort. – bpscott

+0

@bpscott Aber hast du alle Elemente an einem Punkt in ein Array gelegt oder arbeitest du nur mit einem Tag? – ErikE

Antwort

31

Um Nodelists zu verketten, konvertieren Sie sie in Arrays mit Array.prototype.slice.call und dann concat normal.

var a = Array.prototype.slice.call(document.getElementsByTagName("p")), 
    b = Array.prototype.slice.call(document.getElementsByTagName("div")) 

var c = a.concat(b); 

Edit: (Als Reaktion auf Ihren Kommentar)

Wenn Sie nur ein paar Typen von Elementen haben, ist dies in Ordnung, aber die Leistung nimmt mit der Anzahl der DOM Anrufe, die Sie machen. Es kann besser und schneller sein, eine document.getElementsByTagName('*') zu tun, Schleife durch die Liste und wählen Sie die Elemente mit den erforderlichen nodeName.

Eine andere Sache zu beachten ist, dass die oben verwendete Array.prototype.slice Methode möglicherweise nicht in allen Browsern funktioniert. Überprüfen Sie die Kommentar-Startlinie # 723 in sizzle.js (die Selektor-Engine hinter jQuery)

Natürlich ist es am besten, eine Bibliothek wie jQuery verwenden, die alle Kopfschmerzen behandelt.Sie können einfach tun:

$("input, select, textarea, <other tags>") 
+0

Ich war nur auf der Suche nach einer einfachen Möglichkeit, eine Liste von mehreren Elementen zu erhalten (in diesem Fall, Formularelemente INPUT, SELECT, TEXTAREA und möglicherweise BUTTON). Ist das der beste Weg? Ich denke, es ist Zeit, eine neue Frage zu stellen. – ErikE

+0

@Emtucifor: Ich habe meine Antwort aktualisiert. –

+0

Für den Aufruf von document.getElementsByTagName ("*") wird ein Zitat benötigt, und nodeName ist die zu suchende Sache. –

1
var a1=document.getElementsByTagName('div'), 
a2=document.getElementsByTagName('button'); 
a1=[].slice.call(a1, 0,a1.length).concat([].slice.call(a2, 0,a2.length)) 
3
function mergeNodeLists(a, b) { 
    var slice = Array.prototype.slice; 
    return slice.call(a).concat(slice.call(b)); 
} 

console.log(mergeNodeLists(inputs, selects)); // => [input, select]

+1

Ich sehe nicht wirklich, dass dies viel mehr zur ausgewählten Antwort hinzufügt. Danke für die Teilnahme! – ErikE

0

ich gedacht hatte es hätte mehr Antworten gewesen, als dies ohnehin gab ich diesen einen Schuss und kam mit der folgenden Funktion nach oben obwohl ich mir ein bisschen den Kopf schütteln musste.

function group_elements(element, tags) { 
    var elements = element.getElementsByTagName('*'); 
    var results = []; 
    for (var i = 0; i < elements.length; ++i) { 
     if (tags.indexOf(elements[i].nodeName.toLowerCase()) > -1) { 
     results.push(elements[i]); 
     } 
    } 
    return results; 
} 


var form = document.getElementById('form'); 
var tags = ['input', 'select']; 
console.log(group_elements(form, tags)); 
+0

Probleme: Verwenden Sie keine Zeichenfolge, verwenden Sie ein Array: 'var nodes = ['input', 'select'];' dann keine Notwendigkeit, zu teilen. Ändern Sie keine Parameter. Parameter neu zu deklarieren ist unsinnig. 'node' ist kein guter Name, try'tagName' (sie sind Strings, keine Knotenobjekte). JavaScript verwendet idiomatisch camelCase, also sollte 'selected_elements'' selectedElements' sein. – ErikE

1

Mit dem ES6 spread operator können Sie

let arr = [...nodeList1, ...nodeList2]; 
+0

Ich habe gerade gestern darüber nachgedacht! – ErikE

0

tun Wie in der MDN Documentation erwähnt, können Sie auch Array.from verwenden, um eine NodeList in einem Array auf Browsern zu konvertieren, die sie unterstützen.