I am trying to detect if a folder or a file is dragged in the dragover
or dragenter
events.
In the ondrop
event, there is an argument called MouseEvent
, which has a field named dataTransfer
, where are listed files (.files
) or items (.items
), depending on the browser, and I can read that in both Chrome and Firefox. However, for the dragover
and dragenter
events those fields (.files
and .items
) are empty. The problem is that I need that information while dragging, not dropping.
NOTE: For both files and folders event.dataTransfer.types[i] === "Files"
is true
.
I found the following answer to partially fit for my question:
WebKit, and hence Chrome, is quite restrictive on when you can call
getData
. You're not allowed to do it insidedragstart
ordragover
. I think this is the canonical bug.
But that answer is from 2012, and I can't find actual updated information on the topic, so I am looking for updated information on this.
Drag-and-drop editing describes any editing performed by dragging an image, text, or object from one place to another. For example, to move text from one place to another in a document, you could select the text and then click-and-drag that text to another location.
Files and folders can be copied or moved to another location by literally "dragging" them across the screen. "Drag" means placing the cursor over the icon of an item, pressing the left (or sometimes right) mouse button to highlight it, and while keeping the button depressed, moving the selected item across the screen.
You can drag and drop a file onto another application outside of File Manager, regardless of whether the application is displayed as an icon or as an open window. If you drop a file with an inappropriate format onto a window or icon, the move or copy is not performed.
TL;DR you can't.
If you're wondering why this question still hasn't got an accepted answer, you can read this meta question created by OP, and my answer.
drag
/drop
in HTML5I made some research in different pieces of documentation for this topic and tested it by myself on various browsers, so I decided to summarize all I know about drag and drop of files here.
When you drag a file you can use some listeners, such as:
dragenter
dragover
dragend
dragleave
Given that these are drag
events, the files
property of event.dataTransfer
will either have length == 0
or be empty (null
).
Imagine you could read files on a drag event: you would be able to read everything even if the user doesn't want to upload files to your site. It would make no sense, seriously. Imagine you are dragging a file from your desktop to another folder and you accidentally drag it through a web page: now the web page reads your file and stores your personal information on its server... that would be a huge security flaw.
However, you will still be able to detect whether the user is dragging files (and by files I mean folders too, because folders are files) or not by iterating over the array event.dataTransfer.types
. You can create a function that checks if the drag event contains files, and then call it in the event handler.
Example:
function containsFiles(event) { if (event.dataTransfer.types) { for (var i=0; i<event.dataTransfer.types.length; i++) { if (event.dataTransfer.types[i] == "Files") { return true; } } } return false; } function handleDragEnter(e) { e.preventDefault(); if (containsFiles(e)) { // The drag event contains files // Do something } else { // The drag event doesn't contain files // Do something else } }
When you drop a file into the drop <div>
(or whatever element you're using as dropzone), you will use a listener for the event drop
to read some file properties such as name, size, type and last modification date.
To detect if a file is a folder, you are going to:
type == ""
, because folders have no type.size%4096 == 0
, because folders always have a size multiple of 4096 bytes (which is 4KiB).Example:
function handleDrop(e) { e.stopPropagation(); e.preventDefault(); var files = e.dataTransfer.files; for (var i = 0, f; f = files[i]; i++) { // iterate in the files dropped if (!f.type && f.size%4096 == 0) { // The file is a folder // Do something } else { // The file is not a folder // Do something else } } }
KNOWN ISSUE: Since that folders are actually files, this is the only way to distinguish them from another kind of file. Although this method doesn't give you absolute certainty that a file is a folder: it might be a file without extension and with a size of 0 or exactly N x 4096B.
Here are some working examples to see what I said above in action and test it by yourself. Before running them, make sure that your browser supports drag and drop features. Have fun:
This is work on Dropping -on drop event- (please note that this doesn't work on dragover event):
isDraggedItemIsFile = function(e) { // handle FF if (e.originalEvent.dataTransfer.files.length == 0) { return false; } // handle Chrome if (e.originalEvent.dataTransfer.items) { if (typeof (e.originalEvent.dataTransfer.items[0].webkitGetAsEntry) == "function") { return e.originalEvent.dataTransfer.items[0].webkitGetAsEntry().isFile; } else if (typeof (e.originalEvent.dataTransfer.items[0].getAsEntry) == "function") { return e.originalEvent.dataTransfer.items[0].getAsEntry().isFile; } } return true; }; $forms.on('drop', function(e) { if (isDraggedItemIsFile(e)) { // do something if file } else{ // is directory } });
Tested on FF V49, Chrome V55, Edge V25
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With