How do I detect a file is being dragged rather than a draggable element on my page?

后端 未结 4 1678
没有蜡笔的小新
没有蜡笔的小新 2020-12-29 01:30

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 dragg

相关标签:
4条回答
  • 2020-12-29 02:13

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

    // 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">
                                                                          
    0 讨论(0)
  • 2020-12-29 02:14

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

    Tested on Windows 7 with:

    • Firefox version 39
    • Chrome version 44
    • Safari version 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

    $(document).on('dragover', function(e){
        var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer);
        console.log(IsFile);
    });
    
    0 讨论(0)
  • 2020-12-29 02:24

    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.

    $(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:

    $(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 :)

    0 讨论(0)
  • 2020-12-29 02:24

    I just use this to detect files in dragover event:

    Array.prototype.indexOf.call(files, "Files")!=-1 // true if files
    
    0 讨论(0)
提交回复
热议问题