2

I am trying to create a drop box where image files can be dragged for upload. This works fine in Chrome and Edge. However, I am having troubles in Firefox and IE 11. For example, in IE 11, when I click on the browse button, a window pops up titled, "Choose File to Upload." If I click an Image and click "open" it works fine, but I can't drag any files out of the window. However, if I open my file explorer, I can drag and drop images just fine from the File Explorer window. A similar thing happens in Firefox. I can drag images from File Explorer just fine, but when I try to drag from the popup window titled "File Upload", I get a ghost image with a circle and red slash. Some threads here have suggested using a dragstart function, but that does not seem to be working, probably because the documentation says "Note that dragstart and dragend events are not fired when dragging a file into the browser from the OS." https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API

So is there a way I can drag files from the file upload window in these browsers as opposed to having to open file explorer? Again, I can drag and drop from the popup in Chrome and Edge.

Here is my HTML:

    Files: <input type="file" id="fileInput" name="files" multiple><br />

    <div id="selectedFiles"></div>

    <div class="picList">
        <div id="dropbox" style="border:1px solid black;height:500px;">
             Drop Here
        </div>
    </div>

Here is my javascript:

dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
function dragenter(e) {
  e.stopPropagation();
  e.preventDefault();
}

function dragover(e) {
    e.stopPropagation();
    e.preventDefault();
}
function drop(e) {
    e.stopPropagation();
    e.preventDefault();

    var dt = e.dataTransfer;
    var files = dt.files;

    handleFiles(files);
}

Any advice?

Edit:

Here is my handleFiles function (dupCheck is an array to check for duplicates and stored files is an array of files to be uploaded, which I need because I want users to be able to delete a file by deleting the preview image and HTML FileReader is read only so I can't delete single images directly from the file stack.):

    function handleFiles(files) {
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        var imageType = /^image\//;

        if (!imageType.test(file.type)) {
            continue;
        }
        var img = document.createElement("img");
        img.classList.add("obj");
        img.file = file;
        $(img).addClass('selFile');
        $(img).attr('data-file', file.name);
        var A = [];
        for (var z = 0; z < dupCheck.length; z++) {
            A.push(dupCheck[z].name)
        }
        if (!A.includes(file.name)) {
            storedFiles.push(file);
            var _checker = { name: file.name };
            dupCheck.push(_checker);
            dropbox.appendChild(img);
            var reader = new FileReader();
            reader.onload = (function (aImg) { return function (e) { aImg.src = e.target.result; }; })(img);
            reader.readAsDataURL(file);
            A = [];
        };
    }
}
Pennywise
  • 281
  • 2
  • 4
  • 11
  • consider using a library. here's one i wrote. https://github.com/Pamblam/fileUpload – I wrestled a bear once. Nov 11 '16 at 21:46
  • Cool. I'll take a look. – Pennywise Nov 11 '16 at 21:47
  • Can you include text of `handleFiles` at Question? – guest271314 Nov 11 '16 at 22:03
  • I edited my question to include the handleFiles code. Thanks! – Pennywise Nov 11 '16 at 22:09
  • @Pennywise See also [How FileReader.readAsText in HTML5 File API works?](http://stackoverflow.com/questions/40146768/how-filereader-readastext-in-html5-file-api-works) – guest271314 Nov 11 '16 at 22:11
  • What is purpose of dragging files from `Choose File` explorer? What are you trying to achieve? – guest271314 Nov 11 '16 at 22:21
  • I want users to be able to drag individual files, or a group of selected files, into a drop box where a preview of each image will be displayed. Then I want users to be able to delete a preview image by clicking on it, which in turn will remove the file from the array of files to be uploaded upon submitting a form with other data such as name, address, etc... As I said it works fine in Chrome and Edge, and also works by dragging images from the File Explorer. I just can't drag images directly from the file upload window. – Pennywise Nov 11 '16 at 22:28
  • Why do you append `img` element to `dropbox`? Did you mean to append `img` to `#selectedFiles`? – guest271314 Nov 11 '16 at 22:31
  • So that an image appears in the dropbox that the user can preview and delete from the pictures to be uploaded upon form submission. I'm a newbie. Is there a more appropriate way? My problem seems to be that I can't drag out of the upload window rather than the drop function, but I could very well be wrong. The selected files div is just a div with the words "Selcted Files." The images are displayed in the dropbox div. – Pennywise Nov 11 '16 at 22:35
  • Well, the `dropbox` element is the element which you have attached drag and drop events to. You have an element having `id` `"selectedFiles"` though you do not append the created `img` to that element? _"I'm a newbie. Is there a more appropriate way?"_ See also [Upload multiple image using AJAX, PHP and jQuery](http://stackoverflow.com/questions/28856729/upload-multiple-image-using-ajax-php-and-jquery/) , links at previous comments. Not certain why you want to drag files from file explorer after clicking `` element? – guest271314 Nov 11 '16 at 22:39
  • I am able to successfully drag multiple images into my dropbox by manually opening file explorer and dragging from there. But when I click on my "Browse" button (in IE), I get a window pops up titled "Choose File to Upload." It is from there that I cannot drag anything, so I have to open file explorer and drag from there. I guess I could just simply allow users to only select files by clicking on them in Firefox and IE, but was hoping for the same functionality I have in Chrome and Edge. To be sure, I don't need my selected files div and have removed it. – Pennywise Nov 11 '16 at 22:53
  • Consider using `URL.createObjectURL(file)` instead of using filereader – Endless Nov 12 '16 at 11:10

2 Answers2

1

You can substitute using two <input type="file"> elements for drag and drop events. Drop selected files at <label> element having <input type="file"> control having opacity set to 0.

<!DOCTYPE html>
<html>

<head>
  <style type="text/css">
    #drop {
      opacity: 0;
    }
    #drop,
    label[for="drop"] {
      height: 500px;
      width: 500px;
    }
    label[for="drop"] {
      display: block;
      border: 1px solid black;
    }
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js">
  </script>
  <script>
    $().ready(function() {
      var selectedFiles = $("#selectedFiles");
      
      function handleFiles(e) {
        var files = e.target.files;
        var input = this;

        for (var i = 0; i < files.length; i++) {
          (function(i, input) {
            var file = files[i];
            var figure = $("<figure></figure>", {
              append: $("<figcaption></figcaption>", {
                html: file.name
              })
            });

            var img = $("<img>").on("load", function() {
              selectedFiles.append(figure.prepend(img));
              input.value = null;
            });

            var reader = new FileReader();
            reader.onload = function(e) {
              img.attr("src", e.target.result);
            };
            reader.readAsDataURL(file);
          })(i, input);

        }
      }
      $(".fileInput").change(handleFiles);

    })
  </script>
</head>

<body>
  Files:
  <input type="file" 
         accept="image/*" 
         class="fileInput" 
         name="files0" 
         multiple="multiple" />
  <br />

  <div class="picList">

    <label for="drop" id="dropbox">
      Drop Here
      <input type="file" 
             accept="image/*" 
             id="drop" 
             class="fileInput" 
             name="files1" 
             multiple="multiple" />
    </label>
  </div>
  <div id="selectedFiles"></div>
</body>

  
</html>
guest271314
  • 1
  • 15
  • 104
  • 177
  • Right on. That gives me something to go by. Thanks! – Pennywise Nov 12 '16 at 00:10
  • When I run the above code snippet in Chrome it works, but not in Firefox. I still get the circle with the slash in Firefox. When I run it in IE 11, I am able to drag images out of the window, but they are not appending like they do in Chrome. It works by clicking, but not dragging. Still though, I very much value the approach! I must be doing something wrong. – Pennywise Nov 12 '16 at 00:39
  • @Pennywise Had not yet considered dragging files from explorer after clicking `` until read your Question. Not certain if the `Choose File` or `Browse` dialog is expected to be used as for drag and drop. You can drag and drop files to `` element itself at both chromium and firefox. – guest271314 Nov 12 '16 at 00:43
  • Yeah, it's a pain. The reason I want this feature is because it seems the most user friendly from the perspective of someone not that adept at computers. You click on the browse button and a window pops up with your pictures, so it seems natural to want to drag the pictures from that window rather that opening file explorer separately. At least they can click on multiple images and append. I would like to get the drag feature working from the popup window, but maybe those browsers don't support it? Thanks again for helping with this! I really appreciate it :) – Pennywise Nov 12 '16 at 00:48
  • @Pennywise No worries. You can file bug reports describing the behaviour, and what behaviour you expect; to try to get answers as to what specification is for each browser https://www.chromium.org/for-testers/bug-reporting-guidelines , https://bugzilla.mozilla.org/ – guest271314 Nov 12 '16 at 00:52
  • 1
    I might have to try that. I hit the community form on monzilla, but so far no replies: https://support.mozilla.org/en-US/search/advanced?a=1&asked_by=pennywise&w=2 – Pennywise Nov 12 '16 at 01:05
  • I provided a solution that works great in Firefox, but not IE 11. – Pennywise Nov 16 '16 at 20:27
0

So I managed to solve this in Firefox by adding:

e.dataTransfer.dropEffect = 'copy';

to my dragover function, which now looks like this:

    function dragover(e) {
    e.stopPropagation();
    e.preventDefault();
    e.dataTransfer.dropEffect = 'copy';
}

Doing this removes the circle with slash when I drag over my dropbox, which in turn allows me to make the drop for upload.

However, this does not work in IE 11, so if anyone has any ideas, I'd greatly appreciate it!

Pennywise
  • 281
  • 2
  • 4
  • 11