28

I have an onbeforeunload event that's supposed to get triggered any time a user goes to a new page. It works well enough, but I've found that it also gets triggered in Chrome any time a user downloads a file from the page they're on.

I'd like to be able to tell if the event is getting fired because it's being triggered by a file download. What's the best way to do that?

EDIT: As a clarification, I don't own the site that I'm listening to onbeforeunload on. The event is listened to by a Javascript snippet that's being installed on 3rd party sites.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
dshipper
  • 3,489
  • 4
  • 30
  • 41
  • [Download binary without triggering onbeforeunload](http://stackoverflow.com/questions/2452110/download-binary-without-triggering-onbeforeunload) – Felipe Fonseca Jan 18 '13 at 02:55
  • Sorry I should have made this more clear, I don't own the site that I'm listening to onbeforeunload on. It's for a widget I've built. – dshipper Jan 18 '13 at 03:12
  • 1
    @dshipper I realize it's a bit late but I found a nice work around using some non-obstrusive javascript, see my answer below. What do you think? – Adriano Oct 09 '14 at 13:21

2 Answers2

22

If you add download="[FILENAME]" to the a tag, it seems to prevent onbeforeunload from firing:

<a download="myfile.jpg" href="mysite.com">click me</a>

This is a much simpler solution. You can leave off the filename and just say 'download' to use the default filename. Let me point out this has the side effect of forcing redownload instead of using cache. I think this was added to chrome and ff in 2012. Not sure about safari or ie support.

jsarma
  • 1,344
  • 11
  • 19
  • 6
    This can be nicely used together with `target="_blank"`, which helps in browsers that don't have support for `download`, like all Internet Explorer versions. For those it opens a new tab for a short moment. Those with proper `download` support will start the download right away and won't open a new tab. – cheshire Apr 20 '17 at 19:08
  • 'download' is not supported on IE. – Tomas Aug 25 '17 at 12:32
  • FWIW, this works perfectly in Chrome for me, although in my case I'm setting the attribute programatically via Javascript (as in `a.setAttribute('download', filename||1)`). Curious to know if this is not working for anyone still or if @tirdadc was running into a Chrome bug that has since been fixed... – logidelic Aug 23 '19 at 13:43
  • 1
    Doesn't work in Chrome for cross origin requests. See also [chrome-download-attribute-not-working](https://stackoverflow.com/questions/23872902/chrome-download-attribute-not-working) – Tom Oct 02 '19 at 13:18
1

A javascript work around

That's the only "clean" work around I could think of & it seems to work just fine.


Some more code in your question showing how you actually use the "onbeforeunload" would be great.

But I will assume you are using something like the code below for the cursor "loading..." animation.

/* Loading Progress Cursor
 * 
 * Tested on:    IE8, IE11, Chrome 37, & Firefox 31
 * 
 * [1] the wildcard selector is not performant but unavoidable in this case
 */ 
.cursor-loading-progress,
.cursor-loading-progress * { /* [1] */
  cursor: progress !important;
}

The solution

1st step:

/* hooking the relevant form button
 * on submit we simply add a 'data-showprogresscursor' with value 'no' to the html tag
 */
$(".js-btn-download").on('submit', function(event) {
    $('html').data('showprogresscursor', 'no' );
});

2nd step:

/* [1] when page is about to be unloaded
 * [4] here we have a mechanism that allows to disable this "cursor loading..." animation on demand, this is to cover corner cases (ie. data download triggers 'beforeunload')
 * [4a] default to 'yes' if attribute not present, not using true because of jQuery's .data() auto casting
 * [4b] reset to default value ('yes'), so default behavior restarted from then on
 */
var pageUnloadOrAjaxRequestInProgress = function() {
    /* [4] */
    var showprogresscursor = $('html').data('showprogresscursor') || 'yes';  /* [4a] */
    if( showprogresscursor === 'yes' ){
        $('html').addClass('cursor-loading-progress');
    }
    else {
        $('html').data('showprogresscursor', 'yes' );  /* [4b] */
    }
}

$( window ).on('beforeunload', function() {    /* [1] */
    pageUnloadOrAjaxRequestInProgress();
});

Note that I use $('html').addClass('cursor-loading-progress'); as this is the expected CSS in my example but you can just do anything you like at this point.


Another couple of work arounds could be:

  • To open the file download page in a new tab
  • To trigger a page refresh once the file download is done
Adriano
  • 19,463
  • 19
  • 103
  • 140