DEV Community

Cover image for Drag and Drop HTML elements and files
Practicing Datscy
Practicing Datscy

Posted on

Drag and Drop HTML elements and files

Webapps can be useful for data collection/ingestion. If the mechanism to collect and store data is easy to use, lot of useful data can be amassed for data processing. One easy to way to move data from one location to another is the Drag and drop functionality on webapps.

In this post, I show three examples for how to move and store HTML element data and files using JavaScript drag and drop programming.

Example 0: Drag and drop an HTML element

<!DOCTYPE html>
<html>
<head></head>
<body>

<h1>Example 0: Drag and Drop HTML text/elements</h1>
<div id="HTML_text" draggable="true" class="dragElement">HTML text</div>

<br><br>

<div id="dropArea" class="dropArea"> Drop for Example 0 & 1</div>

<style>
.dropArea { height: 200px;
    width: 200px;
    border-radius: 15px;
    border: 0.25px solid black;
    background-color: #7084c4;
}

.HTML_text { cursor: move; }
</style>
<script>
var example;
var other_data_related_to_dragEvent = {};
var html_element_drag_list_metaData = [];


// ----------------------------------------------------
// Drag functionality: Example 0
// ----------------------------------------------------
document.getElementById("HTML_text").addEventListener("dragstart", processEvent_drag_example0, false);
// document.getElementById("HTML_text").addEventListener("dragend", processEvent_drag_example0, false); // to stop

function processEvent_drag_example0(event) {
    example = 0;
    event.dataTransfer.setData('text/plain', event.target.id);
}
// ----------------------------------------------------

// ----------------------------------------------------
// Drop functionality: Example 0 and 1
// ----------------------------------------------------
document.getElementById("dropArea").addEventListener("drop", processEvent_drop, false);
document.getElementById("dropArea").addEventListener("dragover", processEvent_dragover, false);

function processEvent_drop(event) {

    // Stop defaults and allow drop events
    event.preventDefault();

    // Detects files dragged from pc 
    html_element_drag_list_metaData.push(event.dataTransfer.files);
    console.log('html_element_drag_list_metaData: ', html_element_drag_list_metaData);

    // Detects html elements dragged from the html page
    const data = event.dataTransfer.getData('text/plain');
    console.log('data: ', data);
    if (data.length != 0) {
      // find the draggable element based on the data
      const dragElement = document.getElementById(data);
      console.log('dragElement: ', dragElement);

      // Append the draggable element 
      event.target.appendChild(dragElement);

    }
}

function processEvent_dragover(event) {
  // Stop defaults and allow drop events
  event.preventDefault();
}
// -------------------------------------------------

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

Before dragging and dropping the HTML text (HTML text) to the purple dropArea

Before dragging and dropping the HTML text (HTML text) to the purple dropArea

After dragging and dropping the HTML text (HTML text) to the purple dropArea

After dragging and dropping the HTML text (HTML text) to the purple dropArea

In example 0, the HTML text element was actually moved into the drop area. The id of the div for HTML text appeared in the variable data, thus one can keep track of the element ids inside the dropArea. This example is useful for organizing/storing existing html written on a webapp, but in most data ingestion situation one wants to organize/store data from different places.

Example 1: a file upload is represented as a draggable HTML element/emoji

This example is a cross between dragging an HTML element and dragging a file. One can select a file using the Browse button; drag a file to the browse button or click on the browse button to select a file. Then an emoji appears after the file has been selected, the appearance of the emoji represents the file in terms of an HTML element. The HTML element emoji, representative of a file, can then be dragged to the dropArea for data ingestion/storage.

<!DOCTYPE html>
<html>
<head></head>
<body>

<h1>Example 1: Click button create drag and drop elements</h1>
<input type="file" id="upload_file" accept="audio/*" style="display:block" multiple>
<div id="file_name" style="display:none"></div>
<div id="base64_string" style="display:none"></div>
<div id="base64_string_icon" draggable="true" class="dragElement" style="display:none">📄</div>

<br><br>

<div id="dropArea" class="dropArea"> Drop for Example 0 & 1</div>

<style>
.dropArea { height: 200px;
    width: 200px;
    border-radius: 15px;
    border: 0.25px solid black;
    background-color: #7084c4;
}

.HTML_text { cursor: move; }
</style>

<script>
var example;
var other_data_related_to_dragEvent = {};
var html_element_drag_list_metaData = [];

// ----------------------------------------------------
// Drag functionality: Example 1
// ----------------------------------------------------
// The eventlistener needs to be always running, to detect which file the user selected with browse
document.getElementById("upload_file").addEventListener("change", previewInput_drop, false);

async function previewInput_drop(event) {

    // Take the first file
    const file = event.target.files[0];  // first file in the list of selected files, better for selecting multiple files at one time
    // console.log("file :", file);

    document.getElementById("file_name").innerHTML = file.name;

    // ---------------------

    const reader = new FileReader();

    reader.onload = async function(e){
        document.getElementById("base64_string").innerHTML = e.target.result;
        document.getElementById("base64_string_icon").style.display = "block";
    }

    reader.readAsDataURL(file);
}


document.getElementById("base64_string_icon").addEventListener("dragstart", processEvent_drag_example1, false);

function processEvent_drag_example1(event) {
    example = 1;
    event.dataTransfer.setData('text/plain', event.target.id);
}

// ----------------------------------------------------

// ----------------------------------------------------
// Drop functionality: Example 0 and 1
// ----------------------------------------------------
document.getElementById("dropArea").addEventListener("drop", processEvent_drop, false);
document.getElementById("dropArea").addEventListener("dragover", processEvent_dragover, false);

function processEvent_drop(event) {

    // Stop defaults and allow drop events
    event.preventDefault();

    // Detects files dragged from pc 
    html_element_drag_list_metaData.push(event.dataTransfer.files);
    console.log('html_element_drag_list_metaData: ', html_element_drag_list_metaData);

    // Detects html elements dragged from the html page
    const data = event.dataTransfer.getData('text/plain');
    console.log('data: ', data);
    if (data.length != 0) {
      // find the draggable element based on the data
      const dragElement = document.getElementById(data);
      console.log('dragElement: ', dragElement);

      // Append the draggable element 
      event.target.appendChild(dragElement);

    }
}

function processEvent_dragover(event) {
  // Stop defaults and allow drop events
  event.preventDefault();
}
// -------------------------------------------------

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

Before selecting a file

Before selecting a file

Dragged a file to the browse button

Dragged a file to the browse button

Dragged the representative file emoji to the dropArea

Dragged the representative file emoji to the dropArea

Example 2: Drag and drop an HTML element

In this example, one can efficiently drag multiple files to the dropArea at one time.

<!DOCTYPE html>
<html>
<head></head>
<body>

<h1>Example 2: Drag and drop files</h1>
<input type="file" id="upload_file_dragdrop" style="display:block" class="dropArea1" multiple>

<br><br>

<button id="use_moved_data" onclick="use_moved_data()">use_moved_data</button>

<!-- ---------------------------------------- -->
<!-- CSS -->
<style>
.dropArea1 { height: 200px;
    width: 200px;
    border-radius: 15px;
    border: 0.25px solid black;
    background-color: #56b06e;
}
</style>
<!-- ---------------------------------------- -->

<script>
var other_data_related_to_dragEvent = {};
var html_element_drag_list_metaData = [];

// ----------------------------------------------------
// Drag and Drop functionality: Example 2
// ----------------------------------------------------
document.getElementById("upload_file_dragdrop").addEventListener("change", previewInput, false);

async function previewInput(event) {

    // For multiple files
    const allFiles = event.target.files;
    // console.log("allFiles :", allFiles);

    var i = 0;
    while (i < allFiles.length) {

        const file = allFiles[i];
        // console.log("file :", file);

        await obtain_fileInfo(file)
            .then(base64str => { other_data_related_to_dragEvent[file.name] = base64str; })
            .catch(error => console.error(error));

        i = i + 1;
    }

    // ---------------------
}

async function obtain_fileInfo(file) {
    var base64_string = await new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = async function(e){ 
            resolve(e.target.result); // inside resolve is the value that the function returns
        };
        reader.readAsDataURL(file);
    });
     return base64_string;
}

// ----------------------------------------------------

async function use_moved_data() {
    console.log('html_element_drag_list_metaData: ', html_element_drag_list_metaData);
    console.log('other_data_related_to_dragEvent: ', other_data_related_to_dragEvent);
}

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

Before dragging files into the dropArea

Before dragging files into the dropArea

After dragging files into the dropArea and pushing the use_moved_data button

After dragging files into the dropArea and pushing the use_moved_data button

We can see an the base64 string data of the three files that were dragged into the dropArea! The base64 string data can then be saved as a blob object and transferred to across the Internet.

I hope these ways to drag and drop HTML elements and files helps someone.

Happy Practicing! 👋

💻 GitHub | 🌷 Practicing Datscy @ Dev.to | 🌳 Practicing Datscy @ Medium

References

  1. How to Create Drag and Drop Functionality in JavaScript: A Step-by-Step Tutorial: https://medium.com/@future_fanatic/how-to-create-drag-and-drop-functionality-in-javascript-a-step-by-step-tutorial-8ea236ef9416
  2. Read files in JavaScript: https://web.dev/articles/read-files

Top comments (0)