1

I'm building a plugin with the code below. If I change $(opts.section, this).animate to $(opts.section).animate it works as I want it too, but it animates all instances of the section element, and I want it to only affect this current one. Once I add "this" to it, it stops working all together.

  $('.next', this).on({
    click: function() {
      if(count+2 <= totalElems) {
        count += 1;
        currentAnimationSpot += singleElem + opts.offset;
        $(opts.section, this).animate({
          left: -currentAnimationSpot
        });
      }
    }
  });

  $('.prev', this).on({
    click: function(){
      if(count != 1) {
        count-=1;
        currentAnimationSpot -= singleElem + opts.offset;
        $(opts.section, this).animate({
          left: -currentAnimationSpot
        });
      }
    }
  });  
Ian Hoar
  • 1,174
  • 1
  • 19
  • 40
  • 2
    that suggests to me that the `this` inside your anonymous functions refers to something different than the `this` outside your function. what happens if you do something like: `var self=this` outside your function and reference `self` instead? – Jeff Tratner Aug 20 '12 at 00:05
  • Wow it worked! I've been trying to figure this out for hours. I still don't understand why it doesn't work, with this? If you answer the question I'll award you the answer. – Ian Hoar Aug 20 '12 at 00:07
  • 2
    In `$('.next', this)`, `this` is the context (ancestor) of the `.next` which you're binding the handler to. Inside the handler, `this` references the element that triggered the handler, the `.next` element. There's a lot of material on SO about closures/scopes and `this`. `=]` – Fabrício Matté Aug 20 '12 at 00:11
  • @FabrícioMatté, do you have a favorite answer on closures/scopes? It'd be great to have a link to share when I want to explain the concept :) – Jeff Tratner Aug 20 '12 at 00:25
  • 1
    Closures and variable scope in general are very well explained [here](http://stackoverflow.com/q/111102/1331430) (the first most upvoted answers are slightly harder to understand, so you may start reading some simpler answers below those), now I've been looking for some specific material on the `this` scope, check [this answer](http://stackoverflow.com/a/9674288/1331430). – Fabrício Matté Aug 20 '12 at 00:36
  • The 2 questions that I linked above may make you more confused than you're now at first, but after reading those by 10th time over a span of a couple weeks (as I did), you'll grasp the closures concept and it'll improve your productivity exponentially. `=]` As the first question implies, it isn't an easy concept but after exercising it in your JS/jQuery a bit it'll make sense quickly. – Fabrício Matté Aug 20 '12 at 00:49

1 Answers1

2

The this inside the function is different than the this outside your function. EDIT: as @FabricioMatte's answer says -" this in the scope of your $(".next", this) handler references the element that triggered the handler".

So, you need to store the outer this in a separate variable so you can access it inside your function. E.g.

var self=this;

$('.prev', this).on({
    click: function(){
      if(count != 1) {
        count-=1;
        currentAnimationSpot -= singleElem + opts.offset;
        // now use self here
        $(opts.section, self).animate({
          left: -currentAnimationSpot
        });
      }
    }
  });

Even though this might seem strange at first, it's actually the same behavior you'd see any time you assign a new value in the local scope of a function, it's just that the this assignment is hidden.

Quick example of closures/scoping: Say you have a variable scoped, you could replicate the behavior as follows:

var scoped = "Outer scope!";
var saved = scoped;

myfn() {
    var scoped = "Inner scope!";
    console.log("Inner `scoped` is " + scoped); // Inner `scoped` is Inner scope!
    console.log("Inner `saved` is " + saved);  // Inner `saved`` is Outer scope!
};

console.log("Outer scoped is: " + scoped); // Outer scope!
console.log("Outer saved is: " + saved); // Outer scope!
myfn();

Just imagine you replaced "scoped" with "this" and you should get the general idea (it's as if someone set var this = triggerElement inside the scope of the function.

Jeff Tratner
  • 16,270
  • 4
  • 47
  • 67
  • opinionated side note: this is why I like that Python has you explicitly include `self` as a parameter to methods -- it lets you be very explicit and clear about where each variable comes from, instead of the (*very* minimal magic of the changing `this`) – Jeff Tratner Aug 20 '12 at 00:21