0

I have 5 buttons and I can not change DOM and can not use id and name attribute and cant use innerHTML and now I need to give output like when I click button 1 it should give a alert like "You click button # 1" and same will continue for all 5 buttons. I want to print the value of i .Now I got stuck as I have two solutions :

HTML Part:

    //creating 5 buttons
        <button>one</button>
        <button>two</button>
        <button>three</button>
        <button>four</button>
        <button>five</button>

1st Solution:

            /* here I am always having you clicked element #5*/
           var nodes = document.getElementsByTagName('button');//getting    references
       var counter;
       for (var i = 0; i < nodes.length; i++) {
         nodes[i].addEventListener('click', function() {
              alert('You clicked element #' + i);
            });
        } //which is not working

2nd Solution:

    /* here I am getting correct output*/


var nodes = document.getElementsByTagName('button');
   var counter;
    for (var i = 0; i < nodes.length; i++) {
          assignEvent(nodes[i], i);
    }

 function assignEvent(node, i){
        node.addEventListener('click', function(){
            alert('You clicked element#' + (i+1));
        });
    }//this one is working

Now my question is why Solution 2 is working but solution 1 doesn't.. Please help. Why solution 2 is carrying the value of i correctly, while not solution 1.

georg
  • 211,518
  • 52
  • 313
  • 390
  • 2
    possible duplicate of [adding 'click' event listeners in loop](http://stackoverflow.com/questions/8909652/adding-click-event-listeners-in-loop), or [javascript closure inside loops simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Teemu Mar 12 '15 at 18:30

3 Answers3

0

In your first solution when you add the anonymous function as parameter of addEventListener, the alert message is looking for the last value of i in this case i=5, that happens because you don't have the variable as local in the function, so your onlye possible value if the global variable.

If you want to do that try this:

        var nodes = document.getElementsByTagName('button');//getting    references

        function alertMessage(i){
            alert('You clicked element#' + (i+1));
        }

        for (i = 0; i < nodes.length; i++) {
            nodes[i].addEventListener('click', alertMessage.bind(null,i) , false);
        }

Also I recommend you this lecture

eusoj
  • 374
  • 3
  • 12
0

If you don't want to create an additional function, just wrap the event listener assignment within a self-invoking anonymous function to which you pass 'i':

var nodes = document.getElementsByTagName('button');
var counter;
for (var i = 0; i < nodes.length; i++) {
    (function(j) {
        nodes[i].addEventListener('click', function() {
            alert('You clicked element #' + (j+1));
        });
    })(i);
}

jsfiddle here: http://jsfiddle.net/vu31aa7y/

the-catalin
  • 1,178
  • 11
  • 18
0

You can write this:

[].forEach.call(document.getElementsByTagName('button'),
    function(elt, index) {
        elt.addEventListener('click', function() {
            alert('You clicked element #' + (index + 1));
        }, false);
});
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125