jQuery beforeunload reliability [duplicate] - javascript

I have a form where the input fields are saved onChange. In Firefox (5) this works even when the window is closed, but for Chrome and IE it doesn't and I need to be sure that I'm saving this data even if they try to close the window after they've typed in a field but an onBlur event hasn't occurred (i.e. they've typed something into a textbox, but haven't tabbed out of it).
I have read the following SO articles on using window.onbeforeunload:
article 1
article 2
if I use the following:
window.onbeforeunload = function() {
return "onbeforeunload";
}
then I get a popup with onbeforeunload in.
but if I try:
window.onbeforeunload = function() {
alert("onbeforeunload");
}
then nothing happens in any browser, even Firefox.
what I want to achieve is:
window.onbeforeunload = function() {
saveFormData();
}
I'd be grateful if someone could point out where I might be going wrong.

You have to return from the onbeforeunload:
window.onbeforeunload = function() {
saveFormData();
return null;
}
function saveFormData() {
console.log('saved');
}
UPDATE
as per comments, alert does not seem to be working on newer versions anymore, anything else goes :)
FROM MDN
Since 25 May 2011, the HTML5 specification states that calls to window.showModalDialog(), window.alert(), window.confirm(), and window.prompt() methods may be ignored during this event.
It is also suggested to use this through the addEventListener interface:
You can and should handle this event through window.addEventListener() and the beforeunload event.
The updated code will now look like this:
window.addEventListener("beforeunload", function (e) {
saveFormData();
(e || window.event).returnValue = null;
return null;
});

There seems to be a lot of misinformation about how to use this event going around (even in upvoted answers on this page).
The onbeforeunload event API is supplied by the browser for a specific purpose: The only thing you can do that's worth doing in this method is to return a string which the browser will then prompt to the user to indicate to them that action should be taken before they navigate away from the page. You CANNOT prevent them from navigating away from a page (imagine what a nightmare that would be for the end user).
Because browsers use a confirm prompt to show the user the string you returned from your event listener, you can't do anything else in the method either (like perform an ajax request).
In an application I wrote, I want to prompt the user to let them know they have unsaved changes before they leave the page. The browser prompts them with the message and, after that, it's out of my hands, the user can choose to stay or leave, but you no longer have control of the application at that point.
An example of how I use it (pseudo code):
onbeforeunload = function() {
if(Application.hasUnsavedChanges()) {
return 'You have unsaved changes. Please save them before leaving this page';
}
};
If (and only if) the application has unsaved changes, then the browser prompts the user to either ignore my message (and leave the page anyway) or to not leave the page. If they choose to leave the page anyway, too bad, there's nothing you can do (nor should be able to do) about it.

The reason why nothing happens when you use 'alert()' is probably as explained by MDN: "The HTML specification states that calls to window.alert(), window.confirm(), and window.prompt() methods may be ignored during this event."
But there is also another reason why you might not see the warning at all, whether it calls alert() or not, also explained on the same site:
"... browsers may not display prompts created in beforeunload event handlers unless the page has been interacted with"
That is what I see with current versions of Chrome and FireFox. I open my page which has beforeunload handler set up with this code:
window.addEventListener
('beforeunload'
, function (evt)
{ evt.preventDefault();
evt.returnValue = 'Hello';
return "hello 2222"
}
);
If I do not click on my page, in other words "do not interact" with it, and click the close-button, the window closes without warning.
But if I click on the page before trying to close the window or tab, I DO get the warning, and can cancel the closing of the window.
So these browsers are "smart" (and user-friendly) in that if you have not done anything with the page, it can not have any user-input that would need saving, so they will close the window without any warnings.
Consider that without this feature any site might selfishly ask you: "Do you really want to leave our site?", when you have already clearly indicated your intention to leave their site.
SEE:
https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload

I seem to be a bit late to the party and much more of a beginner than any expertise; BUT this worked for me:
window.onbeforeunload = function() {
return false;
};
I placed this as an inline script immediately after my Head and Meta elements, like this:
<script>
window.onbeforeunload = function() {
return false;
}
</script>
This page seems to me to be highly relevant to the originator's requirement (especially the sections headed window.onunload and window.onbeforeunload):
https://javascript.info/onload-ondomcontentloaded
Hoping this helps.

you just cant do alert() in onbeforeunload, anything else works

To pop a message when the user is leaving the page to confirm leaving, you just do:
<script>
window.onbeforeunload = function(e) {
return 'Are you sure you want to leave this page? You will lose any unsaved data.';
};
</script>
To call a function:
<script>
window.onbeforeunload = function(e) {
callSomeFunction();
return null;
};
</script>

Yes what everybody says above.
For your immediate situation, instead of onChange, you can use onInput, new in html5. The input event is the same, but it'll fire upon every keystroke, regardless of the focus. Also works on selects and all the rest just like onChange.

Related

AngularJS how to show browser dialog protects before changing tab

I have to display a message which warns the user before changing tab without saving changes. An url in the browser does not change in this process because user changes only a tab.
SetPristine, SetDirty will not help me because the url does not change. Is there any way to display this system-browser popup manually? If not maybe can you tell me how to create identical alert in the same space (it is placed in top-center part of the website).
I would like to get a result similar to the picture below.
Thanks in advance :)
What your asking for is not an Angular only thing. You can do it in pure javascript.
What you're asking about is the beforeUnload event.
Here is some sample code from mozilla:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "\o/";
e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+
return confirmationMessage; // Gecko, WebKit, Chrome <34
});
This example prevents a dialog box, but to show one you need to set the return value to your dialog text:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "\o/";
return "You will loose any unsaved changes, by leaving the page"
});
Another mozilla page explains in more detail
What this means is you can put other code in the event handler that will pop up a modal say, or some other dialog to inform the user about data loss.
If what you want is actually about changing tab, then the cleanest way is to use the Page Visibility API which is reasonably well supported now.
What you want is now more like so:
document.addEventListener("visibilitychange", handleVisibilityChange, false);

Display custom alert box like facebook when you navigate to other page

I want to show custom alert box instead of browser default alert box when user tries to navigate from the existing page. Using this code:
window.onbeforeunload = function(){
return "are you sure?";
}
I can use this code to alert user if he has any unsaved data and want to leave page. But I want to make custom alert box with my own design like facebook does. How it is possible? Something like:
window.onbeforeunload = function(){
myownalertbox.show(); //here I want to bind leave page or stay on page button with my own button.
}
And I want to bind stay on this page and leave this page button to my button.
The problem is not with implementing custom alert boxes (as some of the other answers pointing it out), that's not a hard thing to do, there are plenty of solutions, framework, plugin, etc. The problem is JavaScript execution timing.
Using the onbeforeunload handler it's impossible to achieve your goal, because it needs to run "synchronously": you cannot display the alert, return something and then later with some callback get back and return the actual value. When you return from the function, the result will be used by the browser, and you will end up having your custom alert box shown, but the user action will be "lost", because the handler has already been finished.
To go further, I've never been able to find any solution which would provide a custom alert box, which behaves synchronously in this sense. By synchronous behavior I mean that code execution would be blocked until a user clicks on alert buttons. Every custom alert/confirm/prompt solution I've seen was using callbacks. And last but not least JavaScript doesn't even provide a way for kind of a "blocking waiting".
UPDATE
What you can do (and Facebook does it too) is to handle navigation links, buttons, clicks, etc. which you know that will leave the page, and there you can show a custom confirmation box.
Note: Actually I've tried Facebook, and for me (Windows 10, Chrome latest) it prompts the default confirmation box when I tried to close the browser tab, not any custom one. But when I clicked on a link, it indeed showed a custom confirmation box. So to summarize, Facebook, when possible, uses the custom one, and when not possible (only with onbeforeunload, like browser close, tab close, page reload, URL navigation, etc.) it uses the default handling mechanism.
Note 2: For 2016 it seems like all major browsers chose to not let developers customize the message which is shown on onbeforeunload, so your string return value from the handler will not be taken as the message. There are several articles about this. The main reason is safety, as lots of sites used it for tricking naive users and asking them do do some actions, or prompting them malicious content, etc. Now all major browsers display a default message about possibly having unsaved changes.
The orginal answer is suitable for IE6-8 and FX1-3.5 , but is rather out of date now and won't work in most current browsers - I've left it below for reference.
The window.onbeforeunload is not treated consistently by all browsers. It should be a function reference and not a string (as the original answer stated) but that will work in older browsers because the check for most of them appears to be whether anything is assigned to onbeforeunload (including a function that returns null).
You set window.onbeforeunload to a function reference, but in older browsers you have to set the returnValue of the event instead of just returning a string:
var confirmOnPageExit = function (e)
{
// If we haven't been passed the event get the window.event
e = e || window.event;
var message = 'Any text will block the navigation and display a prompt';
// For IE6-8 and Firefox prior to version 4
if (e)
{
e.returnValue = message;
}
// For Chrome, Safari, IE8+ and Opera 12+
return message;
};
You can't have that confirmOnPageExit do the check and return null if you want the user to continue without the message. You still need to remove the event to reliably turn it on and off:
// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;
// Turn it off - remove the function entirely
window.onbeforeunload = null;
To turn it on:
window.onbeforeunload = "Are you sure you want to leave?";
To turn it off:
window.onbeforeunload = null;
Bear in mind that this isn't a normal event - you can't bind to it in the standard way.
To check for values? That depends on your validation framework.
In jQuery this could be something like (very basic example):
$('input').change(function() {
if( $(this).val() != "" )
window.onbeforeunload = "Are you sure you want to leave?";
});
I would use some normal HTML layout, and play with CSS's display:none;/display:block;
For instance (you do your styling):
CSS:
.popup {
display: none;
position: absolute;
left: 20%;
top: 20%;
height: 60%;
width: 60%;
background-color: orange;
}
JAVASCRIPT:
var myownalertbox = {
show: function(message) {
var popup = document.createElement("DIV");
popup.className = "popup";
document.body.appendChild(popup);
popup.style.display = "block";
popup.innerHTML = message;
var ybutton = document.createElement("BUTTON");
ybutton.innerHTML = "YES";
var nbutton = document.createElement("BUTTON");
nbutton.innerHTML = "NO";
ybutton.onclick = function () {
// do with "YES"
window.location = "/main.html"; // <-- go back to the main page
popup.style.display = "none";
}
nbutton.onclick = function () {
// do with "NO"
window.location = "#"; // <-- stay at this page
popup.style.display = "none";
}
popup.appendChild(ybutton);
popup.appendChild(nbutton);
}
}
myownalertbox.show("ARE YOU SURE?");
Here's a JSFiddle.
You can try this website.
http://t4t5.github.io/sweetalert/
It is not a custom alert box but it provides alert box that are actually quite beautiful.
I am attaching you a link from where I used code to customize my dialog/alert boxes. Hope this might help you.
http://www.bitrepository.com/stylish-javascript-dialog-boxes.html

Why onbeforeunload event is not firing

I tried the code on Chrome, FireFox and Safari. Still the onbeforeunload does not fire. I also tried the onunload, but it did not work.
Here is the code I am experimenting with:
<!doctype html>
<html lang="en">
<head>
<title> Output to a Page </title>
<meta charset="utf-8">
<script>
window.onload = init;
window.onclick = clk;
window.onbeforeunload = closing;
function clk() {
window.alert("Ouch !!");
}
function closing() {
console.log("function alrt WORKS !!!!");
window.alert("closing now.....");
}
function init() {
var output = "";
for (var mms = 5; mms > 0; mms--) {
if (mms >= 3) {
output += "Still lots of M&Ms left, so eat more!<br>";
} else {
output += "Getting low on M&Ms, take it easy!<br>";
}
}
output += "All out of M&Ms";
var e = document.getElementById("output");
e.innerHTML = output;
}
</script>
</head>
<body>
<p id="output"></p>
</body>
</html>
Onbeforeunload is subject of one of bigest missunderstanding in the webdevelopers world :D
1) It refuses to call all blocking native functions (alert, prompt, confirm). It is obvious from User perspective.
2) it (according to MDN) should be registered by "addEventListener" (MDN)
3) It is fired only if there was ANY interaction of the user with the site. Without ANY interaction (even one click anywhere) event onbeforeunload won't be fired.
4) The aim of this event IS eg. secretly saving data left in forms (or else) on behalf of user (or logging user behavior etc.). It is NOT for blocking refreshing the site !
Thus there is no way (because it would be for nothing) to show personalised information.
The only sens is to hide the prompt window while reloading with prior saveing data.
5) If you want to hide the prompt window just NOT set any value for the event.returnValue field.
This example unload site (writing on console text "UNLOAD:1") without window prompt during refresh.
window.addEventListener("beforeunload", function(event) {
console.log("UNLOAD:1");
//event.preventDefault();
//event.returnValue = null; //"Any text"; //true; //false;
//return null; //"Any text"; //true; //false;
});
This example unload site (writing on console text "UNLOAD:1") WITH window prompt during refresh.
window.addEventListener("beforeunload", function(event) {
console.log("UNLOAD:1");
//event.preventDefault();
event.returnValue = null; //"Any text"; //true; //false;
//return null; //"Any text"; //true; //false;
});
You can use any kind of value to event.returnValue (as listed on the right). It is just coding style matter.
Both event.preventDefault nor return has no influence on this event (so in your code you can omit those commented lines).
Tested on Chrome, Edge, Firefox, Opera (verified on 23.09.2019). Hope it helps.
[EDIT:]
To avoid reloading mobile application by accidentally swipe/drag of the screen (eg. google maps, images and any other stable content) this css trick can be usefull:
body {
overscroll-behavior-y: contain !important;
}
The application will be safe against reloading.
It is woth to consider to give to user another possibilty (eg. some button) to reload if needed.
The onbeforeunload event is not cancel-able, because of security reasons, but if an event handler function for the onbeforeunload event returns a string value, this text will be shown in a confirmation dialog box, where the user can confirm whether he wants to stay or leave the current page.
Note that event listeners cannot be registered for the onbeforeunload event with the addEventListener and attachEvent methods (only Safari and Google Chrome support it). For a cross-browser solution, register the event handler in HTML (with the onbeforeunload attribute of the body element) or with the onbeforeunload in-line event property of the window object. See the examples below for details.
Examples:
In HTML:
<ELEMENT onbeforeunload="handler">
In JavaScript:
object.onbeforeunload = handler;
object.addEventListener ("beforeunload", handler, useCapture);
Actions that invoke the onbeforeunload event:
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.
Try to modify your code, like this:
window.onbeforeunload = closing;
/* other code here */
var closing = function () {
console.log("function alrt WORKS !!!!");
window.alert("closing now.....");
}
...or just put directly the code in your body tag:
<body onbeforeunload="alert('function alrt WORKS !!!!')">
See here and here for more details.
I faced problem where neither beforeunload nor onunload worked to execute one ajax call that should get called when user closes the browser. In fact, none of the methods worked. The javascript method was inside the body tag, which was actually the problem. It was magically solved when I moved the javascript method inside Head tag.
For people who are experiencing this issue in certain browsers (Safari in my case), after some research, I realized that it was because of how the browser works. This post has a more detailed explanation.
Basically, what I did was to use the alternative which is onpagehide, and so far it works with all browsers that I have tested.

Can I stop JS location.href without a popup?

I want to build a JS external script ( tag) which stops code (which usually isn't mine) like location.href from happening without the use of a popup.
I tried things like:
$(window).bind('beforeunload', function() {
window.stop();
event.stopImmediatePropagation();
event.preventDefault();
location.href = '#';
});
but nothing seemed to help.
again, I need it without the use of the: return "are you sure?"
maybe a different callback?
Thanks,
Dan
The right way to use onbeforeunload to confirm navigating away is to just return the string of the message you want to have shown. MDN has this to say.
The function should assign a string value to the returnValue property of the Event object and return the same string
So your onbeforeunload function for the behavior you ask for would just be (same as binding it with jquery, especially since onbeforeunload does not support multiple event listeners like other events do)
window.onbeforeunload = function() {
return "Are you sure?";
};
But ironically, Firefox doesn't support this for security purposes.
Note that in Firefox 4 and later the returned string is not displayed to the user. See bug 588292.
Edit: I read more of the bug report. The main reason they site for this decision is: "1. Remove the site-supplied text, since this is a security issue (untrusted text in browser dialogs)". I wonder how they feel about an alert?
Most modern browsers (Chome, IE 9+ or earlier, and Opera, I know for sure) will ignore anything you try to do in an onbeforeunload function other than returning a string for display. This is to prevent hijacking the users browser, opening popups, overriding navigation attempts by pointing the user another, possibly malicious domain, etc.
Edit 2: I was apparently incorrect. Only some things are disallowed in onbeforeunload, they just happen to mainly be the types of things you tried in your sample code, having to do with event propagation and page navigation. From deep in the comments of that FF bug report, user oyasumi posts a link to this jsFiddle with a work around for displaying custom text to FF 4+ users: http://jsfiddle.net/ecmanaut/hQ3AQ/ So apparently calling alert() is still allowed, even in onbeforeunload, which hilariously is doing exactly what the was original reason for the 'bug' "fix": displaying custom text in a browser/application/OS/official-looking dialog.
did you try to use "return false" ?
Also you should have the event sent to your function.
here is an example where you can prevent from a button click and hyper link
<input type="button" value="click me" />
google
$(document).ready(function(){
$('input[type="button"]').click(function(e){
e.preventDefault();
});
$('a').click(function(e){
e.preventDefault();
});
});
here is the link http://jsfiddle.net/juTtG/143/

How to change css visibly before returning something on "window.onbeforeunload"

I would like to ask a question about window.onbeforeunload.
I consider making a covering-element appear before confirming whether to unload or not.
But the following code seems not to work fine. The dom element 'COVERALL' appears just after confirming unloading.
window.onbeforeunload = function(event){
$( COVERALL )
.css('zIndex', 1000000)
.fadeTo(1000, 1.0);
~~~~
~~~~
some time-consuming tasks here
~~~~
~~~~
return event.returnValue = "are you sure?";
}
The correct way to do this is using an event listener to capture the event object and then prevent the default action which is to leave.
window.addEventListener('beforeunload',
function(e)
{
if (!confirm('Are you sure that you want to leave?'))
e.preventDefault();
}, 1);
Its implementation may vary between browsers though. In my Fiefox 6, it asks again to confirm once the e.preventDefault(); instruction is reached, as a security measure implemented by Mozilla.
August 1st:
Today I have tried, and, in Chromium browser, if you prevent default action without asking user for confirmation such as with a confirm box, the page will close anyways.
I did some research today about this, and I have found that it is apparently impossible to trigger a page close event from Javascript, so using a custom HTML made confirm box for this would be out. I tried creating custom events, dispatching them to various window elements and even inspecting and copying browser made events. (All this on Firefox, in Chromium I did not check because, well, no support in Firefox means not to ever rely on something like that)
But good news for you, I have found that if you quickly set up an XMLHttpRequest and send the information you want to save before leaving, the data sending will finish in background even if the page has been closed.
I have successfully been able to achieve that for both browsers with the following code.
window.addEventListener('beforeunload',
function(e)
{
var fd = new FormData();
fd.append('html', document.body.innerHTML);
var xhr = new XMLHttpRequest;
xhr.open('POST', './dataRetriever.php');
xhr.send(fd);
// uncomment these if you want confirmation for all browsers
// because this code will not ask for confirmation in others
// than Mozilla powered ones.
//if (!confirm('Leave?'))
// e.preventDefault();
}
, 1);
With that one, I send all the body innerHTML to my dataRetriever.php script so tell me how it goes and if it works for you as expected.

Categories

Resources