35

In Javascript, I know how to set up a drag & drop target that accepts file uploads from the user's computer. How can I set up a drop target that accepts images that are dragged from another website? All I need to know is the URL of the image that they've dragged.

I know this is possible, since Google Docs accepts image drops from other websites. Any idea how they're doing it?

Ben Dilts
  • 10,535
  • 16
  • 54
  • 85

6 Answers6

47

UPDATE:

It looks like there are differences between Chrome on Windows and MacOS. On Windows dataTransfer.getData('Text'); works but not on MacOS. dataTransfer.getData('URL'); should work on both.


OLD answer:

You could define a drop zone:

<div id="dropbox">DropZone => you could drop any image from any page here</div>

and then handle the dragenter, dragexit, dragover and drop events:

var dropbox = document.getElementById('dropbox');

dropbox.addEventListener('dragenter', noopHandler, false);
dropbox.addEventListener('dragexit', noopHandler, false);
dropbox.addEventListener('dragover', noopHandler, false);
dropbox.addEventListener('drop', drop, false);

function noopHandler(evt) {
    evt.stopPropagation();
    evt.preventDefault();
}
function drop(evt) {
    evt.stopPropagation();
    evt.preventDefault(); 
    var imageUrl = evt.dataTransfer.getData('Text');
    alert(imageUrl);
}

​ It is inside the drop event handler that we are reading the image data from the dataTransfer object as Text. If we dropped an image from some other webpage this text will represent the url of the image.

And here's a live demo.

TSR
  • 17,242
  • 27
  • 93
  • 197
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • This is alerting a blank string in Chrome – methodofaction Aug 15 '12 at 18:09
  • @Duopixel, that's very weird. It works for me: Chrome 21.0, Windows 7 64 bit. What OS are you using? Does it work with FF? – Darin Dimitrov Aug 15 '12 at 18:10
  • Chrome 21 MacOS 10.7.4. Perhaps other MacOS user can confirm, anyone? It does work in Firefox. – methodofaction Aug 16 '12 at 01:20
  • I can confirm that it does not work in Chrome 21.0.1180.79 Mac OS X 10.8, but does work in Firefox 14.0.1. – zackdever Aug 20 '12 at 04:19
  • 3
    Looks like Chrome on MacOS uses `dataTransfer.getData('url');`. – Darin Dimitrov Aug 20 '12 at 05:54
  • getData('Text') doesn't work in chromium 22.0.1221.0 on a mac, but does in Firefox 14.0.1 on the same mac. Whereas getData('URL') works in both. – Simon M Aug 20 '12 at 06:02
  • @DarinDimitrov I read your comment before you edited it ;) I'll boot up my VM and see if it's the same here. In the meantime, you could just check the value of one of them, and if it's null just use the other value, right? – Simon M Aug 20 '12 at 06:18
  • @SimonM, actually `getData('URL')` seems to work everywhere and is the correct method to use. – Darin Dimitrov Aug 20 '12 at 06:20
  • @DarinDimitrov It makes more sense, why would you get an image URL by requesting Text? Anyway, in windows both Text and URL seem to work, in chrome and firefox. Weird... – Simon M Aug 20 '12 at 06:26
  • 5
    `getData('URL')` doesn't work when the dragged image is a link, but I can't find another way to get the information about dragged object... it seems that instead of image the object is the link that contains that image – haynar Aug 20 '12 at 06:49
  • Thanks for the follow up Darin `getData('URL')` seems to be the right solution here. – methodofaction Aug 21 '12 at 04:18
  • 1
    It has an issue with local files, undoubtedly for security reasons. The file has to be remote for this to work. – djabraham Jan 05 '14 at 20:04
  • Checked recently and this answer is working on Firefox 46.0.1, Chrome 50.0.2661, Edge 25.10586, and Internet Explorer 11.306. – Stout Joe Jun 01 '16 at 01:12
  • It was a useful explanation – Ali Khoshgoftar Mar 03 '21 at 13:35
4
function drop(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var imageUrl = evt.dataTransfer.getData('URL');  // instead of 'Text'
    alert(imageUrl);
}

Seems to work in Firefox, Safari, and Chrome on Mac. Also works in Firefox, IE, and Chrome in Windows.

Updated fiddle

zackdever
  • 1,642
  • 1
  • 13
  • 22
  • What version? It's working here on Windows 7, Chrome 21.0.1180.79 – zackdever Aug 20 '12 at 06:11
  • 2
    this doesn't work when the dragged image is a link, it alerts the link url (on Chrome/Mac) or blank string (on Safari/Mac) instead of image url – haynar Aug 20 '12 at 06:40
4

Although you are able to accept the drag and drop of an image from another website, you are unable to do any processing of it (e.g. converting it to a base64 string using the canvas) (as of 21st August 2014) because of various cross-origin policy issues.

var dt = event.dataTransfer;
var url = dt.getData('url');
if (!url) {
    url = dt.getData('text/plain');
    if (!url) {
        url = dt.getData('text/uri-list');
            if (!url) {
                // We have tried all that we can to get this url but we can't. Abort mission
                 return;
             }
         }
     }

Even Google can't get around this - If you use gmail, you can drag and drop an image from another location in to the email body, but all this does is create an <img/> element with its src set to url (from the code above).

However, I've created a plugin that allows you to fake it cross-origin drag and drop. It requires a PHP backend.

Read the article I wrote on it here https://coderwall.com/p/doco6w/html5-cross-origin-drag-and-drop

Luke Madhanga
  • 6,871
  • 2
  • 43
  • 47
3

Here's my solution to the problem: Dropzone js - Drag n Drop file from same page

Please do keep in mind that ability to drag an image from another domain depends on their CORS setup.

Community
  • 1
  • 1
B Λ R T
  • 174
  • 1
  • 2
  • 8
  • 3
    The fact that this feature is depending on the CORS-Setup from the other domain was the most important info here! – Joniras Jul 24 '19 at 16:44
2

Some browsers use text/plain some use text/html as well

This code should pull any text or image source url on the latest Chrome, FF on Mac and PC.

Safari doesn't seem to give the URL so if someone knows how to get it let me know.

I'm still working on IE.

function getAnyText(theevent) {
//see if we have anything in the text or img src tag
    var insert_text;
    var location = theevent.target;
    var etext;
    var ehtml;
    try {
            etext = theevent.dataTransfer.getData("text/plain");
    } catch (_error) {}
    try {
            ehtml = theevent.dataTransfer.getData("text/html");
    } catch (_error) {}
    if (etext) {
            insert_text = etext;
    } else if (ehtml) {
            object = $('<div/>').html(ehtml).contents();
            if (object) {
                    insert_text =  object.closest('img').prop('src');
            }
    }
    if (insert_text) {
            insertText(insert_text,location);
    }
}
DanJGer
  • 514
  • 3
  • 4
1

As the other answers correctly state: It normally depends on the CORS-Settings of the server if drag & drop from another browser window is possible (Access-Control-Allow-Origin has to be set).

However I've just found out by chance that it's possible to drap & drop any images from a Firefox (current version 68.0.1) to a Chrome window (current version 76.0.3809) and process it in Javascript, regardless if CORS headers are set or not.

See working example (based on jsfiddle of Darin Dimitrov) which accepts and directly shows images from:

  1. drag and drop from local computer (e.g. from file explorer)
  2. drag and drop from other website, if CORS headers are set, e.g. an image from https://imgur.com/
  3. drag and drop any images from Firefox window to Chrome window:
    • open jsfiddle demo in Chrome
    • open e.g. google image search in Firefox and search for any image
    • click on the image for bigger preview
    • drag & drop the preview image to the jsfiddle demo in Chrome

However this seems to be kind of a bug of Firefox and therefore I would not rely on this behaviour in an productive application.

klues
  • 847
  • 12
  • 21