2011-12-10 4 views
12

GMailがhtml5ドラッグアンドドロップアタッチメントを処理する方法を再現しようとしています - ファイルをページ上にドラッグするとすぐにあなたはそれらを落とす。私はその部分を取り除いた(私はそれがそうであると思ったようにまっすぐではなかった)。HTML5ドラッグドロップファイルのマウスカーソルを変更する(GMailドラッグドロップ)

ここでは、マウスがdrop要素以外の要素の上にあるときにマウスカーソルを変更して、ドロップを許可しないユーザーに通知するようにしています。私はカスタムカーソルでそれを行うことができると思いますが、それはGMailがやっているようには見えません。 The specでも、マウスカーソルを変更することは可能ですが、dropzone/effectAllowedを使用して正しく動作させるようには見えません。

任意の助けをいただければ幸い、ここに私の現在の設定です:http://jsfiddle.net/guYWx/1/

ETA:ここに私がなってしまったものです:http://jsfiddle.netは、/guYWx/16/

<body style="border: 1px solid black;"> 
    <div id="d0" style="border: 1px solid black;">drag files onto this page</div> 
    <div id="d1" style="border: 1px solid black; display: none; background-color: red;">-&gt; drop here &lt;-</div> 
    <div id="d2" style="border: 1px solid black;">and stuff will happen</div> 
    <div style="float: left;">mouse them all over&nbsp;</div> 
    <div style="float: left;">these elements</div> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <div>end page</div> 
</body> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
<script type="text/javascript"> 
    var resetTimer; 

    var reset = function() 
    { 
     $('#d1').hide(); 
    }; 

    var f = function(e) 
    { 
     var srcElement = e.srcElement? e.srcElement : e.target; 

     if ($.inArray('Files', e.dataTransfer.types) > -1) 
     { 
      e.stopPropagation(); 
      e.preventDefault(); 

      e.dataTransfer.dropEffect = (srcElement.id == 'd1') ? 'copy' : 'none'; 

      if (e.type == "dragover") 
      { 
       if (resetTimer) 
       { 
        clearTimeout(resetTimer); 
       } 
       $('#d1').show(); 
       console.info('dropped on <' + srcElement.tagName.toLowerCase() + ' id="' + srcElement.id + '">\n\ne.dataTransfer.types is ' + e.dataTransfer.types + '\n\ne.dataTransfer.files.length is ' + e.dataTransfer.files.length); 

      } 
      else if (e.type == "dragleave") 
      { 
       resetTimer = window.setTimeout(reset, 25); 
      } 
      else if (e.type == "drop") 
      { 
       reset(); 
       alert('dropped on <' + srcElement.tagName.toLowerCase() + ' id="' + srcElement.id + '">\n\ne.dataTransfer.files.length is ' + (e.dataTransfer.files ? e.dataTransfer.files.length : 0)); 
      } 
     } 
    }; 

    document.body.addEventListener("dragleave", f, false); 
    document.body.addEventListener("dragover", f, false); 
    document.body.addEventListener("drop", f, false); 
</script> 
+0

こんにちは、私は何時間もこの自分と戦ってきました。あなたのコードはもっとうまく機能しています。リセットのタイムアウトの遅延の目的を説明できますか? – benb

+1

dragleaveイベントの誤検出を防止します。 dragover/dragleaveを複数のサブ要素を持つ要素にバインドすると、サブ要素からサブ要素にマウスを移動するとイベントが発生します。私はtimeoutを 'reset'の呼び出しで置き換えたので、あなたはhttp://jsfiddle.net/guYWx/20/(Chromeでたくさんの隠れている/表示している)をドラッグすると悪いことがわかります。 – Langdon

答えて

24

ソースを掘り下げて、event.dataTransfer.dropEffect = 'move';dragoverイベントハンドラ内に設定することが判明しました。より多く見つかっを読むためにdropEffectプロパティのためにGoogleで検索:

dataTransfer.dropEffect

は、ユーザーがdragenterイベントと のdragoverイベント中に与えられているのフィードバックを制御します。ユーザーがターゲット要素の上を移動すると、 ブラウザのカーソルは、 場所(コピー、移動など)を取る操作のタイプを示します。このエフェクトは、値なし、コピー、リンク、移動のいずれかの値を持つ のいずれかを取ることができます。 http://www.html5rocks.com/en/tutorials/dnd/basics/

編集:から

http://jsfiddle.net/guYWx/16/はそれが完璧に働いて得るために一つの追加のトリックをしなければならなかった。ここで私がなってしまったものです。このようにスポイトを使用して、テキストを選択し、ページの周りにドラッグしたときに表示されませんでした:

if ($.inArray('Files', e.dataTransfer.types) > -1) 
-3

あなたはcursor CSSプロパティを変更する必要があります。

cursorhereという異なる値の一覧があります。

cursor: url('foo.png');でカスタムカーソルイメージを指定することもできます。

+0

私はカーソルを変更することができますが、Gmailはこれをやっていません。カーソル間には大きな違いがあります:ノードロップと、カーソルがGMail上でどのように見えるか。 – Langdon

4

@Langdon - 私が必要な正確に何を指摘してくれてありがとう!私はそれをupvotedしています。

私はあまりにも多くの時間を費やした後、その提案が意図した通りに正確に働いています。

Iはの使用は、ドラッグドロップ操作を実行するときに視覚的な手がかりを提供するdropEffectプロパティと組み合わせてをeffectAllowedました。完全にクロスブラウザ!

$(document).on('dragstart dragenter dragover', function(event) {  
    // Only file drag-n-drops allowed, http://jsfiddle.net/guYWx/16/ 
    if ($.inArray('Files', event.originalEvent.dataTransfer.types) > -1) { 
     // Needed to allow effectAllowed, dropEffect to take effect 
     event.stopPropagation(); 
     // Needed to allow effectAllowed, dropEffect to take effect 
     event.preventDefault(); 

     $('.dropzone').addClass('dropzone-hilight').show();  // Hilight the drop zone 
     dropZoneVisible= true; 

     // http://www.html5rocks.com/en/tutorials/dnd/basics/ 
     // http://api.jquery.com/category/events/event-object/ 
     event.originalEvent.dataTransfer.effectAllowed= 'none'; 
     event.originalEvent.dataTransfer.dropEffect= 'none'; 

     // .dropzone .message 
     if($(event.target).hasClass('dropzone') || $(event.target).hasClass('message')) { 
      event.originalEvent.dataTransfer.effectAllowed= 'copyMove'; 
      event.originalEvent.dataTransfer.dropEffect= 'move'; 
     } 
    } 
}).on('drop dragleave dragend', function (event) { 
    dropZoneVisible= false; 

    clearTimeout(dropZoneTimer); 
    dropZoneTimer= setTimeout(function(){ 
     if(!dropZoneVisible) { 
      $('.dropzone').hide().removeClass('dropzone-hilight'); 
     } 
    }, dropZoneHideDelay); // dropZoneHideDelay= 70, but anything above 50 is better 
});