Fixing addEventListener not working with beforeunload
Guide to Fixing why addEventListener not working with beforeunload event!
Jul 7, 2023 | Read time 10 minutesπ Table of contents
Introduction
The reason why addEventListener not working with beforeunload can be due to:
- Using βonbeforeunloadβ instead of βbeforeunloadβ - and check for any typos!
- The user have not interacted with the page - sticky activation
- You are not using the
event.returnValue
property - You are not using the
event.preventDefault()
function - There are browser compatibility issues
Recently I was working on a Vue project and had the requirement to display a message to the user before they leave the page.
I wanted to also save the userβs form data when they leave the page also - just to make sure that they do not lose any of their data.
However, I found that using the βbeforeunloadβ was not working.
β Note: The onbeforeunload event is a special type of event in JavaScript that is triggered when the user is about to leave the current webpage. This event is often used to warn users about unsaved changes or other important state that could be lost if they navigate away.
In this post I will detail over the steps and checklist I took to troubleshoot and fix this error.
1. Using βonbeforeunloadβ instead of βbeforeunloadβ - and check for any typos!
A common mistake is to use the βonbeforeunloadβ when calling the addEventListener
:
// β This will not work
window.addEventListener('onbeforeunload', function (event) {
// Your code here...
});
The proper way is to use βbeforeunloadβ (eg no - βonβ prefix)
window.addEventListener('beforeunload', function (event) {
// Your code here...
});
Keep in mind that addEventListener
is case-sensitive on the event types that it accepts. So only βbeforeunloadβ (all lowercase will work) and NOT βBeforeUnloadβ (having capitals)
π Difference between onbeforeunload and beforeunload
So what is the difference between βonbeforeunloadβ and βbeforeunloadβ??
They are pretty much the same - just different ways of registering the event handler in JavaScript.
If you are dealing with βonbeforeunloadβ - you can set the handler on objects like βwindowβ:
window.onbeforeunload = function(e) {
return 'Are you sure you want to leave?';
};
If you are using βbeforeunloadβ, then it is a string (case-sensitive) that is passed to the addEventListener
function:
window.addEventListener('beforeunload', function(e) {
e.preventDefault();
e.returnValue = 'Are you sure you want to leave?';
});
In terms of functionality, the should be able to fire when the document and its resources are about to be unloaded.
Using addEventListener with βbeforeunloadβ is generally considered better practice because it allows you to add multiple event handlers for the same event, whereas onbeforeunload only allows one.
Another disadvantage of using βonbeforeunloadβ is that if you assign a new function to it - the old handler will be overwritten.
2. The user have not interacted with the page - sticky activation
One thing to keep in mind is that the beforeunload event will only be triggered when sticky activation is true.
So what the heck is sticky activation??
Its also known as βsticky user activation,β is a state of a window that signifies a user has interacted with the page through actions like:
- clicking a button,
- moving the mouse,
- using a menu, or other user interactions.
A page is deemed βuser activatedβ if a user is currently interacting with it or has performed a touch, pointer, or keyboard interaction since the page was loaded.
Sticky user activation remains set for the entire session once itβs activated.
So it may be that your code is correct, but the beforeunload might seem like its not working because the user have not done anything with the page!
Additionally, uou can check if sticky activation is on by checking the UserActivation.hasBeenActive property!
if (navigator.userActivation.hasBeenActive) {
// proceed with auto-playing an animation, for example
}
3. You are not using the event.returnValue
property
Generally, you will need to supply a value for the event.returnValue property. The HTML standard does not require this, but some browsers seem to expect it.
Hereβs an example:
window.addEventListener('beforeunload', function (event) {
event.preventDefault(); // If you want to prevent the default action
event.returnValue = 'Do you want to leave?'; // This will cause a confirmation dialog to appear
});
Now originally, the string you set for the βreturnValueβ is what is going to be displayed in the dialog. However with more modern browsers this is just replaced by a standard message.
π History of beforeunload event
Over the years theres been a few changes to the βbeforeunloadβ and how that is implemented with browsers.
In 2014, the general approach would be:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "Do you want to leave?";
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Webkit, Safari, Chrome etc.
});
Now with more modern browsers and updated HTML standard, the approach to maximize browser compatibility is:
window.addEventListener('beforeunload', (event) => {
// Cancel the event as stated by the standard.
event.preventDefault();
// Chrome requires returnValue to be set.
event.returnValue = '';
});
We do need to set a meaningful message text for the beforeunload event, as it will lead to inconsistent user experiences across different browsers.
- You can use event = event || window.event to ensure that the event object is defined.
- Use event.preventDefault(), but first check if preventDefault is defined.
- Set
event.returnValue = ''
andreturn ''
to ensure the beforeunload event works correctly.
4. You are not using the event.preventDefault()
function
According to the specification, to show the confirmation dialog an event handler should call preventDefault()
on the event.
The preventDefault() method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.
5. There are browser compatibility issues
The HTML specification advises using the Event.preventDefault() method instead of Event.returnValue to prompt the user, but not all browsers support this yet.
If this event returns a value other than null or undefined, or if the returnValue property is set to such a value, the user will be prompted to confirm the page unload.
In older browsers, the return value of the event is displayed in this dialog. However, since Firefox 44, Chrome 51, Opera 38, and Safari 9.1, a generic string not controlled by the webpage is shown instead.
Firefox displays: βThis page is asking you to confirm that you want to leave - data you have entered may not be saved.β
Chrome displays: βDo you want to leave the site? Changes you made may not be saved.β
Some browsers may ignore calls to window.alert(), window.confirm(), and window.prompt() during this event.
Certain browsers ignore the result of the event and do not ask the user for confirmation at all, automatically unloading the document. Firefox has a switch named dom.disable_beforeunload in about:config to enable this behavior.
As of Chrome 60, the confirmation will be skipped if the user has not performed a gesture in the frame or page since it was loaded. Pressing F5 in the page counts as user interaction, but mouse-clicking the refresh arrow or pressing F5 with Chrome DevTools focused does not count as user interaction (as of Chrome 81).
π TIP: Using the onbeforeunload in HTML
One thing that I found works the best for cross browser compatibility is to use the βonbeforeunloadβ attribute in HTML:
<body onbeforeunload="alert('Goodbye')">
Keep in mind that the onbeforeunload event can be invoked by:
- Navigating to another page directly in the browser or via a link.
- Closing the current browser window or tab page.
- Reloading the current page.
- Manipulating the URL of the currently loaded page through the location object from JavaScript.
- Invoking the window.navigate method.
- Invoking the window.open or the document.open method to open a document in the same window.
Summary
Generally, addEventListener
is not working with beforeunload
can be due to multiple reasons.
This can mean that you are using onbeforeunload instead of βbeforeunloadβ. Also make sure that there are no typos since addEventListener
event type is case-sensitive.
Also check for the following:
- that the user have interacted with the page (sticky activation)
- you have set a value for event.returnValue
- you have called the event.preventDefault()
- browser compatibility issues with beforeunload - the HTML standard is not fully implemented by modern browsers