使用jQuery UI使可拖放元素在droppable内可排序 [英] Make draggable element sortable within droppable using jQuery UI

查看:79
本文介绍了使用jQuery UI使可拖放元素在droppable内可排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已解决

因此,我对带有connectWith属性的sortable()进行了更多的研究,发现解决方案比我预期的要简单,但是由于draggable()droppable()的缘故,我一直在思考它. >

这是小提琴: http://jsfiddle.net/DKBU9/12/


原始问题如下:

这是对上一个SO问题的扩展,我认为应该将其分开.

原始问题在这里: http://jsfiddle .net/DKBU9/7/

以及所需的代码,因为SO喜欢抱怨和at肿这些帖子:

HTML

<ul id="draggables">

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

</ul>

<ul class="droppable new">

</ul>

JS

$(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

我一直在尝试使用此问题来解决我的问题,因为结果恰好是我要实现的目标,特别是接受的答案的注释中提供的最后一个小提琴,但我似乎无法考虑到细微的差异,找出如何使其适应我的代码.例如,该问题中的小提琴是克隆可拖动对象而不是拖动实际元素,并且与我的方法不同,它不允许将元素拖回到初始列表中.

因此,非常感谢您尝试为我的代码获得该结果的帮助.

此外,在该示例中,将accept属性设置为返回true的函数.这是什么原因呢?难道不就意味着它将接受任何东西或任何可拖动元素?

我读了几个答案,这些答案仅将sortable()与connectWith属性一起使用,但是由于某些原因,我不认为它满足了我的需要,部分原因是我不希望初始列表可排序也一样但是,单独使用sortable()似乎可以得到我想要的功能,但是我还没有适应所有的事件处理程序.

解决方案

请参见 此小提琴 .

这将使这些项目在新列表中可投放和排序,但在初始列表中则不行(根据您的编辑).

有一些技巧:

1)从可拖动对象开始,我添加了一个新函数,因为我们需要保留一个占位符(使用克隆),以便容器在拖动过程中不会跳动,并且需要将新元素初始化为可拖动对象. /p>

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:-这使我们有机会在还原时删除拖动"类(使原始(克隆的)元素不可见).

最后,有一个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)最后,正如您已经提到的,我们真的希望droppable是可排序的:

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.

RESOLVED

So I studied sortable() with the connectWith attribute a bit more and found the solution was simpler than I expected, but I was thinking about it sort of backwards because of draggable() and droppable().

Here's the fiddle: http://jsfiddle.net/DKBU9/12/


Original question follows:

This is an extension of a previous SO question that I felt should be kept separate.

The original question is here: jQuery UI - Clone droppable/sortable list after drop event. It regards reinitializing the droppable handler on cloned elements.

On top of that though, I'm trying to allow the elements that have been dragged from the initial list to be sorted within the droppable lists.

Here is a fiddle essentially illustrating the current behaviour as a result of the original question: http://jsfiddle.net/DKBU9/7/

And the required code because SO likes to complain and bloat these posts:

HTML

<ul id="draggables">

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

</ul>

<ul class="droppable new">

</ul>

JS

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

}

Reference question: Jquery UI combine sortable and draggable

I've been trying to use this SO question to resolve my issue as the result is exactly what I'm trying to achieve, specifically the last fiddle provided in the comments of the accepted answer, but I can't seem to figure out how to adapt it to my code considering the minor differences. For example, the fiddle in that question clones the draggable rather than dragging the actual element and unlike mine doesn't allow elements to be dragged back into the initial list.

So any help to try to get that result for my code would be greatly appreciated.

Also, in that example, the accept attribute is set as a function to return true. What is the reason for this? Doesn't that just mean it will accept anything, or any draggable element?

EDIT: I read a couple answers that just used sortable() with the connectWith attribute, but for some reason I didn't think it did what I needed to, partly because I didn't want the initial list to be sortable as well. However, using sortable() alone seems to get the functionality I'm after but I just haven't yet adapted all the event handlers.

解决方案

See this fiddle.

It will make the items droppable and sortable in the new lists, but not in the initial (as per your edit).

There are a few tricks:

1) Starting with the draggable, I added a new function because we need to leave a placeholder (use a clone) so that the containers don't jump about during drag and we need to initialise the new element as draggable.

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');
        }
    });
}

Note the connectToSortable: with .droppable (As a cleanup, I think you should change droppable to sortable);

Note also revert: - this gives us an opportunity to remove the 'dragging' class (which makes the original (cloned) element invisible) on revert.

Finally, there is start which adds the 'dragging' class which makes the original (cloned) element invisible during drag. It also sets the $draggingParent which is used to check whether the item is being dragged from #draggables or .droppables.

2) Then there is the droppable() for the #draggables:

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

Note that the drop handler checks whether this element is dropped from #draggables or .droppables and acts accordingly.

3) Finally, as you already mentioned, we really want the droppable to be sortable:

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

}

Note the connectWith and specifically that it refers to both .droppable and #draggables.

这篇关于使用jQuery UI使可拖放元素在droppable内可排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆