Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make sure the addEventListener doesn't ignore the iteration of the i var in my for loop? [duplicate]

Tags:

javascript

I'm working on a userscript that will make lots of buttons, and I can't seem to give them all an unique function.

I already tried

 downArrow.onclick = function (){downVote(id, username)};<br>

and

 downArrow.onclick = "downVote(\"" + id + "\", \"" + username + "\")";

But they don't work. Then I read somewhere that only the following works:

 downArrow.addEventListener('click', downVote(id, username), false);

This causes that all the buttons will only downvote the last ID and username of the iteration.

I want them all to have unique onclick functions.

Entire for loop:

var targetPosts = document.getElementsByClassName("thing message");
for (var i=0;i<targetPosts.length;i++) 
    {
    try
      {
        id = targetPosts[i].getAttribute("data-fullname");
        username = targetPosts[i].childNodes[4].childNodes[1].childNodes[0].childNodes[1].childNodes[1].childNodes[0].innerHTML;

        var upArrow=document.createElement("DIV");
        upArrow.className = "arrowUp";
        upArrow.id = id + "up";
        upArrow.addEventListener('click', function(){ upVote(id, username)} , false);

        var downArrow=document.createElement("DIV");
        downArrow.className = "arrowDown";
        downArrow.id = id + "down";
        downArrow.addEventListener('click', function(){ downVote(id, username)} , false

      targetPosts[i].childNodes[3].appendChild(upArrow);
      targetPosts[i].childNodes[3].appendChild(downArrow);
      }
    catch(err){}
    }
like image 544
Maarten Boogaard Avatar asked May 31 '13 13:05

Maarten Boogaard


People also ask

Can you add an event listener in a loop?

You actually can attach event listeners in a for loop # As you can see from this example, an event listener is successfully attached to each button, and the console is logged each time one of them is clicked. Problems emerge when you try to use your i counter variable within the event callback.

Is it better to use onclick or addEventListener?

Summary: addEventListener can add multiple events, whereas with onclick this cannot be done. onclick can be added as an HTML attribute, whereas an addEventListener can only be added within <script> elements.

Which is the correct method to add an event listener?

The addEventListener() method allows you to add event listeners on any HTML DOM object such as HTML elements, the HTML document, the window object, or other objects that support events, like the xmlHttpRequest object.

How do you make EventListener work only once?

Using the once option We can pass an object as an argument to the addEventListener method and specify that the event is only handled once. This is achieved by passing the property once to the object. If we set once to true, the event will only be fired once.


2 Answers

bind was invented for exactly such a case :

 upArrow.addEventListener('click', upVote.bind(upArrow, id, username), false);

should do the job.

like image 65
GameAlchemist Avatar answered Sep 19 '22 13:09

GameAlchemist


Since JavaScript has no block scope (will come with ES6) try the following:

downArrow.addEventListener('click', function(uid, uname) {
    return function() {
        downVote(uid, uname);
    };
}(id, username), false);

When invoking the anonymous function (happens immediately) you capture the current state of id and username and use it when the inner function is invoked (happens when the user clicks the button).

In ES6 you can use let id = ... to define a variable with block scope and your posted code should work fine.

like image 34
Johannes Egger Avatar answered Sep 18 '22 13:09

Johannes Egger