How to get current element in getElementsByClassName
Asked Answered
T

3

12

Consider a simple JS event of

document.getElementsByClassName('test')[0].onclick=function(){
document.getElementsByClassName('test')[0].innerHTML = 'New Text';
}

How can I extend this code to generally work for all elements with class="test". I mean getting the element clicked and replace its content. In fact, we need to get the node number (provided inside the bracket) from the click event.

I am trying to better understand Javascript in unobtrusive codes, not a practical method like jQuery.

Tournedos answered 18/6, 2012 at 0:21 Comment(0)
D
16

Just iterate over them:

var elements = document.getElementsByClassName('test');

for (var i = 0; i < elements.length; i++) {
    elements[i].addEventListener('click', (function(i) {
        return function() {
            this.innerHTML = 'New Text';
        };
    })(i), false);
}​

I used (function(i) { return function() { ... }; })(i) instead of just function() { ... } because if you happen to use i in the callback, the value of i will be elements.length - 1 by the time you call it. To fix it, you must shadow i and make it essentially pass by value.

Dianthe answered 18/6, 2012 at 0:26 Comment(1)
I wonder if it wouldn't be better to define the function once, and just add its reference in each iteration of the loop. I'm not sure if the browser is smart enough, but it may be creating one anonymous function each iteration.Sulphurize
C
4

Just use this inside the function. this will be the element on which the event is being fired.

(function() {
    var elms = document.getElementsByClassName("test"),
        l = elms.length, i;
    for( i=0; i<l; i++) {
        (function(i) {
            elms[i].onclick = function() {
                this.innerHTML = "New Text";
            };
        })(i);
    }
})();

It's a bit more complicated than jQuery's:

$(".test").click(function() {
    $(this).html("New Text");
});

But it'll be significantly faster without the bloat that jQuery adds ;)

Crummy answered 18/6, 2012 at 0:24 Comment(3)
@Derek this is an interesting point! but why? addEventListerner does not overwrite previous events, but it is not supported in IE<9. Is there any advantage that I missed?Tournedos
onclick is perfectly fine, provided you understand the limitation it comes with: If you overwrite it, you lose any existing attached event.Crummy
@Ali Well, you can always use attachEvent in IE9< , or jQuery.Paginal
I
2
var all = document.getElementsByClassName('test');
for(var i=0;i<all.length;i++)
    all[i].onclick=function(){
        this.innerHTML = 'New Text';
    }

But it's most recommended to use addEventListener (or attachEvent, in IE/Some versions of Opera, I guess):

var all = document.getElementsByClassName('test');
for(var i=0;i<all.length;i++)
    all[i].addEventListener('click',function(){//If you're gonna use attachEvent, use 'onclick' instead of 'click'
        this.innerHTML = 'New Text';
    }});
Inexplicit answered 18/6, 2012 at 0:24 Comment(1)
He is asking how to do this for all of the elements with the class name 'test' and how to get in javascript the element [i] which was clicked. Not just to set the innerHTML to 'New Text'Embitter

© 2022 - 2024 — McMap. All rights reserved.