2011-03-20 116 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