Search code examples
javascriptjqueryjquery-ui-draggablejquery-ui-droppable

Drag multiple divs into another jQuery


I've been trying to drag divs from one div to another using jQuery. Here's what I've got so far

$(document).ready(function() {
  $(".draggable").draggable();
  $(".bucket").droppable({
    drop: function(event, ui) {
      if (($(this).attr('id')) !== ui.draggable.attr("data-bucket")) {
        ui.draggable.attr("data-bucket", $(this).attr('id'));

        var p1 = ui.draggable.parent().offset();
        $(this).append(ui.draggable);

        var p2 = ui.draggable.parent().offset();

        ui.draggable.css({
          top: parseInt(ui.draggable.css('top')) + (p1.top - p2.top),
          left: parseInt(ui.draggable.css('left')) + (p1.left - p2.left)
        });
      }
    }
  });
});
.bucket {
  width: 400px;
  height: 150px;
  background: #ddd
}

.draggable {
  width: 50px;
  height: 30px;
  margin-top: 5px;
  background: red;
}

#destination {
  background: #aaa
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<div class="bucket" id="origin">
  <div class="draggable" data-bucket="origin">Drop 1</div>
  <div class="draggable" data-bucket="origin">Drop 2</div>
  <div class="draggable" data-bucket="origin">Drop 3</div>
  <div class="draggable" data-bucket="origin">Drop 4</div>
</div>
<div class="bucket" id="destination">
</div>

I've adapted the js from this answer, but to handle multiple draggable elements I've used the data-bucket attribute to only apply the positioning when the element is initially dropped into the bucket, instead of every time it's moved around in it.

As you can see from the example, this solution kind-of works, but once more than two divs have been dragged into the destination bucket then they all start to jump around and don't land where the cursor puts them

It seems like it should be a simple fix but I've been scratching my head on this one for a day or so now, any help?


Solution

  • I've set the .draggable divs CSS to position: absolute, and the parents to position: relative. Also some adjustments for initially displaying the absolute positioned divs and showing the status after they've been dropped.

    Please have a look at the code below:

        $(document).ready(function () {
            $.each( $(".draggable"), function( key, value ) {
                $(this).css('top',(35*key)+"px");
            });
            $(".draggable").mousedown(function() {
                $("#status").html('');
            })
    
            $(".draggable").draggable();
            $(".bucket").droppable({
                drop: function (event, ui) {
                    $("#status").html(ui.draggable.html()+" is in the "+$(this).attr('id')+" bucket.");
    
                    if (($(this).attr('id')) !== ui.draggable.attr("data-bucket")) {
                        ui.draggable.attr("data-bucket", $(this).attr('id'));
    
                        var p1 = ui.draggable.parent().offset();
                        $(this).append(ui.draggable);
    
                        var p2 = ui.draggable.parent().offset();
    
                        ui.draggable.css({
                            top: parseInt(ui.draggable.css('top')) + (p1.top - p2.top),
                            left: parseInt(ui.draggable.css('left')) + (p1.left - p2.left)
                        });
                    }
                }
            });
        });
        .bucket {
            width: 400px;
            height: 150px;
            background: #ddd;
            position: relative;
        }
    
        .draggable {
            width: 50px;
            height: 30px;
            margin-top: 5px;
            background: red;
            position: absolute;
            z-index: 10;
        }
    
        #destination {
            background: #aaa;
            position: relative;
        }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
    <div class="bucket" id="origin">
        <div class="draggable" data-bucket="origin">Drop 1</div>
        <div class="draggable" data-bucket="origin">Drop 2</div>
        <div class="draggable" data-bucket="origin">Drop 3</div>
        <div class="draggable" data-bucket="origin">Drop 4</div>
    </div>
    <div class="bucket" id="destination">
    </div>
    
    <pre id="status"></pre>