Detect Close window event in Firefox

2019-04-12 11:19发布

I know it is a very asked question, but believe me I don't find the answer through the Web.

My purpose is to trigger the message box only if the user clicks on the close (X) button. The user continues to get the message box if he clicks on the back/forward button and also if he uses F5, CTRL+R, ...

I do not want to associate any other action than the window close button click as behind, there will be a session kill with Ajax. So it is not acceptable to kill the session if the user types F5 button.

Here is my code. For info, I know that there is a way in IE to check the event object clientY, but this does not work in Firefox.

$("a").click(function () {
window.onbeforeunload = null;
});

window.onbeforeunload = function (e) {
var closewindowmessage="If you leave this page, your session will be definitely closed.";

  e = e || window.event;
  // For IE and Firefox
  if (e) {
    e.returnValue = closewindowmessage;
  }

  // For Safari
  return closewindowmessage;
};

1条回答
虎瘦雄心在
2楼-- · 2019-04-12 11:56

There's no definitive way of detecting why/how a page is being unloaded. You could rebuild your site to use the now ever so popular "anchor navigation" method which stores data in the HTML anchor, such as http://www.example.com/page#something=something. This would at least typically solve the problem for the back/forward buttons but not when the user is reloading the page.

Other than that, you could employ various ad hoc ways of tracking the mouse and keyboard action before the user tries to unload the page. You could for example track when the user drags the mouse diagonally up to the right – that probably means he's just about to close the the window/tab, so keep the message. Diagonally up to the left – that probably means he's just about to click the back forward buttons or maybe enter something to the address field. If you're really serious, conduct a study of how people move the cursor and correlate that with whether they're about to close the page or do something "allowed". Then again, on a Mac the close button is in the upper left corner of the window. And so on and so forth. It'll still just be best guesses.

You could also track upward mouse movements and show a big red message in the browser viewport (not a popup/alert) to warn the user before he even considers leaving the page.

Tracking keyboard events is a little bit more deterministic, but still requires some cross browser and platform research. I leave you with this code, which I'm hoping may work as a boilerplate. It logs the key presses and suppresses the message if F5 or Apple+R (Mac) was pressed. Otherwise it will show a message containing a list of all logged key presses.

The analysis needs testing and extension; it's only been tested on Firefox Mac. One bug that I can immediately point out is that if you press Apple+R,R you'll still get prompted because the second page instance never recorded any keydown event for the Apple key – only for the R key. It will also fail if the user presses something inbetween, like Apple+L,R. You might be fine with just checking if the last key pressed was R.

<script>
// Create an empty array.
window.keys = [];

// Log every key press
window.onkeydown = function (e) {
  var evt = window.event || e;

  var keyCode = e.keyCode || e.which;

  window.keys.push(keyCode)

}

function analyzeKeyPresses(){
  keys.reverse();   // Reverse the array so it's easier to handle.
  var doBlock = true;

  // Here we only apply certain checks if there are enough keys in the array. Don't want a JS error...
  switch(window.keys.length){
    case 0:
      doBlock = true;  // Redundant. If there are no key presses logged, assume we should prompt the user.
      break;
    default: // Two or more key presses logged.
      if(keys[0] == 82 && keys[1] == 224) doBlock = false;  // User pressed apple+r on a Mac - don't prompt!
      if(keys[0] == 82 && keys[1] == 17)  doBlock = false;  // User pressed ctrl+r on Windovs (untested) - don't prompt!

      // Note: No break! Intentional fall-through! We still want to check for F5!
    case 1:  // One or more key presses logged.
      if(keys[0] == 116) doBlock = false;   // User pressed F5 - don't prompt!
  }

  keys.reverse();   // Un-reverse the array in case we need to use it again. (Easier to read...)
  return doBlock;
}

window.onbeforeunload = function (e) {
  var closewindowmessage=window.keys.join(" ");

  var blockUnload = analyzeKeyPresses();

  if(blockUnload){
    e = e || window.event;
    // For IE and Firefox
    if (e) {
      e.returnValue = closewindowmessage;
    }

    // For Safari
    return closewindowmessage;
  }
};

</script>
<a href="#1">1</a> <a href="#2">2</a> 
查看更多
登录 后发表回答