2011-12-10 121 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 
});