web-dev-qa-db-ja.com

jQueryのソート可能およびドロップ可能

並べ替え可能なリストが必要ですが、そのリスト内の要素も、ドロップ可能として定義したdivにドロップ可能にする必要があります。それを行う方法を見つけることができないようです。何か案は?

27
Colin

これは、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でテスト済み)。とにかく、これはいくつかのマウスオーバー検出で簡単に解決できます。

22
Reimund

私が知る限り、私が投稿した以前のコードの問題は、ドロップ可能オブジェクトのドロップ関数がソート可能オブジェクトのマウスアップの前に呼び出されていたことであり、リストを書き直したため、ソート可能オブジェクトは怒っていました(より良い用語がないため) )。それは推測です。

最終的なコードを見る:

<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のstartイベントで#sortable htmlを保存しようとしましたが、すべてのui-cssが適用された後に呼び出され、狂った場所にリスト要素を配置してしまいました。そのため、LIでマウスダウン機能を使用する必要がありました。

SetSortableは関数内にあります。これは、stopイベントがsortableを書き換えるからです。これは、「再帰的」だと思います。ここでは正確な用語はわかりませんが、迷惑なほど混乱する可能性があります。

幸い、droppableのdrop関数はsortables停止関数の前に呼び出されるため、要素が削除されたかどうかを確認するために使用されるグローバルな「dropped」変数を設定できました。

これを行うのが簡単ではないことにまだ驚いています。jQueryにはそれをよりよく処理する関数があると思いました。おそらく何かが足りないのでしょうか?

4
Colin

正確にはあなたが要求したものではありませんが、アイテムを別の並べ替え可能なコンテナにドラッグできる最初のコンテナが必要でした-共有する必要があると思いました。これが私がそれを達成した方法でした(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/

1
Aske B.

他のドロップ可能な領域もソート可能にできる場合は、一般的なセレクターで 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' });

とにかく、このソリューションは私にとっては美しく機能しました。

0
Steven Hunt

私は一日中これに費やしてきましたが、かなり近づきましたが、それでも望みどおりに機能していません。これで必要な機能を利用できましたが、Javascriptエラーが発生しています。

問題は、要素がリストではなくドロップ可能要素にドロップされた場合に、ソート可能リストが前の位置に戻るようにすることです。現在、私はhtml onmousedownを保存してから、ドロップ可能オブジェクトのドロップ機能でhtmlを書き換えています。これは機能しますが、jquery変数を指定するとnullエラーになります。誰かがより良い解決策を見つけることができますか?

コード:

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

各ターゲットDIVを独自のソート可能にすることで、同様の最終結果を得ることができました。

次に、connectWithを使用して、すべてのソート可能オブジェクトを接続し、ドラッグ可能オブジェクトを共有できるようにしました。

何かのようなもの:

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