The frameset

Ok, you're ready for part 1. This is where you find out how you want your frameset done. There is two options, a dynamically created frameset, or a regular frameset. A dynamically created frameset is where we use JavaScript to write the frameset to the document, thereby overriding already present HTML. The tree menu website is an example of a frameset created that way.

A regular frameset it created using plain HTML just like any other frames-enabled site. Both solutions has their pros & cons. I feel the dynamically created frameset is slightly more friendly to different browsers, but the regular frameset is easier to get running. This install guide will first create a regular frameset, and then show you how you can use that frameset for dynamic creation. If you already have a site with a frameset and want to incorporate the menu into it you can read the first part and skip the second.

Getting the frameset right

In this part we'll create a regular frames-enabled site, and then incorporate the menu into it. That way we'll have find out what the code behind a frameset looks like and then how the menu is inserted into it. It's not a difficult task to get right, but it might look slightly confusing at first.

What you first need to do is decide what your web-site should look like. This example I'll be using here is the same frameset that's used on the tree menu website. It's a three-split window with a top-frame for the site heading, a left frame for the menu and a right frame for site content. Since you're already here you know what this kind of setup looks like, and therefore it's easy to see what it'll look like when you're finished.

The HTML behind this kind of frameset looks like this (this is not exactly what I use, it's slightly altered for readability):

<FRAMESET ROWS="75,*">
  <FRAME SRC="heading.html" NAME="heading">
  <FRAMESET COLS="200,*">
    <FRAME SRC="menu.html" NAME="menu">
    <FRAME SRC="main.html" NAME="text">
  </FRAMESET>
</FRAMESET>

There's three frames: heading, menu and text. They all consist of regular HTML-documents with content. Now we want to use the JavaScript menu for this site, instead of the static HTML-document "menu.html". What we then need is another document which I've called "menu_empty.html", and we also need to split a frame into two frames. First, lets look at the document "menu_empty.html".

"menu_empty.html" is, as the file name says, an empty menu. To be exact it's an HTML-document with no content, only containing a document head and body. You can find the document in the directory "example-site" in the downloadable files. Here's the source code for it:

<html>
<head>
<title>[insert your title here]</title>
<style type="text/css" id="mtmsheet">
/* this is only a Mozilla quirk fix */
</style>
</head>
<body>
<!-- blank page -->
</body>
</html>

This document will be where the menu code later will write the actual menu, erasing any content already present in the document. Since the menu replaces any content you do not need to have any for people using a JavaScript-enabled browser, but having a link to a static HTML menu for those without JavaScript would be a good idea.

We also need the code, or else the menu won't work. All the code is kept in the file "code.html". As you might have noticed, if we want both "menu_empty.html" and "code.html" in our frameset there aren't enough frames. We have 4 documents (heading, menu, code & content (text)), but only three frames. Therefore we need to split one frame into two. It's the menu-frame that is split into two parts, one for the menu and one for the code. The code is kept in a frame with a size of 0 (zero) which means it'll be invisible or nearly invisible (some browsers make it invisible, some don't). Here's what our menu-frame looked like:

<FRAME SRC="menu.html" NAME="menu">

Now we split it so it becomes:

<FRAMESET ROWS="0,*">
  <FRAME SRC="code.html" NAME="code">
  <FRAME SRC="menu_empty.html" NAME="menu">
</FRAMESET>

Our whole frameset then looks like this:

<FRAMESET ROWS="75,*">
  <FRAME SRC="heading.html" NAME="heading">
  <FRAMESET COLS="200,*">
    <FRAMESET ROWS="0,*">
      <FRAME SRC="code.html" NAME="code">
      <FRAME SRC="menu_empty.html" NAME="menu">
    </FRAMESET>
    <FRAME SRC="main.html" NAME="text">
  </FRAMESET>
</FRAMESET>

That is actually all we need to do to have the frameset correctly set up. You can use this setup if you want to. Keep in mind that you'd like to add a NOFRAMES-section for users with browsers that don't handle frames.

If you want to keep this setup you can go on to the second part, setting options . You can also read on and get to know how this frameset can be created dynamically, making the site slightly more browser-friendly (in my opinion it makes a site more accessible to different browsers).

Frameset on-the-fly

Now we'll take our already existing frameset and make sure it's created by JavaScript. This will make a JavaScript-enabled browser show the frameset, while those without JavaScript-support will get a regular HTML-document. There are caveats to this solution too, just like there's pros " cons with a regular frameset. Lets look at how the frameset is created.

First we'll have a look at what our frameset already looks like (just in case you forgot):

<FRAMESET ROWS="75,*">
  <FRAME SRC="heading.html" NAME="heading">
  <FRAMESET COLS="200,*">
    <FRAMESET ROWS="0,*">
      <FRAME SRC="code.html" NAME="code">
      <FRAME SRC="menu_empty.html" NAME="menu">
    </FRAMESET>
    <FRAME SRC="main.html" NAME="text">
  </FRAMESET>
</FRAMESET>

Ok? What we'll do is take this frameset, put lots of document.write() -things around it, and then throw it all into the head of a regular HTML document. A browser running JavaScript will then read the web-page down to where this frameset is, find out that it should use the script, write the frameset to the document, and then it'll find a frameset in the document and show it to the user. Sounds easy and straightforward in theory, right? It's not all that difficult in practice either. First we'll put JavaScript-statements around the whole frameset so the browser writes it to the document. We use the document.write()-statement to do that. Here's how it'll look once finished:

document.write('<FRAMESET ROWS="75,*">');
document.write('  <FRAME SRC="heading.html" NAME="heading">');
document.write('  <FRAMESET COLS="200,*">');
document.write('    <FRAMESET ROWS="0,*">');
document.write('      <FRAME SRC="code.html" NAME="code">');
document.write('      <FRAME SRC="menu_empty.html" NAME="menu">');
document.write('    </FRAMESET>');
document.write('    <FRAME SRC="main.html" NAME="text">');
document.write('  </FRAMESET>');
document.write('</FRAMESET>');

document.write() is a JavaScript-statement telling the browser that what's between the single quotes should be written to the document. In other words we're telling the browser that this frameset we have here should be written to the document. The browser will then see the frameset and show it to the user (also known as "render the written frameset").

We're not finished yet, there's a couple of things I'd like to do first. One thing that's neat with JavaScript is the possibility of identifying the browser and then acting accordingly. The menu doesn't work perfectly will all variants of browsers you can find out there. Therefore, we identify what browser the user has, and make sure that only those who can run the menu get the code for it. The rest get a regular HTML menu through the document "menu.html". This is what I do on my site.

To make this possible we need to check what browser the user has, and then make sure we change what's written to the document. For this I use this code:

var MTMUsableBrowser = false;
// browser sniffing routine
browserName = navigator.appName;
browserVersion = parseInt(navigator.appVersion);
if(browserName == "Netscape" && browserVersion >= 3) {
  MTMUsableBrowser = (navigator.userAgent.indexOf("Opera") == -1) ? true : false;
} else if(browserName == "Microsoft Internet Explorer" && browserVersion >= 4) {
  MTMUsableBrowser = true;
} else if(browserName == "Opera" && browserVersion >= 5) {
  MTMUsableBrowser = true;
}

Yeah, I know it's got rather long lines. The lines ask the user's browser if it's Netscape (Navigator) version 3 or newer, Microsoft Internet Explorer version 4 or newer, or a version of Opera newer than 5.0. If the user says he/she is running Netscape (Navigator) version 3 or 4 we also check if the user runs Opera , since in that version its JavaScript support doesn't enable to run the menu. If the user has the right browser the variable "MTMUsableBrowser" is set to true. Otherwise it'll stay false, meaning we don't have a browser that can use the menu. We then alter the code that writes the frames "code" & "menu" to the document so that they're only written when MTMUsableBrowser is true. The code for this looks like this:

if(MTMUsableBrowser) {
  document.write('    <FRAMESET ROWS="0,*">');
  document.write('      <FRAME SRC="code.html" NAME="code">');
  document.write('      <FRAME SRC="menu_empty.html" NAME="menu">');
  document.write('    </FRAMESET>');
} else {
  document.write('    <FRAME SRC="menu.html" NAME="menu">');
}

What this code does is first to check the variable MTMUsableBrowser for true/false. If it's true it writes the frameset for the code and the menu, if not it writes a single frame with the document "menu.html". This is also done on this web-site. Lastly, what we need is to put all this code into the head of the HTML document. So, somewhere between <HEAD> and </HEAD> you will want to put this:

<SCRIPT TYPE="text/javascript">
var MTMUsableBrowser = false;
// browser sniffing routine
browserName = navigator.appName;
browserVersion = parseInt(navigator.appVersion);
if(browserName == "Netscape" && browserVersion >= 3) {
  MTMUsableBrowser = (navigator.userAgent.indexOf("Opera") == -1) ? true : false;
} else if(browserName == "Microsoft Internet Explorer" && browserVersion >= 4) {
  MTMUsableBrowser = true;
} else if(browserName == "Opera" && browserVersion >= 5) {
  MTMUsableBrowser = true;
}

document.write('<FRAMESET ROWS="75,*">');
document.write('  <FRAME SRC="heading.html" NAME="heading">');
document.write('  <FRAMESET COLS="200,*">');

if(MTMUsableBrowser) {
  document.write('    <FRAMESET ROWS="0,*">');
  document.write('      <FRAME SRC="code.html" NAME="code">');
  document.write('      <FRAME SRC="menu_empty.html" NAME="menu">');
  document.write('    </FRAMESET>');
} else {
  document.write('    <FRAME SRC="menu.html" NAME="menu">');
}

document.write('    <FRAME SRC="main.html" NAME="text">');
document.write('  </FRAMESET>');
document.write('</FRAMESET>');
document.close();
</SCRIPT>

Now you'll have a frameset that is created on-the-fly. The behaviour of this frameset can be summarized as follows:

Browsers without JavaScript
They use the rest of the document and display that. Therefore you should make sure it contains useful content for those browsers.
Browsers with JavaScript, but unable to run the menu
They are referred to the document "menu.html" which should contain a regular HTML links pointing to the documents found in the menu.
Browsers with JavaScript, and able to run the menu
They'll load and run the menu

If you want to see how this works, turn off JavaScript-support in your browser and reload the tree menu web site. For a look at a complete version of such a script there's a file called "javascript-frameset.html" available in the downloadable files' example-site directory.

Apart from this there isn't any magic needed, so now that you're finished with the frameset you can instead go on to part 2, setting options.