JavaScript:ページ上のすべてのDOM要素をループする方法は?


156

ページ上のすべての要素をループ処理しようとしているので、このページに存在するすべての要素をチェックして、特別なクラスを探します。

それで、すべての要素をチェックしたいと言うにはどうすればよいですか?


1
自分ですべての要素をループしてよろしいですか?jqueryとセレクターを使用して、その特定のクラスの要素を取得しないのはなぜですか?
NG。

document.getElementsByTagNameメソッドはありませんか?
SuperJedi224

* TL; DR:可視要素のみ、使用:document.body.getElementsByTagName('*')
アンドリュー

イテレート:for (... of ...) { }
アンドリュー

回答:


252

a *を渡してgetElementsByTagName()、ページ内のすべての要素を返すことができます。

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

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

が使用querySelectorAll()可能な場合(IE9 +、IE8のCSS)、特定のクラスの要素を検索するために使用できることに注意してください。

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

これは確かに最新のブラウザの問題をスピードアップするでしょう。


ブラウザはNodeListでforeachをサポートするようになりました。つまり、独自のforループを作成する代わりに、要素を直接ループできます。

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

パフォーマンスのメモ -探しているものを対象とするために最善を尽くしてください。ユニバーサルセレクターは、ページの複雑さに応じて多くのノードを返すことができます。誰かが目にする可能性のあるすべてを調べる必要がある場合でも、'body *'すべてのheadコンテンツを切り取るセレクターとして使用できます。


2
この方法は非常にいいようですが、上の方法で要素を選択するにはどうすればよいですか?インデックス「i」しかありませんか?
フロリアン・ミュラー

2
@Florian:配列要素にアクセスするのと同じようにall[i]、現在の要素を取得します。
アンディE

2
ループ内の要素を選択するにはどうすればよいですか?
Debiprasad 2013

2
@JesseAldridge:習慣/良い習慣の力。すべての反復でプロパティルックアップを回避することは、通常、マイクロ最適化ですが、書くのはそれほど難しくはないので、自然にそれを行います。
アンディE

2
@Jonathan getElementsByClassName()querySelectorAll()(前者はIE 8ではサポートされていません)よりもサポートが劣っています。OP は、ページ上のすべての要素をループしたいことを明確に述べていました。そのため、私は彼にソリューションを提供し、代替案を提供しました。何が問題なのか、私にはわかりません;-)。
アンディE

39

同じを探していました。まあ、そうではありません。私はすべてのDOMノードをリストしたかっただけです。

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

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

特定のクラスの要素を取得するには、フィルター関数を使用できます。

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

MDNで見つかったソリューション


document.ceeateNodeIteratorを見たことがない。JSがもたらす新しいものを機能面白いようです;)
フロリアン・ミュラー

2
これの優れた機能は、nodeiteratorもhtmlに表示される順序でノードをウォークすることです。いくつかはdocument.body.getElementsByTagName('*')スクランブルされた順序でノードを返すことができるのだろうか。
民間人

うわー、実際には十分にサポートされています!
rogerdpack

15

常に最善の解決策は再帰を使用することです:

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

他の提案とは異なり、このソリューションでは、すべてのノードの配列を作成する必要がないため、メモリの負荷が軽減されます。さらに重要なことに、それはより多くの結果を見つけます。それらの結果が何であるかはわかりませんが、Chromeでテストすると、document.getElementsByTagName("*");


19
再帰を使用する最適な時間は、再帰を使用する最適な時間です。
Adamlive 2017年

8
document.getElementsByTagName("*");見つかったノードの数は約50%増加しています」—そうです。テキストノード、コメントノード、および要素ノードが見つかります。OPが要素について尋ねているだけなので、それは不要です。
ポールD.ウェイト

1
それメモリ上で軽いかもしれません。再帰の各レベルで実行する量に応じて、最下部に到達するまでに非常に大きなコールスタックを構築できます。A NodeListは単にNodeDOMに既に組み込まれているを参照しているだけなので、想像するほど重くはありません。もっと知っている人は重さを量ることができますが、それは単なるメモリ参照サイズなので、ノードあたり8バイトだと思います。
カリブのジョシュ、18年

9

次に、ドキュメントまたは要素をループ処理する別の例を示します。

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.は良い答えを出しました。

特別なセレクターですべての子を選択したい場合(最近、この必要が発生しました)、必要なDOMオブジェクトにメソッド「getElementsByTagName()」を適用できます。

例として、Webページの「視覚的」な部分を解析するだけでよいので、これを作成しました

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

これは決して頭の部分を考慮に入れません。


優れた!。。。
Andrew

2

このリンク
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>

更新:編集

私の最後の答え以来、私はより簡単な解決策を見つけました

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

    }

応じて、このSOの議論document.allの賛成で推奨されてdocument.getElementBy*
thejoshwolfe

@thejoshwolfe私が更新した私のsocondソリューションについてどう思いますか
shareef 2013

0

使用する *

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


0

すべての要素をvar all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++);チェックする必要がある場合は、使用してすべての要素を取得できますが、繰り返しの要素またはテキストのチェックまたはループが発生します。

以下は、すべてのDOM要素の各要素を一度だけチェックまたはループして追加する再帰の実装です。

(@George Reithによる再帰の回答は、 HTMLから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

あなたは試すことができます document.getElementsByClassName('special_class');


4
正しい方法がありgetElementsByClassName()、それはバージョン9までのInternet Explorerでサポートされていない
アンディ・E
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.