I am writing some vanilla JavaScript to create a nice navigation menu. I am stuck on adding an active class.
I am getting elements by class name NOT by id. The below code works if substituted with id, however, I need it to apply to more than one element.
HTML
<img class="navButton" id="topArrow" src="images/arrows/top.png" />
<img class="navButton" id="rightArrow" src="images/arrows/right.png" />
JS
var button = document.getElementsByClassName("navButton");
button.onmouseover = function() {
button.setAttribute("class", "active");
button.setAttribute("src", "images/arrows/top_o.png");
}
No answers containing jQuery please.
document.getElementsByClassName
returns a node list. So you'll have to iterate over the list and bind the event to individual elements. Like this...Simply add a class name to the beginning of the funciton and the 2nd and 3rd arguments are optional and the magic is done for you!
getElementsByClassName()
returns HTMLCollection so you could try thisEdit
Here is a method adapted from Jquery 2.1.1 that take a dom element instead of a jquery object (so jquery is not needed). Includes type checks and regex expressions:
I like to use a custom "foreach" function of sorts for these kinds of things:
(Can't remember where I found the above function, but it has been quite useful.)
Then after fetching your objects (to
elements
in this example) just doclassList
is a simple way for handling elements' classes. Just needs a shim for a few browsers. If you must usesetAttribute
you must remember that whatever is set with it will overwrite the previous values.EDIT: Forgot to mention that you need to use
attachEvent
instead ofaddEventListener
on some IE versions. Test withif ( document.addEventListener ) {...}
.In your snippet,
button
is an instance ofNodeList
, to which you can't attach an event listener directly, nor can you change the elements'className
properties directly.Your best bet is to delegate the event:
Of course, my guess is that the
active
class needs to be removed once themouseout
event fires, you might consider using a second delegator for that, but you could just aswell attach an event handler to the one element that has theactive
class:There is some room for improvements, with this code, but I'm not going to have all the fun here ;-).
Check the fiddle here