Is there a JQuery plugin which combines Draggable and Selectable

Will Dean picture Will Dean · Apr 1, 2009 · Viewed 22.3k times · Source

I'm looking to implement a web interface with a number of items which can be selected and dragged around to position them, either in groups or singly. Rather like the Windows Desktop, really.

We're using JQuery already, so additions to that would be first choice. JQuery UI Draggables and Selectables individually do much of what we want, but don't really work together to give the sort of effect we're looking for.

I am completely overwhelmed by the JQ plugin site (it's 'popular' algorithm doesn't seem very useful), and would welcome guidance as to the best way to avoid a lot of wheel-reinvention here, as I would guess that this metaphor has already been done.

Answer

Sinan picture Sinan · Jun 28, 2009

I also needed to do same thing, and i didn't want to use interface extension from eyecon.ro. After some research, I found Combining Selectables And Draggables Using jQuery UI. It is nicely told but to make the code snippets run you have to dig into it. I was able to make it work. I slightly changed it, this is my way to get it done. It needs modifications for using on production level, but i hope it helps.

// this creates the selected variable
// we are going to store the selected objects in here
var selected = $([]), offset = {top:0, left:0}; 

// initiate the selectable id to be recognized by UI
$("#selectable").selectable({
    filter: 'div',
});

// declare draggable UI and what we are going to be doing on start
$("#selectable div").draggable({
     start: function(ev, ui) {
        selected = $(".ui-selected").each(function() {
           var el = $(this);
            el.data("offset", el.offset());
        });

        if( !$(this).hasClass("ui-selected")) $(this).addClass("ui-selected");
        offset = $(this).offset();
    },
    drag: function(ev, ui) {
        var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left;

        // take all the elements that are selected expect $("this"), which is the element being dragged and loop through each.
        selected.not(this).each(function() {
             // create the variable for we don't need to keep calling $("this")
             // el = current element we are on
             // off = what position was this element at when it was selected, before drag
             var el = $(this), off = el.data("offset");
             el.css({top: off.top + dt, left: off.left + dl});
        });
    }
});

CSS Styles to be able to see what's happening:

#selectable {   width: 100%; height: 100%;}
#selectable div {
    background: #ffc;
    line-height: 25px;
    height: 25px;
    width: 200px;
    border: 1px solid #fcc;
    }
#selectable div.ui-selected {
    background: #fcaf3e;
    }
#selectable div.ui-selecting {
    background: #8ae234;
    }

HTML Markup:

<div id="selectable">
    <div>item 1</div>
    <div>item 2</div>
    <div>item 3</div>
    <div>item 4</div>
</div>