任意のDOM要素同士 を ドラッグ&ドロップ(前編)

0 件のコメント

HTML5のドラッグ&ドロップとはちょっと違う… HTMLの任意DOM要素同士でドラッグ&ドロップしたいんだよね。。 どのイベント使っていいかわからないから、とりあえず「前編」として調査です。

ブラウザ別イベントの発生順序

次のような状況(プログラム)を想定して、IE、Chr(Chrome)、FF(FireFox)において どのような順序でイベントが発生するか調査してみた。

  1. とりあえず、一通りのイベントをドラッグ対象となる任意のDOM要素(source)に追加。
  2. とりあえず、一通りのイベントをドロップ先となる任意のDOM要素(target)に追加。
  3. ドラッグ対象となる任意のDOM要素(source)を mousedown
  4. mousedown された 任意のDOM要素(source) のクローン(clone)を作成
  5. 作成したクローン(clone)を body 末尾へ追加
  6. 作成したクローン(clone)に style を追加
  7. 任意のDOM要素(source)に style を追加
  8. mousemove で 作成したクローン(clone)を移動
  9. ドロップ先となる任意のDOM要素(target)上で作成したクローン(clone)を mouseup
  10. 作成したクローン(clone)を body 末尾から削除

※上記シーケンスは若干適当に書かれているので、実際とは異なる部分があります。

調査結果

基本的な操作のとき(ゆっくり操作したとき)は、次の表のようなイベント順になる。 色をつけた行が「使えそうかな?」と思えるイベントとタイミング。 document.onmouseup の後、target.onmouseenter または target.onmouseover が発生すると、どこへドロップされたと見なせる。

実行シーケンス DOM要素 イベント IE8 IE9 Ch23 FF14
1 source mousedown o o o o
2 document mousedown o o o o
3 source mouseleave o o o o
4 source mouseup o o o o
5 clone mouseleave o
6 clone mouseup o
7 document mouseup o o o o
8 document mousemove o o    
9 source mouseover o
10 clone mouseenter o o o
11 clone mouseover o o o o
12 document mouseover o o o o
13 document mousemove o o o o
14 source mouseup o
15 clone mouseup o o o o
16 document mouseup o o o o
17 document mousemove o o
18 clone mouseleave o
19 clone mouseup o
20 target mouseenter o o o o
21 target mouseover o o o o
22 document mouseenter o o
23 document mouseover o o o o
24 document mousemove o o o  
※IE = Internet Explorer、Ch = Chrome、FF = Firefox

マウス移動を素早く行うと、描画がが追いつかず、別のイベントが発生してしまう。 次の表にあげるいずれかが、ランダムに発生する。 IE8だけ、発生するタイミングが怪しいけど、発生するイベントの種類や数は似ている (というか、ランダム発生だから何ともいえない。)。

実行シーケンス DOM要素 イベント IE8 IE9 Ch23 FF14
1 clone mouseenter o o o o
2 clone mouseover o o o o
3 clone mouseleave o o o o
4 clone mouseup o o o o
※IE = Internet Explorer、Ch = Chrome、FF = Firefox
実行シーケンス DOM要素 イベント IE8 IE9 Ch23 FF14
1 target mouseenter o o o o
2 target mouseover o o o o
3 target mouseleave o o o o
4 target mouseup o o o o
※IE = Internet Explorer、Ch = Chrome、FF = Firefox

結局…

どいうイベントを監視、実装したら良さそうか?

  1. source.onmousedown:ドラッグ開始
  2. document.onmousemove:ドラッグ中のエフェクト
  3. document.onmouseup:ドラッグ終了。ドロップしたフラグ。
  4. ドロップしたフラグが立っているとき、
    • target.onmouseenter または target.onmouseover:ドロップされた
    • document.onmouseover:ドロップされなかった
  5. 後始末(イベントハンドラ、フラグ類)
といった感じでいけるのではないか?…と思うが、実際できるかどうかは試してからのお楽しみ。