0

I'm trying to show a downloading gif next to the file link while the browser downloads the file via a POST request. Currently, clicking on the file link does nothing. If I change the .submit(function(){...}); to just .submit(); then it downloads the file but doesn't show the loading gif. If I set the loading gif to .show(); previous to the .submit();, then it doesn't show until after the file is already downloaded.

Here is the my current structure and JS...

HTML

<a class="file" data-location="directory/file">File.xlsx</a>
<span class="download_loader"></span>

JS

$(document).on('click', 'a.file', function () {
    var location = $(this).data("location");
    var name = $(this).html();
    var loader = $(this).nextAll("span.download_loader");
    $('<form action="FileManager/download.php" method="POST" id="temp_download_form"><input type="hidden" name="name" value="'+name+'" /><input type="hidden" name="location" value="'+location+'" /></form>').appendTo('body').submit(function(loader) {
        loader.show();
        return true;
    });
    $("#temp_download_form").remove();
});

-- Solution --

I was able to finally get something that is working based on the answer below and the comments. I used a download function from https://github.com/filamentgroup/jQuery-File-Download and also some timeout functions to manage the flow. The final UX is good and allows the download gif to show and hide nicely. See here: http://d.pr/i/KfRP

Final JS Code

// Download Function
function download(url, data, method){
    //url and data options required
    if( url && data ){ 
        //data can be string of parameters or array/object
        data = typeof data == 'string' ? data : $.param(data);
        //split params into form inputs
        var inputs = '';
        $.each(data.split('&'), function(){ 
            var pair = this.split('=');
            inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />'; 
        });
        //send request
        $('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
        .appendTo('body').submit().remove();
    };
};

// Download File
$(document).on('click', 'a.file', function () {
    var location = $(this).data("location");
    var name = $(this).html();
    var cell = $(this).closest('td');
    $('<span class="download_loader"></span>').appendTo(cell);

    setTimeout(function(){
        download('FileManager/download.php','name='+name+'&location='+location,'post');
    }, 1000);

    setTimeout(function(){
        $("span.download_loader").fadeOut();
    }, 2000);
});
George Ortiz
  • 199
  • 2
  • 4
  • 22

1 Answers1

0

I would do something like this instead:

var form = $("<form/>", {
    action : "FileManager/download.php",
    method : "POST",
    id : "temp_download_form"
});

//add inputs the same way and append to form... form.append(input1)... form.append(input2)

form.on('submit', function () {
    loader.show();
});

BUT... The problem is that this is an asynchronous operation, so it is not easy to tell when operation is complete.

Here is an article about checking for when a form is done

How to do a Jquery Callback after form submit?

BUT... I would use $.ajax to submit the form and use the success method to trigger the removing of the loading icon.

Here is the documentation on using jQuery's $ajax

https://api.jquery.com/jQuery.ajax/

Community
  • 1
  • 1
jOshT
  • 1,275
  • 1
  • 9
  • 15
  • ajax doesn't work well with file downloads as you can't pass the headers to the browser. There are some query plugins that try to work around this, though they submit the form the same as I'm attempting. In your first example, the form isn't being automatically submitted, right? It's only binding to the submit event, right? – George Ortiz Mar 27 '14 at 20:21
  • Thanks for the answer, I was able to come up with something based on your suggestions. I've edited the question with the final code. – George Ortiz Mar 28 '14 at 16:11