19

I have a program and it works well. See HERE.

This is the code:

<div id="round"></div>

<style>
#round{
position: absolute;
width: 200px;
height: 200px;
border-radius: 50%;
left: 400px;
top: 200px;
background-color: #e1e1e1;
}
</style>

<script src="jquery.js"></script>
<script src="jquery.easing.1.3.js"></script>
<script>
$(document).ready(function(){
    $("#round").click(function(){
        setInterval(function(){
            $("#round").animate(
                {height: 250,
                width: 150,
                top:150,
                left: 425},
                {duration: 300}
                ).
            animate(
                {height: 200,
                width: 200,
                top:200,
                left: 400},
                {duration: 300}
            );
        }, 0);
    });
});
</script>

But when I change "#round" to "this". It won't work. why? (actually it works, but when I put them into setInterval(), it won't work)

$(document).ready(function(){
    $("#round").click(function(){
        setInterval(function(){
            $("#round").animate(
                {height: 250,
                width: 150,
                top:150,
                left: 425},
                {duration: 300}
                ).
            animate(
                {height: 200,
                width: 200,
                top:200,
                left: 400},
                {duration: 300}
            );
        }, 0);
    });
});

change to "this", it won't work.

$(document).ready(function(){
    $("#round").click(function(){
        setInterval(function(){
            $(this).animate(
                {height: 250,
                width: 150,
                top:150,
                left: 425},
                {duration: 300}
                ).
            animate(
                {height: 200,
                width: 200,
                top:200,
                left: 400},
                {duration: 300}
            );
        }, 0);
    });
});
Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
SPG
  • 6,109
  • 14
  • 48
  • 79
  • 2
    See [Javascript _this_ gotchyas](http://www.sitepoint.com/javascript-this-gotchas/) – Brad Christie Jul 19 '11 at 15:23
  • 3
    [More than you ever wanted to know about `this`](http://stackoverflow.com/questions/133973/how-does-this-keyword-work-within-a-javascript-object-literal/134149#134149) – andyb Jul 19 '11 at 15:25
  • @andyb: Funny, was just looking for that post... – Brad Christie Jul 19 '11 at 15:27
  • Not sure if this is it, but you're calling another function (setInterval). Can you pass $this in setInterval(function($this){... – Luke Jul 19 '11 at 15:27

6 Answers6

27

this is a reference to the member that invokes the current function...

then you can wrap it in the jquery function $() to select it just like you would another selector.

So setInterval calls a anonymous function so it is not invoked by a referencable member, so it defaults to the window object.

save the this context in a variable and then use it internally like this...

$(document).ready(function(){
    $("#round").click(function(){
        var clicked = this;   //<----store the click context outside setInterval
        setInterval(function(){
            $(clicked).animate(  //<----------use it here
                {height: 250,
                width: 150,
                top:150,
                left: 425},
                {duration: 300}
                ).
            animate(
                {height: 200,
                width: 200,
                top:200,
                left: 400},
                {duration: 300}
            );
        }, 0);
    });
});
jondavidjohn
  • 61,812
  • 21
  • 118
  • 158
7

Inside of a jQuery bound event function, this refers to the current DOM element from the collection which is being operated on. Since it is a DOM element, passing it to jQ like $( this ) makes it a jQuery collection so that you can do more jQuery stuff to it.

In your modified, non-workng code, however, you moved that into a new anonymous function. Inside of that function, this now refers to the new scope.

You need to get a reference to this before your function:

$(document).ready(function(){
    $("#round").click(function(){
        var jQuerizedElement = $( this );
        setInterval(function(){
            jQuerizedElement.animate(
                {height: 250,
                width: 150,
                top:150,
                left: 425},
                {duration: 300}
                ).
            animate(
                {height: 200,
                width: 200,
                top:200,
                left: 400},
                {duration: 300}
            );
        }, 0);
    });
});
JAAulde
  • 19,250
  • 5
  • 52
  • 63
  • Note that jondavidjohn and I have given the same solution, but he chose to sotre only a reference to `this` in `self` whereas I chose to store a referenced to the jQuerized `this` in `jQuerizedElement`. Either is fine in this case. – JAAulde Jul 19 '11 at 15:28
5

$(this) is context sensitive. Each [anonymous, in this case] function you're entering, the value of $(this) changes. For example:

$('#round').click(function(){
    alert($(this).attr('id')) // alerts round
    setInterval(function(){
        alert($(this).attr('id')) // alerts undefined
    });
});
wanovak
  • 6,117
  • 25
  • 32
1

Because you are using a callback function that is fired by setInterval on a different context...

You can handle this by copying 'this' to an other variable ex :

var that = this:

And on callback

$(that).animate...
ChristopheCVB
  • 7,269
  • 1
  • 29
  • 54
1

this is basically context related. When you say $(this) if this is a dom element it will give you jquery object associated with this dom element.

ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
0

If I understand well it seems that $(this) is just the node that was triggerd.

For instance when you have a click event on a button. In the callback of the event you can use $(this) that represent the node of the button...

Doctor
  • 7,115
  • 4
  • 37
  • 55