You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: files/en-us/web/api/html_drag_and_drop_api/drag_data_store/index.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ page-type: guide
6
6
7
7
{{DefaultAPISidebar("HTML Drag and Drop API")}}
8
8
9
-
The {{domxref("DragEvent")}} interface has a {{domxref("DragEvent.dataTransfer","dataTransfer")}} property, which is a {{domxref("DataTransfer")}} object. {{domxref("DataTransfer")}} objects represent the main context of the drag operation, and it stays consistent across the firing of different events. It includes the [drag data](/en-US/docs/Web/API/HTML_Drag_and_Drop_API#drag_data_store), drag image, drop effect, etc. This article focuses on the _data store_ part of the `dataTransfer`.
9
+
The {{domxref("DragEvent")}} interface has a {{domxref("DragEvent.dataTransfer","dataTransfer")}} property, which is a {{domxref("DataTransfer")}} object. {{domxref("DataTransfer")}} objects represent the main context of the drag operation, and it stays consistent across the firing of different events. It includes the [drag data](/en-US/docs/Web/API/HTML_Drag_and_Drop_API#drag_data_store), [drag image](/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#setting_the_drag_feedback_image), [drop effect](/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#drop_effects), etc. This article focuses on the _data store_ part of the `dataTransfer`.
10
10
11
11
## DataTransfer, DataTransferItem, and DataTransferItemList
event.dataTransfer.setData("text/plain", "This text may be dragged");
35
+
});
36
36
```
37
37
38
38
You could also listen to a higher ancestor as drag events bubble up as most other events do. For this reason, it is common to also check the event's target, so that dragging a selection contained within this element does not trigger the `setData` (although selecting text within the element is hard, it is not impossible):
@@ -304,13 +304,15 @@ The {{domxref("HTMLElement/dragover_event", "dragover")}} event will fire at the
304
304
305
305
Finally, the {{domxref("HTMLElement/dragleave_event", "dragleave")}} event will fire at an element when the drag leaves the element. This is the time when you should remove any insertion markers or highlighting. You do not need to cancel this event. The {{domxref("HTMLElement/dragleave_event", "dragleave")}} event will always fire, even if the drag is cancelled, so you can always ensure that any insertion point cleanup can be done during this event.
306
306
307
+
For a practical example of using these events, see our [Kanban board example](/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Kanban_board#inserting_at_a_particular_location).
308
+
307
309
## Performing a drop
308
310
309
311
When the user releases the mouse, the drag and drop operation ends.
310
312
311
313
In order for the drop to be _potentially successful_, the drop must happen over a valid [drop target](#dragging_over_elements_and_specifying_drop_targets), and the `dropEffect` must not be `none` at the time of mouse release. Otherwise, the drop operation is considered [failed](#a_failed_drop).
312
314
313
-
If the drop is potentially successful, a {{domxref("HTMLElement/drop_event", "drop")}} event is fired on the drop target. You need to cancel this event using `preventDefault()` in order for the drop to be considered actually successful. Otherwise, the drop is also considered successful if the drop was dropping text (the data contains a `text/plain` item) into an editable text field. In this case, the text is inserted into the field (either at the cursor position or at the end, depending on platform conventions) and, if the `dropEffect` is `move` while the source is a selection within an editable region, the source is removed. Otherwise, for all other drag data and drop targets, the drop is also considered failed by default.
315
+
If the drop is potentially successful, a {{domxref("HTMLElement/drop_event", "drop")}} event is fired on the drop target. You need to cancel this event using `preventDefault()` in order for the drop to be considered actually successful. Otherwise, the drop is also considered successful if the drop was dropping text (the data contains a `text/plain` item) into an editable text field. In this case, the text is inserted into the field (either at the cursor position or at the end, depending on platform conventions) and, if the `dropEffect` is `move` while the source is a selection within an editable region, the source is removed. Otherwise, for all other drag data and drop targets, the drop is considered failed.
314
316
315
317
During the {{domxref("HTMLElement/drop_event", "drop")}} event, you should retrieve that data that was dropped from the event and insert it at the drop location. You can use the {{domxref("DataTransfer.dropEffect","dropEffect")}} property to determine which drag operation was desired. The `drop` event is the only time when you can read the drag data store, other than `dragstart`.
HTML Drag and Drop interfaces enable web applications to drag and drop files on a web page. This document describes how an application can accept one or more files that are dragged from the underlying platform's _file manager_and dropped on a web page.
9
+
As mentioned on [the landing page](/en-US/docs/Web/API/HTML_Drag_and_Drop_API#concepts_and_usage), the Drag and Drop API simultaneously models three use cases: dragging elements within a page, dragging data out of a page, and dragging data into a page. This tutorial demonstrates the third use case: dragging data into a page. We will be implementing a basic drop zone that admits dropping image files from the user's operation system file explorer and displays them on the page. For users who can't or don't want to use drag & drop, we also provide the alternative functionality of file selection via an `<input>` element.
10
10
11
-
The main steps to drag and drop are to define a _drop zone_ (i.e., a target element for the file drop) and to define event handlers for the {{domxref("HTMLElement/drop_event", "drop")}} and {{domxref("HTMLElement/dragover_event", "dragover")}} events. These steps are described below, including example code snippets.
11
+
## Basic page layout
12
12
13
-
## Define the drop zone
14
-
15
-
The HTML defines the drop zone as a {{htmlelement("div")}}, and an output region ({{htmlelement("pre")}}) to be populated later.
13
+
Because we want to allow normal `<input>` file selection as well, it makes sense for the drop zone to be backed by an `<input>` element so that we can simultaneously drag into it and click on it. We take advantage of a common trick, which is to make the `<input>` invisible, and use its associated {{HTMLElement("label")}} to interact with the user instead, because `<label>` elements are much easier to style. We also add the elements for previewing the dropped images.
16
14
17
15
```html live-sample___file-dnd
18
-
<divid="drop-zone">
19
-
<p>Drag one or more files to this <i>drop zone</i>.</p>
We style the label element to visually indicate the element is a drop zone, and hide the file input.
25
+
26
+
```css live-sample___file-dnd
27
+
body {
28
+
font-family: "Arial", sans-serif;
29
+
}
30
+
31
+
#drop-zone {
32
+
display: flex;
33
+
align-items: center;
34
+
justify-content: center;
35
+
width: 500px;
36
+
max-width: 100%;
37
+
height: 200px;
38
+
padding: 1em;
39
+
border: 1pxsolid#cccccc;
40
+
border-radius: 4px;
41
+
color: slategray;
42
+
cursor: pointer;
43
+
}
44
+
45
+
#file-input {
46
+
display: none;
47
+
}
48
+
49
+
#preview {
50
+
width: 500px;
51
+
max-width: 100%;
52
+
display: flex;
53
+
flex-direction: column;
54
+
gap: 0.5em;
55
+
list-style: none;
56
+
padding: 0;
57
+
}
58
+
59
+
#previewli {
60
+
display: flex;
61
+
align-items: center;
62
+
gap: 0.5em;
63
+
margin: 0;
64
+
width: 100%;
65
+
height: 100px;
66
+
}
67
+
68
+
#previewimg {
69
+
width: 100px;
70
+
height: 100px;
71
+
object-fit: cover;
72
+
}
22
73
```
23
74
24
-
As the _target element_, it listens to the {{domxref("HTMLElement/drop_event", "drop")}} event to process the dropped file.
75
+
By virtue of us using the `<label>` and `<input>` elements, no additional JavaScript is needed to implement the file selection UX. We now focus on file dropping and the subsequent processing of the dropped files.
76
+
77
+
## Declaring the drop target
78
+
79
+
Our drop target is the `<label>` element. As the _target element_, it listens to the {{domxref("HTMLElement/drop_event", "drop")}} event to process the dropped file.
In order for the `drop` event to fire, the element must also cancel the {{domxref("HTMLElement/dragover_event", "dragover")}} event. Here, we cancel the event on `window` (which would also cancel the event fired on `dropZone` as it bubbles up), because we also want to listen for the `drop` event on `window` to prevent the default browser action of opening the file when it was not dropped into the drop zone.
87
+
For file dropping, the browser may process them by default (such as opening or downloading the file) even when the file is not dropped into a valid drop target. To prevent this behavior, we also need to listen for the `drop` event on `window`and cancel it. We take care to only handle the event only if a file is being dragged; if it's something else, such as a link, we still use the default behavior. If the dragged item is a non-image file, we still handle the event, but provide feedback to the user that it is not allowed.
34
88
35
89
```js live-sample___file-dnd
36
-
window.addEventListener("dragover", (e) => {
37
-
e.preventDefault();
38
-
});
39
90
window.addEventListener("drop", (e) => {
40
-
e.preventDefault();
91
+
if ([...e.dataTransfer.items].some((item) =>item.kind==="file")) {
92
+
e.preventDefault();
93
+
}
41
94
});
42
95
```
43
96
44
-
Lastly, an application may want to style the drop target element to visually indicate the element is a drop zone. In this example, the drop target element uses the following styling:
97
+
In order for the `drop` event to fire, the element must also cancel the {{domxref("HTMLElement/dragover_event", "dragover")}} event. Because we are listening for `drop` on `window`, we need to cancel the `dragover` event for the whole `window` as well. We also set {{domxref("DataTransfer.dropEffect")}} to `none` if the file is not an image or not dragged to the correct place.
45
98
46
-
```css live-sample___file-dnd
47
-
#drop-zone {
48
-
border: 5pxsolidblue;
49
-
width: 200px;
50
-
height: 100px;
51
-
}
52
-
```
99
+
```js live-sample___file-dnd
100
+
dropZone.addEventListener("dragover", (e) => {
101
+
constfileItems= [...e.dataTransfer.items].filter(
102
+
(item) =>item.kind==="file",
103
+
);
104
+
if (fileItems.length>0) {
105
+
e.preventDefault();
106
+
if (fileItems.some((item) =>item.type.startsWith("image/"))) {
107
+
e.dataTransfer.dropEffect="copy";
108
+
} else {
109
+
e.dataTransfer.dropEffect="none";
110
+
}
111
+
}
112
+
});
53
113
54
-
```css hidden live-sample___file-dnd
55
-
div {
56
-
margin: 0em;
57
-
padding: 2em;
58
-
}
114
+
window.addEventListener("dragover", (e) => {
115
+
constfileItems= [...e.dataTransfer.items].filter(
116
+
(item) =>item.kind==="file",
117
+
);
118
+
if (fileItems.length>0) {
119
+
e.preventDefault();
120
+
if (!dropZone.contains(e.target)) {
121
+
e.dataTransfer.dropEffect="none";
122
+
}
123
+
}
124
+
});
59
125
```
60
126
61
127
> [!NOTE]
62
128
> {{domxref("HTMLElement/dragstart_event", "dragstart")}} and {{domxref("HTMLElement/dragend_event", "dragend")}} events are not fired when dragging a file into the browser from the OS. To detect when OS files are dragged into the browser, use {{domxref("HTMLElement/dragenter_event", "dragenter")}} and {{domxref("HTMLElement/dragleave_event", "dragleave")}}.
63
129
> This means that it is not possible to use {{domxref("DataTransfer.setDragImage","setDragImage()")}} to apply a custom drag image/cursor overlay when dragging files from the OS — because the drag data store can only be modified in the {{domxref("HTMLElement/dragstart_event", "dragstart")}} event. This also applies to {{domxref("DataTransfer.setData","setData()")}}.
64
130
65
-
## Process the drop
66
-
67
-
The {{domxref("HTMLElement/drop_event", "drop")}} event is fired when the user drops the file(s). In the following drop handler, the {{domxref("DataTransferItem.getAsFile","getAsFile()")}} method is used to access each file. This example shows how to write the name of each dragged file to the console. In a _real_ application, an application may want to process a file using the [File API](/en-US/docs/Web/API/File_API).
131
+
## Processing the drop
68
132
69
-
Note that in this example, any drag item that is not a file is ignored.
133
+
Now we implement the `dropHandler` by using the {{domxref("DataTransferItem.getAsFile","getAsFile()")}} method to access each file. Then your application can decide how to process this file using the [File API](/en-US/docs/Web/API/File_API). Here we just display them on the page; in practice, you probably want to eventually upload them to the server as well.
Finally we add a way to clear the preview area. We use {{domxref("URL.revokeObjectURL_static","URL.revokeObjectURL()")}} to release the memory used by the image objects.
0 commit comments