Enable Shift-Multiselect in jQuery UI Selectable

bardiir picture bardiir · Feb 21, 2012 · Viewed 18.3k times · Source

I want to enable multiselect capabilities in a jQuery UI Selectable table by holding shift.

I probably should do something like this if shift is held down on mouseclick

  • Get topmost selected element
  • Get clicked element
  • Select all elements in between

but i can't find how to do this in a clean way...

At the moment i got this inside the selectable configuration:

start: function(e)
        {
            var oTarget = jQuery(e.target);
            if(!oTarget.is('tr')) oTarget = oTarget.parents('tr');
        }

So oTarget is the clicked element (and e.currentTarget is the whole table) but now what? How can i find which elements are already selected in a way that can tell me if the clicked element is over or below the selected ones and select everything in between?

I've solved it now like this, added to the selectable element:

jQuery(table).mousedown(function(e)
    {
        //Enable multiselect with shift key
        if(e.shiftKey)
        {
            var oTarget = jQuery(e.target);
            if(!oTarget.is('.ui-selectee')) oTarget = oTarget.parents('.ui-selectee');

            var iNew = jQuery(e.currentTarget).find('.ui-selectee').index(oTarget);
            var iCurrent = jQuery(e.currentTarget).find('.ui-selectee').index(jQuery(e.currentTarget).find('.ui-selected'));

            if (iCurrent < iNew) {
                iHold = iNew;
                iNew = iCurrent;
                iCurrent = iHold;
            }

            if(iNew != '-1')
            {
                jQuery(e.currentTarget).find('.ui-selected').removeClass('ui-selected');
                for (i=iNew;i<=iCurrent;i++) {
                    jQuery(e.currentTarget).find('.ui-selectee').eq(i).addClass('ui-selected');
                }
                e.stopImmediatePropagation();
                e.stopPropagation();
                e.preventDefault();
                return false;
            }
        }
    }).selectable(...)

Answer

mac picture mac · Jan 22, 2013

You can do it without plugins like this:

var prev = -1; // here we will store index of previous selection
$('tbody').selectable({
    selecting: function(e, ui) { // on select
        var curr = $(ui.selecting.tagName, e.target).index(ui.selecting); // get selecting item index
        if(e.shiftKey && prev > -1) { // if shift key was pressed and there is previous - select them all
            $(ui.selecting.tagName, e.target).slice(Math.min(prev, curr), 1 + Math.max(prev, curr)).addClass('ui-selected');
            prev = -1; // and reset prev
        } else {
            prev = curr; // othervise just save prev
        }
    }
});

Here is live demo: http://jsfiddle.net/mac2000/DJFaL/1/embedded/result/