jQuery Sortable - 选择并拖动多个列表项

dan*_*nts 57 jquery jquery-ui

我有一个设计,我有一个"可用的盒子"列表,用户通过将它们从"可用的盒子"列表拖到他们的"我的盒子"列表来获取盒子.

用户通常一次多取多个盒子(最多20个),一旦他们完成盒子,他们将它们拖回"可用盒子"列表以返回它们.

jQuery sortable允许我一次拖动一个框,从用户的角度来看是不合需要的.我一直无法想出这个问题的简单解决方案.

我可能必须完全提出一种不同的UI方法,但首先是否有人对如何实现这一点有任何建议?

谢谢!

Aar*_*ush 74

工作方案

tl; dr:请参阅这个小提琴,找到合适的答案.


我到处寻找解决将多个选定项目从可排序拖动到连接可排序的问题的解决方案,这些答案是我能找到的最好的.

然而...

接受的答案是错误的,@ Shanimal的答案很接近,但还不完全.我拿了@Shanimal的代码并在它上面构建.

我解决了:

我补充说:

  • 正确Ctrl + click(或Cmd + click在Mac上)支持选择多个项目.点击没有Ctrl按住键将使该项目选中,并在同一列表中的其他项目将被取消.这与jQuery UI Selectable()小部件的点击行为相同,区别在于Selectable()mousedrag上有一个选取框.

小提琴

HTML:

<ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
</ul>
<ul>
    <li>Four</li>
    <li>Five</li>
    <li>Six</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

JavaScript(使用jQuery和jQuery UI):

$("ul").on('click', 'li', function (e) {
    if (e.ctrlKey || e.metaKey) {
        $(this).toggleClass("selected");
    } else {
        $(this).addClass("selected").siblings().removeClass('selected');
    }
}).sortable({
    connectWith: "ul",
    delay: 150, //Needed to prevent accidental drag when trying to select
    revert: 0,
    helper: function (e, item) {
        var helper = $('<li/>');
        if (!item.hasClass('selected')) {
            item.addClass('selected').siblings().removeClass('selected');
        }
        var elements = item.parent().children('.selected').clone();
        item.data('multidrag', elements).siblings('.selected').remove();
        return helper.append(elements);
    },
    stop: function (e, info) {
        info.item.after(info.item.data('multidrag')).remove();
    }

});
Run Code Online (Sandbox Code Playgroud)

注意:

自从我发布这个以来,我实现了类似的东西 - 将可拖动的列表项连接到可排序的多选功能.它的设置几乎完全相同,因为jQuery UI小部件非常相似.一个UI提示是确保您delay为draggables或selectables设置了参数,因此您可以单击以选择多个项目而不启动拖动.然后你构建一个帮助器,看起来像所有选定的元素放在一起(创建一个新的元素,克隆选定的项目,并附加它们),但确保保持原始项目完整(否则它搞砸了功能 - 我不能说确切原因,但它涉及很多令人沮丧的DOM例外).

我还添加了Shift + Click功能,使其功能更像本机桌面应用程序.我可能要开始一个博客,所以我可以更详细地阐述这个:-)

  • @Mrigesh,我看了这个答案的小提琴,并记得我如何访问`stop`回调中的拖动元素.我没有在这里解释,而是对Fiddle进行了更新,其中有评论,因此您可以看到如何做到这一点.(提示:它使用[`jQuery.data()`](http://api.jquery.com/data/)方法将元素附加到Sortable在其回调之间传递的拖动`item`.你必须在启动排序时将所选项目附加到"item".我在`helper`回调中执行了此操作.)http://jsfiddle.net/hQnWG/614/ (2认同)

Mot*_*tie 48

我没有使用sortable工作,但我确实使用了draggable&droppable.我不知道我是否涵盖了你需要的所有功能,但它应该是一个好的开始(这里演示):

HTML

<div class="demo">
    <p>Available Boxes (click to select multiple boxes)</p>    
    <ul id="draggable">
        <li>Box #1</li>
        <li>Box #2</li>
        <li>Box #3</li>
        <li>Box #4</li>
    </ul>

    <p>My Boxes</p>
    <ul id="droppable">
    </ul>

</div>
Run Code Online (Sandbox Code Playgroud)

脚本

$(document).ready(function(){

    var selectedClass = 'ui-state-highlight',
        clickDelay = 600,     // click time (milliseconds)
        lastClick, diffClick; // timestamps

    $("#draggable li")
        // Script to deferentiate a click from a mousedown for drag event
        .bind('mousedown mouseup', function(e){
            if (e.type=="mousedown") {
                lastClick = e.timeStamp; // get mousedown time
            } else {
                diffClick = e.timeStamp - lastClick;
                if ( diffClick < clickDelay ) {
                    // add selected class to group draggable objects
                    $(this).toggleClass(selectedClass);
                }
            }
        })
        .draggable({
            revertDuration: 10, // grouped items animate separately, so leave this number low
            containment: '.demo',
            start: function(e, ui) {
                ui.helper.addClass(selectedClass);
            },
            stop: function(e, ui) {
                // reset group positions
                $('.' + selectedClass).css({ top:0, left:0 });
            },
            drag: function(e, ui) {
                // set selected group position to main dragged object
                // this works because the position is relative to the starting position
                $('.' + selectedClass).css({
                    top : ui.position.top,
                    left: ui.position.left
                });
            }
        });

    $("#droppable, #draggable")
        .sortable()
        .droppable({
            drop: function(e, ui) {
                $('.' + selectedClass)
                 .appendTo($(this))
                 .add(ui.draggable) // ui.draggable is appended by the script, so add it after
                 .removeClass(selectedClass)
                 .css({ top:0, left:0 });
            }
        });

});
Run Code Online (Sandbox Code Playgroud)


Sha*_*mal 20

JSFiddle:http://jsfiddle.net/hQnWG/

<style>
    ul {border:1px solid Black;width:200px;height:200px;display:inline-block;vertical-align:top}
    li {background-color:Azure;border-bottom:1px dotted Gray}   
    li.selected {background-color:GoldenRod}
</style>
<h1>Click items to select them</h1>
<ul>
    <li>One</li>
    <li>Two<li>
    <li>Three</li>
</ul><ul>
    <li>Four</li>
    <li>Five<li>
    <li>Six</li>
</ul>
<script>
    $("li").click(function(){
        $(this).toggleClass("selected");
    })
    $("ul").sortable({
        connectWith: "ul",
        start:function(e,info){
            // info.item.siblings(".selected").appendTo(info.item);
            info.item.siblings(".selected").not(".ui-sortable-placeholder").appendTo(info.item);

        },
        stop:function(e,info){
            info.item.after(info.item.find("li"))
        }
    })
</script>
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!这非常简单,正是我想要的.我在JSFiddle示例中注意到的一件事是,有一个奇怪的错误,如果您选择了一个项目,然后将它放在中心周围,它就会消失. (3认同)
  • 这段代码对我来说很有用.我刚刚在`stop`函数中添加了一行,使其从所有选中的项中删除`.selected`类. (2认同)