49

このJSFiddleを検討してください。Firefox(14.0.1)では正常に動作しますが、Windows(7)とOS X(10.8)の両方のChrome(21.0.1180.75)、Safari(?)、Opera(12.01?)では失敗します。私が知る限り、問題はオブジェクトのsetData()またはgetData()メソッドのいずれかにありdataTransferます。これが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以上のバージョンでこれに取り組んだ後、私は頭がおかしくなり始めているので、提案をいただければ幸いです。私が知っているのは、バージョン60かそこらで動作していたことと、特定のコードがまったく変更されていないことだけです...

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

アップデート

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

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

4

8 に答える 8

88

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

この問題の本当の原因は、DnD 仕様自体にあります。、、、およびイベントの仕様によると、ドラッグ データ ストア モードdragは保護モードです。あなたが尋ねるプロテクトモードとは何ですか? それは:dragenterdragleavedragoverdragend

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

つまり、「設定したデータにはアクセスできず、読み取り専用モードであってもアクセスできません!自分自身で f@ を実行してください。」. 本当に?これを思いついた天才は誰ですか?

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

私が持っているこのルートをたどると、2 つの HTML5 API を実装することになります。実装したいからではなく、実装しなければならないからです。今、私は、HTML5 DnD APIの惨事についての PPK の暴言に感謝し始めています。

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

この場合、Mozilla は明らかに仕様への完全な準拠をオプトアウトしたため、私の JSFiddle は問題なく動作していました。たまたま、完全な仕様をサポートしていないことを私が完全にサポートしたのはこれが 1 度だけです。

于 2012-08-14T19:26:51.603 に答える
17

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

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

于 2013-03-15T19:30:13.400 に答える
14
var dragStartHandler = function (e) {
    e.originalEvent.dataTransfer.effectAllowed = "move";
    e.originalEvent.dataTransfer.setData("text/plain", this.id);
};

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

私は同じ問題に数週間苦労し、「ドロップ」イベントが IE では正しく起動されず、CHrome では正しく起動されなかった理由を突き止めようとしました。これは、dataTransfer データが正しく読み込まれていないためです。

于 2013-12-03T06:35:36.473 に答える
6

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

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

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

クロムのみでテスト済み

于 2012-12-28T21:48:30.983 に答える
2

また、タイムアウトを使用して実行チェーンを終了すると、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);
}
于 2015-06-26T12:56:12.973 に答える
1

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

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

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

event.originalEvent.dataTransfer.effectAllowed = "移動"; event.originalEvent.dataTransfer.setData("テキスト", event.target.getAttribute('id'));

そして、それは私のために働きました。

于 2016-02-19T06:12:06.513 に答える
0

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

私のラップトップの WAMP では、OP のようなコードが機能しました。しかし、サイトをHOSTMONSTERに移したら動かなくなりました。

Joshua Espanaの答えに従いましたが、問題は解決しました。

失敗した:

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

働いた:

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

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

于 2019-03-05T16:47:10.137 に答える