Search code examples
javascripthtmlcssdrag-and-dropinput-type-file

How can I add drag & drop functionality to my file input HTML tag which I have customized as an image?


I am currently designing a form using HTML, CSS, and JavaScript which includes an input type=file. I customized the form, so that the input now uses an image which can be clicked to browse and select files from the user's machine. However, I'd also like it to have drag & drop capabilities.

Below is the code I currently have. This code is enough to do a couple of things:

  1. It replaces the default 'Choose File' button that is rendered when using the input tag with type=file with the image called in the img tag.
  2. It uses some JavaScript for the span tag to indicate to the user which file they have selected or if no file has been selected.

The reason those are possible is because of the CSS used to change the default behavior in the input tag where type=file. However, I haven't found code to implement drag & drop to my current solution. Can somebody please help?

<style>
    .required-file::after {
    content: "*";
    color: red;
    }
    .custom-upload {
    display: inline-block;
    padding: 6px 12px;
    cursor: pointer;
    }
    input[type="file"] {
    display: none;
    }
    </style>
    <script>
    $(function() {
    const fileUploadElement = document.getElementById('fileUpload');
    const chosenFileElement = document.getElementById('chosen-file');
    fileUploadElement.addEventListener('change', function(){
    chosenFileElement.textContent = this.files[0].name;
    });
    });
    </script>
    <label for="fileUpload" class="custom-upload">
    <img src="/fakepath/image.png" width="100" height="100">
    </label>
    <input type="file" id="fileUpload" name="fileUpload" >
    <span class="required-file" id="chosen-file">No file chosen</span>

Solution

  • Here's the solution

    document.addEventListener("DOMContentLoaded", function() {
      const fileUploadElement = document.getElementById('fileUpload');
      const chosenFileElement = document.getElementById('chosen-file');
      const fileDropArea = document.getElementById('fileDropArea');
    
      const handleFileSelect = function(event) {
        event.stopPropagation();
        event.preventDefault();
        const files = event.dataTransfer.files;
        showFileName(files);
      };
    
      const handleDragOver = function(event) {
        event.stopPropagation();
        event.preventDefault();
        event.dataTransfer.dropEffect = 'copy'; 
      };
    
      const showFileName = function(files) {
        if (files.length > 0) {
          chosenFileElement.textContent = files[0].name;
        } else {
          chosenFileElement.textContent = 'No file chosen';
        }
      };
    
      fileDropArea.addEventListener('dragover', handleDragOver, false);
      fileDropArea.addEventListener('drop', handleFileSelect, false);
    
      fileUploadElement.addEventListener('change', function() {
        showFileName(this.files);
      });
    });
    .required-file::after {
      content: "*";
      color: red;
    }
    
    .custom-upload {
      display: inline-block;
      padding: 6px 12px;
      cursor: pointer;
      border: 2px dashed #ccc;
    }
    
    input[type="file"] {
      display: none;
    }
    <label for="fileUpload" class="custom-upload" id="fileDropArea">
            <img src="https://cataas.com/cat" width="100" height="100">
        </label>
    <input type="file" id="fileUpload" name="fileUpload">
    <span class="required-file" id="chosen-file">No file chosen</span>