1

How do I return the index of only the button that is clicked?

Here's the code that got me worried:

window.onload = function(){

var    description = document.getElementsByClassName('description'),
        buttons = document.getElementsByClassName('button');

var currD = 0; // this var stands for the current description that should be shown

var show = function(){

    for( var i = 0; i < description.length; i++ ){

        if( i !== currD ){
            description[i].style.display='none';
        }

        else if( i === currD ){
            description[i].style.display='block';   
        }

    }

};

  for (var i = 0; i < buttons.length; i++){
    buttons[i].addEventListener('click', function(){
        currD = i;
        console.log(i);
    });
}

    window.setInterval(show,300);
};

Every time I click the button the for loop return the last element.

Since I didn't have many buttons on this page I went for the unproficient old way which is:

window.onload = function(){

var description = document.getElementsByClassName('description'),
    buttons = document.getElementsByClassName('button');

    var currD = 0; // this var stands for the current description that should be shown

    var show = function(){

        for( var i = 0; i < description.length; i++ ){

            if( i !== currD ){
                description[i].style.display='none';
            }

            else if( i === currD ){
                description[i].style.display='block';   
            }

        }

    };

buttons[0].addEventListener('click', function(){
    currD = 0;
});

buttons[1].addEventListener('click', function(){
    currD = 1;
});

buttons[2].addEventListener('click', function(){
    currD = 2;
});

        window.setInterval(show,300);
    };

This works but if I want to add more buttons it'd be a loss of time setting all the event listeners.

1

1 Answer 1

1

This is a common CLOSURE issue. This should work:

for (var i = 0; i < buttons.length; i++){

    (function (_i) {
        buttons[_i].addEventListener('click', function(){
          currD = _i;
          console.log(_i);
        });
    })(i);

}

Another solution:

for (var i = 0; i < buttons.length; i++){

    buttons[i].addEventListener('click', function(){
        return function() {
            currD = i;
            console.log(i);
        }
    });
}

You can read more about closure even here: http://www.w3schools.com/js/js_function_closures.asp but there are a lot of other interesting articles. Just google javascript closure

For your specific example, maybe even something like this can work:

for (var i = 0; i < buttons.length; i++){
    buttons[i].addEventListener('click', function(e){
        currD = buttons.indexOf( e.currentTarget );
        console.log(currD);
    });
}
Sign up to request clarification or add additional context in comments.

9 Comments

The first solution is awful, the second solution doesn't work : (.
Lol. Those are the solutions for closure. Why a function wrapper is awful? Anyway, can you create a jsFiddle so we can show it working?
In the first solution you're creating a new function on every round, that works though, but is considered a bad practice. In the second snippet i inside of the handler function is the event object, not the looping variable.
Also, the second solution does the same thing as the first one. Yes, that's the idea of the closure, you need to create a function for each element. Otherwise you will not have the i variable!. You need to set different functions for each button with the corresponding "i".
Actually the second solution doesn't work at all.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.