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开发者_JS百科 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.
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)
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/
I had a similar problem with hundreds of images that needed to be draggable. and initialization just took too much time
I was able to solve it by lazy instantiation upon mouseenter, it works great, and the user experience is not changed
See more info here https://stackoverflow.com/a/20399896/287455
Move your code to bind all the controls out of the page load event. It won't be any faster but it will appear faster to the user. You might also change the code and markup so the individual items are disabled on load and after their events are bound they're enabled. This will prevent fast twitch users from clicking on them and wondering why nothing happened.
I was able to make it a lot faster if I hide the sortables before I call .sortable(). But, it only made a huge difference on the iPad Safari. For other browsers, it was pretty much the same.
Example code:
$(".milestone-day").hide()
$(".milestone-day").sortable({
handle: '.handle',
connectWith: '.milestone-day',
items: '.milestone',
stop: sortableStop
});
$(".milestone-day").show()
精彩评论