Previous Page
Next Page

Forcing a Site into a Frame

If you have a large site, with numerous pages that you want inside a frame, the method described on the preceding page can easily become unwieldy. Here's a method that works better for larger sites. Script 5.5 shows the frameset, which also calls the JavaScript, shown in Script 5.6 (detailed below). Figure 5.6 shows our page by itself, and Figure 5.7 shows how we intended our site to look. Not shown is the simple HTML page that makes up the left-hand navigation bar in Figure 5.7, or the equally simple HTML pages that make up the content frames. The latter call the JavaScript (just in case they are loaded directly), in the same way as Script 5.5.

Script 5.5. The frameset page calls the external JavaScript file.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
     <title>Site Frameset</title>
     <script language="javascript" type="text/javascript" src="script03.js"></script>
</head>
<frameset cols="30%,70%">
     <frame src="left3.html" name="left" id="left" />
     <frame src="frame3a.html" name="content" id="content" />
</frameset>
</html>

Script 5.6. This JavaScript forces the site we want into the frame we want.

var framesetPage = "frameset3.html";
var currPage = justTheFilename (self.location.pathname);
if (top.location == self.location && framesetPage != currPage) {
     self.location.replace(framesetPage + "?" + currPage);
}
window.onload = chgFrame;
function chgFrame() {
     if (top.location == self.location && document.location.search) {
        var linkURL = justTheFilename (document.location.search);
        var contentWin = document.getElementById ("content").contentWindow;
        var currURL = justTheFilename (contentWin.location.pathname);

        if (currURL != linkURL) {
           contentWin.location.replace (linkURL);
        }
     }
}

function justTheFilename(thisFile) {
     if (thisFile.indexOf("/") > -1) {
        thisFile = thisFile.substring (thisFile.lastIndexOf("/")+1);
     }

     if (thisFile.indexOf("?") == 0) {
        thisFile = thisFile.substring(1);
     }

     return thisFile;
}

Figure 5.6. Here's our page outside the frame.


Figure 5.7. But here's how we really want it to look.


To force a site into a frame:

1.
var framesetPage = "frameset3.html";
var currPage = justTheFilename
  (self.location.pathname);



We start off by creating and setting two variables: framesetPage and currPage. The former is the frameset page that we always want to load overall, so that's hard-coded to frameset3.html. The latter is the name of the HTML page that called this external JavaScript file. It needs to be calculated, as JavaScript doesn't have a built-in function that does this (although it should!). We'll use the justTheFilename() function to do that, as explained in step 10.

In this step, that function gets passed self.location.pathname (a variable that holds that part of a URL that comes after the domain name). For example, if you are viewing http://www.peachpit.com/index.html, self.location. pathname is /index.html. If you are at http://www.peachpit.com/books/index.html, self.location.pathname is /books/index.html. In either case, all we want is index.html, so that's what justTheFilename() will calculate and return, and that's what will be stored in currPage.

2.
if (top.location == self.location && framesetPage != currPage) {
  self.location.replace (framesetPage + "?" + currPage);
}



Now we do the usual check to see if top.location is the same as self.location that we've done previously, with one thing added: a check to see if we're currently on the frameset page. If we are, that's great; we don't need to reload anything. But if currPage isn't the frameset, something's wrongso we need to reload this page, going to the frameset page, and passing currPage in the bargain so that it ends up in the content frameset.

3.
window.onload = chgFrame;



The onload handler is here because we want every page that uses this external JavaScript file to call the chgFrame() function.

4.
function chgFrame() {



This function checks to see if (a) it's the frameset page and (b) there was a question mark in the URL followed by a file name. If that's the case, that file needs to be loaded into the content frame.

5.
if (top.location == self.location && document.location.search) {

Once again, we're doing the usual check to see if top.location is the same as self.locationin this case, if the two are equal, we know we're in the frameset. After that, we look at document.location.search, another built-in field that will contain everything in a URL from a question mark (if one exists) to the end. If there's no question mark, document.location.search has no value, and we get kicked out of this function.

6.
var linkURL = justTheFilename (document.location.search);



This is the first of three variables we'll need to set before we load in a new content frame. The first, linkURL, is the file to load in the content frame. The linkURL field is set by calling justTheFilename() and passing in document.location.search.

7.
var contentWin = document.getElementById("content"). contentWindow;



The contentWin variable needs to contain what JavaScript knows about the content frame. Set it by looking for the id content, taking its result (which will be a frame), and then getting contentWindow of that framewhich is the page loaded into that frame.

8.
var currURL = justTheFilename (contentWin.location.pathname);



The currURL variable is set here to the current content frame page, that is, the current HTML page loaded in the content frame. That is done by calling justTheFilename(), this time passing it contentWin.location.pathname, and storing the result.

9.
if (currURL != linkURL) {
   contentWin.location.replace (linkURL);
}

At this point, we could reload the content page, as we've got everything we needbut we can make things smarter by adding one more step. Why bother reloading the content page, if what we're going to load is already there? Here's where we check to see if currURL is equal to linkURL. If it is, we're on the right page already, so don't do anything. If it isn't, call that same old replace(), and we're done.

10.
function justTheFilename(thisFile) {
  if (thisFile.indexOf("/") > -1) {
     thisFile = thisFile.substring (thisFile.lastIndexOf ("/")+1);
  }

  if (thisFile.indexOf("?") == 0) {
     thisFile = thisFile.substring(1);
  }

  return thisFile;
}



All that's left now is the justTheFilename() function. This function takes in a string and tries to clean it up and turn it into a filename. First, we check to see if it contains a /. If it does, then we look for the last / in the filename (note that lastIndexOf), resetting the filename to be everything after it. Then, we look for a question mark. If it's the first character in the filename (i.e., at position zero), then we reset the filename to be everything from position one to the end. The filename is returned to wherever it was called.


Previous Page
Next Page