0

In a web application that I am writing, I have a series of divs which create a grid. The grid is X divs by Y divs, based on user input. Using jQuery hover function, I would like to change the background color of all surrounding divs within a certain distance. Basically, if I hover over a div, all divs within 4 rows and 4 columns away should also change their background color. I can get this functioning fine, but when the grid becomes 32 by 128 divs there is a real performance issue and the hover effect noticeably lags behind the mouse. I am almost certain that it is because of the large amount of similar divs within the DOM because the issue is not there when the grid is something like 30 by 30.

This is the basic structure of my html:

<div class="table_area">
    <div class="table_row" id="row-0">
        <div class="cap" data-row="0" data-column="0"></div>
        <div class="cap" data-row="0" data-column="1"></div>
        ...
    </div>
    <div class="table_row" id="row-1">
        <div class="cap" data-row="1" data-column="0"></div>
        <div class="cap" data-row="1" data-column="1"></div>
        ...
    </div>
    ...
</div>

To try to speed up the search of the DOM, I have added each row to an array. Thus, $('div.table_row[data-row="0"]') would be in arr[0]. So when a div in row 8 is hovered, I only check arr[4] through arr[12] for the necessary divs.

I would think that this would speed up the process quite a bit, since I am eliminating a substantial amount of the searching, but there is still a very noticeable lag in the hover.

Is there anything blatantly wrong with how I set this up? I am using the latest version of Chrome, if that matters.

7
  • 1
    care to create a jsfiddle.net of what you have? Commented Jan 18, 2013 at 18:24
  • can you setup a small demo? there may be other areas that you can optimize. Commented Jan 18, 2013 at 18:25
  • How about sharing some code? Commented Jan 18, 2013 at 18:27
  • Without seeing your code, I suspect at least part of your problem is that you are probably firing a whole slew of hover events as you move across your table. You might look at this question and see if you can delay the hover for a few milliseconds. Commented Jan 18, 2013 at 18:29
  • Does this work fast enough? Commented Jan 18, 2013 at 19:11

2 Answers 2

1

Selecting by class name is native to the browser, whereas selecting by data within an element depends on looping within jQuery.

Use class names to label your rows and columns and your selector will be much faster.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks I'll try it out! I always thought that class name was the slowest. Good to know!
this depends on browser, selecting by data attribute is done with queryselectorall.
I use arr[0].children('[data-column=1][data-row=3]'); I assumed that would be efficient enough to the point where using class OR data attribute wouldn't matter
The OP says they are already caching rows in an array, which is a good idea. I'd probably just cache all the cells in a 2D array for quicker lookup of both rows and columns.
0

If you add a class to each of the caps, you can then dynamically build a massive selector:

  var sel = "";
$(".cap").hover(function () {
    var row  = $(this).data("row");
    var col = $(this).data("column");
    sel = "";
    for(var i=row-2; i<=row+2; i++)
    {
      for(var j=col-2; j<=col+2; j++)
      {
        sel += ".r" + i + ".c" + j + ",";
      }
    }
  sel = sel.slice(0,-1);
  $(sel).css("background-color","blue");
},function () {
    $(sel).css("background-color","white");
  });
});

Example: http://jsbin.com/izeyal/38/edit

Since I was dynamically creating the rows and columns, I also added ids to each of the rows, which you can use for testing if you want by changing the selector generation code:

  sel += "#r" + i + "c" + j + ",";

For completeness, the code I used to generate the grid:

  for(i=0; i<128; i++)
  {
    var newRow = $('<div/>', {
    id: 'row-' + i
}).appendTo('.table_area');
    for (j=0; j<32; j++)
    {
      var rowid= "r" +i + "c" + j;
      $('<div/>', {id: rowid }).data("row",i).data("column",j).addClass("cap r" + i + " c" + j).appendTo(newRow);  
    }
  }

1 Comment

Thank you! I believe that this is the most responsive I will get it with the way that I have the grouping of divs set up! I was unaware that the same selector could be used for the mouse exit as well. Makes sense! Thanks a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.