Drag and Drop APIを試す

やりたいこと

  • Drag and Drop APIを触る
  • ElementをDrag and Dropで移動させたい

Elementにdraggable属性を付与してドラッグ可能にする

ブラウザ規定のドラッグ動作可能なElementは以下の3つ

  • テキストの選択範囲
  • 画像
  • リンク

上記以外のElementをドラッグ可能にするには、Elementにdraggable="true"を付与する。

<!DOCTYPE html>
<html lang="jp">
  <style>
    p {
      border: thin solid darkblue;
      padding: 10px;
    }
  </style>
  
   <body>
    <p>ドラッグ不可</p>
    <p id="element1" draggable="true">
      ドラッグ可能
    </p>
  </body>
</html>

Elementがドラッグされた瞬間にEventを発火する

Elementにondragstart属性を付与することで、
ドラッグされた瞬間にEventを発火することができる。

<!DOCTYPE html>
<html lang="jp">
  <title>Drag and Drop API テスト</title>

  <style>
    p {
      border: thin solid darkblue;
      padding: 10px;
    }
  </style>

  <body>
    <p>ドラッグ不可</p>
    <p id="element1" draggable="true" ondragstart="handleDragStart(event);">
      ドラッグ可能
    </p>
  </body>

  <script>
    function handleDragStart(e) {
      console.log("Drag Start");
    }
  </script>
</html>

Elementがドロップされた瞬間にEventを発火する

Elementをドロップしたいエリアにondrop属性を付与することで、
ドロップされた瞬間にEventを発火する。

また、ondragover属性にevent.preventDefault();を設定する。
ドラッグ状態のElementがドロップ可能なElementの上に重なったとき、
デフォルトアクションを抑制する。

参考 MDN - Event.preventDefault()

<!DOCTYPE html>
<html lang="jp">
  <title>Drag and Drop API テスト</title>

  <style>
    p {
      border: thin solid darkblue;
      padding: 10px;
    }

    div {
      margin: 0em;
      padding: 2em;
      border: thin solid red;
    }
  </style>

  <body>
    <p>ドラッグ不可</p>
    <p id="element1" draggable="true" ondragstart="handleDragStart(event);">
      ドラッグ可能
    </p>
    <div
      id="target"
      ondrop="handleDrop(event);"
      ondragover="event.preventDefault();"
    >
      ドロップエリア
    </div>
  </body>

  <script>
    function handleDragStart(e) {
      console.log("Drag Start");
    }

    function handleDrop(e) {
      console.log("Drop");
    }
  </script>
</html>

ドラッグEventとドロップEventでDataTransferオブジェクトの設定を行う

ドラッグ開始時に発火されるEventにe.dataTransfer.setData("text/plain", e.target.id);を記述する。
これにより、ドラッグ開始時に、ドラッグ対象のElement情報をDataTransferオブジェクトに設定することができる。

ドロップ時に発火されるイベントには、DataTransferオブジェクトからドラッグしているElementの情報を取得して、appendChildメソッドで親Elementの子に追加する処理を追加する。
また、clearDataメソッドでDataTransferオブジェクトをクリアしておく。

<!DOCTYPE html>
<html lang="jp">
  <title>Drag and Drop API テスト</title>

  <style>
    p {
      border: thin solid darkblue;
      padding: 10px;
    }

    div {
      margin: 0em;
      padding: 2em;
      border: thin solid red;
    }
  </style>

  <body>
    <p>ドラッグ不可</p>
    <p id="element1" draggable="true" ondragstart="handleDragStart(event);">
      ドラッグ可能
    </p>
    <div
      id="target"
      ondrop="handleDrop(event);"
      ondragover="event.preventDefault();"
    >
      ドロップエリア
    </div>
  </body>

  <script>
    function handleDragStart(e) {
      console.log("Drag Start");
      e.dataTransfer.setData("text/plain", e.target.id);
    }

    function handleDrop(e) {
      console.log("Drop");
      var data = e.dataTransfer.getData("text");
      e.target.appendChild(document.getElementById(data));
      e.dataTransfer.clearData();
    }
  </script>
</html>

以上で(最小単位の)Drag and Drop APIを試せる

参考
MDN - HTML ドラッグ&ドロップ API
html5rocks - ネイティブ HTML5 ドラッグ&ドロップ