7

私は次のものを持っています:

アイテムをドラッグすると、表示されている div 要素にのみドロップされ、覆われないように設定しようとしています。

だから私はこのjsを使用しました:

$(".draggable").draggable({
    helper: "clone"
})
$("#bottom, .draggable").droppable({
    drop: function(event, ui) {
        var $this = $(this),
            $dragged = $(ui.draggable);
        $this.append($dragged.clone());
    },
    hoverClass: "dragHover"
})​

しかし、ドロップ ゾーンの 1 つだけが表示されていなくても、両方の場所要素をドロップします。

これが起こらないように修正するにはどうすればよいですか?

フィドル: http://jsfiddle.net/maniator/Wp4LU/


フィドルなしでページを再作成するための追加情報:

HTML:

  <div id="top">
    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>

    <div class="draggable">
      Lorem ipsum dolor sit amet
    </div>
  </div>

  <div id="bottom"></div>

CSS:

.draggable {
    border: 1px solid green;
    background: white;
    padding: 5px;
}

.dragHover{
    background: blue;
}

#top {
    height: 500px;
    overflow-y: scroll;
}
#bottom {
    height: 150px;
    overflow-y: scroll;
    border: red solid 4px;
}

</p>

4

4 に答える 4

2

私があなたを正しければ-これはあなたの問題を解決するはずです-http://jsfiddle.net/Wp4LU/60/ また、カスタム受け入れ関数を書くこともできます -http://jqueryui.com/demos/droppable/#option-accept

コード:

var draggableList = $('#top');

$(".draggable").draggable({
    helper: "clone"
});
$("#bottom, .draggable").droppable({
    drop: function(event, ui) {
        var $this = $(this),
            $dragged = $(ui.draggable);

        if ($this.hasClass("draggable")) {
            if ($this.position().top >= draggableList.height() || 
                $this.position().top + $this.outerHeight() >= 
                draggableList.height()) 
                return;
        }

        $this.append($dragged.clone());
    },
    hoverClass: "dragHover"
})​;​
于 2012-08-26T11:18:52.897 に答える
2

関数で設定してみてくださいaccept動作デモ。

$("#bottom, .draggable").droppable({
    drop: function(event, ui) {
        var $this = $(this),
            $dragged = $(ui.draggable);
        $this.append($dragged.clone());
    },
    accept: function () {
        var $this = $(this), divTop= $("#top");
        if ($this.is(".draggable")) {
          return $this.offset().top < divTop.offset().top + divTop.height() ;
        }
        return true;
    },
    hoverClass: "dragHover"
})​;​
于 2012-08-30T07:24:37.363 に答える
1

ソース (jquery.ui.droppable.js) によると、ドロップ操作はすべての適格なドロップ可能オブジェクトを検索し、それと交差するすべてのものにドロップ関数を適用します。

drop: function(draggable, event) {

    var dropped = false;
    $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {

        if(!this.options) return;
        if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
            dropped = this._drop.call(this, event) || dropped;

(古いバージョンでは、最後の「OR」条件が逆になっているため、単一のドロップ可能なものにのみ適用されます。jQuery 1.5.2 / jQuery UI 1.8.9 を使用してフィドルを試してみて、「間違ったもの...)

また、関数に現在実装されているすべての許容モードは$.ui.intersect、(x,y) 座標のみを考慮します。

switch (toleranceMode) {
    case 'fit':
        return (l <= x1 && x2 <= r
            && t <= y1 && y2 <= b);
        break;
    case 'intersect':
        return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
            && x2 - (draggable.helperProportions.width / 2) < r // Left Half
            && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
            && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
        break;
    ...

したがって、誰かが z-index 対応のトレランス モードを追加しない限り、問題を回避するしかありません。最初にすべてのドロップ可能な候補をセットに追加し、ドロップするときに、画面に「最も近い」ものだけを選択することをお勧めします。

$("#bottom, .draggable").droppable({
    over: function(event, ui) {
        if ( !ui.draggable.data("drop-candidates") )
            ui.draggable.data("drop-candidates",[]);
        ui.draggable.data("drop-candidates").push(this);
    },
    out: function(event, ui) {
        var that = this,
            candidates = ui.draggable.data("drop-candidates") || [];
        ui.draggable.data("drop-candidates", $.grep(candidates, function(e) {
            return e != that;
        });
    },
    drop: function(event, ui) {
        var $this = $(this),
            $dragged = $(ui.draggable);
        var candidates = $.data("drop-candidates").sort(closestToScreen);
        if ( candidates[0] == this )
            $this.append($dragged.clone());
    },
    hoverClass: "dragHover"
})​

ここで、コンパレーターの実装はclosestToScreenトリッキーな部分です。W3C CSS 仕様には、レンダリング エンジンが要素を並べ替えて描画する方法が記述されていますが、この情報にアクセスする簡単な方法を今のところ見つけることができませんでした。ここSOでもこの質問をしました。誰かが良い方法を見つけるかもしれません。


PS jQuery UIソースを変更することがオプションである場合は、上記の質問に対するこの回答が示唆しているようdocument.getElementFromPointに、を使用してz-index対応トレランスモードを実装してみてください:

var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
    y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
switch (toleranceMode) {
    ...
    case 'z-index-aware':
        return document.elementFromPoint(x1,y1) == droppable;
        break;

(これにより、ドラッグ可能な要素の左上隅のすぐ下にある要素のみがドロップ ターゲットとして「十分」と見なされるようになります。理想的ではありませんが、これまでのものよりは優れています。同様のソリューションを適用して、代わりにマウス ポインターの座標)

そして、いいえ、前に提示された回避策でこのメソッドを使用することはできません: ドロップが発生した瞬間、ドラッグヘルパーは画面に最も近い要素です... (編集: d'oh! 次の場合は機能しません同じ理由で、許容モードとして実装されています...)

于 2012-08-30T06:42:03.310 に答える
0

要素にドロップしたいだけの場合は、セレクターを変更できることがわかります。

$(".draggable:visible").draggable({
    helper: "clone"
});
$("#bottom, .draggable:visible").droppable({
    drop: function(event, ui) {
        var $this = $(this),
            $dragged = $(ui.draggable);
        $this.append($dragged.clone());
    },
    hoverClass: "dragHover"
})​;

または、要素を非表示にするときに、そのドラッグ可能なクラスを別のものに変更します。

于 2012-08-30T07:33:01.430 に答える