TransWikia.com

jQuery removeClass not working with draggable

Stack Overflow Asked by Heila Al-Mogren on January 21, 2021

so I’m trying to make a schedule table where lectures can be dragged from a cell to another, unless the new cell already has a lecture, in this case dragging will be rejected. I’m trying to do this by adding and removing class ‘has_lecture’ from the cell to indicate if it should allow moving cells into or not.
Here is my code.. but for some reason the remove class doesn’t work.

$(".draggable").draggable({
            revert: 'invalid'
        });

        $(".droppable").droppable({
            accept: function () {
                return (!$(this).hasClass('has_lecture'))
            },
            drop: function (event, ui) {
                var $this = $(this);
                ui.draggable.position({
                    my: "center",
                    at: "center",
                    of: $this,
                    using: function (pos) {
                        $(this).animate(pos, 200, "linear");
                    }
                });
                $(this).addClass('has_lecture')

            },
            out: function () {
                    // this line doesn't work
                    $(this).removeClass('has_lecture')
            }
        });

One Answer

The accept function runs whenever the draggable moves over the droppable. That means it checks when you are dragging in, and it also checks when you are dragging out. Once you have dropped it in and set the has_lecture class, your accept function runs as you attempt to drag it out, and since it has the has_lecture class, it always returns false, and never gives your out function a chance to run.

So, knowing about this sort of unexpected behavior, the idea is: if the drop zone is empty, it should only accept if it does not have the has_lecture class. But if the dropzone is not empty, it should continue to accept the element that is currently in it. That will allow you to drag it out. So, once you drag an element into the dropzone, store a reference to the element on the dropzone via $(this).data('dropped', ui.draggable) and now your accept function can check to see if the element you are attempting to drag in or out is the one that has already been dragged in.

(HTML and css added so the snippet will run)

$(function () {
    $(".draggable").draggable({
        // revert: 'invalid'
    });

    $(".droppable").droppable({
        accept: function (draggable) {
            // new code: new accept clause, accept is not has_lecture OR if the element already dragged onto it is the one you are attempting to drag out
            return (!$(this).hasClass('has_lecture') || $(this).data('dropped') && $(this).data('dropped').is(draggable))
        },
        drop: function (event, ui) {
            var $this = $(this); // << your existing code
            ui.draggable.position({ // << your existing code
                my: "center", // << your existing code
                at: "center", // << your existing code
                of: $this, // << your existing code
                using: function (pos) { // << your existing code
                    $(this).animate(pos, 200, "linear"); // << your existing code
                } // << your existing code
            }); // << your existing code

            $this.addClass('has_lecture'); // << your existing code
            // new code: store a reference to the dropped element on the drop zone
            $this.data('dropped', ui.draggable)

        },
        out: function () {
            $(this).removeClass('has_lecture'); // << your existing code
            // new code: once you have moved it out, then delete the reference to it since your drop zone is now empty again
            $(this).data('dropped', null);
        }
    });
});
    .draggable {
        width: 90px;
        height: 90px;
        padding: 0.5em;
        float: left;
        margin: 10px 10px 10px 0;
        border: 1px solid black;
    }

    .droppable {
        width: 120px;
        height: 120px;
        padding: 0.5em;
        float: left;
        margin: 10px;
        border: 1px solid black;
    }

    h3 {
        clear: left;
    }

    .has_lecture {
        background-color: blue;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

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

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

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

<div class="droppable" class="ui-widget-header">
    <p>Drop here</p>
</div>

Correct answer by chiliNUT on January 21, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP