Browser Window close detection - javascript

This is something that's been driving me nuts.
I'm trying to detect whether the uses closes or navigates away from a page in order to do an ajax response upon the event. I have tried almost every possible method to invoke this but no luck. The only thing I can think of is that the activate window in question was fired using: window.open() method. Could that cause any issues? What I have so far:
window.onbeforeunload = function() {
//ajax stuff here
};
However, I've noticed that this does not work after the page is fully loaded. The event fires within the first few milliseconds (if I open the window and try to close it right away) during the page load and won't work after that.
Any ideas?

I once ran into this issue, and found it worked for me only by setting async : false on the ajax, like this:
jQuery(window).bind('beforeunload', function () {
jQuery.ajax({
url: 'your.url',
async: false,
data: yourdata
timeout: 2000 // or whatever timeout in milliseconds you want
success: function(data){
// Do whatever you want
}
});
});
As Ian mentioned on the comments, it's a good idea to set a timeout to prevent the window for taking too long to close in case the request takes a while. And keep in mind it won't work in all browsers...

This also supports old versions of IE and Firefox.
window.onbeforeunload = function (e) {
var message = "Your confirmation message goes here.",
e = e || window.event;
// For IE and Firefox
if (e) {
e.returnValue = message;
}
// For Safari
return message;
};

Related

Chrome window.open after ajax request acts like popup

I have a situation where, when a user pushes a button I perform an ajax request, and then use the result of the ajax request to generate a URL which I want to open in a new tab. However, in chrome when I call window.open in the success handler for the ajax request, it opens in a new window like a popup (and is blocked by popup-blockers). My guess is that since the the success code is asynchronous from the click handling code that chrome thinks it wasn't triggered by a click, even though it is causally related to a click. Is there any way to prevent this without making the ajax request synchronous?
EDIT
Here is some minimal code that demonstrates this behaviour:
$('#myButton').click(function() {
$.ajax({
type: 'POST',
url: '/echo/json/',
data: {'json': JSON.stringify({
url:'http://google.com'})},
success: function(data) {
window.open(data.url,'_blank');
}
});
});
http://jsfiddle.net/ESMUA/2/
One note of clarification: I am more conerned about it opening in a separate window rather than a tab, than I am about it being blocked by a popup blocker.
Try to add
window.open(url,'_blank');
Edit
Well, I don't think you can get around popup-blockers when opening a page that's not the immediate result of a user action (i.e. not async).
You could try something like this though, it should look like a user action to a popup-blocker:
var $a = $('<a>', {
href: url,
target: '_blank'
});
$(document.body).append($a);
$a.click();
Edit 2
Looks like you're better of keeping things sync.
As long as the new window is "same origin" you have some power to manipulate it with JS.
$('#a').on('click', function(e){
e.preventDefault();
var wi = window.open('about:blank', '_blank');
setTimeout(function(){ // async
wi.location.href = 'http://google.com';
}, 500);
});
Try adding async: false. It should be working
$('#myButton').click(function() {
$.ajax({
type: 'POST',
async: false,
url: '/echo/json/',
data: {'json': JSON.stringify({
url:'http://google.com'})},
success: function(data) {
window.open(data.url,'_blank');
}
});
});
What worked for me was:
var win = window.open('about:blank', '_blank');
myrepository.postmethod('myserviceurl', myArgs)
.then(function(result) {
win.location.href = 'http://yourtargetlocation.com/dir/page';
});
You open the new window tab before the sync call while you're still in scope, grab the window handle, and then re-navigate once you receive the ajax results in the promise.
The answer posted by #pstenstrm above (Edit 2) mostly works, but I added just one line to it to make the solution more elegant. The ajax call in my case was taking more than a second and the user facing a blank page posed a problem. The good thing is that there is a way to put HTML content in the new window that we've just created.
e.g:
$('#a').on('click', function(e){
e.preventDefault();
var wi = window.open('about:blank', '_blank');
$(wi.document.body).html("<p>Please wait while you are being redirected...</p>");
setTimeout(function(){ // async
wi.location.href = 'http://google.com';
}, 500);
});
This fills the new tab with the text "Please wait while you are being redirected..." which seems more elegant than the user looking at a blank page for a second. I wanted to post this as the comment but don't have enough reputation.
There is no reliable way. If your tab/window has been blocked by a pop-blocker in FF and IE6 SP2 then window.open will return the value null.
https://developer.mozilla.org/en-US/docs/Web/API/Window/open#FAQ
How can I tell when my window was blocked by a popup blocker? With the
built-in popup blockers of Mozilla/Firefox and Internet Explorer 6
SP2, you have to check the return value of window.open(): it will be
null if the window wasn't allowed to open. However, for most other
popup blockers, there is no reliable way.

Detect Close windows event by jQuery

Could you please give me the best way to detect only window close event for all browsers by jQuery?
I mean clicking X button on the browser or window.close(), not meaning F5, form submission,
window.location or link.
I was looking for many threads but have not found the right way yet.
You can use :
$(window).unload(function() {
//do something
});
Unload() is deprecated in jQuery version 1.8, so if you use jQuery > 1.8 you can use even beforeunload instead.
The beforeunload event fires whenever the user leaves your page for any reason.
$(window).on("beforeunload", function() {
return confirm("Do you really want to close?");
});
Source Browser window close event
There is no specific event for capturing browser close event.
You can only capture on unload of the current page.
By this method, it will be effected while refreshing / navigating the current page.
Even calculating of X Y postion of the mouse event doesn't give you good result.
The unload() method was deprecated in jQuery version 1.8.
so if you are using versions older than 1.8
then use -
$(window).unload(function(){
alert("Goodbye!");
});
and if you are using 1.8 and higher
then use -
window.onbeforeunload = function() {
return "Bye now!";
};
hope this will work :-)
There is no specific event for capturing browser close event. But we can detect by the browser positions XY.
<script type="text/javascript">
$(document).ready(function() {
$(document).mousemove(function(e) {
if(e.pageY <= 5)
{
//this condition would occur when the user brings their cursor on address bar
//do something here
}
});
});
</script>
Combine the mousemove and window.onbeforeunload event :-
I used for set TimeOut for Audit Table.
$(document).ready(function () {
var checkCloseX = 0;
$(document).mousemove(function (e) {
if (e.pageY <= 5) {
checkCloseX = 1;
}
else { checkCloseX = 0; }
});
window.onbeforeunload = function (event) {
if (event) {
if (checkCloseX == 1) {
//alert('1111');
$.ajax({
type: "GET",
url: "Account/SetAuditHeaderTimeOut",
dataType: "json",
success: function (result) {
if (result != null) {
}
}
});
}
}
};
});
You can solve this problem with vanilla-Js:
Unload Basics
If you want to prompt or warn your user that they're going to close your page, you need to add code that sets .returnValue on a beforeunload event:
window.addEventListener('beforeunload', (event) => {
event.returnValue = `Are you sure you want to leave?`;
});
There's two things to remember.
Most modern browsers (Chrome 51+, Safari 9.1+ etc) will ignore what you say and just present a generic message. This prevents webpage authors from writing egregious messages, e.g., "Closing this tab will make your computer EXPLODE! đź’Ł".
Showing a prompt isn't guaranteed. Just like playing audio on the web, browsers can ignore your request if a user hasn't interacted with your page. As a user, imagine opening and closing a tab that you never switch to—the background tab should not be able to prompt you that it's closing.
Optionally Show
You can add a simple condition to control whether to prompt your user by checking something within the event handler. This is fairly basic good practice, and could work well if you're just trying to warn a user that they've not finished filling out a single static form. For example:
let formChanged = false;
myForm.addEventListener('change', () => formChanged = true);
window.addEventListener('beforeunload', (event) => {
if (formChanged) {
event.returnValue = 'You have unfinished changes!';
}
});
But if your webpage or webapp is reasonably complex, these kinds of checks can get unwieldy. Sure, you can add more and more checks, but a good abstraction layer can help you and have other benefits—which I'll get to later. 👷‍♀️
Promises
So, let's build an abstraction layer around the Promise object, which represents the future result of work- like a response from a network fetch().
The traditional way folks are taught promises is to think of them as a single operation, perhaps requiring several steps- fetch from the server, update the DOM, save to a database. However, by sharing the Promise, other code can leverage it to watch when it's finished.
Pending Work
Here's an example of keeping track of pending work. By calling addToPendingWork with a Promise—for example, one returned from fetch()—we'll control whether to warn the user that they're going to unload your page.
const pendingOps = new Set();
window.addEventListener('beforeunload', (event) => {
if (pendingOps.size) {
event.returnValue = 'There is pending work. Sure you want to leave?';
}
});
function addToPendingWork(promise) {
pendingOps.add(promise);
const cleanup = () => pendingOps.delete(promise);
promise.then(cleanup).catch(cleanup);
}
Now, all you need to do is call addToPendingWork(p) on a promise, maybe one returned from fetch(). This works well for network operations and such- they naturally return a Promise because you're blocked on something outside the webpage's control.
more detail can view in this url:
https://dev.to/chromiumdev/sure-you-want-to-leavebrowser-beforeunload-event-4eg5
Hope that can solve your problem.

Popstate on page's load in Chrome

I am using History API for my web app and have one issue.
I do Ajax calls to update some results on the page and use history.pushState() in order to update the browser's location bar without page reload. Then, of course, I use window.popstate in order to restore previous state when back-button is clicked.
The problem is well-known — Chrome and Firefox treat that popstate event differently. While Firefox doesn't fire it up on the first load, Chrome does. I would like to have Firefox-style and not fire the event up on load since it just updates the results with exactly the same ones on load. Is there a workaround except using History.js? The reason I don't feel like using it is — it needs way too many JS libraries by itself and, since I need it to be implemented in a CMS with already too much JS, I would like to minimize JS I am putting in it.
So, would like to know whether there is a way to make Chrome not fire up popstate on load or, maybe, somebody tried to use History.js as all libraries mashed up together into one file.
In Google Chrome in version 19 the solution from #spliter stopped working. As #johnnymire pointed out, history.state in Chrome 19 exists, but it's null.
My workaround is to add window.history.state !== null into checking if state exists in window.history:
var popped = ('state' in window.history && window.history.state !== null), initialURL = location.href;
I tested it in all major browsers and in Chrome versions 19 and 18. It looks like it works.
In case you do not want to take special measures for each handler you add to onpopstate, my solution might be interesting for you. A big plus of this solution is also that onpopstate events can be handled before the page loading has been finished.
Just run this code once before you add any onpopstate handlers and everything should work as expected (aka like in Mozilla ^^).
(function() {
// There's nothing to do for older browsers ;)
if (!window.addEventListener)
return;
var blockPopstateEvent = document.readyState!="complete";
window.addEventListener("load", function() {
// The timeout ensures that popstate-events will be unblocked right
// after the load event occured, but not in the same event-loop cycle.
setTimeout(function(){ blockPopstateEvent = false; }, 0);
}, false);
window.addEventListener("popstate", function(evt) {
if (blockPopstateEvent && document.readyState=="complete") {
evt.preventDefault();
evt.stopImmediatePropagation();
}
}, false);
})();
How it works:
Chrome, Safari and probably other webkit browsers fire the onpopstate event when the document has been loaded. This is not intended, so we block popstate events until the the first event loop cicle after document has been loaded. This is done by the preventDefault and stopImmediatePropagation calls (unlike stopPropagation stopImmediatePropagation stops all event handler calls instantly).
However, since the document's readyState is already on "complete" when Chrome fires onpopstate erroneously, we allow opopstate events, which have been fired before document loading has been finished to allow onpopstate calls before the document has been loaded.
Update 2014-04-23: Fixed a bug where popstate events have been blocked if the script is executed after the page has been loaded.
Using setTimeout only isn't a correct solution because you have no idea how long it will take for the content to be loaded so it's possible the popstate event is emitted after the timeout.
Here is my solution:
https://gist.github.com/3551566
/*
* Necessary hack because WebKit fires a popstate event on document load
* https://code.google.com/p/chromium/issues/detail?id=63040
* https://bugs.webkit.org/process_bug.cgi
*/
window.addEventListener('load', function() {
setTimeout(function() {
window.addEventListener('popstate', function() {
...
});
}, 0);
});
The solution has been found in jquery.pjax.js lines 195-225:
// Used to detect initial (useless) popstate.
// If history.state exists, assume browser isn't going to fire initial popstate.
var popped = ('state' in window.history), initialURL = location.href
// popstate handler takes care of the back and forward buttons
//
// You probably shouldn't use pjax on pages with other pushState
// stuff yet.
$(window).bind('popstate', function(event){
// Ignore inital popstate that some browsers fire on page load
var initialPop = !popped && location.href == initialURL
popped = true
if ( initialPop ) return
var state = event.state
if ( state && state.pjax ) {
var container = state.pjax
if ( $(container+'').length )
$.pjax({
url: state.url || location.href,
fragment: state.fragment,
container: container,
push: false,
timeout: state.timeout
})
else
window.location = location.href
}
})
A more direct solution than reimplementing pjax is set a variable on pushState, and check for the variable on popState, so the initial popState doesn't inconsistently fire on load (not a jquery-specific solution, just using it for events):
$(window).bind('popstate', function (ev){
if (!window.history.ready && !ev.originalEvent.state)
return; // workaround for popstate on load
});
// ... later ...
function doNavigation(nextPageId) {
window.history.ready = true;
history.pushState(state, null, 'content.php?id='+ nextPageId);
// ajax in content instead of loading server-side
}
Webkit's initial onpopstate event has no state assigned, so you can use this to check for the unwanted behaviour:
window.onpopstate = function(e){
if(e.state)
//do something
};
A comprehensive solution, allowing for navigation back to the original page, would build on this idea:
<body onload="init()">
page 1
page 2
<div id="content"></div>
</body>
<script>
function init(){
openURL(window.location.href);
}
function doClick(e){
if(window.history.pushState)
openURL(e.getAttribute('href'), true);
else
window.open(e.getAttribute('href'), '_self');
}
function openURL(href, push){
document.getElementById('content').innerHTML = href + ': ' + (push ? 'user' : 'browser');
if(window.history.pushState){
if(push)
window.history.pushState({href: href}, 'your page title', href);
else
window.history.replaceState({href: href}, 'your page title', href);
}
}
window.onpopstate = function(e){
if(e.state)
openURL(e.state.href);
};
</script>
While this could still fire twice (with some nifty navigation), it can be handled simply with a check against the previous href.
This is my workaround.
window.setTimeout(function() {
window.addEventListener('popstate', function() {
// ...
});
}, 1000);
Here's my solution:
var _firstload = true;
$(function(){
window.onpopstate = function(event){
var state = event.state;
if(_firstload && !state){
_firstload = false;
}
else if(state){
_firstload = false;
// you should pass state.some_data to another function here
alert('state was changed! back/forward button was pressed!');
}
else{
_firstload = false;
// you should inform some function that the original state returned
alert('you returned back to the original state (the home state)');
}
}
})
The best way to get Chrome to not fire popstate on a page load is to up-vote https://code.google.com/p/chromium/issues/detail?id=63040. They've known Chrome isn't in compliance with the HTML5 spec for two full years now and still haven't fixed it!
In case of use event.state !== null returning back in history to first loaded page won't work in non mobile browsers.
I use sessionStorage to mark when ajax navigation really starts.
history.pushState(url, null, url);
sessionStorage.ajNavStarted = true;
window.addEventListener('popstate', function(e) {
if (sessionStorage.ajNavStarted) {
location.href = (e.state === null) ? location.href : e.state;
}
}, false);
The presented solutions have a problem on page reload. The following seems to work better, but I have only tested Firefox and Chrome. It uses the actuality, that there seems to be a difference between e.event.state and window.history.state.
window.addEvent('popstate', function(e) {
if(e.event.state) {
window.location.reload(); // Event code
}
});
I know you asked against it, but you should really just use History.js as it clears up a million browser incompatibilities. I went the manual fix route only to later find there were more and more problems that you'll only find out way down the road. It really isn't that hard nowadays:
<script src="//cdnjs.cloudflare.com/ajax/libs/history.js/1.8/native.history.min.js" type="text/javascript"></script>
And read the api at https://github.com/browserstate/history.js
This solved the problem for me. All I did was set a timeout function which delays the execution of the function long enough to miss the popstate event that is fired on pageload
if (history && history.pushState) {
setTimeout(function(){
$(window).bind("popstate", function() {
$.getScript(location.href);
});
},3000);
}
You can create an event and fire it after your onload handler.
var evt = document.createEvent("PopStateEvent");
evt.initPopStateEvent("popstate", false, false, { .. state object ..});
window.dispatchEvent(evt);
Note, this is slightly broke in Chrome/Safari, but I have submitted the patch in to WebKit and it should be available soon, but it is the "most correct" way.
This worked for me in Firefox and Chrome
window.onpopstate = function(event) { //back button click
console.log("onpopstate");
if (event.state) {
window.location.reload();
}
};

window.onbeforeunload ajax request in Chrome

I have a web page that handles remote control of a machine through Ajax. When user navigate away from the page, I'd like to automatically disconnect from the machine. So here is the code:
window.onbeforeunload = function () {
bas_disconnect_only();
}
The disconnection function simply send a HTTP GET request to a PHP server side script, which does the actual work of disconnecting:
function bas_disconnect_only () {
var xhr = bas_send_request("req=10", function () {
});
}
This works fine in FireFox. But with Chrome, the ajax request is not sent at all. There is a unacceptable workaround: adding alert to the callback function:
function bas_disconnect_only () {
var xhr = bas_send_request("req=10", function () {
alert("You're been automatically disconnected.");
});
}
After adding the alert call, the request would be sent successfully. But as you can see, it's not really a work around at all.
Could somebody tell me if this is achievable with Chrome? What I'm doing looks completely legit to me.
Thanks,
This is relevant for newer versions of Chrome.
Like #Garry English said, sending an async request during page onunload will not work, as the browser will kill the thread before sending the request. Sending a sync request should work though.
This was right until version 29 of Chrome, but on Chrome V 30 it suddenly stopped working as stated here.
It appears that the only way of doing this today is by using the onbeforeunload event as suggested here.
BUT NOTE: other browsers will not let you send Ajax requests in the onbeforeunload event at all. so what you will have to do is perform the action in both unload and beforeunload, and check whether it had already taken place.
Something like this:
var _wasPageCleanedUp = false;
function pageCleanup()
{
if (!_wasPageCleanedUp)
{
$.ajax({
type: 'GET',
async: false,
url: 'SomeUrl.com/PageCleanup?id=123',
success: function ()
{
_wasPageCleanedUp = true;
}
});
}
}
$(window).on('beforeunload', function ()
{
//this will work only for Chrome
pageCleanup();
});
$(window).on("unload", function ()
{
//this will work for other browsers
pageCleanup();
});
I was having the same problem, where Chrome was not sending the AJAX request to the server in the window.unload event.
I was only able to get it to work if the request was synchronous. I was able to do this with Jquery and setting the async property to false:
$(window).unload(function () {
$.ajax({
type: 'GET',
async: false,
url: 'SomeUrl.com?id=123'
});
});
The above code is working for me in IE9, Chrome 19.0.1084.52 m, and Firefox 12.
Checkout the Navigator.sendBeacon() method that has been built for this purpose.
The MDN page says:
The navigator.sendBeacon() method can be used to asynchronously
transfer small HTTP data from the User Agent to a web server.
This method addresses the needs of analytics and diagnostics code that
typically attempt to send data to a web server prior to the unloading
of the document. Sending the data any sooner may result in a missed
opportunity to gather data. However, ensuring that the data has been
sent during the unloading of a document is something that has
traditionally been difficult for developers.
This is a relatively newer API and doesn't seems to be supported by IE yet.
Synchronous XMLHttpRequest has been deprecated (Synchronous and asynchronous requests). Therefore, jQuery.ajax()'s async: false option has also been deprecated.
It seems impossible (or very difficult) to use synchronous requests during beforeunload or unload
(Ajax Synchronous Request Failing in Chrome). So it is recommended to use sendBeacon and I definitely agree!
Simply:
window.addEventListener('beforeunload', function (event) { // or 'unload'
navigator.sendBeacon(URL, JSON.stringify({...}));
// more safely (optional...?)
var until = new Date().getTime() + 1000;
while (new Date().getTime() < until);
});
Try creating a variable (Boolean preferably) and making it change once you get a response from the Ajax call. And put the bas_disconnect_only() function inside a while loop.
I also had a problem like this once. I think this happens because Chrome doesn't wait for the Ajax call. I don't know how I fixed it and I haven't tried this code out so I don't know if it works. Here is an example of this:
var has_disconnected = false;
window.onbeforeunload = function () {
while (!has_disconnected) {
bas_disconnect_only();
// This doesn't have to be here but it doesn't hurt to add it:
return true;
}
}
And inside the bas_send_request() function (xmlhttp is the HTTP request):
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
has_disconnected = true;
}
Good luck and I hope this helps.
I had to track any cases when user leave page and send ajax request to backend.
var onLeavePage = function() {
$.ajax({
type: 'GET',
async: false,
data: {val1: 11, val2: 22},
url: backend_url
});
};
/**
* Track user action: click url on page; close browser tab; click back/forward buttons in browser
*/
var is_mobile_or_tablet_device = some_function_to_detect();
var event_name_leave_page = (is_mobile_or_tablet_device) ? 'pagehide' : 'beforeunload';
window.addEventListener(event_name_leave_page, onLeavePage);
/**
* Track user action when browser tab leave focus: click url on page with target="_blank"; user open new tab in browser; blur browser window etc.
*/
(/*#cc_on!#*/false) ? // check for Internet Explorer
document.onfocusout = onLeavePage :
window.onblur = onLeavePage;
Be aware that event "pagehide" fire in desktop browser, but it doesn't fire when user click back/forward buttons in browser (test in latest current version of Mozilla Firefox).
Try navigator.sendBeacon(...);
try {
// For Chrome, FF and Edge
navigator.sendBeacon(url, JSON.stringify(data));
}
catch (error)
{
console.log(error);
}
//For IE
var ua = window.navigator.userAgent;
var isIEBrowser = /MSIE|Trident/.test(ua);
if (isIEBrowser) {
$.ajax({
url: url,
type: 'Post',
.
.
.
});
}
I felt like there wasn't an answer yet that summarized all the important information, so I'm gonna give it a shot:
Using asynchronous AJAX requests is not an option because there is no guarantee that it will be sent successfully to the server. Browsers will typically ignore asynchronous requests to the server. It may, or may not, be sent. (Source)
As #ghchoi has pointed out, synchronous XMLHTTPRequests during page dismissal have been disallowed by Chrome (Deprecations and removals in Chrome 80). Chrome suggests using sendBeacon() instead.
According to Mozilla's documentation though, it is not reliable to use sendBeacon for unload or beforeunload events.
In the past, many websites have used the unload or beforeunload events to send analytics at the end of a session. However, this is extremely unreliable. In many situations, especially on mobile, the browser will not fire the unload, beforeunload, or pagehide events.
Check the documentation for further details: Avoid unload and beforeunload
Conclusion: Although Mozilla advises against using sendBeacon for this use case, I still consider this to be the best option currently available.
When I used sendBeacon for my requirements, I was struggling to access the data sent at the server side (PHP). I could solve this issue using FormData as recommended in this answer.
For the sake of completeness, here's my solution to the question:
window.addEventListener('beforeunload', function () {
bas_disconnect_only();
});
function bas_disconnect_only () {
const formData = new FormData();
formData.append(name, value);
navigator.sendBeacon('URL', formData);
}
I've been searching for a way in which leaving the page is detected with AJAX request. It worked like every time I use it, and check it with MySQL. This is the code (worked in Google Chrome):
$(window).on("beforeunload", function () {
$.ajax({
type: 'POST',
url: 'Cierre_unload.php',
success: function () {
}
})
})
To run code when a page is navigated away from, you should use the pagehide event over beforeunload. See the beforeunload usage notes on MDN.
On that event callback, you should use Navigator.sendBeacon(), as Sparky mentioned.
// use unload as backup polyfill for terminationEvent
const terminationEvent = "onpagehide" in self ? "pagehide" : "unload";
window.addEventListener(terminationEvent, (event) => {
navigator.sendBeacon("https://example.com/endpoint");
});

Catching A Browser Close Event

Hello Seniors (As I am new to Web Based Applications),
I was keen to implement or catching browser closing event.
Yes! I did it and successfully implemented it by using javascript{see code below}
but I have implemented it in a web page without MasterPage.
Now, as I am trying to implement it in a webpage with MASTERPAGE but in each post back...the event window.onunload is caught, which is giving me problems...
Is there any technique or logic to detect whether I can differentiate between a Close browser button and a page's post back event.
Please guide me...as I have to implement in a project as soon as possible....
thank you.
Ankit Srivastava
<script type="text/javascript">
function callAjax(webUrl, queryString)
{
var xmlHttpObject = null;
try
{
// Firefox, Opera 8.0+, Safari...
xmlHttpObject = new XMLHttpRequest();
}
catch(ex)
{
// Internet Explorer...
try
{
xmlHttpObject = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(ex)
{
xmlHttpObject = new ActiveXObject('Microsoft.XMLHTTP');
}
}
if ( xmlHttpObject == null )
{
window.alert('AJAX is not available in this browser');
return;
}
xmlHttpObject.open("GET", webUrl + queryString, false);
xmlHttpObject.send();
return xmlText;
}
</script>
<script type="text/javascript">
var g_isPostBack = false;
window.onbeforeunload = check ()
function check()
{
if ( g_isPostBack == true )
return;
var closeMessage =
'You are exiting this page.\n' +
'If you have made changes without saving, your changes will be lost.\n' +
'Are you sure that you want to exit?';
if ( window.event )
{
// IE only...
window.event.returnValue = closeMessage;
}
else
{
// Other browsers...
return closeMessage;
}
g_isPostBack = false;
}
window.onunload = function ()
{
if ( g_isPostBack == true )
return;
var webUrl = 'LogOff.aspx';
var queryString = '?LogoffDatabase=Y&UserID=' + '<%# Session["loginId"] %>';
var returnCode = callAjax(webUrl, queryString);
}
</script>
There is no javascript event which differentiates between a browser being closed and the user navigating to another page (either via the back/forward button, or clicking a link, or any other navigation method). You can only tell when the current page is being unloaded. Having said that, I'm not sure why you'd even need to know the difference? Sounds like an XY problem to me.
The answer can be found on SO:
How to capture the browser window close event?
jQuery(window).bind("beforeunload", function(){return confirm("Do you really want to close?") })
and to prevent from confirming on submits:
jQuery('form').submit(function() {
jQuery(window).unbind("beforeunload");
...
});
First step: add global JavaScript variable called "_buttonClicked" which is initially set to false.
Second step: have every button click assign _buttonClicked value to true.. with jQuery it's one line, pure JavaScript is also few lines only.
Third step: in your function check _buttonClicked and if it's true, don't do anything.
EDIT: After quick look in your code I see you already have steps #1 and #3, so all you need is the second step, assign g_isPostBack as true when any submit button is clicked. Let me know if you need help implementing the code and if you can have jQuery.
If one wants to catch Log out when the browser is closed (by clicking on the cross), we can take the help of window events.
Two events will be helpful: onunload and onbeforeunload.
But the problem arises that the code will also work if you are navigating from one page to another as well as also when one
refreshes the page. We don't want our sessions to be clear and inserting the record of logging out while refreshing.
So the solution is if we distinguish the difference between closing and refreshing or navigating.
I got the solution:
Write 'onbeforeunload ="loadOut();"' within the body tag on master page.
Add the following function inside script in head section of master page :-
function loadOut() {
if ((window.event.clientX < 0) || (window.event.clientY < 0))
{
// calling the code behind method for inserting the log out into database
}
}
And its done. It is working for IE, please check for other browsers. Similarly you can detect the event if the window is closed
by pressing the combination of keys ALT+F4.
window.unload fires when we navigate from one page to another as well as when we click on close button of our browser,So to detect only browser close button you need to use flag.
var inFormOrLink;
$("a,:button,:submit").click(function () { inFormOrLink = true; });
$(":text").keydown(function (e) {
if (e.keyCode == 13) {
inFormOrLink = true;
}
})/// Sometime we submit form on pressing enter
$(window).bind("unload", function () {
if (!inFormOrLink) {
$.ajax({
type: 'POST',
async: false,
url: '/Account/Update/'
});
}
})

Categories

Resources