views:

95

answers:

4

I have been trying to learn how to write faster more efficient jQuery and would like to get some insight on how I should write this function so it will work faster. Should i use variables, I am most concerned with speed on a page so what will run more optimal cross browser and why is the answer I would like to see.

    $("#div-one, #div-two").find('tr').hover(function(){
    $(this).find('a').stop().animate({color:"#FFF"}, 'fast');
    $(this).stop().animate({
        backgroundColor:"#7DBE36"
    }, 'fast');
}, function(){
    $(this).find('a').stop().animate({color:"#000"}, 'fast');
    $(this).stop().animate({
        backgroundColor:"#FFF"
     }, 'fast')
});

Thanks all in advance.

+2  A: 

You can use .delegate() here, like this:

$("#div-one, #div-two").delegate('tr', 'mouseenter', function(){
    $(this).stop().animate({ backgroundColor:"#7DBE36" }, 'fast')
           .find('a').stop().animate({ color:"#FFF" }, 'fast');
}).delegate('tr', 'mouseleave', function(){
    $(this).stop().animate({ backgroundColor:"#FFF" }, 'fast')
           .find('a').stop().animate({ color:"#000" }, 'fast');
});

This attaches a pair of handlers on #div-one and #div-two instead of a pair per <tr> inside each, this means quicker binding and just relies on event bubbling for listening to the events. Also inside the function you can chain, no need to create another $(this) jQuery object.

Nick Craver
This is exactly what I was looking for, Thank you. Unfortunatley I am using an older V of jQuery that is required by Drupal but this is something I will take with me for the future. Thanks!
jnolte
A: 

You could write another utility function to give you the toggle callbacks:

function animCallback(linkColor, bgColor) {
  return function() {
    $(this).stop().animate({backgroundColor: bgColor}, 'fast')
      .find('a').stop().animate({color: linkColor}, 'fast');
  };
}
$('#div-one, #div-two').find('tr').hover(
  animCallback('#FFF', '#7DBE36'),
  animCallback('#000', '#FFF')
);

edit also Nick's idea is good - you can combine both our answers!

Pointy
Thanks for the answer, Nicks was what I was looking for but nonetheless valuable.
jnolte
A: 

As well as using delegate as suggested by Nick, you can also reuse the result of $(this) for an additional micro optimization.

$("#div-one, #div-two").delegate('tr', 'mouseenter', function(){
    var $this = $(this);
    $this.find('a').stop().animate({color:"#FFF"}, 'fast');
    $this.stop().animate({ backgroundColor:"#7DBE36" }, 'fast');
}).delegate('tr', 'mouseleave', function(){
    var $this = $(this);
    $this.find('a').stop().animate({color:"#000"}, 'fast');
    $this.stop().animate({ backgroundColor:"#FFF" }, 'fast');
});

Edit Nick changed his answer to use chaining thus avoiding the reuse of $(this) in the first place. So I'd go with his version instead.

Day
A: 

Hi jnolte,

As a jQuery developer I have a simple rule, if I will use a selector more than one time in a scope I store it in a variable.

$("#div-one tr, #div-two tr").hover(function() {
    var $this = $(this);
    $this.find('a').stop().animate({color:"#FFF"}, 'fast');
    $this.stop().animate({backgroundColor:"#7DBE36"}, 'fast');
}, function(){
    var $this = $(this);
    $this.find('a').stop().animate({color:"#000"}, 'fast');
    $this.stop().animate({backgroundColor:"#FFF"}, 'fast');
});

I have heard or read that jQuery use some kind of cache when using $(...) for same selectors or objects. jQuery itself use to wrap the keyword this and store it in local variable.

Brief, to optimize jQuery code you should avoid to use $(...) for the same selector in a function scope. A better practice to improve performance is to use it once and store in a variable.

EDIT

After reading answers from Pointy and Nick Craver it wouldn't be necessary this kind of optimization for your code. Because in both answers, they make use of $(this) once.

PD Thanks for your comment/feedback!

Rubens Mariuzzo
Thanks, that is a rule of thumb i will certainly be using.
jnolte