Hi. I'm trying to add event listeners to multiple elements of the same class. The DOM is something like this:

<body>
....
.......
..........
       <ul class="x">
             <li class="a">
                 ....
                 ...
                 <span class="someclass">
                      [
                      <a href="http://someurl/x1>link text</a>
                      ]
                 </span>
                 </li>
             <li class="b>
                 ....
                 .....
                 <span class="someclass>
                    [
                      <a href="http://someurl/x1>link text</a>
                    ]
                  </span>
               </li>  
       <ul class="y">
               <li class="a">
                  ....
                  ...
                 <span class="someclass">
                      [
                      <a href="http://someurl/x1>link text</a>
                      ]
                    .... 
      <ul class="z">
               <li class="a">
                  ....
                  ...
                 <span class="someclass">
                      [
                      <a href="http://someurl/x1>link text</a>
                      ]
                  ....

I want to attach an event listener to each of the <a> element inside <span> elements of class "someclass".

Here's what I did

for(var i in document.getElementsByClassName('someclass'))
{
         document.getElementsByClassName('someclass')[i].childNodes[1].addEventListener('click', function(){return alert("link clicked");},false);
}

When I run this (in Firebug) I get this error:

TypeError: document.getElementsByClassName('someclass').childNodes is undefined

Even though document.getElementsByClassName('someclass')[S].hasChildNodes(); evaluates to true. (S is any integer literal: 0,1,2...upto to the length of the array-1)

>>>document.getElementsByClassName('someclass')[2].hasChildNodes();

>>>true

Not sure what I'm doing wrong; are there any alternate ways to do this? Thanks.

I think the for (var i in ...) is the problem. My guess is i is not an integer, but an object (element).

I think you should store the document.getElementsByClassName('someclass') in an array and loop through it using for (i=0; i<array.length;i++).

An other option would be to use jQuery, which makes this stuff real easy.

ZVN,

As Pritaes said plus ......

Unfortunately, .getElementsByClassName is far from safe. Too many browsers don't support it. So you have to be a bit old fashioned and do it longhand with .getElementsByTagName then test for .className in the loop.

Try this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Airshow :: Untitled</title>
<style type="text/css">
{}
</style>

<script>
onload = function(){
	var elArray = document.getElementsByTagName('span');
	for(var i=0; i<elArray.length; i++){
		if(elArray[i].className !== 'someclass') continue;
		var elArray2 = elArray[i].getElementsByTagName('a');
		for(var j=0; j<elArray2.length; j++){
			elArray2[j].onclick = function(){
				return alert(this.innerHTML + ' : ' + this.href);
				return false;
			};
		}
	}
}
</script>
</head>

<body>

<ul class="x">
<li class="a"><span class="someclass"><a href="http://someurl/x1/A">link text 1</a></span></li>
<li class="b"><span class="someclass"><a href="http://someurl/x1/B">link text 2</a></span></li>
</ul>

<ul class="y">
<li class="a"><span class="someclass"><a href="http://someurl/x1/C">link text 3</a></span>
</ul>

<ul class="z">
<li class="a"><span class="someclass"><a href="http://someurl/x1/D">link text 4</a></span>
</ul>

</body>
</html>

As you see, I have used !Doctype XHTML but I think it should work for XML too.

Airshow

Thanks for the example Airshow. Just one more reason to use jQuery for me ;)

jQuery, Prototype etc. are good but tricky. I encourage novices to learn JS basics before trying to use these libs. People can't run before they can walk.

My rules (only occasionally broken) : if it's a jQuery (etc.) question then it gets a jQuery answer; otherwise basic JS. I might steer someone in the direction of jQuery if I think the problem is large enough to warrant the overhead and the poster appears advanced enough to cope with it.

Airshow

commented: Agreed. +4

Thank you Airshow, pritaeas for the help!:) My script is now working as expected. (..and I'll definitely start reading a book on jQuery/YUI once I'm confident enough with the basic concepts of Javascript).

--