23

I want to be able to drag a group of elements with jQuery, like if I selected and dragged multiple icons on the Windows desktop.

I found the demo of threedubmedia's jQuery.event.drag:

http://threedubmedia.com/code/event/drag/demo/multi
http://threedubmedia.com/code/event/drag#demos

I think this plugin is great. Is this good and popular library? Do you know websites or applications which use it?

Are there any other libraries or plugins to drag multiple objects?

Can jQuery UI drag multiple objects?

isherwood
  • 58,414
  • 16
  • 114
  • 157
js_
  • 4,671
  • 6
  • 44
  • 61
  • What do you mean by dragging multiple objects? You can bind jQuery UI's draggable to multiple elements, but to make all/some of them move at once, you'll have to implement your logic on top of it. – Ortiga Apr 15 '11 at 14:16
  • Yes, I wanna make all/some objects move at once. – js_ Apr 15 '11 at 14:21
  • How can i do it with jQuery UI? – js_ Apr 15 '11 at 14:21
  • Take a look in the documentation, in the events there will be start event. Try adding .ui-draggable-dragging class to the other elements you're trying to move. I may be wrong, but I think UI uses this class to move the element, so they'll move together. – Ortiga Apr 15 '11 at 16:52
  • See http://stackoverflow.com/questions/793559/grouping-draggable-objects-with-jquery-ui-draggable for the solution you're looking for. – Greg Blass Dec 02 '16 at 22:23

8 Answers8

12
var selectedObjs;
var draggableOptions = {
    start: function(event, ui) {
        //get all selected...
        selectedObjs = $('div.selected').filter('[id!='+$(this).attr('id')+']');
    },
    drag: function(event, ui) {
        var currentLoc = $(this).position();
        var orig = ui.originalPosition;

        var offsetLeft = currentLoc.left-orig.left;
        var offsetTop = currentLoc.top-orig.top;

        moveSelected(offsetLeft, offsetTop);
    }       
};

$(document).ready(function() {
    $('#dragOne, #dragTwo').draggable(draggableOptions);
});

function moveSelected(ol, ot){
    console.log(selectedObjs.length);
    selectedObjs.each(function(){
        $this =$(this);
        var pos = $this.position();

        var l = $this.context.clientLeft;
        var t = $this.context.clientTop;

        $this.css('left', l+ol);
        $this.css('top', t+ot);
    })
}
ChrisThompson
  • 1,998
  • 12
  • 17
11

I am the author of the of the threedubmedia plugins. I added this functionality for supporting multiple elements, because I could not find a satisfactory solution anywhere else.

If you need a solution that works with the jQuery UI, here is a plugin which adds some multi-drag functionality, though the demos don't seem to work correctly in Firefox for Mac.

http://www.myphpetc.com/2009/11/jquery-ui-multiple-draggable-plugin.html

BSMP
  • 4,596
  • 8
  • 33
  • 44
  • thanks for introducing your plugin. can i group items by just a click(not by a ctrl-click)? can i customize effect when items are grouped? your demo changes color of a item when it is grouped. but i wanna move position of a object some pixels when it is grouped. and can i handle end-of-drag event with your plugin? – js_ Apr 16 '11 at 06:18
  • Sorry if I was not entirely clear. I am the author of the threedubmedia plugins. I was simply posting the other link as an example of creating similar functionality with jQuery UI. – mike.helgeson May 10 '11 at 20:25
  • sorry for my misunderstanding. im very glad and surprised to get an answer from the author of the threedubmedia plugins! im using your jquery.event.drag for my software which im developing now. i like your plugin. its really simple and powerful as you say. – js_ May 11 '11 at 06:47
7

This worked for me.

Fiddle here:

var selectedObjs;
var draggableOptions = {
start: function(event, ui) {
    //get all selected...
    if (ui.helper.hasClass('selected')) selectedObjs = $('div.selected');
    else {
        selectedObjs = $(ui.helper);
        $('div.selected').removeClass('selected')
    }
},
drag: function(event, ui) {
    var currentLoc = $(this).position();
    var prevLoc = $(this).data('prevLoc');
    if (!prevLoc) {
        prevLoc = ui.originalPosition;
    }

    var offsetLeft = currentLoc.left-prevLoc.left;
    var offsetTop = currentLoc.top-prevLoc.top;

    moveSelected(offsetLeft, offsetTop);
    selectedObjs.each(function () {
           $(this).removeData('prevLoc');
        });
    $(this).data('prevLoc', currentLoc);
}
};

$('.drag').draggable(draggableOptions).click(function()     {$(this).toggleClass('selected')});


function moveSelected(ol, ot){
console.log("moving to: " + ol + ":" + ot);
selectedObjs.each(function(){
    $this =$(this);
    var p = $this.position();
    var l = p.left;
    var t = p.top;
    console.log({id: $this.attr('id'), l: l, t: t});


    $this.css('left', l+ol);
    $this.css('top', t+ot);
})
}

Thanks to ChrisThompson and green for the almost-perfect solution.

Bug
  • 2,576
  • 2
  • 21
  • 36
1

Check this out:

https://github.com/someshwara/MultiDraggable

Usage:$(".className").multiDraggable({ group: $(".className")});

Drags the group of elements together. Group can also be an array specifying individual elements.

Like:$("#drag1").multiDraggable({ group: [$("#drag1"),$("#drag2") ]});

1

I wanted to add (this coming up high in google), since none of the plugins in this thread worked and it is not nativity supported by jquery ui, a simple elegant solution.

Wrap the draggable elements in a container and use an event to drag them all at once, this allows for singles draggables and multidraggables (but not really selective draggables).

jQuery(document).click(function(e) {

  if(e.shiftKey) {
      jQuery('#parent-container').draggable();
  }
}); 
Wyck
  • 2,023
  • 4
  • 28
  • 34
  • This solution is obvious, but not always possible, especially when elements you want to drag at once are located in different containers and this order can't be changed. – user35443 Jul 01 '16 at 09:31
0

Put your items into some container and make this container draggable. You will need to set handle option to be a class of your item element. Also you will need to recalculate items position after drag. And obviously when you deselect items you have to take them from this container and put back to their origin.

Ev_genus
  • 135
  • 11
  • this way you won't be able to select individual elements within that container. – magikMaker Nov 22 '12 at 11:05
  • this is a good solution but needs some calculation on put inside container and after realease with CTRL get destroy the parent container and add elements back +1 – albanx Nov 29 '12 at 15:50
0

This is what i used, Worked in my case.

function selectable(){
$('#selectable').selectable({
  stop: function() {
    $('.ui-selectee', this).each(function(){
        if ($('.ui-selectee').parent().is( 'div' ) ) {
            $('.ui-selectee li').unwrap('<div />');
        }


    });

    $('.ui-selected').wrapAll('<div class=\"draggable\" />');

    $('.draggable').draggable({ revert : true });   
  }
});

};

Sjoerd de Wit
  • 2,353
  • 5
  • 26
  • 45
-20

there is Draggable in the jquery UI

all you would have to do is:

$(selector).draggable(); // and you are done!

see example here: http://jsfiddle.net/maniator/zVZFq/


If you really want multidragging you can try using some click events to hold the blocks in place

$('.drag').draggable();

$('.drag').click(function(){
    console.log(this, 'clicked')
    var data = $(this).data('clicked');
    var all = $('.all');
    if(data == undefined || data == false){
        $(this).data('clicked', true);
        this.style.background = 'red';
        $(this).draggable('disable');
        if(all.children().length <= 0){
            all.draggable().css({
                top: '0px',
                left: '0px',
                width: $(window).width(),
                height: $(window).height(),
                'z-index': 1
            });
        }
        var top = parseInt(all.css('top').replace('px','')) +
                    parseInt($(this).css('top').replace('px',''))
        var left = parseInt(all.css('left').replace('px','')) +
                    parseInt($(this).css('left').replace('px',''))
        $(this).css({
            top: top,
            left: left
        })
        $('.all').append($(this));
    }
    else {
        $(this).data('clicked', false);
        this.style.background = 'grey';
        $(this).draggable('enable');
        $('body').append($(this));
        if(all.children() <= 0){
            all.draggable('destroy');
        }
        /*
        var top = parseInt(all.css('top').replace('px','')) -
                    parseInt($(this).css('top').replace('px',''))
        var left = parseInt(all.css('left').replace('px','')) -
                    parseInt($(this).css('left').replace('px',''))
        $(this).css({
            top: top,
            left: left
        })*/
    }
})

See example here: http://jsfiddle.net/maniator/zVZFq/5

Naftali
  • 144,921
  • 39
  • 244
  • 303
  • 3
    Thanks for your answer. But i think draggable() makes single-object-drag possible, not multiple-object-drag. http://threedubmedia.com/code/event/drag/demo/multi is a demo of multiple-object-drag. 1. First, click some objects. 2. Then the color of the objects changed. 3. And if you drag the object which clicked before, all of clicked objects move. – js_ Apr 15 '11 at 14:32
  • @js_ you can use multiple selectors and they all will become draggable. ill make a fiddle, one minute – Naftali Apr 15 '11 at 14:33
  • @js_ i made a fiddle and attached it to my answer. – Naftali Apr 15 '11 at 14:35
  • Thank you very much for making a fiddle. But what i wanna do is to drag more than two objects by a single drag. In your fiddle, i only can drag a object by a single drag. – js_ Apr 15 '11 at 14:41
  • 3
    @_js i updated the fiddle here: http://jsfiddle.net/maniator/zVZFq/5/ its not perfect but im sure you can fix it ^_^ – Naftali Apr 15 '11 at 14:58
  • @js_ it does not work perfectly, but that is the best i can do in the short time i had, ur welcome :-). On stack you should pick the best answer as `accepted` that way on future questions people would be more likely to help you out ^_^ – Naftali Apr 15 '11 at 15:11
  • As far as I can tell, there's no way to drag multiple elements. It's at least not as simple as just calling `draggable()`. I did find this plugin was pretty much perfect: http://comp345.awardspace.com/multidraggable/base.html – Wesley Murch Mar 18 '12 at 01:32
  • 2
    @WesleyMurch I've updated Neals's fiddle and it works perfect without the multidraggable plugin: http://jsfiddle.net/zVZFq/358/ – Gelin Luo Sep 12 '12 at 23:18
  • @Neal you should update the answer to the solution in your second fiddle (jsfiddle.net/maniator/zVZFq/5) as this is a popular question and the accepted answer does not work as the question asked and has a negative score. – Lonergan6275 Aug 03 '18 at 15:30
  • Done @Lonergan6275 :-) – Naftali May 14 '19 at 19:37