infimum.dk > DHTML F.A.Q. > Windows in Javascript

Javascript windows

One of the uses of Javascript in browsers, is to open, manipulate, and close browser windows.

Index

Opening a new window

There are two ways to open a new window: HTML and Javascript

New windows with HTML

In HTML, you can make a link open a new window. You use the "target" attribute:

<a href="foo.html" target="windowName">about foos</a>

If a window or frame named "windowName" already exists, the page "foo.html" is loaded into it. Otherwise, a new window is created first.

The window name must be a single word (only letters, digits and underscore and cannot begin with a digit). There are four predefined targets: "_blank", "_self", "_parent", and "_top". Their meanings are:

_blankalways opens a new window.
_selfalways opens in the current window or frame.
_parentopens in the parent frame, if any, otherwise as _self.
_topopens in entire browser window, even if there are frames.

New windows with Javascript

In Javascript, you can simulate a click on the above link with the code:

window.open("foo.html","windowName");

Since "window" is a reference to the global object, the function is also a global variable, and can be referred to by just "open" (unless another variable with the same name is in the scope). It is traditionally written out as "window.open", which helps to distinguish it from "document.open". In HTML event handler attributes (e.g., "onclick"), the "document.open" function is directly available as "open". This hides the global "open" variable, so the "window" prefix is necessary to open a new window.

What makes the "window.open" function is attractive, is the optional third argument which can control how the new window looks (size, position, whether there are scrollbars or titlebars, etc.).

window.open("foo.html","windowName", "width=200,height=200,scrollbars=no");

The third argument, the "window configuration" is a string. It contains a comma-separated list. There should not be any spaces around the commas or anywhere else in the string. Some browsers, most notably Netscape 4, fails to work if there are spaces in the config string.

Each element of the list is on the form "<config option>=<value>". Each browser supports a different set of configuration options, but there are some that most browsers agree on:

NameTypeDescriptionExample
width number Width, not including chrome (in pixels) width=640
height number Height, not including chrome (in pixels) height=480
left number Horizontal position wrt. screen (pixels) left=0
top number Vertical position wrt. screen (pixels) top=0
titlebar boolean Window has titlebar titlebar=no
menubar boolean Window has menubar menubar=yes
toolbar boolean Window has toolbar (e.g., back button) toolbar=yes
location boolean Window has location bar location=no
scrollbars boolean Window has scrollbars scrollbars=yes
status boolean Window has statusbar status=yes
resizable boolean Window can be resized resizable=no

The width and height is the inner size of the window, not including title bar or status bar. In Netscape 4, the menu bar is included in the specified size.

For more information on browser specific window configuration options, check either Netscape's or Microsoft's online documentation.

A so-called "chromeless window" is one where all the bars have been turned off.

Live example of code that opens a new window:
window.open(location.href,"myWindow", "height=300,width=300,menubar=no,status=no")
(if your browser allows)

Opening a new window also gives it focus.

Sizing and positioning windows

The window configuration options allows you to decide the initial size and position of a window. There are a few dangers with this, that one must be aware of.

Most browsers' standard security settings will not allow you to create a window that is less than 100 pixels wide or high.

It is dangerous to decide the size or position of the window based on the size of the screen, for several reasons:

Browser
Argle-bargle glop glyf!
Popup
Argle-bargle glop glyf!
What the author intended.
Browser
Argle-bargle glop glyf!
Popup
Argle-bar
glyf!
Popup in MDI
Relative to application
Browser
Argle-bargle glop glyf!

gle glop
Popup in MDI
Relative to screen
Browser
Argle-bargle glop glyf!
Popup
Argle-bargle g
glyf!

lop
Two monitors with different resolutions
Browser
Argle-bargle glop glyf!
Popup
Argle-bargle glop glyf!
Large font

In summary, make the new window the size it needs to be, and let the browser place it. Also make sure that the window is resizable

Links that open windows

A link is meant to refer to a new page. That makes links an obvious place to put code that opens a new page in a new window. There is a simple way to do this, that still allows access to the page for people without Javascript.

<a href="foo.html" target="windowName" onclick="window.open(this.href,this.target,'width=300,height=300'); return false;">about foos</a>

The important part is to have a valid href value, so that the link works even without Javascript. If Javascript is available, the advanced window opening code (with window configuration) takes over, and the return false stops the normal operation of the link. Links that uses "href='#'" or similar, should be avoided.

Problems with opening windows

Opening windows is not as safe as it used to be. Pages opening unwanted windows with advertisements have made people distrust new windows. Many users have installed software that prevents unwanted windows from opening.

Such popup blockers work in many different ways, which makes it hard to say anything definite. Some examples:

In the face of such diverse and unpredictable opposition, anybody trying to open a window should be prepared for it to fail. And it can fail silently, visibly, or irrecoverably. Some are of the opinion that window.open is no longer safe enough to use for anything important.

Referencing windows

In order to manipulate other windows, or communicate with them, you need to have a reference to the window object.

Referencing new windows

The "window.open" function returns a reference to the new window, or to the old window, if it was already open. It is important to keep this reference in order to communicate with the new window, or to close it again.

var myWindow = window.open("foo.html","windowName","resizable=yes");

Referencing existing windows

A new window gets a reference to the window that opened it in the opener property of its own window object.

Previous calls to window.open have returned references to the windows. They should be remembered for later reference.

Calls to window.open with the same window name as an already existing window, loads the URL into that window and gives a reference to the window back. The window isn't given focus, its opener property isn't changed, and a third argument to window.open is ignored. You can use the focus method to give the window focus manually.

var oldWin = window.open("url.html","oldName"); oldWin.focus(); // give focus

Moving and resizing windows

When you have created a window, you can use Javascript to move it or resize it.

Moving windows

A window object has two methods for moving it: moveTo and moveBy. Both take two numbers as arguments.

The first function moves the window to the specified coordinates, measured in pixels from the top left corner of the screen. The first argument is the horizontal, or X, coordinat, and the second is the vertical, or Y, coordinate.

The second method changes the current coordinates by the given amounts, which can be negative to move the window left or up.

Not all browsers allow you to move a window. A browser with a tabbed interface has one window in each tab, and cannot move or resize them individually. A browser with MDI (e.g., Opera) can only move the windows inside the parent application's window, and only if the document window isn't maximized.

window.moveBy(-10,20);

Resizing windows

Similar to the methods for moving, there are two methods for resizing a window: resizeTo and resizeBy. Like for moving, they either set the size absolutely or modify the size relatively to the current size.

Most browsers' standard security setting will not let you resize a window to less than 100 pixels in any direction.

window.resizeBy(100,-100);

Closing windows

Closing a window is simple when it works. All windows have a close method, so you can attempt to close any window you have a referene to.

myWindow.close();

However, not all windows can be closed without asking the user for permission. This is to protect the user from accidentally losing his browsing history.

The cases where you can close a window without a warning are:

Checking whether window has been closed

Given a reference to a window, it is possible to see whether the window has been closed.

if (myWindow.closed) { /* do something, e.g., open it again */ }

Browsers will generally not allow access to another window's properties, if it contains a page from a different domain. In some browsers, this even includes the closed property.

Cross window/frame scripting

All Javascript is executed in the scope of one window, the one containing the call to the code in its document. Code in one window can open and close other windows, and it can also access and change the documents of other windows.

Accessing other windows or frames

To access another HTML document or the window it lives in, one needs a reference to that window.

As stated above, when opening a window with window.open, a reference to the new window is returned.

Frames inside a window or frameset can be accessed through the global "frames" collection.:

var otherWindow = frames["theOtherFrame"];

Global window/frame references are:

window, self the current window/frame
parent the immediate parent window/frame of the current frame.
top the topmost frame of the browser window.
opener the window or frame that opened this browser window.
frames["frameName"] the frames/iframes contained in this frameset/page.

Accessing global variables of other pages

Each page has its own Javascript environment with its own global variables. These are properties of the window object.

If we have a frameset with two frames ("left" and "right"), and our code in the "left" frame wants to access a global variable of the "right" frame, the procedure is:

parent.frames["right"].rightGlobal = 42;

If we want to change the color of the element with id="foo" in the "right" frame, we write:

parent.frames["right"].document.getElementById("foo").style.color="red";

For a larger example, assume we have a frameset with the two frames "left" and "right". In the left frame, we have another frameset with the frames "topframe" and "bottom" (it's not called "top", since one should avoid calling frames the same as a property of the window object or a global variable). In the bottom frame, a window is opened using Javascript. A reference to the window object is stored in the global variable "myWindow". In the new window is a document with an iframe called "inner".

We can visualize it like this:

top
bot
right
inner
MyWindow

The blue border represens the "left" frame and the black border is the original frameset.

To access across several different frames and windows, you simply put the small steps together.

If code in the "right" frame needs to set a global variable in the "inner" iframe, the code is simply:

self.parent.frames['left'].frames['bottom'].MyWindow.frames['inner'].varName = 42

The initial self isn't necessary, and is only included for completenes. The color of a part of the path represents the element in the display above that it points to.

If code in the "inner" iframe wants to write a variable in the "right" frame, the steps are just the opposite:

self.parent.opener.parent.parent.frames["right"].varName = 42;

See a . Press the button in the bottom frame to open the second window. (Example opens windows, which can be stopped by popup-blockers). When done, .

Calling functions across frames/windows

You can access variables of other windows, including those holding functions. A special note about calling such functions is needed.

Function values in Javascript are closures. They contain the references to the variables that occur in the function, so moving a function to another document, or calling it from another document, will not change what the variables in the function refer to.

Assume again that we have a frameset with the two frames "left" and "right". In the "right" frame, we have declared a global function:

function foo(color) {document.body.style.backgroundColor = color;}

If we call this function from some Javascript in the left frame, the code is:

parent.frames["right"].foo("red");

It will still change the background color of the document in the right frame, since the variable "document" in the function closure always refer to the global variable of the right frame.

If we move the function to the left frame, by assigning it to global variable of the left frame, and then call it, the code is:

var globalFoo = parent.frames["right"].foo; globalFoo("red");

This still turns the right frame red, not the left frame. The function itself doesn't care where it is, it always works the same.

One thing that does change when you move a function to somewhere else, is the value of the this keyword. Assume the above function had been written as:

function foo(color) { this.document.body.style.backgroundColor = color; }

Then moving it to a global variable of the left frame would let it change the left background. The this keyword would then point to the left frame's window object.

When handling functions from different windows, it is important to remember which function comes from where. It is possible to have two functions with identical definitions (e.g., function(){return x;}) that acts differently, because they take their global variables from different windows.


lrn@infimum.dk