6.6. Communicating with a New Window

NN 2, IE 3

6.6.1. Problem

You want to access the subwindow and its document from scripts in the main window.

6.6.2. Solution

Provided you preserve the reference to the subwindow returned by the window.open( ) method, and if the content of the subwindow is served by the same domain and server as the main window document, you can access any property or method that you are able to from scripts within the subwindow.

The following complete HTML page contains two functions that create a new window and populate its content with dynamically written content:

<html>
<head>
<title>A New Window</title>
<script type="text/javascript">
// global variable for subwindow reference
var newWindow;
// generate and fill the new window
function makeNewWindow( ) {
    // make sure it isn't already opened
    if (!newWindow || newWindow.closed) {
        newWindow = window.open("","sub","status,height=200,width=300");
        // delay writing until window exists in IE/Windows
        setTimeout("writeToWindow( )", 50);
    } else if (newWindow.focus) {
        // window is already open and focusable, so bring it to the front
        newWindow.focus( );
    }
}
function writeToWindow( ) {
    // assemble content for new window
    var newContent = "<html><head><title>Secondary  Window</title></head>";
    newContent += "<body><h1>This is a script-created window.</h1>";
    newContent += "</body></html>";
    // write HTML to new window document
    newWindow.document.write(newContent);
    newWindow.document.close( ); // close layout stream
}
</script>
</head>
<body>
<form>
<input type="button" value="Create New Window" onclick="makeNewWindow( );" />
</form>
</body>
</html>

6.6.3. Discussion

The example in the Solution points out an important aspect of referencing a newly created window. Internet Explorer for Windows tends to race ahead of script execution (presumably to improve performance). The downside of this feature is that in the case of a newly created external object, a reference to the new object may not be valid when the subsequent statements execute in the shadows. To prevent this race-ahead execution from causing script errors, you need to place statements referencing the object in a separate function that begins executing after the current function thread completes. The setTimeout( ) method is the mechanism that assists in this task.

How much time you build into the setTimeout( ) delay is not important. The 50 milliseconds shown in the example is an exceptionally small amount of time (from the user's perspective), but it's enough to keep processing in order, and allow global variable references to the new window to be valid when needed. You can use this same technique for any kind of immediate access to a newly created window. But if, for example, you have two distinct user actions (e.g., two buttons)—one to create the window and one to populate it—you don't need the setTimeout( ) because the second button's event handler function will be executing in a separate thread anyway.

Some versions of IE for Windows are particularly sensitive to potential cross-domain security breeches. Moreover, the results can be different when the main page is hosted on a local hard disk (for testing) and a web server (for deployment). You'll know if you're having the problem when a reference to the subwindow or one of its properties results in an "Access is denied" script error.

Because a subwindow reference returned from the window.open( ) method is an object reference (with no string equivalent), you cannot pass this reference between pages that occupy the main window. In other words, do not expect to open a subwindow from one page and have a script in a subsequent main window page be able to reference it. The only possible workaround is to display your main window document in a frame of a frameset (with the other frame hidden if you don't want the user to see the frames). When you create the new window, copy the returned reference to a global variable either in the frameset (parent window) or the other child frame. A new visible document in the main window can then read that global variable to obtain a reference to the subwindow.

Regard a reference to a subwindow just like any window or frame reference. Any global variables defined in the subwindow's document scripts are accessible from the main window in the subwindow's global variable space:

var remoteValue = newWind.someVar;

Access to the document's contents goes through the document object of the subwindow, as in the following examples:

var remoteBody = newWind.document.body;
newWind.document.getElementById("myTextBox").value = "fred";

Adjusting the URL of the subwindow is just like doing the same for the main window, but with the leading subwindow reference:

newWind.location.href = "yetAnotherPage.html";

Be careful when you start loading new documents into either the main or secondary window, however. The only error-free way to close a subwindow from a script in the main window is if the document invoking close( ) is also the document that opened the window. Plus, if your script or the user loads a document into the subwindow from a different server and domain, your main window scripts lose the ability to read the location object or any document content objects in the subwindow—all in the name of securing the browser from nefarious scripts capable of tracking surfing habits.

6.6.4. See Also

Recipe 6.7 to see how scripts in a subwindow talk to the main window; Recipe 10.5 for passing data between pages via frames.