Drag and drop with DataTransfer Object in JavaScript

Drag and drop with DataTransfer Object in JavaScript

Learn how the DataTransfer object powers drag-and-drop in JavaScript.

·

6 min read

The DataTransfer object in JavaScript is the fundamental component of drag-and-drop interactions and clipboard operations.

This is not to be confused with DTOs — which is a pattern that determines how data is sent between different layers of an application.

This JavaScript object provides a structured way to store and transfer various data types such as text, files, and images.

This article focuses on building a basic HTML drag-and-drop flow using the DataTransfer object, which you can customize.

By the end of this article, you’ll learn how to build a drag-and-drop feature similar to the one below.

Prerequisites

  • A basic understanding of JavaScript is required.

  • Knowledge of HTML and CSS is also essential but not compulsory.

  • An IDE or text editor of your choice.


💡
I’ll use the terminal to create files and folders; the commands will work across all operating systems.

Project Setup

Create a drag-and-drop-js folder in your workspace.

Author’s screenshot of the terminal

Next, change the current directory into the newly created folder.

Create the index.html and app.js files, then open the directory in your preferred IDE or text editor. I use VSCode, but WebStorm or Zed are good alternatives if you'd rather use them.

Author’s screenshot of the terminal

Web page design

Let’s create a basic HTML5 skeleton and dive right in.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body></body>
</html>

Create user interface

Understanding the Code Changes

  • The title was updated to make our webpage more descriptive.

  • A container class was added to help us style and center our components.

  • An h1 element was included to provide a clear header for the webpage.

  • An ul element was added to display a list of the selected files.

Styling the interface

Inline styling would be used for this project to make it simple.

Insert a <style> tag within the <head></head> section of your index.html file and paste the following code inside the <style></style> tag.

Next, load the webpage in your browser. If you followed the above correctly, you should have something similar to the image below.

Finally, we insert the <script> tag into the HTML document, linking it to the JavaScript file we created earlier.

Your index.html file should look similar to what we have below if you followed the tutorial correctly.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Interactive File Upload Demo</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        padding: 20px;
        background-color: #f9f9f9;
      }

      .container {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }

      .text-large {
        text-align: center;
      }

      .file-upload-container {
        border: 2px dashed #ccc;
        padding: 20px;
        width: 400px;
        margin-bottom: 20px;
        background-color: white;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
      }

      .file-list {
        list-style: none;
        padding: 0;
      }

      .file-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin: 10px 0;
        background-color: #f0f0f0;
        padding: 10px;
        border-radius: 4px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        transition: transform 0.3s;
      }

      .file-item:hover {
        transform: scale(1.05);
      }

      .file-item img.preview {
        max-width: 50px;
        max-height: 50px;
        margin-left: 10px;
      }

      .file-type-icon {
        margin-right: 10px;
        width: 20px;
        height: 20px;
      }

      .remove-btn {
        cursor: pointer;
        color: red;
        font-size: 18px;
        font-weight: bold;
      }

      .drag-area {
        border: 2px dashed #66cc66;
        padding: 60px;
        text-align: center;
        margin-bottom: 20px;
        background-color: #e9f7e9;
        border-radius: 8px;
        cursor: pointer;
      }
    </style>
  </head>

  <body>
    <div class="container">
      <h1 class="text-large">Interactive File Upload</h1>

      <div class="file-upload-container">
        <div class="drag-area" id="drag-area">Drag and Drop Files Here</div>
        <ul id="file-list" class="file-list"></ul>
      </div>
    </div>

    <script src="app.js"></script>
  </body>
</html>

Drag and Drop Functionality

Let’s create the base logic for our drag-and-drop functionality.

Paste the code below inside the app.js file.

document.addEventListener("DOMContentLoaded", () => {
    const fileListContainer = document.getElementById("file-list");
    const dragArea = document.getElementById("drag-area");

    dragArea.addEventListener("dragover", (event) => event.preventDefault());
    dragArea.addEventListener("drop", handleFileDrop);

    function handleFileDrop(event) {
    }

    // Display icon function
    function getFileTypeIcon(file) {
    }

    // Remove file function
    function createRemoveButton(fileItem) {
    }
});

Implement the getFileTypeIcon functionality.

    function getFileTypeIcon(file) {
        const icon = document.createElement("img");
        if (file.type.startsWith("image/")) {
            icon.src = "https://img.icons8.com/ios-filled/50/000000/image.png";
        } else if (file.type === "application/pdf") {
            icon.src = "https://img.icons8.com/ios-filled/50/000000/pdf-2.png";
        } else {
            icon.src = "https://img.icons8.com/ios-filled/50/000000/file.png";
        }
        icon.classList.add("file-type-icon");
        return icon;
    }

Code Explanation

  • Programmatically created a new <img> element using the document.createElement method.

  • Conditional expression to set the src attribute to the proper icons for the type of file selected.

  • Added a class to the <img> element so that the style we defined earlier is applied to it.

Implement the createRemoveButton functionality

  function createRemoveButton(fileItem) {
        const removeButton = document.createElement("span");
        removeButton.classList.add("remove-btn");
        removeButton.textContent = "✖";
        removeButton.onclick = () => {
            fileItem.remove();
        };
        return removeButton;
    }

Code Explanation

  • Programmatically created a new <span> element using the document.createElement method.

  • A class was added to the <span> element to apply the style we defined earlier.

  • The onclick function was added to enable the functionality of removing the selected file.

Implement the handleFileDrop functionality.

 function handleFileDrop(event) {
        event.preventDefault();
        const files = event.dataTransfer.files;
        if (files.length === 0) return;

        // Handle dropped files
        Array.from(files).forEach((file) => {
            const fileItem = document.createElement("li");
            fileItem.classList.add("file-item");
            const fileTypeIcon = getFileTypeIcon(file);
            const removeButton = createRemoveButton(fileItem);

            const fileInfo = document.createElement("span");
            fileInfo.textContent = file.name;

            fileItem.appendChild(fileTypeIcon);
            fileItem.appendChild(fileInfo);

            // If the file is an image, show a preview
            if (file.type.startsWith("image/")) {
                const reader = new FileReader();
                reader.onload = () => {
                    const img = document.createElement("img");
                    img.src = reader.result;
                    img.classList.add("preview");
                    fileItem.appendChild(img);
                    fileItem.appendChild(removeButton);
                };
                reader.readAsDataURL(file);
            } else {
                fileItem.appendChild(removeButton);
            }
            fileListContainer.appendChild(fileItem);
        });
    }

Code Explanation

  • event.preventDefault()prevents the default behavior for the drop event.

  • event.dataTransfer.files is used to get the list of files dropped onto the target.

  • For each file, an <li> element is created and assigned a file-item class.

  • If the file is an image (checked via file.type.startsWith("image/")), a preview is generated using FileReader.

    • An image element (<img>) is created, and its source is set to the file data.

    • The image is appended along with the remove button.

  • Each fileItem is appended to the fileListContainer for display on the page.

Finally, let’s reload the web and test the drag-and-drop functionality.

Key Takeaways

The DataTransfer object provides a way to interact with files in JavaScript. It is also essential for drag-and-drop interactions and clipboard operations.

  • This article provided a step-by-step tutorial on implementing a drag-and-drop feature using the DataTransfer object.

  • We covered setting up a basic HTML and JavaScript project to create a drag-and-drop interface.

  • The tutorial also included creating user interface elements, styling them, and implementing JavaScript functions for handling file drops.

If you like to explore more functionality of the DataTransfer object, read the MDN docs.


If you liked this article, consider following me for more articles like this.

You can also reach me on X (formerly Twitter) and LinkedIn.