2011-03-20 114 views
13

我广泛利用HTML5本机拖动&下降,而且它几乎完全表现自己,一个小小的例外。HTML5拖放行为

我想什么时候拖过上突出显示我的dropzones。我最初试图通过戴上文档正文jQuery的听众,这样来实现:

$("body").live('dragover',function(event){lightdz(event)}); 
$("body").live('dragexit dragleave drop',function(event){dimdz(event)}); 

与lightdz()和dimdz()改变页面上的所有dropzones的背景颜色样式属性,以使他们脱颖而出出。这没有奏效。只要拖动的对象进入页面上的子元素(如div容器),监听器就会将其标记为dragleave事件,并将下拉框变暗。

我解决此得到了应用听众页面上的所有可见元素,而不只是身体。当穿过一个元素与另一个元素之间的边界时,偶尔会有一些可见的闪烁,但看起来很好。

反正现在我已经改变lightdz()和dimdz(),使它们适用于快速的jQuery fadeTo()动画所有非dropzones。这看起来真棒当它的工作,并使其非常明显的用户他们可以和不能放下东西。麻烦的是当它在元素边界之间传递时,它应用淡入淡出动画。这比背景颜色的偶尔闪烁要明显得多,特别是因为如果对象很快被拖动到多个边界上,它会排列动画并使页面反复淡入淡出。

即使我不打扰fadeTo()动画,只是改变不透明度,它比背景颜色闪烁更明显,因为整个页面变化而不仅仅是dropzone元素。

有什么办法来引用整个页面为的的dragover和dragleave事件的目的的单个元素?否则,有什么办法可以检测到在浏览器窗口之外发生的拖放?如果我跳过dragleave事件,它看起来很好,但如果有任何对象被拖动到浏览器窗口上,然后掉到外面,整个页面将保持淡化状态。

回答

13

我真的很尴尬这是多么容易。

$("*:visible").live('dragenter dragover',function(event){lightdz(event)}); 

$("#page").live('dragleave dragexit',function(event) 
{ 
    if(event.pageX == "0") 
     dimdz(event); 
}); 

$("*:visible").live('drop',function(event){dimdz(event)}); 

#page是一个页面范围的容器。如果dragleave事件将拖动的对象带到浏览器窗口外部,则event.pageX的值将为0.如果发生在其他任何地方,则它将具有非零值。

+1

似乎至少在一些浏览器上,这是event.originalEvent.pageX而不是event.pageX ... – 2012-03-01 06:04:08

+0

不适用于歌剧和Firefox我的 – 2013-01-23 20:12:45

+0

'.live'被depricated ..使用'.on'而不是http ://api.jquery.com/live/ – Lipis 2013-02-22 17:55:50

2

我在这里可以得到过于复杂,但我会做这样的事情:

var draggingFile = false; 
var event2; 

//elements with the class hotspots are OK 
var hotspots = $(".hotspots"); 

//Handlers on the body for drag start & stop 
$("body").live("dragover", function(event){ draggingFile = true; event2 = event; }); 
$("body").live("dragexit dragleave drop", function(event){ draggingFile = false; event2 = event; }); 

//Function checks to see if file is being dragged over an OK hotspot regardless of other elements infront 
var isTargetOK = function(x, y){ 
    hotspots.each(function(i, el){ 
     el2 = $(el); 
     var pos = el2.offset(); 
     if(x => pos.left && x <= pos.left+el2.width() && y => pos.top && y <= post.top+el2.height()){ 
      return true; 
     } 
    }); 
    return false; 
}; 

//Mousemove handler on body 
$("body").mousemove(function(e){ 
    //if user is dragging a file 
    if(draggingFile){ 
     //Check to see if this is an OK element with mouse X & Y 
     if(isOKTarget(e.pageX, e.pageY)){ 
      //Light em' up! 
      lightdz(event2); 
     } else { /* Fade em' :(*/ dimdz(event2); } 
    } else { 
     dimdz(); //Having no parematers means just makes sure hotspots are off 
    } 
}); 

BTW这可能行不通直客蝙蝠,所以你必须调整它有点工作与您的代码。

+0

其实我已经发现了一些有点马车与fadeTo()。从拖放相关事件中完全褪色到部分不透明似乎立即发生,但相反褪色似乎有几秒钟前置时间。它发生在我的所有页面上,所以对我的脚本来说可能只是特别的,但我决定只是将CSS改为直接改变而不是将它变成动画。不看起来干净,但它的工作原理,也使我原来​​的问题是多余的。 – 2011-03-20 18:31:25

+0

废弃该声明。 Chrome中仍然存在问题。 Firefox无缝地处理CSS更改,但Chrome会在每个边界更改上闪烁。我会看看这样的事情是否有效。 – 2011-03-20 19:23:34

1

我试图接受的解决方案在这里,但最终使用的setTimeout来克服这个问题。如果页面范围内的容器浮动在顶部,并且仍然会导致问题(如果是drop元素),那么我们在整个页面范围内都会阻塞drop元素。

<body style="border: 1px solid black;"> 
    <div id="d0" style="border: 1px solid black;">&nbsp;</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;">&nbsp;</div> 
    <div style="float: left;">other element</div> 
    <div style="float: left;">&nbsp;-&nbsp;</div> 
    <div style="float: left;">another element</div> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
</body> 
<script type="text/javascript"> 
    var resetTimer; 

    var f = function(e) 
    { 
     if (e.type == "dragover") 
     { 
      e.stopPropagation(); 
      e.preventDefault(); 
      if (resetTimer) 
      { 
       clearTimeout(resetTimer); 
      } 
      document.getElementById('d1').style.display = ''; 
     } 
     else 
     { 
      var f = function() 
      { 
       document.getElementById('d1').style.display = 'none'; 
      }; 
      resetTimer = window.setTimeout(f, 25); 
     } 
    }; 

    document.body.addEventListener("dragover", f, true); 
    document.body.addEventListener("dragleave", f, true); 
    document.getElementById('d1').addEventListener("drop", function(e){ f(); alert('dropped'); }, false); 
</script> 

如果你只是调用f();而不是window.setTimeout(f, 250);,你会看到在显示和隐藏元素的一些讨厌的闪烁。

http://jsfiddle.net/guYWx/

+0

闪烁是因为它在进入dropzone时会在BODY上触发dragleave,这会使dropzone消失,并再次触发dragover。我认为我通过将dragover监听器应用于页面上所有可见的块元素来解决这个问题(我的项目是八九个月前,因此我不记得所有的细节)。你的可能是一个更优雅的解决方案。 – 2011-12-12 16:46:19

+0

如果您将事件侦听器附加到文档(而不是主体),则如果文件被拖动到正文的最后,则dragover也会被触发。此解决方案不包括在当前页面上拖动元素,另请参见[此问题](http://stackoverflow.com/questions/6848043/how-do-i-detect-a-file-is-being-dragged-rather -than-A-可拖动的元素上,我-PA/8494918#8494918)。 – bouke 2011-12-14 10:47:14