views:

63

answers:

1

I am trying to make each number displayed clickable. "1" should alert() 80, "2" should produce 60, etc.

However, when the alert(adjust) is called, it only shows 0, not the correct numbers. However, if the commented out alert(adjust) is uncommented, it produces the correct number on page load, but not on clicking.

I was wondering why the code inside addEvents cannot access the previously defined variable adjust.

<html>
<head>
<script type="text/javascript" charset="utf-8" src="mootools.js"></script>
<script type="text/javascript" charset="utf-8">
    window.addEvent('domready', function() {

            var id_numbers = [1,2,3,4,5];

            for(var i = 0; i<id_numbers.length; i++) {
                var adjust = (20 * (5 - id_numbers[i]));
                // alert(adjust);
                $('i_' + id_numbers[i]).addEvents({
                    'click': function() {
                        alert(adjust);
                    }
                });
            }

    });
</script>
</head>
<body>

<div id="i_1">1</div>
<div id="i_2">2</div>
<div id="i_3">3</div>
<div id="i_4">4</div>
<div id="i_5">5</div>

</body>
</html>

Thanks.

+3  A: 

You are having a very common closure problem in that for loop.

Variables enclosed in a closure share the same single environment, so by the time the click callbacks are called, the for loop would have run its course, and the adjust variable will be left pointing to the last value it was assigned.

You can solve this with even more closures, using a function factory:

function makeClickHandler(adjust) {  
   return function() {  
      alert(adjust);
   };  
}

// ...

for(var i = 0; i<id_numbers.length; i++) {
   var adjust = (20 * (5 - id_numbers[i]));

   $('i_' + id_numbers[i]).addEvents({
      'click': makeClickHandler(adjust)
   });
}

This can be quite a tricky topic, if you are not familiar with how closures work. You may to check out the following Mozilla article for a brief introduction:

Daniel Vassallo