Marion
Marion

Reputation: 198

Assign a Function Argument with a Loop

I have an array of list items in a piece of Javascript code. I would like to assign an onclick event handler to each one. Each handler would be the same function, but with a different input argument. Right now I have:

function contentfill(i) {
    box = document.getElementById("text");
    box.style.background="rgba(0,0,0,0.8)";
    var content = new Array();
    contentdivs = document.querySelectorAll("#contentfill>div");
    box.innerHTML = contentdivs[i].innerHTML;
}
li[3].onclick = function() {contentfill(0);};
li[4].onclick = function() {contentfill(1);};
li[5].onclick = function() {contentfill(2);};

This works well enough, but I would like to achieve the same thing with a loop, for example:

for(i=3;i<=5;i++) {
    j=i-3;
    li[i].onclick = function() {contentfill(j);};
}

This, however, does not work. Since j seems to be defined as 2 at the end of the loop, each time I click, it only seems to call contentfill(2).

Upvotes: 1

Views: 148

Answers (2)

Eevee
Eevee

Reputation: 48546

For an alternative approach, consider having each of the elements aware of what argument it should be using.

for (var i = 0; i < 3; i++) {
    var el = li[i + 3];
    el.dataset.contentIndex = i;
    el.addEventListener('click', contentfill);
}

Then contentfill would have to extract the argument from .dataset instead of taking an argument, of course. (This is the same mechanism as jQuery's $.data.)

I tend to prefer this since (a) it doesn't generate tons of tiny wrappers, (b) it allows me to later examine and possibly change the "arguments", and (c) it lets me predefine them in the document using data- attributes. Effectively changes them from function arguments into behavior.

Upvotes: 3

Ja͢ck
Ja͢ck

Reputation: 173562

The value of i - 3 should be bound to the click handler function; a closure can provide this functionality:

li[i].onclick = (function(j) {
    return function() {
        contentfill(j);
    }
)(i - 3));

Btw, it's better practice to use addEventListener or attachEvent to register click handlers.

Upvotes: 1

Related Questions