How to run a method when the window closes in JavaScript - javascript

I'm wondering how I can run a method when a window or tab closes. I've tried using the following...
window.onclose = () => {
// execute function
}
window.onbeforeunload = () => {
// execute function
}
but both of these only fire when I refresh the page not when I close it.
Any help would be very appreciated thanks!

Not possible anymore.
Newer browsers doesn't support it anymore.

Related

Capturing window close or refresh not working in reactjs [duplicate]

This question already has answers here:
window.onbeforeunload not displaying the alert box
(2 answers)
Closed 4 months ago.
I hope you are doing well!
I am trying to catch the window close or tab close or refresh event in my project and I tried all possible solutions but haven't succeeded.
I tried using:
useEffect(() => {
return () => {
window.alert("Alert");
};
});
and I tried:
useEffect(() => {
window.onbeforeunload = () => {
window.alert("alert");
};
return () => {
window.onbeforeunload = null;
};
});
which seems to only trigger if I have my window in the background for a while.
and I tried:
window.addEventListener("onbeforeunload", () => {
window.alert("alert");
});
but haven't been able to capture it.
I will use this functionality to send data to a specific API whenever the user closes the window or tab or refreshes (and possibly turns off the PC while on the page if that is event possible). But all these methods weren't working for me.
Is there any other way or is there a reason they aren't working?
Thank you for your time!
You might need to call preventDefault, and I think the event is called beforeunload, try:
window.addEventListener("beforeunload", ev => {
ev.preventDefault()
return (ev.returnValue = "Are you sure you want to close?")
})
When registering event listeners, you should do this with useEffect so you properly remove the listeners.
useEffect(() => {
const onUnload = (e: any) => {
e.preventDefault()
return (e.returnValue = "Are you sure you want to close?")
}
window.addEventListener("beforeunload", onUnload)
return () => window.removeEventListener("beforeunload", onUnload)
}, [])
Some things to know about beforeunload:
It does not call blocking functions such as alert, prompt or confirm. It is evident from a user perspective.
And it is fired only if there has been ANY user interaction with the site. Without ANY interaction (even one click anywhere) event beforeunload won't be fired.
It is impossible to catch a tab/browser close and even if it was, it was not going to be reliable as the user might force close the browser or kill the process, etc.
So the best option I found, I wrapped in a NPM package here: https://www.npmjs.com/package/#garage-panda/use-before-unload
Take a look and let me know if it works for you.
This is how you use it:
const setEnabledBeforeUnload = useBeforeUnload({
initEnable: false, // do you need to be enabled by default
onRefresh: () => {
// the page has been refreshed (the user has clicked Reload)
},
onCancel: () => {
// the user has clicked Cancel
}
});
And the only possible (and the correct way) to know if the user has left your page is to actually catch the event when he lands on your page (e.g. the sessionStorage is empty).

How can I catch close tab event reliably in Javascript?

My requirement is that I need to call some API after close tab from browser in Javascript.
I have tried below code which almost everyone suggest, but that is not working every time. I have tried every possible way with below code:
window.onbeforeunload = function () {
callClose();
return;
};
function callClose() {
// API call
}
I need proper reliable solution for this. Can anyone help me on this, I am stuck here.

.onbeforeunload sometimes returns, sometimes doesn't (popup,IE11)

I'm working on this code at work. Basically, it returns a console.log whenever the popup is closed. Using .onbeforeunload works with every browser but IE11. With IE11 it'll work sometimes and sometimes it doesn't call at all. I'm not doing anything different, just opening the popup then closing it. I've no idea how to fix this as it's temperamental. I've pasted the function code below. Thanks
function open(config, refID, cb) {
var w = window.open(
config.baseURL,
"_blank",
"toolbar,scrollbars,resizable,top=250,left=250,width=599,height=500"
);
w.onbeforeunload = function () {
if (cb) cb()
};
}
I really don't know how you managed to make your code work. It simply won't. The problem is that you can't add an event like you are trying. You need to use addEventListener. I made a simple snippet. Works 100% of times. No temperamental code, if such thing even existed :)
function open(url, callback) {
// Open the window
var win = window.open(url, "popup", "toolbar=1, scrollbars=1, resizable=1, top=250, left=250, width=500, height=500");
// Add the event listener
win.addEventListener('beforeunload', function () {
if(callback) callback();
}, false);
}
// Opens the window, with the url and callback as arguments
open('whatever.html', function() {
console.log('hello!');
});
Remember that you need permissions on the opened window url to be able the add the event listener to it.
Hope it helps.

Confirm beforeunload in Electron

i know that there are hundreds of questions like: "How can i prevent close event in electron" or something like that.
After implementing a confirmation box (electron message box) in the beforeunload event i was able to close my app and cancel the close event. Since the dev tools are always open, i didn't recognize that it doesn't work while the dev tools are closed...
window.onbeforeunload = e =>
{
// show a message box with "save", "don't save", and "cancel" button
let warning = remote.dialog.showMessageBox(...)
switch(warning)
{
case 0:
console.log("save");
return;
case 1:
console.log("don't save");
return;
case 2:
console.log("cancel");
return false;
// e.returnValue = "false";
// e.returnValue = false;
}
};
So, when the dev tools are opened, i can close the app with saving, without saving and cancel the event.
When the dev tools are closed, the cancel button doesn't work anymore.
Btw.:
window.onbeforeunload = e =>
{
return false;
alert("foo");
};
will cancel the close event and obviously wouldn't show the message (doesn't matter if dev tools are open or closed)
window.onbeforeunload = e =>
{
alert("foo");
return false;
};
will cancel the close event after pressing ok if dev tools are open and will close the app after pressing ok if dev tools are closed
Intentionally i'm using the synchronous api of the message box and while i'm writing this question i figured out that a two windowed app (new remote.BrowserWindow()) will behave exactly like with the dev tools.
Has anyone an idea how i can resolve this problem?
Many thanks in advance
Instead of onbeforeunload prefer working with the event close. From this event, you'll be able to catch the closing event before the whole closure process is completed (event closed). With close, you'll be able to take the control and stop whenever you need the completion of the closure.
This is possible when you create your BrowserWindow, preferably in the main process:
// Create the browser window.
window = new BrowserWindow({});
// Event 'close'
window.on('close', (e) => {
// Do your control here
if (bToStop) {
e.preventDefault();
}
})
// Event 'closed'
window.on('closed', (e) => {
// Fired only if you didn't called e.preventDefault(); above!
})
In addition, be aware that the function e.preventDefault() is spreading in the whole code. If you need to be back to the natural behaviour of Electron, you need to toggle the variable e.defaultPrevented to false.
Actually, it seems e.preventDefault() function is handling the variable e.defaultPrevented to true until any change on it.
Maybe this will help someone with similar needs as i had, i have a react app wrapped in an electron app, the react app is agnostic to electron and can also run in the browser and the requirements i had was to show the default browser prompt, the infamous Leave Site? alert.
In the browser this is easy, for example with react i just do this:
useEffect(() => {
window.onbeforeunload = promptOnProjectLeave ? () => true : undefined;
return () => {
window.onbeforeunload = undefined;
}
}, [promptOnProjectLeave]);
Which will show the default browser Leave Site? prompt, but in electron this will only prevent the window from being closed without any action prompt asking you if you are sure, so my approach was a mix of this post and another post.
This is the solution
mainWindow.webContents.on('will-prevent-unload', (event) => {
const options = {
type: 'question',
buttons: ['Cancel', 'Leave'],
message: 'Leave Site?',
detail: 'Changes that you made may not be saved.',
};
const response = dialog.showMessageBoxSync(null, options)
if (response === 1) event.preventDefault();
});
This will allow me to use window.onbeforeunload in my react code as i would in the browser, in the browser i will get the default browser prompt and in electron i will get a message box :)
This is my first time working with electron so might be some ways to improve this but either way hope this helps someone, i know it would have helped me when i started with this task.
Update:
As I mentioned above in the comments of the accepted answer, the preventDefault was ignored on Windows. To be precise, I had it placed in the callback of a native electron dialog that opened when the user closed the app.
Therefore I have implemented a different approach:
let close: boolean = false
win.on('close', (ev: any) => {
if (close === false) {
ev.preventDefault()
dialog.showMessageBox({
type: 'warning',
buttons: ['Cancel', 'Ok'],
title: 'Do not forget to safe your changes',
cancelId: 0,
defaultId: 1,
noLink: true
}).then((val) => {
if (val.response === 0) {
// Cancel the close process
} else if (win) {
close = true
app.quit()
}
})
}
})
You can simply use 'pagehide' event. It seems to be working fine for electron apps. It works slightly different from 'beforeunload' as it can't prevent closing window/tab, but if you only need to do something before the page is closed(send some async request with navigator.sendBeacon(), etc) then this event might suit your needs.
You can read more info about it here, here and in the docs
Example of usage:
window.addEventListener('pagehide', () => {
window.navigator.sendBeacon(url, data);
}

jQuery function not invoked from window variable

I need to show a primefaces dialog when my applet is closed, because there is a thread doing some stuff once it's finished i would like to hide the dialog from the page.
In order to do this i have used the liveConnect using netscape.javascript.JSObject.
this is working like a charm everything is alright.
The problem is the javascript functions are well invoked, but the dialog.show() function is not invoked.
Here is the code :
function doit1() {
$(window).ready(function() {
statusDialog.show();
});
}
;
function doit2() {
$(window).ready(function() {
statusDialog.hide();
});
};
window.callJS = function() {
console.log("we're here 1");
doit1();
console.log("its here1");
};
window.callJS1 = function() {
console.log("we're here 2");
doit2();
console.log("its here2");
};
these methods are called from the applet like this :
JSObject window = JSObject.getWindow(this);
window.call("callJS", null);
//do_some_thread_stuff();
window.call("callJS1", null);
And here is what's happening in the console :
we're here 1
its here1
we're here 2
its here2
So, what i'm really missing and what's preventing the dialog from showing.
Note : when i use chrome DevTools console to execute the doit() methods they're working fine but i get the undefined aftermath.
The problem was with threads, i was invoking JS methods before thread.start().
I've put the window.call("callJS", null); inside the thread and it's working fine.

Categories

Resources