tags:

views:

50

answers:

4

Ok I have a very basic function which moves the background position of a div to give it a 'sheen' effect and a second one which shifts it back.

If I get the div by its ID that works fine. But when I try to make the function a bit more universal by using 'this' - it breaks.

This works fine:

function runsheen() {
$('#sheen').animate({backgroundPosition: '-400px 0px'},1000);
}

function resetsheen() {
$('#sheen').css({backgroundPosition: '-0px 0px'});
}

But this does nothing

function runsheen() {
$(this).animate({backgroundPosition: '-400px 0px'},1000);}

function resetsheen() {
$(this).css({backgroundPosition: '-0px 0px'});}

Running it with the ID version means a new function for every button - rubbish. If I use 'this' I can reuse the code over and over, right? Can anyone help me make this work?

+2  A: 

You can't use $(this) in any given function, this is a reference to the object on which the function is being invoked.

The easier way (assuming you're doing this on hover) is to pass the functions directly to the .hover event:

$('div').hover(
  function () {
    $(this).animate({backgroundPosition: '-400px 0px'},1000);
  }, 
  function () {
    $(this).css({backgroundPosition: '-0px 0px'});
  }
);

Or, modify your functions to take an argument and pass in the div to apply the effect to:

function runsheen($div) {
  $div.animate({backgroundPosition: '-400px 0px'},1000);
}

function resetsheen($div) {
  $div.css({backgroundPosition: '-0px 0px'});
}

$('div').hover(
   function () { runsheen($(this)); },
   function () { resetsheen($(this)); }
});
meagar
In my opinion, if you're going to write a function that takes a jQuery object as its argument, you might as well write the function as a jQuery plugin.
Pointy
A: 

this has a different scope in your second context. this in your second context is referring to the function not #sheen

What you could do is define this to a different meaning outside the function.

var self = this;

function runsheen() {
$(self).animate({backgroundPosition: '-400px 0px'},1000);}

function resetsheen() {
$(self).css({backgroundPosition: '-0px 0px'});}
Mike Fielden
Your idea is correct but not sure whether self should be declared globally. It'll always return the document object.
Sidharth Panwar
You are correct. I was assuming these functions sat inside a json class. If not you are correct it would return the document which is probably what he is looking for.
Mike Fielden
A: 

Make it a jQuery plugin maybe?

$.fn.runsheen = function() {
  this.animate({backgroundPosition: '-400px 0px'}, 1000);
  return this;
});

(same with the other one)

Then you just say

$('#sheen').runsheen();

or if you're in an event handler:

$('#whatever').click(function() {
  $(this).runsheen();
});
Pointy
A: 

The meaning of "this" changes with they way you call your functions. If you call these functions from the document.ready function, it'll give you a document object. If you call it from within another object it'll give you the instance of that object.

Read a bit about Execution Context in jQuery/JavaScript. Try this: http://www.webreference.com/programming/javascript/object-oriented_javascript3/

I'd suggest you get this cleared up and not look for a shortcut becuase this is one of the key concepts in JavaScript/jQuery. So don't look for a quick-fix on this one but try to understand what you want to do and what is happening.

Sidharth Panwar