Detecting when popup window is closed in Firefox - javascript

I open a new window like this:
var newWindow = window.open('myPage.aspx', null, 'height=650,width=900,status=yes,toolbar=no,scrollbars=yes,menubar=no,location=no,top=0, left=0');
And I wait for it to close:
var windowTimer = window.setInterval(function () {
if (win.closed !== false) {
//If window is closed ...
window.clearInterval(windowTimer);
}
}, 100);
This does work in Chrome and IE9 and Edge but not in Firefox, why?
Firefox does get inside the function but it never gets on win.closed if, even if there is an else it neither goes into it... is there any alternative to this?
Solution that worked for me:
On the popup window:
//Fires an event on the window that opened it
window.onbeforeunload = function () {
window.opener.myEvent();
};
On the main window:
window.myEvent= function () {
//This fires only when the popup gets closed on beforeunload
}
Note: the event to fire in the main window must be declared as public so it can be accessible, like so window.myEvent= function ()
Another reference: cross-window javascript events

Basically, I think the simplest way to do this is the following:
function hasClosed(){
document.getElementById('open').textContent = 'window has been closed';
}
window.addEventListener('beforeunload', function(){
if(window.opener) window.opener.hasClosed();
});
document.getElementById('open').addEventListener('click', function(e){
e.preventDefault();
window.open('test.html');
});
open window
Please keep in mind that SO snippets are not allowed to open windows, so the code is not functional inside the snippet. Simply copy the code and save it as a file called test.html.
You do not need to keep checking, the child will simply call the function on the parent. This has the advantage that you are not using resources to keep checking for it. Also, be aware that when navigating in this window, onbeforeunload gets called if a new page is loaded, calling the parent function, but maybe you could just do the check you were already doing in the hasClosed function.
You might want to give an uuid to your window and pass it into it so it can inform you of it's identity on closing, but that's all refinement.

Related

showModalDialog and window.open does not work in Microsoft Edge [duplicate]

We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS

Return a value from window.open

We recently discovered that Chrome no longer supports window.showModalDialog which is problematic because our enterprise application uses this method.
There is, apparently, a short term workaround that allows you to restore showModalDialog but it involves modifying the registry which is too complicated (and risky) four our average user. Therefore I'm not a big fan of this workaround.
The long term solution is obviously to remove all calls to this obsolete method and replace them with a convenient jQuery plugin (such as VistaPrint's Skinny Modal Dialog plugin, for example. Other suggestions are welcome by the way).
The typical scenario we use the modal dialog is to ask the user for Yes/No confirmation before executing an action that cannot be undone, ask the user to agree to terms and condition before proceeding, etc. Typically the onclick event on the "Yes" or "Ok" button in the modal dialog looks like this:
window.returnValue = true;
window.close();
Similarly, the "Cancel" or "No" button looks like this:
window.returnValue = false;
window.close();
The fact that we can return a value from the dialog is very convenient because it allows the "parent" window to be notified whether the user has clicked the "Ok" or the "Cancel" button like so:
var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
... proceed ...
}
The last thing I'm going to mention about the showModalDialog is that it works great even when the document displayed in the dialog is from a different domain. It's very common for us to have our javascript running from http://the-client.com but the "Terms of Service" web page is from http://the-enterprise-vendor.com
I need a temporary solution that I can deploy ASAP while we work on the long term solution. Here are my criteria:
minimal code change in existing JavaScript
the pop up window must be able to return a value to the "parent". Typically this value is a Boolean but it could be any simple type (e.g.: string, int, etc.)
solution must work even if the URL of the content is from different domain
Here's what I have so far:
1) Add the following method in my JavaScript:
function OpenDialog(url, width, height, callback)
{
var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
var timer = setInterval(function ()
{
if (win.closed)
{
clearInterval(timer);
var returnValue = win.returnValue;
callback(returnValue);
}
}, 500);
}
As you can see in this method, I try to make the pop up window look as similar to a dialog as possible by hiding the menu and the toolbar, I setup a time every 500 milliseconds to check if the window has been closed by the user and if so, get the 'returnValue' and invoke a callback.
2) replace all calls to showModalDialog with the following:
OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
if (termsOfServiceAccepted)
{
... proceed ....
}
});
The fourth parameter to the method is the callback where I check if the user has clicked the "Ok" button before allowing her to proceed.
I know it's a long question but basically it boils down to:
What do you think of the solution I propose?
In particular, do you think I'll be able to get a returnValue from a window that was opened with window.open?
Any other alternative you can suggest?
I have two ideas that could help you but the first one is tied to CORS, so you won't be able to use it from different domains at least you can access both services and configure them.
FIRST IDEA:
The first one is related to this native api. You could create on the parent window a global function like this:
window.callback = function (result) {
//Code
}
As you can see it receives a result argument which can hold the boolean value you need. The you could open the popup using the same old window.open(url) function. The popup's onlick event handler could look like this:
function() {
//Do whatever you want.
window.opener.callback(true); //or false
}
SECOND IDEA: Solves the problem
The other idea I got is to use this other native api to trigger an event on the parent window when the popup resolves (better known as cross-document messaging). So you could do this from the parent window:
window.onmessage = function (e) {
if (e.data) {
//Code for true
} else {
//Code for false
}
};
By this way you are listening to any posted message on this window, and checking if the data attached to the message is true (the user clicks ok in the popup) or false (the user clicks cancel in the popup).
In the popup you should post a message to the parent window attaching a true or a false value when corresponds:
window.opener.postMessage(true, '*'); //or false
I think that this solution perfectly fits your needs.
EDIT
I have wrote that the second solution was also tied to CORS but digging deeper
I realized that cross-document messaging isn't tied to CORS

Trying to handle a close window event on child window

I have a website that opens a new window. I am trying to trigger onclose event on the child window (if the user closed the window the parent window will alert it).
I found a stackoverflow question regarding that problem at: How to run function of parent window when child window closes?
But, the answer also preforms action on the child window which I think I can't do because the child window opens a website not in my control (I can't edit its html).
I was thinking of using the following to trigger the on close event
var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });
$(window).bind("beforeunload", function() {
return inFormOrLink;
})
How do I apply this on the new tab/window?
This is not possible to do solely on the client-side.
In order to do this, you'll need to do the following:
Upon opening a tab, send an ajax call to a script that doesn't stop loading until it receives a second ajax call, this is usually done with a script that waits for an sql value to exist before outputting.
Upon closing the tab, send the second ajax call to that script so that it replies to the original ajax call.
Viola.
I'm not aware of a simpler way to do this.
Original window:
function waitForTabClose(windowID) {
$.post('waitfortabclose.php',{windowID:windowID},function(data) {
if (data == 1) {
// Do tab closed stuff
} else {
waitForTabClose(windowID);
}
});
}
waitfortabclose.php
$i=1;
$wID = $_POST['windowID'];
do {
if (file_get_contents($wID) == $wID) {
echo 1;exit;
}
set_time_limit(30);
sleep(5);
} while($i++ < 50);
echo 0;
New Tab
window.onclose = function() {
$.post('windowclosed.php',{windowID:windowID);
};
windowclosed.php
$wID = $_POST['windowID'];
file_put_contents($wID,$wID);
This is pseudocode, and hasn't been tested. The functionality can be written in a lot of ways, this is just how I'd do it.
Found a solution to what i were looking for. it was much easier then the above answer plus its actually works and what i were looking for.
var win = open('http://www.google.com');
if (win.closed) {
alert('Window closed! Hoorah!');
}
Thanks very much for whoever tried helping.

js popup open and check it's status on another page

open a popup window using window.open() on on html page
pop=window.open('pops.html','mypop');
when i go to new page how can i detect whether this popup still opened or closed using java script. Thank you
You could use window.opener.methodYouWantToCall() to call methods in the window that opened the new window to talk to the opening window and tell it things like "I'm still open". you can read more here. You will have to make sure that the method exists in the window though.
here is some pseudo code for how to handle it:
my_window = window.open(...);
my_window.opener.document.onUnload = function(){
my_window.opener.document.onload = function(){
my_window.opener.theWindow(a variable) = my_window;
}
};
(in new page):
function check(){
if(theWindow != null){
if(!theWindow.closed){
// handle
}
} else {
setTimeout("check()", 1000);
}
}

Javascript,calling child window function from opener doesn't work

I'm developing a web application that opens a popup using windows.open(..). I need to call a function on the opened window using the handle returned by "window.open", but I'm always getting the error message "addWindow.getMaskElements is not a function", as if it couldn't access the function declared on child window. This is the behavior in both IE and FF. My code looks like this:
function AddEmail(target,category)
{
if(addWindow == null)
{
currentCategory = category;
var left = getDialogPos(400,220)[0];
var top = getDialogPos(400,220)[1];
addWindow = window.open("adicionar_email.htm",null,"height=220px, width=400px, status=no, resizable=no");
addWindow.moveTo(left,top);
addWindow.getMaskElements ();
}
}
I've googled and read from different reliable sources and apparently this is supposed to work, however it doesn't.
One more thing, the functions in child window are declared in a separate .js file that is included in the adicionar_email.htm file. Does this make a difference? It shouldn't..
So, if anyone has ran into a similar problem, or has any idea of what I'm doing wrong, please, reply to this message.
Thanks in advance.
Kenia
The window creation is not a blocking operation; the script continues to execute while that window is opening and loading the HTML & javascript and parsing it.
If you were to add a link on your original page like this:
Test
You'd see it works. (I tried it just to be sure.)
**EDIT **
Someone else posted a workaround by calling an onload in the target document, here's another approach:
function AddEmail()
{
if(addWindow == null) {
addWindow = window.open("test2.html",null,"height=220px, width=400px, status=no, resizable=no");
}
if(!addWindow.myRemoteFunction) {
setTimeout(AddEmail,1000);
} else { addWindow.myRemoteFunction(); }
}
This keeps trying to call addWindow.myRemoteFunction every 1 second til it manages to sucessfully call it.
The problem is that window.open returns fairly quickly, the document that is requested and then any other items that that document may subsequently refer to will not yet have been loaded into the window.
Hence attempting to call this method so early will fail. You should attach a function to the opened window's load event and attempt to make you calls from that function.
The problem with the below one is :
When the javascript is being executed in the parent window, the child window is not loading. Hence, the invoking function from parent window is in the infinite loop and it is leading to crashing the window.
The window creation is not a blocking operation; the script continues
to execute while that window is opening and loading the HTML &
javascript and parsing it.
If you were to add a link on your original page like this:
Test
You'd see it works. (I tried it just to be sure.)
**EDIT **
Someone else posted a workaround by calling an onload in the target
document, here's another approach:
function AddEmail()
{
if(addWindow == null) {
addWindow = window.open("test2.html",null,"height=220px, width=400px, status=no, resizable=no");
}
if(!addWindow.myRemoteFunction) {
setTimeout(AddEmail,1000);
} else { addWindow.myRemoteFunction(); }
}
This keeps trying to call addWindow.myRemoteFunction every 1 second
til it manages to sucessfully call it.
You are calling the function immediately after opening the window; the page on the popup may not be loaded yet, so the function may not be defined at that point.

Categories