Articles | Creating A Java script Site Map |  back 

Introduction

Most Web sites use either simple hypertext links or image links to allow visitors to navigate around the various linked pages. These techniques, although tried and tested, do not necessarily give an indication of the breadth and depth of the site. Using the JavaScript described in this article, you will be able to include a visual representation of your site that can be dynamically expanded and collapsed, enabling visitors to quickly identify which parts of the site they wish to explore.

The site map could be written completely in HTML. But this would require a separate file, and therefore a separate request to the server, for each different view of the site map. This article describes how to implement a dynamic site map using images, frames and JavaScript, using just three files for Netscape Navigator, and for Microsoft Internet Explorer, a few additional, small images. The difference between treatments for the two browsers is due to Netscape Navigator's inclusion of undocumented and unsupported internal-gopher images that we can utilize.

Images

There are nine undocumented internal-gopher images which we can use in Netscape Navigator. You may have actually come across them when viewing a directory listing in Navigator:

If you are viewing this article in Microsoft Internet Explorer, the above images will not be displayed. Therefore, I have created the following .GIF images which can be used for Microsoft Internet Explorer:

The JavaScript detailed later in this article will use either the internal-gopher images or the alternate .GIF images, depending on which browser is being used.

Frames

To enable the site map to be dynamic and allow the contents to change without downloading any additional files from the server, we need to be able to redisplay/reload the document. Normally, this would overwrite all the contents of the document, including the JavaScript source code and, more importantly, the current values of the JavaScript variables. However, by using frames, we are able to store the JavaScript and JavaScript variables in the document that defines the frameset, i.e., the parent frame, and then only redisplay one or another of the child frames.

We'll use the following simple frameset definition contained within the sitemap.htm file:

<head>
<script language="JavaScript"><!--
/* this will contain the JavaScript detailed later */
//--></script>
</head>

<frameset cols="50%,*">
    <frame src="menu.htm" name="menu">
    <frame src="dummy.htm" name="content">
</frameset>

The sitemap.htm file also contains 99% of your JavaScript code.

When using JavaScript and a frameset definition in the same document, the JavaScript is usually held between the <head>and </head> tags. Otherwise, it is possible that neither the JavaScript nor the frameset will be processed correctly. The actual JavaScript is detailed in the rest of the article.

menu.htm, loaded into the menu frame, contains the 1% of the JavaScript necessary to request and display the site map. The background color is set to white, and whatever is returned from the parent frames ShowSiteMap() function is output to the document:

<body bgcolor="#FFFFFF">
<script language="JavaScript"><!--
document.write(parent.ShowSiteMap());
//--></script>
</body>

dummy.htm, loaded into the content frame, contains just the body tags to ensure that the background color is set to white:

<body bgcolor="#FFFFFF"></body>

The site map will be displayed in the menu frame. When a document is selected in the site map, it will be shown in the content frame. However, the JavaScript source code that enables the site map to be displayed will be held in the parent frame, i.e., the sitemap.htm file.

JavaScript

Below is the JavaScript source code that is required in the sitemap.htm file, as well as the contents of the site map file structure, i.e., the list of files and their connection with one another.

Microsoft Internet Explorer does not support the undocument internal gopher/ftp images used by Netscape Navigator. Therefore, we need to be able to identify which browser is being used. We define a boolean variable MSIE, with a value of true if the browser being used is Microsoft Internet Explorer, or false if it isn't:

<head>
<script language="JavaScript"><!--
if (navigator.appName == 'Microsoft Internet Explorer') var MSIE = 
true; else var MSIE = false;

The location of the current window is manipulated to obtain the path of the currently loaded document. The baseHREF will then be used later to give the absolute path to a file/menu in the site map and when changing the text displayed in the status bar. We'll assume that the site map is located in the fictitious directory: http://xxx.yyy.zzz/abc123/

The next three JavaScript functions -- File(), Menu() and Add() -- define the objects and methods used to create a tree hierarchy of files and menus.

The following File() function is actually a constructor function for File objects, as it will be invoked later using the new operator, e.g., new File('index.html','text').

function File(name,type) {
  this.name = name;    // the name of the file to appear in the site map
  this.type = type;    // image/binary/movie/text/sound/telnet/unknown/index
  this.path = baseHREF;// initial path, built when adding nested objects
}

The following Menu() function is a constructor function for Menu objects. It is similar to the File constructor, except that it has three additional properties, as well as Add, a user-defined method (e.g., Menu.Add() ) and Contents, a built-in JavaScript Object.

The use of Object() effectively creates an empty array. Unlike Array() it is fully supported in earlier releases of JavaScript.

The value of the open property is conditional on whether open parameter has a value or is null, i.e., a value has not been passed. This avoids the need to set each and every Menu object's open property; we can omit them, whereby they will default to false.

function Menu(name,ref,open) {
  this.name = name;    // the name of the file/menu to appear in the site map
  this.type = 'menu';
  this.path = baseHREF;// initial path, built up when adding nested objects
  this.ref  = ref;     // reference to the object being constructed 
  if (!open)           // optional value indicating if object is open or closed
    this.open = false;
  else
    this.open = true;
  this.index = 0;                // initial number of items in Contents
  this.Add = Add;                // Add is a Menu method e.g. Menu.Add()
  this.Contents = new Object();  // adds an empty built-in JavaScript Object
}

The following Add() function is used as a method of Menu, e.g., Menu.Add(). The obj parameter is added to the Contents[] array of the referenced Menu object, and the index property of the referenced Menu is increased by one. The path property of obj is set to the path of the owning Menu object plus the name property of obj.

function Add(obj) {
  this.Contents[this.index++] = obj;
  obj.path = this.path + '/' + obj.name;
}

What we have implied, but not yet stated, is that the obj parameter is actually an object that has been created somewhere else in the script. Using File(), Menu() and Add() we can create a structure that links files together in a hierarchical tree structure. For example, the following would first create a Menu object called rootMenu, and then a File object which would be added to the Contents array of the rootMenu object:

rootMenu = new Menu('home','rootMenu',true);
rootMenu.Add(new File('index.html','index'));

To add another File object to the rootMenu is as simple as:

rootMenu.Add(new File('email.html','text'));

To add a Menu object to the rootMenu require two lines, as we need a variable name for the object to which we can refer later:

docMenu = new Menu('documents','docMenu');
rootMenu.Add(docMenu);

If we had done it in one line, we wouldn't be able to add File objects to the docMenu:

docMenu.Add(new File('readme.txt','text'));
docMenu.Add(new File('logo.gif','image'));

So, in theory, our example object structure looks something like this:

    rootMenu -+- index.html
              |
              +- email.html
              |
              +- docMenu ---+- readme.txt
                            |
                            +- logo.gif

The object structure shows the order in which the objects are added. Therefore, if we want all the Menu objects to appear before the File objects in a particular menu, and all the objects to appear in alphabetical order, we just need to make sure that they are added to the Contents array of the owning Menu object in the correct order:

rootMenu = new Menu('home','rootMenu',true);
docMenu = new Menu('documents','docMenu');
rootMenu.Add(docMenu);
docMenu.Add(new File('logo.gif','image'));
docMenu.Add(new File('readme.txt','text'));
rootMenu.Add(new File('email.html','text'));
rootMenu.Add(new File('index.html','index'));

Now the structure will, in theory, look like this:

    rootMenu -+- docMenu ---+- logo.txt
              |             |
              |             +- readme.gif
              +- email.html
              |
              +- index.html

Now we'll show how to output the site map to the menu frame using both images and text links.

The following Show() function iterates around the object stucture building up an HTML table of images and text links of the currently open menus and their contents. It holds the HTML to be displayed in the output variable which is then returned to the menu.htm document for display in the menu frame. The starting point within the object structure will normally be the rootMenu, although this does not always have to be the case. You may prefer to show only a small section of the structure, e.g., the contents of a menu hidden deep in the object structure:

function Show(obj) {
  if (obj.type == 'menu')
    var anchor = '<a href="javascript:parent.OpenMenu(parent.' 
+ obj.ref + ')"';
  else
    var anchor = '<a href="' + obj.path + '" target="content"';
    
  anchor += ' onMouseover="window.status=\'' + obj.path + '\'; return true"';
  anchor += ' onMouseout="window.status=\'\'; return true">';

  if (MSIE) var picture = '<img src="' + obj.type + '.gif" align="absbottom" 
border="0" width="20" height="21">';
  else      var picture = '<img src="internal-gopher-' + obj.type + '" align=
"absbottom" border="0">';
    
  var output = '<table border=0><tr>' +
               '<td valign=top>' + anchor + picture + '</a></td>' +
               '<td><font face="arial">' + anchor + obj.name + '</a>';
    
  if (obj.open)
    for (var i=0; i<obj.index; i++)
      output += Show(obj.Contents[i]);

  output += '</td></tr></table>';

  return output;
}

function ShowSiteMap() {
  return Show(rootMenu);
}

function OpenMenu(obj) {
  obj.open = !obj.open;
  window.menu.location.href = window.menu.location.href;
}
//--></script>
</head>

The Show() function first builds up the anchor to be displayed. If the current obj objects type property is "menu," then the anchor will contain a javascript:url to the OpenMenu() function. It will be something like:

<a href="javascript:parent.OpenMenu(parent.rootMenu)" 
onMouseover="window.status=
'http://xxx.yyy.zzz/abc123/';return true" onMouseout=
"window.status='';return true"> 

You may now begin to appreciate why we need a ref property for each Menu object. We need the name of the variable holding the Menu object to be able to pass it to the OpenMenu() function. Without this we wouldn't be able to refer to a particular Menu object directly.

Note that, as both the function and variable are defined in the Menu frame's parent frame, they both require a reference to the parent frame. Otherwise, neither the function nor the variable will be found.

If the type property is not "menu," then the anchor will contain a link to the absolute URL of the file, like this:

<a href="http://xxx.yyy.zzz/abc123/index.html" target="content"
onMouseover="window.status='http://xxx.yyy.zzz/abc123/index.html';return true" 
onMouseout="window.status='';return true"> 

Next, the picture to be displayed in the link is built up. If the browser being used is Microsoft Internet Explorer, then images supplied by the Web site are used, again depending on the type property:

<img src="menu.gif" align="absbottom" border="0" width="20" height="21"> 

If the browser is Netscape Navigator, the undocumented internal-gopher images are used:

<img src="internal-gopher-menu" align="absbottom" border="0"> 

The beginning of the HTML table is then constructed using two columns, one containing the image link and the other containing the text link. If the obj objects open property is true, then for each entry in the Contents array, the Show() function is invoked to embed yet another table within the current table. Finally, the HTML table is closed and the contents of output are returned to the caller of the OpenMenu() function.

The OpenMenu() function, which completes the JavaScript, when invoked will toggle the open property of the current obj object, and then reload the document in the menu frame.

The ShowSiteMap() function is invoked by the menu.htm document, which in turn invokes the Show() function with the rootMenu, i.e., the initial Menu object:

What actually happens when a menu link is selected is that the Menu object is passed by the menu.htm document to the OpenMenu() function in the sitemap.htm document. The OpenMenu() function then toggles the open property of the Menu object before reloading the contents of the menu frame, which then calls the Show() function in the parent frame to rebuild the site map -- all within the blink of an eye.

Working Example

You can try out a sample site map: sitemap.htm.

Potential enhancements

If you use the above three HTML files (sitemap.htm, dummy.htm and menu.htm) on your own site, and then amend the tree structure using the Menu and File functions, you will be able to create a dynamic site map that your visitors can explore without the need for further downloads from the server. This will aid your visitors to locate the area of your site in which they are most interested without having to navigate a multitude of links.

You could further enhance the site map to use your own images or create others for specific filetypes. However, if you restrict yourself to the nine internal-gopher images, then, at least for Netscape Navigator, there will be no need for the browser to wait for the images to be downloaded.

The content frame could have an initial document loaded, perhaps explaining how to use the site map. The frameset can be enhanced to remove the border and to make the frames nonresizable.

You could include + and - gifs to indicate how to close and open the menus; this could be combined with additional menu images that show the menu image as open or closed, or you could include an indicator against the menu that contains the document currently being viewed in the content frame, i.e., a "You are Here" type of indicator.

You don't even need to build up the path of each file as it's added to the object structure! You can pass the complete relative or absolute URL as a parameter, which can be a local or a remote file and can, if required, use protocols other than http -- ftp:, mailto: and even javascript:.

Articles | Creating A Java script Site Map |  back

 

 

Menu

Home
Articles
FAQ's
Links
Tools
Blog Links
AJAXCoded Blog
CyberCoded.net
CyberCoder
CybersView

Applications

 

Questions, Comments
or Suggestions

Site Search
FAQ Search

AJAX Coded
CAAD @ CyberCoded.net


 

Copyright


Google
WWW CyberCoded.com
Provide Feedback on CyberCoded.com

Copyright © 1996-2008 CyberCoded.com, All Rights Reserved.
CyberCoded.com liability, trademark, document use and software licensing rules apply. Your interactions with this site are in accordance with our public privacy statements.
Website Hosted By: USNX

We recommend USNX for quality ASP Web Hosting