Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery's selectable plugin's very slow

it's slow when used on huge lists, etc. how make it fast?

like image 271
somenamehere Avatar asked Dec 06 '10 10:12

somenamehere


4 Answers

jQuery UI selectable takes all the elements of the DOM structure, limit the numbers of elements to those that are in the top. Add a filter:

$("#items").selectable({filter: 'li'}); 

http://forum.jquery.com/topic/major-performance-problems-with-selectable

like image 171
Chumpocomon Avatar answered Nov 20 '22 06:11

Chumpocomon


If you have a huge list, you'll want to disable the expensive autoRefresh option like this:

$(".mySelector").selectable({ autoRefresh: false });

When you want (say on stop) you can refresh yourself, like this:

$(".mySelector").selectable("refresh");
like image 36
Nick Craver Avatar answered Nov 20 '22 08:11

Nick Craver


I found that jquery.selectable is very slow in older browsers (like IE7 and 8) because it has to call the .offset() method on each item. I was using it on the cells in a table, so I was able to reduce the number of .offset() calls to one for each row and one for each column (instead of one call for every cell) by making a modified version of the plugin with a modified refresh function. This made the performance acceptable for large tables. The cellPositions array holds the horizontal position for each column.

      this.refresh = function() {
            var cellPositions = [];
            var firstRow = true;
            selecteeRows = $("tr", self.element[0]);
            selecteeRows.each(function() {
                var row = $(this);
                // adding any filters here seems to slow down IE a lot
                // self.options.filter is not used!!
                var selecteeCells = $(row).find("td"); 
                if (firstRow && selecteeCells.length > 0) {
                    for (var i = 0; i < selecteeCells.length; i++) {
                        cellPositions[i] = $(selecteeCells[i]).offset().left;
                    }
                    cellPositions[selecteeCells.length] = cellPositions[selecteeCells.length - 1] + $(selecteeCells).outerWidth(true);
                    firstRow = false;
                }
                if (selecteeCells.length > 0) {
                    var top = $(selecteeCells).first().offset().top;
                    var bottom = top + $(selecteeCells).first().outerHeight();
                    var i = 0;
                    selecteeCells.each(function() {
                        var $this = $(this);
                        first = false;
                        $.data(this, "selectable-item", {
                            element: this,
                            $element: $this,
                            left: cellPositions[i],
                            top: top,
                            right: cellPositions[i + 1],
                            bottom: bottom,
                            startselected: false,
                            selected: $this.hasClass('ui-selected'),
                            selecting: $this.hasClass('ui-selecting'),
                            unselecting: $this.hasClass('ui-unselecting')
                        });
                        i++;
                    });
                }
            });

        };

Edit: Here's a link to the code in github: https://github.com/dfjackson/jquery.ui.selectableTable

like image 20
Rn222 Avatar answered Nov 20 '22 08:11

Rn222


Unlike other jquery ui methods, selector is applied even on nested elements. to select only direct ancestors use:

jQuery('#content').selectable({
filter: '>*',
});
like image 2
Neil Woods Avatar answered Nov 20 '22 08:11

Neil Woods