如何检测文件被拖动而不是我页面上的可拖动元素?

时间:2021-11-18 09:45:16

I'm using the html5 events to enable both file and element drag-and-drop. I've attached the dragover event to the body and am using event delegations to show where a draggable can be dropped. My question is how can I tell if a file is being dragged vs. an element with draggable=true. I know I can detect the element being dragged via e.target. But, how can I tell if it is a file.

我正在使用html5事件来启用文件和元素拖放。我已将dragover事件附加到正文并使用事件委派来显示可拖放的可拖动位置。我的问题是如何判断文件是否被拖动与具有draggable = true的元素。我知道我可以通过e.target检测被拖动的元素。但是,我怎么知道它是否是一个文件。

jquery is available.

jquery可用。

Also, not talking about jquery-ui draggable here.

另外,不要在这里讨论jquery-ui draggable。

I'm starting to think maybe the only way to detect the file will be by exclusion and detecting the elements instead. If we're not dragging an element, assume it's a file. This will require extra work though as images and links are draggable by default, so I will have to add events to them or prevent them from dragging.

我开始认为可能检测文件的唯一方法是排除并检测元素。如果我们不拖动元素,则假设它是一个文件。这将需要额外的工作,但默认情况下图像和链接是可拖动的,因此我将不得不向它们添加事件或阻止它们拖动。

5 个解决方案

#1


55  

You can detect what is being dragged by inspecting dataTransfer.types. This behaviour is not (yet) consistent across browsers so you have to check for the existence of 'Files' (Chrome) and 'application/x-moz-file' (Firefox).

您可以通过检查dataTransfer.types来检测正在拖动的内容。这种行为在浏览器中并不一致(因此),因此您必须检查是否存在“文件”(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


6  

Further improvement of bouke's answer:

进一步改善布克的答案:

Since chrome calls dragleave of document on every dragenter foe each element, it can cause flickering of the dropzone, especially if there are many nested elements.

由于chrome在每个元素的每个dragenter上调用文档的dragleave,它可能导致dropzone的闪烁,特别是如果有许多嵌套元素。

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

What I did to fix the issue for me is increasing the timeout a bit and adding clearTimeout before setting each timeout, since previously in some cases there would be more than one timeouts which are not cleared in the dragover event, since dragTimer stores only the latest one. The result version:

我为解决这个问题所做的是在设置每个超时之前增加一点超时并添加clearTimeout,因为之前在某些情况下,dragover事件中不会清除多个超时,因为dragTimer只存储最新的一。结果版本:

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

btw, thanks for the idea! My other solution was an absolute pain :)

顺便说一句,谢谢你的想法!我的另一个解决方案是绝对的痛苦:)

#3


3  

I just use this to detect files in dragover event:

我只是用它来检测dragover事件中的文件:

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

#4


0  

I'm not fully understand you current situation but if your element is a drag-able object, I guess you can wrap it inside another object with different id for file and normal elements? So when you invoke an event, you can check for its id before processing. Hope this can help! =)

我不完全了解你当前的情况,但如果你的元素是一个可拖动的对象,我想你可以将它包装在另一个具有不同id的文件和普通元素的对象中吗?因此,当您调用事件时,可以在处理之前检查其id。希望这可以帮助你! =)

#5


0  

Use the function below to check if the drag source is an external file.

使用以下功能检查拖动源是否为外部文件。

Tested on Windows 7 with:

在Windows 7上测试:

  • Firefox version 39
  • Firefox版本39
  • Chrome version 44
  • Chrome版本44
  • Safari version 5.1.7
  • 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;
        }
    }
}

Example Usage with JQuery

使用JQuery的示例

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

#1


55  

You can detect what is being dragged by inspecting dataTransfer.types. This behaviour is not (yet) consistent across browsers so you have to check for the existence of 'Files' (Chrome) and 'application/x-moz-file' (Firefox).

您可以通过检查dataTransfer.types来检测正在拖动的内容。这种行为在浏览器中并不一致(因此),因此您必须检查是否存在“文件”(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


6  

Further improvement of bouke's answer:

进一步改善布克的答案:

Since chrome calls dragleave of document on every dragenter foe each element, it can cause flickering of the dropzone, especially if there are many nested elements.

由于chrome在每个元素的每个dragenter上调用文档的dragleave,它可能导致dropzone的闪烁,特别是如果有许多嵌套元素。

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

What I did to fix the issue for me is increasing the timeout a bit and adding clearTimeout before setting each timeout, since previously in some cases there would be more than one timeouts which are not cleared in the dragover event, since dragTimer stores only the latest one. The result version:

我为解决这个问题所做的是在设置每个超时之前增加一点超时并添加clearTimeout,因为之前在某些情况下,dragover事件中不会清除多个超时,因为dragTimer只存储最新的一。结果版本:

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

btw, thanks for the idea! My other solution was an absolute pain :)

顺便说一句,谢谢你的想法!我的另一个解决方案是绝对的痛苦:)

#3


3  

I just use this to detect files in dragover event:

我只是用它来检测dragover事件中的文件:

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

#4


0  

I'm not fully understand you current situation but if your element is a drag-able object, I guess you can wrap it inside another object with different id for file and normal elements? So when you invoke an event, you can check for its id before processing. Hope this can help! =)

我不完全了解你当前的情况,但如果你的元素是一个可拖动的对象,我想你可以将它包装在另一个具有不同id的文件和普通元素的对象中吗?因此,当您调用事件时,可以在处理之前检查其id。希望这可以帮助你! =)

#5


0  

Use the function below to check if the drag source is an external file.

使用以下功能检查拖动源是否为外部文件。

Tested on Windows 7 with:

在Windows 7上测试:

  • Firefox version 39
  • Firefox版本39
  • Chrome version 44
  • Chrome版本44
  • Safari version 5.1.7
  • 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;
        }
    }
}

Example Usage with JQuery

使用JQuery的示例

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