Search code examples
javascriptdom-eventsonbeforeunload

Distinguish onbeforeunload for File Download vs Page Change


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.


Solution

  • 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