Reputation: 325
My issue is basically this - 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 but since none of the answers solved my problem, I'm asking the question again.
Applying .sortable() on 300 elements (http://jsfiddle.net/LcgEL/) takes about 60ms. Applying it to thousands of element results in times approaching 250ms. This introduces a very noticeable delay that affects the user experience as it appears the application is laggy.
Is there any way to speed this up? Thanks!
JSFiddle link for the code - http://jsfiddle.net/LcgEL/
Upvotes: 13
Views: 9026
Reputation: 9846
For me the issue was the CSS3 transition: all
property set on the sortable elements due to an erroneous comma:
.item {
transition: flex-basis ease 200ms, margin ease, 200ms;
// here ^
}
which basically equates to transition: all 200ms;
I mistakenly put a comma after ease
after the margin ease,
, removing the comma and restoring the transitions to just being on margin and flex-basis fixed it.
Upvotes: 2
Reputation: 1
If you proceed with @e-benzle suggestion and run the latest JQuery version (v3.3.1), which is the best solution so far (in my opinion), you will have to replace the following function call in the jquery-ui.js v1.11.14 script with the one from version 1.12.1 because of the errors withinElement.offset()
will throw.
Function from v1.12.1
getWithinInfo: function( element ) {
var withinElement = $( element || window ),
isWindow = $.isWindow( withinElement[ 0 ] ),
isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
hasOffset = !isWindow && !isDocument;
return {
element: withinElement,
isWindow: isWindow,
isDocument: isDocument,
offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
scrollLeft: withinElement.scrollLeft(),
scrollTop: withinElement.scrollTop(),
width: withinElement.outerWidth(),
height: withinElement.outerHeight()
};
}
Upvotes: 0
Reputation: 420
If anyone stumbles on this page because they upgraded to 1.12.1 like me and hit the performance issue:
Instead of rolling back to 1.11.4, find the _setHandleClassName
function in the sortable widget (in my custom download around line #5300 in jquery-ui.js
) and change:
$.each( this.items, function() {
that._addClass(
this.instance.options.handle ?
this.item.find( this.instance.options.handle ) :
this.item,
"ui-sortable-handle"
);
});
To:
$.each( this.items, function() {
(this.instance.options.handle
? this.item.find( this.instance.options.handle )
: this.item
).addClass('ui-sortable-handle');
});
Like it was in the previous version.
For my case this sped up the initialization of a sortable list of 700 items from ~20 seconds to some milliseconds. o_O
Do note: While I haven't seen any issues yet using this approach for my page, it hasn't been thoroughly tested due to lack of time.
Upvotes: 19
Reputation: 346
You should roll back your version of jQuery UI to version 1.11.4 https://jqueryui.com/download/all/
After struggling with this for a few days that was the only thing that helped me. I have about 800 entries being sorted between 6 lists. Using UI v1.12.1 my page was taking about 20 seconds to load. After switching to v1.11.4 my page load time was closer to 5 seconds.
I tried the solution by ekeren which partially worked, but elements that hadn't been initialized weren't in the 'sorting order' so you could only interact with elements that had already been hovered over.
Upvotes: 11
Reputation: 3458
a tough one, 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
Here is how it could be done with sortable: (http://jsfiddle.net/q8ND4/3/)
var $sortable1 = $( "#sortable1" ).sortable({
connectWith: ".connectedSortable",
items: ".sorting-initialize" // only insert element with class sorting-initialize
});
$sortable1.find(".ui-state-default").one("mouseenter",function(){
$(this).addClass("sorting-initialize");
$sortable1.sortable('refresh');
});
In your example it decreases the time from 30ms to 8ms.
Another improvement:
The next step will be to move the mouseenter handler binding to the point in code when you append these <li>
to the list (if this is done via js on the client side)
Upvotes: 14