somenamehere
somenamehere

Reputation: 71

jquery's selectable plugin's very slow

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

Upvotes: 7

Views: 3363

Answers (6)

M. Mehrjardi
M. Mehrjardi

Reputation: 19

Had the same problem with a very large list and ended up handling the hover event and calling .selectable() there for each row. That solved the issue for me.

Upvotes: 0

Nick Craver
Nick Craver

Reputation: 630369

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");

Upvotes: 11

Rn222
Rn222

Reputation: 2207

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

Upvotes: 4

Alex
Alex

Reputation: 1673

I know this is a couple of years too late, but I've been trying to get selectable feeling snappy on a 50x100 table.

I have found that if I create the selectable on the table's container div (with filter:'td') prior to inserting the table content it runs super fast. In firefox it was instantiating in about 1ms (compared to about 100 when creating it on pre-existing content).

Upvotes: 0

Chumpocomon
Chumpocomon

Reputation: 161

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

Upvotes: 16

Neil Woods
Neil Woods

Reputation: 123

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

jQuery('#content').selectable({
filter: '>*',
});

Upvotes: 2

Related Questions