防止浏览器加载拖放文件
我正在添加一个html5的拖放上传到我的网页。
当一个文件被放入上传区域时,一切正常。
但是,如果我不小心将文件放在上载区域之外,浏览器将加载本地文件,就好像它是新页面一样。
我怎样才能防止这种行为?
谢谢!
您可以将事件侦听器添加到调用所有dragover和drop事件的preventDefault()
的窗口中。
例:
window.addEventListener("dragover",function(e){ e = e || event; e.preventDefault(); },false); window.addEventListener("drop",function(e){ e = e || event; e.preventDefault(); },false);
经过大量的摆弄之后,我发现这是最稳定的解决scheme:
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>
为了只允许拖放一些元素,你可以做一些事情:
window.addEventListener("dragover",function(e){ e = e || event; console.log(e); if (e.target.tagName != "INPUT") { // check wich element is our target e.preventDefault(); } },false); window.addEventListener("drop",function(e){ e = e || event; console.log(e); if (e.target.tagName != "INPUT") { // check wich element is our target e.preventDefault(); } },false);
对于jQuery,正确的答案是:
$(document).on({ dragover: function() { return false; }, drop: function() { return false; } });
这里return false
将performance为event.preventDefault()
和event.stopPropagation()
。
默认情况下阻止所有拖放操作可能不是您想要的。 至less在某些浏览器中,可以检查拖动源是否是外部文件。 我已经包含了一个函数来检查拖动源是否是这个StackOverflow答案中的外部文件。
修改数字平面的答案,你可以做这样的事情:
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);
尝试这个:
document.body.addEventListener('drop', function(e) { e.preventDefault(); }, false);
build立在其他一些答案中概述的“检查目标”方法,这里是一个更通用/function的方法:
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 object
( embed
),填充页面的宽度和高度。 @数字平面的答案在普通的网页上工作,但如果用户掉到一个embedded的对象上,则不会。 所以我需要一个不同的解决scheme
如果我们切换到使用事件捕获阶段,我们可以在embedded对象接收它们之前获取事件(注意在事件侦听器调用结束时的true
值):
// 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);
使用下面的代码(基于@ digital-plane的答案)页面变成一个拖动目标,它可以防止对象embedded捕获事件,然后加载我们的图像:
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);
在Mac上testingFirefox。