DEV Community

Cover image for Sure you want to leave?—browser beforeunload event

Sure you want to leave?—browser beforeunload event

Sam Thorogood on September 17, 2018

In the video, I explain a bit about the beforeunload event—which lets you prompt or warn your user that they're about to leave your page. If mi...
Collapse
 
yerycs profile image
yerycs • Edited

Thanks for good post.
I have one error, I want your help.

beforeunload function does not work if there is no user interaction.
It causes following error:

Blocked attempt to show a 'beforeunload' confirmation panel for a frame that never had a user gesture since its load.

How to show warning message even no user interaction?

Hoping your help.
Thanks

Collapse
 
samthor profile image
Sam Thorogood

Good observation, although I actually mentioned this in the article:

Showing a prompt isn't guaranteed. Just like playing audio on the web, browsers can ignore your request if a user hasn't interacted with your page.

This makes sense—a page that I've put into a background tab and then later closed shouldn't be able to get my attention!

Collapse
 
yerycs profile image
yerycs

Thanks for your reply.

Little trick.
So, is it impossible to show warning message if there is no user interaction?

Thread Thread
 
samthor profile image
Sam Thorogood

There's no harm in trying (a browser might decide that the page is allowed to—perhaps if your user has visited you a lot before) but it's unlikely to work. As per my post, maybe consider using sendBeacon if there's some information you want to exfiltrate from the page before it closes...

Even calling alert() is often disallowed in background pages (or at least delayed until the page gets focus again).

Thread Thread
 
yerycs profile image
yerycs

Let us assume.

I have passed complex page which has decades tests.
After passing this page, I get into the test result page.

If I click back button without any interaction in browser, then it goes to test page without confirmation, and I lost test result and should pass complex test again.

I hope it can be resolved.
Any Idea?

Thread Thread
 
samthor profile image
Sam Thorogood

Yes, that will go "back", but there are lots of other ways to store state (like your test results) that don't rely on the user keeping a page open.

e.g., indexdb, local storage, building a SPA where 'back' is handled by your code, etc ...

Thread Thread
 
yerycs profile image
yerycs

Understand.

Thanks for your kindly help.
Hoping your good post. :)

Collapse
 
yerycs profile image
yerycs

Do you think it is impossible to implement warning message without user interaction?

Thread Thread
 
samthor profile image
Sam Thorogood • Edited

Yes, I think it's impossible. Allowing an annoying popup to be generated without the user ever using the page is against what browsers are aiming for.

Thread Thread
 
yerycs profile image
yerycs

Can you explain about "against what browser are aiming for"?
Sorry for annoying. :)

Collapse
 
maxart2501 profile image
Massimo Artizzu • Edited

I've always found those notifications annoying but eh, they actually saved me a couple of times.

What's way worse in my opinions is showing those "don't miss this other content!" modals when the mouse cursor leaves the boundaries of the page. They should be outright banned! 😩

To stay on topic, I think sendBeacon is a great thing - too bad IE and mobile Safari don't support it 🙁

Collapse
 
karapapas profile image
karapapas

Hello! Great article on beforeunload.

I have a question though, is it possible to prevent page unload and stay on the page without prompting the user? Or, if that is not possible, to at least customize the confirmation dialog?

Thank you for your time!!

Collapse
 
samthor profile image
Sam Thorogood

No, that's the whole point. You could write something like "CLOSING THIS PAGE WILL EXPLODE YOUR COMPUTER", and browsers have decided that you should not be able to do that.

Collapse
 
oathkeeper profile image
Divyesh Parmar

How to ensure to know if a user has clicked on cancel on that alert? and Revert the action/API call that I was going to if user had proceeded to leave.

Collapse
 
samthor profile image
Sam Thorogood

Inside your beforeunload handler, you can add code in a setTimeout—probably even with a timeout of zero. That code will only run if the user allowed the page to stay open.

Collapse
 
oathkeeper profile image
Divyesh Parmar

Ok so we are basically making it async?

Thread Thread
 
samthor profile image
Sam Thorogood

Yeah, because your code otherwise won't have a chance to run.

I'd probably put a longer delay than zero on it, some browsers might let code execute even if the page is closing. I admit this behavior is a bit undefined.

Collapse
 
tux0r profile image
tux0r

Yes, please annoy a user who wants to leave...

Collapse
 
samthor profile image
Sam Thorogood

This feature exists on the web whether I write about it or not! :)

Hopefully this post has given some examples of when beforeunload is appropriate to use, and detailed a technical approach so that folks don't just generate warnings all the time. And you might also save your users' data—if a network request is still pending while a page is being closed, beforeunload can be useful to ensure that it does complete successfully.

Collapse
 
sleepyfran profile image
Fran González

This is a super useful feature that saved me countless times in pages in which I'd lose all my progress if they didn't implement it. Of course this can be used in bad situations, just like many other features, but that doesn't mean that it can't be helpful sometimes too.

Collapse
 
amsharma9 profile image
Amal • Edited

I would like to know if I can differentiate between beforeunload happening when closing window and moving away from page etc. I need to logout the user when s/he closes the window but NOT when s/he is moving to another page etc.

I am using sendBeacon right now as ajax didn't work.

Collapse
 
samthor profile image
Sam Thorogood

Moving to another page can be detected by watching focus or the Page Visibility API. The page is still open in that case, just hidden or not being used by the user.

Collapse
 
sashirocks1 profile image
Sashi • Edited

I use the following piece of code in 'beforeunload' to delete a user session during logout, but this fails to clear the user session on a firefox browser, can you please help out here
var req = new XMLHttpRequest();
req.open('DELETE', URI, true);
req.setRequestHeader("TOKEN", $rootScope._TOKEN);
req.send(null);

Collapse
 
samthor profile image
Sam Thorogood

Don't send an XMLHttpRequest—use sendBeacon, like I mentioned in the article.

Collapse
 
jalson1982 profile image
Jalson1982

Any idea how to perform graphql mutation with sendBeacon?

Collapse
 
samthor profile image
Sam Thorogood

Well, you send off a POST request with sendBeacon. You'd tell your server (on some HTTP handler) to do something, but you wouldn't be able to see whether the result was successful.

Collapse
 
jalson1982 profile image
Jalson1982

The issue with this I can not set headers or on some way control it. I am using synchronous XMLHttp request, it runs on all browsers but slows down a little navigation and it is not also the most happier solution. I do not need to see the result I just need to save analytics data to db on browser close.

Collapse
 
kenny08gt profile image
Alan Hurtarte

Thanks! this is very helpful, I wish it had an option to make an action when the user actually agree to leave, like delete localstorage.

Collapse
 
samthor profile image
Sam Thorogood

You could do the action and revert it if your JS runs again.

Collapse
 
samishakhurana profile image
Samisha Khurana

Hi, Thanks for an insightful post.
Is there any way I can track the click of leave button on this popup.
If user click on cancel button we can use setTimeOut to do some operations, but in my case I want to do some final operation on click of leave button.

Collapse
 
rudyhadoux profile image
rudyhadoux

Hi,

For Angular, @HostListener( 'window:beforeunload' ) seems not working for every browsers...

Collapse
 
pinguinosod profile image
David Cautin

Everything works fine, except when I try to create UI tests, seems like firefox doesn't trigger beforeunload when it is being controlled by an automated software.

Collapse
 
samthor profile image
Sam Thorogood

Unfortunately, since the browser is entirely allowed to decide whether to show this message at all (e.g. if a tab has never had focus), it might not be something you can really test in an automated fashion. 😔

Collapse
 
tachuong20121997 profile image
Chuong Tran

I use Reactjs to build the app, and "beforeunload" doesn't seem to work on iphone safari