Key Concepts
Drag and drop is a common functionality in web applications. jQuery offers robust features like ‘draggable’ and ‘droppable’ that enable drag-and-drop functionality and enhance user-friendly interfaces. Let’s explore the key features of this functionality and how to implement various drag-and-drop scenarios using jQuery.
Draggable
You can make an element draggable using jQuery UI if you apply the ‘draggable()’ method on that element. We introduce and explain the main options and events of the draggable feature in the two following tables.
Main Draggable Options |
|||
Option |
Definition |
Possible Value |
Syntax |
axis |
It limits the dragging of the element to a particular axis. |
|
axis: "y" |
containment |
It restricts the dragging area to a container element. |
- "parent" - "document" - "window" - jQuery selector |
containment: "parent" |
cursor |
It applies a cursor when the element is being dragged. |
CSS cursor value |
cursor: "move" |
handle |
It limits dragging to a specific child of the draggable element. |
jQuery selector |
handle: ".handle" |
helper |
It specifies the helper element for displaying the dragging action. |
- "original": the original element (default) - "clone": a copy of the element - Custom: function which returns a DOM element |
helper: "clone" |
revert |
It helps return the draggable element to its original position after dragging it. |
- true: always revert the dragging - false: never revert the dragging - "invalid": revert the dragging if the element dropped in a non-droppable area |
revert: "invalid" |
scroll |
It determines whether the page should scroll when the draggable element is being dragged near the edge of the viewport. |
- true: enable the auto-scrolling (default) - false: disable the auto-scrolling |
scroll: false |
opacity |
It is the opacity value of the draggable element during a dragging action. |
A valid opacity value, which is a number between 0 and 10. |
opacity: 0.5 |
cancel |
It disables dragging particular children of the draggable element. |
jQuery selector |
cancel: ".non-draggable" |
Main Draggable Events |
||
Event |
Definition |
Syntax |
start |
It is triggered when the user starts dragging the element. |
start: function(event, ui) { console.log("Dragging started!"); } |
drag |
It is triggered repeatedly as the element is being dragged. |
drag: function(event, ui) { console.log("Dragging in progress!"); } |
stop |
It is triggered when the dragging stops. |
stop: function(event, ui) { console.log("Dragging stopped!"); } |
Main Event Parameters |
||
event |
The corresponding event. |
drag: function(event, ui) { console.log("event:", event); } |
ui |
A jQuery UI object that contains the draggable element's properties like ‘helper’, ‘position’, and ‘offset’. |
drag: function(event, ui) { console.log("ui:", ui); } |
ui.helper |
The draggable element at the time it is dragged. |
|
ui.position |
The current position of the draggable element (top, left), relative to the parent. |
|
ui.offset |
The current position of the draggable element (top, left), relative to the document. |
|
Droppable
Similarly, you can make an element droppable using jQuery UI if you apply the ‘droppable()’ method on that element. The element marked as droppable will react when a draggable element is dropped on it. The main options and events of the droppable functionality are summarized in the following two tables.
Main Droppable Options |
|||
Option |
Definition |
Value |
Syntax |
accept |
It describes which draggable elements are accepted by the droppable element. |
jQuery selector |
accept: "#specific-draggable" |
activeClass |
It applies a CSS class to the droppable element when a draggable is being dragged. |
CSS class |
activeClass: "ui-state-hover" |
tolerance |
It determines whether the drop can be performed based on the intersection area between them when a draggable element hovers over a droppable. |
"fit": The draggable must be entirely inside the droppable. "intersect": The draggable must overlap the droppable by at least 50% (default). "pointer": The mouse pointer must overlap the droppable. "touch": The draggable must overlap the droppable at any point. |
tolerance: "pointer" |
Main Droppable Events |
||
Event |
Definition |
Syntax |
drop |
It is triggered when the draggable is dropped on the droppable. |
drop: function(event, ui) { console.log("Element dropped:", ui.draggable); } |
activate |
It is triggered when the draggable starts being dragged, and the droppable is prepared to be dropped on it. |
activate: function(event, ui) { $(this).css("border", "2px dashed red"); }, |
deactivate |
It is triggered when dragging ends. |
deactivate: function(event, ui) { $(this).css("border", ""); } |
over |
It is triggered when a draggable is being dragged over the droppable. |
over: function(event, ui) { $(this).css("background-color", "lightyellow"); } |
out |
It is triggered when a draggable is dragged out of the droppable. |
out: function(event, ui) { $(this).css("background-color", ""); } |
Dragging and Dropping an Element
Here is an example of dragging and dropping an original element, which is the contents of a table cell. The draggable element will replace the contents of another cell if the user confirms the drop action (confirm dialog box will be opened). If the user rejects the replacement action, the dragged object will return to each initial position.
Note. You can download the full example here:
https://github.com/noura-github/drag-drop-jquery
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script>
$(document).ready(function(){
$(".draggable").draggable({
containment: "#dragDropTab",
axis: "y",
tolerance: "pointer",
cursor: "move",
revert: "invalid",
helper: "original", //clone
scroll: true,
opacity: 0.5,
cancel: ".non-draggable"
});
$(".droppable").droppable({
accept: ".draggable",
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
greedy: true,
drop: function(event, ui) {
let source = ui.draggable.text();
let target = $(event.target).find('div').text();
if (confirm("Are you sure to move " + source + " to " + target + "?")) {
$(this).find('div').replaceWith(ui.draggable.html())
ui.draggable.remove();
} else {
ui.draggable.draggable('option', 'revert', true);
}
}
});
});
</script>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid lightgrey;
text-align: left;
padding: 10px;
}
tr:nth-child(even) {
background-color: lightgrey;
}
</style>
</head>
<body>
<table id="dragDropTab">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody id="myTable">
<tr>
<td><div class="draggable">Jack</div></td>
<td><div class="draggable">Sparrow</div></td>
<td><div class="draggable">jack@gmail.com</div></td>
</tr>
<tr>
<td>Mary</td>
<td>Cruze</td>
<td>mary@gmail.com</td>
</tr>
<tr>
<td><div class="non-draggable">Hony</div></td>
<td><div class="non-draggable">Moon</div></td>
<td><div class="non-draggable">hony@gmail.com</div></td>
</tr>
<tr>
<td class="droppable"><div>Tanya</div></td>
<td class="droppable"><div>Crood</div></td>
<td class="droppable"><div>tanya@yahoo.com</div></td>
</tr>
</tbody>
</table>
</body>
</html>
Swapping two Elements
Here is an example of how to swap the contents of two table cells. Take the example above and replace the custom script section with the following script. To write this code, we defined a function ‘swapWith’ to swap two elements using the JavaScript ‘replaceWith’ method. This method replaces existing content in the DOM with new content.
<script>
$(document).ready(function(){
jQuery.fn.swapWith = function(to) {
return this.each(function() {
var clone_to = $(to).clone(true);
var clone_from = $(this).clone(true);
$(to).replaceWith(clone_from);
$(this).replaceWith(clone_to);
});
};
$(".draggable").draggable({
containment: "#dragDropTab",
axis: "y",
tolerance: "pointer",
cursor: "move",
revert: "invalid",
helper: "clone",
scroll: true,
cancel: ".non-draggable"
});
$(".droppable").droppable({
accept: ".draggable",
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
greedy: true,
drop: function(event, ui) {
let source = ui.draggable.text();
let target = $(event.target).find('div').text();
if (confirm("Are you sure to swap " + source + " and " + target + "?")) {
$($(this).find('div')).swapWith($(ui.draggable));
} else {
ui.draggable.draggable('option', 'revert', true);
}
}
});
});
</script>
Drag & Drop a Group of Elements
Here is an example of how to drag the contents of multiple table cells (one row) onto another row. Take the entire example above and replace the custom script section with the following:<script>
$(document).ready(function(){
$(".draggable").draggable({
containment: "#dragDropTab",
axis: "y",
tolerance: "pointer",
cursor: "move",
revert: "invalid",
helper: "clone",
scroll: true,
opacity: 0.5,
cancel: ".non-draggable",
helper: function(){
var selected = $('#dragDropTab tr td').children(".draggable");
if (selected.length === 0) {
selected = $(this);
}
var container = $('<div/>').attr('id', 'draggingContainer');
container.append(selected.clone());
return container;
}
});
$(".droppable").droppable({
accept: ".draggable",
activeClass: "ui-state-hover",
hoverClass: "ui-state-active",
greedy: true,
drop: function(event, ui) {
let source = "(" + $.map(ui.helper.children(), function(element) { return $(element).text()}).join(", ") + ")";
let target = "(" + $.map($(event.target).parent('tr').find('td'), function(element) { return $(element).text()}).join(", ") + ")";
if (confirm("Are you sure to move " + source + " to " + target + "?")) {
let cell = $(this);
$.each(ui.helper.children(), function() {
let child = $(this);
cell.empty();
cell.append(child);
cell = cell.next();
});
} else {
ui.draggable.draggable('option', 'revert', true);
}
}
});
});
</script>