使用jQuery UI使可拖动元素在可放置元素内排序

10

已解决

我进一步研究了具有connectWith属性的sortable(),发现解决方案比我预期的要简单,但由于draggable()droppable()的原因,我对它的思考方式有些颠倒。

这里是示例:http://jsfiddle.net/DKBU9/12/


以下是原始问题:

这是前面一个SO问题的扩展,我觉得应该保持单独。

原问题在这里:jQuery UI - Clone droppable/sortable list after drop event。它涉及到重新初始化克隆元素上的droppable处理程序。

除此之外,我正在尝试允许从初始列表中拖动的元素在可放置的列表内进行排序。

这里是基本说明当前行为结果的fiddle:http://jsfiddle.net/DKBU9/7/

以及所需的代码,因为SO喜欢抱怨并膨胀这些帖子:

HTML

<ul id="draggables">

    <li>foo1</li>
    <li>foo2</li>
    <li>foo3</li>

</ul>

<ul class="droppable new">

</ul>

JavaScript

$(function() {

    $('#draggables > li').draggable({
        appendTo: 'document',
        revert: 'invalid'
    });

    $('.droppable > li').draggable({
        appendTo: 'document',
        revert: 'invalid'
    });

    $('#draggables').droppable({
        accept: '.droppable > li',
        drop: function(event, ui) {
            ui.draggable.detach().css({top: 0,left: 0}).appendTo($(this));
            cleanUp();
        }
    });

    initDrop($('.droppable'));

});

function initDrop($element) {

    $element.droppable({
        accept: function(event, ui) {
            return true;
        },
        drop: function(event, ui) {
            if($(this).hasClass('new')) {
                var clone = $(this).clone();                
                $(this).after(clone);
                $(this).removeClass('new');
                initDrop( clone );
            }
            ui.draggable.detach().css({top: 0,left: 0}).appendTo($(this));  
            cleanUp();
        }
    }).sortable({
        items: 'li',
        revert: false,
        update: function() {
            cleanUp();   
        }
    });

}

function cleanUp() {

    $('.droppable').not('.new').each(function() {
        if($(this).find('li').length == 0) {
            $(this).remove();
        }
    });

}

参考问题:Jquery UI combine sortable and draggable

我一直在尝试使用这个 Stack Overflow 问题解决我的问题,因为答案中提供的结果正是我想要实现的,特别是接受答案评论中提供的最后一个 fiddle,但我似乎无法弄清楚如何根据我的代码进行调整,考虑到细微区别。例如,那个问题中的 fiddle 克隆可拖动的元素而不是拖动实际元素,并且与我的不同,它不允许将元素拖回到初始列表。

因此,任何帮助尝试为我的代码获得该结果将非常感激。

此外,在那个示例中,accept 属性被设置为返回 true 的函数。这样做的原因是什么?这难道不意味着它会接受任何东西,或者任何可拖动元素吗?

编辑:我读了几个答案,只是使用了具有 connectWith 属性的 sortable(),但由于某种原因,我认为它并没有做我需要的事情,部分原因是我不想初始列表也可以排序。然而,仅使用 sortable() 似乎可以获得我想要的功能,但我还没有适应所有事件处理程序。


我的回答将允许初始列表不按您的编辑进行排序,但如果您可以接受它是可排序的,那么我认为您应该使用您的,因为它更简单。 - acarlon
是的,我非常感谢你的时间和努力,但我会坚持这个选择,因为最初的列表可排序并不是什么大问题。 - Bobe
1个回答

5
请见此示例。该示例可使项目在新列表中具备放置和排序功能,但在初始列表中不行(根据您的编辑而言)。
有一些技巧:
1)从可拖动对象开始,我添加了一个新函数,因为我们需要保留占位符(使用克隆),以便在拖动期间容器不会跳动,并且我们需要将新元素初始化为可拖动对象。
function initDraggable($element)
{
    $($element).draggable({
        connectToSortable: '.droppable',     
        revert: function(droppableObj)
        {
            if(droppableObj === false)
             {                
                $(this).removeClass('dragging');
                return true;
             }
             else
             {              
                return false;
             }
        },
        helper: 'clone',
        start: function(e, ui)
        {           
            $draggingParent = $(this).parent();
           $(this).addClass('dragging');
        }
    });
}

请注意 connectToSortable:.droppable(作为一次清理,我认为您应该将 droppable 更改为 sortable);
还要注意 revert: - 这给了我们一个机会在恢复时删除“dragging”类(这使得原始(克隆)元素不可见)。
最后,有 start,它添加了“dragging”类,使原始(克隆)元素在拖动期间不可见。 它还设置了 $draggingParent,用于检查项目是否正在从 #draggables.droppables 中拖动。
2)然后是 #draggablesdroppable()
 $("#draggables").droppable({    
    drop: function(ev, ui) {
        if($draggingParent[0] === $(ui.helper).parent()[0])
        {
            //dragged from draggables to draggables
            $(ui.draggable).removeClass('dragging');
        }
        else
        {            
            if(ui.draggable.parent())
            var $clone = $(ui.draggable).clone();
            $(ui.draggable).remove();
            $clone.removeClass();
            $clone.removeAttr('style');
            initDraggable($clone);
            $(this).append($clone);        
        }
    }

请注意,drop处理程序检查此元素是否从#draggables.droppables中拖动并相应地采取行动。
3)最后,正如您已经提到的那样,我们真的希望可投放物品可以排序:
function initDroppableSort($element) {       
    $element.sortable({
       items: 'li',
        connectWith: ".droppable,#draggables",
        revert: true,
       stop: function(event, ui) {
           $(ui.item).removeClass('dragging');
            $('.dragging').remove();
            if($(this).hasClass('new')) {
                var clone = $(this).clone();                
                clone.empty();
                $(this).after(clone);
                $(this).removeClass('new');
                initDroppableSort( clone );
            }            
            cleanUp();
        }
    });

}

请注意connectWith,它同时指的是.droppable#draggables

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