aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/api/html_drag_and_drop_api/index.html
blob: 5c47136d427b51710a5bb50e5ec15135ff691eb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
---
title: HTML 拖放 API
slug: Web/API/HTML_Drag_and_Drop_API
translation_of: Web/API/HTML_Drag_and_Drop_API
---
<p>{{DefaultAPISidebar("HTML Drag and Drop API")}}</p>

<p><span class="seoSummary">HTML 拖放介面能讓網頁應用程式於 Firefox 及其他瀏覽器中使用拖放功能。</span>舉例來說,使用者可以利用此功能以滑鼠選擇<em>可拖曳(draggable)</em>元素,拖曳至一個<em>可放置(droppable)</em>元素上,並放開滑鼠按鍵來放置此元素。在拖曳操作時,一個半透明的<em>可拖曳(draggable)</em>元素會跟隨著滑鼠游標。</p>

<p>對於網站、擴充套件以及 XUL 應用程式來說,你可以自定義能成為<em>可拖曳(draggable)</em>的元素類型、<em>可拖曳(draggable)</em>元素產生的回鐀類型,以及<em>可放置(droppable)</em>的元素。</p>

<p>此文件為 HTML 拖放的概述,包含了相關介面的說明、在應用程式中加入拖放支援的基本步驟,以及相關介面使用簡介。</p>

<h2 id="events" name="events">拖曳事件</h2>

<p>HTML 拖放操作基於 {{domxref("Event","DOM 事件模型")}}並且使用繼承自{{domxref("MouseEvent","滑鼠事件")}}<em>{{domxref("DragEvent","拖曳事件")}}</em>介面。一個典型的拖曳操作開始於使用者利用滑鼠選取了一個<em>可拖曳(draggable)</em>元素、移動滑鼠至一個<em>可放置(droppable)</em>元素並放開滑鼠按鍵。在操作的過程中,會觸發多種類型的事件,且一些事件類型可能會被觸發多次(如 {{event("drag")}}{{event("dragover")}} 事件類型)。</p>

<p>所有的<a href="/zh-TW/docs/Web/API/DragEvent#Event_types">拖曳事件類型</a>都有相關的<a href="/zh-TW/docs/Web/API/DragEvent#GlobalEventHandlers">通用事件處理器</a>(global event handler)。每一種拖曳事件類型及拖曳通用事件處理器屬性都有說明此事件的參考文件。以下的表格提供了每一種事件的簡要說明,以及參考文件的連結。</p>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">事件</th>
   <th scope="col">事件處理器屬性</th>
   <th scope="col">說明</th>
  </tr>
  <tr>
   <td>{{event('drag')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondrag','ondrag')}}</td>
   <td>於一個元素或文字選取區塊被拖曳時觸發。</td>
  </tr>
  <tr>
   <td>{{event('dragend')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondragend','ondragend')}}</td>
   <td>於拖曳操作結束時觸發(如放開滑鼠按鍵或按下鍵盤的 escape 鍵)。(請參考<a href="/en-US/docs/DragDrop/Drag_Operations#dragend" title="Finishing a Drag">結束拖曳</a>。)</td>
  </tr>
  <tr>
   <td>{{event('dragenter')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondragenter','ondragenter')}}</td>
   <td>於一個元素或文字選取區塊被拖曳移動進入一個有效的放置目標時觸發。(請參考<a href="/en-US/docs/DragDrop/Drag_Operations#droptargets" title="Specifying Drop Targets">指定拖曳目標</a>。)</td>
  </tr>
  <tr>
   <td>{{event('dragexit')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondragexit','ondragexit')}}</td>
   <td>當一個元素不再是被選取中的拖曳元素時觸發。</td>
  </tr>
  <tr>
   <td>{{event('dragleave')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondragleave','ondragleave')}}</td>
   <td>於一個元素或文字選取區塊被拖曳移動離開一個有效的放置目標時觸發。</td>
  </tr>
  <tr>
   <td>{{event('dragover')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondragover','ondragover')}}</td>
   <td>於一個元素或文字選取區塊被拖曳移動經過一個有效的放置目標時觸發(每幾百毫秒觸發一次)。</td>
  </tr>
  <tr>
   <td>{{event('dragstart')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondragstart','ondragstart')}}</td>
   <td>於使用者開始拖曳一個元素或文字選取區塊時觸發。(請參考<a href="/en-US/docs/DragDrop/Drag_Operations#dragstart" title="Starting a Drag Operation">開始拖曳</a>。)</td>
  </tr>
  <tr>
   <td>{{event('drop')}}</td>
   <td>{{domxref('GlobalEventHandlers.ondrop','ondrop')}}</td>
   <td>於一個元素或文字選取區塊被放置至一個有效的放置目標時觸發。(請參考<a href="/en-US/docs/DragDrop/Drag_Operations#drop" title="Performing a Drop">執行放置</a>。)</td>
  </tr>
 </tbody>
</table>

<p class="note">注意:<code>dragstart</code><code>dragend</code> 事件,在把檔案從作業系統拖放到瀏覽器時,並不會觸發。</p>

<h2 id="介面">介面</h2>

<p>HTML 拖放介面有 {{domxref("DragEvent")}}{{domxref("DataTransfer")}}{{domxref("DataTransferItem")}} 以及 {{domxref("DataTransferItemList")}}</p>

<p>{{domxref("DragEvent")}} 介面擁有一個建構式及一個屬性-{{domxref("DragEvent.dataTransfer","dataTransfer")}} 屬性為一個 {{domxref("DataTransfer")}} 物件。{{domxref("DataTransfer")}} 物件包含了拖放事件的狀態,如正在進行的拖放事件類型(例如 <code>copy</code><code>move</code>)、拖放中的資料(一或多個項目)以及每一個<em>拖放項目(drag item)</em>的檔案類型(MIME type)。{{domxref("DataTransfer")}} 物件也擁有加入及移除拖放資料項目的方法。{{domxref("DragEvent")}}{{domxref("DataTransfer")}} 介面應該是唯一須要加至應用程式中的 HTML 拖放功能。另外,請留意 Firefox 支援了一些 {{anch("Gecko specific interfaces","Gecko-specific 擴充")}}{{domxref("DataTransfer")}} 物件使用,雖然這些擴充只能在 Firefox 上作用。</p>

<p>每個 {{domxref("DataTransfer")}} 物件都包含了 {{domxref("DataTransfer.items","items")}} 屬性。此屬性乃 {{domxref("DataTransferItem")}} 物件的 {{domxref("DataTransferItemList","list")}}。而每個 {{domxref("DataTransferItem")}} 物件,則代表著一個<em>拖放單元</em>,每個拖放單元則擁有代表該資料<em>種類</em>{{domxref("DataTransferItem.kind","kind")}} 屬性(<code>string</code><code>file</code>)、還有表示該單元檔案類型(如 MIME)的{{domxref("DataTransferItem.type","type")}} 屬性。另外,{{domxref("DataTransferItem")}} 物件能取得拖放單元的資料。</p>

<p>{{domxref("DataTransferItemList")}} 物件為 {{domxref("DataTransferItem")}} 的列表。該物件列表擁有以下方法:給列表增加拖放單元、從列表刪除拖放單元、還有清除列表內所有的拖放單元。</p>

<p>{{domxref("DataTransfer")}}{{domxref("DataTransferItem")}} 介面的最大不同,就是前者使用同步的 {{domxref("DataTransfer.getData","getData()")}} 方法訪問拖放單元的資料;後者則使用非同步的 {{domxref("DataTransferItem.getAsString","getAsString()")}} 方法訪問。</p>

<p class="note">注意:{{domxref("DragEvent")}}{{domxref("DataTransfer")}} 介面受廣泛的桌面瀏覽器支援。但只有少數瀏覽器支援 {{domxref("DataTransferItem")}}{{domxref("DataTransferItemList")}} 介面。請參見 <a href="#interoperability">Interoperability</a> 以取得有關拖放功能互通性的資訊。</p>

<h3 id="Gecko-specific_interfaces">Gecko-specific interfaces</h3>

<p>Mozilla and Firefox support some features not in the standard drag and drop model. These are <em>convenience functions</em> to facilitate dragging multiple items and dragging non-string data (such as files). For more information, see <a href="/en-US/docs/DragDrop/Dragging_and_Dropping_Multiple_Items" title="Dragging and Dropping Multiple Items">Dragging and Dropping Multiple Items</a>. Additionally, see the {{domxref("DataTransfer")}} reference page for all of the <a href="/en-US/docs/Web/API/DataTransfer#Gecko_properties">Gecko-specific properties</a> and <a href="/en-US/docs/Web/API/DataTransfer#Gecko_methods">Gecko-specific methods</a>.</p>

<h2 id="基本用法">基本用法</h2>

<p>This section provides a summary of the basic steps to add drag and drop functionality to an application. Each section includes a description of the step, a short code example, and links to additional information.</p>

<h3 id="Identify_what_is_draggable">Identify what is <em>draggable</em></h3>

<p>To make an element <em>draggable</em> requires adding the {{htmlattrxref("draggable")}} attribute plus the {{domxref("GlobalEventHandlers.ondragstart","ondragstart")}} global event handler, as shown in the following code sample</p>

<pre class="brush: js">function dragstart_handler(ev) {
 console.log("dragStart");
 // Add the target element's id to the data transfer object
 ev.dataTransfer.setData("text/plain", ev.target.id);
}

&lt;body&gt;
 &lt;p id="p1" draggable="true" ondragstart="dragstart_handler(event);"&gt;This element is draggable.&lt;/p&gt;
&lt;/body&gt;
</pre>

<p>See the <a href="/en-US/docs/Web/HTML/Global_attributes/draggable" title="draggable global attribute">draggable attribute reference</a> and the <a href="/en-US/docs/Web/Guide/HTML/Drag_operations#draggableattribute">Drag operations guide</a> for more information.</p>

<h3 id="Define_the_drag's_data">Define the drag's data</h3>

<p>The application is free to include any number of data items in a drag operation. Each data item is a {{domxref("DOMString","string")}} of a particular <code>type</code>, typically a MIME type such as <code>text/html</code>.</p>

<p>Each {{domxref("DragEvent","drag event")}} has a {{domxref("DragEvent.dataTransfer","dataTransfer")}} property that <em>holds</em> the event's data. This property (which is a {{domxref("DataTransfer")}} object) also has methods to <em>manage</em> drag data. The {{domxref("DataTransfer.setData","setData()")}} method is used to add an item to the drag data, as shown in the following example.</p>

<pre class="brush: js">function dragstart_handler(ev) {
  // Add the drag data
  ev.dataTransfer.setData("text/plain", ev.target.id);
  ev.dataTransfer.setData("text/html", "&lt;p&gt;Example paragraph&lt;/p&gt;");
  ev.dataTransfer.setData("text/uri-list", "http://developer.mozilla.org");
}
</pre>

<p>For a list of common data types used for drag and drop (such as text, HTML, links, and files), see <a href="/en-US/docs/DragDrop/Recommended_Drag_Types" title="Recommended Drag Types">Recommended Drag Types</a> and for more information about drag data, see <a href="/en-US/docs/Web/Guide/HTML/Drag_operations#dragdata" title="Drag Data">Drag Data</a>.</p>

<h3 id="Define_the_drag_image">Define the drag image</h3>

<p>By default, the browser supplies an image that appears beside the mouse pointer during a drag operation. However, an application may define a custom image by using the {{domxref("DataTransfer.setDragImage","setDragImage()")}} method as shown in the following example.</p>

<pre class="brush: js">function dragstart_handler(ev) {
  // Create an image and then use it for the drag image.
  // NOTE: change "example.gif" to an existing image 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);
}
</pre>

<p>To learn more about drag feedback images, see <a href="/en-US/docs/DragDrop/Drag_Operations#dragfeedback" title="Setting the Drag Feedback Image">Setting the Drag Feedback Image</a>.</p>

<h3 id="Define_the_drag_effect">Define the drag <em>effect</em></h3>

<p>The {{domxref("DataTransfer.dropEffect","dropEffect")}} property is used to control the feedback (typically visual) the user is given during a drag and drop operation. It affects which cursor the browser displays while dragging. For example, when the user hovers over a target drop element, the browser's cursor may indicate the type of operation that will occur.</p>

<p>Three effects may be defined:</p>

<p><code>copy</code> indicates that the data being dragged will be copied from its present location to the drop location.</p>

<p><code>move</code> indicates that the data being dragged will be moved</p>

<p><code>link</code> indicates that some form of relationship or connection will be created between the source and drop locations.</p>

<p>During the drag operation, the drag effects may be modified to indicate that certain effects are allowed at certain locations. If allowed, a drop may occur at that location.</p>

<p>The following example shows how to use this property.</p>

<pre class="brush: js">function dragstart_handler(ev) {
  // Set the drag effect to copy
  ev.dataTransfer.dropEffect = "copy";
}
</pre>

<p>See <a href="/en-US/docs/Web/Guide/HTML/Drag_operations#drageffects" title="Drag Effects">Drag Effects</a> for more details.</p>

<h3 id="Define_a_drop_zone">Define a <em>drop zone</em></h3>

<p>By default, the browser prevents anything from happening when dropping something onto the HTML element. To change that behavior so that an element becomes a <em>drop zone</em> or is <em>droppable</em>, the element must have both {{domxref("GlobalEventHandlers.ondragover","ondragover")}} and {{domxref("GlobalEventHandlers.ondrop","ondrop")}} event handler attributes. The following example shows how to use those attributes and includes basic event handlers for each attribute.</p>

<pre class="brush: js">function dragover_handler(ev) {
 ev.preventDefault();
 // Set the dropEffect to move
 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");
 ev.target.appendChild(document.getElementById(data));
}
&lt;body&gt;
 &lt;div id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);"&gt;Drop Zone&lt;/div&gt;
&lt;/body&gt;
</pre>

<p>Note each handler calls {{domxref("Event.preventDefault","preventDefault()")}} to prevent additional event processing for this prevent (such as touch events or pointer events).</p>

<p>For more information, see <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets">Specifying Drop Targets</a>.</p>

<h3 id="Handle_the_drop_effect">Handle the drop <em>effect</em></h3>

<p>The handler for the {{event("drop")}} event is free to process the drag data in an application specific way. Typically, an application will use the {{domxref("DataTransfer.getData","getData()")}} method to retrieve drag items and process them accordingly. Additionally, application semantics may differ depending on the value of the {{domxref("DataTransfer.dropEffect","dropEffect")}} and/or the state of modifier keys.</p>

<p>The following example shows a drop handler getting the source element's id from the drag data and then using the id to move the source element to the drop element.</p>

<pre class="brush: js">function dragstart_handler(ev) {
 // Add the target element's id to the data transfer object
 ev.dataTransfer.setData("text/plain", ev.target.id);
 ev.dropEffect = "move";
}
function dragover_handler(ev) {
 ev.preventDefault();
 // Set the dropEffect to move
 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");
 ev.target.appendChild(document.getElementById(data));
}
&lt;body&gt;
 &lt;p id="p1" draggable="true" ondragstart="dragstart_handler(event);"&gt;This element is draggable.&lt;/p&gt;
 &lt;div id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);"&gt;Drop Zone&lt;/div&gt;
&lt;/body&gt;
</pre>

<p>For more information, see <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#drop">Performing a Drop</a>.</p>

<h3 id="Drag_end">Drag end</h3>

<p>At the end of a drag operation, the {{event("dragend")}} event fires at the <em>source</em> element - the element that was the target of the drag start. This event fires whether the drag completed or was canceled. The {{event("dragend")}} event handler can check the value of the {{domxref("DataTransfer.dropEffect","dropEffect")}} property to determine if the drag operation succeeded or not.</p>

<p>For more information about handling the end of a drag operation, see <a href="/en-US/docs/DragDrop/Drag_Operations#dragend" title="Finishing a Drag">Finishing a Drag</a>.</p>

<h2 id="Interoperability">Interoperability</h2>

<p>As can be seen in the <a href="/en-US/docs/Web/API/DataTransferItem#Browser_compatibility">DataTransferItem interface's Browser Compatibility table</a>, drag-and-drop interoperability is relatively broad among desktop browsers (except the {{domxref("DataTransferItem")}} and {{domxref("DataTransferItemList")}} interfaces have less support). This data also indicates drag and drop support among mobile browsers is very low.</p>

<h2 id="Examples_and_demos" name="Examples_and_demos">Examples and demos</h2>

<ul>
 <li><a href="https://mdn.github.io/dom-examples/drag-and-drop/copy-move-DataTransfer.html">Copying and moving elements with the <code>DataTransfer</code> interface</a></li>
 <li><a href="http://mdn.github.io/dom-examples/drag-and-drop/copy-move-DataTransferItemList.html">Copying and moving elements with the <code>DataTransferListItem</code> interface</a></li>
 <li>Dragging and dropping files; Firefox only: <a class="external" href="http://jsfiddle.net/9C2EF/" title="http://jsfiddle.net/9C2EF/">http://jsfiddle.net/9C2EF/</a></li>
 <li>Dragging and dropping files; All browsers: <a class="external" href="https://jsbin.com/hiqasek/edit?html,js,output" title="https://jsbin.com/hiqasek">https://jsbin.com/hiqasek/</a></li>
 <li>A parking project using the Drag and Drop API: <a href="https://park.glitch.me/">https://park.glitch.me/</a> (You can edit <a href="https://glitch.com/edit/#!/park">here</a>)</li>
</ul>

<h2 id="See_also" name="See_also">參見</h2>

<ul>
 <li><a class="internal" href="/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations" title="Drag Operations">Drag Operations</a></li>
 <li><a class="internal" href="/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Multiple_items" title="Dragging and Dropping Multiple Items">Dragging and Dropping Multiple Items</a></li>
 <li><a class="internal" href="/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types" title="Recommended Drag Types">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>
 <li><a href="http://caniuse.com/#search=draganddrop" title="Drag and Drop interoperability data from CanIUse">Drag and Drop interoperability data from CanIUse</a></li>
</ul>