2011-03-20 24 views
13

HTML5 doğal sürükleme & düşüşünü kapsamlı olarak kullanıyorum ve neredeyse tek başına küçük bir istisna olarak davranıyor.HTML5 sürükle ve bırak davranışı

Sayfadaki herhangi bir şey sürüklendiğinde dropzonlarımı vurgulamaya çalışıyorum. lightdz() ve dimdz() sayfasında tüm dropzones arka plan renkli stil özelliğini değişen

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

onları durmasını sağlamak için: Başlangıçta bu gibi belge gövdesi üzerinde jQuery dinleyici koyarak bunu başarmak için çalıştı dışarı. Bu işe yaramadı. Sürüklenen bir nesne sayfada bir alt öğe (div kabı gibi) girdiğinde, dinleyici bunu sürükleyici bir olay olarak işaretler ve dropzonları kararabilir.

Dinleyiciyi, yalnızca gövde yerine, sayfadaki tüm görünür öğelere uygulayarak bunu yaşadım. Bazen bir öğe ile diğeri arasındaki sınırı geçtiğinde, açılan kısımlarda ufak tefek görülebilir bir titreklik vardı, ama iyi görünüyordu.

Her neyse, şimdi lightdz() ve dimdz() işlevlerini değiştirdim, böylece tüm non-dropzonlara hızlı bir jQuery fadeTo() animasyonu uyguladılar. Bu, çalıştığı zaman harika görünüyor ve kullanıcıya ne yapabildiğini ve neler yapamayacağını çok açık hale getiriyor. Sorun, element sınırları arasında geçtiğinde, soluk animasyonu uyguladığıdır. Bu, arka plan renginin ara sıra titremesinden çok daha belirgindir, özellikle de nesne çok sayıda sınır üzerinde çok hızlı bir şekilde sürüklendiyse, animasyonları sıraya koyar ve sayfanın tekrar tekrar girip çıkmasını sağlar.

Ben fadeto() animasyon ile rahatsız ve sadece donukluk değiştirmek bile

, bu background-color titrek çok daha görünür, çünkü tüm sayfa değişiklikleri yerine sadece dropzone elemanları.

Tüm sayfayı, dragover ve dragleave olayları için tek bir öğe olarak göndermenin bir yolu var mı? Başarısızlık, tarayıcı penceresinin dışında gerçekleşen bir düşüşü tespit etmenin herhangi bir yolu var mı? Dragleave etkinliğini atlarsam iyi görünüyor, ancak herhangi bir nesne tarayıcı penceresinin üzerine sürüklendiyse ve bunun dışında bırakılırsa, tüm sayfa soluk kalır.

cevap

13

Bu kişinin ne kadar kolay olduğundan gerçekten utanıyorum.

$("*: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 sayfa genişliğindedir. Dragleave olayı sürüklenen nesneyi tarayıcı penceresinin dışına çıkarırsa, event.pageX değeri 0 değerini alır. Başka bir yerde olursa, sıfırdan farklı bir değere sahip olur.

+1

en azından bazı tarayıcılarda görünüyor, event.originalEvent.pageX ve event.pageX değil ... –

+0

çalışmıyor Opera ve firefox benim için –

+0

'.live' depricated .. kullanımı '.on' yerine http : //api.jquery.com/live/ – Lipis

2

Burada aşırı karmaşık alıyor olabilir ama böyle bir şey yapacağını: İşe it a bit oynamak gerekecek, böylece

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 muhtemelen düz kapalı yarasa işe gitmiyor senin kodunla.

+0

Aslında bir şey fadeto ile biraz arabası fark ettik(). Sürükle-bırak ile ilgili bir olaydan kısmi opaklığın tamamından soluklaşmak anında gerçekleşir, ancak diğer yöne doğru solması birkaç saniyelik süre süresine sahip gibi görünür. Tüm sayfalarımda oluyor, bu yüzden sadece senaryonun iddialı bir örneği olabilir, fakat opaklığı sadece onu canlandırmak yerine düz bir CSS değişimi olarak değiştirmeye karar verdim. Temiz görünmüyor, ama işe yarıyor ve aynı zamanda orijinal sorumu gereksiz hale getiriyor. –

+0

Bu ifadeyi yapıştırın. Chrome'da hala sorun yaşıyorum. Firefox, CSS değişikliğini sorunsuz bir şekilde işler, ancak Chrome her sınır değişikliğinde titreder. Böyle bir şey işe yarayıp yaramadığını göreceğim. –

1

Kabul edilen çözümü burada denedim, ancak sorunun üstesinden gelmek için setTimeout kullanarak bitti. Eğer sayfa üstündeki kapsayıcıyı, üstte süzülüyorsa bırakma elemanını bloke ediyor ve yine de damla elemanı olsaydı soruna neden oluyordu.

<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> 

sadece f(); yerine window.setTimeout(f, 250); aramaya olsaydı, gösterme ve gizleme elemanın bazı kötü titremeyi göreceksiniz.

http://jsfiddle.net/guYWx/

+0

Titreşme, dropzone'a girerken BODY üzerinde sürükleyici bir ateş açmasıdır; bu da dropzone'un kaybolmasına neden olur, bu da dragover'i tekrar tetikler. Galiba dinleyiciyi sayfadaki tüm görünür blok elemanlarına uygulayarak bu projenin etrafından geçtiğimi düşünüyorum (projem sekiz ya da dokuz ay önce, bu yüzden tüm detayları hatırlayamıyorum). Seninki muhtemelen çok daha zarif bir çözüm. –

+0

Olay dinleyicisini belgeye (gövde yerine) eklerseniz, dosya gövdenin sonuna sürüklendiyse, ejderha da tetiklenir. Bu çözüm, geçerli sayfadaki sürükleme öğelerini kapsamaz, ayrıca bkz. [Bu soru] (http://stackoverflow.com/questions/6848043/how-do-i-detect-a-file-is-being-dragged-rather -than-a-sürüklenebilir-element-on-my-pa/8494918 # 8494918). – bouke

İlgili konular