SCENARIO: I just want to warn user on window change; so I've used jQuery's window blur & JavaScript's confirm dialogue box. When user will click OK button the application will redirect to another page & when user will click CANCEL button nothing will happen. He can continue his work on the same page.
ISSUE: OK button is working perfectly but when I click on the CANCEL button, the browser keeps on regenerating the dialogue box. How do I stop that?
CODE:
$(window).blur( function (e) {
var closeWindow = window.confirm("Your test will be cancelled if you switch the tabs.");
if (closeWindow) {
// redirect to another page
}
else {
// do nothing.
}
});
As #ROAL explained, the first blur event is because of actual blur, and rest are because of the browser trying to move away from the tab. A simple solution for this would be to use a flag to distinguish between the user generated event and the browser generated event. Give this a try:
var manualCancellation = false;
$(window).blur( function (e) {
if(!manualCancellation ){
var closeWindow = window.confirm("Your test will be cancelled if you switch the tabs.");
console.log(e);
if (closeWindow) {
// redirect to another page
}
else {
manualCancellation = true;
// do nothing.
}
} else {
// Reset the value of manualCancellation so that the event is fired the next time.
manualCancellation = false;
}
});
Related
I've written a small jQuery plugin which is designed to ask the question, "Are you sure?" when clicking on a link or submitting a form.
It's used like this:
Link
Or like this:
<form action="link.php" method="post">
<button class="confirm">Submit</button>
</form>
What I am doing is using preventDefault() to prevent the default behavior when the anchor or button is clicked. I then display a confirm dialogue where the user has to click either OK or Cancel.
If the user clicks Cancel then nothing happens (as expected).
However, if the user clicks OK I am firing the click event again, and using a flag that was set first time around to not prevent the default behaviour second time around (I'm instead returning true). Except that it's not working. Clicking either OK or Cancel in the confirm dialogue doesn't do anything.
The plugin is below:
(function($) {
$.fn.fw_confirm = function(options) {
// Flag to check for the first click event
var paused = false;
return this.on("click", function(e) {
// The anchor or the button that was clicked
var button = $(this);
// If this is the second click event, the user must have confirmed so return true
if (paused == true) {
// Reset the flag
paused = false;
// This isn't working, or at least it's not submitting the form or proceeding to the URL of the hyperlink when I would expect it to
return true;
}
// First time around prevent the default behavior
e.preventDefault();
e.stopImmediatePropagation();
// Set the flag to true, ready for the second click event
paused = true;
if (confirm("Are you sure?")) {
// The user is certain, so trigger the click event again
return button.trigger("click");
} else {
// The user cancelled, reset the flag
paused = false;
return;
}
});
}
})(jQuery);
I'm using the following function to prevent double submissions:
$("#form").submit(function () {
var form = $(this);
form.find("input[type=submit]").attr("disabled", "disabled")
form.find("input[type=submit]").attr("value", "Processing");
});
It works fine, but then I have the following code which triggers an alert to avoid accidentally leaving the page:
function goodbye(e) {
if(!e) e = window.event;
//e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = '¿DO YOU REALLY WANT TO LEAVE THIS PAGE?'; //This is displayed on the dialog
//e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
}
window.onbeforeunload=goodbye;
The problem is if the user clicks submit and the realizes he didnt want to leave the page and clicks on stay on this page instead, the submit button is still disabled.
How could I re-enable it upon clicking stay on this page?
Thanks!
The button problem
You want to disable and enable the submit button so you know you going to touch the same kind of function and object twice, it is better to make advantage out of this in a function
function disableSubmit(form, enabled){
var submit = form.find("input[type=submit]"),
dataVar = enabled !== true ? "processing-message" : "send-message",
message = submit.data(dataVar);
submit.prop('disabled', (enabled !== true) );
submit.val(message);
}
I could make it even more generic for using it on each form. But the message in the button will display whatever you put in the data-attribute.
Cancel Submit
There is a problem with cancellation of an onbeforeunload event; there is no callback for it. The solution I came with is using a timeout. Since you don't know if the person canceled or not, I think 2 seconds is enough for the page to submit.
You have to have 2 seconds patient to get the submit button enabled again. But you can adjust it all you want of course
if (e.stopPropagation) {
setTimeout(function () {
disableSubmit(formObject, true);
}, 2000);
e.stopPropagation();
e.preventDefault();
}
The JSFiddle example
I know how to display an alert to the user if they attempt to navigate away from the current page asking them if they are sure they wish to do so but I was wondering if there is a way to display this alert ONLY when the window / tab is being closed?
I'd like to only have the confirmation display when the window or tab is being closed, not when the user clicks a link.
Not possible.
the only thing close is the onbeforeunload event, but there isn't a difference (to javascript) between a closed window/tab or a navigation to another page.
Follow-up:
I suppose you could attach a click handler to every anchor on the page and use a "dirty" flag, but that's really hack-ish. something like (forgive me, but using jquery for simplicity):
(function(){
var closingWindow = true;
$('a').on('click', function(){
if (this.href == /* on-domain link */){
closingWindow = false;
}
});
$(window).on('beforeunload',function(){
if (closingWindow){
// your alert
}
});
})();
but that's about as close as you're going to get. note: this isn't going to help if another javascript function uses window.location, etc.
You cannot differentiate between the two.
window.onbeforeunload is triggered immediately before the browser unloads its resources. You do not know the reason for the unload, only that it's about to occur:
From the MDN:
An event that fires when a window is about to unload its resources.
The document is still visible and the event is still cancelable.
How about doing something like this?
Have a global variable set to false (i.e. var hasCLickedLink = false;)
On all your links (<a>), attach an event handler that sets the variable to true
On onbeforeunload, check the value of the variable to see if a link has been clicked or not. If it is still false, then they haven't clicked a link so give them the alert.
You need to explicitly specify events for which you don't want to show confirmation dialogue box.
var validNavigation = 0;
function bindDOMEvents() {
// Attach the event keypress to exclude the F5 refresh
$(document).keydown(function(e)
{
var key = e.which || e.keyCode;
if (key == 116)
{
validNavigation = 1;
};
});
// Attach the event click for all links in the page
$("a").bind("click", function()
{
validNavigation = 1;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function()
{
validNavigation = 1;
});
// Attach the event click for all inputs in the page
$("input[type=submit]").bind("click", function()
{
validNavigation = 1;
});
};
$(document).ready(function()
{
bindDOMEvents();
window.onbeforeunload = function () {
console.log(validNavigation);
if (validNavigation == '1')
{
console.log("No Alert.. Continue");
}
else
{
return false;
}
};
});
This solution worked for me in Firefox with Violentmonkey.
It is used like most of all window.onbeforeunload and check if left mouse button was pressed. So if pressed, this mean, click at free space or link opens - not closing tab.
function DetectBrowserExit()
{
if (butpres == 0) {
//your action before closing tab, alert not showing
}
}
window.onbeforeunload = function(){ DetectBrowserExit(); }
// the key is pressed, then when window.onbeforeunload - link is opening, so, tab not closing
document.addEventListener('mousedown',function(e){
if (e.which == 1) { //1-lbutton 2-mb 3-rb
//e.preventDefault();
butpres = 1
setTimeout(function() {
butpres = 0 //if after 3 seconds the script still works then the link has not been clicked, clear the click and continue to catch new clicks
//alert(butpres);
}, 3000); //Two seconds will elapse and Code will execute.
//alert(butpres);
//command_lock();
}
},false);
I got the snippet below from this SO post, and it works when a user tries to reload the page or close the browser etc. but if the user clicks on a link then it lets them naivagate away, and then incorrectly starts displaying the message on the wrong page. I am using pjax for the links.
$(document).ready(function () {
$('textarea').change(function () {
window.onbeforeunload = function () { return "Your changes to the survey have not been saved?" };
});
});
You should use onbeforeunload like this, inconditionally:
<script type="text/javascript">
saved=true; // initially, it is saved (no action has been done)
window.onbeforeunload = confirmExit;
function confirmExit() {
if (!saved) {
return "You did not save, do you want to do it now?";
}
}
</script>
It is not safe to handle this event only when another event is fired. The onchange event of your textarea here probably don't fire before you click on a link so the window won't handle the onbeforeunload at all. The link will work as expected: you will get redirected.
To deal with the saved flag, you could listen to what happens in your textarea, for example, when the user is actually typing something:
$('textarea').keyup(function(){
saved=false;
});
Then, if you save the data in ajax, the save button could set it back to true:
$('#btnSave').click(function(){
// ajax save
saved=true;
});
Otherwise, it will load the next page with the saved flag on.
what about something like the following?
Listening on all <a> links and then, depending on whether the variable needToSave is set to true, showing the message or letting it go.
var needToSave = false; // Set this to true on some change
// listen on all <a ...> clicks
$(document).click("a", function(event){
if (needToSave == true) {
alert("You need to save first");
event.preventDefault();
return;
}
});
UPDATE (as per Roasted's suggestion) this should trigger the unload event every time the link is clicked and perform your existing logic:
// listen on all <a ...> clicks
$(document).click("a", function(event){
$(window).trigger("unload");
});
jsFiddle here - http://jsfiddle.net/k2fYM/
I have a confirm box on my colorbox("are you sure you want to leave?").
This triggers when i close the popup. This works when i click on the "cboxClose" div on the popup.
I am trying to show this confirm box on a button click. But the popup just closes right away without showing the confirm box.
My question is how do i trigger the the confirm box when i click on a cancel button. i tried several ways
//This just closes the pop up without showing the confirm box
$('#btnCancel').click(function () {
parent.$.colorbox.close(); });
//doesn't work
$('#btnCancel').click(function () {
$('#cboxClose').click()
});
COLORBOX
onComplete: function () {
$("#cboxClose").click(function (e) {
// stop any other script from firing
e.stopPropagation();
if (confirm('are you sure you want to leave?')) {
$.colorbox.close();
// ensure that the binding is removed when closed
$("#cboxClose").unbind();
}
});
} // close oncomplete
The issue here is that colorbox registers a click handler on the cboxClose element. As a result, neither stopping bubbling nor preventing the click (by returning false in a click handler) will have any effect because the colorbox handler is already registered. The only way of stopping that handler from being run is to unbind it. However, to do that you need a reference to the handler, which you won't get without modifying the colorbox code.
In any case, that's what's going on and why the code you have above doesn't work. Another option for you would be to override the colorbox close function (which is the public colorbox method that is called by colorbox's close button handler). All you need is this:
$.colorbox._close = $.colorbox.close;
$.colorbox.close = function() {
if(confirm("Close?")) {
$.colorbox._close();
}
}
The down side (which may not be an issue in your situation) is that this will affect all colorboxes on the page.
I solved this issue by making this method and binding it to the cancel button
var originalClose = $.colorbox.close;
$.colorbox.close = function (e) {
var response;
var formChanged = localStorage.getItem("isFormChanged");
var saveClicked = localStorage.getItem("saveClicked");
if (formChanged == "true" && saveClicked == "false") {
response = confirm('Do you want to close this window? All your changes will not be saved');
if (!response) {
return
}
}
originalClose();
};
<input type="button" value="Cancel" id="btncancel" onclick="parent.$.colorbox.close()"/>