Hi! This time let's look at how we can drag and drop files into a document.
So, the first thing you must know is that, by default, the browser does things when you drag and drop.
If I drag and drop an image, it just shows the image in full size in a new tab.
If I drag and drop a video, the browser will just play it using a default player.
So, if you want to drag and drop some multimedia files, we will have to take care and prevent this default behavior.
So first, let's look at a more simple example.
We will just drag and drop files, one or multiple files into a drop zone.
The first thing you must know… (ok, I wanted to drag and drop multiple files but I missed the multiple selection…) OK, it work with multiple files.
So the first thing you must know is that we can't have a dragstart handler, there is no need for a dragstart handler.
As soon as you drop files in a document, the file descriptors are copied in the drag and drop clipboard.
The source code is much simpler than the one we saw in the previous videos.
So here we define a drop zone, a div called droppableZone, with a dragenter, drop, dragover and dragleave event listeners.
We also created an empty numbered list inside the div … this is the container that will be used to display the file names here.
What do we do in order to prevent this default behavior?
Because if I drag and drop an image in this div without taking some precautions, it will just open a new tab with the image.
So, in the different drop and dragover handlers we will have to call event.preventDefault() for preventing this default behavior and we also call stopPropagation(), so that the event will not go to the parents of the div... and in case they will also have this default behavior triggered.
As we don't have any dragstart handler, and the files are copied directly into the drag and drop clipboard, we get back the files using event.dataTransfer.files.
We are not using a key to get the value here, it is just files.
It is the same name and the same content we got when we use an onchange listener on an input type="file".
Each element (from files) has the same properties we saw in the HTML5 Part 1 course about forms, and in particular about the input type="file".
We get the files that have been copied into the clipboard and then we do a loop on the files, we get the current file name here, and we create a list item and we just set the text content.
Then we append the list item that has the file name as its content, to the dropped zone.
That's all, it is very easy, you drag and drop files... in the drop handler you stop the propagation, prevent the default behavior, get the files property with all the files copied, do a loop and process them.
That's all.
Bye, bye!
Try the example below directly in your browser (just drag and drop files to the greyish drop zone), or play with it at CodePen:
Complete source code from the example:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
div {
height: 150px;
width: 350px;
float: left;
border: 2px solid #666666;
background-color: #ccc;
margin-right: 5px;
border-radius: 10px;
box-shadow: inset 0 0 3px #000;
text-align: center;
cursor: move;
}
.dragged {
border: 2px dashed #000;
background-color: green;
}
.draggedOver {
border: 2px dashed #000;
background-color: green;
}
</style>
<script>
function dragLeaveHandler(event) {
console.log("drag leave");
// Set style of drop zone to default
event.target.classList.remove('draggedOver');
}
function dragEnterHandler(event) {
console.log("Drag enter");
// Show some visual feedback
event.target.classList.add('draggedOver');
}
function dragOverHandler(event) {
//console.log("Drag over a droppable zone");
// Do not propagate the event
event.stopPropagation();
// Prevent default behavior, in particular when we drop images or links
event.preventDefault();
}
function dropHandler(event) {
console.log('drop event');
// Do not propagate the event
event.stopPropagation();
// Prevent default behavior, in particular when we drop images or links
event.preventDefault();
// reset the visual look of the drop zone to default
event.target.classList.remove('draggedOver');
// get the files from the clipboard
var files = event.dataTransfer.files;
var filesLen = files.length;
var filenames = "";
// iterate on the files, get details using the file API
// Display file names in a list.
for(var i = 0 ; i < filesLen ; i++) {
filenames += '\n' + files[i].name;
// Create a li, set its value to a file name, add it to the ol
var li = document.createElement('li');
li.textContent = files[i].name; document.querySelector("#droppedFiles").appendChild(li);
}
console.log(files.length + ' file(s) have been dropped:\n' + filenames);
}
</script>
</head>
<body>
<h2>Drop your files here!</h2>
<div id="droppableZone" ondragenter="dragEnterHandler(event)" ondrop="dropHandler(event)"
ondragover="dragOverHandler(event)" ondragleave="dragLeaveHandler(event)">
Drop zone
<ol id="droppedFiles"></ol>
</div>
<body>
<html>
Note that:
We prevented the browser default behavior in the drop and dragover handlers Otherwise, if we dropped a media file (an image, an audio of video file), the browser would try to display/play it in a new window/tab. We also stop the propagation for performance reasons, because when we drag an object it can raise many events within the parents of the drop zone element as well.
Lines 73-74 create a <li> element. Its value is initialized with the file name of the current file in the collection, and added to the <ol> list.
In principle, this example is very similar to the "fruit" examples we worked through earlier, except that this time we're working with files. And when we work with files, it is important to prevent the browser's default behavior.