Extending AJAX file Uploader with Drag & Drop functionality
Tags: django, javascript, python, beginners
Published: 2021-07-02 18:30:28

Hello,

In the [previous article](https://dev.to/shubhamkshatriya25/ajax-file-upload-in-chunks-using-django-with-a-progress-bar-4nhi) we saw how we can upload any file chunk by chunk to a Django server using AJAX. That's pretty much good but still most of the sites allows user to drag and drop their files directly on the page and do consequent actions along with an option to browse the file.

Personally I like the drag and drop feature. It provides better user experience as well. In this article, we will see how we can also add this amazing feature to our existing uploader. Without wasting any time, let's start with the code.

[Here](https://github.com/shubhamkshatriya25/AJAX-File-Uploader/tree/browse-file-and-upload) is the code of file uploader that we created in the last article. You can directly continue from here itself or if you are interested in exploring some basics of AJAX and DJANGO, then you can visit [here](https://dev.to/shubhamkshatriya25/ajax-file-upload-in-chunks-using-django-with-a-progress-bar-4nhi). 

We are going to add some more code into our existing one so as to implement the drag and drop functionality.

#### upload.html
The most basic thing for D&D is a drop zone where users can release the files. For the drop zone we will create a div and add some css for it.

This is our updated template file.
```
{% load static %}
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
        integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
        crossorigin="anonymous">
    <title>AJAX + DJANGO File Uploader</title>
    <link rel="stylesheet" href="{% static 'css/app.css' %}">
</head>
<body>
    <div class="col-lg-6 col-md-6" style="margin: 100px auto; display: block;">
        // drop zone
        <div class="drop-box" id="dropBox" style="width: 100%; height: 400px; border: 4px dashed gray;" >
            <p style="text-align: center; vertical-align: middle; line-height: 400px; font-size: 24px; color: gray;">Drag & Drop to Upload File</p>
        </div>
        <form enctype="multipart/form-data" method="POST" action="" style="text-align: center;">
            <p style="color: gray; padding-top: 20px;">or</p>
            {% csrf_token %}
            <div class="form-group">
                <label>Select file to upload.</label>
                <input type="file" class="form-control" id="fileupload" placeholder="Select file">
            </div>
            <input type="submit" value="Upload" id="submit" class="btn btn-success">     
        </form>
        <div id="uploaded_files"></div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="{% static 'js/app.js' %}"></script>
</body>
</html>
``` 

This is how the UI will appear now.
![Output 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yyuu44eqnrez7tvb3j2c.png)

Now the user has a spot where he can drop his/her file. The questions arising in your mind could be like, How will our code know that user has entered into drop-zone? How will our code know that user has dropped the file in the drop-zone.For that exact purpose, JavaScript/ jQuery introduced events. An event is something that waits for a particular action to occur, like the click event of the button.

All we need to do is bind some events to our drop-zone that will continuously listen to the user actions. The events we need are are:
* dragenter : This event will be fired when user enters into the drop-zone
* dragover : This event will be fired when user moves over the drop-zone
* drop : This event will be fired when user drops a file into the drop-zone

With these there are plenty more events but that's all we need at the moment.

#### app.js
```
...
ondragenter = function(evt) {
    evt.preventDefault();
    evt.stopPropagation();
};

ondragover = function(evt) {
    evt.preventDefault();
    evt.stopPropagation();
};
  
ondrop = function(evt) {
    evt.preventDefault();
    evt.stopPropagation();
    const files = evt.originalEvent.dataTransfer;
    var uploader = new FileUpload(files);
    uploader.upload();
};

$('#dropBox')
    .on('dragover', ondragover)
    .on('dragenter', ondragenter)
    .on('drop', ondrop);
```

As you can see, we have created three functions namely ondragenter , ondragover and ondrop. Also we have bind them with events. We need to cancel the default behavior of browser and can achieve that using preventDefault() and stopPropagation().

When the user drops the file, it will be stored at "event.originalEvent.dataTransfer". We just need to retrieve from here. It will return an array of files. 

The next thing would be to create an instance of the FileUpload class and call the upload method with the files object as a parameter. The existing code will upload the file to the server.

These are few snapshots of the output.
![Output 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15q0uta174hqrwy7witn.png)
![Output 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wqm63ibvv8uhlfeg8gj.png)

You can find the entire code here.
{% github  shubhamkshatriya25/AJAX-File-Uploader %}

Hope this could help you to learn something new today. Thank you for your precious time.

Adios!