Запретить браузеру загрузку файла перетаскивания - PullRequest
164 голосов
/ 20 июля 2011

Я добавляю html5 drag and drop uploader на мою страницу.

Когда файл помещается в область загрузки, все прекрасно работает.

Однако, если я случайно уронилфайл за пределами области загрузки, браузер загружает локальный файл, как будто это новая страница.

Как я могу предотвратить это поведение?

Спасибо!

Ответы [ 9 ]

256 голосов
/ 20 июля 2011

Вы можете добавить прослушиватель событий в окно, которое вызывает preventDefault() для всех событий перетаскивания и отбрасывания.
Пример:

window.addEventListener("dragover",function(e){
  e = e || event;
  e.preventDefault();
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
},false);
28 голосов
/ 08 февраля 2016

После долгих раздумий я обнаружил, что это самое стабильное решение:

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>

Безусловная установка в окне параметров effectAllow и dropEffect заставляет мою зону удаления больше не принимать dnd, независимо от того, установлены ли свойства как новыеили нет.

8 голосов
/ 11 июля 2016

Для jQuery правильный ответ будет:

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

Здесь return false будет вести себя как event.preventDefault() и event.stopPropagation().

8 голосов
/ 24 октября 2015

Чтобы разрешить перетаскивание только для некоторых элементов, вы можете сделать что-то вроде:

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);
2 голосов
/ 17 августа 2015

Предотвращение всех операций перетаскивания по умолчанию может быть не тем, что вам нужно. Можно проверить, является ли источник перетаскивания внешним файлом, по крайней мере, в некоторых браузерах. Я включил функцию, чтобы проверить, является ли источник перетаскивания внешним файлом в этом StackOverflow ответе .

Изменяя ответ 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);
2 голосов
/ 20 июля 2011

попробуйте это:

document.body.addEventListener('drop', function(e) {
    e.preventDefault();
}, false);
1 голос
/ 21 сентября 2016

Чтобы использовать метод проверки цели, описанный в нескольких других ответах, вот более общий / функциональный метод:

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])
);
0 голосов
/ 25 сентября 2018

Я использую селектор классов для нескольких областей загрузки, поэтому мое решение приняло эту менее чистую форму

На основе ответа Акселя Амтора с зависимостью от jQuery (с псевдонимом $)

_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);
        });
    },
0 голосов
/ 17 января 2017

У меня есть HTML object (embed), который заполняет ширину и высоту страницы. Ответ @ digital-plane работает на обычных веб-страницах, но не в том случае, если пользователь падает на внедренный объект. Поэтому мне нужно было другое решение.

Если мы переключимся на использование фазы захвата события , мы сможем получить события до того, как встроенный объект получит их (обратите внимание на значение 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), страница становится целью перетаскивания, она не позволяет встроенным объектам захватывать события, а затем загружает наши изображения:

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

Проверено на Firefox на Mac.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...