4

次の問題があります。必要に応じて折りたたんだり展開したりできるサブノードを持つ大きなツリーがあります (ノード内のデータは AJAX でフェッチされます)。ただし、jquery.event.drop/drag を使用してドラッグ/ドロップ ターゲットを作成します。

ただし、折りたたんだり展開したりすると、ドロップ ターゲットの位置が変わり、再計算する必要があります。これが私がやりたかった方法です:

function create_drop_targets() {
  $('li a')
    .bind('dropstart', function(event) {
    })
    .bind('drop', function(event) {
    })
    .bind('dropend', function(event) {
    });
}

create_drop_targets() は折り畳み/展開時に呼び出されます。

ただし、これは機能しません。jquery.event.drop 内で以下を見つけました。

var drop = $.event.special.drop = {
    setup: function(){
        drop.$elements = drop.$elements.add( this );
        drop.data[ drop.data.length ] = drop.locate( this );
        },
    locate: function( elem ){ // return { L:left, R:right, T:top, B:bottom, H:height, W:width }
        var $el = $(elem), pos = $el.offset(), h = $el.outerHeight(), w = $el.outerWidth();
        return { elem: elem, L: pos.left, R: pos.left+w, T: pos.top, B: pos.top+h, W: w, H: h };
        }

ここで、setup() メソッドを再度呼び出して、$elements にドロップ可能な新しい位置を再設定する方法を知る必要があります。

4

4 に答える 4

3

同じ問題がありました。jQuery のソース コード内をさまよい、これを見つけました (でui.droppable.js):

drag: function(draggable, event) {
  //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
  if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
  ...

だから、あなたはただ使用する必要があります

$(".cocktails").draggable({
  refreshPositions: true,
});

あまり文書化されていないようです...しかし、それは私の問題を解決しました。もちろん、すべてが少し遅くなります。使用状況に応じた微調整をお勧めします (変更が発生する前に有効にし、ユーザーがマウスを動かして変更が発生したら無効にします)。

于 2009-04-25T18:48:18.890 に答える
1

jQuery 1.3で導入されたライブイベントを追加した方が良いのではないでしょうか?

$("li a").live("dropstart", function(){...});

于 2009-04-07T15:14:24.230 に答える
0

liteGrid でスクロールとドラッグ可能な行を組み合わせようとしたときに同じ問題に遭遇しましたが、回避策が見つかりました。あなたの走行距離は異なるかもしれませんが、私がしたことは、グリッドがスクロールされているかどうかを確認するロジックをドラッグ イベント ハンドラーに追加することでした (これは、ドロップ可能な位置を強制的に更新する必要があるときです)。ドラッグ可能で、refreshPositions を true に設定します。これにより、位置がすぐに更新されるわけではありませんが、次にドラッグ ハンドルが移動したときに位置が更新されます。refreshPositions を使用すると速度が低下するため、次にドラッグ イベント ハンドラーが起動したときに再度無効にします。最終的な結果として、liteGrid でグリッドがスクロールしているときにのみ refreshPositions が有効になり、残りの時間は無効になります。説明するコードを次に示します。

//This will be called every time the user moves the draggable helper.
function onDrag(event, ui) {
    //We need to re-aquire the drag handle; we don't
    //hardcode it to a selector, so this event can be
    //used by multiple draggables.
    var dragHandle = $(event.target);

    //If refreshOptions *was* true, jQueryUI has already refreshed the droppables,
    //so we can now switch this option back off.
    if (dragHandle.draggable('option', 'refreshPositions')) {
        dragHandle.draggable('option', 'refreshPositions', false)
    }

    //Your other drag handling code

    if (/* logic to determine if your droppables need to be refreshed */) {
                dragHandle.draggable('option', 'refreshPositions', true);
    }
}


$("#mydraggable").draggable({
    //Your options here, note that refreshPositions is off.
    drag: onDrag
});

これで、私と同じように何度も頭をキーボードにぶつけなくてすむようになることを願っています...

于 2010-01-15T22:15:34.963 に答える
0

元の質問はかなり古いものであることに気付きましたが、オーバーヘッドをあまりかけずにドラッグ可能な要素の位置を更新するために思いついた小さなトリックの 1 つ (AFAICT) は、適切な場所でそれらを無効にしてすぐに再度有効にすることです。

たとえば、ブラウザー ウィンドウのサイズを変更しても、ドラッグ可能なテーブル行の位置が更新されないことに気付いたので、次のようにしました。

$(window).resize(function () {                
    $(".draggable").draggable("option", "disabled", true);
    $(".draggable").draggable("option", "disabled", false);
});

これが誰かを助けることを願っています!

于 2010-11-24T17:32:03.080 に答える