Chapter 12. Scripting Frames

The previous two lessons focused on the window object — a programmatic representation of the browser window. The browser window typically contains one web page, and thus only one window object. The <frameset/> element, however, allows web developers to divide a browser window into two or more smaller window panes.

Each of these panes is itself a browser window, and as such has a full-fledged window object. In fact, some browsers allow you to move and resize an individual frame with the moving and resizing methods you learned in Lesson 11 (it is highly recommended that you do not use these methods on a frame).

Arguably the most important aspect of dealing with frames as a JavaScript developer is accessing code and objects across frames. Over the course of this lesson you'll see many similarities between cross-frame scripting and cross-window scripting.

FRAMES AND THE WINDOW OBJECT

The easiest way to delve into frame scripting is with a demonstration. The first item you'll look at is the frameset page. Its HTML is as follows:

<html>
<head>
    <title>Frameset Page</title>
</head>
<frameset rows="50%,*">
    <frame name="frmTop" src="frame_top.htm" />
    <frame name="frmBottom" src="frame_bottom.htm" />
</frameset>
</html>

This is a simple frameset page: It divides the page into upper and lower regions. The frame on top, named frmTop, loads the frame_top.htm page into it, and the bottom frame, frmBottom, loads frame_bottom.htm. Make note of each frame's name, as they are key when you are accessing them through script.

The browser creates a hierarchy of three window objects when it loads this frameset page. The first window object belongs to the main window — the one that loaded the frameset page. This is referred to as the parent window.

The second and third window objects are child objects of the parent window. The first of these is created for the first frame in the frameset (frmTop), and the next is created for the frmBottom frame. Figure 12-1 is a visual representation of the relationship and hierarchy of these three window objects — a family tree, if you will.

Figure 12-1

Figure 12.1. Figure 12-1

This illustration also doubles as a guide to communicating between frames. You can see that the parent window has a direct relationship to its children. So it is safe to assume that accessing the children from the parent in JavaScript is done directly. You access a child frame's window object much as you access an opened window's window object. In Lesson 11 you learned that the open() method returns the window object of the newly created window, and that you can assign that object to a variable, like this:

var newWindow = open("");

Retrieving a frame's window object is even simpler, as the browser automatically creates a variable using the name of the frame as the variable's identifier. So to call the alert() method of the top frame from the frameset page, you write code like this:

frmTop.alert("Hello, Top!");

The same principle is used for accessing the bottom frame. The following bolded code adds a <script/> element to the frameset page:

<html>
<head>
    <title>Frameset Page</title>
    <script type="text/javascript">
    function sayHello(message) {
        alert(message);
    }
    </script>
</head>
<frameset rows="50%,*">
    <frame name="frmTop" src="frame_top.htm" />
    <frame name="frmBottom" src="frame_bottom.htm" />
</frameset>
</html>

Inside the <script/> element is a simple function called sayHello(). It accepts one argument that is then displayed in an alert box. There is nothing in this main page that calls this function; instead, it is called from within the HTML pages loaded into each frame.

Think back to Lesson 11, and remember how child windows access their parent with the opener keyword. Accessing the main frameset window object from a page loaded into a frame is just as simple; the difference is that instead of using opener, you use the parent keyword.

The following is the source code for frame_top.htm. Focus on the bold line:

<html>
<head>
    <title>Top Frame</title>
    <script type="text/javascript">
    parent.sayHello("Hello from Top!");
    </script>
</head>
<body>

</body>
</html>

This single statement uses the parent keyword to access the parent's window object and calls sayHello(). When the browser loads this page into the top frame, it executes this line of code, which results in an alert box displaying the text "Hello from Top!"

The source code for frame_bottom.htm is similar:

<html>
<head>
    <title>Bottom Frame</title>
    <script type="text/javascript">
    parent.sayHello("Hello from Bottom!");
    </script>
</head>
<body>

</body>
</html>

The code in this page goes through the same process. The only difference is the message that the alert box displays when the browser loads this page and executes the JavaScript code.

As you can see from these examples, scripting between the parent window and child frames is very much like scripting between parent and child windows. The only difference is in how you refer to the child and parent window objects. But what if you want to script between two individual frames?

Using JavaScript to script between frames is slightly different from, but almost as straightforward as, using it to script between parent and child. Refer back to Figure 12-1 and take note of how, in the illustration, each window object is linked. Notice that there is no direct link between the two child frames; instead, the only thing linking them is the parent window. This is indicative of how you access the code and objects of one child frame from its sibling frame.

Let's say you want to access the top frame and call its alert() method from the bottom frame. To do this you must first reference the parent window with the parent keyword, and then use frmTop, the name of the top frame. The following code shows you what this might look like:

parent.frmTop.alert("Called from frame_bottom.htm");

Here the parent keyword is used to refer to the window object of the main page. Then the top frame's window object is accessed via the frame's name, frmTop, and the alert() method is called. This has the result of showing an alert box, but it isn't evident that the alert box belongs to the frmTop frame. Modify the JavaScript in frame_bottom.htm to write some text in the top frame. Following is a new version of frame_bottom.htm:

<html>
<head>
    <title>Bottom Frame</title>
    <script type="text/javascript">
    parent.frmTop.document.write("Hello from frame_bottom.htm");
    </script>
</head>
<body>

</body>
</html>

Here, the bold line of code is the only thing that changes from the previous line of code. It uses the parent object to access the frmTop object. From there this code uses frmTop's document object to write some text to the page. The result of this code can be seen in Figure 12-2.

Figure 12-2

Figure 12.2. Figure 12-2

Despite the extra step of using the parent object, scripting between two frames is still a straightforward process. You simply navigate through the tree to get to the object you want.

There is also an object called top, and it gives you direct access to the topmost page's window object — the main frameset page. This is extremely helpful when a page has nested framesets, as shown in Figure 12-3.

Figure 12-3

Figure 12.3. Figure 12-3

In this diagram frmTop is itself a frameset, dividing the frame into two frames, frmA and frmB; frmTop is now a parent of frmA and frmB. If code within frmA accesses an object in frmBottom, the code to get from frmA to frmBottom looks like this:

parent.parent.frmBottom

Here the first parent refers to frmA's parent, which is frmTop. The next parent references frmTop's parent, the main frameset page. From this object you can directly access frmBottom. The more nested framesets you add, the more tedious it becomes to script between frames. The top object helps you avoid having to climb the tree to the topmost page. Instead of typing parent.parent.frmBottom, you simply type this:

top.frmBottom

It's a shortcut to get to the top of the window object tree if you need it. You'll see this object used in the next section.

TRY IT

In this lesson, you learn how to script frames. You learn how the browser automatically creates a variable to allow access to a frame. You also learn about the parent and top objects that allow you to navigate the window object hierarchy created by framesets.

Lesson Requirements

For this lesson, you need a text editor; any plain text editor will do. For Microsoft Windows users, Notepad is available by default on your system or you can download Microsoft's free Visual Web Developer Express (www.microsoft.com/express/web/) or Web Matrix (www.asp.net/webmatrix/). Mac OS X users can use TextMate, which comes as part of OS X, or they can download a trial for Coda (www.panic.com/coda/). Linux users can use the built-in VIM.

You also need a modern web browser. Choose any of the following:

  • Internet Explorer 8+

  • Google Chrome

  • Firefox 3.5+

  • Apple Safari 4+

  • Opera 10+

Create a subfolder called Lesson12 in the JS24Hour folder you created in Lesson 1. Store the files you create in this lesson in the Lesson12 folder.

Step-by-Step

Take another look at Figure 12-3. Use it as a blueprint and create five web pages to use in framesets. The JavaScript in frmA will write text into frmBottom, and the JavaScript in frmB will call a function in frmTop that will call a function in the main window to write text in frmB.

  1. Open your text editor and type the following HTML:

    <html>
    <head>
        <title>Frameset Page</title>
        <script type="text/javascript">
        function writeInB(message) {
            frmTop.frmB.document.write(message);
        }
        </script>
    </head>
    <frameset rows="50%,*">
        <frame name="frmTop" src="frame_top.htm" />
        <frame name="frmBottom" src="frame_bottom.htm" />
    </frameset>
    </html>

    Save it as frameset_main.htm. This is the main frameset page that is loaded into the browser, and it divides the screen into top and bottom frames. The JavaScript in this page defines a function called writeInB(). It'll access the frmB frame (a child in frmTop) and write a message in it using the document.write() method.

  2. Open another instance of your text editor and type the following HTML:

    <html>
    <head>
        <title>Top Frame</title>
        <script type="text/javascript">
        function callParentFunction() {
            parent.writeInB("Calling from frmTop");
        }
        </script>
    </head>
    <frameset cols="50%,*">
        <frame name="frmA" src="frame_a.htm" />
        <frame name="frmB" src="frame_b.htm" />
    </frameset>
    </html>

    Save it as frame_top.htm. This is another frameset page that loads in the top frame of frameset_main.htm. It divides the available screen into two columns. The JavaScript in this page defines a function called callParentFunction(). It calls the writeInB() function defined in frameset_main.htm.

  3. Open another instance of your text editor and type the following HTML:

    <html>
    <head>
        <title>Bottom Frame</title>
    </head>
    <body>
        <h1>Bottom Frame</h1>
    </body>
    </html>

    Save this file as frame_bottom.htm. This page loads in the bottom frame in frameset_main.htm. This page does not contain any JavaScript.

  4. Now you need to write the HTML for the pages loaded into the frame_top.htm frameset. So once again, open another instance of your text editor, and type the following HTML:

    <html>
    <head>
        <title>Frame A</title>
        <script type="text/javascript">
        top.frmBottom.document.write("Hello from frmA!");
        </script>
    </head>
    <body>
        <h1>Frame A</h1>
    </body>
    </html>

    Save this as frame_a.htm. The JavaScript in this page does not define a function, but it does use the top object to refer to the frameset_main.htm's window object. Then it accesses the frmBottom object and writes a message to that frame.

  5. The final HTML file you need to write is frame_b.htm. Once again, open a new instance of your text editor and type the following HTML:

    <html>
    <head>
        <title>Frame B</title>
        <script type="text/javascript">
        parent.callParentFunction();
        </script>
    </head>
    <body>
        <h1>Frame B</h1>
    </body>
    </html>

    Save it as frame_b.htm. The JavaScript code in this file uses the parent object to access the window object of frame_top.htm, and it calls the callParentFunction() function defined in that page.

  6. Open the frameset_main.htm file in your browser. You should see something similar to Figure 12-4.

    Figure 12-4

    Figure 12.4. Figure 12-4

To get the sample code files, you can download Lesson 12 from the book's website at www.wrox.com.

Note

Please select Lesson 12 on the DVD to view the video that accompanies this lesson.

Figure 12-4
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.141.75