diff options
Diffstat (limited to 'files/ja/dragdrop')
-rw-r--r-- | files/ja/dragdrop/drag_operations/index.html | 350 | ||||
-rw-r--r-- | files/ja/dragdrop/dragging_and_dropping_multiple_items/index.html | 108 | ||||
-rw-r--r-- | files/ja/dragdrop/index.html | 9 | ||||
-rw-r--r-- | files/ja/dragdrop/recommended_drag_types/index.html | 228 |
4 files changed, 695 insertions, 0 deletions
diff --git a/files/ja/dragdrop/drag_operations/index.html b/files/ja/dragdrop/drag_operations/index.html new file mode 100644 index 0000000000..4739714e52 --- /dev/null +++ b/files/ja/dragdrop/drag_operations/index.html @@ -0,0 +1,350 @@ +--- +title: ドラッグ操作 +slug: DragDrop/Drag_Operations +tags: + - Advanced + - Guide + - HTML + - HTML5 + - XUL + - ドラッグ&ドロップ +translation_of: Web/API/HTML_Drag_and_Drop_API/Drag_operations +--- +<p>{{DefaultAPISidebar("HTML Drag and Drop API")}}</p> + +<p>以下は、ドラッグ&ドロップ操作が行われる時の各段階についての解説です。</p> + +<p class="note">この文書で記述されているドラッグ操作は {{domxref("DataTransfer")}} インターフェイスを使用します。この文書では {{domxref("DataTransferItem")}} インターフェイスや {{domxref("DataTransferItemList")}} インターフェイスは説明<em>しません</em>。</p> + +<h2 id="draggableattribute" name="draggableattribute">draggable 属性</h2> + +<p>ウェブページにおいては、既定のドラッグ&ドロップの挙動が使われる場合がいくつかあります。文字列の選択範囲、画像、リンクなどのドラッグなどがこれにあたります。画像かリンクがドラッグされた時は、画像もしくはリンク先の URL がドラッグデータとして設定され、ドラッグ操作が始まります。その他の要素は、既定のドラッグ操作が行われるためには選択範囲に含まれていなければなりません。実際の様子を確認するには、ウェブページの一部を選択して、その上でマウスのボタンを押下し、そのまま選択範囲をドラッグしてください。ドラッグ中、選択範囲の内容を半透明で描画した物がマウスポインターに伴って表示されるでしょう。ただしこの挙動は、ドラッグされたデータを加工するイベントリスナーが存在しない場合の、既定のドラッグの挙動によるものです。</p> + +<p>HTML では、画像、リンク、選択範囲の上での既定の動作を除くと、他の要素は初期状態ではドラッグできません。 <a href="/ja/docs/Mozilla/Tech/XUL">XUL</a> では、すべての要素がドラッグ可能です。</p> + +<p>上記以外の他の HTML 要素をドラッグできるようにするには、以下の3つの事をしなくてはなりません。</p> + +<ul> + <li>ドラッグできるようにしたい要素の <code>{{htmlattrxref("draggable")}}</code> 属性の値を <code>true</code> に設定する。</li> + <li><code>{{event("dragstart")}}</code> イベントにリスナーを設定し、そのリスナーの中でドラッグデータを設定する。</li> + <li>上記で定義されたリスナーの中で{{domxref("DataTransfer.setData","ドラッグデータを設定する")}}。</li> +</ul> + +<p>以下は、コンテンツの一部がドラッグできるようにする例です。</p> + +<pre class="brush: html"><div draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'この文字列はドラッグができます')"> + この文字列はドラッグが<strong>できます</strong>。 +</div> +</pre> + +<p><code>{{htmlattrxref("draggable")}}</code> 属性を true に設定すると、その要素はドラッグできるようになります。この属性が設定されていない、あるいは false に設定されている場合、その要素をドラッグする事はできず、代わりにテキストが選択されるでしょう。 <code>{{htmlattrxref("draggable")}}</code> 属性は画像やリンクを含めてあらゆる要素に設定できます。ただし、画像とリンクについてだけは初期値がtrueとなっていますので、実際にこれらの要素で使う場合は、要素をドラッグできないようにするために <code>{{htmlattrxref("draggable")}}</code> 属性に <code>false</code> を設定するという場合がほとんどでしょう。</p> + +<p>要素がドラッグ可能になった場合、文字列やその要素に含まれている他の要素が、マウスによるクリックやドラッグなどの通常の操作では選択する事ができなくなることに注意してください。ユーザーが文字列を選択するには、通常の操作の代わりに、 Alt キーを押しながらマウスで選択するか、キーボードで操作を行う必要があります。</p> + +<p>XUL 要素では、 <code>{{htmlattrxref("draggable")}}</code> 属性を使う必要はありません。全ての XUL 要素はドラッグ可能です。</p> + +<pre class="brush: html"><button label="ドラッグしてください" ondragstart="event.dataTransfer.setData('text/plain', '「ドラッグしてください」ボタン');"> +</pre> + +<h2 id="dragstart" name="dragstart">ドラッグ操作の開始</h2> + +<p>この例では、 <code>{{domxref("GlobalEventHandlers.ondragstart","ondragstart")}}</code> 属性を使って、 {{event("dragstart")}} イベントのためのリスナーが追加されています。</p> + +<pre class="brush: html"><div draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'この文字列はドラッグができます')"> + この文字列はドラッグが<strong>できます</strong>。 +</div> +</pre> + +<p>ユーザーがドラッグを開始しようとした時、 {{event("dragstart")}} イベントが発行されます。この例では {{event("dragstart")}} のリスナーは、ドラッグされる要素自身に追加されていますが、他の多くのイベントがそうであるようにドラッグイベントもバブリングしますので、より上位の祖先要素でイベントを監視することもできます。 {{event("dragstart")}} イベントでは、以下で解説している「ドラッグデータ」「フィードバック画像」「ドラッグの種類」を設定することができます。ドラッグデータの指定は必須ですが、多くの状況では、フィードバック画像とドラッグの種類は既定のもので問題ありません。</p> + +<h2 id="dragdata" name="dragdata">ドラッグデータ</h2> + +<p>全ての{{domxref("DragEvent","ドラッグイベント")}}は、ドラッグデータを保持するための {{domxref("DragEvent.dataTransfer","dataTransfer")}} と呼ばれるプロパティを持っています(<code>dataTransfer</code> は {{domxref("DataTransfer")}} オブジェクトの一つです)。</p> + +<p>ドラッグが行われた時には、何がドラッグされているのかを識別するデータが、そのドラッグに対して関連付けられなくてはなりません。例えば、テキストボックスの中の選択された文字列がドラッグされた時は、ドラッグに関連付けられたデータは、文字列それ自体となります。同様に、ウェブページの中のリンクがドラッグされた時は、リンク先の URL がドラッグデータとなります。</p> + +<p>ドラッグデータは、データの型(データの形式)と、データの値の、2つの情報を含んでいます。データの形式はタイプ文字列(テキストデータを示す<a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#text" title="Ja/DragDrop/Recommended Drag Types#text">text/plain</a>などのような)で指定し、データの値は文字列で指定します。ドラッグが開始された時、あなたはデータを型と値の設定で指定するでしょう。ドラッグが行われている間、<font face="Courier New">dragenter</font>および<font face="Courier New">dragover</font>イベントのイベントリスナーにおいて、あなたはデータの型を、ドロップが許可されているかどうかの判定に使うでしょう。具体例としては、リンクのドロップを受け付けるドロップターゲットは、リンクの型である <a href="/ja/docs/DragDrop/Recommended_Drag_Types#link" title="text/uri-list">text/uri-list</a> かどうかを確認するでしょう。dropイベントにおいてはリスナーは、この型の情報を元にドラッグされたデータを取得して、ドロップ位置に挿入するでしょう。</p> + +<p>型は、 <a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#text" title="Ja/DragDrop/Recommended Drag Types#text">text/plain</a> や <a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#image" title="Ja/DragDrop/Recommended Drag Types#image">image/jpeg</a> などのような、 MIME-type に似た形式の文字列で、独自の型を作ることもできます。広く一般的に使われている型の一覧が<a class="internal" href="/Ja/DragDrop/DataTypes" title="Ja/DragDrop/DataTypes">ドラッグ型</a>のページにあります。</p> + +<p>一つのドラッグ操作で、複数の異なる形式のデータを提供できます。この仕組みにより、独自の形式や、その形式のデータを受け取れない要素向けのフォールバック用の形式など、データをより適切な形式で引き渡すことができます。通常、最後のフォールバック先として使われる形式は、 <a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#text" title="Ja/DragDrop/Recommended Drag Types#text">text/plain</a> 型として表される普通のテキストデータです。このデータは元のテキストの単純な文字列となるでしょう。</p> + +<p>データを {{domxref("DragEvent.dataTransfer","dataTransfer")}} に設定するには、 {{domxref("DataTransfer.setData","setData()")}} メソッドを使います。このメソッドは、データの型とデータの値の、2つの引数を取ります。例:</p> + +<pre class="brush: js">event.dataTransfer.setData("text/plain", "ドラッグされたテキスト"); +</pre> + +<p>この例では、データの値は「ドラッグされたテキスト」で、形式は <a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#text" title="Ja/DragDrop/Recommended Drag Types#text">text/plain</a> です。</p> + +<p>データは複数の形式で提供できます。これを実現するには、異なる形式を指定して {{domxref("DataTransfer.setData","setData()")}} メソッドを複数回呼び出します。最も具体的な形式から、具体的でない形式に向けて呼び出します。</p> + +<pre class="brush: js">var dt = event.dataTransfer; +dt.setData("application/x-bookmark", bookmarkString); +dt.setData("text/uri-list", "http://www.mozilla.org"); +dt.setData("text/plain", "http://www.mozilla.org"); +</pre> + +<p>これは、3つの異なる型のデータを追加する例です。最初の型の「application/x-bookmark」は独自の形式です。他のアプリケーションはこの形式をサポートしていないでしょうが、同じウェブサイトやアプリケーションの中の領域同士でのドラッグでは、このような独自の形式を利用できます。また、他の型でもデータを提供することで、このような独自形式をサポートしていない他のアプリケーション向けにも、代替の形式でドラッグできるようになります。「application/x-bookmark」型はそのアプリケーションの中ではより使いやすく詳細な情報を提供できますが、他の型で渡されるデータは、単純な1つの URL もしくは文字列となります。</p> + +<p>なお、この例では <a href="/ja/docs/DragDrop/Recommended_Drag_Types#link" title="text/uri-list">text/uri-list</a> も <a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#text" title="Ja/DragDrop/Recommended Drag Types#text">text/plain</a> も同じデータを含んでいます。このようにすることが多いのですが、こうしなければならない訳ではありません。</p> + +<p>同じ形式で2回データを登録すると、古いデータは新しいデータによって置き換えられますが、データの形式の登録の順番自体は古いデータを登録した時のままになります。</p> + +<p>登録したデータは {{domxref("DataTransfer.clearData","clearData()")}} メソッドによって削除できます。このメソッドは、削除するデータの形式を引数として求めます。</p> + +<pre class="brush: js">event.dataTransfer.clearData("text/uri-list"); +</pre> + +<p>{{domxref("DataTransfer.clearData","clearData()")}} メソッドの引数によるデータ形式の指定は省略可能です。データの形式が指定されなかった時は、全ての型のデータが削除されます。ドラッグ開始時にデータが1つも登録されなかった場合、もしくは後の処理で全てのデータが削除された場合、ドラッグ操作は発生しません。</p> + +<h2 id="dragfeedback" name="dragfeedback">ドラッグフィードバック画像の設定</h2> + +<p>ドラッグが行われた時、ドラッグ元(dragstartイベントが発行された要素)を元にして OS によって画像が生成され(例えば Windows では半透明の画像になります)、ドラッグしている間マウスポインターに伴って表示されます。この画像は自動的に生成されるため、あなたが用意する必要はありません。しかし、 {{domxref("DataTransfer.setDragImage","setDragImage()")}} によって、独自のドラッグ中のフィードバック画像を指定することができます。</p> + +<pre class="brush: js">event.dataTransfer.setDragImage(image, xOffset, yOffset); +</pre> + +<p>このメソッドは3つの引数を要求します。第1引数は一般的には画像の要素ですが、 canvas 要素やその他の要素を指定することもできます。フィードバック画像は、その画像が画面上で表示される場合と同じ形・原寸大で生成されます。 {{domxref("DataTransfer.setDragImage","setDragImage()")}} の第2、第3引数は画像を表示するマウスポインターからの相対オフセットです。</p> + +<p>文書中に存在しないものをフィードバック画像として使うために、以下の例のようにして、画像や canvas を利用することもできます。</p> + +<pre class="brush: js">function dragWithCustomImage(event) { + var canvas = document.createElementNS("http://www.w3.org/1999/xhtml","canvas"); + canvas.width = canvas.height = 50; + + var ctx = canvas.getContext("2d"); + ctx.lineWidth = 4; + ctx.moveTo(0, 0); + ctx.lineTo(50, 50); + ctx.moveTo(0, 50); + ctx.lineTo(50, 0); + ctx.stroke(); + + var dt = event.dataTransfer; + dt.setData('text/plain', 'ドラッグされるデータ'); + dt.setDragImage(canvas, 25, 25); +} +</pre> + +<p>この例では、 canvas の大きさは幅50ピクセル・高さ50ピクセルで、オフセット値はそれぞれの半分の値(各25ピクセル)となっており、画像はマウスポインターの中央に表示されます(マウスポインターが画像の中央に表示されます)。</p> + +<p>{{h2_gecko_minversion("Using XUL panels as drag images", "9.0")}}</p> + +<p>Gecko の開発者(アドオンまたは Mozilla アプリケーションコードのどちらかを開発している人)の場合、 Gecko 9.0 {{geckoRelease("9.0")}} は XUL {{XULElem("panel")}} 要素をドラッグフィードバック画像として使用することの対応を追加します。 {{domxref("DataTransfer.setDragImage","setDragImage()")}} に {{XULElem("panel")}} 要素に渡すだけです。</p> + +<p>この XUL {{XULElem("panel")}} を考えてみてください。</p> + +<pre class="brush: xml"><<span class="start-tag">panel</span><span class="attribute-name"> id</span>=<span class="attribute-value">"panel" </span><span class="attribute-name">style</span>=<span class="attribute-value">"opacity: 0.6</span><span class="attribute-value">"</span>> + <<span class="start-tag">description</span><span class="attribute-name"> id</span>=<span class="attribute-value">"pb"</span>>Drag Me</<span class="end-tag">description</span>> +</<span class="end-tag">panel</span>> + +<<span class="start-tag">vbox</span><span class="attribute-name"> align</span>=<span class="attribute-value">"start" </span><span class="attribute-name">style</span>=<span class="attribute-value">"border: 1px solid black;" </span><span class="attribute-name">ondragstart</span>=<span class="attribute-value">"startDrag(event)"</span>> + <<span class="start-tag">description</span>>Drag Me</<span class="end-tag">description</span>> +</<span class="end-tag">vbox</span>> +</pre> + +<p>ユーザーが上記の {{XULElem("vbox")}} をクリックしてドラッグを始めると、以下の <code>startDrag()</code> 関数が呼び出されます。</p> + +<pre class="brush: js"><span class="cdata">function startDrag(event) { + event.dataTransfer.setData("text/plain", "<strong>Body</strong>"); + event.dataTransfer.setDragImage(document.getElementById("panel"), 20, 20); +}</span> +</pre> + +<p>これは "<strong>Body</strong>" という文字列が HTML 形式で入った panel をドラッグ画像として使用します。パネルをテキストエディタ―にドロップすると、 "<strong>Body</strong>" という文字列がテキスト中のドロップした場所に挿入されます。</p> + +<h2 id="drageffects" name="drageffects">ドラッグの種類</h2> + +<p>ドラッグを行う時の操作には、いくつかの種類があります。 <code>copy</code> (コピー)はドラッグされているデータが現在の場所からドロップ先の場所にコピーされることを示します。 <code>move</code> (移動)はドラッグされているデータがドロップ先に移動されることを示し、 <code>link</code> (リンク)はドラッグ元とドロップ先の場所との間に何らかの形での関連付けや繋がりが作られることを示します。</p> + +<p><code>{{event("dragstart")}}</code> イベントのリスナーにおいて、 {{domxref("DataTransfer.effectAllowed","effectAllowed")}} プロパティに値を設定することで、 ドラッグ元について上記の3つの操作のうちどれが許可されているのかを示すことができます。</p> + +<pre class="brush: js">event.dataTransfer.effectAllowed = "copy"; +</pre> + +<p>この例では、コピーのみが許可されています。複数の種類の操作を組み合わせることもできます。</p> + +<dl> + <dt>none</dt> + <dd>どの操作も許可されていない(ドロップを禁止)。</dd> + <dt>copy</dt> + <dd>コピーのみが許可されている。</dd> + <dt>move</dt> + <dd>移動のみが許可されている。</dd> + <dt>link</dt> + <dd>リンクのみが許可されている。</dd> + <dt>copyMove</dt> + <dd>コピーまたは移動のみが許可されている。</dd> + <dt>copyLink</dt> + <dd>コピーまたはリンクのみが許可されている。</dd> + <dt>linkMove</dt> + <dd>リンクまたは移動のみが許可されている。</dd> + <dt>all</dt> + <dd>コピー、移行、リンクの全ての操作が許可されている。</dd> +</dl> + +<p>上に列挙されている値のいずれかと全く等しい値だけが利用可能であることに注意してください。 {{domxref("DataTransfer.effectAllowed","effectAllowed")}} プロパティを <code>copyMove</code> に設定すると、コピーや移動の操作を許可しますが、ユーザーがリンク操作を行うことを防ぐことができます。 {{domxref("DataTransfer.effectAllowed","effectAllowed")}} プロパティを変更しない場合、「all」が指定された時と同様に、全ての操作が許可されます。ですので、特定の種類の操作を除外したい場合を除いて、プロパティの値を手動で設定する必要はありません。</p> + +<p>ドラッグ操作の間、 <code>{{event("dragenter")}}</code> または <code>{{event("dragover")}}</code> イベントのリスナーは、操作が許可されているかどうかを確かめるために {{domxref("DataTransfer.effectAllowed","effectAllowed")}} プロパティを参照できます。これらのイベントにおいて、関連するプロパティである {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティへ、実際に行われる操作の種類1つだけが指定されるべきです。 {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティの値として妥当な物は、<code>none</code>、<code>copy</code>、<code>move</code>、または<code>link</code>のみです。このプロパティへは、複数の操作を組み合わせた値は指定できません。</p> + +<p>{{event("dragenter")}} および {{event("dragover")}} イベントにおいて、 {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティはユーザーが要求している操作に初期化されます。ユーザーは操作の種類を修飾キーを押すことにより変更することができます。実際に使用されるキーはプラットフォームごとに異なりますが、大抵の場合は Shift キーと Control キーが、コピー・移動・リンクの各操作の切り替えに使われるでしょう。マウスポインターはどの操作が望まれているのかを示すために、例えばコピーならカーソルの横に「+」記号が表示される、といった風に変化するでしょう。</p> + +<p>{{event("dragenter")}} または {{event("dragover")}} イベントの間に {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティの値を変更すると、ユーザーが選択した操作の種類を上書きし、特定のドロップ操作を強制することができます。この時に指定できる操作の種類は、 {{domxref("DataTransfer.effectAllowed","effectAllowed")}} プロパティの値として列挙されている操作に含まれていなくてはならないことに注意してください。それ以外の値を設定した場合は、許可されている操作の中から代わりの値が設定されます。</p> + +<pre class="brush: js">event.dataTransfer.dropEffect = "copy"; +</pre> + +<p>この例では、「コピー」が行なわれる効果です。</p> + +<p>その場所へのドロップが禁止されていることを示すために、値として <code>none</code> を設定することもできます。</p> + +<p>{{event("drop")}} および {{event("dragend")}} イベントの中では、 {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティをチェックすることで最終的に選択されている効果を特定できます。選択された効果が「move」であれば、 {{event("dragend")}} イベントの中でドラッグ元から元のデータを削除するべきです。</p> + +<h2 id="droptargets" name="droptargets">ドロップ先の指定</h2> + +<p>{{event("dragenter")}} および {{event("dragover")}} イベントのリスナーは、ドラッグされている項目がどの場所にドロップされようとしているのかを正確に示す働きをすることが多いです。ウェブページやアプリケーションのほとんどの領域は、ドロップデータを受け取る場所としては不適切です。従って、これらのイベントに対する既定の動作はドロップを禁止する働きをします。</p> + +<p>ドロップを許可したい場合、イベントをキャンセルして既定の動作を無効化する必要があります。属性値として定義されたイベントリスナーで <code>false</code> を返すか、イベントの {{domxref("Event.preventDefault","preventDefault()")}} メソッドを呼ぶことで、既定の動作を無効にできます。別のファイルに分けられたスクリプトで機能を定義する場合は、後者の方が便利でしょう。</p> + +<pre class="brush: html"><div ondragover="return false"> +<div ondragover="event.preventDefault()"> +</pre> + +<p>{{event("dragenter")}} および {{event("dragover")}} イベントのどちらにおいても、 {{domxref("Event.preventDefault","preventDefault()")}} メソッドを呼び出すと、その場所がドロップ可能な場所であるということを示します。多くの場合は、例えばリンクがドラッグされている時だけなど、特定の状況でのみ {{domxref("Event.preventDefault","preventDefault()")}} メソッドを呼び出したいと思うでしょう。これを実現するには、条件を確かめて、条件が満たされている時だけイベントをキャンセルするような関数を使って下さい。条件が満たされていない時はイベントをキャンセルしないでおけば、ユーザーがマウスのボタンを放してもその場所へのドロップは行われません。</p> + +<p>ドロップを受け付けるか拒絶するかを決める最も一般的な方法は、データ転送の仕組みに含まれているドラッグデータの型を判別するものです。例えば、画像やリンク、もしくはその両方のみを受け付けるといった事ができます。これを実現するには、イベントの {{domxref("DragEvent.dataTransfer","dataTransfer")}} (プロパティ)の {{domxref("DataTransfer.types","types")}} プロパティを確認します。 {{domxref("DataTransfer.types","types")}} プロパティはドラッグが開始された時に登録されたタイプ文字列のリストで、最も適切なものから最も適切でないものの順で並んでいます。</p> + +<pre class="brush: js">function contains(list, value) { + for( var i = 0; i < list.length; ++i ) { + if(list[i] === value) return true; + } + return false; +} + +function doDragOver(event) { + var isLink = contains( event.dataTransfer.types, "text/uri-list"); + if (isLink) { + event.preventDefault(); + } +}</pre> + +<p>この例では、型のリストの中に <a href="/ja/docs/DragDrop/Recommended_Drag_Types#link" title="text/uri-list">text/uri-list</a> 型があるかどうかを確認するために <code>contains</code> メソッドを使用しています。もし条件が真であれば、イベントはキャンセルされて、ドロップが許可されるでしょう。もしドラッグデータがリンクを含んでいなければ、イベントはキャンセルされず、その場所でのドロップも行われません。</p> + +<p>実際に行われる処理の種類をより適切に示すために、 {{domxref("DataTransfer.effectAllowed","effectAllowed")}} や {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティのいずれか、あるいはその両方に値を指定したいと思う事もあるでしょう。当然ですが、イベントをキャンセルするのを忘れると、これらのプロパティの値を変えても何も起こりません。</p> + +<h3 id="Updates_to_DataTransfer.types" name="Updates_to_DataTransfer.types">DataTransfer.types の更新</h3> + +<p>なお、最新の仕様書では {{domxref("DataTransfer.types")}} は {{domxref("DOMStringList")}} ではなく {{domxref("DOMString")}} の凍結した配列を返すべきだとしています(Firefox 52 以降で対応されました)。</p> + +<p>結果として、 <a href="/ja/docs/Web/API/Node/contains">contains</a> メソッドはこのプロパティでは動作しなくなりました。特定の種類のデータが提供されているかをチェックするためには、代わりに <a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes">includes</a> メソッドを使用してください。以下のようなコードを使用します。</p> + +<pre class="brush: js">if ([...event.dataTransfer.types].includes('text/html')) { + // Do something +}</pre> + +<p><code>types</code> がどちらのメソッドに対応しているかを判別する機能を使用すれば、適切なコードを実行できます。</p> + +<h2 id="dropfeedback" name="dropfeedback">ドロップのフィードバック</h2> + +<p>その場所へのドロップが許可されていることをユーザーに示す方法はいくつかあります。マウスポインターは {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティの値に応じて適切なものに変化します。実際の正確な表示のされ方はユーザーのプラットフォームに依存しますが、通常は例えば「コピー」に対しては「+」記号が表示され、また、ドロップが許可されていない時は「ここにはドロップできません」という意味のアイコンが表示されるでしょう。多くの場合において、このポインターによるフィードバックは十分に役立ちます。</p> + +<p>それ以外にも必要に応じて、ユーザーインターフェースを更新して挿入箇所を示したりハイライト表示したりすることもできます。単にハイライト表示するだけであれば、ドロップ対象においてCSSの<code>-moz-drag-over</code>疑似クラスが利用できます。</p> + +<pre class="brush: css">.droparea:-moz-drag-over { + border: 1px solid black; +} +</pre> + +<p>この例において<code>droparea</code>クラスの要素は、 {{event("dragenter")}} イベントの中で {{domxref("Event.preventDefault","preventDefault()")}} メソッドが呼ばれて有効なドロップ対象となっている間、1ピクセルの黒い枠が表示されます。この疑似クラスは {{event("dragover")}} イベントでの状態の変化には反応しませんので、この疑似クラスでの指定を適用させるには {{event("dragenter")}} イベントをキャンセルしなくてはならない事に注意してください。</p> + +<p>より凝った視覚効果のために、例えばドロップが行われる位置に要素を挿入するなど、 {{event("dragenter")}} イベントの間に他の操作をすることもできます。この例なら、挿入される要素は、挿入箇所を示すマーカーあるいはドラッグされている要素が新しい位置に挿入された時の状態のプレビューなどとして利用できるでしょう。このような効果は、例えば <a class="internal" href="/ja/XUL/image" title="ja/XUL/image">image</a> や <a class="internal" href="/ja/XUL/separator" title="ja/XUL/separator">separator</a> を生成して、 {{event("dragenter")}} イベントの処理中にドキュメント中に単に挿入するだけで実現できます。</p> + +<p>{{event("dragover")}} イベントは、マウスポインターが現在指している要素において発行されます。挿入点のマーカーを {{event("dragover")}} イベントの発行に応じて移動させたいと思うのは自然な欲求でしょう。そのような場合には、他のマウスイベントでマウスポインターの位置を取得するために使われるのと同じ要領で、イベントの {{domxref("MouseEvent.clientX","clientX")}} と {{domxref("MouseEvent.clientY","clientY")}} プロパティを利用できます。</p> + +<p>最後に、ドラッグ中にマウスポインターが要素の上を離れる時、 {{event("dragleave")}} イベントが発行されます。これは挿入点のマーカーやハイライト表示を消すのにちょうどいいタイミングです。このイベントをキャンセルする必要はありません。 <code>-moz-drag-over</code> 疑似クラスを使って指定されたハイライト表示やその他の視覚効果は、すべて自動的に消去されます。 {{event("dragleave")}} イベントは、ドラッグがキャンセルされた時でも常に発行されますので、このイベントによって、挿入点の消去などを確実に行うことができます。</p> + +<h2 id="drop" name="drop">ドロップの実行</h2> + +<p>ユーザーがマウスのボタンを放した時、ドラッグ&ドロップの操作は終了します。有効なドロップ対象となっている要素の上でマウスのボタンが放された場合、最後の {{event("dragenter")}} と {{event("dragover")}} イベントはキャンセルされて、ドロップが成功し、 {{event("drop")}} イベントがそのドロップ対象において発行されます。それ以外の場所でボタンが放された場合は、ドラッグ操作はキャンセルされ、 {{event("drop")}} イベントは発行されません。</p> + +<p>{{event("drop")}} イベントの間、あなたはドロップされたデータをイベントから取得して、ドロップ位置に挿入することになります。どのドラッグ&ドロップ操作が望まれていたのかは、 {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティで判別することができます。</p> + +<p>すべてのドラッグ&ドロップ関連のイベントにおいて、イベントの {{domxref("DragEvent.dataTransfer","dataTransfer")}} プロパティはドラッグされた対象に関するデータを保持しています。データの取得には {{domxref("DataTransfer.getData","getData()")}} メソッドを利用することになるでしょう。</p> + +<pre class="brush: js">function onDrop(event) { + var data = event.dataTransfer.getData("text/plain"); + event.target.textContent = data; + event.preventDefault(); +} +</pre> + +<p>{{domxref("DataTransfer.getData","getData()")}} メソッドは、取得したいデータの型を引数として取ります。実行すると、ドラッグ操作の開始時に {{domxref("DataTransfer.setData","setData()")}} メソッドによって登録された値が文字列として返されます。その型に対するデータが存在しない場合は、空文字が返されます。当然ながら、直前の {{event("dragover")}} イベントでの処理においてチェックした時と同様に、あなたはデータの正しい形式が利用可能かどうかを知りたいと思うでしょう。</p> + +<p>上記の例では、まずデータを取得し、ドロップ対象の内容テキストとしてそれを挿入しています。これは <code>p</code> 要素や <code>div</code> 要素がドロップ対象の領域として使われる事を想定しており、ドラッグされたテキストをドロップ位置に挿入するという効果をもたらします。</p> + +<p>ウェブページにおいては、ドロップを受け付けた場合、イベントの {{domxref("Event.preventDefault","preventDefault()")}} メソッドを呼び出すべきです。これによって、ブラウザ内でのドロップ時の既定の挙動がキャンセルされます。例えば、リンクがウェブページにドロップされた場合、 Firefox はそのリンク先を読み込もうとします。イベントをキャンセルすることで、この動作は抑止されます。</p> + +<p>他の形式でデータを取得することもできます。データがリンクであった場合、そのデータは <a href="/ja/docs/DragDrop/Recommended_Drag_Types#link" title="text/uri-list">text/uri-list</a> 型でも提供されているでしょう。その場合、リンクを内容に挿入することができます。</p> + +<pre class="brush: js">function doDrop(event) { + var lines = event.dataTransfer.getData("text/uri-list").split("\n"); + for (let line of lines) { + if (line.startsWith("#")) + continue; + + let link = document.createElement("a"); + link.href = line; + link.textContent = line; + event.target.appendChild(link); + } + event.preventDefault(); +} +</pre> + +<p>この例は、ドラッグされたデータからリンクを挿入します。名前から想像できる通り、 <a href="/ja/docs/DragDrop/Recommended_Drag_Types#link" title="text/uri-list">text/uri-list</a> 型は実際に複数のURLの改行区切りのリストを含んでいる場合があります。このコードでは、 <a class="internal" href="/ja/JavaScript/Reference/Global_Objects/String/split" title="Ja/Core JavaScript 1.5 Reference/Global Objects/String/split">split</a> を使って文字列を行ごとに分割し、各行に繰り返し処理を行って、それぞれをリンクとして文書中に挿入しています。ナンバー記号(#)で始まる物はコメントとして除外していることに注意してください。</p> + +<p>単純な使い方として、リストの中の最初の有効なURLを取得するために、特別な型 <code>URL</code> も利用できます。例:</p> + +<pre class="brush: js">var link = event.dataTransfer.getData("URL"); +</pre> + +<p>これによって、コメントの除外などの処理は一切不要になります。しかし、これはリストの中の最初の URL だけしか取得できないという制限があります。</p> + +<p><code>URL</code> 型は特別な省略表記用の型で、 {{domxref("DataTransfer.types","types")}} プロパティで取得できる型のリストには列挙されません。</p> + +<p>時には、複数の形式をサポートして、そのうち最も適切な形式で提供されたデータを取得したいと思う事もあるでしょう。以下の例では、3つの形式がドロップ対象によってサポートされています。</p> + +<p>以下の例は、提供されたデータの中で最も適切なデータを返す例です。</p> + +<pre class="brush: js">function doDrop(event) { + var types = event.dataTransfer.types; + var supportedTypes = ["application/x-moz-file", "text/uri-list", "text/plain"]; + types = supportedTypes.filter((value) => types.includes(value)); + if (types.length) + var data = event.dataTransfer.getData(types[0]); + event.preventDefault(); +} +</pre> + +<p>この例は Firefox 3 で利用可能な JavaScript の拡張された機能を使って書かれていますが、他の環境でも動作する様に書き換えることもできます。</p> + +<h2 id="dragend" name="dragend">ドラッグの終了</h2> + +<p>1回のドラッグ操作が終了すると、 {{event("dragend")}} イベントがドラッグ元(<code> {{event("dragstart")}} </code>イベントが発行されるのと同じ要素)において発行されます。このイベントは、ドラッグ操作が成功したかキャンセルされたかに関わらず発行されます。どの操作が行われたのかは、 {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティを参照して知ることができます。</p> + +<p>{{event("dragend")}} イベントにおいて {{domxref("DataTransfer.dropEffect","dropEffect")}} プロパティの値が<code>none</code>である場合、ドラッグ操作がキャンセルされたことを意味します。それ以外の場合は、プロパティの値は実際に行われた操作の種類を示します。ドラッグ元はこの情報に基づいて、ドラッグされた項目を「移動」の操作の後に元の場所から削除することができます。 {{domxref("DataTransfer.mozUserCancelled","mozUserCancelled")}} プロパティの値は、ユーザーが(Escapeキーを押すなどして)ドラッグ操作をキャンセルした場合は true となり、不正なドロップ先だった場合などの他の理由でドラッグ操作がキャンセルされた場合や、ドロップに成功した場合はfalseとなります。</p> + +<p>ドロップ操作は同じウィンドウの中または他のアプリケーションの上で行われ得ます。いずれの場合も常に {{event("dragend")}} イベントは発行されます。このイベントの {{domxref("MouseEvent.screenX","screenX")}} および {{domxref("MouseEvent.screenY","screenY")}} プロパティの値には、ドロップが行われたときの画面上での座標が設定されます。</p> + +<p>{{event("dragend")}} イベントの伝搬が終了した後、ドラッグ&ドロップの操作は完了します。</p> + +<p>[1] Gecko では、元のノードがドラッグ中(例えばドロップ中や {{event("dragover")}})に移動したり削除されたりした場合、 {{event("dragend")}} が発行されません。 <a class="external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=460801" title="New D&D API: dragend is not dispatched if the source node was moved or removed during the drag session">bug 460801</a></p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a class="internal" href="/Web/API/HTML_Drag_and_Drop_API" title="HTML Drag and Drop API">HTML ドラッグ&ドロップ API (概要)</a></li> + <li><a class="internal" href="/Web/Guide/HTML/Dragging_and_Dropping_Multiple_Items" title="Dragging and Dropping Multiple Items">複数の項目のドラッグ&ドロップ</a></li> + <li><a class="internal" href="/Web/Guide/HTML/Recommended_Drag_Types" title="Recommended Drag Types">推奨されるドラッグタイプ</a></li> + <li><a href="https://html.spec.whatwg.org/multipage/interaction.html#dnd" title="Drag and Drop Standard">HTML5 Living Standard: Drag and Drop</a></li> +</ul> diff --git a/files/ja/dragdrop/dragging_and_dropping_multiple_items/index.html b/files/ja/dragdrop/dragging_and_dropping_multiple_items/index.html new file mode 100644 index 0000000000..aadaeb095d --- /dev/null +++ b/files/ja/dragdrop/dragging_and_dropping_multiple_items/index.html @@ -0,0 +1,108 @@ +--- +title: 複数の項目のドラッグ&ドロップ +slug: DragDrop/Dragging_and_Dropping_Multiple_Items +translation_of: Web/API/HTML_Drag_and_Drop_API/Multiple_items +--- +<p>{{ Fx_minversion_header(3.5) }} Mozillaはいくつかの非標準の機能によって、複数の項目のドラッグをサポートしています。それらの機能は<a class="internal" href="/Ja/DragDrop/DataTransfer#types.28.29" title="Ja/DragDrop/DataTransfer#types.28.29">types</a>プロパティや<a class="internal" href="/Ja/DragDrop/DataTransfer#getData.28.29" title="Ja/DragDrop/DataTransfer#getData.28.29">getData</a>、<a class="internal" href="/Ja/DragDrop/DataTransfer#setData.28.29" title="Ja/DragDrop/DataTransfer#setData.28.29">setData</a>、<a class="internal" href="/Ja/DragDrop/DataTransfer#clearData.28.29" title="Ja/DragDrop/DataTransfer#clearData.28.29">clearData</a>の各メソッドに酷似していますが、データの取得や変更、削除の際などに項目のインデックスを追加の引数として要求します。</p> +<p><a class="internal" href="/Ja/DragDrop/DataTransfer#mozSetDataAt.28.29" title="Ja/DragDrop/DataTransfer#mozSetDataAt.28.29">mozSetDataAt</a>を使うと、<code>dragstart</code>イベントで複数の項目を登録することができます。これは<a class="internal" href="/Ja/DragDrop/DataTransfer#setData.28.29" title="Ja/DragDrop/DataTransfer#setData.28.29">setData</a>メソッドとよく似た働きをします。</p> +<pre>var dt = event.dataTransfer; +dt.mozSetDataAt("text/plain", "ドラッグされるデータ", 0); +dt.mozSetDataAt("text/plain", "ドラッグされる2つめのデータ", 1); +</pre> +<p>この例では2つのドラッグ項目を追加しています。最後の引数は追加する項目のインデックスを示しています。これらの項目は0番から順番に登録するべきで、最後の方(インデックスの大きなもの)から逆順に登録することはできません。また、すでにデータが登録されているインデックスを指定してもう1度データを登録すると、前に登録したデータを置き換えることができます。インデックスとして0を指定すると、<a class="internal" href="/Ja/DragDrop/DataTransfer#setData.28.29" title="Ja/DragDrop/DataTransfer#setData.28.29">setData</a>メソッドを呼んだのと等しく扱われます。</p> +<p><a class="internal" href="/Ja/DragDrop/DataTransfer#mozClearDataAt.28.29" title="Ja/DragDrop/DataTransfer#mozClearDataAt.28.29">mozClearDataAt</a>メソッドを使って、指定した項目を削除することもできます。</p> +<pre>event.dataTransfer.mozClearDataAt("text/plain", 1); +</pre> +<p>あるインデックスで示される項目について、最後のデータ形式の削除によって項目全体を削除すると、残りの項目が繰り上がって項目のインデックスが変わることに注意してください。例えば、</p> +<pre>var dt = event.dataTransfer; +dt.mozSetDataAt("text/uri-list", "URL1", 0); +dt.mozSetDataAt("text/plain", "URL1", 0); +dt.mozSetDataAt("text/uri-list", "URL2", 1); +dt.mozSetDataAt("text/plain", "URL2", 1); +dt.mozSetDataAt("text/uri-list", "URL3", 2); +dt.mozSetDataAt("text/plain", "URL3", 2); +// [item1] data=URL1, index=0 +// [item2] data=URL2, index=1 +// [item3] data=URL3, index=2 +</pre> +<p>このように2つの形式で提供されたデータを持つ3つの項目を登録した後で、</p> +<pre>dt.mozClearDataAt("text/uri-list", 1); +dt.mozClearDataAt("text/plain", 1); +</pre> +<p>このように2番目の項目についてすべての形式のデータを削除すると、3番目だった項目が繰り上がって2番目の項目になり、インデックスが2から1に変わります。</p> +<pre>// [item1] data=URL1, index=0 +// [item2] data=URL3, index=1 +</pre> +<p>幸いなことに、通常は項目を削除する必要がある場合は希で、それよりも、必要に応じて項目を追加するだけの場合の方がずっと多いです。</p> +<p>複数の項目のドラッグが使われる場合の代表は、複数のファイルやブックマークをドラッグする時です。この場合には、適切な形式でそれらの項目を追加してください。また必須ではありませんが、それぞれの項目は常に同じ形式でデータを追加するべきです。これによりドロップ対象は、一貫したデータの受け取りを期待できます。</p> +<p>複数のファイルがドラッグされているかどうかを確認するには、<a class="internal" href="/Ja/DragDrop/DataTransfer#mozItemCount.28.29" title="Ja/DragDrop/DataTransfer#mozItemCount.28.29">mozItemCount</a>プロパティを調べます。このプロパティにはドラッグされている項目の数がセットされます。もしそのドロップ対象が1つの項目のドロップだけを受け付ける場合には、ドラッグされた項目すべてを拒否することもできますし、最初の項目だけを受け取ることもできます。複数の項目の受け取りを拒否するには、dragoverイベントをキャンセルしないか、<a class="internal" href="/Ja/DragDrop/DataTransfer#effectAllowed.28.29" title="Ja/DragDrop/DataTransfer#effectAllowed.28.29">effectAllowed</a>プロパティに<code>none</code>を指定します。他のイベントリスナがすでにイベントをキャンセルしている場合に備えて、両方を実行しても構いません。</p> +<p>ドロップされた項目のうち最初の項目だけを扱う場合は、1つだけの項目のドラッグの場合と同様に<a class="internal" href="/Ja/DragDrop/DataTransfer#getData.28.29" title="Ja/DragDrop/DataTransfer#getData.28.29">getData</a>を使います。これは、何も追加の処理が必要ないドロップ項目を1つだけ受け取るドロップ対象のために有用です。</p> +<p>それに対して、任意のインデックスの項目をデータトランスファーから取得するには<a class="internal" href="/Ja/DragDrop/DataTransfer#mozGetDataAt.28.29" title="Ja/DragDrop/DataTransfer#mozGetDataAt.28.29">mozGetDataAt</a>メソッドを使います。以下の例は、ドラッグされたファイルを取得し、それらを配列に追加するものです。</p> +<pre>function onDrop(event) +{ + var files = []; + var dt = event.dataTransfer; + for (var i = 0; i < dt.mozItemCount; i++) + files.push(dt.mozGetDataAt("application/x-moz-file", i)); +} +</pre> +<p><a class="internal" href="/Ja/DragDrop/DataTransfer#mozTypesAt.28.29" title="Ja/DragDrop/DataTransfer#mozTypesAt.28.29">mozTypesAt</a>メソッドを使って、望んでいる形式のデータが存在しているかどうかを確かめたいとも思うでしょう。<a class="internal" href="/Ja/DragDrop/DataTransfer#types.28.29" title="Ja/DragDrop/DataTransfer#types.28.29">types</a>プロパティと同様に、このメソッドは、その項目が保持しているデータの型の文字列を返します。<a class="internal" href="/Ja/DragDrop/DataTransfer#types.28.29" title="Ja/DragDrop/DataTransfer#types.28.29">types</a>プロパティを取得する事は、インデックスが0の項目の型のリストを取得する事に等しいです。</p> +<pre>var types = event.dataTransfer.mozTypesAt(1); +</pre> +<h2 id="文字列でないデータのドラッグ">文字列でないデータのドラッグ</h2> +<p>上で解説した追加のメソッドが扱えるデータは文字列に限定されず、どんな種類のデータでも指定することができます。例えば、ファイルは<a class="internal" href="/Ja/DragDrop/Recommended_Drag_Types#file" title="Ja/DragDrop/Recommended Drag Types#file">application/x-moz-file</a>型で<a class="internal" href="/ja/nsIFile" title="ja/nsIFile">nsIFile</a>のオブジェクトとして保持されてドラッグされます。<code>setData</code>メソッドは文字列しかサポートしておらず、 ドラッグするファイルを指定するのには利用できないため、代わりに<a class="internal" href="/Ja/DragDrop/DataTransfer#mozSetDataAt.28.29" title="Ja/DragDrop/DataTransfer#mozSetDataAt.28.29">mozSetDataAt</a>メソッドを使わなくてはなりません。</p> +<pre>dt.mozSetDataAt("application/x-moz-file", file, 0); +</pre> +<p>複数の項目を扱う必要がない場合でも、このメソッドを使うことによって任意のオブジェクトをデータに指定できます。この場合には、インデックスとして0を指定しておきます。</p> +<p>同様に、ファイルやその他のオブジェクトを取得するには<a class="internal" href="/Ja/DragDrop/DataTransfer#mozGetDataAt.28.29" title="Ja/DragDrop/DataTransfer#mozGetDataAt.28.29">mozGetDataAt</a>メソッドを使う必要があります。もし<a class="internal" href="/Ja/DragDrop/DataTransfer#getData.28.29" title="Ja/DragDrop/DataTransfer#getData.28.29">getData</a>を使った場合は、値が文字列でない型のデータは空文字として取得されます。ただし、数値のような単純な型のデータについては文字列に変換できるため、この場合は<a class="internal" href="/Ja/DragDrop/DataTransfer#getData.28.29" title="Ja/DragDrop/DataTransfer#getData.28.29">getData</a>を使っても問題ありません。</p> +<h2 id="複数項目のドロップの例">複数項目のドロップの例</h2> +<p>以下は、ドロップされた項目のデータとその形式を一覧表示するボックスの例です。</p> +<pre><html> +<head> +<script> + +function dodrop(event) +{ + var dt = event.dataTransfer; + var count = dt.mozItemCount; + output("Items: " + count + "\n"); + + for (var i = 0; i < count; i++) { + output(" Item " + i + ":\n"); + var types = dt.mozTypesAt(i); + for (var t = 0; t < types.length; t++) { + output(" " + types[t] + ": "); + try { + var data = dt.mozGetDataAt(types[t], i); + output("(" + (typeof data) + ") : <" + data + " >\n"); + } catch (ex) { + output("<<error>>\n"); + dump(ex); + } + } + } +} + +function output(text) +{ + document.getElementById("output").textContent += text; + dump(text); +} + +</script> +</head> +<body> + +<div id="output" style="min-height: 100px; white-space: pre; border: 1px solid black;" + ondragenter="document.getElementById('output').textContent = ''; event.stopPropagation(); event.preventDefault();" + ondragover="event.stopPropagation(); event.preventDefault();" + ondrop="event.stopPropagation(); event.preventDefault(); dodrop(event);"> +<div> + +</body> +</html> +</pre> +<p>この例は、<a class="internal" href="/ja/DOM/event.preventDefault" title="ja/DOM/event.preventDefault">preventDefault</a>メソッドによって<code>dragenter</code>イベントと<code>dragover</code>イベントを両方ともキャンセルします。これにより、要素の上でのドロップが可能になっています。</p> +<p>項目をドロップした時に、<code>dodrop</code>関数が呼ばれます。この関数は<a class="internal" href="/Ja/DragDrop/DataTransfer#mozItemCount.28.29" title="Ja/DragDrop/DataTransfer#mozItemCount.28.29">mozItemCount</a>プロパティを見て、いくつの項目がドロップされたのかを調べ、それらに繰り返し処理を行います。それぞれの項目について、型の一覧を得るために<a class="internal" href="/Ja/DragDrop/DataTransfer#mozTypesAt.28.29" title="Ja/DragDrop/DataTransfer#mozTypesAt.28.29">mozTypesAt</a>メソッドが呼ばれます。この一覧の生成処理は、ドラッグに対して関連づけられたすべてのデータに対して繰り返されます。</p> +<p>この例は、あるドラッグ操作が保持しているデータを確かめたい時に便利です。ただ項目をこの例のドロップ対象にドロップするだけで、ドラッグされたどの項目がどんな形式でどのようなデータを保持しているのかを見ることができます。</p> +<p>{{ languages( { "en": "En/DragDrop/Dragging_and_Dropping_Multiple_Items" } ) }}</p> diff --git a/files/ja/dragdrop/index.html b/files/ja/dragdrop/index.html new file mode 100644 index 0000000000..6b9a4be242 --- /dev/null +++ b/files/ja/dragdrop/index.html @@ -0,0 +1,9 @@ +--- +title: DragDrop +slug: DragDrop +--- +<p> </p> + +<p>This page was auto-generated because a user created a sub-page to this page.</p> + +<p> </p> diff --git a/files/ja/dragdrop/recommended_drag_types/index.html b/files/ja/dragdrop/recommended_drag_types/index.html new file mode 100644 index 0000000000..eb8487d158 --- /dev/null +++ b/files/ja/dragdrop/recommended_drag_types/index.html @@ -0,0 +1,228 @@ +--- +title: 推奨されるドラッグのデータ型 +slug: DragDrop/Recommended_Drag_Types +tags: + - Guide + - drag and drop +translation_of: Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types +--- +<p>{{DefaultAPISidebar("HTML Drag and Drop API")}}</p> + +<p>HTML Drag and Drop API は、プレーンテキスト、URL、HTML コード、ファイルなど、さまざまな形式のデータのドラッグをサポートしています。このドキュメントでは、一般的なドラッグ可能なデータ形式のベストプラクティスについて説明しています。</p> + +<div class="overheadIndicator nonStandard nonStandardHeader"> +<p><strong>注意事項:</strong><br> + <code>mozSetDataAt()</code> のような <code>moz</code> プレフィックスを持つこのドキュメントのすべてのメソッドとプロパティは、Gecko ベースのブラウザでのみ動作します。</p> +</div> + +<h2 id="text" name="text">テキストのドラッグ</h2> + +<p>テキストをドラッグする時は、<code>text/plain</code> 型を使用します。2番目の引数には、ドラッグした文字列を指定します。例えば、以下のようになります。</p> + +<pre class="brush: js notranslate">event.dataTransfer.setData("text/plain", "これはドラッグされるテキストです"); +</pre> + +<p>Web ページのテキストボックスや選択範囲の文字列のドラッグは、ブラウザが自動的に処理を行うので、自分で処理する必要はありません。</p> + +<p>そのデータが代替テキストでは表現できない物である場合を除いて、他のデータ形式をサポートしないアプリケーションやドロップ対象のためのフォールバック用に、常に <code>text/plain</code> 型のデータを提供することをおすすめします。そのために、データを追加する時には最後に <code>text/plain</code> 型のデータを登録しておいてください。</p> + +<p class="note">注: 古いコードにおいて、<code>text/unicode</code> や <code>text</code> といった型の記述を見かけることがあるかもしれません。これらはどちらも <code>text/plain</code> と等しく扱われ、プレーンテキスト型のデータとして登録・取得されます。</p> + +<h2 id="link" name="link">リンクのドラッグ</h2> + +<p>ドラッグされたハイパーリンクには、<code>text/uri-list</code> と <code>text/plain</code> の<em>2種類</em>のデータを含める必要があります。どちらの形式もリンクの URL をデータに使用しなければなりません。例えば、以下のようになります。</p> + +<pre class="brush: js notranslate">var dt = event.dataTransfer; +dt.setData("text/uri-list", "https://www.mozilla.org"); +dt.setData("text/plain", "https://www.mozilla.org"); +</pre> + +<p><code>text/uri-list</code> 型のフォールバックとして、<code>text/plain</code> 型を最後に設定します。</p> + +<p class="note">注:URL 用の型は <code>ur<em><strong>i</strong></em>-list-list</code> で、L ではなく I であることに注意してください。</p> + +<p>複数のリンクをドラッグするには、それぞれのリンクを <code>text/uri-list</code> データ内で CRLF 改行で区切ってください。ナンバー記号 (<code>#</code>) で始まる行はコメントで、有効な URL として扱われません。コメントは、リンクの目的を示したり、リンクに関連づけられたタイトルを保持したりする目的で利用できます</p> + +<div class="blockIndicator warning"> +<p>複数のリンクのための <code>text/plain</code> 型のフォールバックは、すべての URL を含むべきですが、コメントを含めるべきではありません。</p> +</div> + +<p>例えば、以下のサンプル <code>text/uri-list</code> データには、2つのリンクと1つのコメントが含まれています。</p> + +<pre class="notranslate">http://www.mozilla.org +#2つ目のリンク +http://www.example.com +</pre> + +<p>ドロップされたリンクを取得する時は、コメントを含めて複数のリンクをドラッグした場合の処理を確実に行ってください。便宜上、<code>text/uri-list</code> 型のデータ内の最初の有効なリンクを参照するために、特別な型として <code>URL</code> を使用することができます。</p> + +<div class="blockIndicator warning"> +<p><code>URL</code> 型でデータを追加しないでください - それを行うと、代わりに <code>text/uri-list</code> 型のデータとして登録されます。</p> +</div> + +<pre class="brush: js notranslate">var url = event.dataTransfer.getData("URL"); +</pre> + +<p>Mozilla 特有の型として、<code>text/x-moz-url</code> 型のデータを見かけることがあるかもしれません。この型が表示される場合は、<code>text/uri-list</code> 型の前に表示されるはずです。この型のデータは、リンクの URL に続いてリンクのタイトルが保持されており。例えば、以下のようになります。</p> + +<pre class="notranslate">http://www.mozilla.org +Mozilla +http://www.example.com +Example +</pre> + +<h2 id="html" name="html">HTMLとXMLのドラッグ</h2> + +<p>HTML の内容は <code>text/html</code> 型を使用します。この型のデータはドラッグされる HTML をシリアライズしたものであるべきです。具体的には、この型のデータとして登録されるのに適した値は、要素の <code>{{domxref("Element.innerHTML","innerHTML")}}</code> プロパティの値です。</p> + +<p>XML の内容は <code>text/xml</code> 型を使用することができますが、内容は整形式の XML に変換しておくべきです。</p> + +<p>また、<code>text/plain</code> 型を使用して、HTML または XML のプレーンテキストでの表現を提供することもできます。その場合のデータは単純なテキストであるべきで、タグや属性などのソース文字列を含めるべきではありません。例えば、以下のようになります。</p> + +<pre class="brush: js notranslate">var dt = event.dataTransfer; +dt.setData("text/html", "こんにちは、<strong>見知らぬ人</strong>"); +dt.setData("text/plain", "こんにちは、見知らぬ人"); +</pre> + +<h2 id="file" name="file">ファイルのドラッグ</h2> + +<p>ローカルのファイルは <code>application/x-moz-file</code> 型で、 <a href="/en/XPCOM_Interface_Reference/nsIFile" title="nsIFile">nsIFile</a> のオブジェクトとしてドラッグされます。特権を持っていない Web ページでは、この型のデータを取得することも変更することもできません。</p> + +<p>ファイルを文字列にはできないため、データを登録するには {{domxref("DataTransfer.mozSetDataAt","mozSetDataAt()")}} メソッドを使用する必要があります。同様に、データを取得するには {{domxref("DataTransfer.mozGetDataAt","mozGetDataAt()")}} メソッドを使わなくてはなりません。</p> + +<pre class="brush: js notranslate">event.dataTransfer.mozSetDataAt("application/x-moz-file", file, 0); +</pre> + +<p>可能であれば、<code>text/uri-list</code> 型と <code>text/plain</code> 型の両方を使ってファイルの URL を含めてください。これらの型は最後に登録されるべきで、それによって、 <code>application/x-moz-file</code> 型は優先度の高い、より適切な型となります。</p> + +<p>複数のファイルは、データ転送中に複数のアイテムとしてドロップ中に受信されます。これについての詳細は、<a href="/DragDrop/Dragging_and_Dropping_Multiple_Items" title="Dragging and Dropping Multiple Items">複数の項目のドラッグ&ドロップ</a>を参照してください。</p> + +<p>以下の例は、ドロップしたファイルを受信するための領域を作成する方法を示しています。</p> + +<pre class="brush: xml notranslate"><listbox ondragenter="return checkDrag(event)" + ondragover="return checkDrag(event)" + ondrop="doDrop(event)"/> + +<script> +function checkDrag(event) { + return event.dataTransfer.types.contains("application/x-moz-file"); +} + +function doDrop(event) { + var file = event.dataTransfer.mozGetDataAt("application/x-moz-file", 0); + if (file instanceof Components.interfaces.nsIFile) { + event.currentTarget.appendItem(file.leafName); + } +} +</script> +</pre> + +<p>この例では、データ転送に <code>application/x-moz-file</code> 型が含まれている場合にのみ、イベントが false を返します。ドロップイベントの間、ファイル型に関連付けられたデータが取得され、ファイルのファイル名がリストボックスに追加されます。{{domxref("DataTransfer.mozGetDataAt","mozGetDataAt()")}} メソッドは、<code>nsISupports</code> を返すので、nsIFile 型に変換するために、ここでは <code>instanceof</code> 演算子を使用していることに注意してください。これは、誤ってファイルではない型のデータを登録した場合のためのチェックとしても有効です。</p> + +<h3 id="DataTransfer.types_の更新">DataTransfer.types の更新</h3> + +<p>最新の仕様では、{{domxref("DataTransfer.types")}} は {{domxref("DOMStringList")}} ではなく、{{domxref("DOMString")}} で固定した配列を返すようになっています(これは Firefox 52 以上でサポートされています)。</p> + +<p>その結果、<a href="/docs/Web/API/Node/contains">contains</a> メソッドはもう機能しません。代わりに <a href="/docs/Web/JavaScript/Reference/Global_Objects/Array/includes">includes</a> メソッドを使用し、以下のようなコードで特定の形式のデータが提供されているかどうかを確認する必要があります。</p> + +<pre class="brush: js notranslate">if ([...event.dataTransfer.types].includes('text/html')) { + // 実行するコード +}</pre> + +<p>特徴検出を使用して、どのメソッドがサポートされている<code>型</code>なのかを判断し、適切なコードを実行することができます。</p> + +<h2 id="image" name="image">画像のドラッグ</h2> + +<p>画像の直接のドラッグは一般的ではありません。そのため、Mozilla は Mac と Linux での画像の直接のドラッグをサポートしていません。その代わり、画像は通常その URL としてドラッグされます。そのためには、他の URL と同様に <code>text/uri-list</code> 型を使用します。データは、画像の URL、または画像がWeb上やディスク上に無い場合は <a href="/docs/Web/HTTP/Basics_of_HTTP/Data_URIs">データ URL</a> である必要があります。</p> + +<p>リンクと同様に、<code>text/plain</code> 型のデータには URL も含まれている必要があります。しかし、<a href="/docs/Web/HTTP/Basics_of_HTTP/Data_URIs">データ URL</a> は通常のテキストの内容には有用ではないので、このような状況では <code>text/plain</code> 型のデータを除外した方がよいでしょう。</p> + +<p>Chrome などの特権的なコードでは、画像の種類に応じて、<code>image/jpeg</code>、<code>image/png</code>、<code>image/gif</code> のいずれかの形式を使用することもできます。データは、<a href="/en/XPCOM_Interface_Reference/nsIInputStream" title="nsIInputStream">nsIInputStream</a> インターフェースを実装したオブジェクトでなければなりません。このストリームが読み込まれる時には、そのファイル形式での画像のデータビットを提供しなければなりません。</p> + +<p>画像がディスク上にある場合は、<code>application/x-moz-file</code> 型も含める必要があります。実際に、これは画像ファイルをドラッグする一般的なやり方です。</p> + +<p>最も適切なデータ形式からそうでない形式まで、正しい順序でデータを登録することが重要です。最初に <code>image/jpeg</code> のような標準的な画像型を設定し、次に <code>application/x-moz-file</code> 型を設定します。次に、<code>text/uri-list</code> 型を設定し、最後に <code>text/plain</code> 型を設定します。例えば、以下のようになります。</p> + +<pre class="brush: js notranslate">var dt = event.dataTransfer; +dt.mozSetDataAt("image/png", stream, 0); +dt.mozSetDataAt("application/x-moz-file", file, 0); +dt.setData("text/uri-list", imageurl); +dt.setData("text/plain", imageurl); +</pre> + +<p>{{domxref("DataTransfer.mozGetDataAt","mozGetDataAt()")}} メソッドは、テキスト以外のデータに使用されることに注意してください。内容によっては、これらの型の一部しか含まれていない場合があるので、ドロップされた画像を受信する時には、どの型が利用可能になっているかを確認することが重要です。</p> + +<h2 id="node" name="node">ノードのドラッグ</h2> + +<p>ドキュメント内のノードや要素は、<code>application/x-moz-node</code> 型を使ってドラッグすることができます。型のデータは DOM ノードでなければなりません。これにより、ドロップ対象はドラッグが開始された実際のノードを受け取ることができます。ノードがドロップされていても、異なるドメインからの呼び出し元はそのノードにアクセスできないことに注意してください。</p> + +<p>ノードの内容は常に <code>text/plain</code> 型の代替文字列で提供するべきです。</p> + +<h2 id="custom" name="custom">独自データのドラッグ</h2> + +<p>独自の目的のために、他の型を使うこともできます。そのデータが特定のサイトやアプリケーションに固有のものでない限り、常に <code>text/plain</code> 型の代替文字列を含めるようにしてください。代替テキストを用意しなかった場合は、他の場所にドロップできなくなります。</p> + +<h2 id="filestoos" name="filestoos">OS のフォルダにファイルをドラッグ</h2> + +<p>既存のドラッグイベントセッションにファイルを追加したり、コードが対象フォルダーの場所の通知を受信したときに、オペレーティングシステム内のフォルダーに対してのドロップ操作だった場合、ファイルをディスクに書き出したい場合があります。これは拡張機能(またはその他の特権コード)でのみ動作し、<code>application/moz-file-promise</code> 型を使用する必要があります。次のサンプルでは、この高度なケースの概要を説明します。</p> + +<pre class="brush: js notranslate">// currentEvent is an existing drag operation event + +currentEvent.dataTransfer.setData("text/x-moz-url", URL); +currentEvent.dataTransfer.setData("application/x-moz-file-promise-url", URL); +currentEvent.dataTransfer.setData("<span class="p">application/x-moz-file-promise-dest-filename</span>", leafName); +currentEvent.dataTransfer.mozSetDataAt('application/x-moz-file-promise', + new dataProvider(success,error), + 0, Components.interfaces.nsISupports); + +function dataProvider(){} + +dataProvider.prototype = { + QueryInterface : function(iid) { + if (iid.equals(Components.interfaces.nsIFlavorDataProvider) + || iid.equals(Components.interfaces.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + getFlavorData : function(aTransferable, aFlavor, aData, aDataLen) { + if (aFlavor == 'application/x-moz-file-promise') { + + var urlPrimitive = {}; + var dataSize = {}; + + aTransferable.getTransferData('application/x-moz-file-promise-url', urlPrimitive, dataSize); + var url = urlPrimitive.value.QueryInterface(Components.interfaces.nsISupportsString).data; + console.log("URL file orignal is = " + url); + + var namePrimitive = {}; + aTransferable.getTransferData('<span class="p">application/x-moz-file-promise-dest-filename</span>', namePrimitive, dataSize); + var name = namePrimitive.value.QueryInterface(Components.interfaces.nsISupportsString).data; + + console.log("target filename is = " + name); + + var dirPrimitive = {}; + aTransferable.getTransferData('application/x-moz-file-promise-dir', dirPrimitive, dataSize); + var dir = dirPrimitive.value.QueryInterface(Components.interfaces.nsILocalFile); + + console.log("target folder is = " + dir.path); + + var file = Cc['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile); + file.initWithPath(dir.path); + file.appendRelativePath(name); + + console.log("output final path is =" + file.path); + + // now you can write or copy the file yourself… + } + } +} +</pre> + +<h2 id="関連情報">関連情報</h2> + +<ul> + <li><a class="internal" href="/Web/API/HTML_Drag_and_Drop_API" title="HTML Drag and Drop API">HTML Drag and Drop API (Overview)</a></li> + <li><a class="internal" href="Web/Guide/HTML/Drag_operations" title="Drag Operations">Drag Operations</a></li> + <li><a class="internal" href="/Web/Guide/HTML/Dragging_and_Dropping_Multiple_Items" title="Dragging and Dropping Multiple Items">Dragging and Dropping Multiple Items</a></li> + <li><a href="https://html.spec.whatwg.org/multipage/interaction.html#dnd" title="Drag and Drop Standard">HTML5 Living Standard: Drag and Drop</a></li> +</ul> |