HTML ドラッグ&ドロップ API

HTML ドラッグ & ドロップインターフェイスにより、アプリケーションはブラウザーでドラッグ&ドロップ機能を使用することができます。ユーザーはマウスでドラッグ可能な要素を選択し、その要素をドロップ可能な要素へドラッグし、マウスボタンを離すことでドロップすることができます。ドラッグ操作の間、ドラッグ可能な要素の半透明の表示がマウスポインターに続きます。

ウェブサイト、拡張機能、XUL アプリケーションでは、ドラッグ可能にできる要素の種類、ドラッグ可能な要素が生成するフィードバックの種類、およびドロップ可能な要素をカスタマイズできます。

この HTML ドラッグ&ドロップの概要では、インターフェイスの説明、アプリケーションにドラッグ&ドロップのサポートを追加するための基本的なステップ、およびインターフェイスの相互運用性の要約が含まれています。

ドラッグイベント

HTML ドラッグ&ドロップ では DOM イベントモデルマウスイベント を継承した ドラッグイベント を使います。典型的なドラッグ操作は ユーザーがドラッグ可能な要素を選択したときと、ドロップ可能な要素に要素をドラッグしたとき、ドラッグ可能な要素を離したときに開始します。

ドラッグ操作のあいだ、いくつかのイベント種類が発火し、そのうちいくつかはdragdragover イベントのように、複数発火することもあります。

おのおのの ドラッグイベントタイプには関連したグローバルイベントハンドラがあります:

イベント On イベントハンドラ 発火する条件…
drag ondrag …ドラッグ項目 (要素や選択テキスト) がドラッグされた場合
dragend ondragend …ドラッグ操作の終了 (マウスボタンを話したり、Esc キーを押したりした場合。詳しくはドラッグの終了を参照してください。)
dragenter ondragenter …ドラッグ項目が無効なドロップ対象に入った場合(Specifying Drop Targets を見てください)
dragexit ondragexit …要素がドラッグ操作の選択対象でなくなった場合
dragleave ondragleave …ドラッグ項目が無効なドロップ対象を離れた場合
dragover ondragover …ドラッグ項目が有効なドロップ対象にドラッグされた場合、数百ミリ秒ごとに
dragstart ondragstart …ユーザーが項目をドラッグ開始した場合(Starting a Drag Operation を見てください)
drop ondrop …項目が有効なドロップ対象にドロップされた場合(Performing a Drop を見てください)

dragstartdragend イベントは、OS からブラウザーにファイルをドラッグしたときには発火しません。

インターフェイス

HTML ドラッグとドロップのインターフェイスは DragEvent, DataTransfer, DataTransferItem DataTransferItemListです。

DragEvent インターフェイスにはコンストラクタとDataTransfer オブジェクトである dataTransfer プロパティがあります。

DataTransfer オブジェクトはドラッグイベントの状態、例えば(copymove のような)ドラッグの種類や、ドラッグのデータ (1 つ以上の項目)や、各ドラッグ項目の MIME タイプのようなものを含んでいます。DataTransfer オブジェクトにはドラッグデータを追加・削除するメソッドもあります。

DragEventDataTransfer インターフェイスは、アプリケーションに HTML ドラッグ&ドロップ能力を追加する唯一のものです。しかし、Firefox ではDataTransferオブジェクトへのGecko-specific extensions をサポートし、この拡張機能は Firefox でのみ動作します。

それぞれのDataTransfer オブジェクトには items プロパティがあり、これは DataTransferItem オブジェクトのlist です。DataTransferItem オブジェクトは単一のドラッグ項目を表し、それぞれが kind プロパティ (stringfile の値を取る) と項目の MIME タイプを表す type プロパティを持ちます。DataTransferItem オブジェクトにはドラッグ項目のデータを取得するメソッドもあります。

DataTransferItemList オブジェクトは DataTransferItem オブジェクトのリストです。このリストオブジェクトはリストにドラッグ項目を追加したり、リストからドラッグ項目を削除したり、ドラッグ項目のリストをクリアするメソッドを持ちます。

DataTransferDataTransferItem インターフェイスの主な違いは、前者が同期のgetData() メソッドを使ってドラッグ項目のデータにアクセスするのに対し、後者は代わりに非同期のgetAsString() メソッドを使うことです。.

記: DragEventDataTransfer はデスクトップブラウザーでは広くサポートされていますが、DataTransferItemDataTransferItemList インターフェイスには限定されたブラウザーサポートのみです。相互接続性について、より詳しくは Interoperability を見てください。

Gecko-特有のインターフェイス

Mozilla と Firefox は、標準のドラッグ&ドロップのモデルに含まれていないいくつかの機能に対応しています。複数の項目や、文字列以外のデータ (ファイルなど) をドラッグしたりする補助になる便利な関数があります。詳しくは複数の項目のドラッグ&ドロップを参照してください。加えて、DataTransfer リファレンスページを見るとすべての Gecko固有プロパティGecko固有メソッドがわかります。

基本

この節は、アプリにドラッグ&ドロップ機能を追加する基本手順のまとめです。

ドラッグ可能なものを特定する

要素をドラッグ可能 とするには draggable 属性と ondragstart のグローバルイベントハンドラを追加することが求められ、そのコード例は以下です:

<script>
function dragstart_handler(ev) {
 // Add the target element's id to the data transfer object
 ev.dataTransfer.setData("text/plain", ev.target.innerText);
}
</script>

<p id="p1" draggable="true" ondragstart="dragstart_handler(event)">This element is draggable.</p>

詳しくは draggable attribute referenceDrag operations guide を見てください。

ドラッグするデータの定義

アプリケーションは、ドラッグ操作にいくつでもデータ項目を含めることが自由にできます。各データ項目は特定 typestring —よくあるのは text/html のような MINE タイプです。

ドラッグイベント は イベントデータを格納するdataTransfer プロパティを持ちます。このプロパティ (これは DataTransfer オブジェクトです) にはドラッグデータを管理するメソッドもあります。setData() メソッドはドラッグデータに項目を追加するのに使用され、その例は下記の通りです。

function dragstart_handler(ev) {
  // Add different types of drag data
  ev.dataTransfer.setData("text/plain", ev.target.innerText);
  ev.dataTransfer.setData("text/html", ev.target.outerHTML);
  ev.dataTransfer.setData("text/uri-list", ev.target.ownerDocument.location.href);
}

ドラッグ&ドロップで使用される一般的なデータ型の一覧 (テキスト、HTML、リンク、ファイルなど) については、推奨されるドラッグ型をご覧ください。ドラッグデータについて詳しくは、ドラッグデータをご覧ください。

ドラッグ画像の定義

既定では、ブラウザーはドラッグ操作中にポインターの横に現れる画像を提供します。しかし、アプリケーションは setDragImage() メソッドにてカスタム画像を定義できて、その例は下記の通りです。

function dragstart_handler(ev) {
  // Create an image and then use it for the drag image.
  // NOTE: change "example.gif" to a real image URL or the image 
  // will not be created and the default drag image will be used.
  var img = new Image(); 
  img.src = 'example.gif'; 
  ev.dataTransfer.setDragImage(img, 10, 10);
}

ドラッグフィードバックイメージについてより詳しく学びたい場合は、ドラッグフィードバックイメージの設定を参照してください。

ドラッグ効果の定義

dropEffect プロパティはドラッグ&ドロップ操作中のユーザーへのフィードバックを管理するのに使います。よくあるのはドラッグ中にどのカーソルをブラウザーが表示するかに影響します。例えば、ユーザーがドロップターゲット上に持ってきたとき、ブラウザーのカーソルは起こる動作の種類を示すことがあります。

効果は次のように定義されます:

  1. copy はドラッグデータが現在の場所からドロップされる場所にコピーされることを示します。
  2. move はドラッグデータが現在の場所からドロップされる場所に移動されることを示します。
  3. link はドラッグデータが元からドロップ先にある種の関連や接続が作成されることを示します。

ドラッグ操作の間、ある効果はある場所にだけ許可されることを示すために、ドラッグ効果は変更される場合があります。

下記の例はこのプロパティの使い方を示します。

function dragstart_handler(ev) {
  ev.dataTransfer.dropEffect = "copy";
}

詳しくは Drag Effects を見てください。

ドロップゾーンの定義

既定では、HTML要素にドロップしたときに、ブラウザーは何か起こるのを防いでいます。この動作を変更して要素をドロップゾーンドロップ可能にするには、要素はondragoverondrop イベントハンドラ属性を持たねばなりません。以下の例はこの属性の使い方と、各属性の基本的なイベントハンドラを示しています。

<script>
function dragover_handler(ev) {
 ev.preventDefault();
 ev.dataTransfer.dropEffect = "move";
}
function drop_handler(ev) {
 ev.preventDefault();
 // Get the id of the target and add the moved element to the target's DOM
 var data = ev.dataTransfer.getData("text/plain");
 ev.target.appendChild(document.getElementById(data));
}
</script>

<p id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Zone</p>

各ハンドラが preventDefault() を呼んで、このイベントが(タッチイベントポインターイベントなどに)追加で処理されることを防いでいるのに注意してください

より詳しくは、Specifying Drop Targets を見てください。

ドロップ効果を扱う

drop イベントのハンドラでは、アプリケーション固有の方法でドラッグデータを自由に処理できます。典型的にはアプリケーションはgetData() メソッドでドラッグ項目を取得して、そのようよ処理します。加えて、アプリケーションのセマンティクスは dropEffect の値や modifier キーの状態により異なります。

下記の例では、ドラッグデータからソース要素の id を取得し、id を使ってソース要素をドロップ要素に移動するドロップハンドラのを示しています。

<script>
function dragstart_handler(ev) {
 // Add the target element's id to the data transfer object
 ev.dataTransfer.setData("application/my-app", ev.target.id);
 ev.dataTransfer.dropEffect = "move";
}
function dragover_handler(ev) {
 ev.preventDefault();
 ev.dataTransfer.dropEffect = "move"
}
function drop_handler(ev) {
 ev.preventDefault();
 // Get the id of the target and add the moved element to the target's DOM
 var data = ev.dataTransfer.getData("application/my-app");
 ev.target.appendChild(document.getElementById(data));
}
</script>

<p id="p1" draggable="true" ondragstart="dragstart_handler(event)">This element is draggable.</p>
<div id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Zone</div>

より詳しくは、Performing a Drop を見てください。

ドラッグの終了

ドラッグ操作の終わりに、dragend イベントがソース要素 — ドラッグ開始のターゲット — で発火します。このイベントはドラッグが完了したりキャンセルされたいずれでも発火します。dragend イベントハンドラは dropEffect プロパティの値をチェックしてドラッグ操作が成功したか否かを決定できます。

ドラッグ操作の終了を扱うことの詳細は、Finishing a Drag を見てください。

相互運用性

DataTransferItem インターフェイスのブラウザー互換性テーブルに見られるように、ドラッグ&ドロップの相互接続性はデスクトップブラウザーでは相対的に広いです(サポートの少ないDataTransferItemDataTransferItemList インターフェイスを覗いて)。このデータはモバイルブラウザーでのドラッグ&ドロップサポートはとても低いことも示しています。

例とデモ

関連情報