javascript - navegadores - Evitar que el navegador cargue un archivo arrastrado y soltado
evitar caché de los navegadores al actualizar una aplicación web (8)
Estoy agregando un comando de arrastrar y soltar HTML html5 a mi página.
Cuando se deja caer un archivo en el área de carga, todo funciona bien.
Sin embargo, si dejo caer el archivo accidentalmente fuera del área de carga, el navegador carga el archivo local como si fuera una página nueva.
¿Cómo puedo prevenir este comportamiento?
¡Gracias!
Después de muchas vueltas, encontré que esta era la solución más estable:
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";
}
});
<div id="dropzone">...</div>
Establecer tanto effectAllow
como dropEffect
incondicionalmente en la ventana hace que mi zona de dropEffect
no acepte ninguna dnd por más tiempo, independientemente de si las propiedades se establecen como nuevas o no.
Evitar todas las operaciones de arrastrar y soltar de forma predeterminada puede no ser lo que desea. Es posible verificar si el origen de arrastre es un archivo externo, al menos en algunos navegadores. He incluido una función para verificar si el origen de arrastre es un archivo externo en esta respuesta de .
Modificando la respuesta del Plano Digital, podrías hacer algo como esto:
function isDragSourceExternalFile() {
// Defined here:
// https://.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);
Para construir sobre el método "verificar el objetivo" descrito en algunas otras respuestas, aquí hay un método más genérico / funcional:
function preventDefaultExcept(predicates) {
return function (e) {
var passEvery = predicates.every(function (predicate) { return predicate(e); })
if (!passEvery) {
e.preventDefault();
}
};
}
Llamado como:
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])
);
Para jQuery, la respuesta correcta será:
$(document).on({
dragover: function() {
return false;
},
drop: function() {
return false;
}
});
Aquí return false
se comportará como event.preventDefault()
y event.stopPropagation()
.
Para permitir arrastrar y soltar solo en algunos elementos, puedes hacer algo como:
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);
Tengo un object
HTML ( embed
) que llena el ancho y el alto de la página. La respuesta por @ digital-plan funciona en páginas web normales, pero no si el usuario cae en un objeto incrustado. Entonces necesitaba una solución diferente.
Si pasamos a utilizar la fase de captura de eventos , podemos obtener los eventos antes de que el objeto incrustado los reciba (observe el valor true
al final de la llamada de escucha de evento):
// 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 el siguiente código (basado en la respuesta de @ digital-plane), la página se convierte en un destino de arrastre, evita que las incrustaciones de objetos capturen los eventos y luego carga nuestras imágenes:
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);
Probado en Firefox en Mac.
prueba esto:
document.body.addEventListener(''drop'', function(e) {
e.preventDefault();
}, false);
Puede agregar un detector de eventos a la ventana que llama a preventDefault()
en todos los eventos de dragover y drop.
Ejemplo:
window.addEventListener("dragover",function(e){
e = e || event;
e.preventDefault();
},false);
window.addEventListener("drop",function(e){
e = e || event;
e.preventDefault();
},false);