Pass object through dataTransfer

I'm trying to figure out a way to pass a native object through javascript's event.dataTransfer for drag and drop. I'm writing the front end editor portion of a CMS, and want users to be able to drag and drop elements (of many different types, ranging from files to images to snippets of HTML to just about anything). That's why I want to pass a real object, so I can attach data to it to specify things that will be necessary in order to know how to render it.

One workaround is to use jQuery's .data() to attach an object to something else on the page, and then simply pass the selector string in setData... but I don't particularly enjoy that hack.

This could also be solved with jQuery UI's draggable/droppable (and I'm not totally opposed to using any libraries), but since the dropzone is in an iframe, this is a actually a documented bug in the latest jQuery UI (1.10.2). Also, I would strongly prefer to do it natively if possible. There are already enough libraries in this app.

Here's the problem: http://jsfiddle.net/AHnh8/

var foo = {foo: "foo", bar: "bar"};

$dragme.on("dragstart", function(e) {
    e.originalEvent.dataTransfer.setData("foo", foo);
});

$dropzone.on("dragenter", function(e) { e.preventDefault(); });
$dropzone.on("dragover", function(e) { e.preventDefault(); });
$dropzone.on("drop", function(e) {
    console.log(e.originalEvent.dataTransfer.getData("foo")); // [Object object]
    console.log(typeof e.originalEvent.dataTransfer.getData("foo")); // string
});

Now, after reading the specs, I totally understand why this fails. What I don't understand, is how to ultimately achieve what I want.

Thanks


You should pass the object to JSON.stringify before using setData because you can only store strings.

var j = JSON.stringify(foo);
e.originalEvent.dataTransfer.setData("foo", j);

And the other way round you have to reconvert the string to an object:

var obj = JSON.parse(e.originalEvent.dataTransfer.getData("foo"));
console.log("foo is:", obj);

See this working Fiddle


Maybe what I am about to suggest is wrong (if so I will be happy to hear why ). Why not set a variable in the dragstart listener to reference what you need, for example:

//global variable
var obj;

//set the global variable to wahtever you wish in the dragstart:
$dragme.on("dragstart", function(e) {
    obj = foo;
    //or even obj = document.getElementById("some element's id");
});

//use this obj in the drop listener.
$dropzone.on("drop", function(e) {
    obj.doWahtEver();
});