2011-07-20 54 views
116

Tôi đang thêm trình tải lên và kéo thả html5 vào trang của mình.Ngăn trình duyệt tải một tệp kéo và thả

Khi tệp được thả vào khu vực tải lên, mọi thứ đều hoạt động tuyệt vời.

Tuy nhiên, nếu tôi vô tình thả tệp ra ngoài vùng tải lên, trình duyệt sẽ tải tệp cục bộ như thể đó là trang mới.

Làm cách nào để ngăn chặn hành vi này?

Cảm ơn!

+1

Chỉ tò mò bạn đang sử dụng mã nào để xử lý việc tải lên kéo/thả html5. Cảm ơn. – robertwbradford

Trả lời

193

Bạn có thể thêm trình xử lý sự kiện vào cửa sổ gọi preventDefault() trên tất cả các sự kiện kéo và thả.
Ví dụ:

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

dragover là phần tôi đã mất tích. – cgatian

+3

Tôi xác nhận rằng cả hai trình xử lý 'dragover' và' drop' là cần thiết để ngăn trình duyệt tải tệp đã bị xóa. (Chrome mới nhất 2015/08/03). Các giải pháp hoạt động trên FF mới nhất, quá. – Offirmo

+1

Điều này hoạt động hoàn hảo và tôi có thể xác nhận rằng nó có thể được sử dụng kết hợp với các phần tử trang được định cấu hình để chấp nhận các sự kiện thả, chẳng hạn như các sự kiện từ tệp tải lên tệp kéo và thả như resumable.js. Sẽ hữu ích khi ngăn chặn hành vi trình duyệt mặc định trong trường hợp người dùng vô tình xóa tệp họ muốn tải lên bên ngoài vùng thả tệp tải lên thực tế và sau đó tự hỏi tại sao họ lại thấy cùng một tệp được hiển thị trực tiếp trong cửa sổ trình duyệt (giả sử một loại tệp tương thích như hình ảnh hoặc video bị xóa), thay vì hành vi mong đợi khi thấy tệp tải lên của họ. – bluebinary

1

thử điều này:

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

Ngăn chặn tất cả kéo và thả các hoạt động theo mặc định có thể không phải những gì bạn muốn. Có thể kiểm tra xem nguồn kéo có phải là tệp bên ngoài hay không, ít nhất là trong một số trình duyệt. Tôi đã bao gồm một chức năng để kiểm tra xem nguồn kéo là một tập tin bên ngoài trong StackOverflow answer này. câu trả lời

Sửa Digital Plane, bạn có thể làm một cái gì đó như thế này:

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); 
+0

Điểm của 'e || sự kiện; '? 'Sự kiện' được định nghĩa ở đâu? Đừng bận tâm. Có vẻ như đó là một đối tượng toàn cầu trong IE? Tôi tìm thấy báo giá này, '" Trong Microsoft Visual Basic Script Edition (VBScript), bạn phải truy cập đối tượng sự kiện thông qua đối tượng cửa sổ. "' [Ở đây] (https://msdn.microsoft.com/en-us/library/ ms535863 (v = vs.85) .aspx) –

7

Để chỉ cho phép kéo-và-thả trên một số yếu tố, bạn có thể làm một cái gì đó như:

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); 
18

Sau một rất nhiều không quan trọng xung quanh, tôi thấy đây là giải pháp ổn định nhất:

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>

Thiết cả effectAllowdropEffect vô điều kiện trên cửa sổ gây ra vùng thả tôi không chấp nhận bất kỳ d-n-d nữa, bất kể các thuộc tính được thiết lập mới hay không.

4

Đối với jQuery câu trả lời đúng sẽ là:

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

Đây return false sẽ cư xử như event.preventDefault()event.stopPropagation().

1

Để xây dựng vào "kiểm tra các mục tiêu" phương pháp được nêu trong một vài câu trả lời khác, đây là một chung chung hơn/chức năng phương pháp:

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

gọi như:

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]) 
); 
0

Tôi có một HTML object (embed) lấp đầy chiều rộng và chiều cao của trang. Câu trả lời của @ digital-plane hoạt động trên các trang web bình thường nhưng không phải nếu người dùng rơi vào một đối tượng nhúng. Vì vậy, tôi cần một giải pháp khác.

Nếu chúng ta chuyển sang sử dụng các event capture phase chúng tôi có thể nhận được các sự kiện trước khi đối tượng nhúng nhận họ (chú ý giá trị true vào cuối của cuộc gọi lắng nghe sự kiện):

// 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); 

Sử dụng đoạn mã sau (dựa trên câu trả lời của máy bay kỹ thuật số @) trang trở thành mục tiêu kéo, nó ngăn cản việc nhúng đối tượng từ việc chụp các sự kiện và sau đó tải hình ảnh của chúng tôi:

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); 

Đã thử nghiệm trên Firefox trên máy Mac.

Các vấn đề liên quan