Dan
Dan

Reputation: 3

Combining getElementsByTagName and getElementsByClassName

I'm trying to combine getElementsByTagName and getElementsByClassName to narrow a search down and count the resulting nodes, but the second search always results in a length of 0, and I've no idea why.

<!DOCTYPE html>
<html>
	<head></head>
	<body>
		<p>Stuff</p>
		<p class="content">Stuff2</p>
		<p>Stuff</p>
		<p class="content">Stuff2</p>
		<script type="text/javascript">
			pElements = document.getElementsByTagName("p");
			console.log(pElements);
			for(i = 0; i < pElements.length; i++) {
				console.log(pElements[i].getElementsByClassName("content").length);
			}
			//console.log(document.querySelectorAll('p.content').length);
		</script>
	</body>
</html>

I know I can use querySelectorAll for this like the line I have commented out, but I'd like to understand why the first solution isn't working, and what I can do to fix it.

Thanks!

Upvotes: 0

Views: 7428

Answers (3)

Isha Saran
Isha Saran

Reputation: 21

You can NOT combine getElementsByTagName and getElementsByClassName. Because as mentioned by @juunas, pElements now consists of the result consisting of an array of all the <p> elements.

And when you apply the getElementsByClassName to this result-set, using pElements[i].getElementsByClassName("content"), it searches in the child elements of pElements.

Suggestive Result : Use the getAttribute() function to check the class of each element in pElements, like,

pElements = document.getElementsByTagName("p");
console.log(pElements);
for(var i = 0, j = 0; i < pElements.length; i++) {
    if (pElements[i].getAttribute("class") === "content") {
        j++;
    }
}
console.log("Length of the resulting nodes: ", j);

Upvotes: 2

juunas
juunas

Reputation: 58733

The problem with the first example is that:

pElements[i].getElementsByClassName("content")

searches for children of the p element. But since it is actually on the same element, they are not found.

W3C reference: "The getElementsByClassName() method returns a collection of an element's child elements with the specified class name"

EDIT: To find if a p element has the content class, instead of getElementsByClassName(), you could use

pElements[i].classList.contains("content")

which will return true if the element has the class. Reference

EDIT2: A more backwards-compatible way would be to get the className property, split it on spaces and iterate the array to see if the class is there.

var names = pElements[i].className.split(" ");
var found = false;
for(var i = 0; i < names.length; i++){
  if(names[i] === "content"){
    found = true;
    break;
  }
}
if(found){
 //Your code here
}

Upvotes: 4

maxeh
maxeh

Reputation: 1583

It's because your p-elements dont have any elements with the class "content". The p-elements itself have this class, so you cant find it and 0 is correct.

Change

<p class="content">Stuff2</p>

To

<p><span class="content">Stuff2</span></p>

And you will get 1 as the result.

Upvotes: 0

Related Questions