18

概要:

jquery.event.dragjquery.event.dropを使用するページがあります。ドラッグが開始された後でも、常に dom に追加される要素にドラッグ アンド ドロップできる必要があります。


問題:

イベントが発生すると、dragstart使用可能なドロップ ターゲットがチェックされ、ドラッグ オブジェクトに追加されます。

私が抱えている問題は、dragstartイベントが発生した後にドロップ ターゲットを動的に追加しているため、ユーザーはこれらの動的に追加されたドロップ ターゲットにドロップできないことです。


例:

http://jsfiddle.net/blowsie/36AJq/


質問:

ドラッグを更新して、ドラッグの開始後に dom に追加された要素をドロップできるようにするにはどうすればよいですか?

4

5 に答える 5

5

このスニペットを使用できます。

重要な機能は次のとおりです。$.event.special.drop.locate();

chrome/safari/firefox/ie9 でテストされ、動作するようです。

デモを見る


アップデート

重複するイベントについては、次のコードが機能するかどうかを確認してください。グローバル変数を避けるために、無名関数内に設定しました。アイデアは、イベントの currentTarget プロパティを使用して、同じ要素が同じイベントをトリガーしていないかどうかを確認することです。ここでテストする目的で、newdrop 要素に id を設定しました。

更新されたデモを見る

(function () {
    var $body = $("body"),
        newdrops = [],
        currentTarget = {},
        ondragstart = function () {

            $(this).css('opacity', .75);
        }, ondrag = function (ev, dd) {
            $(this).css({
                top: dd.offsetY,
                left: dd.offsetX
            });
        }, ondragend = function () {

            $(this).css('opacity', '');
            for (var i = 0, z = newdrops.length; i < z; i++)
            $(newdrops[i]).off('dropstart drop dropend').removeClass('tempdrop');
            newdrops = [];
        }, ondropstart = function (e) {
            if (currentTarget.dropstart === e.currentTarget) return;
            currentTarget.dropstart = e.currentTarget;
            currentTarget.dropend = null;
            console.log('start::' + e.currentTarget.id)
            $(this).addClass("active");
        }, ondrop = function () {
            $(this).toggleClass("dropped");
        }, ondropend = function (e) {
            if (currentTarget.dropend === e.currentTarget) return;
            currentTarget.dropend = e.currentTarget;
            currentTarget.dropstart = null;
            console.log('end::' + e.currentTarget.id)
            $(this).removeClass("active");
        };

    $body.on("dragstart", ".drag", ondragstart)
        .on("drag", ".drag", ondrag)
        .on("dragend", ".drag", ondragend)
        .on("dropstart", ".drop", ondropstart)
        .on("drop", ".drop", ondrop)
        .on("dropend", ".drop", ondropend);



    var cnt = 0;
    setInterval(function () {
        var dataDroppables = $body.data('dragdata')['interactions'] ? $body.data('dragdata')['interactions'][0]['droppable'] : [];

        var $newDrop = $('<div class="drop tempdrop" id="' + cnt + '">Drop</div>');
        cnt++;
        $("#dropWrap").append($newDrop);
        var offset = $newDrop.offset();
        var dropdata = {
            active: [],
            anyactive: 0,
            elem: $newDrop[0],
            index: $('.drop').length,
            location: {
                bottom: offset.top + $newDrop.height(),
                elem: $newDrop[0],
                height: $newDrop.height(),
                left: offset.left,
                right: offset.left + $newDrop.width,
                top: offset.top,
                width: $newDrop.width
            },
            related: 0,
            winner: 0
        };
        $newDrop.data('dropdata', dropdata);
        dataDroppables.push($newDrop[0]);
        $newDrop.on("dropstart", ondropstart)
            .on("drop", ondrop)
            .on("dropend", ondropend);
        $.event.special.drop.locate($newDrop[0], dropdata.index);
        newdrops.push($newDrop[0]);
    }, 1000);
})();
于 2013-04-14T16:26:46.223 に答える
1

jquery.event.drag と jquery.event.drop を使用してこれを機能させることはできませんでしたが、ネイティブの HTML5 イベントで機能させることができました。

http://jsfiddle.net/R2B8V/1/

解決策は、関数内のドロップ ターゲットにイベントをバインドし、それを呼び出してバインディングを更新することでした。同様のプリンシパルを使用して、jquery.event.drag および jquery.event.drop でこれを機能させることができると思います。それらを機能させることができれば、回答を更新します。

JS は次のとおりです。

$(function() {
    var bind_targets = function() {
        $(".drop").on({
            dragenter: function() {
                $(this).addClass("active");
                return true;
            },
            dragleave: function() {
                $(this).removeClass("active");
            },
            drop: function() {
                $(this).toggleClass("dropped");
            }
        });
    };    

    $("div[draggable]").on({
        dragstart: function(evt) {
            evt.originalEvent.dataTransfer.setData('Text', 'data');
        },
        dragend: function(evt) {
            $('.active.drop').removeClass('active');   
        }
    });
  setInterval(function () {
      $("#dropWrap").append('<div class="drop">Drop</div>');
      // Do something here to update the dd.available
      bind_targets();
  }, 1000)
});
于 2013-04-13T18:57:45.863 に答える
0

できません。ではdragstart、可能なドロップ ゾーンが DOM から計算され、 まで編集できませんdragend.on()(Demo: http://jsfiddle.net/36AJq/84/ ) を常に再バインドしても、目的の効果は得られません。

私は問題を少し違った方法で解決しました。(デモ: http://jsfiddle.net/36AJq/87/ )

  1. <div>HTML のevery から始めます。
  2. 適用opacity: 0すると、非表示になり、非表示width: 0になるのを防ぎdropendます。
  3. setInterval次の非表示の div ( $('.drop:not(.visible)').first()) を 1000 ミリ秒ごとに表示するために使用します。

JS:

$("body")
  .on("dragstart", ".drag", function () {
    $(this).css('opacity', .75);
  })
  .on("drag", ".drag", function (ev, dd) {
    $(this).css({
      top: dd.offsetY,
      left: dd.offsetX
    });
  })
  .on("dragend", ".drag", function () {
    $(this).css('opacity', '');
  })
  .on("dropstart", ".drop", function () {
    $(this).addClass("active");
  })
  .on("drop", ".drop", function () {
    $(this).toggleClass("dropped");
  })
  .on("dropend", ".drop", function () {
    $(this).removeClass("active");
  });
setInterval(function () {
    $('.drop:not(.visible)').first()
      .addClass('visible').removeClass('hidden');
}, 1000)
于 2013-04-13T17:15:18.713 に答える
-2

すべての div をページに配置して、それらの可視性を非表示に設定してみませんか? 次に setInterval() を使用して、それぞれの可視性を毎秒変更します。

于 2013-04-13T16:25:50.433 に答える