当使用jQuery sortable时,如何复制项目?

61

我正在使用这种方法http://jqueryui.com/demos/sortable/#connect-lists将两个列表连接在一起。我希望能够从列表 A 拖动到列表 B,但是当项目被放下时,我需要保留原始项目仍然在列表 A 中。我查看了选项和事件,但我认为没有类似的功能。有什么解决方法吗?


好问题,odle。我也在文档上遇到了困难。 - Adam Fraser
找解决方案花了很长时间。好问题。 - Birju Shah
6个回答

90
$("#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;
    }
});

4
相较于Thorsten的方法,这种方法更好,因为它保留了原始列表的顺序。 - Adam Fraser
3
非常完美!这真的应该标记为正确答案。 - ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
比标记为正确的答案好得多。这个复制并保留了顺序。 - Joel Kinzel
谢谢你的回答,这正是我所寻找的。另外需要说明的是,从copyHelper = li.clone().insertAfter(li);中删除insertAfter(li)将不会在原始列表中创建副本。如果您想将该项复制到多个列表中,但不包括原始列表,则可以这样做。 - Huy Phạm

29

作为入门,先看一下这个,并且也要阅读@Erez的答案。

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

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

8
这种方法的缺点是无法保留$('#sortable2')的顺序。例如,如果您将一个项目放在列表顶部的$('#sortable2')中,则该解决方案会将放置的项目呈现在列表底部。下面是Erez的答案,可以保留放置的位置,在我的使用情况中更加优秀。 - Andrew Sauder

29

Erez的解决方案对我有效,但我发现它缺乏封装性是令人沮丧的。我建议使用以下解决方案来避免使用全局变量:

$("#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);
    }
});

这里有一个 jsFiddle: http://jsfiddle.net/v265q/190/


7
在第一个列表中使用隐藏的占位符,将使其具有常见的从精确位置拖动的效果,如下所示:http://jsfiddle.net/BrianDillingham/v265q/320/ - im_brian_d

9

我知道这是老的内容,但是我无法让Erez的答案生效,而Thorsten的答案对我需要的项目来说不够。以下方法似乎完全符合我的需求:

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

是的,这个解决方案更好,因为它使用了 li.item,所以可以用于多个元素。谢谢,它帮助了我。 - themhz
实际上,在我的情况下,return li.item.clone(); 甚至都不需要。 - mplungjan
你在吗?能告诉我如何克隆多个项目吗?https://jsfiddle.net/mplungjan/8sfx1z9b/ - mplungjan

7
对我来说,abuser2582707的答案最好。 除了一个错误:你需要将return更改为


return li.item.clone();

所以应该是这样的:
$("#sortable2, #sortable1").sortable({
    connectWith: ".connectedSortable",
    remove: function (e, li) {
        li.item.clone().insertAfter(li.item);
        $(this).sortable('cancel');
        return li.item.clone();
    }
}).disableSelection();

0
当使用Erez的解决方案连接2个可排序的Portlets(基础是从http://jqueryui.com/sortable/#portlets中获取的Portlet示例代码)时,克隆上的切换不起作用。我在“return li.clone();”之前添加了以下行以使其正常工作。
copyHelper.click(function () {
    var icon = $(this);
    icon.toggleClass("ui-icon-minusthick ui-icon-plusthick");
    icon.closest(".portlet").find(".portlet-content").toggle();
});

我花了一段时间才弄明白,希望能帮到别人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接