Thursday, September 19, 2024

JQuery UI Draggable and Droppable: Use Cases



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.

"x": dragging only horizontally

"y": dragging only vertically

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>




No comments:

Post a Comment

Blog Posts

Enhancing Performance of Java-Web Applications

Applications built with a Java back-end, a relational database (such as Oracle or MySQL), and a JavaScript-based front-end form a common and...