Jquery可排序和克隆

4

场景:拖动一个或多个元素并将它们放置在另一个列表中,但不要从源列表中删除拖动的元素。

为了允许多次拖动,我使用了Aaron Blenkush这里发布的代码。

演示

我已经进行了一些更改以适应我的需求,例如修复了Shift键问题。

  $("ul").on('click', 'li', function (e) {
      if (e.ctrlKey || e.metaKey) { //meta key for mac users
          $(this).toggleClass("ui-selected");
          $(this).parent().parent().siblings().children('ul').children().removeClass('ui-selected');
    }
    else if (e.shiftKey) {
        // $(this).toggleClass("selected");               
        var list = $(this).parent();
        var first = list.find('.ui-selected').first().index();
        // var last = list.find('.selected').last().index();
        var last = $(this).index();

        if (first == -1 || last == -1) {
            return false;
        }

        if (last < first) {
            firstHolder = first;
            first = last;
            last = firstHolder;
        }

        for (i = first; i <= last ; i++) {
            list.children().eq(i).addClass("ui-selected");
        }
    }
    else {                
        $(this).addClass("ui-selected").siblings().removeClass('ui-selected'); //select only clicked element and unselecting other elements

        //to Remove selected Class from 2nd UL li
        $(this).parent().parent().siblings().children('ul').children().removeClass('ui-selected');
    }
})
   .sortable({
       connectWith: "ul",
       delay: 150, //Needed to prevent accidental drag when trying to select
       revert: 0,
       cursor: "move",
       disabled: false,
       placeholder: 'placeholder',
       //  handle: ".handle",
       helper: function (e, item) {
           //Basically, if you grab an unhighlighted item to drag, it will deselect (unhighlight) everything else
           if (!item.hasClass('ui-selected')) {
               item.addClass('ui-selected').siblings().removeClass('ui-selected');
           }

           //////////////////////////////////////////////////////////////////////
           //HERE'S HOW TO PASS THE SELECTED ITEMS TO THE `stop()` FUNCTION:

           //Clone the selected items into an array
           var elements = item.parent().children('.ui-selected').clone();

           //Add a property to `item` called 'multidrag` that contains the selected items, then remove the selected items from the source list
           item.data('multidrag', elements)
               //.siblings('.ui-selected').remove();

           //Now the selected items exist in memory, attached to the `item`, so we can access them later when we get to the `stop()` callback

           //Create the helper
           var helper = $('<li/>');
           return helper.append(elements);
       },
       start: function(event, ui) {
           //$(ui.item).show();
           var elements = ui.item.data('multidrag');
           ui.item.after(elements);
           //clone = $(ui.item).clone();
           //before = $(ui.item).prev();
       },
       stop: function (e, ui) {
           //Now we access those items that we stored in `item`s data!
           var elements = ui.item.data('multidrag');

           //`elements` now contains the originally selected items from the source list (the dragged items)!!

           //Finally I insert the selected items after the `item`, then remove the `item`, since item is a duplicate of one of the selected items.
           ui.item.after(elements).remove();
         //  $(ui.item).show();
           //$(this).sortable('cancel');
       }
   });
问题: 它从源列表中删除了被拖动的元素。
我对此问题进行了一些研究。有些人建议在helper方法中使用克隆,但当我传递给返回多个元素的函数时,我不能使用克隆。在Firebug中,当我拖动元素时,它会在它们上面放置style=display:none,但当我将元素放下时,它会从源列表中删除它们。 更新 我对答案进行了一些修改,使其更简单。 更新后的答案 存在一些问题,例如当从第一个列表中删除li并移到第二个列表时,如果将该li再次从第二个列表拖回第一个列表,则会删除元素。 解决方案是当项目被拖放到第二个列表中时,删除ui-selected类。
希望能对某些人有所帮助 :)
1个回答

2

我花了一些时间研究它,以下是我在那段时间内能想到的最好的解决方案。

var selected;
var selectedCurrent;
var temp;
var received = false;
$("ul").on('mousedown', 'li', function (e) {
if($(this).next('li').hasClass('pholder'))
        $(this).next('li').remove();
if ((e.ctrlKey || e.metaKey) && selected != undefined) {
    if($(this).text() != selectedCurrent.text()) 
         selectedCurrent.after(selected.clone().addClass('pholder temp').hide());
}
selectedCurrent = $(this);
selected = $(this).clone().removeClass('selected');
});
$("ul").on('click', 'li', function (e) {
if(temp != undefined)
    $('.temp').remove();        
if (e.ctrlKey || e.metaKey) {
    if($(this).next('li').hasClass('pholder'))
        $(this).next('li').remove();
    else
        $(this).after($(this).clone().addClass('pholder').hide());
    $(this).toggleClass("selected");
} else {
    $(this).addClass("selected").siblings().removeClass('selected');
    $('.pholder').remove();
}
}).sortable({
connectWith: "ul",
delay: 150,
revert: 0,
helper: function (e, item) {
    if (!item.hasClass('selected')) {
        item.addClass('selected').siblings().removeClass('selected');
    }
    var elements = item.parent().children('.selected').clone();
    item.data('multidrag', elements).siblings('.selected').remove();
    var helper = $('<li/>');
    return helper.append(elements);
},
stop: function (e, ui) {
    if(!received){
        selected.remove();
        $('.pholder').remove(); 
    }
    else{
        received = false;
        $('.pholder').removeClass('pholder');
    }
    var elements = ui.item.data('multidrag');
    ui.item.after(elements).remove();
    $('.selected').removeClass('selected');
},
start: function(event, ui){
    ui.item.after(selected);
    $('.pholder').show();
},
receive: function(event, ui){
        received = true;
}
});

Fiddle(JSFiddle)

http://jsfiddle.net/hQnWG/749/

更新

http://jsfiddle.net/hQnWG/752/

更新2 - 清除列表中的重复项。

http://jsfiddle.net/hQnWG/754/


有一个问题。如果您使用Ctrl选择所有三个li,它会在第一个和第二个之间复制li,从而增加li的计数。 - Salman
@user751959 是的,我担心可能会有一些错误。不过我会研究一下的。 - Trevor
@user751959 我想到了一个更健壮的更新。http://jsfiddle.net/hQnWG/752/ 现在唯一能找到的问题是,比如说如果列表中有多个One或多个任何数字,并且你将它们都移动到另一个列表中,那么原始列表中只会保留一个One而不是两个...我不知道为什么你想在列表中有多个相同的东西,所以我会再想一个fiddle,在列表中有重复项时它会将它们删除。 - Trevor
@user751959 最后一次更新,消除重复项... http://jsfiddle.net/hQnWG/754/ - Trevor
我已经尝试了您的代码。它太复杂了,所以我想出了一个更简单的解决方案。[http://jsfiddle.net/abUF2/1/] - Salman

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