Search code examples
jqueryhtmlmultifile-uploader

Removing file from multiple files uploader on button click when using HTML5 file input


How to add remove button here like simple remove one by one in files queue like this

enter image description here

The reason why im not using free file upload plugins with OOB plugs because my client requirements is for security purposes and they need simple upload ui without any complicated plugins.

$(function() {
  var dropZoneId = "drop-zone";
  var buttonId = "clickHere";
  var mouseOverClass = "mouse-over";

  var dropZone = $("#" + dropZoneId);
  var ooleft = dropZone.offset().left;
  var ooright = dropZone.outerWidth() + ooleft;
  var ootop = dropZone.offset().top;
  var oobottom = dropZone.outerHeight() + ootop;
  var inputFile = dropZone.find("input");
  document.getElementById(dropZoneId).addEventListener("dragover", function(e) {
    e.preventDefault();
    e.stopPropagation();
    dropZone.addClass(mouseOverClass);
    var x = e.pageX;
    var y = e.pageY;

    if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
      inputFile.offset({
        top: y - 15,
        left: x - 100
      });
    } else {
      inputFile.offset({
        top: -400,
        left: -400
      });
    }

  }, true);

  if (buttonId != "") {
    var clickZone = $("#" + buttonId);

    var oleft = clickZone.offset().left;
    var oright = clickZone.outerWidth() + oleft;
    var otop = clickZone.offset().top;
    var obottom = clickZone.outerHeight() + otop;

    $("#" + buttonId).mousemove(function(e) {
      var x = e.pageX;
      var y = e.pageY;
      if (!(x < oleft || x > oright || y < otop || y > obottom)) {
        inputFile.offset({
          top: y - 15,
          left: x - 160
        });
      } else {
        inputFile.offset({
          top: -400,
          left: -400
        });
      }
    });
  }

  document.getElementById(dropZoneId).addEventListener("drop", function(e) {
    $("#" + dropZoneId).removeClass(mouseOverClass);
  }, true);

  inputFile.on('change', function(e) {
    $('#filename').html("");
    var fileNum = this.files.length,
      initial = 0,
      counter = 0;
    for (initial; initial < fileNum; initial++) {
      counter = counter + 1;
      $('#filename').append('<span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">' + counter + '</strong></span> ' + this.files[initial].name + '&nbsp;&nbsp;<span class="fa fa-times-circle fa-lg closeBtn" title="remove"></span><br>');
    }
  });

})
#drop-zone {
  width: 100%;
  min-height: 150px;
  border: 3px dashed rgba(0, 0, 0, .3);
  border-radius: 5px;
  font-family: Arial;
  text-align: center;
  position: relative;
  font-size: 20px;
  color: #7E7E7E;
}
#drop-zone input {
  position: absolute;
  cursor: pointer;
  left: 0px;
  top: 0px;
  opacity: 0;
}
/*Important*/

#drop-zone.mouse-over {
  border: 3px dashed rgba(0, 0, 0, .3);
  color: #7E7E7E;
}
/*If you dont want the button*/

#clickHere {
  display: inline-block;
  cursor: pointer;
  color: white;
  font-size: 17px;
  width: 150px;
  border-radius: 4px;
  background-color: #4679BD;
  padding: 10px;
}
#clickHere:hover {
  background-color: #376199;
}
#filename {
  margin-top: 10px;
  margin-bottom: 10px;
  font-size: 14px;
  line-height: 1.5em;
}
.file-preview {
  background: #ccc;
  border: 5px solid #fff;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
  display: inline-block;
  width: 60px;
  height: 60px;
  text-align: center;
  font-size: 14px;
  margin-top: 5px;
}
.closeBtn:hover {
  color: red;
}
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="drop-zone">
  <p>Drop files here...</p>
  <div id="clickHere">or click here.. <i class="fa fa-upload"></i>
    <input type="file" name="file" id="file" multiple />
  </div>
  <div id='filename'></div>
</div>

Note: I didnt own the code i've been reused it as my resources from other people and modified it for my client

**UPDATE Here my fiddle link


Solution

  • The file list of HTML5 file input is readonly, so when trying to remove a file from it you won't be allowed.

    What you need to do is maintain a separate array list (JSON array as per the example).

    I have wrapped your X button with a div that hold the file index concatenated to a 'file_' string, and added an onclick function removeLine(obj) that accepts the element as an object.

    I have also added a JSON array finalFiles in the global scope as well as moved the inputFile to the global scope.

    When the file input changes, I am setting the JSON array with the selected files through :

    $.each(this.files,function(idx,elm){
               finalFiles[idx]=elm;
            });
    

    The function removeLine will flush the input file list to allow the same file selection again if the user removed the file by mistake, the function obtains the file index from the wrapper division id, removes the wrapper div then deletes the file from the JSON array.

    function removeLine(obj)
        {
          inputFile.val('');
          var jqObj = $(obj);
          var container = jqObj.closest('div');
          var index = container.attr("id").split('_')[1];
          container.remove(); 
    
          delete finalFiles[index];
          //console.log(finalFiles);
        }
    

    You can the maintain your files when the form submits and send them through AJAX post using FormData in a similar manner to This Article.

    var dropZoneId = "drop-zone";
      var buttonId = "clickHere";
      var mouseOverClass = "mouse-over";
    var dropZone = $("#" + dropZoneId);
     var inputFile = dropZone.find("input");
     var finalFiles = {};
    $(function() {
      
    
      
      var ooleft = dropZone.offset().left;
      var ooright = dropZone.outerWidth() + ooleft;
      var ootop = dropZone.offset().top;
      var oobottom = dropZone.outerHeight() + ootop;
     
      document.getElementById(dropZoneId).addEventListener("dragover", function(e) {
        e.preventDefault();
        e.stopPropagation();
        dropZone.addClass(mouseOverClass);
        var x = e.pageX;
        var y = e.pageY;
    
        if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
          inputFile.offset({
            top: y - 15,
            left: x - 100
          });
        } else {
          inputFile.offset({
            top: -400,
            left: -400
          });
        }
    
      }, true);
    
      if (buttonId != "") {
        var clickZone = $("#" + buttonId);
    
        var oleft = clickZone.offset().left;
        var oright = clickZone.outerWidth() + oleft;
        var otop = clickZone.offset().top;
        var obottom = clickZone.outerHeight() + otop;
    
        $("#" + buttonId).mousemove(function(e) {
          var x = e.pageX;
          var y = e.pageY;
          if (!(x < oleft || x > oright || y < otop || y > obottom)) {
            inputFile.offset({
              top: y - 15,
              left: x - 160
            });
          } else {
            inputFile.offset({
              top: -400,
              left: -400
            });
          }
        });
      }
    
      document.getElementById(dropZoneId).addEventListener("drop", function(e) {
        $("#" + dropZoneId).removeClass(mouseOverClass);
      }, true);
    
    
      inputFile.on('change', function(e) {
        finalFiles = {};
        $('#filename').html("");
        var fileNum = this.files.length,
          initial = 0,
          counter = 0;
    
        $.each(this.files,function(idx,elm){
           finalFiles[idx]=elm;
        });
    
        for (initial; initial < fileNum; initial++) {
          counter = counter + 1;
          $('#filename').append('<div id="file_'+ initial +'"><span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">' + counter + '</strong></span> ' + this.files[initial].name + '&nbsp;&nbsp;<span class="fa fa-times-circle fa-lg closeBtn" onclick="removeLine(this)" title="remove"></span></div>');
        }
      });
    
    
    
    })
    
    function removeLine(obj)
    {
      inputFile.val('');
      var jqObj = $(obj);
      var container = jqObj.closest('div');
      var index = container.attr("id").split('_')[1];
      container.remove(); 
    
      delete finalFiles[index];
      //console.log(finalFiles);
    }
    #drop-zone {
      width: 100%;
      min-height: 150px;
      border: 3px dashed rgba(0, 0, 0, .3);
      border-radius: 5px;
      font-family: Arial;
      text-align: center;
      position: relative;
      font-size: 20px;
      color: #7E7E7E;
    }
    #drop-zone input {
      position: absolute;
      cursor: pointer;
      left: 0px;
      top: 0px;
      opacity: 0;
    }
    /*Important*/
    
    #drop-zone.mouse-over {
      border: 3px dashed rgba(0, 0, 0, .3);
      color: #7E7E7E;
    }
    /*If you dont want the button*/
    
    #clickHere {
      display: inline-block;
      cursor: pointer;
      color: white;
      font-size: 17px;
      width: 150px;
      border-radius: 4px;
      background-color: #4679BD;
      padding: 10px;
    }
    #clickHere:hover {
      background-color: #376199;
    }
    #filename {
      margin-top: 10px;
      margin-bottom: 10px;
      font-size: 14px;
      line-height: 1.5em;
    }
    .file-preview {
      background: #ccc;
      border: 5px solid #fff;
      box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
      display: inline-block;
      width: 60px;
      height: 60px;
      text-align: center;
      font-size: 14px;
      margin-top: 5px;
    }
    .closeBtn:hover {
      color: red;
      display:inline-block;
    }
    }
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <div id="drop-zone">
      <p>Drop files here...</p>
      <div id="clickHere">or click here.. <i class="fa fa-upload"></i>
        <input type="file" name="file" id="file" multiple />
      </div>
      <div id='filename'></div>
    </div>