ColdFusion, WordPress, Flash & other web things


Cross-window Javascript communication

This solution is now officially obsolete. A much nicer and simpler solution is available here.

This is a solution to a problem that I’ve come accross several times before but never really had a go at solving. This time, I just had to get it right or we would have had to use a nasty system of hidden frames. Yuk!

The problem

Right, so you have this page you want to open in a popup and you want to be able to call JS functions defined in the popup from the main window. Nothing revolutionary here. When you create a popup with the window.open method, you can specify a name for the new window object and use it to reference the popup from the main window.

// Create a new popup window
var popupWin = window.open( url, "popupWin" );

// To call functions defined in the popup:
popupWin.doSomething();

Now, when the user navigates to another page in the main window, the reference to the popup window object is lost and you cannot communicate with the popup anymore. This can be problematic if you need the popup to stay open. You can re-create the popup with the open method but this always reloads the page and when your popup is a music player, you get a very rubbish user experience indeed.

So, using the music player as an example, what we would need is a way to maintain a persistent link between the player and its opener so that the main window can call methods to control the player.

The solution

What we need to do is get the popup to broadcast its existence to the main window. Fortunately, the popup is not as forgetful as our main window and still has a reference to its creator: self.opener. We can get the popup to remind the opener at regular intervals with this code:

function notifyOpener() {
	if(self.opener || !self.opener.popupWin) self.opener.popupWin = self;
}

setInterval( notifyOpener, 200 );

This ensures that any page opened in the main window gets notified. The interval time should be short enough for the window to be notified before the user gets a chance to click any links. Now, the main window can call functions of the popup:

// Initialise popup pointer
var popupWin = null;

function doSomething() {
	if( popupWin && !popupWin.closed ) {
		popupWin.doSomething();
	}
}

Initialising the popupWin variable ensures that the script doesn’t break if the popup is closed. Before making the call to the popup, we can also check the closed property of the popup window. When true, this property indicates that the popup window was closed by the user (hardly rocket science, heh?).

So, if we combine the code above with the open routine we get this for the main window:

// Initialise popup pointer
var popupWin = null;

function openPopup() {
	var url = "the_url_to_your_popup.htm"
	if( !popupWin || popupWin.closed ) {
		popupWin = window.open( url, "popupWin" );
	} else popupWin.focus();
}

function doSomething() {
	if( popupWin && !popupWin.closed ) {
		// The popup is open so call it
		popupWin.doSomething();
	} else {
		// The popup is closed so open it
		openPopup();
	}
}

And in the popup:

function notifyOpener() {
	if(self.opener || !self.opener.popupWin) self.opener.popupWin = self;
}

setInterval( notifyOpener, 200 );

self.focus();

function doSomething() {
	alert("I'm doing something");
}

That’s it. Well, actually no, there is one more thing: the popup script will start throwing errors if the user closes the main window or navigates to a page on a different domain. To prevent any unnecessary errors, we add the following lines to the popup script:

function handleError() { return true; }
window.onerror = handleError;

Download an example

22 comments

Pages: [3] 2 1 » Show All

  1. #22: music Says:

    Thanks, I enjoyed your post immensely. It’s nice to see someone writing something worth reading

  2. #21: ????? ????????? Says:

    ??????? ??? ??? ? ????, ?? ????? ???? ??? ????? ?????? :)

Pages: [3] 2 1 » Show All

Leave a comment