12

I would like to have an animation effect which starts when people leave a page.

I use this currently:

window.onbeforeunload = function (){
    alert("test");
    console.log("test");
    sliderIntervalId = setInterval('SlideDown()',1);
}

While the "test" is indeed logged to the console, the neither the function slideDown nor the test alert is produced...

Is this normal behavior? Can we use the beforeunload function only for backend purposes?

P.S. I'm testing on Chrome, that's why I had to use onbeforeUnload instead of onUnLoad which seems not to be supported by Chrome?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
jorrebor
  • 2,166
  • 12
  • 48
  • 74
  • I don't think you can postpone the new page from loading with onbeforeunload. alert actually stops execution and freezes the page until you click away the alert. – ChrisR Sep 26 '11 at 19:54
  • 2
    P.S. In an unrelated note you shouldn't pass strings to `setTimeout`, you should pass functions. `setInterval(SlideDown,1);` – gen_Eric Sep 26 '11 at 20:07
  • 2
    Chrome blocks `alert`s in `onbeforeunload`. If you look in the console, you'll see `Blocked alert('test') during beforeunload.`. Chrome supports `onunload`, but it's very restricted as to what it can do. Check this fiddle: http://jsfiddle.net/EE4Md/3/ – gen_Eric Sep 26 '11 at 20:25

4 Answers4

16

onbeforeunload can delay the page unload in only one case: When a return statement with a defined value is returned. In this case, the user gets a confirmation dialog, which offers the user an option to not leave the page.

Your desired result cannot be forced in any way. Your animation will run until the browser starts loading the next page:

[User] Navigates away to http://other.website/
[Your page] Fires `beforeunload` event
[Your page] `unload` event fires
[Browser] Received response from http://other.website/
[Browser] Leaves your page
[Browser] Starts showing content from http://other.website/
Rob W
  • 341,306
  • 83
  • 791
  • 678
4

Assuming jQuery for the sake of brevity:

$('nav a').click(function (e) {

    //ignore any "modified" click that usually doesn't open in the current window
    if (e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.isDefaultPrevented()) {
        return;
    }

    //where you going here?
    var place = this.href;

    //you're not going anywhere, buddy
    e.preventDefault();

    //watch me dance, first
    $('.animate-me').fadeOut(1000, function afterAnimation () {

        //you're free to go!
        document.location = place;
    });
});

Basically, you don't use onbeforeunload. One advantage is that you can keep the user as long as you want, one disadvantage is that the user won't see an animation when using a link outside nav (but you can just change the selector)

Obviously keep the animation fast, like suddenlyoslo.com do.

fregante
  • 29,050
  • 14
  • 119
  • 159
  • 1
    This will WORK if the user Clicks the `a` Link. What of if they literally typed the *www.othersite.com* in the Address bar?... or a site in the `iframe` wants to redirect to `www.someothersites.com`?...This will FAIL. You can test what I mean in the **http://jsfiddle.net/** *try to enter any input and then attempt exiting the page*. – ErickBest May 17 '14 at 17:22
  • That's correct. You can't reliably hold a browser from navigating away unless the navigation is trigger **in-page**, especially if you expect an animation to finish. I usually use this method in conjunction with a **simpler** animation on `onbeforeunload`, so I catch both cases. – fregante May 17 '14 at 17:41
3

Jorrebor, If your trying to have this animation fire when they leave your site or close the browser it will not work as intended. However, you can create this animation while the user travels within your site by removing the 'href' property of your links and creating animations that have a callback function that set the window.location property. Something like:

document.getElementById('home').onclick(function(){
     yourAnimationFunction(function(){
          window.location="example.com";
     });  
});

alot of work and wont be seo friendly however

Marlin
  • 751
  • 4
  • 8
3

I am working with onbeforeunload and What I was able to figure out is:

  • onbeforeunload handler is blocking the browser from destroying the current page
  • if you don't return anything, the popup does not appear.

So your code will be working as long as the event handler runs. This means that timer functions are not usable. They just add to the execution queue, so anything they would do is being queued after the end of currently running handler, which is after the last point in time you were guaranteed your code is still running.

So there is only one way to stop the browser from unloading before the animation finishes:

  • put a blocking loop that wastes some time in the beforeunload handler
  • start CSS3 animation by setting an appropriate class on the element before the loop
  • make the loop end when the animation finishes (make the loop check the actual height of an element or something)

Oh, and yes, this is a nastiest hack of all, but I was able to find a way to stop the browser from unloading the page, right?

I would appreciate comments with ideas on what to put in the loop. I am taking some options into account:

  • wasting CPU on come math on large numbers
  • accessing localstorage (synchronous call, IO operration)
  • accessing DOM (this solution already has to)

Any ideas?

naugtur
  • 16,827
  • 5
  • 70
  • 113