Javascript 阻止浏览器加载拖放文件
我正在向我的页面添加一个html5拖放上传程序 当一个文件被放到上传区域时,一切都很好 但是,如果我不小心将文件放在上载区域之外,浏览器将加载本地文件,就像加载新页面一样 如何防止这种行为Javascript 阻止浏览器加载拖放文件,javascript,jquery,html,drag-and-drop,Javascript,Jquery,Html,Drag And Drop,我正在向我的页面添加一个html5拖放上传程序 当一个文件被放到上传区域时,一切都很好 但是,如果我不小心将文件放在上载区域之外,浏览器将加载本地文件,就像加载新页面一样 如何防止这种行为 谢谢 您可以将事件侦听器添加到对所有dragover和drop事件调用preventDefault()的窗口中。 例如: 试试这个: document.body.addEventListener('drop', function(e) { e.preventDefault(); }, false);
谢谢 您可以将事件侦听器添加到对所有dragover和drop事件调用
preventDefault()
的窗口中。例如: 试试这个:
document.body.addEventListener('drop', function(e) {
e.preventDefault();
}, false);
默认情况下,阻止所有拖放操作可能不是您想要的。至少在某些浏览器中,可以检查拖动源是否是外部文件。我已经包含了一个函数来检查拖动源是否是这个文件中的外部文件 修改Digital Plane的答案,您可以执行以下操作:
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);
要仅允许在某些图元上进行拖放,可以执行以下操作:
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);
经过一番折腾,我发现这是最稳定的解决方案:
var dropzoneId=“dropzone”;
window.addEventListener(“dragenter”,函数(e){
如果(e.target.id!=dropzoneId){
e、 预防默认值();
e、 dataTransfer.effectAllowed=“无”;
e、 dataTransfer.dropEffect=“无”;
}
},假);
window.addEventListener(“dragover”,函数(e){
如果(e.target.id!=dropzoneId){
e、 预防默认值();
e、 dataTransfer.effectAllowed=“无”;
e、 dataTransfer.dropEffect=“无”;
}
});
window.addEventListener(“drop”,函数(e){
如果(e.target.id!=dropzoneId){
e、 预防默认值();
e、 dataTransfer.effectAllowed=“无”;
e、 dataTransfer.dropEffect=“无”;
}
});代码>
…
对于jQuery,正确答案是:
$(document).on({
dragover: function() {
return false;
},
drop: function() {
return false;
}
});
此处return false
将作为event.preventDefault()
和event.stopPropagation()
以其他几个答案中概述的“检查目标”方法为基础,这里有一个更通用的/功能性方法:
function preventDefaultExcept(predicates) {
return function (e) {
var passEvery = predicates.every(function (predicate) { return predicate(e); })
if (!passEvery) {
e.preventDefault();
}
};
}
被称为:
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])
);
我有一个HTML对象
(嵌入
),它填充了页面的宽度和高度。@digital plane的答案适用于普通网页,但如果用户掉落到嵌入式对象上,则答案无效。所以我需要一个不同的解决方案
如果切换到使用,则可以在嵌入对象接收事件之前获取事件(注意事件侦听器调用末尾的true
值):
使用以下代码(基于@digital plane的答案),页面成为拖动目标,它阻止对象嵌入捕获事件,然后加载我们的图像:
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);
document.body.addEventListener(“dragover”,函数(e){
e=e | |事件;
e、 预防默认值();
console.log(“over true”);
},对);
document.body.addEventListener(“drop”,函数(e){
e=e | |事件;
e、 预防默认值();
console.log(“Drop true”);
//开始加载图像数据以传递给我们的嵌入式系统
var droppedFiles=e.dataTransfer.files;
var fileReaders={};
var文件={};
变量读取器;
对于(var i=0;i
在Mac上的Firefox上测试 我对多个上传区域使用类选择器,因此我的解决方案采用了这种不太纯粹的形式
基于Axel Amthor的回答,依赖于jQuery(别名为$)
注意:虽然OP没有要求角度解,但我来这里是为了寻找角度解。所以这是分享我发现的可行的解决方案,如果你使用Angular
根据我的经验,这个问题首先出现在向页面添加文件放置功能时。因此,我的意见是,添加此功能的组件还应负责防止跌落区域之外的跌落
在我的解决方案中,drop区域是一个带有类的输入,但是任何明确的选择器都可以工作
import { Component, HostListener } from '@angular/core';
//...
@Component({
template: `
<form>
<!-- ... -->
<input type="file" class="dropzone" />
</form>
`
})
export class MyComponentWithDropTarget {
//...
@HostListener('document:dragover', ['$event'])
@HostListener('drop', ['$event'])
onDragDropFileVerifyZone(event) {
if (event.target.matches('input.dropzone')) {
// In drop zone. I don't want listeners later in event-chain to meddle in here
event.stopPropagation();
} else {
// Outside of drop zone! Prevent default action, and do not show copy/move icon
event.preventDefault();
event.dataTransfer.effectAllowed = 'none';
event.dataTransfer.dropEffect = 'none';
}
}
}
从'@angular/core'导入{Component,HostListener};
//...
@组成部分({
模板:`
`
})
导出类MyComponentWithDropTarget{
//...
@HostListener('document:dragover',['$event']))
@HostListener('drop',['$event']))
onDragDropFileVerifyZone(事件){
if(event.target.matches('input.dropzone')){
//在下降区。我不希望事件链中的听众稍后在这里插手
event.stopPropagation();
}否则{
//放置区域之外!禁止默认操作,并且不显示复制/移动图标
event.preventDefault();
event.dataTransfer.effectAllowed='none';
event.dataTransfer.dropEffect='none';
}
}
}
当组件被创建/销毁时,监听器会自动添加/删除,并且在同一页面上使用相同策略的其他组件不会由于stopPropagation()而相互干扰。只是想知道您正在使用什么代码来处理html5拖放上传。谢谢。您遇到的问题是由于drop/dragenter/etc.事件中缺少e.dataTransfer()或preventDefault()导致的。但如果没有代码示例,我无法判断。dragover是我丢失的部分。我确认需要dragover
和drop
处理程序来防止浏览器加载删除的文件。(最新发布于2015/08/03)。该解决方案也适用于FF最新版本。这非常有效,我可以确认它可以组合使用
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);
_stopBrowserFromOpeningDragAndDropPDFFiles = function () {
_preventDND = function(e) {
if (!$(e.target).is($(_uploadBoxSelector))) {
e.preventDefault();
e.dataTransfer.effectAllowed = 'none';
e.dataTransfer.dropEffect = 'none';
}
};
window.addEventListener('dragenter', function (e) {
_preventDND(e);
}, false);
window.addEventListener('dragover', function (e) {
_preventDND(e);
});
window.addEventListener('drop', function (e) {
_preventDND(e);
});
},
import { Component, HostListener } from '@angular/core';
//...
@Component({
template: `
<form>
<!-- ... -->
<input type="file" class="dropzone" />
</form>
`
})
export class MyComponentWithDropTarget {
//...
@HostListener('document:dragover', ['$event'])
@HostListener('drop', ['$event'])
onDragDropFileVerifyZone(event) {
if (event.target.matches('input.dropzone')) {
// In drop zone. I don't want listeners later in event-chain to meddle in here
event.stopPropagation();
} else {
// Outside of drop zone! Prevent default action, and do not show copy/move icon
event.preventDefault();
event.dataTransfer.effectAllowed = 'none';
event.dataTransfer.dropEffect = 'none';
}
}
}