19

I've tried to create a loop with for, and increment by an onclick event, but it doesn't work.

var gameCase = ['', '', '', '', '', '', '', '', ''],  // 9
    itemLists = $('game').getElementsByTagName('li'); // 9 items

for( var i = 0; i < itemLists.length; i++ ) {
     // i already equals 9
     itemLists[i].onclick = function() {
          // do something
    }
 }

But in this case, the for loop is finished before I was able to click on an element in the list.

Moreover, I would like to get the item list I clicked and save it in an array. I tried gameCase[this] (in onclick function), but I don't know if it's the good way.

2
  • What is $('game').getElementsByTagName('li');, You use jQuery or pure javascript here? Commented Apr 7, 2013 at 9:09
  • @user1479606 Pure javascript, I just created my own selector. Commented Apr 7, 2013 at 9:12

4 Answers 4

32

John Resig covers this topic very well in "Secrets of the JavaScript Ninja" ( http://ejohn.org/apps/learn/#59 )

You'll need to create a temporary scope to preserve i's value

for ( var i = 0; i < itemLists.length; i++ ) (function(i){ 
  itemLists[i].onclick = function() {
      // do something
  }
})(i);

Edit:

var gameCase = ['', '', '', '', '', '', '', '', ''], // 9
$listParent = $('game').find('ul'), // li's parent
itemLists = $('game').getElementsByTagName('li'); // 9 items

var listHandler = (function() {
  var i = 0;

  return function() {
    // $(this) will in here refer to the clicked li
    i++ // increment i

    if ( i === 9 ) {
      $listParent.off('click', 'li', listHandler); //remove eventhandler when i reaches 9
    }
  }
}());

$listParent.on('click', 'li', listHandler); // attach eventhandler to ul element

This should do what you want, cant test it right now since I'm at work.

Sign up to request clarification or add additional context in comments.

9 Comments

As @Tim van Elsloo tell, it's the good way. But there is just something weird, when I console.log the value of the i before I click on any items of my list, the i value decrease. for ( var i = 0; i < itemLists.length; i++ ) (function(i){ console.log(i); //0 1 2 3 4 5 6 7 8 itemLists[i].onclick = function() { // i egal to 4 if I clicked on the third element. } })(i);
The length property starts from 1 and your i var from 0. So you'd either have to change the for loop to start from 1 and end on length+1 or change inside the function to itemLists[i+1].onclick.
Yes, I know, that's not the problem. The interest of the Loop, is when i is egal to 9, I can't do nothing more. But right here, the For loop is already finished, before I click on an element. I would like, when I click on an item of my list, i increment, and when I arrived to 9, the loop stops.
Ok so you just want to increment i every time a listItem is clicked? In that case you dont want a for loop at all. What this does is immediately loop i from 0 to 9 and add an eventhandler to each itemlist. I'll edit my answer with what I think you need when I understand you correctly
Yes, that's what I would like to have.
|
12

Wrap your listener:

onclick = (function(i) {return function() {
    ...
};})(i);

This fixes your variable scope issues.

1 Comment

That's quite good, when I cliked on a list item, it returns the good number of the case. But is it okay, that the For loop increment before I start to click ?
2

Another option is to use a forEach loop this creates a new variable for each iteration.

var gameCase = ['', '', '', '', '', '', '', '', ''], // 9
itemLists = $('game').getElementsByTagName('li'); // 9 items

itemLists.forEach(function(item,index){
    item.onclick = function() {
      // do something
 }
});

Comments

1

Sorry if I did not understand your question properly, From the code I understand that, you are trying to add an onclick handler to all the list elements in found in the game tag (perhaps it should be a class / id).

The for loop will be executed when the script tag / file loads without any user interaction.

If you wish to assign a function that uses the current value of the counter. Use the following code:

itemLists[i].onclick = (function() {
    return function() {
         // TODO ---
        // Your handler code here
}
})();

Comments

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.