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