Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying jQuery UI Sortable to hundreds of elements on a page results in very slow page load -- need ideas on how to make it more efficient

I'm building a drag and drop calendar and have found that jQuery UI's sortable offers the best live performance for what I'm trying to do.

However, applying sortable to many months worth of days (60 to 180 days at a time -- sometimes more) results in a noticeable lag upon page load as my script is applying all those sortable instances. It works fine once it's loaded, but I'd rather not have the initial lag. In some cases the browser even tries to kill the script.

I tried making the first day of the calendar sortable and then using jQuery's .clone() to copy to all the other days, but unfortunately jQuery's .clone() doesn't appear to copy .sortable's events. Other events (such as click, double click, etc) get copied fine, but not sortable. Doing some research online, all I could find was the statement that jQuery "doesn't support cloning of plugins."

Is there a better way to do this? I've scoured stackoverflow, jQuery UI's forums, and Google in general, and have found nothing of help.

Thanks in advance, Jamon

EDIT: Here is some code. Nothing too special.

    function sortableStop(event, ui) {
              // Saves to the DB here. Code removed - not relevant
    }

    $(".milestone-day").bind("dblclick", function(ev) {
      // Allows adding milestones. Code removed - not relevant
    }).sortable({
        handle: '.handle',
        connectWith: '.milestone-day',
        items: '.milestone',
        stop: sortableStop
    });

The markup looks like this:

<table>
  <tbody>
    <tr>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
    </tr>
    <tr>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
      <td><ul class="milestone-day"></ul></td>
    </tr>
    ...
  </tbody>
</table>

Milestones are li elements loaded into their proper milestone-day uls via ajax.

EDIT 2: Working demo posted:

http://www.clearsightstudio.com/demos/calendar-load/

EDIT 3: Demo is gone. Sorry.

Note that there's a lag when you open the page. There's a lot more going on than on that demo in my actual app, so the lag is even more noticeable.

like image 844
Jamon Holmgren Avatar asked May 03 '11 18:05

Jamon Holmgren


People also ask

How does jquery sortable work?

jQueryUI provides sortable() method to reorder elements in list or grid using the mouse. This method performs sortability action based upon an operation string passed as the first parameter.

What is UI sortable?

ui-sortable-handle : The handle of each sortable item, specified using the handle option. By default, each sortable item itself is also the handle. ui-sortable-placeholder : The element used to show the future position of the item currently being sorted.


2 Answers

call the connectWith after call the sortable(), example:

$('.whatever').sortable().sortable( "option", "connectWith", '.whatever' );

for some reason it improved the performance a LOT in my scenario (thousands of elements)

like image 61
Guilherme Lundgren Avatar answered Oct 14 '22 11:10

Guilherme Lundgren


try not to bind all the elements onload do something like this

<script type="text/javascript">
            jQuery(".milestone").live("mouseenter", function(){
                function sortableStop(event, ui) {
                    alert("Sortable stop fired!");
                }

                $($(this).parent()).bind("dblclick", function() {
                    alert("Double-click fired!");
                }).sortable({
                    connectWith: '.milestone-day',
                    items: '.milestone',
                    stop: sortableStop
                });
            });
        </script>

this will improve the performance

Demo: http://jsfiddle.net/P27qv/

like image 21
Kishore Avatar answered Oct 14 '22 11:10

Kishore