Drag and Drop APIのモダンブラウザ間の差異に関する考察
お久しぶりです、わたしです。
今日はHTML5(死語)のDrag and Drop APIのモダンブラウザ間にある(と予想される)実装差異についてです。
Drag and Drop API自体につきましてはググってください。
要はDOMを掴んで投げて落として、データの受け渡しとかイベント処理をよしなにできるAPIです、多分。
まぁざっくりとこの記事の要旨を書きますと
・webkit系ブラウザは、img要素を入れ子した親要素をdragしようとした際に、dragstartイベントのdataTransfer.setDragImageメソッドが正しく機能しない?
・mozilla(Firefox)は、img要素ないしimg要素を内包した親要素でない場合、dragStartイベントのdataTransfer.setDataをしない限りはdragすることができない?
今回、この検証のために書いたコードが以下になります
onload = function(){ var $elmDrag = $('.drag'); var $elmDrop = $('.drop'); var feedbackImg = new Image(); feedbackImg.src = 'http://cdn1.www.st-hatena.com/users/c6/c67n9v6l9/profile.gif'; $elmDrag.on('dragstart',function(e){ e.originalEvent.dataTransfer.setData('text/plain','hoge'); e.originalEvent.dataTransfer.setDragImage(feedbackImg,32,32); }); $elmDrop.on('dragover',function(e){e.preventDefault()}); $elmDrop.on('drop',function(e){ e.preventDefault(); alert('drop'); }); };
3種類のDOM(imgを内包したdiv、img、div)をdraggableにし、dragstartイベントのリスナー内で、ドラッグ時のフィードバック画像を設定できるdataTransfer.setDragImageで別の画像を設定しています。
右下に設置したdivにdropイベントリスナを貼り、alertを出すという、至極シンプルなものになっています。
で、これをchrome、safari、Firefoxの3ブラウザでテストしてみました。
あ、先に申しますと、僕みたいな適当な人間によるコードとテストなので、「違うよなんか、それは違うよかるね君!」って人は後ろから殴ってください。
結果なんですが、
chrome,safari -> imgを内包したdivをdragする際、dataTransfer.setDragImageが機能しない
firefox -> divをdragできない
となりました。
と、ここで疑問が1つ
ネイティブ HTML5 ドラッグ&ドロップ - HTML5 Rocks
このページのサンプル、divにも関わらずFirefoxで動作しているんです
はて、僕が書いたコードと何が違うんだろうと根掘り葉掘り調べてみたところ、dragstartイベント時にdataTransfer.setDataを実行しているか否かでした。
細かい実装上の仕様については調べて追記しますが、そういうことのようです。
現に、上記コードでdataTransfer.setDataの行をコメントアウトすると、Firefoxで動作しなくなります。
まとめると
・webkit系ブラウザは、img要素を内包する親要素をdragしようとすると、dragstartイベントのdataTransfer.setDragImageが動作しない
・firefoxは、img要素でない、若しくはimg要素を内包しない要素をdragする際、dragstartイベントのハンドラでdataTransfer.setDataを実行しないとdragができない
ということになります。
もし違うという指摘がある場合はそっと声をかけてください(弱気)。