2011-12-10 23 views
12

Sto cercando di riprodurre il modo in cui GMail gestisce gli allegati di trascinamento/rilascio html5 - dove non appena trascini i file sulla pagina, visualizza un nuovo elemento per per lasciarli cadere. Ho capito bene quella parte (non era così semplice come pensavo sarebbe).Modifica del puntatore del mouse per i file di trascinamento HTML5 (Goccia di trascinamento di GMail)

Ora sto cercando di perfezionarlo cambiando il cursore del mouse quando il mouse si trova su qualsiasi altro elemento oltre all'elemento di rilascio, per dire che l'utente non è stato lasciato cadere qui. Immagino di poterlo fare con un cursore personalizzato, ma questo non sembra essere ciò che GMail sta facendo. The spec suggerirebbe che è possibile cambiare anche il cursore del mouse, ma non riesco a farlo funzionare correttamente, usando dropzone/effectAllowed.

Qualsiasi aiuto sarebbe apprezzato, qui è la mia messa a punto corrente: http://jsfiddle.net/guYWx/1/

ETA: Ecco quello che ho finito con: 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

Ciao, ho combattuto con me stesso per ore. Il tuo codice funziona molto più bene del mio. Puoi spiegare a cosa serve il ritardo di timeout sul reset? – benb

+1

Previene i falsi positivi per l'evento di trascinamento. Quando si associa il trascinamento/trascinamento a un elemento con un gruppo di elementi secondari, gli eventi si attivano quando si passa il mouse da un elemento secondario a un elemento secondario. Ho sostituito il timeout con una chiamata a 'reset', in modo che tu possa vedere quanto è brutto quando si trascina su: http://jsfiddle.net/guYWx/20/ (un sacco di nascondere/mostrare in Chrome). – Langdon

risposta

24

Abbiamo scavato nella fonte e ho scoperto che dovresti impostare event.dataTransfer.dropEffect = 'move'; all'interno del tuo gestore di eventi dragover. Googled per dropEffect Per saperne di più e ha trovato:

dataTransfer.dropEffect

controlla il feedback che l'utente viene dato durante dragenter e eventi dragover. Quando l'utente si posiziona su un elemento target, il cursore del browser indica quale tipo di operazione sta per assumere il numero (ad esempio una copia, uno spostamento, ecc.). L'effetto può assumere uno dei seguenti valori: nessuno, copia, collegamento, spostamento.

da: http://www.html5rocks.com/en/tutorials/dnd/basics/

Edit: Ecco quello che ho finito con: http://jsfiddle.net/guYWx/16/

doveva fare un trucco supplementare per farlo funzionare perfettamente. Ha fatto questo in modo che il contagocce non sembra quando si seleziona il testo e trascinarlo all'interno della pagina:

if ($.inArray('Files', e.dataTransfer.types) > -1) 
-3

devi cambiare cursor proprietà CSS.

È possibile trovare un elenco dei diversi valori di cursorhere.

È inoltre possibile specificare un'immagine cursore personalizzata con cursor: url('foo.png');.

+0

So che posso cambiare il cursore, ma GMail non sta facendo questo. C'è una grande differenza tra il cursore: no-drop e come appare il cursore su GMail. – Langdon

4

@Langdon - Grazie per aver ricordato esattamente quello che mi serviva! L'ho svalutato.

Dopo aver trascorso così tante ore, ho ottenuto che il suggerimento funzionasse esattamente come previsto.

ho usato effectAllowed in combinazione con dropEffect per fornire indicazioni visive quando si eseguono operazioni di trascinamento goccia. Completamente cross-browser!

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