2009-05-27 19 views
27

¿Hay alguna manera de unir 2 NodeLists devuelto por 2 llamadas de document.getElementsByTagName?JavaScript NodeList

decir que tengo el siguiente código

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

Quiero recorrer los resultados. ¿Es posible en un ciclo?

¡Gracias de antemano!

+0

¿Buclear ambos al mismo tiempo o secuencialmente? –

Respuesta

46

Parece que se puede utilizar el mismo Array.prototype.slice.call que hace que el conjunto args como objetivo convertirse en una matriz. (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

Estaba a punto de decir que :) +1 Prototype y otras bibliotecas usan slice para convertir las listas de nodos a matrices. –

+10

Una cosa menor a tener en cuenta es que esto no funcionará en Internet Explorer ni en el navegador de BlackBerry. jQuery 1.4 tiene una prueba interesante que se utiliza para volver a un ciclo para combinar listas de nodos. Lo he extractado aquí: http://pastebin.com/TkTwMG17 –

4

Por lo que yo sé, el tipo NodeList es inmutable (ver this article por ejemplo), lo que significa que tendrá que generar su propio objeto.

Un método simple sería simplemente crear una matriz y copiar todos los elementos en esa matriz.

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]; 

La variable all contiene entonces la unión de los dos conjuntos de nodos.

+0

Necesitará 2 bucles de todos modos. Para mi tarea particular, necesito recorrer los resultados solo una vez, por lo que no vale la pena crear un objeto. No puedo unirme a los resultados y eso es lo que quería saber, ¡gracias! –

+0

Sí, usar dos bucles es la solución más clara en mi opinión, de todos modos. (Consideré la opción de un ciclo, pero en realidad no ayuda mucho). Me alegra que tenga una solución. – Noldorin

+1

Bueno. ¿Y qué pasa con Array.prototype.slice.call (thatNodeListOfYours, 0); ? – Witiko

0

En primer lugar, pensé que esto es posible a concat matrices usando Array.prototype, así:

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

Pero esto no funciona, por lo que he hecho una de las colecciones de matrices de nodos y concat eso. Parece que:

(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

Creo que el primer truco funciona en cualquier navegador (principal) a excepción de IE. –

+0

Y el primer truco no funcionará en los navegadores basados ​​en WebKit (safari, chrome) –

20

No puede unirse a ellos, pero todavía se puede recorrer de forma secuencial en un bucle como este:

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

Alternativamente, usando jQuery, podría seleccionar a todos en de una sola vez:

$('input, select') 
+0

+1 para proporcionar ambas opciones, y el elegante for loop – annakata

+0

+1 para señalar la opción jQuery. –

+0

¡Agradable! thnaks :) –

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

requiere FF 3.1+, Safari 3.1+, o IE8 + – Dementic

1

me tiró esto juntos. Puede haber un poco de sobrecarga al hacer un si y .length para cada ciclo, pero creo que es menor a menos que el número de elementos sea extremo.

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

No importa, lo mismo que algunas publicaciones anteriores ... no lo vi. –

1

Mi código corto para bookmarklets:

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

Hoy en día sin duda lo utilice lo siguiente:

Chrome, Firefox 3.5+, IE8 +

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

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

EI11 +, Firefox 24+, 30+ Chrome (con experimentos habilitados)

"elemento = elementos [i]"
let elements = document.querySelectorAll('a'); 

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

se prefiere sobre "elements.length" desde:

"Las listas de nodos a menudo se implementan como iteradores de nodos con un filtro. Esto significa que obtener una propiedad como la longitud es O (n) e iterar sobre la lista volviendo a verificar la longitud será O (n^2) "

A diferencia del acceso a la matriz, que es lo que recuerdo O (1).

Más detalles:

0

Array.prototype.slice.call() falla en IE 7, utilice esto:

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

intentar mi manera:

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]); 
       } 
Cuestiones relacionadas