JQuery UI: Cancel Sortable upon Droppable Drop
Asked Answered
D

1

12

I am using JQuery 1.5.1 and JQuery UI 1.8.11.

I have added sortable for a number of items - the task here is to allow drag to sort, this all works fine.

But I also want to incorporate droppable, so that the item can be dropped onto a "copy me" area - the task there will be to duplicate the item (I will work that bit out later)

Problem is the droppable target is at the bottom of the sortable list (I do not want to move this) and once the drop occurs the sortable item moves to the bottom of the list.

What I want to do is cancel this sort when the drop event fires.

You can see my problem in action here (just drag "Item 1" onto the "Drop to Copy Item" area and you will see the sort does not get cancelled)

As you can see I have tried the following in the droppable "drop" event (suggested from JQuery UI Docs) but it does not seem to work...

$(this).sortable('cancel');

I am also open to any other recommendations on how to achieve this "drop to copy" effect I am looking for.

Thanks

Derron answered 20/10, 2011 at 9:57 Comment(5)
What do you mean by cancel? Cancel will stop the sortable and leave what you were sorting at the exact place you left it.Cleocleobulus
@jQuerybeast: Yes that is what I want, the "cancel" will return the item to the original space. So in my JSFiddle, if you try to copy item 1, the copy will happen and item1 should revert back to the top... at the moment it moves to the bottom as that was last highlight position before the drop eventDerron
Cancel doesn't work with sortable but with draggable. In sortable you can cancel/stop the entire function.Cleocleobulus
@jQuerybeast: Yep, I got that far by trying the cancel on the original container DIV. This got the effect of reverting the item but it stopped the sorting working. So I thought maybe I could cancel and then re-add the sortable function - but this doesn't seem to work either (it does not re-add). Any ideas?Derron
@jQuerybeast: I have manage to find a get around to my problem and have posted my own answer. Just in case you are interest to see how I did it ;)Derron
D
4

OK, so I have worked out a solution which does the job.

the cancel code does work if you have it in the "stop" event of the sortable function. However, it will only apply once the "revert" has completed. The problem is that I was trying to copy/revert the element from the droppable "drop" event and this was too early.

The solution is to wait for the "stop" event to complete, and to achieve this I had to create a "awaiting copy" flag, to be checked in the "stop" event.

Here is an example

It still doesn't feel right (UX-wise) but it works correct, and you could always set revert to false on the sortable function to get a slightly better feel.

The code from the example is as follows...

var itemCount = 3;
var awaitingCopy = false;

$(init);

function init() {
    $("#Items").sortable({
        revert: true,
        placeholder: "ItemPlaceHolder",
        opacity: 0.6,
        start: StartDrag,
        stop: StopDrag
    });

    $("#CopyItem").droppable({
        hoverClass: "CopyItemActive",
        drop: function(event, ui) {
            awaitingCopy = true;
        }
    });

    $("#NewItem").click(function(e) {
        e.preventDefault();
        itemCount++;
        var element = $("<div class='Item'>Item " + itemCount + "</div>");
        $("#Items").append(element);
        element.hide().slideDown(500);
    });
}

function CopyItem(element) {
    awaitingCopy = false;
    var clone = element.clone();
    $("#Items").append(clone);
    clone.hide().slideDown(500);
}

function StartDrag() {
    $("#NewItem").hide();
    $("#CopyItem").show();
}

function StopDrag(event, ui) {
    if (awaitingCopy) {
        $(this).sortable('cancel');
        CopyItem($(ui.item));
    }
    $("#NewItem").show();
    $("#CopyItem").hide();
}

Anyway, hopefully this will help others who want the same kind of effect... no stealing my design though ;)

Derron answered 20/10, 2011 at 13:19 Comment(1)
This helped me find the solution, but I'd just like to point out that the global variable was unnecessary - it looks like you were not using the correct jQuery selector. Instead of $(this).sortable('cancel');, it should have been $("#Items").sortable('cancel');Marshmallow

© 2022 - 2024 — McMap. All rights reserved.