jQuery 可排序和可放置

Posted

技术标签:

【中文标题】jQuery 可排序和可放置【英文标题】:jQuery Sortable and Droppable 【发布时间】:2011-01-06 14:27:05 【问题描述】:

我想要一个可排序的列表,但我也希望该列表中的元素可放置到我定义为可放置的 div 中。我似乎找不到办法做到这一点。有什么想法吗?

【问题讨论】:

我提出了一个feature request here 【参考方案1】:

这是 Colin 解决方案的简化版本。

最大的不同是这个方案没有存储可排序元素的整个html,而只存储当前拖动的item。如果项目被放置在可放置区域,它会被插入到它的原始位置。

不管怎样,代码如下:

<!doctype html>
<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.js"></script>

<script type="text/javascript">
$(document).ready(function() 
    var dropped = false;
    var draggable_sibling;

    $("#sortable").sortable(
        start: function(event, ui) 
            draggable_sibling = $(ui.item).prev();
        ,
        stop: function(event, ui) 
            if (dropped) 
                if (draggable_sibling.length == 0)
                    $('#sortable').prepend(ui.item);

                draggable_sibling.after(ui.item);
                dropped = false;
            
        
    );

    $(".droppable").droppable(
        activeClass: 'active',
        hoverClass:'hovered',
        drop:function(event,ui)
            dropped = true;
            $(event.target).addClass('dropped');
        
    );
);

</script>

<style type="text/css">
#sortable li
    clear:both;
    float:left;


.droppable 
    clear:both;
    height:300px;
    width:400px;
    background-color:#CCC;


.droppable.active  background: #CFC; 
.droppable.hovered  background: #CCF; 
.dropped  background: #f52; 
</style>

</head>
<body>

<ul id="sortable">
    <li id="one">One</li>
    <li id="two">Two</li>
    <li id="three">Three</li>
    <li id="four">Four</li>
    <li id="five">Five</li>
    <li id="six">Six</li>
</ul>

<div class="droppable">Drop Here</div>
<div class="droppable">Drop Here</div>

</body>
</html>

如果一个项目被拖到列表中的一个新位置,然后放在&lt;ul&gt; 和可放置的&lt;div&gt; 之外,它仍然会遇到与 Colin 解决方案相同的问题。然后该项目将不会重置,但会占据列表中的最后一个位置(在 Google Chrome 中测试)。无论如何,这很容易通过一些鼠标悬停检测来解决,甚至可能是理想的行为。

【讨论】:

在我的项目中使用了这个的变体。谢谢+1 上面的代码codepen.io/tcosentino/pen/myVEEJ 真的需要保存一个状态并依赖于它的正确性吗?似乎可以使用 drop 的鼠标事件位置/偏移值。【参考方案2】:

据我所知,我发布的上一个代码的问题是,在可排序对象的 mouseup 之前调用了可放置对象的放置函数,并且由于我重写了列表,因此可排序对象变得很生气(因为缺少更好的条款)。这有点猜测。

看最终代码:

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>
    <script type="text/javascript">

var dropped = false;
var templateHtml;
$(document).ready(function()

    setSortable();

    $("#droppable").droppable(
        activeClass: 'active',
        hoverClass:'hovered',
        accept:".drop",
        drop:function(event,ui)
            dropped = true;
            //alert(ui.draggable.text());
        
    );

);

function setSortable()
    $("#sortable").sortable(
        stop:function(event,ui)
            if(dropped)
                $("#sortable").sortable('destroy').html(templateHtml);
                dropped = false;
                setSortable();
            
        
    );

    $("#sortable li").addClass("drop").bind('mousedown',function()
        templateHtml = $("#sortable").html();
    );


    </script>
    <style type="text/css">
    #sortable li
        clear:both;
        float:left;
    

    #droppable 
        clear:both;
        height:300px;
        width:400px;
        background-color:#CCC;
    
    #droppable.active 
        background-color:#CFC;
    
    #droppable.hovered 
        background-color:#CCF;
    
    </style>

</head>
<body>

<ul id="sortable">
<li id="one">One</li>
<li id="two">Two</li>
<li id="three">Three</li>
<li id="four">Four</li>
<li id="five">Five</li>
<li id="six">Six</li>
</ul>

<div id="droppable">
Drop Here
</div>

</body>

这里有很多怪癖。

我试图在 sortable 的开始事件中保存#sortable html,但是在应用了所有 ui-css 之后调用了该 get,并最终将列表元素放置在疯狂的地方。所以,我需要在 LI 上使用 mousedown 功能。

setSortable 在一个函数中,因为停止事件重写了可排序的,我猜这是“递归的”。不确定这里的确切术语,但我们可以使用令人讨厌的混淆。

幸运的是,droppable 的 drop 函数在 sortables 停止函数之前被调用,因此我能够设置一个全局“dropped”变量,用于查看元素是否被删除。

我仍然对这并不容易做到感到惊讶,我认为 jQuery 将具有更好地处理它的函数。也许我错过了什么?

【讨论】:

请看我的简化版。【参考方案3】:

不完全符合您的要求,但我需要一个初始容器,可以将项目拖到另一个可排序的容器中 - 我认为我应该分享它。这就是我实现它的方式(jQuery 1.8.3):

$("#sortable-list").sortable();
$("#initial-list div").draggable(
  revert: true,
  revertDuration: 0
);

$("#initial-list").droppable(
  accept: ".item-selected",
  drop: function(e, ui) 
    var dropped = ui.draggable;
    var droppedOn = $(this);
    var itemInOtherList = $(this).children("#" + dropped.attr('id'));
    itemInOtherList.removeClass('ui-state-disabled').draggable( disabled: false );
    dropped.remove();
  
);
$("#sortable-list").droppable(
  accept: ".item-initial",
  drop: function(e, ui) 
    var dropped = ui.draggable;
    var droppedOn = $(this);
    droppedOn.append(dropped.clone()
      .removeAttr('style')
      .removeClass("item-initial")
      .addClass("item-selected"));
    dropped.animate(dropped.data().origPosition, 
      complete: function() 
        $(this).addClass('ui-state-disabled').draggable( disabled: true );
      
    );
  
);

JSFiddle:http://jsfiddle.net/Muskar/dwz4mvxa/8/

【讨论】:

【参考方案4】:

我花了一整天的时间在这上面,我已经接近了很多,但仍然没有达到我想要的效果。我现在有了我需要的功能,但是抛出了一个 Javascript 错误。

如果元素被放置在可放置对象中,而不是列表中,则问题是让可排序列表返回到其先前的位置。目前,我正在保存 html onmousedown,然后在 droppable 的 drop 函数中重写 html。这可行,但它给我一个 jquery 变量是空错误。谁能找到更好的解决方案?

代码:

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script>
    <script type="text/javascript">

var templateHtml;
$(document).ready(function()

    $("#sortable").sortable();
    $("#sortable li").addClass("drop").bind('mousedown',function()
        templateHtml = $("#sortable").html();
    );
    $("#droppable").droppable(
        activeClass: 'active',
        hoverClass:'hovered',
        accept:".drop",
        drop:function(event,ui)
            $("#sortable").sortable('destroy').html(templateHtml);
            $("#sortable").sortable();
            $("#sortable li").addClass("drop").bind('mousedown',function()
                templateHtml = $("#sortable").html();
            );          
        
    );

);

    </script>
    <style type="text/css">
    #sortable li
        clear:both;
        float:left;
    

    #droppable 
        clear:both;
        height:300px;
        width:400px;
        background-color:#CCC;
    
    #droppable.active 
        background-color:#CFC;
    
    #droppable.hovered 
        background-color:#CCF;
    
    </style>

</head>
<body>

<ul id="sortable">
<li id="one">One</li>
<li id="two">Two</li>
<li id="three">Three</li>
<li id="four">Four</li>
<li id="five">Five</li>
<li id="six">Six</li>
</ul>

<div id="droppable">
Drop Here
</div>

</body>

【讨论】:

【参考方案5】:

通过使每个目标 DIV 成为自己的可排序对象,能够获得类似的最终结果。

然后,我通过 connectWith 使所有可排序对象都能够连接和共享可拖动对象。

类似:

var connects = '#main_sortable, div.target';
$('#main_sortable').sortable( connectWith: connect );
$('div').sortable( connectWith: connect );

【讨论】:

【参考方案6】:

如果您可以允许其他可放置区域也可以排序,则可以将connectWith option 与通用选择器一起使用:

<div id="droppable1" class="droppable-area"></div>
<div id="droppable2" class="droppable-area"></div>
<div id="droppable3" class="droppable-area"></div>

您的 jQuery 代码将是:

$('.droppable-area').sortable( connectWith: '.droppable-area' );

无论如何,这个解决方案对我来说效果很好。

【讨论】:

以上是关于jQuery 可排序和可放置的主要内容,如果未能解决你的问题,请参考以下文章

Jquery 可拖动/可放置和可排序组合

可拖动和可排序的 Portlet // jQuery

可排序、可拖放和可拖动的容器

jQueryUI 可排序和可拖动目标不会水平滚动以进行放置,但会进行排序

Jquery UI 结合了可排序和可拖动

jQuery UI 可排序和可选