1

I have a web application where users can export results by clicking on a button. As far as I know it isn't possible to initiate a file "download" from javascript, so I use a simple server round trip to start the download:

  1. User clicks the export button
  2. Some javascript creates a hidden form field that contains the data I want in the file
  3. A form submit is triggered
  4. The servers takes the form data and sends it back to the user as a file
  5. A file download is triggered

Since uploading the data can take some time, I change the text on the export button to "preparing download" after step 1. Somewhere around step 4 or 5, I want to change the button back to normal. Is there any way to know when the browser starts receiving the response from the post request?

bmesuere
  • 502
  • 3
  • 12

1 Answers1

0

I tried using this solution:

  1. Add an invisible iframe to the page
  2. Let the form post to the iframe using the target attribute
  3. Use the onLoad event of the iframe (triggered by the form post) to reset my button

This works in Firefox, but the onLoad event isn't triggered in Chrome when the server response is a file.

The solution I settled for uses a cookie and works in all browsers:

  1. When the user clicks the download button, add a hidden field to the form containing a random value.
  2. On the server, look for the form field containing the random value and set a cookie with the same value. The cookie will be set with the next server response, thus when the download has started.
  3. On the client, start polling the cookies every second or so to look for the random value from step 1.
  4. Once the client found the value, reset the button.

This is the relevant code from the event handler of the download button with #nonce being the hidden field where I put the random value:

var nonce = Math.random();                      // generate random number
$("#nonce").val(nonce);                         // set number as field value
$("#downloadDataset").button('loading');        // set button to loading state
var downloadTimer = setInterval(function () {   // start polling the cookies
    if (document.cookie.indexOf(nonce) != -1) {
        $("#downloadDataset").button('reset');  // reset button
        clearInterval(downloadTimer);           // stop polling the cookies
    }
}, 1000);                                       // check every 1000ms
bmesuere
  • 502
  • 3
  • 12