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.
|