Impedisci al browser di caricare un file trascinato

Sto aggiungendo un uploader HTML5 per il drag and drop alla mia pagina.

Quando un file viene rilasciato nell’area di caricamento, tutto funziona alla grande.

Tuttavia, se per sbaglio il file viene rilasciato all’esterno dell’area di caricamento, il browser carica il file locale come se fosse una nuova pagina.

Come posso prevenire questo comportamento?

Grazie!

È ansible aggiungere un listener di eventi alla finestra che chiama preventDefault() su tutti gli eventi di trascinamento e rilascio.
Esempio:

 window.addEventListener("dragover",function(e){ e = e || event; e.preventDefault(); },false); window.addEventListener("drop",function(e){ e = e || event; e.preventDefault(); },false); 

Dopo un sacco di manovre in giro, ho trovato che questa fosse la soluzione più stabile:

 var dropzoneId = "dropzone"; window.addEventListener("dragenter", function(e) { if (e.target.id != dropzoneId) { e.preventDefault(); e.dataTransfer.effectAllowed = "none"; e.dataTransfer.dropEffect = "none"; } }, false); window.addEventListener("dragover", function(e) { if (e.target.id != dropzoneId) { e.preventDefault(); e.dataTransfer.effectAllowed = "none"; e.dataTransfer.dropEffect = "none"; } }); window.addEventListener("drop", function(e) { if (e.target.id != dropzoneId) { e.preventDefault(); e.dataTransfer.effectAllowed = "none"; e.dataTransfer.dropEffect = "none"; } }); 
 
...

Per consentire il drag-and-drop solo su alcuni elementi, puoi fare qualcosa come:

 window.addEventListener("dragover",function(e){ e = e || event; console.log(e); if (e.target.tagName != "INPUT") { // check which element is our target e.preventDefault(); } },false); window.addEventListener("drop",function(e){ e = e || event; console.log(e); if (e.target.tagName != "INPUT") { // check which element is our target e.preventDefault(); } },false); 

Per jQuery la risposta corretta sarà:

 $(document).on({ dragover: function() { return false; }, drop: function() { return false; } }); 

Qui return false si comporterà come event.preventDefault() e event.stopPropagation() .

Prevenire tutte le operazioni di trascinamento e rilascio per impostazione predefinita potrebbe non essere quello che desideri. È ansible controllare se la sorgente di trascinamento è un file esterno, almeno in alcuni browser. Ho incluso una funzione per verificare se la sorgente di trascinamento è un file esterno in questa risposta StackOverflow .

Modificando la risposta di Digital Plane, potresti fare qualcosa del genere:

 function isDragSourceExternalFile() { // Defined here: // https://stackoverflow.com/a/32044172/395461 } window.addEventListener("dragover",function(e){ e = e || event; var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer); if (IsFile) e.preventDefault(); },false); window.addEventListener("drop",function(e){ e = e || event; var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer); if (IsFile) e.preventDefault(); },false); 

prova questo:

 document.body.addEventListener('drop', function(e) { e.preventDefault(); }, false); 

Per build sul metodo “controlla il target” delineato in poche altre risposte, ecco un metodo più generico / funzionale:

 function preventDefaultExcept(predicates) { return function (e) { var passEvery = predicates.every(function (predicate) { return predicate(e); }) if (!passEvery) { e.preventDefault(); } }; } 

Chiamato come:

 function isDropzone(e) { return e.target.id === 'dropzone'; } function isntParagraph(e) { return e.target.tagName !== 'p'; } window.addEventListener( 'dragover', preventDefaultExcept([isDropzone, isntParagraph]) ); window.addEventListener( 'drop', preventDefaultExcept([isDropzone]) ); 

Ho un object HTML ( embed ) che riempie la larghezza e l’altezza della pagina. La risposta di @ digital-plane funziona su normali pagine web ma non se l’utente cade su un object incorporato. Quindi avevo bisogno di una soluzione diversa.

Se passiamo all’utilizzo della fase di acquisizione degli eventi, possiamo ottenere gli eventi prima che l’object incorporato li riceva (notare il valore true alla fine della chiamata listener di eventi):

 // document.body or window document.body.addEventListener("dragover", function(e){ e = e || event; e.preventDefault(); console.log("over true"); }, true); document.body.addEventListener("drop", function(e){ e = e || event; e.preventDefault(); console.log("drop true"); }, true); 

Usando il seguente codice (basato sulla risposta di @ digital-plane) la pagina diventa un bersaglio di trascinamento, impedisce agli incorporamenti di oggetti di catturare gli eventi e quindi carica le nostre immagini:

 document.body.addEventListener("dragover", function(e){ e = e || event; e.preventDefault(); console.log("over true"); }, true); document.body.addEventListener("drop",function(e){ e = e || event; e.preventDefault(); console.log("Drop true"); // begin loading image data to pass to our embed var droppedFiles = e.dataTransfer.files; var fileReaders = {}; var files = {}; var reader; for (var i = 0; i < droppedFiles.length; i++) { files[i] = droppedFiles[i]; // bc file is ref is overwritten console.log("File: " + files[i].name + " " + files[i].size); reader = new FileReader(); reader.file = files[i]; // bc loadend event has no file ref reader.addEventListener("loadend", function (ev, loadedFile) { var fileObject = {}; var currentReader = ev.target; loadedFile = currentReader.file; console.log("File loaded:" + loadedFile.name); fileObject.dataURI = currentReader.result; fileObject.name = loadedFile.name; fileObject.type = loadedFile.type; // call function on embed and pass file object }); reader.readAsDataURL(files[i]); } }, true); 

Testato su Firefox su Mac.