Javascript: come eseguire il loop di TUTTI gli elementi DOM su una pagina?


156

Sto cercando di eseguire il ciclo su TUTTI gli elementi in una pagina, quindi desidero controllare ogni elemento esistente in questa pagina per una classe speciale.

Quindi, come posso dire che voglio controllare OGNI elemento?


1
sei sicuro di voler passare in rassegna ogni elemento da solo? perché non usare jquery e selettori per afferrare elementi che appartengono a quella particolare classe?
GN.

Non esiste un metodo document.getElementsByTagName?
SuperJedi224,

* TL; DR: per gli elementi solo visibili, utilizzare:document.body.getElementsByTagName('*')
Andrew

Scorri con:for (... of ...) { }
Andrew

Risposte:


252

Puoi passare un *a in getElementsByTagName()modo che restituisca tutti gli elementi in una pagina:

var all = document.getElementsByTagName("*");

for (var i=0, max=all.length; i < max; i++) {
     // Do something with the element here
}

Si noti che è possibile utilizzare querySelectorAll(), se disponibile (IE9 +, CSS in IE8), per trovare elementi con una particolare classe.

if (document.querySelectorAll)
    var clsElements = document.querySelectorAll(".mySpeshalClass");
else
    // loop through all elements instead

Ciò accelererebbe sicuramente le cose per i browser moderni.


I browser ora supportano foreach su NodeList . Ciò significa che è possibile eseguire il ciclo diretto degli elementi anziché scrivere il proprio per il ciclo.

document.querySelectorAll('*').forEach(function(node) {
    // Do whatever you want with the node object.
});

Nota sulle prestazioni : fai del tuo meglio per individuare ciò che stai cercando. Un selettore universale può restituire molti nodi a seconda della complessità della pagina. Anche se hai bisogno di guardare tutto ciò che qualcuno potrebbe vedere, ciò significa che puoi usare 'body *'come selettore per tagliare tutto il headcontenuto.


2
Questo metodo sembra molto carino, ma come posso selezionare un elemento nel metodo superiore? Ho solo l'indice 'i'?
Florian Müller,

2
@Florian: proprio come accederesti a un elemento array - all[i]ti darebbe l'elemento corrente.
Andy E

2
Come selezionare l'elemento a lato del loop?
Debiprasad,

2
@JesseAldridge: solo una forza di abitudine / buone pratiche. Evitare la ricerca di proprietà su ogni iterazione è di solito una micro-ottimizzazione, ma non è particolarmente più difficile da scrivere e quindi lo faccio semplicemente.
Andy E

2
@Jonathan getElementsByClassName()ha un supporto peggiore di querySelectorAll()(il primo non è supportato in IE 8). L'OP ha chiaramente affermato che vuole passare in rassegna tutti gli elementi di una pagina, per il quale gli ho dato la soluzione e gli ho offerto un'alternativa. Non sono sicuro di quale sia il problema con questo ;-).
Andy E

39

Stava cercando lo stesso. Bene, non esattamente. Volevo solo elencare tutti i nodi DOM.

var currentNode,
    ni = document.createNodeIterator(document.documentElement, NodeFilter.SHOW_ELEMENT);

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}

Per ottenere elementi con una classe specifica, possiamo usare la funzione filtro.

var currentNode,
    ni = document.createNodeIterator(
                     document.documentElement, 
                     NodeFilter.SHOW_ELEMENT,
                     function(node){
                         return node.classList.contains('toggleable') ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
                     }
         );

while(currentNode = ni.nextNode()) {
    console.log(currentNode.nodeName);
}

Soluzione trovata su MDN


mai visto document.ceeateNodeIterator. Sembra interessante quali nuove funzionalità offre JS;)
Florian Müller,

2
Una caratteristica interessante di questo è che il nodoiterator percorre anche i nodi nell'ordine in cui appaiono nell'html. Mi chiedo se alcuni dei document.body.getElementsByTagName('*')potrebbero restituire i nodi in ordine confuso.
Civile,

Wow, in realtà è ben supportato!
rogerdpack

15

Come sempre la soluzione migliore è utilizzare la ricorsione:

loop(document);
function loop(node){
    // do some thing with the node here
    var nodes = node.childNodes;
    for (var i = 0; i <nodes.length; i++){
        if(!nodes[i]){
            continue;
        }

        if(nodes[i].childNodes.length > 0){
            loop(nodes[i]);
        }
    }
}

A differenza di altri suggerimenti, questa soluzione non richiede di creare un array per tutti i nodi, quindi è più leggero sulla memoria. Ancora più importante, trova più risultati. Non sono sicuro di quali siano questi risultati, ma durante i test su Chrome rileva circa il 50% in più di nodi rispettodocument.getElementsByTagName("*");


19
Il momento migliore per usare la ricorsione è il momento migliore per usare la ricorsione.
Adamlive,

8
"Trova circa il 50% in più di nodi rispetto a document.getElementsByTagName("*");" - sì, troverà nodi di testo e nodi di commento, nonché nodi di elementi . Dato che l'OP stava solo chiedendo degli elementi, non è necessario.
Paul D. Waite,

1
Si potrebbe essere più leggero sulla memoria. A seconda di quanto fai in ogni livello di ricorsione, puoi creare uno stack di chiamate possibilmente grande prima di arrivare in fondo. A NodeListsta semplicemente facendo riferimento a quelli Nodegià creati nel DOM, quindi non è così pesante come si potrebbe immaginare. Qualcuno che ne sa di più può pesare, ma penso che sia solo una dimensione di riferimento della memoria, quindi 8 byte per nodo.
Josh di Qaribou,

9

Ecco un altro esempio su come è possibile eseguire il ciclo tra un documento o un elemento:

function getNodeList(elem){
var l=new Array(elem),c=1,ret=new Array();
//This first loop will loop until the count var is stable//
for(var r=0;r<c;r++){
    //This loop will loop thru the child element list//
    for(var z=0;z<l[r].childNodes.length;z++){

         //Push the element to the return array.
        ret.push(l[r].childNodes[z]);

        if(l[r].childNodes[z].childNodes[0]){
            l.push(l[r].childNodes[z]);c++;
        }//IF           
    }//FOR
}//FOR
return ret;
}


3

Andy E. ha dato una buona risposta.

Aggiungerei, se ritieni di selezionare tutti i bambini in un selettore speciale (questo bisogno mi è successo di recente), puoi applicare il metodo "getElementsByTagName ()" su qualsiasi oggetto DOM che desideri.

Per un esempio, dovevo solo analizzare parte "visiva" della pagina Web, quindi ho appena fatto questo

var visualDomElts = document.body.getElementsByTagName('*');

Questo non prenderà mai in considerazione la parte principale.


Eccellente! . . .
Andrew

2

da questo link
riferimento javascript

<html>
<head>
<title>A Simple Page</title>
<script language="JavaScript">
<!--
function findhead1()
{
    var tag, tags;
    // or you can use var allElem=document.all; and loop on it
    tags = "The tags in the page are:"
    for(i = 0; i < document.all.length; i++)
    {
        tag = document.all(i).tagName;
        tags = tags + "\r" + tag;
    }
    document.write(tags);
}

//  -->
</script>
</head>
<body onload="findhead1()">
<h1>Heading One</h1>
</body>
</html>

UPDATE: EDIT

dalla mia ultima risposta ho trovato una soluzione più semplice

function search(tableEvent)
    {
        clearResults()

        document.getElementById('loading').style.display = 'block';

        var params = 'formAction=SearchStocks';

        var elemArray = document.mainForm.elements;
        for (var i = 0; i < elemArray.length;i++)
        {
            var element = elemArray[i];

            var elementName= element.name;
            if(elementName=='formAction')
                continue;
            params += '&' + elementName+'='+ encodeURIComponent(element.value);

        }

        params += '&tableEvent=' + tableEvent;


        createXmlHttpObject();

        sendRequestPost(http_request,'Controller',false,params);

        prepareUpdateTableContents();//function js to handle the response out of scope for this question

    }

secondo questa discussione SO , document.allè scoraggiato a favore di document.getElementBy*.
thejoshwolfe,

@thejoshwolfe grazie cosa ne pensi della mia soluzione socond che ho aggiornato
shareef

0

Uso *

var allElem = document.getElementsByTagName("*");
for (var i = 0; i < allElem.length; i++) {
    // Do something with all element here
}

0

penso che sia molto veloce

document.querySelectorAll('body,body *').forEach(function(e) {

0

Ottenere tutti gli elementi utilizzando var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);è ok se è necessario controllare ogni elemento, ma comporterà il controllo o il ciclo di elementi o testo ripetuti.

Di seguito è un'implementazione di ricorsione che controlla o esegue il ciclo di ogni elemento di tutti gli elementi DOM una sola volta e accoda:

(Ringraziamenti a @George Reith per la sua risposta ricorsiva qui: mappa HTML a JSON )

function mapDOMCheck(html_string, json) {
  treeObject = {}

  dom = new jsdom.JSDOM(html_string) // use jsdom because DOMParser does not provide client-side Window for element access
  document = dom.window.document
  element = document.querySelector('html')

  // Recurse and loop through DOM elements only once
  function treeHTML(element, object) {
    var nodeList = element.childNodes;

    if (nodeList != null) {
      if (nodeList.length) {
        object[element.nodeName] = []; // IMPT: empty [] array for parent node to push non-text recursivable elements (see below)

        for (var i = 0; i < nodeList.length; i++) {
          console.log("nodeName", nodeList[i].nodeName);

          if (nodeList[i].nodeType == 3) { // if child node is **final base-case** text node
            console.log("nodeValue", nodeList[i].nodeValue);
          } else { // else
            object[element.nodeName].push({}); // push {} into empty [] array where {} for recursivable elements
            treeHTML(nodeList[i], object[element.nodeName][object[element.nodeName].length - 1]);
          }
        }
      }
    }
  }

  treeHTML(element, treeObject);

}

-1

Puoi provare con document.getElementsByClassName('special_class');


4
Il metodo corretto è getElementsByClassName()e non è supportato da Internet Explorer fino alla versione 9.
Andy E
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.