クラス名で子要素を取得する方法は?


131

クラス= 4の子スパンを取得しようとしています。要素の例を次に示します。

<div id="test">
 <span class="one"></span>
 <span class="two"></span>
 <span class="three"></span>
 <span class="four"></span>
</div>

私が利用できるツールはJSとYUI2です。私はこのようなことができます:

doc = document.getElementById('test');
notes = doc.getElementsByClassName('four');

//or

doc = YAHOO.util.Dom.get('#test');
notes = doc.getElementsByClassName('four');

これらはIEでは機能しません。オブジェクト(doc)がこのメソッドまたはプロパティ(getElementsByClassName)をサポートしていないというエラーが表示されます。getElementsByClassNameのクロスブラウザー実装のいくつかの例を試しましたが、それらを機能させることができず、そのエラーが発生しました。

必要なのはクロスブラウザーのgetElementsByClassNameか、doc.getElementsByTagName( 'span')を使用して、クラス4が見つかるまでループする必要があると思います。ただし、方法はわかりません。


ここでは、次のとおりです。stackoverflow.com/questions/3808808/...
モスタルは

1
面白いことに、より強力なものquerySelectorAllはIE 8以降getElementsByClassNameでサポートされていますが、IE 9以降でのみサポートされています。IE 7をドロップできる場合は、安全に使用できますquerySelectorAll('.4')。ちなみには4無効なクラス名です。
Prinzhorn 2012

@paritybitその質問はまだgetElementsByClassNameを利用しており、IEの古いバージョンはそれをサポートしていないため、機能しません。編集:申し訳ありませんが、タグ名を使用しています。これはうまくいくかもしれません。
spyderman4g63 2012

@Prinzhorn何らかの理由で、この製品で使用できるYUI2セレクターユーティリティがありません。
spyderman4g63 2012

@ spyderman4g63 YUI2固有のことは何も話しませんでした。document.querySelectorAllはDOMであり、YUIとは関係ありません
Prinzhorn 2012

回答:


85

を使用doc.childNodesして各を反復処理しspan、次にclassName等しいをフィルタリングします4

var doc = document.getElementById("test");
var notes = null;
for (var i = 0; i < doc.childNodes.length; i++) {
    if (doc.childNodes[i].className == "4") {
      notes = doc.childNodes[i];
      break;
    }        
}


1
問題は、getElementsByClassNameがIE8で機能しないことです。
spyderman4g63 2012

7
要素に複数のクラスがある場合、このコードは機能しません。たとえば、「1」クラスの要素を探していて、要素に「1 2 3」クラスがある場合、この関数はそれらを見つけません。
フランベロナ2014

3
@FranVerona好奇心から、単純な "indexOf( 'className')> -1"は、複数のクラスの問題を解決しませんか?
James Poulose、2015年

2
@JamesPoulose、それはしません。要素を2つのクラス(小と大)に設定することを検討してください。thatElement.classNameは、 "small bigger"に等しい文字列を返します。bigと呼ばれるクラスを探している場合、myElement.className.indexOf( "big")は、実際にはクラスの一部ではないにもかかわらず、負の1とは異なる何かを生成します。クラス名を100%制御している場合、このような修正が機能することは保証されません。特に、コードを操作するコードを作成している場合は、完全に制御することはできません。
デッドボーイ、2015年

次のclassNameような正規表現一致を使用する必要if(doc.childNode[i].className.match("\s*" + search_class + "\s*")があります。変数search_classは、探しているクラス名です。
WebWanderer 2016年

130

querySelectorとquerySelectorAllを使用する

var testContainer = document.querySelector('#test');
var fourChildNode = testContainer.querySelector('.four');

IE9以降

;)


スマートソリューションをありがとう!
Tai JinYuan

1
これは、子供だけでなく、すべての子孫をチェックします。
SUM1

47

受け入れられた回答は、直接の子供だけをチェックします。多くの場合、そのクラス名を持つ子孫を探します。

また、classNameを含む子必要な場合もあります。

例えば:<div class="img square"></div>それはだにも関わらず、クラス名「IMG」の検索に一致する必要があり、正確な classNameは「IMG」ではありません。

これらの問題の両方に対する解決策を次に示します。

クラスを持つ子孫要素の最初のインスタンスを見つける className

   function findFirstChildByClass(element, className) {
        var foundElement = null, found;
        function recurse(element, className, found) {
            for (var i = 0; i < element.childNodes.length && !found; i++) {
                var el = element.childNodes[i];
                var classes = el.className != undefined? el.className.split(" ") : [];
                for (var j = 0, jl = classes.length; j < jl; j++) {
                    if (classes[j] == className) {
                        found = true;
                        foundElement = element.childNodes[i];
                        break;
                    }
                }
                if(found)
                    break;
                recurse(element.childNodes[i], className, found);
            }
        }
        recurse(element, className, false);
        return foundElement;
    }

7
いいえ。私すべての子孫が欲しいのではなく、質問されたような子供だけが欲しいです。
Paul Draper 2016

14
Whelp。あなたのコメントが必要でした。(私と同じように)よく似た答えを頻繁に検索して、似ているがおそらく複雑で一般的な問題を解決する13人の他の人を助けてくれてうれしい。
Augie Gardner

5
tnx、私はこの回答がより多くのユースケースに適していると思います
Boban Stojanovski

記録のために、私は両方のユースケース、子孫の方が少し多いことがありましたが、私は子供のユースケースのためにここに来ました。
SUM1

14

element.querySelector()を使用します。'myElement'は既に持っている親要素であると仮定しましょう。'sonClassName'は、探している子のクラスです。

let child = myElement.querySelector('.sonClassName');

詳細については、https//developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorをご覧ください。


何らかの理由で私はlet child = myElement.querySelector('sonClassName');私の場合に使用しなければなりませんでした
マラート

ただし、クラス名querySelector( '。sonClassName')の横にドットを追加する必要があります。それ以外の場合は、sonClassNameがクラス名ではなくタグ名であるため処理されます
Hamza Dahmoun

10

あなたは試すことができます:

notes = doc.querySelectorAll('.4');

または

notes = doc.getElementsByTagName('*');
for (var i = 0; i < notes.length; i++) { 
    if (notes[i].getAttribute('class') == '4') {
    }
}

1
ブラウザーがjQueryのようなものを必要とせずに、最終的にこの機能を備えているのかどうか疑問に思っていました。誰でも好奇心旺盛であれば、それのようなルックスは、最新のブラウザでサポートされています:developer.mozilla.org/en-US/docs/Web/API/Document/...
Liron Yahdav

8

私には、4つ目のスパンが必要なようです。もしそうなら、あなたはこれを行うことができます:

document.getElementById("test").childNodes[3]

または

document.getElementById("test").getElementsByTagName("span")[3]

この最後のものは、それを台無しにする可能性のある非表示のノードがないことを保証します。


1
ありがとうございます。ただし、子要素の数はさまざまです。
spyderman4g63 2012

1
私にとっては、質問は常に4番目のスパンの子を取得することでした。もちろん、他の要素内の任意のインデックスで任意のタイプの要素を取得する関数の方が良いことに同意しますが、私はそのような質問を解釈しませんでした...もう一度質問を読むと、私は完全に誤解しているようですが:- )
クリスチャンヨルゲンセン2013

TagNameそれでおしまい!とても簡単。
Jacksonkr 2017年

この手法を頻繁に使用して、最初の要素を取得します。たとえば、document.getElementById( "test")。childNodes [0]
Louise Eggleton

@LouiseEggletonがあります.firstChildし、.firstChildElementしかし
YakovL

4

ただし、古いブラウザはをサポートしていないことに注意してくださいgetElementsByClassName

その後、あなたはすることができます

function getElementsByClassName(c,el){
    if(typeof el=='string'){el=document.getElementById(el);}
    if(!el){el=document;}
    if(el.getElementsByClassName){return el.getElementsByClassName(c);}
    var arr=[],
        allEls=el.getElementsByTagName('*');
    for(var i=0;i<allEls.length;i++){
        if(allEls[i].className.split(' ').indexOf(c)>-1){arr.push(allEls[i])}
    }
    return arr;
}
getElementsByClassName('4','test')[0];

動作しているようですが、HTMLクラス

  • 文字で始まる必要があります:AZまたはaz
  • 文字(A-Za-z)、数字(0-9)、ハイフン( "-")、およびアンダースコア( "_")が後に続きます。

3

IDの名前は、その前に記号を付けgetElementById#に使用します。次に、をspan使用して子ノードを取得し、getElementsByTagNameそれらをループして適切なクラスを持つ子ノードを見つけることができます。

var doc = document.getElementById('test');

var c = doc.getElementsByTagName('span');

var e = null;
for (var i = 0; i < c.length; i++) {
    if (c[i].className == '4') {
        e = c[i];
        break;
    }
}

if (e != null) {
    alert(e.innerHTML);
}

デモ:http : //jsfiddle.net/Guffa/xB62U/


すみません、その#はタイプミスでした。コンテナーdivを選択できますが、その関数はie8で機能しないため、タグ名で子要素を選択できません。
spyderman4g63 2012

@ spyderman4g63:このgetElementsByTagNameメソッドはIE 8で機能します。これは、IE 5.5までサポートされています。developer.mozilla.org/en-US/docs/DOM/...
Guffa

3

私の意見では、できる限り、Arrayとそのメソッドを使用する必要があります。それらは、DOM /ラッパー全体をループするか、空のものにデータをプッシュするよりもはるかに高速です。ここに提示されているソリューションの大半は、ここで説明されているようにNaiveを呼び出すことができます(素晴らしい記事btw):

https://medium.com/@chuckdries/traversing-the-dom-with-filter-map-and-arrow-functions-1417d326d2bc

私の解決策:(Codepenのライブプレビュー:https://codepen.io/Nikolaus91/pen/wEGEYe )

const wrapper = document.getElementById('test') // take a wrapper by ID -> fastest
const itemsArray = Array.from(wrapper.children) // make Array from his children

const pickOne = itemsArray.map(item => { // loop over his children using .map() --> see MDN for more
   if(item.classList.contains('four')) // we place a test where we determine our choice
     item.classList.add('the-chosen-one') // your code here
})

1

私がjqueryを使用してこれを行う方法は、このようなものです。

var targetchild = $( "#test")。children()。find( "span.four");


14
質問は、jQueryではなくjavascriptに関するものです
Jya

1

これは比較的単純な再帰的な解決策です。ここでは幅優先検索が適切だと思います。これは、見つかったクラスに一致する最初の要素を返します。

function getDescendantWithClass(element, clName) {
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].className &&
            children[i].className.split(' ').indexOf(clName) >= 0) {
            return children[i];
         }
     }
     for (var i = 0; i < children.length; i++) {
         var match = getDescendantWithClass(children[i], clName);
         if (match !== null) {
             return match;
         }
     }
     return null;
}

1

以下の行を追加すると、親クラスを取得できます。IDがある場合は、を使用すると簡単getElementByIdです。それにもかかわらず、

var parentNode = document.getElementsByClassName("progress__container")[0];

次にquerySelectorAll、親<div>を使用して、divクラスと一致するすべてのをフェッチできます.progress__marker

var progressNodes = progressContainer.querySelectorAll('.progress__marker');

querySelectorAlldivのクラスですべてをフェッチしますprogress__marker



0

ES6への2018年6月のアップデート

    const doc = document.getElementById('test');
    let notes = null;
    for (const value of doc) {
        if (value.className === '4') {
            notes = value;
            break;
        }    
    }

-2

うーん。この例はIE8でも機能しますが、オブジェクトに適用した場合は機能しない可能性があります。私の場合、docをyui domオブジェクトとして設定し、doc.getElementsByClassNameを使用します。それが失敗したときです。編集:または多分私はそのオブジェクトがどのように機能するのか理解していないのですか?
spyderman4g63 2012

@ spyderman4g63のYUIバージョンgetElementsByClassNameはのメソッドですYAHOO.util.Dom。あなたの場合、呼び出しは次のようになりYAHOO.util.Dom.getElementsByClassName('four', 'span', 'test')ます。その呼び出しが何をしているかをより詳細に理解するには、おそらくドキュメントを読む必要があります。短いバージョンは、DOM要素の下にspanクラスfourtestとして持つ要素を探すようになりますid
Hank Gay

@ spyderman4g63はい、get呼び出しの結果はDOM要素です。YUIは、jQueryのようなものを販売するような「フレームワーク固有のオブジェクトですべてをラップする」アプローチのようなものを採用していません。また、Prototypeのようにネイティブオブジェクトをモンキーパッチすることもしていません(そうではありません。永遠に)。この点で、YUIはDojoに似ています。
Hank Gay

-3

これは、YUIセレクターを使用して実行した方法です。ハンクゲイの提案に感謝します。

notes = YAHOO.util.Dom.getElementsByClassName('four','span','test');

ここで、4 =クラス名、スパン=要素タイプ/タグ名、テスト=親ID。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.