Javascript: Bagaimana cara loop melalui SEMUA elemen DOM pada halaman?

156

Saya mencoba untuk mengulang semua elemen pada halaman, jadi saya ingin memeriksa setiap elemen yang ada di halaman ini untuk kelas khusus.

Jadi, bagaimana saya mengatakan bahwa saya ingin memeriksa setiap elemen?

Florian Müller
sumber
1
apakah Anda yakin ingin mengulang setiap elemen sendiri? mengapa tidak menggunakan jquery dan penyeleksi untuk mengambil elemen yang dari kelas tertentu?
NG.
Apakah tidak ada metode document.getElementsByTagName?
SuperJedi224
* TL; DR: Untuk elemen yang hanya terlihat, gunakan:document.body.getElementsByTagName('*')
Andrew
Iterate dengan:for (... of ...) { }
Andrew

Jawaban:

252

Anda dapat meneruskan *ke getElementsByTagName()sehingga akan mengembalikan semua elemen di halaman:

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

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

Perhatikan bahwa Anda dapat menggunakan querySelectorAll(), jika tersedia (IE9 +, CSS di IE8), hanya untuk menemukan elemen dengan kelas tertentu.

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

Ini tentu akan mempercepat masalah untuk browser modern.


Browser sekarang mendukung foreach di NodeList . Ini berarti Anda dapat langsung mengulang elemen daripada menulis sendiri untuk loop.

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

Catatan kinerja - Lakukan yang terbaik untuk lingkup apa yang Anda cari. Selektor universal dapat mengembalikan banyak node tergantung pada kompleksitas halaman. Sekalipun Anda perlu melihat-lihat segala sesuatu yang mungkin dilihat seseorang, itu artinya Anda dapat menggunakan 'body *'sebagai pemilih untuk memotong semua headkonten.

Andy E
sumber
2
Metode ini tampaknya sangat bagus, tetapi bagaimana saya bisa memilih elemen di metode atas? Saya hanya mendapat indeks 'i'?
Florian Müller
2
@Florian: sama seperti Anda akan mengakses elemen array - all[i]akan memberi Anda elemen saat ini.
Andy E
2
Bagaimana cara memilih elemen di samping loop?
Debiprasad
2
@JesseAldridge: hanya kekuatan kebiasaan / praktik yang baik. Menghindari pencarian properti pada setiap iterasi biasanya merupakan optimasi mikro, tetapi tidak terlalu sulit untuk menulis dan jadi saya hanya melakukannya secara alami.
Andy E
2
@ Jonathan getElementsByClassName()memiliki dukungan yang lebih buruk daripada querySelectorAll()(yang sebelumnya tidak didukung di IE 8). OP dengan jelas menyatakan bahwa ia ingin mengulang semua elemen pada halaman, yang saya berikan solusinya dan menawarkan alternatif. Saya tidak yakin apa masalahnya dengan itu ;-).
Andy E
39

Sedang mencari yang sama. Ya tidak. Saya hanya ingin mendaftar semua DOM Nodes.

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

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

Untuk mendapatkan elemen dengan kelas tertentu, kita bisa menggunakan fungsi filter.

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);
}

Menemukan solusi pada MDN

tradisional
sumber
tidak pernah melihat document.ceeateNodeIterator. Tampaknya menarik apa yang dibawa fitur baru JS;)
Florian Müller
2
Fitur keren dari ini adalah bahwa nodeiterator juga berjalan di node sesuai urutan yang muncul di html. Saya ingin tahu apakah beberapa di antaranya document.body.getElementsByTagName('*')dapat mengembalikan node dalam urutan acak.
Sipil
Wow itu sebenarnya didukung dengan baik!
rogerdpack
15

Seperti biasa solusi terbaik adalah menggunakan rekursi:

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

Tidak seperti saran lain, solusi ini tidak mengharuskan Anda untuk membuat array untuk semua node, sehingga lebih ringan pada memori. Lebih penting lagi, ia menemukan lebih banyak hasil. Saya tidak yakin apa hasil itu, tetapi ketika pengujian pada chrome ia menemukan sekitar 50% lebih banyak node dibandingkandocument.getElementsByTagName("*");

Ilya Gazman
sumber
19
Waktu terbaik untuk menggunakan rekursi adalah waktu terbaik untuk menggunakan rekursi.
Adamlive
8
“Ia menemukan sekitar 50% lebih banyak node dibandingkan dengan document.getElementsByTagName("*");” - ya, itu akan menemukan node teks dan komentar node serta elemen node . Karena OP hanya bertanya tentang elemen, itu tidak perlu.
Paul D. Waite
1
Ini mungkin lebih ringan pada memori. Bergantung pada seberapa banyak yang Anda lakukan di setiap tingkat rekursi, Anda dapat membangun tumpukan panggilan yang besar pada saat Anda sampai di bawah. A NodeListhanya mereferensikan Nodes yang sudah dibangun di DOM Anda, jadi itu tidak seberat yang Anda bayangkan. Seseorang yang tahu lebih banyak bisa menimbang, tapi saya pikir itu hanya ukuran referensi memori, jadi 8 byte per node.
Josh dari Qaribou
9

Berikut adalah contoh lain tentang bagaimana Anda bisa mengulang dokumen atau elemen:

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;
}
Juggernogger93
sumber
4

Bagi mereka yang menggunakan Jquery

$("*").each(function(i,e){console.log(i+' '+e)});
Matas Vaitkevicius
sumber
3

Andy E. memberikan jawaban yang bagus.

Saya akan menambahkan, jika Anda merasa untuk memilih semua anak di beberapa pemilih khusus (kebutuhan ini terjadi pada saya baru-baru ini), Anda dapat menerapkan metode "getElementsByTagName ()" pada objek DOM yang Anda inginkan.

Sebagai contoh, saya hanya perlu menguraikan bagian "visual" dari halaman web, jadi saya membuatnya

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

Ini tidak akan pernah mempertimbangkan bagian kepala.

korvus
sumber
Luar biasa! . . .
Andrew
2

dari tautan ini
referensi 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>

PEMBARUAN: EDIT

sejak jawaban terakhir saya, saya menemukan solusi yang lebih sederhana dan lebih baik

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

    }
shareef
sumber
menurut diskusi SO ini , document.alltidak disarankan document.getElementBy*.
thejoshwolfe
@thejoshwolfe terima kasih, apa pendapat Anda tentang solusi socond saya yang saya perbarui
shareef
0

Menggunakan *

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

Saya pikir ini sangat cepat

document.querySelectorAll('body,body *').forEach(function(e) {
mempertahankan orca
sumber
0

Mendapatkan semua elemen menggunakan var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);tidak apa-apa jika Anda perlu memeriksa setiap elemen tetapi akan menghasilkan memeriksa atau mengulang elemen berulang atau teks.

Di bawah ini adalah implementasi rekursi yang memeriksa atau mengulang setiap elemen dari semua elemen DOM hanya sekali dan menambahkan:

(Kredit ke @George Reith untuk jawaban rekursi di sini: Peta HTML ke 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);

}
Yi Xiang Chong
sumber
-1

Anda bisa mencobanya document.getElementsByClassName('special_class');

Jimish Gamit
sumber
4
Metode yang benar adalah getElementsByClassName()dan itu tidak didukung oleh Internet Explorer hingga versi 9.
Andy E