Menu

Drag And Drop Image Upload In JavaScript

Drag And Drop Image Upload In JavaScript

File Uploads have yet to really catch up with the times and with technology. Many reasons for this. Security being a major one. It's an open door between the outside world and a server. And we can't just let any old file through to wreak havoc, if havoc is what it's there to wreak. So today I will be going over how to implement a file drag and drop module on your sites.

It's a somewhat involved process, and for sake of momentum I will focus on just the new standards that will make this happen, and I will leave out any compatability code.

Overview

The following will walk you through adding the ever so popular drag and drop file upload feature that we see on many a site. This example will only work on an HTML 5 compliant browser. However, you can easily detect if the browser supports said feature by checking if any of the drag events are supported.

Create a drop zone

First things first, we'll want to set up a drop zone for our files. This will be a pre-determined area somewhere on your site in which users will be able to drag files to. You'll want to make sure that it is designed in a way that will immediately tell the user that it is an area meant for dragging content into. Here's an example of a drop zone that I use on some of my sites.

Drag your file right over here!

It's quick and to the point, and it gives users plenty of room to drag their files into.

Tip #1: Don't give users a tiny area to drop files into

Style the drop zone

Feel free to use the following classes to style your dropzone.


.drag-drop{
    width: 100%;
    /* height: 100px; */
    background-color: #1caff6;
    margin-top: 30px;
    border-radius: 10px;
    border: dashed 2px white;
    color: white;
    text-align: center;
    padding-top: 40px;
    padding-bottom: 40px;
    font-size: 14pt;
    transition: .5s background-color, .5s color;
    height: 100px;
    font-family:inherit;
}

.drag-drop.dragover{
    background-color: #0e384c;
    color: white;
}

.drag-drop.uploading{
    background-color: #0e384c;
    color: white;
}

The dragover and uploading classes will be dynamically added during the corresponding event handlers in the JavaScript down below.

Setup the form

We will use a single input element setting the type to file. To read more about the File API, you can check out the Mozilla Developer Network page. The important parts to remember for this post however are as follows. You'll want your input form to look something like the following:


<form id="drag_files" class="drag-drop" method="post" action="" enctype="multipart/form-data" novalidate>
    <input type="file" name="files[]" id="files" multiple />
    <div class="drag-files-label">
        Drag your file right over here!
    </div>
</form>

A few things to notice in the above markup. Firstly, notice that I set the enctype of the form to multipart/form-data. Secondly, notice that I set the type of the input to file. This is an HTML 5 API and will not work on older browsers. Lastly notice the multiple specifier that we added to our input. That is also an HTML 5 property that allows our input to accept multiple files.

The drag events

There are a few events that will need to be handled in order to have a smooth and seemless process for our drag and drop. And we can start the process, by disabling the default behavior from each.


var form = document.getElementById("drag_files");
var input = form.querySelector('input[type="file"]');

window.addEventListener('load', function(){
    ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function (event) {
         form.addEventListener(event, function (e) {
         // preventing the unwanted behaviours
                 e.preventDefault();
                 e.stopPropagation();
             });
         });
});

We'll want to let the user know when they arrive at the drop zone with their files. So for any event in which the mouse is dragging an item onto the zone, we'll want to add a 'dragover' class to our main form.


['dragover', 'dragenter'].forEach(function (event) {
     form.addEventListener(event, function () {
         form.classList.add('dragover');
     });
 });

['dragleave', 'dragend', 'drop'].forEach(function (event) {
    form.addEventListener(event, function () {
        form.classList.remove('dragover');
    });
});

Next up, we'll want to handle the actual drop event.


var droppedFiles;

form.addEventListener('drop', function (e) {
    droppedFiles = e.dataTransfer.files; // the files that were dropped

    if (droppedFiles.length > 0)
    {
        form.querySelector(".drag-files-label").innerHTML = droppedFiles[0].name;

        // optional - submit the form on drop
        var event = document.createEvent('HTMLEvents');
        event.initEvent('submit', true, false);
        form.dispatchEvent(event);
    }
});

The drop event provides us with the DataTransfer object, which further gives us the list of File objects that were dropped. For the sake of the example, I've only taken the name of the first file and added it to the dropzone. If you so wanted, you could submit the form on drop, which would begin the upload process as soon as your mouse was de-clicked.

Because we have all of our files stored in the droppedFiles object, we can easily push this data to the form. Whether you want to submit the form immediately, or later on in the process, you'll want to use the following method to do so.


     form.addEventListener('submit', function (e) {
         if (form.classList.contains('uploading'))
             return false;

             form.classList.add('uploading');
             e.preventDefault();

             // gathering the form data
             var ajaxData = new FormData(form);
             if (droppedFiles) {
                 Array.prototype.forEach.call(droppedFiles, function (file) {
                     ajaxData.append(input.getAttribute('name'), file);
                 });
             }

For each file that is stored in our droppedFiles object, we'll want to add those to a new formData object, of which you can read more about here. Next up, we're just going to create a standard Ajax request and send our form data along with it.


             // ajax request
             var ajax = new XMLHttpRequest();
             ajax.open(form.getAttribute('method'), form.getAttribute('action'), true);

             ajax.onload = function () {
                 form.classList.remove('uploading');
                 if (ajax.status >= 200 && ajax.status < 400) {
                    // do what you will :)
                 }
                 else {
                     alert('Error. Please, contact the webmaster!');
                 }
             };

             ajax.send(ajaxData);
     });

Feel free to customize the code anyway that you wish, and if you found it useful, feel free to send me a message as well. The full source is down below for your copy and paste pleasure.

View full source
Walter G. author of blog post
Walter Guevara is a Computer Scientist, software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20 years.

Get the latest programming news directly in your inbox!

Have a question on this article?

You can leave me a question on this particular article (or any other really).

Ask a question

Community Comments

No comments posted yet

Add a comment