The frames Collection

The last major element of the window object, aside from its descendant objects, is the frames collection. This collection exists to give a developer access to all of the frames in any frameset currently displayed in the browser.

The frames collection is indexed from 0 so that a three-frame frameset, like the one that follows, has three elements in the frames collection, numbered from 0 to 2. It's important to note that this three-element collection is only seen from the top-level window – more about this in a second.

Each frame is a window object itself, and each frame reference returns a reference to a window object. All we need is a reference to a window object to enable our use of the properties and methods we've spent the last few pages discussing. It shouldn't be surprising then that the frames collection allows us to control each frame in a frameset as if we're controlling a separate window. In fact, this is exactly what we're doing. Each element in the frames collection is a reference to a new window object.

Accessing Collection Members by Index and Name

For example, this code changes the URL of the bottom left-hand frame in the frameset above:

window.frames(1).navigate "http://bossman"

In the above example we're referencing the frame object we want 'by index' which means we're using a number that refers to the frame. We can also access members of the frames collection (and other collections) 'by name' if we've specified an ID or name attribute when we created the element of the collection. For example, if the frameset with an index of 1 was named leftHandFrame, we could also access it with this code:

window.frames("leftHandFrame").navigate "http://bossman.com"

These naming methods work identically – they both return a reference to the same frame.

As we'll see when we talk about scripting in chapter six, we also have the For Each construct available to us for use with collections. We use For Each to iterate through each element in a collection.

The Frame as a Window Object

Now back to that cryptic statement about the top-level window that I made a second ago… The only other confusing aspect about the frames collection also arises from the fact that each frame is a window object in its own right. Think about the world from the point of view of the frame in our example indexed with the number 1. It doesn't contain any additional frames (although it could – its page would need to contain a <FRAMESET> tag with one or more <FRAME> tags). No contained frames means that the frames collection of the frame(1) should be empty, and this is exactly what we see if we query the length property of the collection in code. Its own frames collection has zero elements, but the page containing it owns three frames.

So how do we access another frame from our code in frame(1)? Remember way back to the top and parent properties of the window object? These properties are the key to working with multiple frames in the browser object model. Before we can reference frame(0) or frame(2) from frame(1) we need to get a reference to the top-level window object so we can use its frames collection. This task is just as simple as using the code from frame(1):

parent.frames(0).method
parent.frames(2).method

In this case, since we're only moving up a single level, parent and top return a reference to the same window object.If we were to work with a set of nested frames, we'd see that top always returns a reference to the top-most window object, while parent just returns a reference to the window object that is immediately above itself.

Generally we'll stick to using parent instead of top to avoid problems when our pages are viewed from another site. If a user browses to our framed pages from another site that uses frames then top will return a reference to the top-level frame from the first site. In this instance, assuming that that top and parent are identical breaks our code.