web-dev-qa-db-ja.com

DraggableとSelectableを組み合わせたJQueryプラグインはありますか

選択してドラッグして配置できる多数のアイテムを含むWebインターフェイスを実装しようとしていますグループまたは単独で。むしろ、Windowsデスクトップのようです。

すでにJQueryを使用しているので、それに追加することが最初の選択肢になります。 JQuery UI DraggablesとSelectablesは、私たちが望むことの多くを個別に実行しますが、実際には連携して、私たちが探している種類の効果を与えることはありません。

私はJQプラグインサイトに完全に圧倒されており(「人気のある」アルゴリズムはあまり役に立たないようです)、このメタファーが持っていると思うので、ここで多くの車輪の再発明を回避するための最良の方法に関するガイダンスを歓迎しますすでに行われています。

28
Will Dean

私も同じことをする必要があり、eyecon.roのインターフェース拡張機能を使いたくありませんでした。いくつかの調査の結果、 jQuery UI を使用してSelectablesとDraggablesを組み合わせることがわかりました。それはうまく伝えられていますが、コードスニペットを実行するには、それを掘り下げる必要があります。私はそれを機能させることができました。私はそれを少し変更しました、これはそれを成し遂げるための私の方法です。本番レベルで使用するには変更が必要ですが、お役に立てば幸いです。

// this creates the selected variable
// we are going to store the selected objects in here
var selected = $([]), offset = {top:0, left:0}; 

// initiate the selectable id to be recognized by UI
$("#selectable").selectable({
    filter: 'div',
});

// declare draggable UI and what we are going to be doing on start
$("#selectable div").draggable({
     start: function(ev, ui) {
        selected = $(".ui-selected").each(function() {
           var el = $(this);
            el.data("offset", el.offset());
        });

        if( !$(this).hasClass("ui-selected")) $(this).addClass("ui-selected");
        offset = $(this).offset();
    },
    drag: function(ev, ui) {
        var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left;

        // take all the elements that are selected expect $("this"), which is the element being dragged and loop through each.
        selected.not(this).each(function() {
             // create the variable for we don't need to keep calling $("this")
             // el = current element we are on
             // off = what position was this element at when it was selected, before drag
             var el = $(this), off = el.data("offset");
             el.css({top: off.top + dt, left: off.left + dl});
        });
    }
});

何が起こっているかを確認できるCSSスタイル:

#selectable {   width: 100%; height: 100%;}
#selectable div {
    background: #ffc;
    line-height: 25px;
    height: 25px;
    width: 200px;
    border: 1px solid #fcc;
    }
#selectable div.ui-selected {
    background: #fcaf3e;
    }
#selectable div.ui-selecting {
    background: #8ae234;
    }

HTMLマークアップ:

<div id="selectable">
    <div>item 1</div>
    <div>item 2</div>
    <div>item 3</div>
    <div>item 4</div>
</div>
20
Sinan

この質問は関連性がありますが、古いものです。答えもそうです。 これが更新されたバージョンです @ idFloodのjsfiddleの、jQuery 1.9.1 + jQueryUI 1.10.3で動作します:

// store selected elements and the offset of the dragged element
var selected = $([]), offset = {top:0, left:0}; 

$( "#selectable > div" ).draggable({
    start: function (event, ui) {
        var $this = $(this);

        if ($this.hasClass("ui-selected")) {
            // if this is selected, attach current offset
            // of each selected element to that element
            selected = $(".ui-selected").each(function() {
                var el = $(this);
                el.data("offset", el.offset());
            });
        } else {
            // if this is not selected, clear current selection
            selected = $([]);
            $( "#selectable > div" ).removeClass("ui-selected");
        }
        offset = $this.offset();
    },

    drag: function (event, ui) {
        // drag all selected elements simultaneously
        var dt = ui.position.top - offset.top, dl = ui.position.left - offset.left;
        selected.not(this).each(function() {
            var $this = $(this);
            var elOffset = $this.data("offset");
            $this.css({top: elOffset.top + dt, left: elOffset.left + dl});
        });
    }
});

// enable Marquee selecting and deselect on outside click...
$( "#selectable" ).selectable();

// ...but manually implement selection to prevent interference from draggable()
$( "#selectable" ).on("click", "div", function (e) {
    if (!e.metaKey && !e.shiftKey) {
        // deselect other elements if meta/shift not held down
        // $( "#dc-modules .dc-module" ).removeClass("ui-selected");
        $( "#selectable > div" ).removeClass("ui-selected");
        $(this).addClass("ui-selected");
    } else {
        if ($(this).hasClass("ui-selected")) {
            $(this).removeClass("ui-selected");
        } else {
            $(this).addClass("ui-selected");
        }
    }
});

_mouseStop()呼び出しがエラーをスローする問題が発生したため、削除しました。これは、ui-selecting状態はクリックしても発生しなくなりましたが、他のすべての機能はそのまま残ります。

10
ericsoco

SinanYasarの回答にいくつか変更を加えました。それは完璧ではありませんが、それは私が除いてずっと同じようにすでに動作します。

主な追加の1つは、selectを呼び出すクリックリスナーです。

// manually trigger the "select" of clicked elements
$( "#selectable > div" ).click( function(e){
    if (e.metaKey == false) {
        // if command key is pressed don't deselect existing elements
        $( "#selectable > div" ).removeClass("ui-selected");
        $(this).addClass("ui-selecting");
    }
    else {
        if ($(this).hasClass("ui-selected")) {
            // remove selected class from element if already selected
            $(this).removeClass("ui-selected");
        }
        else {
            // add selecting class if not
            $(this).addClass("ui-selecting");
        }
    }

    $( "#selectable" ).data("selectable")._mouseStop(null);
});

ここで完全な実例を見ることができます: http://jsfiddle.net/DXrNn/4/

それを実行するjquery-uiプラグインも利用できます。 http://code.google.com/p/jqdragdropmultiselect/ 問題は、維持されていないように見えることです。

編集:ドラッグ可能なものの「フィルター」オプションを定義する場合、selectable._mouseStop(null)の前にselectable.refresh()を呼び出す必要があります。

$( "#selectable > div" ).click( function(e){
  ...
  var selectable = $("#container").data("selectable");
  selectable.refresh();
  selectable._mouseStop(null);
  ...
4
idFlood