Programmatically drag and drop element onto another element
Asked Answered
T

3

7

With jQuery UI, is it possible to execute a drag & drop operation using javascript?

Example. When the link is clicked, drag the #pony and drop it into the #box. I've tried triggering the drag event but that doesn't seem work :)

$('#pony').trigger('drag', [$('#box')]);
Terenceterencio answered 31/5, 2013 at 0:50 Comment(0)
O
19

This is how the jQuery UI team programmatically trigger drop event.

droppable_events.js:

draggable = $( "#draggable1" ).draggable(),
droppable1 = $( "#droppable1" ).droppable( config ),
droppable2 = $( "#droppable2" ).droppable( config ),

droppableOffset = droppable1.offset(),
draggableOffset = draggable.offset(),
dx = droppableOffset.left - draggableOffset.left,
dy = droppableOffset.top - draggableOffset.top;

draggable.simulate( "drag", {
    dx: dx,
    dy: dy
});

The simulate function is defined in jquery.simulate.js. In simple words, it moves the draggable onto the droppable to trigger the drop event.

Putting this altogether, we have the following snippet. Cheers.

$(function() {
  $("#draggable").draggable();
  $("#droppable").droppable({
    drop: function(event, ui) {
      console.log(event, ui);
      alert('dropped!');
    }
  });
});

function trigger_drop() {
  var draggable = $("#draggable").draggable(),
    droppable = $("#droppable").droppable(),

    droppableOffset = droppable.offset(),
    draggableOffset = draggable.offset(),
    dx = droppableOffset.left - draggableOffset.left,
    dy = droppableOffset.top - draggableOffset.top;

  draggable.simulate("drag", {
    dx: dx,
    dy: dy
  });
}
#draggable {
  width: 100px;
  height: 100px;
  padding: 0.5em;
  float: left;
  margin: 10px 10px 10px 0;
}
#droppable {
  width: 150px;
  height: 150px;
  padding: 0.5em;
  float: left;
  margin: 10px;
}
br {
  clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>

<script src="https://rawgit.com/jquery/jquery-ui/1-11-stable/external/jquery-simulate/jquery.simulate.js"></script>


<div id="draggable" class="ui-widget-content">
  <p>Drag me to my target</p>
</div>

<div id="droppable" class="ui-widget-header">
  <p>Drop here</p>
</div>
<br>
<button onclick="trigger_drop()">trigger drop event</button>
Orren answered 26/3, 2015 at 17:4 Comment(0)
S
2
  • If you want to fire the same functionality that happens when you actually do drop the object by mouse, you can encapsulate your drop script into a function that you then can simply call elsewhere, too.

  • If you want to have an animated motion of your item being dragged & dropped, you should .stop().animate({}) it to the target position, followed by the step above.

  • If you simply want to append it to the drop target, just .appendTo($('#yourtargetid'));.

Sorry if I missunderstood anything, my reputation points aint enough to just ask you beforehand as I'd have done everywhere else.

Simarouba answered 31/5, 2013 at 1:21 Comment(0)
C
1

If you want to do it with HTML draggable elements, without jquery you need to mock the google chrome dataTransfer API with your own class, because google does not want you creating your own dataTransfer instance.

function simulateDragAndDrop(sourceNode, destinationNode) {


 class MyDataTransfer {
        constructor() {
            this.dropEffect = "all";
            this.effectAllowed = "all";
            this.files = [];
            this.items = new DataTransferItemList();
            this.types = [];
        }
        setData(format, data) {
            this.data[format] = data;
        }
        getData(format) {
            return this.data[format];
        }
        clearData(format = null) {
            if (format) {
                delete this.data[format];
            } else {
                this.data = {};
            }
        }
        clearData(type) {
            if (type) {
                const index = this.types.indexOf(type);
                if (index !== -1) {
                    this.types.splice(index, 1);
                }
            } else {
                this.types = [];
            }
        }

        getData(type) {
            const index = this.types.indexOf(type);
            return index !== -1 ? this.items[index].data : '';
        }

        setData(type, data) {
            const index = this.types.indexOf(type);
            if (index !== -1) {
                this.items[index].data = data;
            } else {
                this.types.push(type);
                this.items.add(new DataTransferItem(type, data));
            }
        }

        setDragImage(imageElement, x, y) {
            // I do nothing here it's just to avoid errrs
        }
    }

    class DataTransferItem {
        constructor(type, data) {
            this.type = type;
            this.data = data;
        }
    }

    class DataTransferItemList extends Array {
        add(item) {
            this.push(item);
        }
    }
    const EVENT_TYPES = {
        DRAG_END: 'dragend',
        DRAG_START: 'dragstart',
        DROP: 'drop'
    }
    const dataTransfer = new MyDataTransfer();

    function createCustomEvent(type) {
        const event = new CustomEvent(type, {
            bubbles: true,
            cancelable: true
        });
        event.dataTransfer = dataTransfer;
        return event;
    }

    let events = [];

    // let myDataTransfer = new MyDataTransfer();
    events.push(createCustomEvent(EVENT_TYPES.DRAG_START));

    events.push(createCustomEvent(EVENT_TYPES.DROP));

    // Dispatch dragstart and dragend events on the sourceNode
    events.forEach((event) => sourceNode.dispatchEvent(event));

    const dropEvent = createCustomEvent(EVENT_TYPES.DROP);
    destinationNode.dispatchEvent(dropEvent);

}

Cannular answered 19/10, 2023 at 5:23 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.