Rookie_123
Rookie_123

Reputation: 2017

Direct File Upload Javascript

How is it possible to upload a file directly without clicking file upload button(I want to click Add Widget Button which should give file upload dialog box)

I have a button declared as follows:

<button class="add-button" style="float:top;">Add Widget</button>

On clicking the button the following function is invoked

    $(".add-button").on("click", function() {


  // get selected color value
  var color = $color_picker.val();

  // build the widget, including a class for the selected color value
  var $widget = $('<li>', {
      'class': 'color_' + color
    })
    .append($('<button>', {
      'class': 'delete-button',
      'text':'-'
    }))
    .append($('<img src="abc.png" height="60px" width="60px">'));

  // add widget to the grid
  gridster.add_widget($widget, 1, 1);

});

But I first want a upload box to appear where in user can upload the image as soon as the button is clicked then the above code should get executed

I did something like this

 $(".add-button").on("click", function() {

    var x = document.createElement("INPUT");
     x.setAttribute("type", "file");
     x.setAttribute("onclick","previewFile()");



  // get selected color value
  var color = $color_picker.val();

  // build the widget, including a class for the selected color value
  var $widget = $('<li>', {
      'class': 'color_' + color
    })
    .append($('<button>', {
      'class': 'delete-button',
      'text':'-'
    }))
    .append($('<img src="abc.png" height="60px" width="60px">'));

  // add widget to the grid
  gridster.add_widget($widget, 1, 1);

});

But this does not brings any dialog box where user can upload the image

This uploaded image I want to then use in the place of

    .append($('uploaded image'));

Preview File Function (This also needs to be modified)

function previewFile() {
  var preview = document.createElement('img');

  var file    = document.querySelector('input[type=file]').files[0];
  var reader  = new FileReader();    //API for reading file stored on user computer

  reader.addEventListener("load", function () {    //"load" :This eventlisterner "listens" loading of file. Once it is loaded function is triggered
    preview.src = reader.result;   
  });

  if (file) {
    reader.readAsDataURL(file);    // helps in reading the content of "file"
  }


  document.body.appendChild(preview);
}

My aim is that preview file function should return an image which I can put in

    .append($('image from preview file'));

A version of code is at Fiddle

Upvotes: 0

Views: 396

Answers (1)

jdmdevdotnet
jdmdevdotnet

Reputation: 1

The way to do this is to have some hidden input with file type somewhere on the dom. You might be able to programatically put it there, but really no point in that. Once the add widget button is clicked, you can simulate a click for the hidden input. This will initiate a prompt to pick a file. Then what you want to do is, wait until the file has been "picked" by the user. This is done via the onchange event. Within that, you can grab the file, read it, and then when it's done you can have a callback via the onload method. I put up a working example here. I imagine you wanted to have the file picked as the image set on the src, so I did that as well.

hidden input

    <input id="test" type="file" style="position: absolute; top: -10; left: -10; height: 0; width: 0;" />

button click function (this is what will wait until the file has been chosen), the call back method is used on the onload event of the filereader.

$(".add-button").on("click", function() {

    $('#test').click();

  $('#test').on('change', function(e) {
    var test = document.getElementById('test');

    if (!test) {
      alert("Um, couldn't find the fileinput element.");
    }
    else if (!test.files) {
      alert("This browser doesn't seem to support the `files` property of file inputs.");
    }
    else if (!test.files[0]) {
      alert("Please select a file before clicking 'Load'");               
    }
    else {
      file = test.files[0];
      console.log(file);
      fr = new FileReader();
      fr.readAsDataURL(file); 
      fr.onload = function() {
        var data = fr.result;  // data <-- in this var you have the file data in Base64 format
        callbackAddButton(data);
        test.value = ''; //here we are resetting the file input's files
        $('#test').replaceWith($('#test').clone()); //here we are resetting the input, if we clone the input with the files then it wont trigger the onchange event if you upload same image. So we need to make sure we have these 2 calls. 
      };
    }
  })
});

And finally, the callback method. Which is simply exactly what you had before but now only gets called once the file has been done (done as in, you read it via filereader and have access to contents if needed). The only difference here is now you have a base64 representation of the image the user uploaded. Which I am setting to the new image widget you created.

 function callbackAddButton(file) {
 // get selected color value
  var color = $color_picker.val();

  // build the widget, including a class for the selected color value
  var $widget = $('<li>', {
      'class': 'color_' + color
    })
    .append($('<button>', {
      'class': 'delete-button',
      'text':'-'
    }))
   .append($(`<img src="${file}" height="60px" width="60px">`));

  // add widget to the grid
  gridster.add_widget($widget, 1, 1);
}

EDIT Once you're done with the input file element, it's good practice to now clear it because you dont need the file anymore (from the input at least, since you have a base64 representation). Just append a $('#test').replaceWith($('#test').clone()) after the you make the callback call.

Upvotes: 1

Related Questions