PDA

View Full Version : Close All Child Windows



karunakaran
01-10-2007, 05:34 PM
Hi,

How do I close multi level childs windows from the base parent window. Some thing like this.
A opens B opens C opens D opens E

If I click on a button on A, I want to close A,B,C,D and E.

Since I open C from B, A does not have a direct reference to C or may be I'm missing something here.

Thanks

Twey
01-10-2007, 06:33 PM
Presuming that all the documents in the windows are stored on the same domain, you can call functions in a separate window as properties of their window.
window.oldopen = window.open;
window.childWindows = [];
function clearOldWindows() {
var ret = 0;
for(var i = 0; i < childWindows.length; ++i)
if(!childWindows[i].document)
ret += childWindows.splice(i, 1).length;
return ret;
}
function closeAllChildWindows() {
for(var i = 0; i < childWindows.length; ++i) {
if(childWindows[i].closeAllChildWindows)
childWindows[i].closeAllChildWindows();
childWindows[i].close();
}
clearOldWindows();
}
window.open = function() {
clearOldWindows();
return childWindows[childWindows.push(window.oldopen.apply(window, arguments)) - 1];
};Put that in a separate JS file, and include it in the heads of all the pages you'd like to include in this chain. Then, call closeAllChildWindows() on a window to close all its children.

karunakaran
01-10-2007, 11:48 PM
return childWindows[childWindows.push(window.oldopen.apply(window, arguments)) - 1];
[/code]Put that in a separate JS file, and include it in the heads of all the pages you'd like to include in this chain. Then, call closeAllChildWindows() on a window to close all its children.

Hi,

I get the following error on that line
Object doesn't support this property or method.
Looks like window.oldopen.apply is giving error.

Thanks

Labhesh
01-11-2007, 04:47 PM
I am also having the same issue/error, which karunakarn has posted.

Any help ?:(

Twey
01-11-2007, 07:03 PM
Sorry, it seems IE doesn't like that. Try:
window.open = function() {
var args = [];
for(var i = 0; i < arguments.length; ++i)
args.push(arguments[i]);
clearOldWindows();
return childWindows[childWindows.push(window.oldopen.apply(window, args)) - 1];
};

Labhesh
01-12-2007, 06:15 AM
I am trying to run this project on Internet Explore (IE).
but I still get an error "Microsoft JScript runtime error: Object doesn't support this property or method"

1. development on dotnet VS2.0
2. Browser is : IE.

Code is attached.
Default page will open A:
A will open B
B will open C
C will open D

On Default page when clicked Close : should close all windows open(Default,A,B,C,D);

Regards
Labhesh S
717

jscheuer1
01-12-2007, 10:45 AM
Perhaps something simpler:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
var kids=[];
onunload=function(){
for (var i_tem = 0; i_tem < kids.length; i_tem++)
if(kids[i_tem].opener)
kids[i_tem].close();
}
</script>

</head>
<body>
A<br>
<a href="b.htm" onclick="kids[kids.length]=window.open(this.href,'','width=400, height=400');return false;">b</a>
</body>
</html>

Twey
01-12-2007, 11:22 AM
That's not quite as flexible though.

I'll debug mine later.

Labhesh
01-12-2007, 06:16 PM
Okay.
I am still waiting.
Thanks !!

jscheuer1
01-12-2007, 07:09 PM
That's not quite as flexible though.

I'll debug mine later.

I don't follow. How is your code more flexible? If you use the code in my post for all pages involved in the chain of open windows and open them all using similar syntax to that shown in the example, the children of any given window in the chain will close when any of its parents are closed.

There is a problem in that Opera will not fire the page's onunload event when its window is closed and all browsers that I tested will fire it when the page is unloaded (changed) but, you could just break it out like so:


<script type="text/javascript">
var kids=[];
function closeAllKids(){
for (var i_tem = 0; i_tem < kids.length; i_tem++)
if(kids[i_tem].opener)
kids[i_tem].close();
}
</script>

and call closeAllKids() as desired. This script could also be external and linked to the head of each page. Its strong point is that it works.

The real issue at stake here, in my opinion is, "Is there an event that fires when and only when a window is closed?" I don't think that there is, if there were, its use would be ideal for this. I may have missed something but, I do not see where your code, Twey, addresses this. Perhaps a poll could be established on the child windows to periodically check to see if the parent window (the .opener) is still open.

Twey
01-12-2007, 07:17 PM
Oh, you're right, of course. I was thinking of selecting a given window and closing all its children.

jscheuer1
01-12-2007, 09:45 PM
Oh, you're right, of course. I was thinking of selecting a given window and closing all its children.

Yes, and, going back to the original post I see that the request was for a button to close all children, in that case, using my script code as amended with the function called closeAllKids() would work fine if on or linked to each page's head section. All children would need to be opened with the syntax shown (red required, green required and configurable):


<a href="b.htm" onclick="kids[kids.length]=window.open(this.href,'','width=400, height=400');return false;">b</a>

Your close button could be like:


<input type="button" value="Close Child Windows" onclick="closeAllKids();">

Labhesh
01-17-2007, 03:55 PM
Twey,

Can you help me with the issue. i am still having the problem.

Thanks
Labhesh S

Twey
01-17-2007, 04:01 PM
John's is just as good as mine (better actually, since it's not necessary to overwrite window.open()): use that instead.

Labhesh
01-18-2007, 05:31 AM
Hi Twey,

I am still waiting for your reply.

can you let me know your finding on the same subject.

Thanks
Labhesh S

Labhesh
01-18-2007, 01:42 PM
Hi John,

I have tried with the same code as u said.

i am using two function in one common.js file. one for opening the window and one for closing the windows using that kids array.
when i open any new window i assing to that returnd value to kids array.
but the issue is : this common.js file should be register to all the child pages also becuase those child pages also have to access the functions defined inside the common.js file.
and the issue is when ever any new child request for common.js file that time this file and the variable will get initilize.
and once it is initilized on child window then you know ::( kids array will loose all the values of child window.

i hope i am clear to make the problem understandable.
still i am adding my code to review.

Let me kow your suggestion on this.

Thanks
Labhesh S
726

jscheuer1
01-18-2007, 03:07 PM
Well, that isn't really what is happening, a variable set for one page will not affect a variable on another page, even if they both have the same name and were set from the same common external script file. The following has limitations but works as long as intermediary windows in the chain haven't been closed:

The script code, it may be external and linked to each page (updated):


var kids=[];
function closeAllKids(){
for (var i_tem = 0; i_tem < kids.length; i_tem++){
if(kids[i_tem].closeAllKids)
kids[i_tem].closeAllKids();
if(kids[i_tem].opener)
kids[i_tem].close();
}
kids.length=0;
}

function openKid(url){
kids[kids.length]=window.open(url,'','width=400, height=400');return false;
}

The example method for opening windows (updated):


<a href="a.htm" onclick="return openKid(this.href);">a</a>


Close all button:


<input type="button" onclick="closeAllKids();">

jscheuer1
01-18-2007, 03:38 PM
This script seems even better. It will keep track and close child windows even if intermediate windows have been closed. But, will cause older browsers (browsers like IE 4 or NS 4) to barf:


var kids=[];
function closeAllKids(){
for (var i_tem = 0; i_tem < kids.length; i_tem++)
if(kids[i_tem])
try{
kids[i_tem].close();
}
catch(e){}
kids.length=0;
}

function openKid(url){
kids[kids.length]=window.open(url,'','width=400, height=400');
var o=window;
while(o=o.opener)
if(o.kids)
o.kids[o.kids.length]=kids[kids.length-1]
return false;
}

karunakaran
01-18-2007, 05:27 PM
Hi John,

The only problem is, it does not close the parent window(the base window of all windows). I added window.close at the end of the closeallkids function.

kids.length=0;
window.close();

This resulted in a popup asking the user for confirmation of closing the window. To get rid of the alert I added a opener reference like this.

kids.length=0;
window.opener="abc";
window.close();

I'm not sure if this is a good idea, any other better way?

Thanks

jscheuer1
01-18-2007, 08:44 PM
I usually use:


window.opener=self;

But, no it isn't a very good idea. However it is done, it is simply fooling the browser and, many browsers simply will not be fooled. The right way to do it is to have opened the page via javascript in the first place. The security protocol involved is:

You cannot close a window using javascript if it wasn't opened using javascript.

So, as you can see, this shouldn't be done from your index page.

jscheuer1
01-19-2007, 05:28 AM
I was thinking about it and, I've just hit upon a method for closing a page with javascript that wasn't originally opened using javascript. The solution is rather simple in concept - As the page is opening, if the window doesn't have a certain name, give the window that name and open the page itself in that named window. This avoids pop up blockers because the window is already open and ensures that your page is now available to be closed via javascript because, after all, it was now opened using javascript. This causes an infinite looping error in the openKid() function in Mozilla though but, there is a way around that as well.

Here's a demo:

http://home.comcast.net/~jscheuer1/side/close_chain/close_chain.htm

djr33
01-19-2007, 06:40 AM
Very impressive coding. Simple, but works great. I like it.

BLiZZaRD
01-19-2007, 06:47 AM
OHHHHH I get it!!! Man I am not with it today, I am going to sleep I promise. Hopefully I will wake up with more cylinders firing in order tomorrow!

Labhesh
01-19-2007, 07:23 AM
I love this approch. It work in gr8 way. Thanks an lot for all the support and input to everyone.

But there is one case when this application will fail, and i have no clue weather any work around exits for this problem.
my default page open 5 page A that mean you click 5 times the button on default page to open new a.aspx page.
and finally user clicks on default button refresh button (F5).
after this if i click on close button on default page. then it does not close all window.
i think it happens because i have lost all the ref of child window.
I am still thinking : is there any better way to outcome of this problem.

Thanks
Labhesh S

jscheuer1
01-19-2007, 07:39 AM
user clicks on default button refresh button (F5).
after this if i click on close button on default page. then it does not close all window

Or if they refresh the page using the context menu or move around with the back and forward buttons or using normal links on the page (if any), same thing. I thought about this but, haven't figured out a way yet. There may be none.

An ideal candidate for a solution, in my opinion would be a cookie or cookies to keep track of all the open windows and reload them to the page(s) if it is (they are) refreshed. However, unlike simple variables (like numbers or strings) that are easily stored in and retrieved from cookies, windows are script objects. Their string value is simply 'Object' or 'Object HTML Window Object', or something like that - it varies from browser to browser but, in every browser, it contains no useful information of the type that would be required to access the windows.

If there were a javascript object that could be used to retrieve all open windows and examine them to see if they met certain criteria, that could be used to rebuild the kids array should any window be refreshed but, I am not aware of such an object.

jscheuer1
01-20-2007, 08:22 PM
This isn't, in my opinion, completely feasible (refreshing the list of windows to be closed). There would inevitably be some circumstances where a window might be missed. But, this is pretty good:

http://home.comcast.net/~jscheuer1/side/close_chain_p/close_chain.htm

It may even be able to be improved upon. It relies upon the unload event and I have instituted it only for the top page in the series though, I suppose all of the pages could have this ability to remember their children on refresh. There is quite a bit of added code to do the cookies and to handle Opera (which doesn't fire onunload when the page is refreshed). Even with the added code for Opera, that browser cannot distinguish which windows are open at the appropriate time (onunload) so it will at times attempt to put up a pop up if a window was closed but, its default settings will block this, unfortunately with notification to the user. Other browsers do not have this problem as far as I could see in testing. The trick involved is that each new window must be given a unique name, the openKid() function allows for this. The real trick, for those who are interested from a coding perspective is that you can open a window that is already open by its name (if it has one) but with no URL. When you do this, it returns a handler (what was lost when we refreshed the top page) but leaves the current page intact. So, all we need to save in the cookie are the names of the windows - perfect as I mentioned before as, these are string values.