web-dev-qa-db-fra.com

Passer l'objet via dataTransfer

J'essaie de trouver un moyen de passer un objet natif via event.dataTransfer de javascript pour le glisser-déposer. J'écris la partie éditeur front-end d'un CMS et je veux que les utilisateurs puissent glisser-déposer des éléments (de nombreux types différents, allant des fichiers aux images aux extraits de code HTML à peu près n'importe quoi). C'est pourquoi je veux passer un objet réel, donc je peux y attacher des données pour spécifier les choses qui seront nécessaires pour savoir comment le rendre.

Une solution de contournement consiste à utiliser .data () de jQuery pour attacher un objet à quelque chose d'autre sur la page, puis passer simplement la chaîne de sélection dans setData ... mais je n'aime pas particulièrement ce hack.

Cela pourrait également être résolu avec le glisser/déposer de jQuery UI (et je ne suis pas totalement opposé à l'utilisation de bibliothèques), mais comme la zone de dépôt est dans un iframe, il s'agit en fait d'un bogue documenté dans la dernière interface jQuery (1.10.2 ). De plus, je préférerais fortement le faire nativement si possible. Il y a déjà suffisamment de bibliothèques dans cette application.

Voici le problème: 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
});

Maintenant, après avoir lu les spécifications, je comprends parfaitement pourquoi cela échoue. Ce que je ne comprends pas, c'est comment atteindre finalement ce que je veux.

Merci

38
sarink

Vous devez passer l'objet à JSON.stringify avant d'utiliser setData car vous ne pouvez stocker que des chaînes.

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

Et dans l'autre sens, vous devez reconvertir la chaîne en un objet:

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

Voir ce violon de travail

49
Le_Morri

Peut-être que ce que je vais suggérer est faux (si c'est le cas, je serai heureux d'entendre pourquoi). Pourquoi ne pas définir une variable dans l'écouteur dragstart pour référencer ce dont vous avez besoin, par exemple:

//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();
});
2
JimmyBoy