0

I've been trying to implement image upload with the following requirements:

  1. Drag and drop
  2. Display dropped image in a popup with option to resize image
  3. Upload image after preview and resize

I'm trying to restrict my options to either bass jobsen's jqueryupload. Using this plugin, I've so far managed to do something similar to this:

$('document).on('drop', '#drop_area', function(event) {
    var file_input = $('<input>').attr({type: 'file', 'id': 'hidden_file_input'});
    $('body').append(file_input.hide());

    var file = event.originalEvent.dataTransfer.files[0];
    var file_reader = new FileReader();

    file_reader.onloadend = function(e) {
       var src = file_reader.result;
       file_upload_preview();
    }
    file_reader.readAsDataUrl(file);
    $file_input[0][files][0] = file; // this line only works 5% of the time
});

function file_upload_preview() {
   self.modal_show('/modal/preview', function(e) { // render popup using file /modal/preview.html
          // do image crop options
   });
   doUpload();
}

function doUpload() {
   var file_input = $('#upload_form_id');
   var file = file_input.get(0).files[0]; // throws error because of $file_input[0][files][0] = file; not working
   var url = '/tmp/uploads';
   var data = {
       'x' : file_input.data('x') // image resize dimension
       // add others, etc.
   };
   // do validations
   file_input.upload(url, data, function(json) { // jqueryupload start
      var res = JSON.parse(json); // throws error if the above code doesn't
   });
}

I am getting multiple errors with this code:

  1. The line $file_input[0][files][0] = file; will not always work for some reason
  2. If #1 does not happen, another error is thrown when trying to upload: "Can not process empty Imagick object"

What is the best and sure way I can set the value of file_input by drag and drop instead of choosing the file? Also is it possible to implement what I need using this plugin?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
user1597438
  • 2,171
  • 5
  • 35
  • 78

2 Answers2

1

There are several issues at javascript at Question

  • $file_input[0]files[0] should select File object, instead of $file_input[0][files][0], where brackets surrounding files property is syntax error;
  • it is not possible to set a File object to the FileList object of an <input type="file"> element, where $file_input[0][files][0] = file; // this line only works 5% of the time attempts to set dropped file var file = event.originalEvent.dataTransfer.files[0]; as value of .files[0] at dynamically created <input type="file"> element var file_input = $('<input>').attr({type: 'file', 'id': 'hidden_file_input'});;
  • var file_input = $('#upload_form_id') is not #drop_area element where files were dropped by user

Edit, Updated

  1. Drag and drop file to main.html 2. Add file to rendered popup - preview.html 3. upload

main.html

<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js">
  </script>
  <style>
    #dropzone {
      display: block;
      width: 400px;
      height: 200px;
      border: 1px solid blue;
      text-align: center;
      font-size: 36px;
    }
  </style>
  <script>
    function handleDrop(event) {
      var file = event.dataTransfer.files[0];
      // copy dropped file
      // note, not necessary though requirement
      var copy = file.slice();
      // create objectURL of `copy`
      var url = URL.createObjectURL(copy);
      // open `preview.html`
      var preview = window
                    .open("preview.html"
                         , "preview"
                         , "width=400,height=400,resizable=yes,scrollbars=yes");
      // set `img` at `preview.html` to `copy` 
      // at `DOMContenetLoaded` event of `peview
      $(preview).on("DOMContentLoaded", function(e) {
        // set `img` `src` to `url`:`copy` of `file` at `preview.html`
        $(e.target.body).find("img").attr("src", url);
        // remove `disabled` for ability to close `preview`
        $("button:eq(1)").removeAttr("disabled")
      });
      $("button:eq(1)").on("click", function() {
        // close `preview`
        preview.close();
        // revoke objectURL
        URL.revokeObjectURL(url);
        $(this).attr("disabled", true)
        // remove `disabled` at previous `button`
        // for ability to upload file
        .prev("button").removeAttr("disabled")
      });
      $("button:eq(0)").on("click", function() {
        // create `FormData` object to `POST`
        var data = new FormData();
        data.append("file", file);
        console.log(data.get("file"));
        $(this).attr("disabled", true)
          // do ajax stuff, post file
          // $.ajax({
          //    type:"POST",
          //    processData:false,
          //    data: data
          // })
      });

    }
  </script>
</head>

<body>
  <div id="dropzone" 
  ondragenter="event.stopPropagation(); event.preventDefault();" 
  ondragover="event.stopPropagation(); event.preventDefault();" 
  ondrop="event.stopPropagation(); event.preventDefault();handleDrop(event)">
    Drop files
  </div>
  <button disabled="">upload</button>
  <button disabled="">close preview</button>
</body>

</html>

preview.html

<!DOCTYPE html>
<html>
  <body>
    <img src="">
  </body>
</html>

plnkr http://plnkr.co/edit/Cij0bUojvfhUNZjRw4FM?p=preview

guest271314
  • 1
  • 15
  • 104
  • 177
  • I'm trying to pass the file into a dynamically created input file which is added onto my $('#upload_form_id') form which is the popup and not the actual drop area. Since this isn't possible, what can you suggest instead in order to display the dropped image on a different popup screen? – user1597438 Jul 17 '16 at 07:08
  • How is the "popup" screen rendered? No `javascript` at Question appears to include processing of a "popup". You can call `FileReader` with dropped file object `var file = event.originalEvent.dataTransfer.files[0];` and pass dropped file object to `doUpload` – guest271314 Jul 17 '16 at 07:09
  • I render it using a separate file – user1597438 Jul 17 '16 at 07:12
  • Not clear what requirement is? You have available dropped `File` object at `var file = event.originalEvent.dataTransfer.files[0];`, you can pass the same variable reference to other functions, or create a copy of the file to pass to other functions – guest271314 Jul 17 '16 at 07:14
  • Yeah, but I need to add file as part of view. – user1597438 Jul 17 '16 at 07:41
  • Where should file be passed to? What is "view"? You can pass `src` to `doUpload()` , e.g., `function doUpload(file) {console.log(file)}`, within `.onloadened` function call `doUpload(src)` – guest271314 Jul 17 '16 at 07:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/117514/discussion-between-user1597438-and-guest271314). – user1597438 Jul 17 '16 at 07:45
0

I think,the cause of the error that readAsDataUrl() is async operation, and you must wait for it to finish before you do the rest of the work. You can try the following code:

file_reader.onload = function(e) {
    if(reader.readyState == FileReader.DONE) //You can remove this if not needed
        alert(file.name);
    }
}
mdameer
  • 1,540
  • 2
  • 14
  • 17