91

How can I display "Are you sure you want to leave the page?" when the user actually tries to close the page (click the X button on the browser window or tab) not when he tries to navigate away from the page (click on another link).

My client wants a message to appear when the user tries to close the page "Are you sure you want to leave the page? You still have items in your shopping cart."

Unfortunately $(window).bind('beforeunload') doesn't fire only when the user closes the page.

jQuery:

function checkCart() { 
  $.ajax({
    url : 'index.php?route=module/cart/check',
    type : 'POST',
    dataType : 'json',
    success : function (result) {
       if (result) {
        $(window).bind('beforeunload', function(){
          return 'leave?';
        });
       }
    }
  })
}
Cris
  • 4,004
  • 16
  • 50
  • 74
  • http://stackoverflow.com/a/18395961/2261259 – Voonic Sep 13 '13 at 10:08
  • 1
    You can't. You cannot programatically tell the difference between the browser closing or the user navigating away from your page. – user229044 Sep 16 '13 at 05:05
  • @Cris Whats error occurred?? – Padmanathan J Sep 16 '13 at 05:23
  • Your message include some code that indicate an Ajax operation running. Is there some of them we need to take into consideration ? (because except that code, you didn't explicitily mentionned it) – Cyril N. Sep 16 '13 at 06:35
  • you can't tell if a window is closed or navigate to another URL, consider when you are using a multi-tab browser, there makes no difference, but if you are using hash navigation (e.g. http://yourdomain.com/#path=/index/news&id=1), you can manage it throw javascript when navagiting – alphakevin Sep 18 '13 at 09:08
  • Your code snippet would cause multiple binds, adding up with each ajax call; try unbinding previous event before binding a new event. – Vishal Sep 20 '13 at 14:59

7 Answers7

154

You can do this by using JQuery.

For example ,

<a href="your URL" id="navigate"> click here </a>

Your JQuery will be,

$(document).ready(function(){

    $('a').on('mousedown', stopNavigate);

    $('a').on('mouseleave', function () {
           $(window).on('beforeunload', function(){
                  return 'Are you sure you want to leave?';
           });
    });
});

function stopNavigate(){    
    $(window).off('beforeunload');
}

And to get the Leave message alert will be,

$(window).on('beforeunload', function(){
      return 'Are you sure you want to leave?';
});

$(window).on('unload', function(){

         logout();

});

This solution works in all browsers and I have tested it.

Human Being
  • 8,269
  • 28
  • 93
  • 136
  • 2
    This is a good one (you probably should observe `onsubmit` too), but it won't work for browser's Back and Forward buttons. I anticipate there is no ideal solution to this. – noseratio Sep 18 '13 at 03:01
  • code is fine. I want to run logout() function if user clicks on "Leave this Page" pop button. But how can I detect whether user have clicked on "Leave this Page" or not? – Bit_hunter Aug 01 '15 at 13:22
  • @Bit_hunter use a `confirm()` dialog – RozzA Oct 04 '15 at 20:27
  • 1
    This `$(window).on('unload', function()` is not getting executed in Safari. – Aarohi Kulkarni Nov 20 '15 at 06:42
  • 1
    Will `beforeunload` fire if the browser is closing due to OS shutdown? – techie_28 Apr 08 '16 at 06:29
  • Did you tested it on ever sin ? – Ahtisham Oct 10 '18 at 13:51
  • 5
    You can't provide custom messages anymore in Chrome or Firefox (because they want to prevent scam): https://developers.google.com/web/updates/2016/04/chrome-51-deprecations#remove_custom_messages_in_onbeforeunload_dialogs – Adam Jun 07 '19 at 11:21
17

Try javascript into your Ajax

window.onbeforeunload = function(){
  return 'Are you sure you want to leave?';
};

Reference link

Example 2:

document.getElementsByClassName('eStore_buy_now_button')[0].onclick = function(){
    window.btn_clicked = true;
};
window.onbeforeunload = function(){
    if(!window.btn_clicked){
        return 'You must click "Buy Now" to make payment and finish your order. If you leave now your order will be canceled.';
    }
};

Here it will alert the user every time he leaves the page, until he clicks on the button.

DEMO: http://jsfiddle.net/DerekL/GSWbB/show/

Padmanathan J
  • 4,614
  • 5
  • 37
  • 75
14

Credit should go here: how to detect if a link was clicked when window.onbeforeunload is triggered?

Basically, the solution adds a listener to detect if a link or window caused the unload event to fire.

var link_was_clicked = false;
document.addEventListener("click", function(e) {
   if (e.target.nodeName.toLowerCase() === 'a') {
      link_was_clicked = true;
   }
}, true);

window.onbeforeunload = function(e) {
    if(link_was_clicked) {
        return;
    }
    return confirm('Are you sure?');
}
Community
  • 1
  • 1
Andy Merhaut
  • 305
  • 1
  • 6
3

As indicated here https://stackoverflow.com/a/1632004/330867, you can implement it by "filtering" what is originating the exit of this page.

As mentionned in the comments, here's a new version of the code in the other question, which also include the ajax request you make in your question :

var canExit = true;

// For every function that will call an ajax query, you need to set the var "canExit" to false, then set it to false once the ajax is finished.

function checkCart() {
  canExit = false;
  $.ajax({
    url : 'index.php?route=module/cart/check',
    type : 'POST',
    dataType : 'json',
    success : function (result) {
       if (result) {
        canExit = true;
       }
    }
  })
}

$(document).on('click', 'a', function() {canExit = true;}); // can exit if it's a link
$(window).on('beforeunload', function() {
    if (canExit) return null; // null will allow exit without a question
    // Else, just return the message you want to display
    return "Do you really want to close?";
});

Important: You shouldn't have a global variable defined (here canExit), this is here for simpler version.

Note that you can't override completely the confirm message (at least in chrome). The message you return will only be prepended to the one given by Chrome. Here's the reason : How can I override the OnBeforeUnload dialog and replace it with my own?

Community
  • 1
  • 1
Cyril N.
  • 38,875
  • 36
  • 142
  • 243
  • 3
    As of jQuery `1.7` `.live` is deprecated. Instead of it the `$(document).on('click', 'a', ...)` should be used. `.on` is generally the preferred way over the _old_ functions so for `.bind` it would be `$('form').on('submit', ...)`. – t.niese Sep 13 '13 at 10:12
  • I'm quite sure this answer is no more cross browser. Someone tested it? – A. Wolff Sep 13 '13 at 10:17
  • As stated, I only copy/pasted the code. I'll edit the answer with a newest version – Cyril N. Sep 13 '13 at 11:43
  • Thank you, but unfortunately the confirm doesn't show up when I close the tab. – Cris Sep 16 '13 at 04:52
  • .. and a big error I made (click instead of beforeunload as the document event). – Cyril N. Sep 16 '13 at 09:00
0

Try this, loading data via ajax and displaying through return statement.

<script type="text/javascript">
function closeWindow(){

    var Data = $.ajax({
        type : "POST",
        url : "file.txt",  //loading a simple text file for sample.
        cache : false,
        global : false,
        async : false,
        success : function(data) {
            return data;
        }

    }).responseText;


    return "Are you sure you want to leave the page? You still have "+Data+" items in your shopping cart";
}

window.onbeforeunload = closeWindow;
</script>
raduns
  • 765
  • 7
  • 18
  • 2
    It's not a good idea to make your user wait for the response of a synchronous AJAX call every time they click a link in your site. – mattalxndr Nov 03 '15 at 03:57
0

here is function you can use in your code anywhere

function setProcessing(isProcessing) {
  $(window).on('beforeunload', function(event) {
    if (isProcessing) {
      event.preventDefault();
      return '';
    }
  });
}

just set setProcessing(true) or setProcessing(false)

-2

You can try 'onbeforeunload' event.

Also take a look at this-

Dialog box runs for 1 sec and disappears?

Community
  • 1
  • 1
halkujabra
  • 2,844
  • 3
  • 25
  • 35