Friday, November 9, 2012

Closing all Child Windows using JavaScript

Hi everyone,

Sorry that it took me so much time to write this 2nd part post, I was pretty loaded at work and personal life, and frankly, I still need to get used to write blog posts ;). I hope that in the future I will be able to write more often, and without these long pauses. Anyway, let’s get down to business.

In my last post I described the way we handle window opening in one of the web application we work on. Just to remind you, we have a single main page that has to be stayed open all the time. This page opens a lot of other page as pop-ups. Those pop-ups can open their own child windows, as pop-up windows or pop-up modal dialogs. Actually it looks like this:

child-windows

I will actually go straight to the implementation of this, but first there are few things we have to remember:

  1. The main page has to be always open, and when it closes all the child windows has to be closed to. So we need to close the child windows when the parent windows are closed, (or starts the process of closing).
  2. When there is a modal dialog opened, the parent window that opened it is frozen, hence cannot run any JavaScript.
  3. The child window cannot always know about his parent window, but the parent window always knows about all of his child windows. That means that the parent should be responsible for the closure of the children.

Given all that, this is how we need to close the child windows:

closing-windows

Finally, code:

Every parent window (e.g. window that opens other windows) should hold a list of references to its child windows, and when it opens a new window it should be added to that list. So we will add this JavaScript code to the head part of the page:

<script type="text/javascript">
var childWindows = [];

function OpenChildWindow() {
var openedWindow = window.open(url, pageName, params);
childWindows[childWindows.length] = openedWindow;
}
</script>

This should be in every page that can open other pages as separate window.


But what about this modal dialog thing? Well, this can be a little bit tricky. Because the window.openModalDialog() function doesn’t return a reference of the dialog, we need to do something like this in the parent script:

<script type="text/javascript">
var childWindows = [];

function OpenModalDialog() {
window.showModalDialog(url, window, params);
}
</script>

And this script in the child dialog:

<script type="text/javascript">
window.dialogArguments.childWindows[window.dialogArguments.childWindows.length] = window;
</script>

This code will pass a reference of the parent window to the child in the second argument (which can used to send all sort of data to the modal dialog), and the modal dialog is responsible to register itself to his parents’ childWindows list, when it’s loaded.


Following this pattern in all of the windows, and you will be able to get to any window from the main page within your code. This is important because of #3 above.


Next, I added this code the main page:

<script type="text/javascript">
function CloseAllChildWindows(window) {
for (var i = 0; i < window.childWindows.length; i++) {
if ((typeof window.childWindows[i].childWindows != "unknown") &&
(typeof window.childWindows[i].childWindows != "undefined")) {
if (window.childWindows[i].childWindows.length > 0) {
CloseAllChildWindows(window.childWindows[i]);
}
}
if (!window.childWindows[i].closed) {
window.childWindows[i].close();
}
}
}
</script>

This main page function will be called when the body.onunload is fired:

<body onunload="CloseAllChildWindows()">

It will go thru all windows, recursively closing all of them, starting from the youngest up to the oldest, and finally the main page will close itself. This will take care of #1 above.


You can notice that the function always check the second hierarchy from the current window. That’s because #2 - The script can’t ask a direct child window to close it’s modal child window, because this will hand the browser process, because the JavaScript code is jammed. Remember modal dialogs freeze their parent window? :)


You can enhance this logic, and check if there are child windows opened, and if there are, prompt the user and ask him if he is sure that he wants to leave the website. Actually, I’ve done this. You can achieve by adding this script to the main page:

    function ThereAreOpenedChildWindows() {
for (var i = 0; i < window.childWindows.length; i++) {
if (!window.childWindows[i].closed) {
return true;
}
}
return false;
}

function PromtUserClosingAllWindows() {
if (ThereAreOpenedChildWindows()) {
window.event.returnValue = "Leaving this page will close all child windows. Continue?";
}
else
return;
};

Note: I tested this code on IE and Chrome. It only works on IE, but I was OK with it since this is what we needed. There is no guarantee that this code will work on different browsers.


And register to the onbeforeunload event of the body:

<body onunload="PromtUserClosingAllWindows()">

That’s it! Hope this post was helpful, good luck closing child windows :)

No comments:

Post a Comment