views:

61

answers:

2

I used Firefug to profile my web application and found that the following function is called, and needs to be called, literally hundreds of times per user visit. So I want to optimize it since Firebug says it uses the most resources/times.

function highlightChildDiv(parentDiv) {

    /* find the closest (hlisting) home listing to the middle of the scrollwindow & highlight */    
    var scrollElemPos = parentDiv.offset();
    var highlightDiv = $(document.elementFromPoint(
        scrollElemPos.left + parentDiv.width()  / 2,
        scrollElemPos.top  + parentDiv.height() / 2)
    ).closest('#parentDiv div.childClass');

    if (highlightDiv.hasClass("HighlightRow")) { 
        return; // if the div is already highlighted, return
    } else {
        $('#parentDiv div.childClass').removeClass("HighlightRow");
        highlightDiv.addClass('HighlightRow');
    }
}

Seems to me that one of the most un-optimized statements is .closest('#parentDiv div.childClass');, but I'm sure there is other things to improve.

Question: Does anyone have any JQuery performance tips on how I can optimize the code above given that this function is run literally hundreds of times per user visit.

+1  A: 

First thought, eliminate the dead statement in the if clause.

if (!highlightDiv.hasClass("HighlightRow")) {  
    $('#parentDiv div.childClass').removeClass("HighlightRow"); 
    highlightDiv.addClass('HighlightRow'); 
} 

In the selector #parentDiv div.childClass, can you guarantee that div will be a direct descendent of #parentDiv? In which case:

.closest('#parentDiv>div.childClass');

and

$('#parentDiv>div.childClass')

You already have parentDiv. I'm guessing this is a DOM object, so you may be able to do the following:

$(parentDiv).children("div.childClass")

Just hide the DIV that is currently highlighted:

$('#parentDiv div.HighlightRow').removeClass("HighlightRow");
James Wiseman
What do you mean "direct descendant". What happens if my HTML was #parent -> #middle -> #child. Would using "#parentDiv>div.childClass" still be appropriate AND faster than "#parentDiv div.childClass"
Allen
No, I am saying that #parent>#middle is faster than #parent #middle. #parent>#child will not work in your example.
James Wiseman
A: 

My guess is this is the most unoptimized line:

$('#parentDiv div.childClass').removeClass("HighlightRow");

You should profile it to make sure (create a date object outside the call and output the getTime() value before and after each call).

Here you are asking jQuery to iterate over all DOM elements that match that selector and remove the class. If there are 1000 rows, jQuery will need to interogate each one to see if it needs to remove a class. Ugh. Here it is with that lookup removed:

// namespace scoped cache
var Hash_$_Cache = {
  $parentDiv : $('#parentDiv'),
  $tgt_row   : $([])  // empty jq object to start
};

// find the closest (hlisting) home listing to the middle of 
// the scrollwindow and highlight
//    
var highlightChildDiv = function (parentDiv){
  var
    scrollElemPos = parentDiv.offset(),
    $tgt_row
    ;

  $tgt_row = $(document.elementFromPoint(
    scrollElemPos.left + parentDiv.width()  / 2,
    scrollElemPos.top  + parentDiv.height() / 2)
  ).closest('#parentDiv div.childClass')
  ;

  // bail if row is already highlighted
  if ($tgt_row.hasClass('HighlightRow')){ return; }

  Hash_$_Cache.$tgt_row.removeClass('HighlightRow');
  $tgt_row.addClass('HighlightRow');

  // save highlighted row for later
  Hash_$_Cache.$tgt_row = $tgt_row; // store new row in cache
};

Hope that helps!

Michael Mikowski