18

I have this code:

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

FIDDLE

If you drop the <img> element it alerts the url of the image. So far so good.

My problem is that if you drop the <a> element it alerts the url of the href of <a> element. I want to alert the url of the <img> element inside the <a> like if you droped the image in the above example.

Is that possible?

I dont mind using Jquery or any other library. I just want to take the url of the image inside a <a> element.

The whole point is to drag images-links from other websites to mine and get the url of images.

To be more clear what i am trying to achieve try to drag my profile image just under this post and drop it to fiddle. It alerts http://stackoverflow.com/users/3074592/laaposto. I want https://i.stack.imgur.com/juvdV.jpg?s=32&g=1 to be alerted.

I want the solution to work on latest version of Chrome and Firefox.

laaposto
  • 11,835
  • 15
  • 54
  • 71

9 Answers9

15

Using jQuery. (I'm just using it to get the "src" attribute so i think you can do without it)

I replaced:

var imageUrl = evt.dataTransfer.getData('URL');

with:

var imageUrl = evt.dataTransfer.getData('text/html');

Oh, and I replace the alert with a console.log so you'll need to open it.

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
Needpoule
  • 4,476
  • 24
  • 33
10

Here's how I'd do it (only tested in Firefox):

  • use jQuery
  • analyze the dropped html-code using jQuery: search for image inside with .find()
  • read src-attribute from the found image with .attr()

Here's the important part from my new drop(event) function:

// Get text/html instead of text/uri-list!
// So you get raw html that is passed even between different websites
var droppedHTML = evt.dataTransfer.getData("text/html");

// add this html to some container.
// if you skip this, the following code won't work if a single img element is dropped
var dropContext = $('<div>').append(droppedHTML);

// now you can read the img-url (not link-url!!) like this:
var imgURL = $(dropContext).find("img").attr('src');
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
Friederike
  • 1,252
  • 15
  • 29
  • 1
    this works in Chrome as well, running in my Ubuntu environment. – Spdermn02 Feb 03 '14 at 19:11
  • 2
    This answer is working just fine. Would have awarded the bounty and accepted but @MrShibby was the fisrt to answer with also a totally working solution. Thanks for your help – laaposto Feb 03 '14 at 19:12
3
function drop(evt) {
    evt.stopPropagation();
    evt.preventDefault(); 
    var imageUrl = evt.dataTransfer.getData('text/html');
    var rex = /src="?([^"\s]+)"?\s*/;
    var url, res;
    url = rex.exec(imageUrl);
    alert(url[1]);
}

It works on Chrome and Firefox, but note that if you drag an image from Chrome to Firefox it doesn't work.

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
Itay Gal
  • 10,706
  • 6
  • 36
  • 75
  • This answer is working just fine. Would have awarded the bounty and accepted but @MrShibby was the fisrt to answer with also a totally working solution. Thanks for your help – laaposto Feb 03 '14 at 19:10
1

Here is my fiddle: http://fiddle.jshell.net/ep2z5/

This works in chrome on my Mac. Basically you take the html returned, and then convert into jquery object, and since the return string is a meta tag, and an img tag, you have to take the 2nd element (number 1 in the array returned by jquery parsing) and jquery-ify that item, and then grab the src attribute.

Update: checked firefox and it isn't working there, researching now.

Update: Okay here is the newest fiddle tested in both chrome and firefox. http://fiddle.jshell.net/ep2z5/6/

It uses recursion, which can be dangerous, but i think will work okay, as long as there isn't to many nested elements.

Spdermn02
  • 179
  • 4
  • This answer is working just fine. Would have awarded the bounty and accepted but @MrShibby was the fisrt to answer with also a totally working solution. Thanks for your help – laaposto Feb 03 '14 at 19:11
  • Not working at Mac OS 10.14.5 (18F132), Chrome 74.0.3729.157, emty url returned – wtorsi May 22 '19 at 09:12
  • It happens because of new Drag&Drop API. https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop – wtorsi May 22 '19 at 17:13
1
<body>
<!--the mouse over and dragging class are defined on each item-->
<div id="root" style="margin:20px 0 0 10px;">
<div id="handle" style="float:left;margin:2px 0 0 10px; padding:5px; background-color:#FFCC00;">Drage Folder</div>
<div id="drop" style="float:left;margin:2px 0 0 110px; padding:5px; background-color:#CCCC00;">Drop Folder</div>
</div>
<img id="example" src="fold.jpg" style="position: relative" />
<script type="text/javascript">
Drag.init(document.getElementById("example"));
</script>

Create drag-drop.js file and add following code.

var Drag = {
    obj : null,

    init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
    {
            o.onmousedown     = Drag.start;

            o.hmode                                  = bSwapHorzRef ? false : true ;
            o.vmode                                  = bSwapVertRef ? false : true ;

            o.root = oRoot && oRoot != null ? oRoot : o ;

            if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
            if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
            if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
            if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

            o.minX     = typeof minX != 'undefined' ? minX : null;
            o.minY     = typeof minY != 'undefined' ? minY : null;
            o.maxX    = typeof maxX != 'undefined' ? maxX : null;
            o.maxY    = typeof maxY != 'undefined' ? maxY : null;

            o.xMapper = fXMapper ? fXMapper : null;
            o.yMapper = fYMapper ? fYMapper : null;

            o.root.onDragStart  = new Function();
            o.root.onDragEnd    = new Function();
            o.root.onDrag                          = new Function();
    },

    start : function(e)
    {
            var o = Drag.obj = this;
            e = Drag.fixE(e);
            var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
            var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
            o.root.onDragStart(x, y);

            o.lastMouseX          = e.clientX;
            o.lastMouseY          = e.clientY;

            if (o.hmode) {
                    if (o.minX != null)      o.minMouseX           = e.clientX - x + o.minX;
                    if (o.maxX != null)    o.maxMouseX         = o.minMouseX + o.maxX - o.minX;
            } else {
                    if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
                    if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
            }

            if (o.vmode) {
                    if (o.minY != null)     o.minMouseY          = e.clientY - y + o.minY;
                    if (o.maxY != null)    o.maxMouseY         = o.minMouseY + o.maxY - o.minY;
            } else {
                    if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
                    if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
            }

            document.onmousemove        = Drag.drag;
            document.onmouseup             = Drag.end;

            return false;
    },

    drag : function(e)
    {
            e = Drag.fixE(e);
            var o = Drag.obj;

            var ey      = e.clientY;
            var ex      = e.clientX;
            var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
            var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
            var nx, ny;

            if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
            if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
            if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
            if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

            nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
            ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

            if (o.xMapper)                         nx = o.xMapper(y)
            else if (o.yMapper)  ny = o.yMapper(x)

            Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
            Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
            Drag.obj.lastMouseX               = ex;
            Drag.obj.lastMouseY               = ey;

            Drag.obj.root.onDrag(nx, ny);
            return false;
    },

    end : function()
    {
            document.onmousemove = null;
            document.onmouseup   = null;
            Drag.obj.root.onDragEnd(       parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]),
                                                                    parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
            Drag.obj = null;
    },

    fixE : function(e)
    {
            if (typeof e == 'undefined') e = window.event;
            if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
            if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
            return e;
    }
};
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
easycodingclub
  • 323
  • 3
  • 5
0

This problem can be solved using only Javascript.

Piece of Code:

// onDrop
function onDrop(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var imageUrl = evt.dataTransfer.getData("URL");
    var links = getAllElementsWith("a", "href", imageUrl);
    var image;
    // console.log(links, evt);

    if(links.length){
        image = links[0].getElementsByTagName("img");
        if(image.length)
            imageUrl = image[0].getAttribute("src");
        else
            imageUrl = "#no-image";
    }

    alert(imageUrl);
};

JSFiddle Here: http://jsfiddle.net/hayatbiralem/7pr7N/5/

Thanks to kevinfahy for getAllElementsWithAttribute function.

Community
  • 1
  • 1
hayatbiralem
  • 649
  • 8
  • 15
  • It is working with image profile example that i gave but it is not working in other examples i tested – laaposto Feb 03 '14 at 19:06
0

I have added a little correction to @Frederike answer:

  function drop(evt) {
    evt.stopPropagation();
    evt.preventDefault(); 
    var droppedObject = $('<div>').html(evt.dataTransfer.getData("text/html"));
    var image = droppedObject.find("img");
    if(image != undefined && image.length > 0){
      console.log(image);
      var imageUrl = image.attr('src');
      if(imageUrl != undefined)
        console.log(imageUrl);
    } else {
      console.log("image undefined");
    }
  }  

Example on JSFiddle: https://jsfiddle.net/0joker01/xdL6gqk0/

Eugen
  • 1,356
  • 12
  • 15
0

event.dataTransfer.getData('text/html') can be used to get the HTML of the dropped image. DOMParser can be used to read the source of the image afterward, which works both for images on the page and images dropped from other sites. DOMParser avoids the possibility of executing any scripts in the HTML that would result from directly appending the HTML to a newly created element.

Demo:

let dropArea = document.getElementById('dropArea');
dropArea.addEventListener('dragover', e => e.preventDefault());
dropArea.addEventListener('drop', function(e) {
  e.preventDefault();
  let html = e.dataTransfer.getData('text/html');
  let src = new DOMParser().parseFromString(html, "text/html")
              .querySelector('img').src;
  console.log(src);
});
<img src="https://via.placeholder.com/100" draggable>
<div id="dropArea" style="height: 100px; background: dodgerblue; text-align: center;">Drop here</div>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
-1

Add an event listener to the window for the "drag" event. Set a global variable to the event source (I.E. The element in the page being dragged.) Then on "drop" you grab that the information you require from the element.

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

window.addEventListener('drag', handleClicks, false);

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

function handleClicks(evt){
    DragElement = evt.srcElement;
}

function noopHandler(evt) {
    evt.stopPropagation();
    evt.preventDefault();
}
function drop(evt) {
    console.log(evt);
    evt.stopPropagation();
    evt.preventDefault(); 
    var imageUrl = DragElement.src;
    alert(imageUrl);
}

http://fiddle.jshell.net/exx4e/

Trendy
  • 460
  • 2
  • 12
  • It works only for imgs that are already in your webiste. The point is to work for images draged and dropped outside your website. If an image is already in my website i can get its src and with others ways. Try dropping one outside fiddle to see what happens – laaposto Jan 15 '14 at 17:23
  • If the image must come from another site, I do not believe the browser will tell you the URL as a matter of security. You should be able to handle it like a file upload though. – Joel Spadin Jan 27 '14 at 17:26
  • Given Ital Gray's answer above, it looks like I was wrong. If it makes sense to do so, you might still want to fall back on handling it like a file upload, in case the browser doesn't have HTML data to give you. – Joel Spadin Jan 28 '14 at 15:02