2009-05-27 9 views
27

Czy istnieje sposób na połączenie 2 węzłów zwróconych przez 2 wywołania document.getElementsByTagName?JavaScript NodeList

Powiedz, mam następujący kod

var inputs = documentElement.getElementsByTagName('input'); 
var selects = document.getElementsByTagName('select'); 

chcę pętli wyników. Czy to możliwe w jednej pętli?

Z góry dziękuję!

+0

Zapętlasz je w tym samym czasie lub sekwencyjnie? –

Odpowiedz

46

Wydaje się, można używać tego samego Array.prototype.slice.call który sprawia, że ​​tablica args podobny przedmiot staje się tablicą. (See here)

var inputs = document.getElementsByTagName('input'); 
var selects = document.getElementsByTagName('select'); 

inputs = Array.prototype.slice.call(inputs); 
selects = Array.prototype.slice.call(selects); 

var res = inputs.concat(selects); 

alert(res.length); 
+1

Już miałem to powiedzieć :) +1 Prototype i inne biblioteki używają plaster do konwertowania list węzłów na tablice. –

+10

Drobne, o czym trzeba pamiętać, jest to, że nie działa to w przeglądarce Internet Explorer ani w przeglądarce BlackBerry. jQuery 1.4 ma interesujący test, który służy do powrotu do pętli w celu połączenia list węzłów. Wyciągnąłem go tutaj: http://pastebin.com/TkTwMG17 –

4

O ile mi wiadomo, typ NodeList jest niezmienna (patrz this article na przykład), co oznacza, że ​​będziesz musiał wygenerować własny obiekt.

Prostą metodą byłoby stworzenie tablicy i skopiowanie wszystkich elementów do tej tablicy.

var inputs = documentElement.getElementsByTagName('input'); 
var selects = document.getElementsByTagName('select'); 
var all = new Array(inputs.length + selects.length); 

var index = 0; 
for (i = 0; i < inputs.length; i++) 
    all[index++] = inputs[i]; 
for (i = 0; i < selects.length; i++) 
    all[index++] = selects[i]; 

Zmienna all zawiera następnie połączenie dwóch zestawów węzłów.

+0

Potrzebne będą 2 pętle. Dla mojego szczególnego zadania muszę przechodzić przez wyniki tylko raz, więc tworzenie obiektu nie jest tego warte. Nie mogę dołączyć do wyników i to właśnie chciałem wiedzieć, dziękuję! –

+0

Tak, przy użyciu dwóch pętli jest moim zdaniem najlepszym rozwiązaniem. (Rozważyłem opcję jednej pętli, ale to naprawdę nie pomaga.) Cieszę się, że masz rozwiązanie. – Noldorin

+1

Dobrze. A co z Array.prototype.slice.call (thatNodeListOfYours, 0); ? – Witiko

0

Najpierw myślałem, że jest to możliwe przy użyciu Array.prototype Concat tablic, jak poniżej:

Array.prototype.concat.call(selects, inputs); 

Ale to nie działa tak, że zrobiłem e tablice z kolekcji węzeł i concat to. Wygląda na to, że:

(function() { 

    var inputs = document.getElementsByTagName('input'), 
     selects = document.getElementsByTagName('select'), 
     result, 
     i, 
     node; 

    function convert (collection) { 
     var a = []; 
     for (var i = 0, length = collection.length; i < length; i++) { 
      a.push(collection[i]); 
     } 
     return a; 
    } 

    // concatenation && convertation 
    result = Array.prototype.concat(convert(inputs), convert(selects)); 
    // traversing 
    i = result.length; 
    while(node = result[--i]) { 
     alert(node.getAttribute('name')); 
    } 

})(); 
+0

Wierzę, że pierwsza sztuczka działa w dowolnej (większej) przeglądarce z wyjątkiem IE. –

+0

Pierwsza sztuczka nie działa w przeglądarkach opartych na WebKit (safari, chrome) –

20

Nie można do nich dołączyć, ale nadal można pętla przez nich kolejno w jednej pętli tak:

for (var i = 0; i < inputs.length + selects.length; i++) { 
    var element = (i < inputs.length) ? inputs[i] : selects[i-inputs.length]; 
} 

Alternatywnie, przy użyciu jQuery, można wybrać je wszystkie w jednym zamachem:

$('input, select') 
+0

+1 za udostępnienie obu opcji, a elegancka pętla – annakata

+0

+1 za wskazanie opcji jQuery. –

+0

Nice! thnaks :) –

12
document.querySelectorAll("input, select"); 
+2

wymaga FF 3.1+, Safari 3.1+ lub IE8 + – Dementic

1

Rzuciłem tym razem. Może być trochę narzut na wykonanie każdej z pętli, ale myślę, że jest ona niewielka, chyba że liczba elementów stanie się ekstremalna.

inputs = div.getElementsByTagName('input'); 
selects = div.getElementsByTagName('select'); 
for (i=0; i<inputs.length+selects.length; i++) { 
    element = (i<inputs.length ? inputs[i] : selects[i-inputs.length]); 

    // do whatever with element 
} 
+0

Nieważne, tak samo jak kilka wpisów powyżej ... nie widziałem. –

1

Mój krótki kod skryptozakładki:

var e, t = d.getElementsByTagName('textarea'), u = d.getElementsByTagName('input'), i = t.length; 
    while(e = (i > 0) ? t[--i] : u[-i--]){ if(e.offsetHeight > 0)... } 
2
function mergeNodeLists(a, b) { 
    var slice = Array.prototype.slice; 
    return slice.call(a).concat(slice.call(b)); 
} 

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

0

Teraz na pewno będę korzystać z następujących powodów:

Chrome, Firefox 3.5+ IE8 +

var elements = document.querySelectorAll('a'); 

for (var i = 0, element; (element = elements[i]); i++) { 
    console.log(element); 
} 

IE11, Firefox 24+, 30+ chrom (z eksperymentów włączone)

let elements = document.querySelectorAll('a'); 

for (let i = 0, element; (element = elements[i]); i++) { 
    console.log(element); 
} 

"element = elementów [j]" jest korzystniejszy "elements.length", ponieważ:

"Listy węzłów są często implementowane jako iteratory węzłów z filtrem, co oznacza, że ​​otrzymanie właściwości takiej jak długość jest O (n), a iterowanie po liście przez ponowne sprawdzenie długości będzie O (n^2) . "

W przeciwieństwie do dostępu do tablicy, o ile pamiętam O (1).

Więcej szczegółów:

0

Array.prototype.slice.call() nie działa w IE 7, użyj tego:

Object.prototype.getMyElements = function(tags){ 
    tags = tags.split(','); 
    var i, j, col=[], ci=0; 
    for(i=0; i<tags.length; i++) { 
     var objs = this.getElementsByTagName(tags[i]); 
     for(j=0; j<objs.length; j++) col[ci++] = objs[j]; 
    } 
    return col; 
} 
var objs = document.getMyElements('INPUT,TEXTAREA'); 
var objs = document.getElementById('myform').getMyElements('INPUT,TEXTAREA'); 
0

spróbować swoich sposób:

var allES = []; 
var inputs = document.getElementsByTagName("input"); 
     for (i = 0; i < inputs.length; i++) { 
       allES.push(inputs[i]); 
      } 
    // gather SELECT elements 
     var selects = document.getElementsByTagName("select"); 
      for (i=0; i < selects.length; i++){ 
       allES.push(selects[i]); 
       } 
Powiązane problemy