2013-04-11 16 views
18

概要ではdragstart火災後:更新可能なドロップターゲットjquery.event.drag

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


問題:

dragstartイベントは、それが可能なドロップターゲットをチェック火災やドラッグオブジェクトに追加します。

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


例:

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


質問:

がどのように私は後にDOMに追加された要素の上にドロップできるようにするためにドラッグを更新することができますドラッグが始まった?

答えて

5

あなたはこのスニペットを使用することができます。

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

はクローム/サファリ/ Firefoxの/ IE9でテストして動作するようです。次のコードが動作するかどうか

SEE DEMO


UPDATE

イベントが重複については、を参照してください。グローバル変数を避けるために、無名関数の中に設定しました。 イベントのcurrentTargetプロパティを使用して、同じエレメントが同じイベントをトリガーしていないかどうかを確認することです。私はnewdrop要素にIDを設定しました。ここでのテストの目的でのみです。

SEE UPDATED DEMO

(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); 
})(); 
+0

素敵な仕事!私はBlowsieが満足していると思う。 –

+0

'data( 'dragdata')['interactions']'かなりかわいい!ありがとう – Blowsie

+0

また、どのようにイベントを重複を停止することができますか? http://jsfiddle.net/blowsie/qtnQF/2/ – Blowsie

-1

refreshPositions optionを有効にします。

+0

OPはjQueryUIを使用していません。 –

+0

また、refreshPositionsはJQUIの問題を解決しません。http://bugs.jqueryui.com/ticket/7619 – Blowsie

-2

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

+0

domのサイズを小さくしてパフォーマンスを向上させるために、要素がdomから動的に追加されたり削除されたりします。 – Blowsie

+0

@Blowsie幅/高さを0に設定して、それを毎秒必要なサイズに増やした場合、 – Tobi

+0

彼らは依然としてdomにあり、遅くなり、それをサイズ変更するとリフローが発生します。それは本当に実行可能なオプションではない – Blowsie

0

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

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

  1. HTMLで始まるすべて<div>です。
  2. opacity: 0を適用して非表示にし、width: 0を非表示にするとdropendが表示されないようにします。
  3. setIntervalを使用すると、それぞれ1000msの次の隠れたdiv($('.drop:not(.visible)').first())が表示されます。

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) 
+0

私はなぜ私の答えをdownvoted downvoterは私に教えてください? – Mooseman

+1

私はdownvoterではありませんが、完璧ではないソリューションを持っているため私をdownvoted以来、私はあなたの問題を指摘します。ドラッグのターゲットを動的に追加する必要があるときに、ドラッグの開始時にすべてのドロップターゲットを作成する必要があります。 –

+0

@AliGangjiあなたが編集をすると、私はdownvoteを削除することができます。 – Mooseman

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) 
}); 
+0

これには2つの問題があります:ブラウザの比較可能性とカスタマイズ。 (例えば、カーソル位置と 'dragEnd'上の' .drag 'の場所) – Mooseman

+0

私はそれが完璧な解決策ではないと言いました。私は概念を説明していた。 –

+0

ここで説明したカスタマイズを実装できます。ブラウザの互換性に関しては、これは大多数のブラウザで機能します。 IE 8以降では動作しませんが、必ずしも問題ではありません。 –

関連する問題