2011-12-10 123 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綁定到具有一堆子元素的元素時,當您從子元素到子元素進行鼠標滑動時,事件將觸發。我用'reset'調用取代了超時時間,所以你可以看到拖動時有多糟糕:http://jsfiddle.net/guYWx/20/(大量在Chrome中隱藏/顯示)。 – Langdon

回答

24

做了一些挖掘,發現你應該在你的dragover事件處理程序中設置event.dataTransfer.dropEffect = 'move';。用Google搜索dropEffect來讀多了,發現:

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 - 感謝您指出我需要什麼!我已經投了票。

花了這麼多小時後,我得到了完全按照預期工作的建議。

我利用的組合effectAlloweddropEffect來執行拖放操作時,提供視覺提示。完全跨瀏覽器!

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