web-dev-qa-db-ja.com

dataTransferを介してオブジェクトを渡す

ドラッグアンドドロップのために、javascriptのevent.dataTransferを介してネイティブオブジェクトを渡す方法を見つけようとしています。 CMSのフロントエンドエディター部分を書いているので、ユーザーが要素をドラッグアンドドロップできるようにしたい(ファイルから画像、HTMLのスニペットなど、さまざまなタイプまで)。そのため、実際のオブジェクトを渡したいので、データを添付して、レンダリング方法を知るために必要なものを指定できます。

回避策の1つは、jQueryの.data()を使用してオブジェクトをページ上の他の何かに添付し、セレクター文字列を単にsetDataに渡すことですが、そのハックは特に楽しみではありません。

これはjQuery UIのドラッグ可能/ドロップ可能でも解決できます(そして、ライブラリを使用することに全く反対していません)が、ドロップゾーンはiframe内にあるため、これは実際には最新のjQuery UI(1.10.2 )。また、可能であればネイティブに行うことを強くお勧めします。このアプリにはすでに十分なライブラリがあります。

問題は次のとおりです。 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
});

今、仕様を読んだ後、これが失敗する理由を完全に理解しています。私が理解していないのは、私が望むものを最終的に達成する方法です。

ありがとう

38
sarink

文字列のみを保存できるため、setDataを使用する前にオブジェクトをJSON.stringifyに渡す必要があります。

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

そして逆に、文字列をオブジェクトに再変換する必要があります:

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

this working Fiddleを参照してください

49
Le_Morri

私が提案しようとしていることは間違っているかもしれません(もしそうなら、私は喜んでその理由を聞くでしょう)。必要なものを参照するように、Dragstartリスナーに変数を設定しないのはなぜですか?

//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