views:

1647

answers:

3

Hi,

I've used JQuery to make the elements in a table draggable. (I've never used JQuery before this). It works fine, but is very slow. For example, from the moment I click and hold on an item, to the moment the cursor changes is about 2 seconds. This is on Firefox 3.0.6. Once the item is being dragged, there's a shorter, but still noticeable delay (about half a second, I'd estimate) between when I let go of the mouse button and when the drop visibly takes place.

I suspect that the reason it's so slow is because the table is quite big (6 columns and about 100 rows), but it doesn't seem to me that it's obscenely big, and I wonder if there's something dumb I'm doing that is making it so slow. For example, I wonder if the JQuery code is being pointlessly applied to every element in the table each time you drag something. I don't know why that would happen, though.

In case it helps, here's my code (note that I've taken out the cursor call, as I was afraid it might be slowing things down).

<script type='text/javascript'>
  $(document).ready
  (
    function()
    {
      $('.draggable_div').draggable
      (
        {
          start: function(event, ui)
          {
            $(this).css('background-color','#ddddff');
          }
        }
      );
      $('.draggable_td').droppable
      (
        {
          over: function(event, ui)
          {
            $(this).css('background-color', '#ccffcc');
          },
          out: function(event, ui)
          {
            $(this).css('background-color', null);
          },
          drop: function(event, ui)
          {
             // snip: removed code here to save space. 
          }
        }
      );
    }
  );
</script>

The HTML table is like this (as generated by PHP):

<table id='main_table' border=0>
<tr>
  <th width=14.2857142857%>0</th>
  <th width=14.2857142857%>1</th>
  <th width=14.2857142857%>2</th>
  <th width=14.2857142857%>3</th>
  <th width=14.2857142857%>4</th>
  <th width=14.2857142857%>5</th>
  <th width=14.2857142857%>6</th>
</tr>
<tr>
  <td class=draggable_td id='td:0:0:'>
  <div class=draggable_div id='div:0:0:1962'>
    content
  </div>
  </td>
  <td class=draggable_td id='td:0:1:1962'>
  <div class=draggable_div id='div:0:1:14482'>
    content
  </div>
  </td>
  <!-- snip: all the other cells removed for brevity -->
</tr>
<!-- snip: all the other rows removed for brevity -->
</table>

(Note: it doesn't seem to work at all in IE 7, so perhaps I'm just doing something very wrong here...)

Thanks,

Ben

+1  A: 

I don't suppose its to do with addClasses ? If set to false, will prevent the ui-droppable class from being added. This may be desired as a performance optimization when calling .droppable() init on many hundreds of elements.

Snapey
Thanks -- that's a good suggestion. I tried it, and I think it may have sped things up very slightly, but it's still way too slow...
Ben
+4  A: 

The presence of so many drop targets seems to make the performance so slow. If possible, try setting the table as a single drop target and calculate the target table cell based on the position data in the drop event.

Unfortunately, you will also lose the ability to apply styles to individual cells on dragOver and dragOut events.

Edit: Another suggestion is to disable droppable on all tds and upon mouseover of a tr, enable the droppables of tds present in the specific tr (and disable them back upon mouseout of tr). Sounds like a hack, but worth a try.

Chetan Sastry
That's an interesting suggestion. I might have to go with that as a last resort, although it will be a shame to lose the ability to style cells, as that's fairly vital feedback to enable a user to tell what cell they're dropping onto.
Ben
Check out my edit. It may be worth a try.
Chetan Sastry
Interesting idea. I'll give that a go tomorrow. Thanks!
Ben
Your new suggestion has worked really well. It works because I only really want to be able to move a given cell from one column to another, so I've restricted movement to the x-axis, and I only have to enable droppable on tds in the same tr as the draggable. Very fast now! Thanks!
Ben
+1  A: 

As a first step, double check that you're using the latest version of jQuery. As I recall, they recently started making use of much faster browser apis (when available) to get the location of dom elements within the display. I think this was mentioned in a presentation John Resig gave recently, and drag and drop was the primary demo of the performance improvement.

Peter Burns
Wow. I only downloaded JQuery a few weeks ago, so I thought I had the latest. But I had 1.3.1, and now there's a 1.3.2. I'm not sure it's made any difference to the speed, though, I'm afraid. Good suggestion, though.
Ben