web-dev-qa-db-ja.com

HTML5 DnD dataTransfer setDataまたはgetDataがFirefoxを除くすべてのブラウザーで機能しない

これを考慮してください JSFiddle 。 Firefox(14.0.1)では正常に動作しますが、Windows(7)とOS Xの両方でChrome(21.0.1180.75)、Safari(?)、Opera(12.01?)で失敗します( 10.8)。私の知る限り、問題はdataTransferオブジェクトのsetData()またはgetData()メソッドのいずれかにあります。JSFiddleからの関連コードです。

_var dragStartHandler = function (e) {
    e.originalEvent.dataTransfer.effectAllowed = "move";
    e.originalEvent.dataTransfer.setData("text/plain", this.id);
};

var dragEnterHandler = function (e) {
    //  dataTransferValue is a global variable declared higher up.
    //  No, I don't want to hear about why global variables are evil,
    //  that's not my issue.
    dataTransferValue = e.originalEvent.dataTransfer.getData("text/plain");

    console.log(dataTransferValue);
};
_

私が知る限り、これは完璧に機能するはずで、アイテムをドラッグしているときにコンソールを見ると、idが書き出されているのがわかります。つまり、要素を見つけてid属性を取得しているということです。問題は、単にデータを設定していないのか、データを取得していないのかということです。

3回の試行と200以上のバージョンでこの作業を1週間行った後、気が散り始めているため、提案を歓迎します。私が知っているのは、それがバージョン60かそこらで動作するために使用され、特定のコードがまったく変更されていないことです...

実際、6Xと124の大きな違いの1つは、イベントバインディングをlive()からon()に変更したことです。私はそれが問題だとは思いませんが、この作業中にDnDに関しては、Chromeからいくつかの失敗を見るようになりました。 これは明らかにされました。イベントバインディングメソッドは、問題に影響しません。

[〜#〜] update [〜#〜]

新しい JSFiddle を作成しました。これは、すべてを完全に取り除き、イベントバインディングとハンドラーのみを残します。 on()live()の両方でjQuery 1.7.2と1.8でテストしました。問題が続いたため、レベルを下げてすべてのフレームワークを削除し、純粋なJavaScriptを使用しました。問題stillは持続したので、テストに基づいて、失敗しているのはコードではありません。代わりに、Chrome、Safari、およびOperaはすべてsetData()またはgetData() off仕様を実装しているか、何らかの理由で失敗しているようです。修正してください。私が間違っていれば私。

とにかく、新しいJSFiddleを見ると、問題を再現できるはずです。ドロップを受け入れるように指定された要素の上にドラッグしているときにコンソールを見るだけです。先に進み、 Chromium でチケットを開きました。結局、私はまだ何か間違ったことをしているかもしれませんが、この時点で他にどうやってDnDをするのかわかりません。新しいJSFiddleは、できる限り削除されています...

39
Gup3rSuR4c

さて、もう少し掘り下げてみると、問題は実際にはChrome、Safari、Operaではないことがわかりました。 Firefoxがそれをサポートしていて、他のブラウザが失敗しているとは言えませんでした。それは私がIEで通常受け入れるものだからです。

問題の本当の原因は DnD仕様自体 です。 dragdragenterdragleavedragoverおよびdragendイベントの仕様によると、ドラッグデータストアモードは保護モード保護モードとは何ですか?それは:

その他のすべてのイベント。ドラッグされたデータを表すアイテムのドラッグデータストアリストの形式と種類は列挙できますが、データ自体は使用できず、新しいデータを追加することはできません。

これは、「読み取り専用モードでも、設定したデータにアクセスできません。自分でf @&#に移動します。」本当に?これを思いついた天才は誰ですか?

さて、その制限を回避するための選択肢はほとんどありません。私が思いついたのは2つだけです。最初の方法は、邪悪なグローバル変数を使用して、グローバル名前空間を汚染することです。 2番目の選択肢は、HTML5 localStorage APIを使用して、DnD APIが最初から提供していた機能とまったく同じ機能を実行することです。

私が持っているこのルートを進むと、あなたはwantするためではなく、あなたhaveto。今、私は感謝し始めています 災害に関するPPKの暴言 HTML5 DnD APIがそうです。

一番下の行はこれです。仕様は、読み​​取り専用モードでのみ保存されているデータにアクセスできるように変更する必要があります。私の場合、 このJSFiddleを使って 、ドロップゾーンを先読みし、ドロップを許可するかどうかを確認する方法として、実際にdragenterを使用しています。

この場合、Mozillaは明らかに仕様への完全な準拠をオプトアウトしたため、JSFiddleは仕様でうまく機能していました。仕様が完全にサポートされていないことを完全にサポートするのは今回が初めてです。

70
Gup3rSuR4c

「保護された」ビットには理由があります。..ドラッグ/ドロップはまったく異なるウィンドウにまたがることができます。また、すべてのコンテンツを盗聴する「リスナー」DIVを実装できるようにしたくありませんでした。その上にドラッグします(そして、それらのコンテンツをAJAXによってElboniaのスパイサーバーに送信します)。DROPエリア(より明確にユーザーの制御下にあります)のみが完全なスクープを取得します。

迷惑ですが、なぜそれが必要と考えられるのかがわかります。

16
Jens Fiederer
var dragStartHandler = function (e) {
    e.originalEvent.dataTransfer.effectAllowed = "move";
    e.originalEvent.dataTransfer.setData("text/plain", this.id);
};

問題は「text/plain」にあります。 setDataのMSDNドキュメントの標準仕様は、単なる「テキスト」です(/ plainなし)。 Chromeは/ plainを受け入れますが、IEは受け入れません。どのバージョンでも試しました。

同じ問題に数週間苦労し、「ドロップ」イベントがCHROMEで行ったときにIEで適切に発火しなかった理由を見つけようとしました。dataTransferデータがなかったためです。 tが適切​​にロードされました。

13
Roland

あなたはすでにこれに答えていることは知っていますが、これは便利なスレッドです-ここに補遺を追加したかっただけです-データを自分で設定している場合は、いつでもフィールド自体にデータを追加できます(ugい)ただし、機能を再作成する必要はありません。

たとえば、独自のカスタムデータを設定する場合:

  dataTransfer.setData('mycustom/whatever', 'data');

データを新しいデータエントリとして追加し、繰り返します。

  dataTransfer.setData('mycustom/whatever/data/{a json encoded string even}');

クエリ:

// naive webkit only look at the datatransfer.types
if (dataTransfer.types.indexOf('mycustom/whatever') >= 0) {

    var dataTest = 'mycustom/whatever/data/';

    // loop through types and create a map
    for (var i in types) {

        if (types[i].substr(0, dataTest.length) == dataTest) {

            // shows:
            // {a json encoded string even}
            console.log('data:', types[i].substr(dataTest.length));

            return; // your custom handler
        }
    }
}

chromeのみでテスト済み

6
ansiart

また、注目に値することは、タイムアウトを使用して実行チェーンを離れると、dataTransferオブジェクトにデータがなくなることです。例えば.

function dropEventHandler(event){
    var dt = event.dataTransfer.getData("text/plain"); // works
    var myEvent = event;

    setTimeout(function(){
       var dt = myEvent.dataTranfer.getData("text/plain"); // null
    }, 1);
}
2
Nate Bosscher

この投稿に出くわしたのは、ChromeのdataTransfer.setData()およびdataTransfer.getData()関数で同様の経験をしていたためです。

次のようなコードがありました。

_HTML:
<div ondragstart="drag(event)" ondrop="newDrop(event)"></div>

JAVASCRIPT:
function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}
function newDrop(ev){
    var itemDragged = ev.dataTransfer.getData("text");
    var toDropTo = ev.target.id;
}
_

コードはInternet Explorerで完全に正常に機能しましたが、Chromeでテストしたとき、dataTransferオブジェクト(ドラッグ関数で設定)でdataTransfer.getData()関数を使用して値を取得できませんnewDrop関数。ステートメント_ev.target.id_からid値を取得することもできませんでした。

Webを調べてみたところ、イベントcurrentTargetプロパティではなく、イベントパラメーターtargetプロパティを使用することになっていることがわかりました。更新されたコードは次のようになりました。

_JAVASCRIPT:
function drag(ev) {
    ev.dataTransfer.setData("text", ev.currentTarget.id);
}
function newDrop(ev){
    var itemDragged = ev.dataTransfer.getData("text");
    var toDropTo = ev.currentTarget.id;
}
_

この変更により、Internet Explorerと同様にchrome=でdataTransfer.setData()およびdataTransfer.getData()関数を使用することができました。これがなぜ機能したのかはわかりません。

1
Joshua Espana

以下のコードでも同じエラーが発生しました:

event.originalEvent.dataTransfer.setData( "text/plain"、event.target.getAttribute( 'id'));

コードを次のように変更しました:

event.originalEvent.dataTransfer.effectAllowed = "move"; event.originalEvent.dataTransfer.setData( "text"、event.target.getAttribute( 'id'));

そしてそれは私のために働いた。

1
RoshanZ

私はFirefoxでWebサイトのテストを行っていました。

私のラップトップ上のWAMPでは、OPのようなコードが機能しました。ただし、WebサイトをHOSTMONSTERに移動すると、そこでは機能しませんでした。

ジョシュアエスパーナの答えに従い、問題を解決しました。

失敗しました:

ev.dataTransfer.setData("text/plain", ev.target.id);

働いた:

 ev.dataTransfer.setData("text", ev.currentTarget.id);

ありがとう、ジョシュア!

0
james