Program Club

jQuery Sortable-여러 목록 항목 선택 및 드래그

proclub 2020. 12. 14. 20:08
반응형

jQuery Sortable-여러 목록 항목 선택 및 드래그


"사용 가능한 상자"목록이있는 디자인이 있는데, 사용자는 "사용 가능한 상자"목록에서 "내 상자"목록으로 끌어서 상자를 가져옵니다.

사용자는 한 번에 여러 개의 상자 (최대 20 개)를 가져 오지 않는 경우가 많습니다. 상자를 다 사용한 후에는 다시 "사용 가능한 상자"목록으로 드래그하여 반환합니다.

jQuery sortable을 사용하면 사용자 관점에서 바람직하지 않은 한 번에 하나의 상자를 드래그 할 수 있습니다. 문제에 대한 간단한 해결책을 찾지 못했습니다.

완전히 다른 UI 방법을 생각해 내야 할 수도 있지만, 먼저 이것이 어떻게 달성 될 수 있는지에 대한 제안이 있습니까?

감사!


정렬 가능을 사용하여 작동하지 않지만 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>

스크립트

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

});

작업 솔루션

tl; dr : 작동하는 대답은이 Fiddle을 참조하십시오 .


여러 개의 선택된 항목을 정렬 가능한 항목에서 연결된 정렬 가능한 항목 으로 드래그 하는 문제에 대한 해결책을 모든 곳에서 찾았 으며 이러한 답변은 제가 찾을 수있는 최선의 방법이었습니다.

하나...

허용되는 대답은 버그 가 있으며 @Shanimal의 대답 은 가깝지만 완전하지는 않습니다. @Shanimal의 코드를 가져와 빌드했습니다.

나는 고쳤다 :

나는 추가했다 :

  • 여러 항목 선택을위한 적절한 Ctrl + click(또는 Cmd + clickMac의 경우) 지원. 클릭 없이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>

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

});

노트:

Since I posted this, I implemented something simmilar - connecting draggable list items to a sortable, with multi-select capability. It is set up almost exactly the same, since jQuery UI widgets are so similar. One UI tip is to make sure you have the delay parameter set for the draggables or selectables, so you can click to select multiple items without initiating a drag. Then you construct a helper that looks like all the selected elements put together (make a new element, clone the selected items, and append them), but make sure to leave the original item intact (otherwise it screws up the functionality - I cannot say exactly why, but it involves a lot of frustrating DOM Exceptions).

I also added Shift + Click functionality, so that it functions more like native desktop applications. I might have to start a blog so I can expound on this in greater detail :-)


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>

There's a jQuery UI plugin for that: https://github.com/shvetsgroup/jquery.multisortable

jsFiddle: http://jsfiddle.net/neochief/KWeMM/

$('ul.sortable').multisortable();

Aaron Blenkush's solution has a major fault: removing and adding items to the sortable list breaks structure; refresh can help, but if other functions process the listing, a trigger for all of them is needed to refresh and it all becomes overly complex.

After analysing some solutions at stackoverflow, I've summarized mine in the following:

Do not use helper - use start function, cause it already has ui.item, which is the helper by default.

    start: function(event, ui){
        // only essential functionality below

        // get your own dragged items, which do not include ui.item;
        // the example shows my custom select which selects the elements
        // with ".selected" class
        var dragged = ui.item.siblings(arr["nested_item"]).children('.tRow.tSelected').parent(arr["nested_item"]);

        // clone the dragged items
        var dragged_cloned = dragged.clone();

        // add special class for easier pick-up at update part
        dragged_cloned.each(function(){$(this).addClass('drag_clone');});

        // record dragged items as data to the ui.item
        ui.item.data('dragged', dragged);

        // hide dragged from the main list
        dragged.hide();

        // attached cloned items to the ui.item - which is also ui.helper
        dragged_cloned.appendTo(ui.item);
        },
  1. On the update part:

    update: function(event, ui){
        // only essential functionality below
    
        // attach dragged items after the ui.item and show them
        ui.item.after(ui.item.data("dragged").show());
    
        // remove cloned items
        ui.item.children(".drag_clone").remove();
        },
    

Stop function may need some copy of the update functionality, but is likely to be separate from update, 'cause if no change - do not submit anything to the server.

To add: preserving order of dragged items.

참고URL : https://stackoverflow.com/questions/3774755/jquery-sortable-select-and-drag-multiple-list-items

반응형