JavaScriptのドラッグ&ドロップのイベント発生タイミングについて - JavaScript

JavaScriptのDrag&Dropのイベント発生タイミングについて紹介します。

概要

JavaScriptでのドラッグ&ドロップのイベントには下記があります。
  • dragstart
  • dragenter
  • dragover
  • dragleave
  • drop
  • dragend
イベントの種類が多いためどのタイミングでイベントが発生するのかわかりにくい部分もあります。この記事ではドラッグ&ドロップのイベント発生タイミングを調べます。

プログラム (イベントの発生と順序)

どのタイミングでイベントが発生するかを確認します。

コード

下記のHTMLファイルを作成します。
DragEvent.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
  <link rel="stylesheet" href="DragEvent.css" />

  <script type="text/javascript">
    var outputTextBox;
    function onload() {
      outputTextBox = document.getElementById('outputText');
      
      var elem = document.getElementById('DragItem');
      elem.addEventListener('dragstart', onDragStart, false);
      elem.addEventListener('dragenter', onDragEnter, false);
      elem.addEventListener('dragover', onDragOver, false);
      elem.addEventListener('dragleave', onDragLeave, false);
      elem.addEventListener('drop', onDragDrop, false);
      elem.addEventListener('dragend', onDragEnd, false);

      var zone = document.getElementById('DropItem');
      zone.addEventListener('dragstart', onTargetDragStart, false);
      zone.addEventListener('dragenter', onTargetDragEnter, false);
      zone.addEventListener('dragover', onTargetDragOver, false);
      zone.addEventListener('dragleave', onTargetDragLeave, false);
      zone.addEventListener('drop', onTargetDragDrop, false);
      zone.addEventListener('dragend', onTargetDragEnd, false);
   }

    function onDragStart(e) {
      outputTextBox.value = outputTextBox.value+"DragItem : dragstart\r\n";
    }

    function onDragEnter(e) {
      outputTextBox.value = outputTextBox.value +"DragItem : dragenter\r\n";
    }

    function onDragOver(e) {
      outputTextBox.value = outputTextBox.value +"DragItem : dragover\r\n";
    }

    function onDragLeave(e) {
      outputTextBox.value = outputTextBox.value +"DragItem : dragleave\r\n";
    }

    function onDragDrop(e) {
      outputTextBox.value = outputTextBox.value +"DragItem : drop\r\n";
   }

    function onDragEnd(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragend\r\n";
    }

    function onTargetDragStart(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragenter\r\n";
    }

    function onTargetDragEnter(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragover\r\n";
    }

    function onTargetDragOver(e) {
      e.preventDefault();
      outputTextBox.value = outputTextBox.value + "DropZone : dragover\r\n";
    }

    function onTargetDragLeave(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragleave\r\n";
    }

    function onTargetDragDrop(e) {
      e.preventDefault();
      outputTextBox.value = outputTextBox.value +"DropZone : drop\r\n";
    }

    function onTargetDragEnd(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : end\r\n";
    }
  </script>
</head>
<body onload="onload();">
  <div id="DragItem" draggable="true">ドラッグ要素です</div>

  <hr />
  <div id="DropItem">ドロップ枠です</div>

  <hr />
  <textarea id="outputText"></textarea> 
</body>
</html>
DragEvent.css
#DragItem{
    width:180px;
    border: 1px solid #ff6a00
}

#DropItem {
    margin:32px 0 32px 0;
    width:360px;
    height:200px;
    border: 1px solid #808080;
    background-color:#f3f3f3;
}

#outputText{
    width:680px;
    height:240px;
}

解説

画面に2つのdiv枠とメッセージ出力用のTextAreaを配置します。2つのdiv枠はidがDragItemのほうがドラッグされる要素、DropItemの枠がドロップされる枠になります。両方の枠に、先のdragstart, dragenter, dragover, dragleave, drop, dragend のイベントハンドラを設定します。イベントハンドラでは、メッセージをTextAreaに出力するコードを記述します。ドラッグ関係のイベントが発生すると、テキストボックスにログが記録される動作になります。
また、DropItemではドロップが受け入れれらるよう、dragover, drop イベントではpreventDefault() メソッドを呼び出すようにしています。

実行結果

上記のHTMLファイルをWebブラウザで表示します。下図のページが表示されます。


[ドラッグ要素です]の項目をドラッグします。DragItemのdragstartイベントが発生し、続いて、dragenterイベントが発生し、その後ドラッグ要素が移動するごとに、dragoverイベントが発生します。


ドラッグを終了すると、DragItemのdragleaveイベントが発生し、その後dragendイベントが発生し、ドラッグ&ドロップ操作が終了します。


実行結果

先のコードではdragoverイベントが大量に発生するため、onDragOverのテキストボックスへの出力をコメントアウトします。
    function onDragOver(e) {
      //outputTextBox.value = outputTextBox.value +"DragItem : dragover\r\n";
    }

再度、HTMLファイルをWebブラウザで表示します。[ドラッグ要素です]の項目をドラッグします。DragItemのdragstartイベントが発生し、続いて、dragenterイベントが発生します。ドラッグして、ドラッグされたオブジェクトが[ドラッグ要素です]の項目から出ると、dragleaveイベントが発生します。


そのままドラッグを終了すると、dragendイベントが発生します。


また、ドラッグした要素がドロップ枠に入ると、ドロップ枠(DropZone)のdragoverイベントが発生します。


ドロップ枠内で要素をドロップすると、ドロップ枠(DropZone)のdropイベントが発生し、その後、DragItemのdragendイベントが発生します。

プログラム (引数のtarget値)

イベントに渡される引数のtaregetの値を確認します。

コード

下記のコードを記述します。CSSファイルは先ほどのコードと同じものを利用しています。
DragEvent2.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
  <link rel="stylesheet" href="DragEvent.css" />

  <script type="text/javascript">
    var outputTextBox;
    function onload() {
      outputTextBox = document.getElementById('outputText');
      
      var elem = document.getElementById('DragItem');
      elem.addEventListener('dragstart', onDragStart, false);
      elem.addEventListener('dragenter', onDragEnter, false);
      elem.addEventListener('dragover', onDragOver, false);
      elem.addEventListener('dragleave', onDragLeave, false);
      elem.addEventListener('drop', onDragDrop, false);
      elem.addEventListener('dragend', onDragEnd, false);

      var zone = document.getElementById('DropItem');
      zone.addEventListener('dragstart', onTargetDragStart, false);
      zone.addEventListener('dragenter', onTargetDragEnter, false);
      zone.addEventListener('dragover', onTargetDragOver, false);
      zone.addEventListener('dragleave', onTargetDragLeave, false);
      zone.addEventListener('drop', onTargetDragDrop, false);
      zone.addEventListener('dragend', onTargetDragEnd, false);
   }

    function onDragStart(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragstart / " + e.target.innerHTML +"\r\n";
    }

    function onDragEnter(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragenter / " + e.target.innerHTML + "\r\n";
    }

    function onDragOver(e) {
      outputTextBox.value = outputTextBox.value +"DragItem : dragover / " + e.target.innerHTML +"\r\n";
    }

    function onDragLeave(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragleave / " + e.target.innerHTML + "\r\n";
    }

    function onDragDrop(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : drop / " + e.target.innerHTML + "\r\n";
   }

    function onDragEnd(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragend / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragStart(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragenter / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragEnter(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragover / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragOver(e) {
      e.preventDefault();
      outputTextBox.value = outputTextBox.value + "DropZone : dragover / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragLeave(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragleave / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragDrop(e) {
      e.preventDefault();
      outputTextBox.value = outputTextBox.value + "DropZone : drop / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragEnd(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : end / " + e.target.innerHTML + "\r\n";
    }
  </script>
</head>
<body onload="onload();">
  <div id="DragItem" draggable="true">ドラッグ要素です</div>

  <hr />
  <div id="DropItem">ドロップ枠です</div>

  <hr />
  <textarea id="outputText"></textarea> 
</body>
</html>

解説

先のコードと同じですが、メッセージ出力時に、e.target.innerHTMLの値もテキストボックスに出力します。e.targetにどのオブジェクトが設定されているかが確認できます。

実行結果

上記のHTMLファイルをWebブラウザで表示します。下図のページが表示されます。


[ドラッグ要素です]の枠をドラッグします。先と同様にdragstart, dragenter, dragover のイベントが発生します。メッセージ末尾のinnerHTMLの値が「ドラッグ要素です」となっていることから、イベント引数のtargetはドラッグされる要素であることがわかります。


ドラッグが終了されると、dragleave, dragendイベントが発生します。こちらも、イベント引数のtargetはドラッグされる要素です。


続いて先のコードと同様に、ドラッグされるオブジェクトのdragover のイベントのメッセージ出力をコメントアウトします。ドラッグ要素をドラッグし、ドラッグ要素から外に出ると、dragleaveイベントが発生します。この場合も引数のtargetには、ドラッグされる要素が設定されています。




ドラッグ要素がドロップ枠に入ると、DropZoneのdragoverイベントが発生します。DropZoneのdragoverイベントでは、targetはドロップされる枠の要素が設定されています。


ドロップ枠内にドラッグ要素をドロップします。DropZoneのdropイベントが発生します。こちらも、targetはドロップされる枠の要素が設定されています。


ドラッグ&ドロップイベントの引数のtargetの値にどのオブジェクトが設定されるのかを確認できました。

参考 : addEventListener()メソッドを利用せず、タグの属性値に記述する場合

上記の例はaddEventListener() メソッドを呼び出して実行時に要素にイベントハンドラを設定しました。addEventHandler()メソッドを呼び出さず、タグの属性にイベントを記述する方法でも実装できます。

addEventListenerのイベント名と属性に記述するイベント名との対応は以下になります。

addEventListernerのイベント名属性のイベント名
dragstartondragstart
dragenterondragenter
dragoverondragover
dragleaveondragleave
dropondrop
dragendondragend

DragEvent3.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
  <link rel="stylesheet" href="DragEvent.css" />

  <script type="text/javascript">
    var outputTextBox;
    function onload() {
      outputTextBox = document.getElementById('outputText');
   }

    function onDragStart(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragstart / " + e.target.innerHTML + "\r\n";
    }

    function onDragEnter(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragenter / " + e.target.innerHTML + "\r\n";
    }

    function onDragOver(e) {
      outputTextBox.value = outputTextBox.value +"DragItem : dragover / " + e.target.innerHTML +"\r\n";
    }

    function onDragLeave(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragleave / " + e.target.innerHTML + "\r\n";
    }

    function onDragDrop(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : drop / " + e.target.innerHTML + "\r\n";
   }

    function onDragEnd(e) {
      outputTextBox.value = outputTextBox.value + "DragItem : dragend / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragStart(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragenter / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragEnter(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragover / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragOver(e) {
      e.preventDefault();
      outputTextBox.value = outputTextBox.value + "DropZone : dragover / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragLeave(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : dragleave / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragDrop(e) {
      e.preventDefault();
      outputTextBox.value = outputTextBox.value + "DropZone : drop / " + e.target.innerHTML + "\r\n";
    }

    function onTargetDragEnd(e) {
      outputTextBox.value = outputTextBox.value + "DropZone : end / " + e.target.innerHTML + "\r\n";
    }
  </script>
</head>
<body onload="onload();">
  <div id="DragItem" draggable="true" 
       ondragstart="onDragStart(event)"
       ondragenter="onDragEnter(event)"
       ondragover="onDragOver(event)"
       ondragleave="onDragLeave(event)"
       ondrop="onDragDrop(event)"
       ondragend="onDragEnd(event)">ドラッグ要素です</div>

  <hr />
  <div id="DropItem"
       ondragstart="onTargetDragStart(event)"
       ondragenter="onTargetDragEnter(event)"
       ondragover="onTargetDragOver(event)"
       ondragleave="onTargetDragLeave(event)"
       ondrop="onTargetDragDrop(event)"
       ondragend="onTargetDragEnd(event)">ドロップ枠です</div>

  <hr />
  <textarea id="outputText"></textarea> 


</body>
</html>

このページのキーワード
  • JSのドラッグ&ドロップのイベント発生タイミングについて
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2020-04-06
作成日: 2019-03-03
iPentec all rights reserverd.