The behavior of the beforeunload
method varies across different browsers due to their attempts to prevent popups and malicious code from running within this handler.
Unfortunately, there is no consistent way to determine what triggered the beforeunload
event in a cross-browser manner.
In your specific case, you can differentiate between the two desired behaviors by detecting a click on the window
:
window.__exit_with_link = false;
window.addEventListener('click', function (e) {
// check if user clicked on a link
var isLink = e.target.tagName.toLowerCase() === 'a';
// check if the link targeted the current page:
// if it targets a popup/iframe/blank page,
// the beforeunload event on this page will not be triggered
var isSelf = !a.target.target || a.target.target.toLowerCase() === '_self';
if (isLink && isSelf) {
window.__exit_with_link = true;
// reset after a short delay
setTimeout(function(){ window.__exit_with_link = false; }, 50);
}
else { window.__exit_with_link = false; }
});
window.addEventListener('beforeunload', function (e) {
if (window.__exit_with_link) {
// user left the page by clicking a link
}
else {
// user left the page for another reason
}
}
While not ideal, this approach still functions. Similarly, additional handlers could be added to detect other reasons for the user leaving the page (such as using keyboard shortcuts like CTRL-R for refresh).