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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Googlebot
  • 15,159
  • 44
  • 133
  • 229

3 Answers3

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.

Blender
  • 289,723
  • 53
  • 439
  • 496
  • 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. – Camilo Martin Jun 16 '13 at 20:48
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 ;)

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
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';
    }});
Danilo Valente
  • 11,270
  • 8
  • 53
  • 67
  • 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' – gabeio Jun 18 '12 at 00:27