Как определить, что файл перетаскивается, а не перетаскиваемый элемент на моей странице?

Я использую события html5, чтобы включить и перетаскивание файлов и элементов. Я привязал событие dragover к телу и использую делегаты событий, чтобы показать, куда можно отбросить draggable. Мой вопрос в том, как я могу определить, перетаскивается ли файл против элемента с draggable = true. Я знаю, что могу обнаружить, что элемент перетаскивается через e.target. Но, как я могу определить, является ли это файлом.

Доступен jquery.

Кроме того, не говорит о jquery-ui, перетаскиваемом здесь.

Я начинаю думать, что единственный способ обнаружить файл - это исключение и обнаружение элементов. Если мы не перетаскиваем элемент, предположим, что это файл. Это потребует дополнительной работы, хотя по умолчанию перетаскиваются изображения и ссылки, поэтому мне придется добавлять к ним события или препятствовать их перетаскиванию.

Ответ 1

Вы можете обнаружить, что перетаскивается, проверяя dataTransfer.types. Такое поведение пока не согласовано между браузерами, поэтому вам нужно проверить наличие 'Files' (Chrome) и 'application/x-moz-file' (Firefox).

// Show the dropzone when dragging files (not folders or page
// elements). The dropzone is hidden after a timer to prevent 
// flickering to occur as `dragleave` is fired constantly.
var dragTimer;
$(document).on('dragover', function(e) {
  var dt = e.originalEvent.dataTransfer;
  if (dt.types && (dt.types.indexOf ? dt.types.indexOf('Files') != -1 : dt.types.contains('Files'))) {
    $("#dropzone").show();
    window.clearTimeout(dragTimer);
  }
});
$(document).on('dragleave', function(e) {
  dragTimer = window.setTimeout(function() {
    $("#dropzone").hide();
  }, 25);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="dropzone" style="border: 2px dashed black; background: limegreen; padding: 25px; margin: 25px 0; display: none; position">
  🎯 Drop files here!
</div>
📄 hover files here

Ответ 2

Дальнейшее улучшение ответа на букет:

Так как chrome вызывает dragleave документа на каждом dragenter враге каждого элемента, это может вызвать мерцание dropzone, особенно если есть много вложенных элементов.

$(document).on('dragleave', function(e) {
    dragTimer = window.setTimeout(function() {
        $("#dropzone").hide();
        }, 25);
});

Что я сделал, чтобы исправить эту проблему для меня, так это увеличить тайм-аут и добавить clearTimeout до установки каждого таймаута, поскольку ранее в некоторых случаях было бы больше одного тайм-аута, которые не удаляются в событии dragover, так как dragTimer сохраняет только последний. Версия результата:

$(document).on('dragleave', function(e) {
    window.clearTimeout(dragTimer);
    dragTimer = window.setTimeout(function() {
        $("#dropzone").hide();
    }, 85);
});

btw, спасибо за идею! Мое другое решение было абсолютной болью:)

Ответ 3

Я просто использую это для обнаружения файлов в событии dragover:

Array.prototype.indexOf.call(files, "Files")!=-1 // true if files

Ответ 4

Я не совсем понимаю вашу текущую ситуацию, но если ваш элемент - объект с возможностью перетаскивания, я думаю, вы можете обернуть его внутри другого объекта с другим идентификатором для файлов и обычных элементов? Поэтому, когда вы вызываете событие, вы можете проверить его идентификатор перед обработкой. Надеюсь, это поможет! =)

Ответ 5

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

Протестировано в Windows 7 с помощью:

  • Firefox версии 39
  • Chrome версии 44
  • Версия Safari 5.1.7
function isDragSourceExternalFile(dataTransfer){
    // Source detection for Safari v5.1.7 on Windows.
    if (typeof Clipboard != 'undefined') {
        if (dataTransfer.constructor == Clipboard) {
            if (dataTransfer.files.length > 0)
                return true;
            else
                return false;
        }
    }

    // Source detection for Firefox on Windows.
    if (typeof DOMStringList != 'undefined'){
        var DragDataType = dataTransfer.types;
        if (DragDataType.constructor == DOMStringList){
            if (DragDataType.contains('Files'))
                return true;
            else
                return false;
        }
    }

    // Source detection for Chrome on Windows.
    if (typeof Array != 'undefined'){
        var DragDataType = dataTransfer.types;
        if (DragDataType.constructor == Array){
            if (DragDataType.indexOf('Files') != -1)
                return true;
            else
                return false;
        }
    }
}

Пример использования с помощью JQuery

$(document).on('dragover', function(e){
    var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer);
    console.log(IsFile);
});