6

I have two jquery.ui draggables. I am constraining their movement to the y-axis. If one is dragged to a certain y-position, I want the other to automatically move to the same y-position and vice versa. Has anyone ever linked two of these together before?

jaketrent
  • 1,173
  • 11
  • 25

5 Answers5

12

Updated: Script and demo updated so it is no longer restricted to the y-axis while dragging.

This script looks for the class "group" followed by a number to drag/drop these combined objects. I posted a demo here.

HTML

<div class="demo">
<div id="draggable">
 <p>Drag from here</p>
 <div class="dragme group1"><img src="image1.jpg"><br>Group 1</div>
 <div class="dragme group1"><img src="image2.jpg"><br>Group 1</div>
 <div class="dragme group2"><img src="image3.jpg"><br>Group 2</div>
 <div class="dragme group2"><img src="image4.jpg"><br>Group 2</div>
</div>
<div id="droppable">
 <p>Drop here</p>
</div>
</div>

Script

$(document).ready(function() {
    // function to get matching groups (change '.group' and /group.../ inside the match to whatever class you want to use
    var getAll = function(t) {
        return $('.group' + t.helper.attr('class').match(/group([0-9]+)/)[1]).not(t);
    };
    // add drag functionality
    $(".dragme").draggable({
        revert: true,
        revertDuration: 10,
        // grouped items animate separately, so leave this number low
        containment: '.demo',
        stop: function(e, ui) {
            getAll(ui).css({
                'top': ui.helper.css('top'),
                'left': 0
            });
        },
        drag: function(e, ui) {
            getAll(ui).css({
                'top': ui.helper.css('top'),
                'left': ui.helper.css('left')
            });
        }
    });
    $("#droppable").droppable({
        drop: function(e, ui) {
            ui.draggable.appendTo($(this));
            getAll(ui).appendTo($(this));
        }
    });
});
Mottie
  • 84,355
  • 30
  • 126
  • 241
  • I'm getting "Uncaught TypeError: Cannot read property '1' of null" at the return statement in getAll. – user3281466 Jun 29 '15 at 11:42
  • The `ui` parameter is `undefined` during the `create` event. So don't use the `getAll` function at that time. – Mottie Jun 29 '15 at 20:18
5

I haven't done this before, but I suggest using the drag event to adjust the position of the respective other element:

$('.selector').draggable({
    ...,
    drag: function(event, ui) {

    },
    ...
});

The ui object will contain information (in the property ui.offset) you can use to manually reposition the other element.

Tom Bartel
  • 2,283
  • 1
  • 15
  • 18
2

https://forum.jquery.com/topic/dragging-a-group-of-items-alsodrag-like-alsoresize

I found an extension for UI draggable(). It works in the same way as 'alsoResize' for UI resizable(), i.e.

$('.selector').draggable({ alsoDrag: '.selected' });

Add the plugin code after main jquery-ui library.

$.ui.plugin.add( 'draggable', 'alsoDrag', {
    start: function() {
        var that = $(this).data("ui-draggable"),
            o = that.options,
            _store = function (exp) {
                $(exp).each(function() {
                    var el = $(this);
                    el.data("ui-draggable-alsoDrag", {
                        top:  parseInt(el.css("top"), 10),
                        left: parseInt(el.css("left"), 10)
                    });
                });
            };

        if (typeof(o.alsoDrag) === "object" && !o.alsoDrag.parentNode) {
            if (o.alsoDrag.length) { o.alsoDrag = o.alsoDrag[0]; _store(o.alsoDrag); }
            else { $.each(o.alsoDrag, function (exp) { _store(exp); }); }
        }else{
            _store(o.alsoDrag);
        }
    },
    drag: function () {
        var that = $(this).data("ui-draggable"),
            o = that.options,
            os = that.originalSize,
            op = that.originalPosition,
            delta = {
                top: (that.position.top - op.top) || 0,
                left: (that.position.left - op.left) || 0
            },

            _alsoDrag = function (exp, c) {
                $(exp).each(function() {
                    var el = $(this), start = $(this).data("ui-draggable-alsoDrag"), style = {},
                        css = ["top", "left"];

                    $.each(css, function (i, prop) {
                        var sum = (start[prop]||0) + (delta[prop]||0);
                        style[prop] = sum || null;
                    });

                    el.css(style);
                });
            };

        if (typeof(o.alsoDrag) === "object" && !o.alsoDrag.nodeType) {
            $.each(o.alsoDrag, function (exp, c) { _alsoDrag(exp, c); });
        }else{
            _alsoDrag(o.alsoDrag);
        }
    },
    stop: function() {
        $(this).removeData("draggable-alsoDrag");
    }
});
Arsen K.
  • 5,494
  • 7
  • 38
  • 51
0

You would have to explicitly set the Y-Axis of both the elements.

For this either in the event handler functions of both the elements you will have to set Y-Axis or bind both the elements with same function.

Happy coding.

Ravi Vanapalli
  • 9,805
  • 3
  • 33
  • 43
0

Here is a simplified version of the code mentioned in the marked answer(for dummies like me):

  • In HTML

    <div id="div1" class="group">...</div>
    <div id="div2"class="group">...</div>
    
  • In Script tag

    $(document).ready(function(){ 
        //to get the group 
        var getGroup = function() {
            return $(".group");
        }; // add drag functionality
    
        $(".group").draggable({
            revertDuration: 10,
            // grouped items animate separately, so leave this number low
            containment: "window",
            scroll: false,
            stop: function(e, ui) {
                getGroup(ui).css({
                    'top': ui.helper.css('top'),
                });
            },
            drag: function(e, ui) {
                getGroup(ui).css({
                    'top': ui.helper.css('top'),
                    'left': ui.helper.css('left')
                });
            }
        });     
    });
    
richerlariviere
  • 799
  • 2
  • 13
  • 29