[ Team LiB ] Previous Section Next Section

7.6 Assuring a Page Loads in its Frameset

NN 2, IE 3

7.6.1 Problem

You want a page bookmarked from a frame within a frameset to load within its frameset.

7.6.2 Solution

For a frameset that always consists of the same framed documents, include a script patterned on the one below in each frame's document. This solution includes a test for a peculiarity of the Netscape Navigator 4 browser described in the Discussion section:

var isNav4 = (navigator.appName =  = "Netscape" && 
    parseInt(navigator.appVersion) =  = 4);
if (top.location.href =  = self.location.href) {
    if (isNav4) {
        if (window.innerWidth != 0) {
            top.location.href="frameset12.html";
        }
    } else {
        top.location.href="frameset12.html";
    }
}

If a user has bookmarked a page with the previous script in it, the page will begin to load, but will then load the frameset that normally houses the page.

7.6.3 Discussion

The Navigator 4 issue affects the Windows version in particular. In that browser, when a user prints a frame, the page is automatically loaded into a temporary window of zero width. Scripts run when the page loads into that invisible window, so it's important to bypass the frameset-loading routine when the page is being printed or else you'll land in an infinite loop. If Navigator 4 is not among your target audience, you can simplify the script to just one branch:

if (top.location.href =  = self.location.href) {
    top.location.href="frameset12.html";
}

This script compares the URLs of the windows referred to as top and self. If they are the same, it means that the document is loading as the only one in the browser window. You'll have to tailor the URL assignment for each document containing this script so that the desired frameset loads.

For a more fluid frameset, where one or more frames changes in response to user action, you need more intelligence built into the scripts and documents. At the core, each page's document needs a script not only to load the frameset, but to convey the URL of the page that needs loading into one of the frames. For example, if a frameset contains a fixed navigation frame through a product catalog, and the content frame's document changes with each menu choice, you want a bookmark to one of the product frames to load the frameset with that product showing.

To make this intelligent frame loading proceed correctly requires scripts in each bookmarkable page and one in the frameset. Each page sends information about itself by way of a search string appended to the frameset page's URL; the frameset's script receives that information and loads the content frame accordingly.

Let's start with a content document. The script gets all of its information from the page itself, so you can write this script once as an external library and link it into each content page. Here is the library script, which runs as the page loads:

var isNav4 = (navigator.appName =  = "Netscape" && 
    parseInt(navigator.appVersion) =  = 4);
if (parent =  = window) {
    // Don't do anything if NN4 is printing frame
    if (!isNav4 || (isNav4 && window.innerWidth != 0)) {
        if (location.replace) {
           // Use replace( ), if available, to keep current page out of history
           location.replace("masterFrameset.html?content=" + escape(location.href));
        } else {
           location.href="masterFrameset.html?content=" + escape(location.href);
        }
    }
}

The current page's URL is attached to the URL of the frameset in the form of a name/value pair, just like a typical form submission search string. All browsers except some early ones apply the location.replace( ) method so that the current page won't be added to the browser's history. If the page were to be part of the history, a user clicking the Back button could get into an infinite backward loop because the button would never be able to go any earlier than this page.

Code for the frameset consists of two functions, one of which is triggered by the onload event handler of the <frameset> tag. The key supporting function converts the search string from the URL into an object whose property name is the name part of the name/value pair passed in the search string. The function also accommodates multiple name/value pairs embedded in the search string in case you wish to pass additional information to the frameset:

function getSearchData( ) {
    var results = new Object( );
    if (location.search.substr) {
        var input = unescape(location.search.substr(1));
        if (input) {
            var srchArray = input.split("&");
            var tempArray = new Array( );
            for (var i = 0; i < srchArray.length; i++) {
                tempArray = srchArray[i].split("=");
                results[tempArray[0]] = tempArray[1];
            }
        }
    }
    return results;
}

The onload event handler of the frameset invokes the following loadFrame( ) function, which reads the search string data and applies the URL to the content frame:

function loadFrame( ) {
    if (location.search) {
        var srchArray = getSearchData( );
        if (srchArray["content"]) {
            self.content.location.href = srchArray["content"];
        }
    }
}

This example uses the same frame name (content) as the property name in the name/value pair of the search string. Theoretically, you could generalize the loadFrame( ) function to assign the URL to the frame whose name arrives in the name/value pair. That design choice, however, places the burden of knowing the destination frame at the individual frame level. By leaving the specification to the frameset script, the destination frame's name is kept within the context of the affected frameset.

Assuming that the framesetting document contains a default URL for the content frameset (i.e., for when the visitor first arrives to the frameset), that default page stays in place if no search string containing a content property name arrives with the frameset URL. If a search string accompanies the URL, the default page appears momentarily, until the passed URL is loaded into the frame.

7.6.4 See Also

Recipe 7.5 for a script that keeps your site from being encapsulated in someone else's frameset; Recipe 10.6 for more examples of passing data between pages via URLs.

    [ Team LiB ] Previous Section Next Section