jQuery 可排序和可丢弃

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2090121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 12:45:05  来源:igfitidea点击:

jQuery Sortable and Droppable

jqueryjquery-ui-sortablejquery-ui-draggablejquery-ui-droppable

提问by Colin

I want to have a list that is sortable, but I also want the elements in that list to be droppable to the divs I have defined as droppable. I can't seem to find a way to do it. Any ideas?

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

采纳答案by Reimund

Here's a simplified version of Colin's solution.

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

The biggest difference is that this solution does not store the entire html of the sortable elements, but only the currently dragged item. It is then inserted into it's original position if the item is dropped on the droppable area.

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

Anyway, here's the code:

无论如何,这是代码:

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

It still suffers the same problem as Colin's solution if an item is dragged into a new position in the list and then dropped outside both the <ul>and the droppable <div>. The item will then not reset but take the last position in the list (tested in Google Chrome). Anyway, this is easily solved with some mouse over detection or it may even be desirable behaviour.

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

回答by Colin

As far as I could tell, the issue with the previous code I posted is that the drop function of the droppable was getting called before the mouseup of the sortable, and since I rewrote the list the sortable was getting angry (for lack of better terms). That's somewhat a guess.

据我所知,我发布的先前代码的问题是 droppable 的 drop 函数在可排序的鼠标向上之前被调用,并且由于我重写了列表,可排序变得生气(因为缺乏更好的术语)。这有点猜测。

Looking at the final code:

查看最终代码:

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

Tons of quirks are involved here.

这里涉及大量的怪癖。

I tried to save the #sortable html on the start event of sortable, but that get's called after all of the ui-css gets applied, and ended up placing list elements in crazy places. So, I needed to use the mousedown function on the LIs.

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

The setSortable is in a function because the stop event rewrites the sortable, which is "recursive" I guess. Not sure the exact terminology here, but we can go with annoyingly confusing.

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

Fortunately, the droppable's drop function gets called before the sortables stop function, so I was able to set a global "dropped" variable that was used to see if the element was dropped.

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

I'm still surprised this wasn't easier to do, I thought jQuery would have functions to handle it a lot better. Perhaps I'm missing something?

我仍然很惊讶这并不容易,我认为 jQuery 会有更好的功能来处理它。也许我错过了什么?

回答by Aske B.

Not exactly what you asked for, but I needed an initial container where the items could be dragged to another sortable container - and thought I should share it. This was how I achieved it (jQuery 1.8.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/

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

回答by mikeycgto

Was able to get a similar end result by making the each of the target DIVs their own sortables.

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

I then, via connectWith, made all of the sortables able to connect and share draggables.

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

Something like:

就像是:

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

回答by Steven Hunt

If you can allow your other droppable areas to be sortable as well, you can use the connectWith optionwith a common selector:

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

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

your jQuery code would then be:

您的 jQuery 代码将是:

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

This solution worked beautifully for me anyways.

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

回答by Colin

I've spent all day on this, and I've gotten a lot closer, but still not doing as well as I'd like. I now have the functionality I need, but a Javascript error is getting thrown.

我已经花了一整天的时间,我已经接近了很多,但仍然没有像我想要的那样好。我现在有了我需要的功能,但是抛出了 Javascript 错误。

The issue is getting the sortable list to return to its previous position if the element is dropped in the droppable, rather than in the list. Currently, I'm saving the html onmousedown, then rewriting the html in the drop function of the droppable. This works, but its giving me a jquery variable is null error. Can anyone find a better solution?

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

Code:

代码:

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