I have a page where users can drag images from one part and drop them to a certain area. This is supported by the drag-drop API. Meanwhile, I also support users to drag and drop images from their local computer.
The question is how I can tell if the image is drag-n-dropped from the same page or uploaded? Previously with Chrome < 96, I can use event.dataTransfer.files.length
to detect. If it is from drag-drop, the length is 0
, if uploaded, length is >0
.
With the updates on the most recent Chrome versions, this has changed. If the img
src
is from remote, this works fines as before. However, my images are base64 coded, and it will be treated as a file in Chrome (length > 0
). My detection on longer works.
Here is some reproducible code on my codepen: https://codepen.io/lz100/pen/BaJVvWr
On Windows and Ubuntu when you drag the first image (remote src), the file count is 0, but when you drag the second one (base64), file count is 1. When you drag and drop a local file, the file count is also 1. So I have no way to tell where the image is coming from. MacOS does not have this issue.
If you try the code above on Firefox, things work as I wanted. The same page drag-drop file count is 0, local drag-upload file count is 1, but with Safari all three cases are giving me 1, even with the remote URL one.
Maybe I should ask, is there a robust way, across platforms, across browsers to tell whether an image is a drag-drop from the same page or from a drag-drop of local files?
It turns out that if you drag-drop a file from a local origin, there is no description in the transfer event, but if the image is transferred from the same webpage, we can manually add some description.
For example, we can add some data to the dragStart
event, and detect in the drop
event
function handleDragStart(e) {
e.dataTransfer.setData('text/plain', 'not_uploaded');
// ....
}
img.addEventListener('dragstart', handleDragStart, false);
function handleDrop(e) {
e.preventDefault(); e.stopPropagation();
/*If dragged from current page e.dataTransfer.getData("text/plain") will be "not_uploaded"*/
if(e.dataTransfer.getData("text/plain") === "not_uploaded") {
// do something
} else {
// do other thing
}
}
el.addEventListener('drop', handleDrop, false);