views:

577

answers:

6
    for(var n=0;n<10;n++)
    {
            $('#content-scroll'+n).mousewheel(function(event, delta) {
  if (delta > 0) sliderUp(n-1);
  else if (delta < 0) sliderDown(n-1);
  return false; // prevent default
 });

 n++;
}

I have a problem with this code, variable "n" is not passed right to the mouswheel function which will add mousewheel only to number 9 (last number) and not to all 10 elements. Can anyone explain how to pass a variable to this function so that it stays?

+2  A: 

I believe this is an issue of closures in javascript, the n is actually a reference to the outside n variable. I believe the following should work instead:

for(var n=0;n<10;n++)
{
  var localN = n;
  $('#content-scroll'+n).mousewheel(function(event, delta) {
    if (delta > 0) sliderUp(localN-1);
    else if (delta < 0) sliderDown(localN-1);
    return false; // prevent default
  });

  //is this really needed??
  //n++;
}
Jeremy Stanley
If that doesn't work try moving the localN inside the mousewheel(function() { var localN = n-1; })
bendewey
Nope, that doesn't work, cause mousewheel always takes the last value of localN or n
+1  A: 

Are your n values supposed to go from 0-9 or 1-10?

If it's 0-9, change all n-1 expressions to just n.

If it's 1-10, change the for loop to var n=1,n<=10;n++, and all n-1 references to just n.

Also, remove the n++ on the bottom because your for loop already increments the value of n.

John Rasch
+3  A: 

My take on this using a fully jQuery solution.

$("[id^='content-scroll']").mousewheel( function(event,delta) {
     var n = this.id.replace(/content-scroll/,'');
     if (delta > 0)
        sliderUp(n);
     else if (delta < 0)
        sliderDown(n);
     event.preventDefault();
});

EDIT: Actually, I may even try to figure out a way to pass the actual matching control to the slider* functions, but not knowing what they actually do I have no idea how or if that would work.

tvanfosson
Thank you, this works fine and I get it that mousewheel now gets a n value from it's Id. But can you explain why my solution didn't work, because on every loop another content-scroll element got his mousewheel function.
I believe it's because what actually happened is that the n in the function created for the event handler got bound to the n in the outer loop -- the actual variable, not the value. When the function is invoked, it uses the last value of the variable, not the value when the function was created.
tvanfosson
@Jeremy's solution works because localN is a new variable created in each interation of the loop. This variable retains the value of n at each iteration of the loop and binding to it in the function gives you the value at that iteration of the loop.
tvanfosson
I prefer my solution because it only searches the DOM once to find all of the matching elements instead of searching once per element to be found.
tvanfosson
i thought that also but @Jeremy's solution also doesn't work, it also binds n and localN to the last value.
+1  A: 

The reason that the code doesn't work is because the n variable is not evaluated during the loop.

You are creating an anonymous function in the loop that you pass to the mousewheel function, so the code in the anonymous function isn't executed until the mouse wheel even occurs. By then the value of the n variable is 10, or perhaps something completely different if you are using the variable anywhere else in the code.

If you instead use the Function function to create the function from a string, you can inject the current value of the n variable into the code:

for(var n=0; n<10; n++) {

   $('#content-scroll' + n).mousewheel(
      Function('event', 'delta',
         'if (delta > 0) sliderUp(' + (n-1) + ');' +
         'else if (delta < 0) sliderDown(' + (n-1) + ');' +
         'return false; // prevent default'
      )
   );

}

However, should it be (n-1)? Should the mousewheel event for the content-scroll0 element call sliderup(-1)?

Guffa
+1  A: 

This is asked a lot on SO (case in point). You need a closure to "trap" the value of n in each iteration:

for(var n=0;n<10;n++)
{
    (function(n){
        $('#content-scroll'+n).mousewheel(function(event, delta) {
            if (delta > 0) sliderUp(n-1);
            else if (delta < 0) sliderDown(n-1);
            return false; // prevent default
        });
    })(n);
}
JPot
A: 

JQuery specifically allows the passing of event data, which may, or may not, be of use to you in this case:

for(var n=0;n<10;n++)
{
  $('#content-scroll'+n).bind('mousewheel', {index:n}, function(event, delta) {
    var innerN = event.data.index;
    if (delta > 0) sliderUp(innerN-1);
    else if (delta < 0) sliderDown(innerN-1);
    return false; // prevent default
  });
}
Jason