-
Notifications
You must be signed in to change notification settings - Fork 22.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modernize beforeunload event information #29595
Conversation
Preview URLs
External URLs (3)URL:
(comment last updated: 2023-10-12 08:18:11) |
- {{domxref("SVGSVGElement")}} | ||
|
||
## Security | ||
- Only show the dialog box if the frame or any embedded frame receives a user gesture or user interaction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not that clear what this means and how it differs from sticky activation (the third condition). I understand the sticky activation requirement (and think it is maybe worth spelling out: the point being that if the user has never interacted with the page, then there is no user data to save, so no legitimate use case for the dialog).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I was supposed to merge those into one point as they are basically the same thing. I've done that in my next commit, as well as adding your thought about "if the user has never interacted..."; I think that is useful. Thanks!
event.returnValue = "any non-empty string value"; | ||
// Equivalent to invoking event.preventDefault(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this example should be showing the non-recommended version (setting returnValue
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you're right. I've updated it to show the same example as on the event page, and I've added a note at the bottom of the section to say that the returnValue
property can also be used, but it is legacy and not best practice.
if (event.target.value !== "") { | ||
window.addEventListener("beforeunload", beforeUnloadHandler); | ||
} else { | ||
window.removeEventListener("beforeunload", beforeUnloadHandler); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why add/remove listeners on input, rather than always have the beforeunload
listener, but conditionally call preventDefault()
based on the value of target
? It seems like that would be more efficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reasons explained in the "Usage notes" section of the event page, most critically the one about Firefox not placing pages in the bfcache if they have beforeunload listeners.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I just realised this. Maybe worth mentioning in the description of this example to save other people from making my mistake!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call; done.
|
||
The `beforeunload` event is fired when the window, the document and its resources are about to be unloaded. | ||
The `returnValue` property defined on `BeforeUnloadEvent`, when set to a non-empty string value, triggers a browser-generated confirmation dialog. This dialog asks users to confirm if they _really_ want to leave the page when they try to close or reload it, or navigate somewhere else. It is intended to help prevent loss of unsaved data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sort of see the point of describing this property here, but I think it would be better just to describe it in the returnValue
page, and adapt the note slightly like:
> **Note:** The `returnValue` property of this interface is...
Otherwise it looks a bit odd that you are going to special lengths to describe this property in this paragraph, then undercutting it immediately in the note.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I've removed most of this text, making sure it is covered in the returnValue
page itself, and added a note about it being legacy to the returnValue
description on the BeforeUnloadEvent
page. This seemed like a better place for it to go.
|
||
## Value | ||
|
||
`returnValue` is initiailized to an empty string (`""`) value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`returnValue` is initiailized to an empty string (`""`) value. | |
`returnValue` is initialized to an empty string (`""`) value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next commit; thanks!
|
||
`returnValue` is initiailized to an empty string (`""`) value. | ||
|
||
Setting it to just about any [truthy](/en-US/docs/Glossary/Truthy) value will cause the dialog to be triggered on page close/reload. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth repeating or linking to the extra conditions (e.g. sticky activation) or this will mislead people.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I've added this info to the returnValue
page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really good, thanks for updating the docs! My concern is that there is no mention of the return "non-empty string"
pattern, which is likely still used by a lot of web developers.
The HTML specification states that calls to {{domxref("window.alert()")}}, {{domxref("window.confirm()")}}, and {{domxref("window.prompt()")}} methods may be ignored during this event. See the [HTML specification](https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#user-prompts) for more details. | ||
- Calling the event object's {{domxref("Event.preventDefault()", "preventDefault()")}} method. | ||
- Setting the event object's {{domxref("BeforeUnloadEvent.returnValue", "returnValue")}} property to a non-empty string value. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that returning a value (e.g. "return "Not empty string") will also trigger the cancel dialog. However, that behavior is weird as it doesn't work on addEventListener, but does work on onbeforeunload. It is a legacy behavior and should still be mentioned on the docs.
You can read more context at crbug.com/809277.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good call, thank you! I have mentioned this now, both in the list of methods for triggering the dialog, and in a comment in the code example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 thank you Chris! Approving but leaving open in case @dizhang168 wants to verify that their comments are addressed. But this is good as far as I am concerned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! (can't approve as I am not a repo owner)
Description
Chrome 119 includes an update to the
beforeunload
event — it now triggers the "leave page?" confirmation dialog whene.preventDefault()
is called upon the event firing, and doesn't do that whene.returnValue
is set to an empty string. This is great because Chrome now behaves like other browsers, so this event is immediately more useful than it was.This PR:
Also related:
Motivation
Additional details
Related issues and pull requests