Search code examples
javascripthtmldrag-and-drop

Block file opening when drag and drop


I use the following script to upload files using drag and drop.

// dragover and dragenter events need to have 'preventDefault' called
// in order for the 'drop' event to register. 
// See: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets
dropContainer.ondragover = dropContainer.ondragenter = function(evt) {
  evt.preventDefault();
};

dropContainer.ondrop = function(evt) {
  // pretty simple -- but not for IE :(
  fileInput.files = evt.dataTransfer.files;

  // If you want to use some of the dropped files
  const dT = new DataTransfer();
  dT.items.add(evt.dataTransfer.files[0]);
  dT.items.add(evt.dataTransfer.files[3]);
  fileInput.files = dT.files;

  evt.preventDefault();
};
<!DOCTYPE html>
<html>
<body>
<div id="dropContainer" style="border:1px solid black;height:100px;">
   Drop Here
</div>
  Should update here:
  <input type="file" id="fileInput" />
</body>
</html>

If I upload multiple files at once, it's OK, it work. But if I upload only a file, the browser open the file in a new tab. How to do to block this action and only put the file in the box ?


Solution

  • The issue is that your code assumes there is a third file, which is not the case, throws an error due to the index being out of bounds and not reaching the preventDefault line. You will need to loop with the index and only add the items that actually exist:

    // dragover and dragenter events need to have 'preventDefault' called
    // in order for the 'drop' event to register. 
    // See: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets
    dropContainer.ondragover = dropContainer.ondragenter = function(evt) {
      evt.preventDefault();
      evt.stopPropagation();
      return false;
    };
    
    dropContainer.ondrop = function(evt) {
      // pretty simple -- but not for IE :(
      //fileInput.files = evt.dataTransfer.files;
    
      // If you want to use some of the dropped files
      const dT = new DataTransfer();
      //dT.items.add(evt.dataTransfer.files[0]);
      //dT.items.add(evt.dataTransfer.files[3]);
      let index = 0;
      while (evt.dataTransfer.files[index]) dT.items.add(evt.dataTransfer.files[index++]);
      fileInput.files = dT.files;
      
      evt.preventDefault();
    };
    <!DOCTYPE html>
    <html>
    <body>
    <div id="dropContainer" style="border:1px solid black;height:100px;">
       Drop Here
    </div>
      Should update here:
      <input type="file" id="fileInput" />
    </body>
    </html>