Implementing Drag-Drop for File Input on the Web.

Felix Owino - Jul 16 - - Dev Community

Drag-drop is one of the most engaging ways of transferring files between windows on a computer. All modern file explorers come with this functionality. Browsers also happen to have a default behavior to drag-drop. By default, the browser will try to open a file dropped into it unless it is programmed to do something else. In this article, we will learn how to program the browser to treat a drag-drop as a file input operation. We will also extend the program to allow us to open the file input dialog and select a file by clicking the drop-drop target.

Implementing actions during drag-drop can be done using the DragEvent interface provided in the browser by JavaScript. The DragEvent interface provides several events from when a drag begins to when it ends. In this article, we will leverage the power of the DragEvent interface to create a drag-drop file input user interface.

We will implement the proposed user interface in the following order:

  1. Create the HTML Markup
  2. Style the Markup
  3. Make it interactive
  4. Style the interaction
  5. Make it clickable

Let's begin ...

1. Create the HTML Markup

Before going any further into the article, let us create a simple HTML markup.

index.html

<body>
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Drag and Drop File Upload</title>
      <link rel="stylesheet" href="./style.css">
    </head>
    <body>
      <div id="drop-zone" class="drop-zone">
        <p>Drag & drop files here or click to upload</p>
      </div>
      <script src="./drag-drop.js"></script>
    </body>
    </html>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

2. Style the Markup

The following stylesheet provides a few basic styles for the page.

style.css

body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }

  .drop-zone {
    width: 300px;
    height: 200px;
    border: 2px dashed #007bff;
    border-radius: 4px;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    color: #007bff;
    cursor: pointer;
    transition: background-color 0.2s ease;
  }
Enter fullscreen mode Exit fullscreen mode

The above markup and style create a container with a blue dotted border and prompt text. The screenshot below shows what we have just created when opened in the browser.

The Drop zone container

3. Make it interactive

Dragging and dropping files into the dotted container or clicking it to input files won't work just yet. We need JavaScript for that part. In the script, we will add various event listeners to elements in the document. The first event we will listen for is the DOMContentLoaded event on the document.

document.addEventListener('DOMContentLoaded', () => {

})
Enter fullscreen mode Exit fullscreen mode

You might be wondering what the DOMContentLoaded event is and how it is different from the load event. Even more, why did we choose to use it over the load event?

The DOMContentLoaded event is fired as soon as the DOM tree has been created. This event does not wait for other resources such as the styles, images, data, and other external resources to be loaded. The DOMContentLoaded is fired as soon as the elements of the page have been inserted into the DOM tree. On the other hand, the load event waits a little longer before it is fired. The load event is fired after all the resources of a page including styles, images, fetched data, and all other external resources have been loaded into the browser.

Our interest in this project has nothing to do with external resources but everything to do with a few DOM elements. This is the reason why we are choosing to use the DOMContentLoaded event over the load event. The load event could work just as well but we do not need to wait for that long. We want to attach the event listeners to the target element as soon as they are added to the DOM.

We will perform all subsequent operations and listen for all the other required events within the DOMContentLoaded event handler.

The drop zone container

We want to make the drop zone container aware of the drag-drop interaction. Here, we will tell the browser what to do when a file is dropped within the borders of the drop-zone container.

First, we need to get the drop zone container element from the DOM as done below.

document.addEventListener('DOMContentLoaded', () => {
    const dropZone = document.querySelector('#drop-zone')
})
Enter fullscreen mode Exit fullscreen mode

Next, we attach the drop event to the drop zone container and provide an event handler.

dropZone.addEventListener('drop', (event) =>{

    })
Enter fullscreen mode Exit fullscreen mode

In the event handler, we will program the browser to treat the drag-and-drop interactions as a file input. This means that if the file is dragged and dropped within the borders of the drop zone container, the browser will override its default behavior with the program in the event handler function. You can do anything with the dropped file. In our case, we will simply log the file information in the browser's console. Below is the implementation:

dropZone.addEventListener('dragover', (event) =>{
        event.preventDefault()

    })

 dropZone.addEventListener('drop', (event) =>{
        event.preventDefault()

        const files = event.dataTransfer.files

        console.log(files)
    })
Enter fullscreen mode Exit fullscreen mode

The code snippet above adds two even listeners to the drop zone container, the dragover and the drop events.

Technically, we only care about dropping the file within the borders of the container. So why bother with the dragover event? We take care of the dragover event because we are dragging the file over the drop zone container before we can drop it and the browser has a default behavior to the dragover event. The least we can do about the default behavior of the browser is to prevent it. We access the files array from event.dataTransfer and log the list on the browser console.

Everything works well but the look, not very much so. In the next section, we will add styles to the process.

4. Style the interaction

What if you wanted to do more than prevent the default behavior of the browser? What if you intend to change the background color of the drag zone container throughout the process? Say one color when dragging over the drop zone container, a different color when you drag past the borders of the target container, and another color when you drop the file in the intended container. Well, that can easily be done as shown below.

 dropZone.addEventListener('dragover', (event) =>{
        event.preventDefault()

        dropZone.style.backgroundColor = '#e0e0e0'
    })

    dropZone.addEventListener('dragleave', () =>{
        dropZone.style.backgroundColor = '#eb6363a6'
    })

    dropZone.addEventListener('drop', (event) =>{
        event.preventDefault()

        dropZone.style.backgroundColor = '#f0f0f0'

        const files = event.dataTransfer.files

        console.log(files)
    })
Enter fullscreen mode Exit fullscreen mode

The adjustments above involve altering the background color of the drop zone container from the initial background color to a gray color when the file is dragged into the drop zone container. The color changes to a shade of red if the drag leaves the container without dropping the file. Dropping the file resets the color to the initial background color.

That's all good but didn't we say we could also click it? Up next ...

5. Make it clickable

The prompt in the container says we can also click the box to input a file. Unfortunately, clicking the box now doesn't open the file explorer as promised. How can we fix that? You guessed it right, add a click event listener to the container.

 dropZone.addEventListener('click', () =>{

    })
Enter fullscreen mode Exit fullscreen mode

We have added the click event listener, now what?

In standard user interfaces, we trigger the opening of the file explorer by clicking a file input element that is displayed on a web page. In our case, we don't want to display a file input element. Lucky for us, we can add the element to the DOM and hide it from display using the hidden attribute. We can also click it programmatically using JavaScript.

Extend the initial HTML markup to include the input element as shown below:

<body>
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Drag and Drop File Upload</title>
      <link rel="stylesheet" href="./style.css">
    </head>
    <body>
      <div id="drop-zone" class="drop-zone">
        <p>Drag & drop files here or click to upload</p>
        <input type="file" id="file-input" multiple hidden>
      </div>
      <script src="./drag-drop.js"></script>
    </body>
    </html>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The hidden attribute allows us to exclude the input element from the display while keeping it in the DOM tree.

Now that we have the input element in the DOM, we can access it from our JS scripts and click it programmatically when the drop zone container is clicked. The code snippet below implements the program.

dropZone.addEventListener('click', () =>{

        const fileInputElement = document.querySelector('input')
        fileInputElement.click()
    })
Enter fullscreen mode Exit fullscreen mode

Summary

That is how we create a clickable drag-drop file input user interface. The drag-drop file input user interface uses the DragEvent interface which provides the dragover, dragleave, drop, and other browser events. When implementing the drag-drop file input, it is important to alter the styles of the drop target to improve the user experience. In addition to the drag-drop input, users will always appreciate an additional option for clicking the drop zone to open the file explorer. You can add a hidden file input element to your markup and click it programmatically when the drop zone is clicked. That's all for the article, thanks for reading. Feel free to say something in the comments section. Bye bye.

Read more about the DragEvent interface on MDN.

. . . . . . . . . . . . . . . . . . . .
Terabox Video Player