Best practice for warning the user they will lose data - javascript

I have a site which uses a lot of JavaScript (mainly jQuery) and I need a nice global way to let the user know that they will lose unsaved changes when they navigate away from a particular page.
At the moment I have an onchange event placed on the inputs and wrap my main navigation in a function which will display the warning when clicked.
This feels really clunky and doesn't scale well (navigation which is not part of the main navigation needs to be manually wrapped, which is far from ideal)

I have an onchange event on my inputs and set an isDirty variable to true when they change.
Then I use onbeforeunload event to warn the user about unsaved changes:
var isDirty = false;
window.onbeforeunload = function (evt) {
if (isDirty) {
return 'If you continue your changes will not be saved.';
}
}

You are looking for the onbeforeunload event.
like
$(window).bind('beforeunload', function(){
return "Are you really sure?";
});
native:
window.onbeforeunload = function(){
return "Are you really sure?";
});
That of course is just the "preventing method". You still need some logic to know whether or not there were changes on your site. That could easily be done by using a boolean for instance. Furthermore you should make a quick detection like
if('onbeforeunload' in window){}
I think all major browsers support the event nowadays, but there are still browser which don't know that event. So if the above condition fails, you can still fallback gracefully to another way.

Use on the on unload window event to catch when the page is going to change. Then prompt a lightbox alert to warn the user if navigating away any unsaved data will be lost.

Related

Catch back button - ASP

I want to redirect client to custom controller when he click back browser button.
Do you know any clear ways to catch back button event and force to call server?
Bests,
Thank you
Back button question is quite well answered on SO. A quick search will turn up lots of extra information. Here is a bit of a summary.
You have a few strategies to choose from.
1 - If you are developing an SPA (or not) you may find making use of the history api useful.
https://developer.mozilla.org/en-US/docs/Web/API/History
https://developer.mozilla.org/en-US/docs/Web/API/History_API
You will find plenty on SO about history api.
Try starting here Preserve dynamically changed HTML on back button
Basically, by adding a listener for popstate event which fires everytime the active history entry changes :
(in jQuery)
$(document).ready(function () {
$(window).on('popstate' , function (event) {
console.log('popstate');
console.log(event);
console.log(event.originalEvent);
});
};
http://caniuse.com/#search=history
2 - add a listner for the pageshow event, will fire when a page load is completed and when session history entry is used for navigation, so basically forward & back buttons.
https://developer.mozilla.org/en-US/docs/Web/Events/pageshow
$(window).on('pageshow' , function (event) {
console.log('pageshow');
console.log(event);
console.log(event.originalEvent);
});
http://caniuse.com/#search=pageshow
3 - Append a hashvalues to your urls with window.location.hash = 'pageHashValue'.
Listen for hashchange event and you can then act based on the #value if needed.
https://developer.mozilla.org/en-US/docs/Web/Events/hashchange
This is a common approach in single page applications.
$(window).on('hashchange' , function (event) {
console.log('hashchange');
console.log(event);
console.log(event.originalEvent);
console.log(window.location.hash);
});
http://caniuse.com/#search=hashchange
Finally take note that while you, as a developer, no doubt hate the browser back button (like me) our users tend to love it. If you change the expected behavior of the back button you can also expect your user experience to be negatively affected. The best strategy is to use these events to maintain the expected behavior of the back button rather than to try and change it.

Is there a way to overwrite the refresh button action?

I would like to use some kind of preventDefault function to overwrite what hitting the refresh button on the browser does (or also pressing CTRL/CMD+R).
Is there something that allows me to prevent refreshing the page?
I tried this but it doesn't seem to do anything in Firefox.
window.onunload = function(){
alert("unload event detected!");
}
You can use onbeforeunload to prompt whether they'd like to leave:
window.onbeforeunload = function() {
return "Are you really sure?\nI don't know why anyone would want to leave my beautiful website!";
};
However, you can't override it any more than that.

Disable Browser onUnload on certain links?

I am working on a Web Hosting panel which has a DNS records manager. I have to use a lot of JavaScript to make it perform almost like a desktop application.
I really wanted to show a Custom Dialog window when a a browser runs beforeunload however after some research I have discovered I am stuck using the browsers default Dialog window.
So this JavaScript code below does just that, my problem is I need to make sure it does NOT get fired off on certain link clicks.
I am hoping to be able to maintain an Array of CSS class names, and if the link clicked is in this array then it will NOT show the onunload event.
I'm sure this is easy for a JavaScript developer. Could someone show me how to do this?
//sample Class array
safeLinks = ['test', 'test2', 'test3', 'test4', 'test5'];
// onunload event
$(window).on('beforeunload', function(){
return 'Are you sure you want to leave?';
});
You could remove the event handler when they're clicked:
var safeLinks = ['.test', '.test2', '.test3', '.test4', '.test5'];
function promptBeforeClose() {
return 'Are you sure you want to leave?';
}
$(window).on('beforeunload', promptBeforeClose);
$(document).on('click', safeLinks.join(', '), function(e) {
$(window).off('beforeunload', promptBeforeClose);
});
Also, if these safe links have a common ancestor, use that instead of document as the delegation parent or people will complain. ;)
use a flag variable.When ever click on the onload then make it as true
$(window).on('beforeunload', function(){
if(flag != false)
return 'Are you sure you want to leave?';
});

Suppress Safari’s “You have entered text…” warning?

Safari helpfully (?) prompts before closing a tab or window when text has been entered into an input.
There are some cases where, as a web developer, this isn’t desirable — for example, when the input is a live search where the user has probably already gotten the results he’s looking for when the window is closed, even though there’s still text in the field.
How can I let Safari know that text in a particular input doesn’t need its protection?
It seems like you are able to disable this warning for an entire page by having an onbeforeunload handler on <body> (even an empty one will do). For example, the following will not produce the warning:
<body onbeforeunload="">
<form method="get"><input></form>
</body>
I'm not sure if this is the intended behaviour, or a bug.
I think I've got a solution to this problem, though it's unquestionably a hack (i.e. if Safari changes how this feature is implemented, it could stop working). Shown here with a touch of jQuery:
$('.unimportant').live('blur', function(){
var olddisplay = this.style.display;
this.style.display = 'none';
this.clientLeft; // layout
this.style.display = olddisplay;
});
Demo (try typing in the "unimportant" field, click somewhere else on the page, then close the window).
In short:
Hide the input
Trigger layout
Show the input
You can also change the value of the input, trigger layout, and change it back.
The one limitation here is that cleaning the input has to be done explicitly. In this case, it will be dirty until blur. This works well in my situation, and probably in many others, since the input will be protected from an accidental window close until something else on the page is manipulated (e.g. a link is clicked). You could choose to run this on keyup if you're willing to live with a flicker of the insertion point every time a key is pressed.
I'm open to cleaner solutions.
I found what I think is a pretty good solution to this problem. When I use AJAX to submit the form then I want the warning to suppress. This is accomplished with onbeforeunload.
window.onbeforeunload=function(e){}
But after I submit I might make additional changes and so I want the warning to show again. To do this I added a keyup handler to a form element.
$('txtarea').onkeyup=dirty;
What dirty does is checks is the input field has changed if it has then I set onbeforeunload to null.
function dirty(e){
if (e.srcElement.value != e.srcElement.defaultValue){
window.onbeforeunload=null;
}
}
I just found another solution to prevent Safari from displaying the "Are you sure you want to reload this page?" dialog when textareas have changed their content.
It turns out that setting the value through Javascript clears Safari's changed state:
$(document).on('blur', 'textarea', function() {
var value = $(this).val();
$(this).val('').val(value);
});
Clearing the value first is important, directly setting it to the content it already is does not work.
EDIT Apparently setting window.onbeforeunload to an empty function still works, however $(window).on('beforeunload', function() {}) does not.

How to detect if the user clicked the "back" button

When the user goes history-back-1...how do I detect that? And then, alert "the user clicked back!"
Using binds (and jQuery preferably)
You generally can't (browser security restriction). You can tell if the user navigates away from the page (onbeforeunload, onunload fire) but you can't tell where they went unless you've set up your page to allow it.
HTML5 introduces the HTML5 History API; in conforming browsers, the onpopstate event will fire if the user navigates back to an earlier "page" on your site.
try:
window.onbeforeunload = function (evt) {
var message = 'Are you sure you want to leave?';
if (typeof evt == 'undefined') {
evt = window.event;
}
if (evt) {
evt.returnValue = message;
}
return message;
}
window.onpopstate=function()
{
alert("Back/Forward clicked!");
}
Following are the steps to detect back button click:
Register a mouse down event on body $('body').on('mousedown', 'on all li');
Now set a variable when mousedown event occur.
Check this variable when your location changes.
IF variable changes to true it means list clicked otherwise back button.
This work in my use case. This solution may help others because it depends on app design.
On the page you are looking at, you can add this piece of code to the onLoad event to move them back the page they were on.
if(history.length>0)history.go(+1)
If you want the alert then make it
if(history.length>0)alert("the user clicked back!")

Categories