ChatGPT解决这个技术问题 Extra ChatGPT

How do I duplicate item when using jquery sortable?

I am using this method http://jqueryui.com/demos/sortable/#connect-lists to connect two lists that i have. I want to be able to drag from list A to list B but when the item is dropped, i need to keep the original one still in list A. I checked the options and events but I believe there is nothing like that. Any approaches?

Good question odle. I had a hard time with the docs on this as well.
Had a hard time finding a solution. Good question.

f
fabpico
$("#sortable1").sortable({
    connectWith: ".connectedSortable",
    forcePlaceholderSize: false,
    helper: function (e, li) {
        copyHelper = li.clone().insertAfter(li);
        return li.clone();
    },
    stop: function () {
        copyHelper && copyHelper.remove();
    }
});
$(".connectedSortable").sortable({
    receive: function (e, ui) {
        copyHelper = null;
    }
});

This approach is preferable to Thorsten's since this one preserves the order of the original list.
Works perfectly! This really should be marked as the correct answer.
Much better answer than the one that is marked correct. This copies and preserves the order.
Thanks for your answer, this is what exactly I'm looking for. And for extra information, removing insertAfter(li) from copyHelper = li.clone().insertAfter(li); will not create a copy in original list. In case you want to duplicate the item to more than one list, but not the original one.
f
fabpico

For a beginning, have a look at this, and read @Erez answer, too.

$(function () {
    $("#sortable1").sortable({
        connectWith: ".connectedSortable",
        remove: function (event, ui) {
            ui.item.clone().appendTo('#sortable2');
            $(this).sortable('cancel');
        }
    }).disableSelection();

    $("#sortable2").sortable({
        connectWith: ".connectedSortable"
    }).disableSelection();
});

The downside of this approach is that the order of $('#sortable2') is not preserved. Ex. if you drop an item into $('#sortable2') at the top of the list, this solution will render the dropped item at the bottom of the list. Erez's answer below does preserve the dropped position and was a better solution in my use case.
S
Sean Anderson

Erez' solution works for me, but I found its lack of encapsulation frustrating. I'd propose using the following solution to avoid global variable usage:

$("#sortable1").sortable({
    connectWith: ".connectedSortable",

    helper: function (e, li) {
        this.copyHelper = li.clone().insertAfter(li);

        $(this).data('copied', false);

        return li.clone();
    },
    stop: function () {

        var copied = $(this).data('copied');

        if (!copied) {
            this.copyHelper.remove();
        }

        this.copyHelper = null;
    }
});

$("#sortable2").sortable({
    receive: function (e, ui) {
        ui.sender.data('copied', true);
    }
});

Here's a jsFiddle: http://jsfiddle.net/v265q/190/


Using a hidden placeholder in the first list will give it the common dragged from the exact position effect like so jsfiddle.net/BrianDillingham/v265q/320
m
mplungjan

I know this is old, but I could not get Erez's answer to work, and Thorsten's didn't cut it for the project I need it for. This seems to work exactly how I need:

$("#sortable2, #sortable1").sortable({
    connectWith: ".connectedSortable",
    remove: function (e, li) {
        copyHelper = li.item.clone().insertAfter(li.item);
        $(this).sortable('cancel');
        return li.item.clone();
    }
}).disableSelection();

yes this solution is better because it uses li.item so it can be used with multiple elements. Thank you it helped me.
Actually return li.item.clone(); is not even needed in my case
Are you around and can you tell me how to clone multiple items jsfiddle.net/mplungjan/8sfx1z9b
f
fabpico

The answer of abuser2582707 works best for me. Except one error: You need to change the return to

return li.item.clone();

So it should be:

$("#sortable2, #sortable1").sortable({
    connectWith: ".connectedSortable",
    remove: function (e, li) {
        li.item.clone().insertAfter(li.item);
        $(this).sortable('cancel');
        return li.item.clone();
    }
}).disableSelection();

f
fabpico

When using Erez's solution but for connecting 2 sortable portlets (basis was the portlet example code from http://jqueryui.com/sortable/#portlets), the toggle on the clone would not work. I added the following line before 'return li.clone();' to make it work.

copyHelper.click(function () {
    var icon = $(this);
    icon.toggleClass("ui-icon-minusthick ui-icon-plusthick");
    icon.closest(".portlet").find(".portlet-content").toggle();
});

This took me a while to figure out so I hope it helps someone.