Tim T
Tim T

Reputation: 333

Javascript - Can't get 'getElementsByClassName' working

Im struggling to figure out why my code is not working. Here is part of the JS:

function init() {
    var showMenu = document.getElementsByClassName('showMenu'),
        perspectiveWrapper = document.getElementById( 'perspective' ),
        container = perspectiveWrapper.querySelector( '.container' ),
        contentWrapper = container.querySelector( '.wrapper' );

    showMenu.addEventListener( clickevent, function( ev ) {
        ev.stopPropagation();
        ev.preventDefault();
        docscroll = scrollY();
        // change top of contentWrapper
        contentWrapper.style.top = docscroll * -1 + 'px';
        // mac chrome issue:
        document.body.scrollTop = document.documentElement.scrollTop = 0;
        // add modalview class
        classie.add( perspectiveWrapper, 'modalview' );
        // animate..
        setTimeout( function() { classie.add( perspectiveWrapper, 'animate' ); }, 25 );
    });
}

Here is part of the HTML:

<div id="topBar">
    <h1>Company</h1>
    <a href="#" class="entypo-menu showMenu"></a>
</div>

<div class="line"></div>

<div id="fixedBar">
    <h1>Company</h1>
    <a href="#" class="entypo-menu showMenu"></a>
</div>

For some reason when I load the page, I get this error:

TypeError: undefined is not a function (evaluating 'showMenu.addEventListener')

I don't understand this because if I change this line:

var showMenu = document.getElementsByClassName('showMenu'),

to:

var showMenu = document.getElementById( 'showMenu' ),

It does work!

Why won't the class selector work but the id one will? I'm trying to get both links with the class showMenu to perform the JS.

Upvotes: 4

Views: 9843

Answers (3)

Kevin Ji
Kevin Ji

Reputation: 10489

document.getElementsByClassName returns an array-like list (an HTMLCollection, to be exact) of all elements that match the class name. You probably care about the first element, so try using the following instead:

var showMenu = document.getElementsByClassName( 'showMenu' )[0],

If you care about all of the elements, you'll need to loop through the elements:

var showMenu = document.getElementsByClassName( 'showMenu' ),

// ...

for ( var i = 0; i < showMenu.length; ++i ) {
    showMenu[i].addEventListener( clickevt, function( ev ) {
        // Your code here
    });
}

Upvotes: 5

Josh Crozier
Josh Crozier

Reputation: 240938

It's because getElementsByClassName return an array-like object of DOM elements.

You need to access each element and attach the event listener individually:

for (var i = 0; i < showmenu.length; i++ ) {
    showMenu[i].addEventListener( clickevent, function( ev ) {
        // ...
    });
}

..or:

Array.prototype.forEach.call(showMenu, function(el, i) {
    el.addEventListener( clickevent, function( ev ) {
        // ...
    });
});

Upvotes: 2

Natsu
Natsu

Reputation: 2175

That's because document.getElementsByClassName() returns a node list, which is similar to an array.

So if you have multiple elements you wish to target, you'll have to loop through them with a for loop or .forEach() but if you're only looking for the nth element with this class then you can specify it's index with bracket notation:

var showMenu = document.getElementsByClassName('showMenu')[0],

Upvotes: 3

Related Questions