How to get child element by class name?

JavascriptYui

Javascript Problem Overview


I'm trying to get the child span that has a class = 4. Here is an example element:

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

The tools I have available are JS and YUI2. I can do something like this:

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

//or

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

These do not work in IE. I get an error that the object (doc) doesn't support this method or property (getElementsByClassName). I've tried a few examples of cross browser implementations of getElementsByClassName but I could not get them to work and still got that error.

I think what I need is a cross browser getElementsByClassName or I need to use doc.getElementsByTagName('span') and loop through until I find class 4. I'm not sure how to do that though.

Javascript Solutions


Solution 1 - Javascript

Use querySelector and querySelectorAll

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

IE9 and upper

Solution 2 - Javascript

Use doc.childNodes to iterate through each span, and then filter the one whose className equals 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;
    }        
}

Solution 3 - Javascript

The accepted answer only checks immediate children. Often times we're looking for any descendants with that class name.

Also, sometimes we want any child that contains a className.

For example: <div class="img square"></div> should match a search on className "img", even though it's exact className is not "img".

Here's a solution for both of these issues:

Find the first instance of a descendant element with the class 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;
	}

Solution 4 - Javascript

Use element.querySelector(). Lets assume: 'myElement' is the parent element you already have. 'sonClassName' is the class of the child you are looking for.

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

For more info, visit: https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector

Solution 5 - Javascript

Modern solution

const context = document.getElementById('context');
const selected = context.querySelectorAll(':scope > div');

documentation

Solution 6 - Javascript

You could try:

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

or

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

Solution 7 - Javascript

To me it seems like you want the fourth span. If so, you can just do this:

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

or

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

This last one ensures that there are not any hidden nodes that could mess it up.

Solution 8 - Javascript

Use the name of the id with the getElementById, no # sign before it. Then you can get the span child nodes using getElementsByTagName, and loop through them to find the one with the right class:

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

Demo: http://jsfiddle.net/Guffa/xB62U/

Solution 9 - Javascript

But be aware that old browsers doesn't support getElementsByClassName.

Then, you can do

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

It seems it works, but be aware that an HTML class

  • Must begin with a letter: A-Z or a-z
  • Can be followed by letters (A-Za-z), digits (0-9), hyphens ("-"), and underscores ("_")

Solution 10 - Javascript

In my opinion, each time you can, you should use Array and its methods. They are much, much faster then looping over the whole DOM / wrapper, or pushing stuff into empty array. Majority of solutions presented here you can call Naive as described here (great article btw):

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

My solution: (live preview on 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
})

Solution 11 - Javascript

using querySelector

var doc=document.getElementById("test");
console.log(doc.querySelector('.two').innerHTML)

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

Using querySelectorAll

var doc=document.getElementById("test");
console.log(doc.querySelectorAll('*')[1].innerHTML)

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

using getElementsByTagNames

var doc=document.getElementById("test");
console.log(doc.getElementsByTagName("SPAN")[1].innerHTML);

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

Using getElementsByClassName

var doc=document.getElementById("test");
console.log(doc.getElementsByClassName('two')[0].innerHTML)

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

Solution 12 - Javascript

The way i will do this using jquery is something like this..

> var targetedchild = $("#test").children().find("span.four");

Solution 13 - Javascript

You can fetch the parent class by adding the line below. If you had an id, it would be easier with getElementById. Nonetheless,

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

Then you can use querySelectorAll on the parent <div> to fetch all matching divs with class .progress__marker

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

querySelectorAll will fetch every div with the class of progress__marker

Solution 14 - Javascript

Another way

const result = [...(parentElement.children)].find(child => {
  return child.classList.contains('some-class-name');
});

First we spread the elements of the NodeList to turn it into an Array so we can make use of the find() method. Lastly, find() will return to us the first element whose classList property contains the given class name.

Solution 15 - Javascript

Here is a relatively simple recursive solution. I think a breadth-first search is appropriate here. This will return the first element matching the class that is found.

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

Solution 16 - Javascript

I know this question is a few years old and there have been a few answers to this but I thought I would add my solution just in case it helps anyone. It's in the same vein as the answer given by user2795540 and involves an array iterator.

If you're just wanting to get the first child that has the four class then you could use the find array iterator. Your browser will need to be able to support ES6 or you can use Babel to compile your JS into something all browsers will support. IE will not support this without a polyfill.

Using the same details you provided in your question it could look something like this:

const parentNode = document.getElementById('test');
const childNode = Array.from(parentNode.childNodes).find(({ className }) => className === 'four');

The above solution will return the node you want to target and store it in the childNode variable.

You can find out more about the find array iterator at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

Solution 17 - Javascript

I believe this would answer your question best

document.querySelector('* > span.four')

This will match the first child element (of any parent) it finds that is a span and also has a class "four" set to it

However since in your example you also had a parent element which you are able to retrieve by id, you could also use this instead

document.querySelector('#test > span.four')

If you have a parent element saved in a variable like in your example, and you wish to search the subtree of that element, using :scope, as Billizzard has mentioned already, is probably your best choice

doc.querySelector(':scope > span.four');

Little extra: If the child element you are looking for isn't a direct child descendent, but somewhere further down the subtree, you can actually just omit the > like so

document.querySelector('#test span.four')

Solution 18 - Javascript

June 2018 update to ES6

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

Solution 19 - Javascript

Solution 20 - Javascript

Here is how I did it using the YUI selectors. Thanks to Hank Gay's suggestion.

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

where four = classname, span = the element type/tag name, and test = the parent id.

Solution 21 - Javascript

Use YAHOO.util.Dom.getElementsByClassName() from here.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionspyderman4g63View Question on Stackoverflow
Solution 1 - JavascriptAlberto Clar BrinesView Answer on Stackoverflow
Solution 2 - JavascriptJoão SilvaView Answer on Stackoverflow
Solution 3 - JavascriptAugie GardnerView Answer on Stackoverflow
Solution 4 - JavascriptHamza DahmounView Answer on Stackoverflow
Solution 5 - JavascriptBillizzardView Answer on Stackoverflow
Solution 6 - JavascriptKorikulumView Answer on Stackoverflow
Solution 7 - JavascriptChristian JørgensenView Answer on Stackoverflow
Solution 8 - JavascriptGuffaView Answer on Stackoverflow
Solution 9 - JavascriptOriolView Answer on Stackoverflow
Solution 10 - Javascriptuser2795540View Answer on Stackoverflow
Solution 11 - JavascriptßãlãjîView Answer on Stackoverflow
Solution 12 - JavascriptMarselus ChiaView Answer on Stackoverflow
Solution 13 - JavascriptOsama KhawarView Answer on Stackoverflow
Solution 14 - JavascriptjSamsaView Answer on Stackoverflow
Solution 15 - JavascriptJerView Answer on Stackoverflow
Solution 16 - JavascriptsamkitsonView Answer on Stackoverflow
Solution 17 - JavascriptKoyaanisView Answer on Stackoverflow
Solution 18 - JavascriptChristopher GriggView Answer on Stackoverflow
Solution 19 - JavascriptHank GayView Answer on Stackoverflow
Solution 20 - Javascriptspyderman4g63View Answer on Stackoverflow
Solution 21 - JavascriptJohn LindalView Answer on Stackoverflow