2010-03-12 6 views
17

Inizialmente chiedevo un modo elegante per simulare la funzionalità Array.concat() sui risultati della funzione getElementsByTagName in IE o nei browser precedenti, perché sembrava che concat non fosse supportato. Solo, ovviamente, il motivo per cui l'oggetto restituito non lo supporta è perché non è uno Array. Oops!Javascript - Concatenare più NodeList insieme

getElementsByTagName restituisce effettivamente un NodeList. La vera domanda, quindi, è: qual è un buon modo per ottenere un singolo elenco di tutti gli elementi del modulo in un documento (input, select, textarea, pulsante) per scorrere in sequenza? Un array non è necessario ... anche un singolo NodeList sarebbe perfetto.

Si noti che sto utilizzando IE6 come questo è per una intranet aziendale (presto IE8 però).

La risposta che mi venne in mente fu:

  • E 'diventato più semplice e probabilmente eseguita meglio appena messo il codice in una funzione separata e chiamarla tre volte con i diversi nodelists, piuttosto che preoccuparsi di un buon modo per riunirli in uno solo.

  • Alla fine sono passato a utilizzare MooTools (dopo diverse ore a leggere i confronti di tutti i diversi framework). Così ora, ottenere una serie di elementi che voglio è molto semplice. Raccomando di utilizzare un framework javascript come questo, piuttosto che persone che si battono il cervello cercando di capire il modo migliore per fare le cose. Certo che sono tutto per imparare effettivamente il linguaggio grezzo (è per questo che ho trattenuto l'uso di un framework per così tanto tempo) ma non è sempre il modo più veloce per far funzionare le cose, che in un'azienda spesso conta tanto come migliorare l'abilità del programmatore con la lingua.

Aggiornamento: quasi 2 anni dopo usavo solo jQuery e il gioco è fatto!

+2

IE supporta questo, puoi chiarire un po 'la domanda? –

+0

L'utilizzo di jQuery è sicuramente la soluzione giusta. Mi sono imbattuto in un caso in cui non avevo accesso a jQuery, però. Ho finito con la creazione di una serie di tag elemento su cui volevo agire e il suo looping, chiamando getElementsByTagName per ognuno. Mi chiedo se sia più o meno efficace della risposta più importante. – bpscott

+0

@bpscott Ma hai messo tutti gli elementi in un singolo array in qualsiasi momento, o hai semplicemente lavorato con loro il valore di un tag alla volta? – ErikE

risposta

31

Per concatenare i nodelist, convertirli in array utilizzando Array.prototype.slice.call e quindi concatenarli normalmente.

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

var c = a.concat(b); 

Edit: (in base al tuo commento)

Se avete solo un paio di tipi di elementi, questo va bene, ma le prestazioni diminuisce con il numero di chiamate effettuate DOM. Potrebbe essere meglio e più veloce fare un document.getElementsByTagName('*'), passare attraverso l'elenco e selezionare gli elementi con il numero richiesto nodeName.

Un'altra cosa da tenere a mente è che il metodo Array.prototype.slice utilizzato in precedenza potrebbe non funzionare in TUTTI i browser. Controlla la riga di partenza del commento n. 723 in sizzle.js (il motore di selezione dietro jQuery)

Naturalmente, è meglio usare una libreria come jQuery che gestisca tutto il mal di testa.Si può semplicemente fare:

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

Stavo solo cercando un modo semplice per ottenere un elenco di più elementi (in questo caso, gli elementi del modulo INPUT, SELECT, TEXTAREA e possibilmente BUTTON). È questo il modo migliore? Immagino sia ora di aprire una nuova domanda. – ErikE

+0

@Emtucifor: ho aggiornato la mia risposta. –

+0

La citazione è necessaria per la chiamata document.getElementsByTagName ("*") e nodeName è la cosa da cercare. –

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

Non vedo davvero che questo aggiunga molto di più alla risposta selezionata. Grazie per aver partecipato, però! – ErikE

0

che avevo di pensiero non ci sarebbe stato più risposte di questo, in ogni caso ho dato a questo un colpo e si avvicinò con la seguente funzione anche se ho dovuto sbattere un po 'la testa.

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

Problemi: non usare una stringa, usare un array: 'var nodes = ['input', 'select'];' quindi non è necessario dividere. Non modificare i parametri. I parametri di redeclaring sono privi di senso. 'node' non è un buon nome, prova 'tagName' (sono stringhe, non oggetti nodo). JavaScript utilizza idiomaticamente camelCase, quindi 'selected_elements' dovrebbe essere' selectedElements'. – ErikE

0

Come notato nel MDN Documentation, è anche possibile utilizzare Array.from per convertire un NodeList in a una matrice su browser che lo supportano.