jQuery可排序和可拖放功能

28

我想要一个可排序的列表,但我也希望该列表中的元素可以被拖放到我定义为可拖放的 div 中。我找不到实现的方法。你有什么建议吗?


我在这里提出了一个功能请求:http://bugs.jqueryui.com/ticket/10628 - T J
6个回答

22

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

最大的区别在于此解决方案不会存储可排序元素的整个 HTML,而只会存储当前拖动的项目。如果将该项目放在可拖动区域上,则将其插入到原来的位置。

无论如何,以下是代码:

<!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>

如果一个项目被拖动到列表中的新位置,然后被放置在<ul>和可放置的<div>之外,它仍然会遇到与Colin的解决方案相同的问题。该项目将不会重置而是占据列表中的最后一个位置(在Google Chrome中测试)。无论如何,这可以通过一些鼠标悬停检测轻松解决,甚至可能是期望的行为。


1
我在我的项目中使用了这个变体。谢谢 +1 - Adam Tomat
从上面的代码 http://codepen.io/tcosentino/pen/myVEEJ <- 不确定为什么会以“VEEJ”结束 - Troy Cosentino
真的需要保存状态并依赖其正确性吗?似乎可以使用鼠标事件位置/偏移值来处理。 - Roman Pokrovskij

4
据我所知,我之前发布的代码存在问题是因为 draggable 组件的 drop 函数在 sortable 组件的 mouseup 事件之前被调用,而由于重写了列表,sortable 组件变得不稳定。这只是我的猜测。
看最终代码:
<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应用之后才被调用,结果导致列表元素放置在了不合理的位置。因此,我需要在LIs上使用mousedown函数。

setSortable在一个函数中是因为停止事件会重写sortable,这可能是“递归”的,我猜的。不确定这里的确切术语,但我们可以称之为令人困惑的烦人事情。

幸运的是,droppable的drop函数在sortables的stop函数之前被调用,所以我能够设置一个全局的“dropped”变量,用于检查元素是否被放置。

我仍然惊讶于这不是更容易做到的事情,我认为jQuery会有更好的处理方法。也许我漏掉了什么?


请查看我略微简化的版本。 - Reimund

1

不完全符合您的要求,但我需要一个初始容器来将项目拖动到另一个可排序的容器中 - 所以我想分享一下。这是我如何实现它的(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/

JSFiddle是一个在线的前端代码编辑器和调试工具,可以帮助开发人员快速测试和分享他们的代码。这个链接指向一个示例代码,展示了如何使用JavaScript和HTML来创建一个简单的网页。


0

我已经花了整整一天的时间在这个问题上,虽然我离解决它更近了,但仍然不如我想象的那样好。现在我有了所需的功能,但是出现了一个Javascript错误。

问题是使可排序列表回到先前的位置,如果元素被放置在可放置区域而不是列表中。目前,我在mousedown事件时保存HTML代码,然后在可放置区域的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>

0

通过将每个目标 DIV 设为自己的可排序元素,我成功地获得了类似的最终结果。

然后,通过 connectWith,我使所有可排序元素能够连接并共享可拖动元素。

类似于以下内容:

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

0

如果您希望其他可拖放区域也可以进行排序,您可以使用connectWith选项和一个公共选择器:

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

这个解决方案对我来说非常有效。


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