1

I am trying to add an event listener to elements that have the same class by doing something like this...

// Add listener's to all elements that have a class name of "foo"
var foos = document.getElementsByClassName("foo");
for (i = 0; i < foos.length; i++) {
    var fooId = foos[i].id;
    foos[i].addEventListener('click', function(){doFoo(fooId)});
}

function doFoo(id) {
    document.getElementById("console").innerHTML += "<li>You clicked Foo " + id + "</li>";
}

The above JavaScript works other than the fact that the anonymous function argument "fooId" will always evaluate to the id of the last element of the collection - instead of the id of the item in scope of the loop.

How do I pass the id of the element id to the anonymous function parameter?

In this fiddle http://jsfiddle.net/6e4NC/ you will see that no matter which Div you click, the JavaScript will always claimed that you clicked the last Div.

Jed
  • 10,649
  • 19
  • 81
  • 125

3 Answers3

2
function doFoo(id) {
    document.getElementById("console").innerHTML += "<li>You clicked Foo " + id + "</li>";
}

var foos = document.getElementsByClassName("foo");
for (i = 0; i < foos.length; i++) {
    foos[i].addEventListener('click', function (e) {
        doFoo(e.target.id);
    });
}

The event has the target, make use of that http://jsfiddle.net/6e4NC/3/

Barbara Laird
  • 12,599
  • 2
  • 44
  • 57
1
var foos = document.getElementsByClassName("foo");
for (i = 0; i < foos.length; i++) {
   var fooId = foos[i].id;
   var f = function (fooId) {
       return function (){doFoo(fooId)};
    }(foos[i].id);
    foos[i].addEventListener('click', f);
}

Example

potashin
  • 44,205
  • 11
  • 83
  • 107
  • Alternatively, you can bind the event listener inside the inner function. `function (fooId) { foos[i].addEventListener('click', function() {doFoo(fooId)}); }(foos[i].id);`. Its more readable, IMO. – aebabis Apr 29 '14 at 23:15
  • @Notulysses - Thanks for the answer. Can you point me to where I can read more about that syntax where you appended the }(foos[i].id);? i.e. I would like to know how/why your solution works. – Jed Apr 29 '14 at 23:23
  • 1
    @Jed : Glad to help you!Link : [JavaScript closures](http://www.mennovanslooten.nl/blog/post/62) – potashin Apr 29 '14 at 23:24
  • 1
    Also, @Jed, [Ben Alman's introduction to the 'Immediately-Invoked Function Expression' ('IIFE')](http://benalman.com/news/2010/11/immediately-invoked-function-expression/). – David Thomas Apr 29 '14 at 23:27
  • @Notulysses - For better readability, wouldn't it be better to replace "}(foos[i].id);" with, simply, "}(fooId);"? I've tested it and it works fine, but I'm not 100% sure that there is something inherently bad about doing so. – Jed Apr 30 '14 at 14:55
  • 1
    @Jed : it doesn't really matter, I've written that way just to underscore the changing `id` property in the loop – potashin Apr 30 '14 at 14:59
0
for (i = 0; i < foos.length; i++) {
    var fooId = foos[i].id;
    foos[i].addEventListener('click', function (e, args) {
        doFoo(e);
});

function doFoo(e) {
    var fooId = e.target.id || e.srcElement.id;
    document.getElementById("console").innerHTML += "<li>You clicked Foo " + fooId + "</li>";
}
Shalin Ved
  • 322
  • 1
  • 6