Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

jquery is available.

Also, not talking about jquery-ui draggable here.

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.

like image 544
aepheus Avatar asked Jul 27 '11 16:07

aepheus


People also ask

Which event specifies where the dragged data can be dropped?

The ondragover event specifies where the dragged data can be dropped. By default, data/elements cannot be dropped in other elements. To allow a drop, we must prevent the default handling of the element.

How do you enable an object in your web page to be dragged with the user's pointer?

To see this in effect, select an area of a webpage, and then click and hold the mouse and drag the selection. An OS-specific rendering of the selection will appear and follow the mouse pointer as the drag occurs. However, this behavior is only the default drag behavior, if no listeners adjust the data to be dragged.

Which attribute defines the drag start?

What is being dragged is defined by the document or application where the drag was started. img elements and a elements with an href attribute have their draggable attribute set to true by default.


2 Answers

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">    🎯 Drop files here!  </div>  📄 hover files here
like image 168
Bouke Avatar answered Sep 27 '22 21:09

Bouke


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

like image 36
elanoism Avatar answered Sep 27 '22 21:09

elanoism