//*********************************************************************
//* 
//* @(#) snippets.js - A collection of handy javascripts.
//* 
//* @(#) Default Java Script library for the website:
//* @(#)	e-bachmann.dk, clicketyclick.dk
//* 
//* A collection of handy javascripts.
//* 
//* Should be functional under all browsers supporting javascript
//*********************************************************************
//* @(#) 2003-03-01/Erik Bachmann (e_bachmann@hotmail.com)
//*********************************************************************

//--- Globale variables -----------------------------------------------

window.onresize = new Function("window.location.reload()")
var _border=0 ;
var _base_name="" ;

var VERBOSE=0;				// Verbose & debug flag

// Chapter and Section headings
var main_level		= 0;		// Current chapter level
var sub_level		= 0;		// Current section level

var global_language	= "en";		// Global language code

// Clock function
var timerI		= null;
var timerRunning	= false;

//--- Functions -------------------------------------------------------

//---------------------------------------------------------------------

//*********************************************************************
// 
// TITLE:
//	Show/hide switch
// 
// DESCRIPTION: 
// 	Flipping the display style between "block" (visible)
//	and "none" (hidden)
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ELEM	Object to hide/display
// 	BUTTON	Button to update
// 
// NOTE:
// 	
// EXAMPLE:
// 
//	<input 
//		type="button" 
//		onclick="show_hide( showcase, this );" 
//		value="+" 
//		class="submit" 
//		onLoad="this.style.display='none';self.status='loading';return true"
//	>
//
//	<table>
//	<tr>
//		<td id=showcase>
//			Now you see!
//		</td>
//	</tr>
//	<table>
//
//	<!-- Make sure that object is visible by default -->
//	<script>showcase.style.display='block';</script>
//
//*********************************************************************
// 2003-05-31/Erik Bachmann
//*********************************************************************

function show_hide( elem, button )
{
	if ( "none" == elem.style.display )
	{
		button.value	= "-"
		elem.style.display="block";
	}
	else
	{
		button.value	= "+"
		elem.style.display="none";
	}
}	//*** show_hide() ***

//---------------------------------------------------------------------

//*********************************************************************
// 
// TITLE:
//	Image create
// 
// DESCRIPTION: 
// 	Create image Object
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// EXAMPLE:
// 
//	<scripts>image_zoom_out( image1, myimg, myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_create( picture, description )
{
	myImage		= new Image();
	myImage.src	= picture;
	myImage.name	= description;
	if ( 0 < VERBOSE )
	{

		alert
		(
			"Picture created: " 
		+	myImage.src
		+	" / "
		+	myImage.name
		);
	}

	return myImage;
}	//*** image_create() ***

//*********************************************************************
// 
// TITLE:
//	image configuration
// 
// DESCRIPTION: 
// 	Build configuration for Object created using image_create()
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// EXAMPLE:
// 
//	<scripts>image_zoom_out( image1, myimg, myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_config( picture )
{
	x = new Array(9);
	x[0]	= picture.src;		// File name
	x[1]	= picture.name;
	//x[2]	=	;	// Reserved
	//x[3]	=	;	// Reserved
	x[4]	= picture.width;	// Full width X
	x[5]	= picture.height;	// Full height Y
	x[6]	= picture.width;	// Current width size X
	x[7]	= picture.height;	// Current height Y
	x[8]	= 100;	// Relative size
	return x;
}	//*** image_config() ***





//*********************************************************************
// 
// TITLE:
//	image zoom out
// 
// DESCRIPTION: 
// 	Zoom out on a image
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// EXAMPLE:
// 
//	<scripts>image_zoom_out( image1, myimg, myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_zoom_out( image_field, image_object, image_cfg )
{
	image_field.height		*= 0.9;
	image_field.width		*= 0.9;
	image_cfg[8]			-= 10;
	
	image_cfg[6]			= image_field.width;
	image_cfg[7]			= image_field.height;
	
	image_cfg[8]			= ( image_cfg[6] * 100 / image_cfg[4] );
	image_cfg[8]			-= ( image_cfg[8] ) % 1 ;

	image_data( image_cfg )
}	//*** image_zoom_out() ***

//*********************************************************************
// 
// TITLE:
//	image zoom in
// 
// DESCRIPTION: 
// 	Zoom in on a picture
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<scripts>image_zoom_in( image1, myimg, myimg_cfg );</scripts>
// 
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_zoom_in( image_field, image_object, image_cfg )
{
	image_field.height		*= 1.1;
	image_field.width		*= 1.1;
	image_cfg[8]			=eval( image_cfg[8] ) + 10; 
	
	image_cfg[6]			= image_field.width;
	image_cfg[7]			= image_field.height;
	
	image_cfg[8]			= ( image_cfg[6] * 100 / image_cfg[4] );
	image_cfg[8]			-= ( image_cfg[8] ) % 1 ;

	image_data( image_cfg )
}	//*** image_zoom_in() ***

//*********************************************************************
// 
// TITLE:
//	Picture zoom small
// 
// DESCRIPTION: 
// 	Zoom to relatively small picture (width = 600) size
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<scripts>image_zoom_small( image1, myimg, myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_zoom_small( image_field, image_object, image_cfg )
{
	// Set default width
	image_cfg[6]			= 400
	
	// Estimate ration
	image_cfg[8]			= ( image_cfg[6] * 100 / image_cfg[4] );
	image_cfg[8]			-= ( image_cfg[8] ) % 1;

	// Calculate height
	image_cfg[7]			= ( image_cfg[5] * image_cfg[8] )/ 100;
	image_cfg[7]			-= ( image_cfg[7] % 1 );

	// Set actual size
	image_field.height		= image_cfg[7];
	image_field.width		= image_cfg[6];

	image_data( image_cfg )
}	//*** image_zoom_small() ***

//*********************************************************************
// 
// TITLE:
//	Picture zoom normal
// 
// DESCRIPTION: 
// 	Zoom to full screen size
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<scripts>image_zoom_normal( image1, myimg, myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_zoom_normal( image_field, image_object, image_cfg )
{
	// Set actual size
	Xfactor				= image_cfg[4] / screen.availWidth;
	Yfactor				= image_cfg[5] / screen.availHeight;

	if ( Yfactor > Xfactor )
	{
		// Relativ heigh
		image_cfg[7]		= screen.availHeight ;
		image_cfg[6]		= image_cfg[4] / Yfactor ;
		if ( 0 < VERBOSE )
		{
			alert( "Y=" + Yfactor + ". X=" + Xfactor  );
		}
	}
	else
	{
		// Relativ wide
		image_cfg[6]		= screen.availWidth ;
		image_cfg[7]		= image_cfg[5] / Xfactor ;
		if ( 0 < VERBOSE )
		{
			alert( "X=" + Xfactor + ". Y=" + Yfactor );
		}
	}

	// Estimate ratio
	image_cfg[8]			= ( image_cfg[6] * 100 / image_cfg[4] );
	image_cfg[8]			-= ( image_cfg[8] ) % 1;

	// Set actual size
	image_field.height		= image_cfg[7];
	image_field.width		= image_cfg[6];

	image_data( image_cfg )
}	//*** image_zoom_normal() ***

//*********************************************************************
// 
// TITLE:
//	image zoom full
// 
// DESCRIPTION: 
// 	Zoom to full image size
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	ID	ID from <img src="x.gif" id="ID">
// 	Object	Javascript image object created using image_create()
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<scripts>image_zoom_full( image1, myimg, myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_zoom_full( image_field, image_object, image_cfg )
{
	// Set actual size
	image_cfg[6]		= image_cfg[4] ;
	image_cfg[7]		= image_cfg[5] ;

	// Estimate ratio
	image_cfg[8]			= ( image_cfg[6] * 100 / image_cfg[4] );
	image_cfg[8]			-= ( image_cfg[8] ) % 1;

	// Set actual size
	image_field.width		= image_cfg[6];
	image_field.height		= image_cfg[7];

	image_data( image_cfg )
}	//*** image_zoom_full() ***

//*********************************************************************
// 
// TITLE:
//	image data
// 
// DESCRIPTION: 
// 	Display image data on status line
// 
// SOURCE:
// 	selfmade
// 
// ARGUMENTS:
// 	Config	Configuration for Object created using image_config()
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<scripts>image_data( myimg_cfg );</scripts>
// 
//*********************************************************************
// 2003-04-02/Erik Bachmann
//*********************************************************************
function image_data( image_cfg )
{

	self.status =
	""
//+	"0=file["
//+	image_cfg[0]
//+	"]. "

+	"1=desc["
+	image_cfg[1]
+	"]. "

//+	"2=res["
//+	image_cfg[2]
//+	"]. "

//+	"3=["
//+	image_cfg[3]
//+	"]. "

+	"4=fullX["
+	image_cfg[4]
+	"]. "

+	"5=fullY["
+	image_cfg[5]
+	"]. "

+	"6=curX["
+	image_cfg[6]
+	"]. "

+	"7=curY["
+	image_cfg[7]
+	"]. "

+	"8=ratio["
+	image_cfg[8]
+	"]. "

//+	"9=["
//+	image_cfg[9]
//+	"]"

;

}





//*********************************************************************
// 
// TITLE:
//	Navigation bar
// 
// DESCRIPTION: 
// 	Display navigation bar with links to previous, top, index
//	and next document
// 
// SOURCE:
// 	selfmade
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<scripts>navigation_bar( "previous.html", "Next.html");</script>
// will display:
// 
// 	|Previous|Top|Index|Next|
// 
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function navigation_bar( previous, next )
{
	var	top_img		= "top.gif" ;
	var	prev_img	= "prev.gif" ;
	var	next_img	= "next.gif" ;
	var	index_img	= "home.png" ;

	if ( ! previous )
	{
		previous = " " ;
	}
	if ( ! next )
	{
		next = " " ;
	}

	var bar = "<div align=right>"
	+	"        |<a href='" + previous + "'	"
	+	"onMouseOver=\"self.status='Previous / Forrige';"
	+	" return true\"		><img src=\"" + prev_img
	+	"\" alt=\"Previous\"	align=abscenter border=0></A>"

	+	"        |<a href='#TOP'		"
	+	"onMouseOver=\"self.status='Top of page / Sidestart';"
	+	" return true\"	><img src=\"" + top_img	  
	+	"\"  alt=\"Top\"		align=abscenter border=0></A>"

	+	"        |<a href='index.html'		"
	+	"onMouseOver=\"self.status='Hjem / Home'; "
	+	"return true\"			><img src=\"" + index_img 
	+	"\" alt=\"Home\"		align=abscenter border=0></A>"

	+	"        |<a href='" + next + "'	"
	+	"onMouseOver=\"self.status='Next / N&aelig;ste'; "
	+	"return true\"		><img src=\"" + next_img  
	+	"\" alt=\"Next\"		align=abscenter border=0></A>"
	+	"</div>"

	document.write( bar ) ;
}	//*** navigation_bar() ***


//*********************************************************************
// 
// TITLE:
//	Find in window
// 
// DESCRIPTION: 
//	Search and highlight a string
// 
// SOURCE:
// 	selfmade
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<!-- Find in current page using form -->
//	<script src="find.js"></script>
//	
//	<form name=search onSubmit="return find_in_window(this, this.string.value);">
//		Find in Page
//		<input name=string type=text size=15 onChange="n = 0;">
//		<input type="submit" name="" value="Search" />
//	</form>
//
//
//	<!-- Find in current page using a pop-up window -->
//	<script src="find.js"></script>
//	<form name=search onSubmit="return find_window();">
//		<input type="submit" name="" value="Find!" />
//	</form>
// 
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************

//*** find_in_window **************************************************
//---------------------------------------------------------------------

//var NS4 = (document.layers);	// Netscape compatible
//var IE4 = (document.all);	// Internet Explorer compatible

//var find_in_window_hits   = 0;	// Hit counter

function xfind_in_window(win, str)
{
	var txt, i, found;
	if (str == "")
		return false;
	if (NS4)
	{
		if (!win.find(str))
			while(win.find(str, false, true))
			find_in_window_hits++;
		else
			find_in_window_hits++;

		if (find_in_window_hits == 0) 
			alert(str + " was not found on this page.");
	}
	if (IE4) 
	{
		//window.status	= find_in_window_hits + "/" + win;
		if ( win.document )
		{
			txt = win.document.body.createTextRange();
			for (i = 0; i <= find_in_window_hits && (found = txt.findText(str)) != false; i++) 
			{
				txt.moveStart("character", 1);
				txt.moveEnd("textedit");
			}
			if (found) 
			{
				txt.moveStart("character", -1);
				txt.findText(str);
				txt.select();
				txt.scrollIntoView();
				find_in_window_hits++;
			}
			else
			{
				if (find_in_window_hits > 0) 
				{
					find_in_window_hits = 0;
					find_in_window(str);
				}
				else
					alert( "[" + str + "] was not found on this page.");
			}
		}
	}
	return false;
}	//*** find_in_window() ***


//*********************************************************************
// 
// TITLE:
//	Popup find in window
// 
// DESCRIPTION: 
//	Search and highlight a string using popup window
// 
// SOURCE:
// 	selfmade
// 
// NOTE:
// 	
// 
// EXAMPLE:
// 
//	<!-- Find in current page using form -->
//	<script src="find.js"></script>
//	
//	<!-- Find in current page using a pop-up window -->
//	<script src="find.js"></script>
//	<form name=search onSubmit="return find_window();">
//		<input type="submit" name="" value="Find!" />
//	</form>
// 
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function xpop_find_in_window()
{
	// Open popup window
	var url = "";
	var hWnd = window.open(url,"","width=475,height=150,resizable=no,status=no,scrollbars=no");

	// Set focus
	if ((document.window != null) && (!hWnd.opener))
	hWnd.opener = document.window;

	// Load "find_in_window" script
	hWnd.document.writeln( '<script src=find.js>');
	hWnd.document.writeln( '<\/script>');

	// Write search form
	hWnd.document.writeln( '<h1>Find in parent window</h1>' );
	hWnd.document.writeln( '<form name=search onSubmit="return find_in_window(window.opener, this.string.value);">' );
	hWnd.document.writeln( '	Find in Page' );
	hWnd.document.writeln( '	<input name=string type=text size=15 onChange="n = 0;" onFocus="string_focus=0; return true;" onBlur="string_focus=1; return true;" >' );
	hWnd.document.writeln( '	<input type="submit" name="" value="Search" />' );
	hWnd.document.writeln( '	<input type="reset" name="" value="Cancel" />' );
	hWnd.document.writeln( '	<input type="button" value="Close" onClick="window.close();" class="Bsbttn"/>' );
	hWnd.document.writeln( '<\/form>');

	// Set focus on input box
	hWnd.document.writeln( '<script>search.string.focus()<\/script>' );
}	//*** pop_find_in_window() ***





//*********************************************************************
// 
// TITLE:
//	Check All Checkboxes
// 
// DESCRIPTION: 
// 	Dynamically checks and unchecks all the checkboxes in a
// 	form when a button is clicked. 
//	Can even be used on multiple individual forms on same page
// 
// SOURCE:
//	Based on:
// 	http://javascript.internet.com/buttons/check-all.html
// 
// NOTE:
// 	Requires specific text on button: "Check All" or "Uncheck All"
// 
// EXAMPLE:
// 
//	<form name=myform action="" method=post>
//	<table>
//	<tr>
//		<td>
//			<b>Your Favorite programming Languages</b><br>
//			<input type=checkbox name=langs value="1">Perl<br>
//			<input type=checkbox name=langs value="2">JavaScript<br>
//			<input type=checkbox name=langs value="3">ASP<br>
//			<input type=checkbox name=langs value="4">Java<br>
//			<br>                                                    
//			<input 
//				type=button 
//				name=checkbutton 
//				value="Check All" 
//				onClick="this.value=check_all_checkboxes(this.form.langs, this.form.checkbutton)"
//			>
//		</td>
//	</tr>
//	</table>
//	</form>
// 
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function check_all_checkboxes(field, button)
{
	var status = button.value + VERBOSE;
	top.window.status	= VERBOSE;
	debug( "check_all_checkboxes()" );

	var checkflag = "false";
	var status = button.value ;

	//top.window.status	= status;

	if ( "Check All" == button.value )
	{
		status = status + " Assume unchecked [ ]" ;
		checkflag = "false";
	}
	if ( "Uncheck All" == button.value )
	{
		status = status + "Assume checked [X]" ;
		checkflag = "true";
	}
	//top.window.status	= status;

	if (checkflag == "false") 
	{
		for (i = 0; i < field.length; i++) 
		{
			field[i].checked = true;
		}
		checkflag = "true";
		return "Uncheck All"; 
	}
	else
	{
		for (i = 0; i < field.length; i++) 
		{
			field[i].checked = false; 
		}
		checkflag = "false";
		return "Check All"; 
	}
}	//*** check_all_checkboxes() ***


//*********************************************************************
// TITLE:
//	Go to button
// 
// DESCRIPTION: 
// 	Builds a button with a link to a new URL
// 
// NOTE:
// 	Form should be styled on the source page
// 
// EXAMPLE:
//	<script>go_to_button("CNN", "http://www.cnn.com", "Link to CNN news");</script>
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function go_to_button(title, url, desc) 
{
	debug( "go_to_button()" );

	debug( "Title=[" + title + "]\nURL=[" + url + "]\nDesc=[" + desc + "]" );
	document.write( "<form><input type=button value='" );
	document.write( title );
	document.write( "' onClick='window.location=\"" );
	document.write( url );
	document.write( "\";' " );

	document.write( "onMouseOver='window.status=\"" );
	document.write( desc );
	document.write( "\"'" );
	document.write( "onMouseOut='window.status=\"\"'>" );
	document.write("</form>" );
}	//*** go_to_button() ***


//*********************************************************************
// TITLE:
//	Mail to button
// 
// DESCRIPTION: 
// 	Builds a button with a link to a new URL
// 
// NOTE:
// 	Form should be styled on the source page
// 
// SYNTAX FOR MAIL:
//	mailto:NAME@DOMAINE?Subject=SUBJECT&body=BODY
//	?	Separating e-mail address from letter
//	&	Separating fields i letter:
//			Subject=
//			Body=
//	%0A	Newline
//	%09	Tab
//
// EXAMPLE:
//	<script>mailto_button("Santa", "santa@northpole.gl", 
//	"Merry X-mas", "Hello world%10- ho ho ho");</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function mailto_button(title, email, subject, body) 
{
	debug( "mailto_button()" );

	debug( "Title=[" + title + "]\nemail=[" + email + "]\nSubject=[" + subject + "]\nbody=[" + body + "]" );
	document.write( "<form><input type=button value='" );
	document.write( title );
	document.write( "' onClick='parent.location=\"mailto:" );
	document.write( email );
	document.write( "?subject=" );
	document.write( subject );
	document.write( "&body=" );
	document.write( body );
	document.write( "\";' " );
	document.write( "onMouseOver='window.status=\"" );
	document.write( subject );
	document.write( "\"'" );
	document.write( "onMouseOut='window.status=\"\"'>" );
	document.write("</form>" );
}	//*** mailto_button() ***


//*********************************************************************
// TITLE:
//	Resize window
// 
// DESCRIPTION: 
// 	Set the width and height of current window
// 
// EXAMPLE:
//	<script>resize_window( 800, 600 );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function resize_window(width, height) 
{
	debug( "resize_window()" );
	if (parseInt(navigator.appVersion)>3) 
	{
		if (navigator.appName=="Netscape")
		{
			if (top.outerWidth < screen.availWidth)
				window.outerWidth=width;
			if (top.outerHeight < screen.availHeight) 
				window.outerHeight=height;
		}
		else 
		{
			window.resizeTo(width,height);
		}
	}
}	//*** resize_window() ***


//*********************************************************************
// TITLE:
//	Maximize window
// 
// DESCRIPTION: 
// 	Set the width and height of current window to max
// 
// EXAMPLE:
//	<script>maximize_window();</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function maximize_window() 
{
	debug( "maximize_window()" );
	if (parseInt(navigator.appVersion)>3) 
	{
		if (navigator.appName=="Netscape")
		{
			if (top.screenX>0 || top.screenY>0)
				top.moveTo(0,0);
			if (top.outerWidth < screen.availWidth)
				top.outerWidth=screen.availWidth;
			if (top.outerHeight < screen.availHeight) 
				top.outerHeight=screen.availHeight;
		}
		else 
		{
			top.moveTo(-4,-4);
			top.resizeTo(screen.availWidth+8,screen.availHeight+8);
		}
	}
}	//*** maximize_window() ***


//*********************************************************************
// TITLE:
//	Maximize window vertically
// 
// DESCRIPTION: 
// 	Set the height of current window to max
// 
// EXAMPLE:
//	<script>maximize_window_vertical();</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function maximize_window_vertical(currentWindow)
{
	debug( "maximize_window_vertical()" );
	var winW;

	if (parseInt(navigator.appVersion)>3) 
	{
		if (navigator.appName=="Netscape")
		{
//			if (top.screenX>0 || top.screenY>0)
//				top.moveTo(0,0);
//			if (top.outerWidth < screen.availWidth)
//				top.outerWidth=screen.availWidth;
			if (currentWindow.outerHeight < screen.availHeight) 
				currentWindow.outerHeight=screen.availHeight;
		}
		else 
		{
			winW = window.document.body.offsetWidth-20;
			window.resizeTo(winW,screen.availHeight+8);
		}
	}
}	//*** maximize_window_vertical() ***


//*********************************************************************
// TITLE:
//	Align window right
// 
// DESCRIPTION: 
// 	Align window to the right of the screen
// 
// EXAMPLE:
//	<script>align_window_right( this );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function align_window_right(currentWindow)
{
	debug( "align_window_right()" );
	var screenH;
	var screenW;
	var winW;
	var winH;
	var posX;
	var posY;

	screenH	= screen.availHeight;
	screenW	= screen.availWidth;

	if (navigator.appName=="Netscape") 
	{
		winW	= window.innerWidth-16;
		winH	= window.innerHeight-16;
	}
	if (navigator.appName.indexOf("Microsoft")!=-1) 
	{
		//winW = currentWindow.document.body.offsetWidth-20;
		//winH = currentWindow.document.body.offsetHeight-20;
		winW = window.document.body.offsetWidth-20;
		winH = window.document.body.offsetHeight-20;
	}

	posX	= screen.availWidth - winW - 25;
	posY	= screen.availheight - winH;

	//currentWindow.moveTo(posX,0);
	window.moveTo(posX,0);
}	//*** align_window_right() ***


//*********************************************************************
// TITLE:
//	Move window
// 
// DESCRIPTION: 
// 	Move current window relative to current position
// 
// EXAMPLE:
//	<script>move_window( 20, 10 );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function move_window(x,y,currentWindow) 
{
	debug( "move_window(" + x + "," + y + ")" );
	window.moveBy(x,y);
}	//*** move_window() ***


//*********************************************************************
// TITLE:
//	Move window to...
// 
// DESCRIPTION: 
// 	Move current window to a specific position
// 
// EXAMPLE:
//	<script>move_window_to( 20, 10 );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function move_window_to(x,y) 
{
	debug( "move_window_to(" + x + "," + y + ")" );
	if (parseInt(navigator.appVersion)>3) 
	{
		window.moveTo(x,y);
	}
}	//*** move_window() ***


//*********************************************************************
// TITLE:
//	Open debug window
// 
// DESCRIPTION: 
// 	Open a new window for displaying debug information
// 
// EXAMPLE:
//	<script>open_debug_window; debug( "debugging..." );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function open_debug_window()
{
	if ( 0 < VERBOSE )
	{
		var winWidth=600;
		var winHeight=480;
		var winW=500;
		var winH=500;
		var x=0;
		var y=0;

		if (parseInt(navigator.appVersion)>3) 
		{
			if (navigator.appName=="Netscape") 
			{
				winW = window.innerWidth-16;
				winH = window.innerHeight-16;
			}

	//		if (navigator.appName.indexOf("Microsoft")!=-1) 
	//		{
	//			winW = document.body.offsetWidth - 20 ;
	//			winH = document.body.offsetHeight - 20 ;
	//		}
		}

		x = (winW + winWidth) / 2 ;
		y = (winH + winHeight) / 2 ;


		//toolbar=no,location=no,resizable=yes,scrollbars=yes
		//resizable=0,menubar=0,scrollbars=0,toolbar=0,location=0,directories=0
		debug_window	= window.open('', 'Debug_window'
			, 'width=' + winWidth + ',height=' + winHeight 
			+ ',scrollbars=1,resizeable=1,toolbar=no,location=no');

		debug_window.document.writeln( '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">');
		debug_window.document.writeln( '\n<html>\n\t<head>\n' );
		debug_window.document.writeln( ' \t\t<title>Verbose and Debug information</title>\n');
		debug_window.document.writeln( '<script language="JavaScript" src="snippets.js"></script>\n' );
		debug_window.document.writeln( '<link rel="stylesheet" type="text/css" href="snippets.css" />\n' );
		debug_window.document.writeln( '</head>\n<body>Debugging: ' + document.URL + '<pre>\n' );

		maximize_window_vertical(debug_window);
		align_window_right(debug_window);

		if (debug_window.opener == null)
		{
			debug_window.opener = self;
		}

	}
}	//*** open_debug_window() ***


//*********************************************************************
// TITLE:
//	Debug
// 
// DESCRIPTION: 
// 	Write debug information to debug window (if open)
// 
// NOTE:
//	Depends on 1 < VERBOSE & open_debug_window()
// 
// EXAMPLE:
//	<script>open_debug_window; debug( "debugging..." );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function debug(string)
{
	if ( 1 < VERBOSE )
	{
		if ( debug_window.opener != null )
		{
			debug_window.document.writeln( string );
			debug_window.scrollBy(0,500);
		}
	}
}	//*** debug() ***


//*********************************************************************
// TITLE:
//	Verbose
// 
// DESCRIPTION: 
// 	Write verbose information to debug window (if open)
// 
// NOTE:
//	Depends on 0 < VERBOSE & open_debug_window()
// 
// EXAMPLE:
//	<script>open_debug_window; verbose( "Talking loud..." );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function verbose(string)
{
//	my ( $str ) = @_ ;
	if ( 0 < VERBOSE )
	{
		debug_window.document.writeln( string );
		debug_window.scrollBy(0,500);
	}
}	//*** verbose() ***


//*********************************************************************
// TITLE:
//	Close window now
// 
// DESCRIPTION: 
// 	Close current (sub-) windows
// 
// EXAMPLE:
//	<script>open_debug_window; verbose( "Talking loud..." );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function close_window_now()
{
	top.window.VERBOSE=0; 
	top.window.status	= "Closing";
	self.opener = null;
	self.close();
}	//*** close_window_now() ***


//*********************************************************************
// TITLE:
//	"Close debug window" button
// 
// DESCRIPTION: 
// 	Display a button for closing the debug window
// 
// NOTE:
//	Clears the verbose flag!
//	Should ONLY be used when terminating the program/script/page
//
// EXAMPLE:
//	<script>close_debug_window_button();</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function close_debug_window_button()
{
//	debug_window.document.writeln( " close_debug_window_button " );
//	var VERBOSE=;
	if ( 0 < VERBOSE )
	{
		debug_window.document.writeln( "\n<!-- verbose=" 
		+	VERBOSE +  " -->\n" );
//		debug_window.document.writeln( "\n verbose=" +  VERBOSE +  " \n" );
		if ( 1 < VERBOSE )
		{
			debug_window.document.writeln( "\n<!-- VERBOSE(>1) ="
			+	VERBOSE + " > 1 -->\n" );
			debug_window.document.writeln( "<center>"
			+	"<form method='post' action='' "
			+	"enctype='application/x-www-form-urlencoded' "
			+	"onsubmit='close_window_now();'>"
			+	"<input type='submit' name='submit' "
			+	"value='Close debug window'></form></center>" );
			debug_window.scrollBy(0,200);
		}
		else
		{
			debug_window.document.writeln( "<!-- VERBOSE(=1) ="
			+	VERBOSE + " -->" );
			debug_window.document.writeln( "<center><form method='post' "
			+	"action='' enctype='application/x-www-form-urlencoded' "
			+	"onsubmit='top.window.VERBOSE=0 ; VERBOSE=0;self.close();'>"
			+	"<input type='submit' name='submit' "
			+	"value='Close debug window'></form></center>" );
			debug_window.scrollBy(0,200);
		}
		VERBOSE=0;

	}
//	else
//	{
//			debug_window.document.writeln( "\n<-- verbose=" );
//			debug_window.document.writeln( VERBOSE );
//			debug_window.document.writeln( " = 0 -->" );
//	}

}	//*** close_debug_window_button() ***


//*********************************************************************
// TITLE:
//	Function button
// 
// DESCRIPTION: 
// 	Activate a javascript function via a button
// 
// EXAMPLE:
//	<script>function_button( open_debug_window() );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function function_button(func)
{
	debug( "function_button(): " + func );
	func;
}	//*** function_button() ***


//*********************************************************************
// TITLE:
//	Print page
// 
// DESCRIPTION: 
// 	Print current page
// 
// EXAMPLE:
//	<script>function_button( print_page() );</script>
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function print_page()
{
	var text	= document;
	debug( "print_page(" + text + "): " );
	print(text); 
}	//*** print_page() ***


//*********************************************************************
// TITLE:
//	Chapter
// 
// DESCRIPTION: 
// 	Display new main chapter number
// 
// EXAMPLE:
//	<script>Chapter();</script>
//	<script>Chapter();</script>
//	<script>Chapter();</script>
// 
// will display as:
// 
// 	1.0
//	2.0
//	3.0
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function Chapter()
{
	main_level = main_level + 1;
	sub_level=0;
	document.write( main_level + "." + sub_level + "&nbsp;" ) ;
}	//*** chapter() ***


//*********************************************************************
// TITLE:
//	Section
// 
// DESCRIPTION: 
// 	Display new sub section number
// 
// EXAMPLE:
//	<script>Chapter();</script>
//	<script>Section();</script>
//	<script>Section();</script>
// 
//	<script>Chapter();</script>
//	<script>Section();</script>
// 
// will display as:
// 
// 	1.0
//	1.1
//	1.2
//	2.0
//
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function Section()
{
	sub_level= sub_level + 1;
	document.write( main_level + "." + sub_level + "&nbsp;" ) ;
}//*** section() ***


//*********************************************************************
// TITLE:
//	Two digit
// 
// DESCRIPTION: 
// 	Pad one digit numbers to two digit with leading 0
// 
// EXAMPLE:
//	<script>document.write(two_digit( 5 ));</script>
// 
// will display as:
// 
// 	05
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function two_digit(value)
{
	var newvalue = "";
	if ( value <= 9 )
	{
		debug( '0' );
		newvalue += '0' ;
	}
	debug( value );
	newvalue += value ;

	return newvalue
}	//*** two_digit() ****

//---------------------------------------------------------------------

//window.onresize = resize;
//window.saveInnerWidth = window.innerWidth;
//window.saveInnerHeight = window.innerHeight;

//function window_resize() 
//{
//	if (saveInnerWidth < window.innerWidth 
//	||	saveInnerWidth > window.innerWidth
//	||	saveInnerHeight > window.innerHeight
//	||	saveInnerHeight < window.innerHeight ) 
//	{
//		window.location.reload();
//	}
//}	//*** window_resize() ***


//*********************************************************************
// TITLE:
//	ISO last modified date
// 
// DESCRIPTION: 
// 	Return document modified date as string in ISO format 
//	YYYY-MM-DD/hh:mm:ss
// 
// EXAMPLE:
//	<script>document.write( iso_lastModified( ));</script>
// 
// will display as:
// 
// 	2003-02-28/21:33:04
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function iso_lastModified()
{
	var isodate = new Date(Date.parse(document.lastModified)) 
	
	var datestr = isodate.getFullYear() 
	datestr += '-' + two_digit( isodate.getMonth() + 1 ) ;
	datestr += '-' + two_digit( isodate.getDate() )
	datestr += '/' + two_digit( isodate.getHours() )
	datestr += ':' + two_digit( isodate.getMinutes() )
	datestr += ':' + two_digit( isodate.getSeconds() )
	
	return datestr 
}	//*** iso_lastModified() ***



//*********************************************************************
// TITLE:
//	Write footer
// 
// DESCRIPTION: 
// 	Write a default document footer with horizontal line,
//	latest modification date (YYYY-MM-DD/hh:mm:ss),
//	email and current URL.
// 
// EXAMPLE:
//	<script>write_footer();</script>
// 
// will display as:
//	--------------------------------------------------------------
// 	[+] 2003-02-28T21:33:04 / <Webmaster>	URL: http://index.html
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function write_footer( value )
{
	var img_height	= 64;
	var img_width	= 64;

	var logo_height	= 48;
	var logo_width	= 90;

	if ( ! value )
	{
		value = iso_lastModified() ;
	}

	
	footer = 
	"<HR><!-- Horsontal line ------------------------------------>"
+	"<TABLE BORDER=0 WIDTH='100%'>"
+	"<TR>"
+	"	<TD ALIGN=Left VALIGN=MIDDLE>"
+	"<SPAN class='footer' ID='txt'>"
+	"<input "
+	"	type='button'"
+	"	onclick='show_hide( debug_info, this );'"
+	"	value='+'"
+	"	class='submit'"
+	"	onLoad=\"this.style.display='none';self.status='loading';return true\""
+	">"
+	"		[" + value + "] / "
+	"		<A HREF='MailTo:e_bachmann@hotmail.com'>Erik Bachmann</A>" 
+	"</SPAN>"
+	"	</TD>"
+	"	<TD ALIGN=RIGHT VALIGN=MIDDLE>" 
+	"	<SPAN CLASS='footer' ID='txt'>URL: <a href=\"" + document.URL
+	"\" tooltip='A link to the current page'>"
+	document.URL
+	"	</SPAN></a>"
+	"	</TD>"
+	"</TR>"
+	"</TABLE><HR>"
	
	// *** footer ***

	document.write( footer ) ;
}	//*** write_footer() ***


function Xwrite_footer()
{
	var img_height	= 64
	var img_width	= 64

	var logo_height	= 48
	var logo_width	= 90

	var image	= "ebp.jpg";
	var email	= "e_bachmann@hotmail.com";
	var name	= "Erik Bachmann";

	footer = 
	"<br clear=both>"
+	"<hr><!-- Horsontal line ------------------------------------>"
+	"<TABLE BORDER=" + _border + " WIDTH='100%'>"
+	"<TR>"
+	"	<TD ALIGN=Left VALIGN=MIDDLE>"
+	"		<SPAN class='footer' ID='txt'>Edited by: "
+	"		<SPAN class='footer' ID='txt'>"
+	"<A HREF='"
+	email
+	"' "
+	"tooltip='Feel free to contact me!'>"
+	name
+	"</A> ["
+	iso_lastModified()
+	"]</SPAN>"
+	"	</TD>"
+	"	<TD ALIGN=RIGHT VALIGN=MIDDLE>"
+	"	<SPAN CLASS='footer' ID='txt'>URL: <a href=\""
+	 document.URL
+	"\" tooltip='A link to the current page'>"
+	document.URL
+	"	</SPAN></a>"
+	"	</TD>"
+	"</TR>"
+	"</TABLE><HR>"
	
	// *** footer ***

	document.write( footer ) ;
}	//*** write_footer() ***







//*********************************************************************
// TITLE:
//	Go home
// 
// DESCRIPTION: 
// 	Checks if a frame named "Main" is pressent in the current window.
//	If NOT found: Clear windows build two frames and write the
//	current document into the side frame.
// 
// EXAMPLE:
//	<body onload="GoHome( index.html );">
// 
// will display as:
//	 _____________________________________________________________
//	|Menu          |Main                                          |
//	|              |                                              |
//	|______________|______________________________________________|
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function GoHome( name )
{
        if (!top.main)	// If main frame is not found
        {
        	
                // Rewrite window with two frames
		document.writeln("<SCRIPT LANGUAGE='JavaScript1.2' SRC='snippets.js'></SCRIPT>");
		document.writeln("<LINK REL=STYLESHEET HREF='snippets.ccs' TYPE='text/css'>");

                document.writeln("<FRAMESET ROWS=\"100%\" COLS=\"25%,*\">") ;
                document.writeln("<FRAME NAME=\"menu\" SRC=\"/menu.htm\" SCROLLING=\"AUTO\">") ;
                // Display current document in side frame
		document.writeln("<FRAME NAME=\"main\" SRC=\"" + name + "\" SCROLLING=\"AUTO\">")
		document.writeln("</FRAMESET>");

		document.writeln("<NOFRAMES>Please enable frames to view this page</NOFRAMES></HTML>");
        }
}       // GoHome()


//*********************************************************************
// TITLE:
//	keypressed
// 
// DESCRIPTION: 
// 	Jump in alphabetic list when pressing a key
// 
// EXAMPLE:
//	<script>document.onkeydown=keypressed;</script>
// 
// will display as:
//	 _____________________________________________________________
//	| A                                                           |
//	| B                                                           |
//	| C                                                           |
//	|_____________________________________________________________|
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function keypressed(e)
{
	Key = window.event.keyCode;
	if (Key != 0)
	{
		KeyState="";
		KeyValue=Key;

		if (window.event.ctrlKey)    	{	KeyState="Ctrl + "	}
		if (window.event.shiftKey)    	{	KeyState="Shift + "	}
		if (window.event.altKey)    	{	KeyState="Ctrl + "	}

		window.status=Key;

		if (37 == Key)	{	KeyState= KeyState + "Arrow left"	}
		if (38 == Key)	{	KeyState= KeyState + "Arrow up"	}
		if (39 == Key)	{	KeyState= KeyState + "Arrow right"	}
		if (40 == Key)	{	KeyState= KeyState + "Arrow down"	}

		//! = debug
		if (49 == Key)	{	KeyState= KeyState + "! (debug)" ; alert('Debug open');	}

		if (65 == Key)	{	KeyState= KeyState + "a" ; window.location.href="#A" ;	}
		if (66 == Key)	{	KeyState= KeyState + "b" ; window.location.href="#B" ;	}
		if (67 == Key)	{	KeyState= KeyState + "c" ; window.location.href="#C" ;	}
		if (68 == Key)	{	KeyState= KeyState + "d" ; window.location.href="#D" ;	}
		if (69 == Key)	{	KeyState= KeyState + "e" ; window.location.href="#E" ;	}

		if (70 == Key)	{	KeyState= KeyState + "f" ; window.location.href="#F" ;	}
		if (71 == Key)	{	KeyState= KeyState + "g" ; window.location.href="#G" ;	}
		if (72 == Key)	{	KeyState= KeyState + "h" ; window.location.href="#H" ;	}
		if (73 == Key)	{	KeyState= KeyState + "i" ; window.location.href="#I" ;	}
		if (74 == Key)	{	KeyState= KeyState + "j" ; window.location.href="#J" ;	}
		if (75 == Key)	{	KeyState= KeyState + "k" ; window.location.href="#K" ;	}
		if (76 == Key)	{	KeyState= KeyState + "l" ; window.location.href="#L" ;	}
		if (77 == Key)	{	KeyState= KeyState + "m" ; window.location.href="#M" ;	}
		if (78 == Key)	{	KeyState= KeyState + "n" ; window.location.href="#N" ;	}
		if (79 == Key)	{	KeyState= KeyState + "o" ; window.location.href="#O" ;	}

		if (80 == Key)	{	KeyState= KeyState + "p" ; window.location.href="#P" ;	}
		if (81 == Key)	{	KeyState= KeyState + "q" ; window.location.href="#Q" ;	}
		if (82 == Key)	{	KeyState= KeyState + "r" ; window.location.href="#R" ;	}
		if (83 == Key)	{	KeyState= KeyState + "s" ; window.location.href="#S" ;	}
		if (84 == Key)	{	KeyState= KeyState + "t" ; window.location.href="#T" ;	}
		if (85 == Key)	{	KeyState= KeyState + "u" ; window.location.href="#U" ;	}
		if (86 == Key)	{	KeyState= KeyState + "v" ; window.location.href="#V" ;	}
		if (87 == Key)	{	KeyState= KeyState + "w" ; window.location.href="#W" ;	}
		if (88 == Key)	{	KeyState= KeyState + "x" ; window.location.href="#X" ;	}
		if (89 == Key)	{	KeyState= KeyState + "y" ; window.location.href="#Y" ;	}

		if (80 == Key)	{	KeyState= KeyState + "z" ; window.location.href="#Z" ;	}

		if (192 == Key)	{	KeyState= KeyState + "æ" ; window.location.href="#Æ" ;	}
		if (222 == Key)	{	KeyState= KeyState + "ø" ; window.location.href="#Ø" ;	}
		if (221 == Key)	{	KeyState= KeyState + "å" ; window.location.href="#Å" ;	}
		window.status=KeyState;
	}
}	//*** keypressed() ***


//*********************************************************************
// TITLE:
//	Set language
// 
// DESCRIPTION: 
// 	Set language code for lang. specific routines
// 
// EXAMPLE:
//	<script>set_language(en);</script>
// 
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function set_language( language_code )
{
	global_language	= language_code;
}	//*** set_language() ***


//*********************************************************************
// TITLE:
//	Expand weekday
// 
// DESCRIPTION: 
// 	Return weekday as a string
//	Sunday		= 1
//	Saturday	= 7
// 
// EXAMPLE:
//	<script>document.write( expand_weekday( 1 );</script>
// 
// will display as:
// 	Sunday
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function expand_weekday( day_of_week )
{
	weekday	=
	[ "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"
		, "Friday", "Saturday"]

	return( weekday[day_of_week] );
}	//*** expand_weekday() ***

//----------------------------------------------------------------------

//*********************************************************************
// TITLE:
//	Expand month
// 
// DESCRIPTION: 
// 	Return name of month as a string
//	January		= 1
// 
// EXAMPLE:
//	<script>document.write( expand_month( 4 );</script>
// 
// will display as:
// 	April
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function expand_month( month_of_year )
{
	month_name	= 
	[ "", "January", "February", "March", "April", "May", "June"
		,"July", "August", "September", "October", "November"
		, "December" ];

	return( month_name[month_of_year] );
}	//*** expand_month() ***

//*********************************************************************
// TITLE:
//	Run clock on status line
// 
// DESCRIPTION: 
// 	Display date + time in window status
// 
// EXAMPLE:
//	<body onLoad="clock_status()" >
// 
// will display as:
// 	2002-02-28/21:59.04 (Friday February 28th)
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function clock_status()
{
	// Get time stamp
	var now		= new Date();

	// YYYY
	var year	= now.getYear();
	// MM		Note! getMonth returns 0-11
	var month	= ((now.getMonth()	< 10) ? "0" : "") + ( now.getMonth() + 1 );
	// DD
	var day		= ((now.getDate()	< 10) ? "0" : "") + now.getDate();
	// xxxday
	var day_of_week	= now.getDay() + 1;

	// hh
	var hours	= ((now.getHours()	< 10) ? "0" : "") + now.getHours();
	// mm
	var minutes	= ((now.getMinutes()	< 10) ? "0" : "") + now.getMinutes();
	// ss
	var seconds	= ((now.getSeconds()	< 10) ? "0" : "") + now.getSeconds();

	weekday	=
	[ "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]


	month_name	= 
	[ "", "January", "February", "March", "April", "May", "June", 
	"July", "August", "September", "October", "November", "December" ]

	window.status=
	(
		"" 
		+ year
		+ "-"
		+ month
		+ "-"
		+ day
		+ "/"
		+ hours
		+ ":"
		+ minutes
		+ ":"
		+ seconds
		+ " ("
		+ expand_weekday(day_of_week)
		+ " "
		+ day
		+ "th of "
		+ expand_month(now.getMonth() + 1)
		+ "). "
	);

	timerID = setTimeout( "clock_status()" ,1000);
	timerRunning = true;
}	//*** clock_status() ***


//*********************************************************************
// TITLE:
//	Action button
// 
// DESCRIPTION: 
// 	CSS formated action button
// 
// EXAMPLE:
//	<script>button( "Hello world", "http://clicketyclick.dk"
//	, "My homepage");</script>
// 
// will display as:
// 	[Hello world]
// 
//*********************************************************************
// 2003-02-28/Erik Bachmann
//*********************************************************************
function button(title, url, tooltip)
{
	var button_obj="<table align=left><tr><td nowrap><div class=\"bttn\">\n" +
		"<a href=\"" + url + "\" tooltip=\"" + tooltip + "\">" + 
		"<font class=\"snu\" color=\"#000066\">" +
		"&nbsp;" + title + "&nbsp;</font></a></font></div>" +
		"</td></tr></table>" ;

	document.write( button_obj ) ;
}	//*** button() ***

//----------------------------------------------------------------------

// The rest of this script is dedicated to Tool Tip functions!!!

///////////////////////////////////////////////////////////////////////
//
//	global.js - version 0.1.3
//
//	Copyright 2000, Mentor Systems Ltd.  All rights reserved.
//
//	Author: Austin David France - Mentor Systems Ltd
//
//	Amendments:
//
//	001 Sun 14th May 2000 - Austin David France - The Software Sorcerer
//		Added exception handler when defining a style sheet to handle
//		the fact that style sheets can't be loaded until at least one
//		style sheet exists.
//
//	002 Sun 14th May 2000 - Austin David France - The Software Sorcerer
//		Extended the MentorWebPage object to include a loadScript()
//		method for loading script source code.
//

///////////////////////////////////////////////////////////////////////
///////////////////////////// Date Object /////////////////////////////
///////////////////////////////////////////////////////////////////////


//
//	Extend the date object with some useful methods.
//

Date.now = function() {				// Get the current date in ms since 1970
	return new Date().getTime();
}

///////////////////////////////////////////////////////////////////////
/////////////////////////// Rectangle Object //////////////////////////
///////////////////////////////////////////////////////////////////////

function Rect(top, left, width, height) {
	this.top = top ? top : 0;
	this.left = left ? left : 0;
	this.width = width ? width : 0;
	this.height = height ? height : 0;
	this.bottom = this.top + this.height - 1;
	this.right = this.left + this.width - 1;
}

Rect.prototype.setWidth = function(w) { 
	this.width = parseInt(w);
	this.right = this.left + this.width - 1;
}

Rect.prototype.setHeight = function(w) { 
	this.height = parseInt(w);
	this.bottom = this.top + this.height - 1;
}

Rect.prototype.isEmpty = function() {
	return this.width == 0 || this.height == 0;
}

Rect.prototype.isInside = function(x,y) {
	return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom;
}

Rect.prototype.toString = function() {
	return 'Rect(' + this.left + ',' + this.top + ',' + this.width + ',' + this.height + ')';
}

///////////////////////////////////////////////////////////////////////
//////////////////////////// Element Object ///////////////////////////
///////////////////////////////////////////////////////////////////////

//	This object is designed to wrap up an object from the DOM of the
//	browser in order to provide additional and compatable functionality
//	not available using the native DOM.
//
//	Where practical, the DOM interface has been replicated.
//

function Element(obj) {

	// The DOM object reference
	this.el = obj;

	// Mirror some of the DOM collections
	if (this.el)
	{
		if (thePage.is.ie)
		{
			this.style		= obj.style;
			this.filters	= obj.filters;
			this.all		= obj.all;
		}
		else if (thePage.is.ns)
		{
			this.style		= obj;
			this.all		= null;		// TODO - How do we do this?
		}
	}

	// For inline method calling, return the new object
	return this;
}

///////////////////////////////////////////////////////////////////////

Element.prototype.toString = function() {
	return "Element(" + (this.el ? this.el.tagName : 'undefined') + ")";
}

///////////////////////////////////////////////////////////////////////

Element.prototype.all = function(what)
{
	if (this.el) {
		return this.el.all(what);
	}
	return null;
}

///////////////////////////////////////////////////////////////////////

function _Element_Evaluate(str)
{
	return eval(str);
}

///////////////////////////////////////////////////////////////////////

Element.prototype.eval = function(str) {
	if (typeof(this.el.eval) != 'function') {
		this.el.eval = _Element_Evaluate;
	}
	return this.el.eval(str);
} 

///////////////////////////////////////////////////////////////////////
//
// Synopsis:
//	obj.getWindowRect()
//
// Description:
//	Return a rectangle object relative to the origin of the client area
//	of the body of the current document.  The window area is the area
//	used by the element including it's border.
//
// Notes:
//	The Window Area also includes the elements scroll bars, margins
//	and padding.
//
// Return Value:
//	A Rect() object.
//

Element.prototype.getWindowRect = function()
{
	var rc = new Rect();
	if (this.el)
	{
		rc.top  = this.el.offsetTop;
		rc.left = this.el.offsetLeft;

		// See Measuring Element Dimension and Location from MSDN
		for (var o = this.el.offsetParent; o; o = o.offsetParent) {
			rc.top  += o.clientTop + o.offsetTop;
			rc.left += o.clientLeft + o.offsetLeft;
		}

		// The origin of elements positioned on a page is the top
		// left corner of the client area of the document body (or
		// so it seems).
		rc.left -= document.body.clientLeft;
		rc.top -= document.body.clientTop;

		// Set the width and height of the element to the offsetWidth
		// and offsetHeight which includes padding, margins and 
		// borders according the the documentation.
		rc.setWidth(this.el.offsetWidth);
		rc.setHeight(this.el.offsetHeight);
	}
	return rc;
}

///////////////////////////////////////////////////////////////////////
//
// Synopsis:
//	obj.getClientRect()
//
// Description:
//	Return a rectangle object relative to the current document that
//	defines the client area of the Element object.  The client area
//	is the area used by the element excluding it's border.
//
// Return Value:
//	A Rect() object.
//

Element.prototype.getClientRect = function()
{
	var rc = this.getWindowRect();
	if (this.el) {
		rc.top += this.el.clientTop;
		rc.left += this.el.clientLeft;
		rc.setWidth(this.el.clientWidth);
		rc.setHeight(this.el.clientHeight);
	}
	return rc;
}

///////////////////////////////////////////////////////////////////////
//
// Synopsis:
//	obj.moveIntoView(container)
//
// Description:
//	This method can be called to cause the left and top position of
//	the Element object to be adjusted so that the right and bottom
//	edges of the element are visible witin the specified container.
//	If the element is simply too large, the top and left positions are
//	simply clipped at the top & left most visble co-ordinate and the
//	right or bottom edges will remain not visible.
//
// Return Value:
//	A rectangle object containing the updated window rect of the 
//	element.
//	

Element.prototype.moveIntoView = function(container)
{
	if (!container) container = document.body;
	var rc = this.getWindowRect();
	var right = container.scrollLeft + container.clientWidth;
	if (rc.right > right) {
		this.el.style.left = right - rc.width;
		if (this.el.style.left < container.scrollLeft) { 
			this.el.style.left = container.scrollLeft;
		}
		rc = this.getWindowRect();
	}
	var bottom = container.scrollTop + container.clientHeight;
	if (rc.bottom > bottom) {
		this.el.style.top = bottom - rc.height;
		if (this.el.style.top < container.scrollTop) { 
			this.el.style.top = container.scrollTop;
		}
		rc = this.getWindowRect();
	}
	return rc;
}

///////////////////////////////////////////////////////////////////////

Element.prototype.centerInView = function(container)
{
	if (!container) container = document.body;
	if (this.el) {
		this.el.style.left = (container.clientWidth - this.el.offsetWidth) / 2;
		this.el.style.top  = (container.clientHeight - this.el.offsetHeight) / 2;
	}
}

///////////////////////////////////////////////////////////////////////

Element.prototype.findAttribute = function(name, accum) {

	var attr = null;
	for (var o = this.el; o; o = o.parentElement) {
		var v = o.getAttribute(name);
		if (v) {
			if (!accum) { attr = v; break; }
			attr = attr ? v + attr : v;
		}
	}
	return attr;
}

///////////////////////////////////////////////////////////////////////

Element.prototype.findElement = function(name) {

	name = name.toUpperCase();
	for (var o = this.el; o; o = o.parentElement) {
		if (o.tagName == name) {
			return o;
		}
	}
	return null;
}

///////////////////////////////////////////////////////////////////////
// Mentor Web Page interface - In here during development.
///////////////////////////////////////////////////////////////////////

function MentorWebPage (name)
{
	this.m_strName = name ? name : "thePage";

	// Add our selves to our own object pool.
	this.m_objPool = new Array();
	this.addToObjectPool(this);

	// The web page image pool (for pre-caching web page images)
	this.m_imgPool = new Array();
	this.m_imgLoading = 0;

	// Initialise browser compatability methods
	this._InitCompatability();
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.toString = function ()
{
	return this.m_strName;
}

///////////////////////////////////////////////////////////////////////
//	Browser Identification 
 
MentorWebPage.prototype.BrowserIs = function ()
{
	////////////////////////////////////////////////////////
	// Get the browser major and minor versions
	////////////////////////////////////////////////////////

    this.major  = parseInt(navigator.appVersion);
    this.minor  = parseFloat(navigator.appVersion);

	////////////////////////////////////////////////////////
	// Detect the O/S
	////////////////////////////////////////////////////////

	var i;
	var v = navigator.appVersion;
	this.nt  = (i = v.indexOf("Windows NT")) != -1;
	if (this.nt) {
		this.nt4 = v.charAt(i+10) == ";";
		this.nt5 = !this.nt4 && v.charAt(i+11) == "5";
	}

	////////////////////////////////////////////////////////
	// Internet Explorer Detection
	////////////////////////////////////////////////////////

    var agent = navigator.userAgent.toLowerCase();
	if (this.ie = agent.indexOf("msie"))
	{
		this.ie = true;
		this.ie3 = this.major < 4;
		this.ie4 = this.major == 4 && agent.indexOf("msie 5.0") == -1;
		this.ie5 = this.major == 4 && agent.indexOf("msie 5.0") != -1;
	}

	////////////////////////////////////////////////////////
	// Netscape Detection
	////////////////////////////////////////////////////////

    if (agent.indexOf('mozilla') != -1
				&& agent.indexOf('spoofer') == -1
				&& agent.indexOf('compatible') == -1
				&& agent.indexOf('opera') == -1
				&& agent.indexOf('webtv') == -1)
	{
		 this.ns = true;
		 this.ns2 = this.major == 2;
		 this.ns3 = this.major == 3;
		 this.ns4 = this.major == 4;
		 this.ns5 = this.major >= 5;
	}

	// Check for DHTML support
	this.dhtml = this.major >= 4;
}

///////////////////////////////////////////////////////////////////////
//	Browser Compatability 

MentorWebPage.prototype._InitCompatability = function()
{
	// Detect browser version
	this.is = new this.BrowserIs();

	// Define the "layers" collection (for IE)
	if (!document.layers && document.all) {
		document.layers = document.all;
	}

	// Define the "all" collection (for netscape)
	if (!document.all) document.all = document;
}

MentorWebPage.prototype.layers = function(name)
{
	return document.layers(name);
}

MentorWebPage.prototype.all = function(name)
{
	return document.all(name);
}

///////////////////////////////////////////////////////////////////////

function MentorWebPage_OnImageLoad (obj)
{
	obj.OnImageLoad();
}

MentorWebPage.prototype.OnImageLoad = function()
{
	window.status = this + ".OnImageLoad";
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.loadImage = function(src)
{
	var imgId = 0;
	this.m_imgPool[imgId = this.m_imgPool.length] = new Image();
	this.m_imgLoading ++;
	// this.m_imgPool[imgId].onload = new Function("return eval(this.toString('OnImageLoad'));");
	this.m_imgPool[imgId].src = src;
	return this.m_imgPool[imgId];
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.addToObjectPool = function(obj)
{
	var objId = 0;
	this.m_objPool[objId = this.m_objPool.length] = obj;
	obj.m_nObjectId = objId;
	obj.m_strName = "thePage.m_objPool[" + obj.m_nObjectId + "]";
	obj.toString = MentorWebPage.prototype.toString;
	return objId;
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.loadStyleSheet = function(url, i)
{
	try {
		document.styleSheets(0).addImport(url, i);
	}
	catch(e) {
		document.write('<link rel="StyleSheet" type="text/css" href="' + url + '">');
		document.styleSheets(0).href = url;
	}
}

MentorWebPage.prototype.loadScript = function(url, language)
{
	document.write('<script language="' + (language ? language : 'JavaScript') + '" src="' + url + '></script>');
}

///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.scriptLoaded = function(scr)
{
	scr = "{" + scr + "}";
	if (typeof(this.m_strScriptsLoaded) == 'undefined')
	{
		this.m_strScriptsLoaded = scr;
	}
	else
	{
		if (this.m_strScriptsLoaded.indexOf(scr) == -1) {
			this.m_strScriptsLoaded += scr;
		}
	}
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.disableContextMenu = function() {
	document.oncontextmenu = function() {
		return false;
	}
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.enableContextMenu = function() {
	document.oncontextmenu = null;
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.cookieEnabled = function ()
{
	return navigator.cookieEnabled;
}

///////////////////////////////////////////////////////////////////////////////
//
// Synopsis:
//	MentorWebPage.readCookie(name)
//
// Description:
//	Retrieve the value of the cookie specified by "name".
//
// Return Value:
//	If the cookie exists, the value of the cookie is returned, otherwise
//	null is returned.
//

MentorWebPage.prototype.readCookie = function(name, def)
{
	var theBigCookie;

	// If no cookies on this page, then fail now.
	if ((theBigCookie = document.cookie).length > 0)
	{
		// there is a cookie, see if the cookie we want exists
		var firstChar = theBigCookie.indexOf(name + '=');

		// if the cookie was found
		if (firstChar != -1)
		{
			// skip 'name' and '='
			firstChar += name.length + 1;

			// Find the end of the value string (i.e. the next ';').
			var lastChar = theBigCookie.indexOf(';', firstChar);
			if (lastChar == -1) {
				lastChar = theBigCookie.length;
			}

			// return the cookie value
			return unescape(theBigCookie.substring(firstChar, lastChar));
		}
	}
	
	// There was no cookie of that name, return the default if defined or null.
	return def ? def : null; 
}

///////////////////////////////////////////////////////////////////////
//
// Synopsis:
//	MentorWebPage.setCookie(name, value, hours, path, domain, secure)
//
// Description:
//	Sets the "value" of the cookie specified by "name" for the optionally
//	specified path and domain.
//
//	If "hours" is specified then this is used to set an expiry time for
//	the cookie.  If "hours" is a number, then it is the number of hours 
//	before the cookie should expire.  If "hours" is a string, then it is 
//	interpreted as a date string specifying the time the cookie should
//	expore.
//
//	If "secure" is specified then this is ... ??? TODO 
//
// Return Value:
//	If the cookie exists, the value of the cookie is returned, otherwise
//	null is returned.
//

MentorWebPage.prototype.setCookie = function (name, value, hours, path, domain, secure)
{
	// Don't waste your time if the browser doesn't accept cookies.
    if (this.cookieEnabled())
	{
		// Netscape Navigator 2 cannot handle Dates, so skip this part
		if (hours && !this.ns2)
		{
			var numHours = null;

			// already a Date string
			if ( (typeof(hours) == 'string') && Date.parse(hours) )
			{
				numHours = hours;
			}
			else
			{
				// calculate Date from number of hours
				if (typeof(hours) == 'number')
				{
					numHours = Date.now() + (hours * 3600000);
					numHours = (new Date(numHours)).toGMTString();
				}
			}
		}
		
		// Set the cookie, adding any parameters that were specified.
		document.cookie = name	+ '=' + escape(value)
								+ (numHours ? (';expires=' + numHours) : '')
								+ (path ? ';path=' + path : '')
								+ (domain ? ';domain=' + domain : '')
								+ ((secure && (secure == true)) ? '; secure' : '');
	}
}

///////////////////////////////////////////////////////////////////////////////
//
// Synopsis:
//	MentorWebPage.killCookie(name, path, domain)
//
// Description:
//	Delete (kill) the cookie who's name is "name".  If domain and or path are
//	specified, the cookie within that path/domain is killed.
//
//	The cookie is killed by making it expired.
//
// Return Value:
//	None:
//
MentorWebPage.prototype.killCookie = function(name, path, domain)
{
	// We need the value to kill the cookie
  var theCookie = readCookie(name);
  
  // get the time of the recent past
  var exp = new Date(Date.now() - 1);
  
  // set an already-expired cookie of the same name and value
  document.cookie = name + "=" + theValue
								+ "; expires=" + exp.toGMTString()
								+ (path ? ';path=' + path : '')
								+ (domain ? ';domain=' + domain : '');

} 

///////////////////////////////////////////////////////////////////////

MentorWebPage.prototype.hideSupportInfo = function() {
	if (this.m_objSupportInfo) {
		this.m_objSupportInfo.style.display = 'none';
	}
}

MentorWebPage.prototype.showSupportInfo = function()
{
	var strHTML;

	alert( "showSupportInfo(639)" );
	// Make sure the Support Info layer is available.
	this.m_objSupportInfo = new Element(thePage.layers("$$SupportInfo"));
	if (!this.m_objSupportInfo.el)
	{
		strHTML = '<table id="$$SupportInfo" style="position:absolute;z-index:32766;'
								+ 'background-color: white; font-size: 10pt;'
								+ 'border-top: 4px #D0D0D0 solid;'
								+ 'border-left: 4px #D0D0D0 solid;'
								+ 'border-right: 4px black solid;'
								+ 'border-bottom: 4px black solid;'
								+ 'margin:10px; padding:10px;">'
						+ '<tr><td valign="top" id="$$SupportInfoDetails"></td></tr></table>';
		document.body.insertAdjacentHTML("BeforeEnd", strHTML);
		this.m_objSupportInfo = new Element(thePage.layers("$$SupportInfo"));
	}
	alert( "showSupportInfo(655)" );
	// Generate the support info popup window.
	strHTML = '<table width="100%"><tr><td colspan="3" bgcolor="blue">';
	alert( "showSupportInfo(659)" );
	strHTML = strHTML
					+ '<table width="100%"><tr style="color:white; font-weight: bold;">'
						+ '<td>'
						+	'<img border="0" src="'+ picdir + 'info-32x32.gif" align="absmiddle">'
						+	'&nbsp;<FONT SIZE="+1">Support Info:</FONT></td>'
						+ '<td align="right">'
						+	'<img style="cursor:hand" onclick="thePage.hideSupportInfo()"'
						+		' border="0" align="right" src="' + picdir + 'cross.gif">'
						+	'</td>'
					+ '</tr></table>';
	alert( "showSupportInfo(669)" );
	strHTML = strHTML

				+ '</td></tr>'
				+ '<tr><td width="10">&nbsp;</td><td>'
				+ '<table width="100%">';
	alert( "showSupportInfo(675)" );
	strHTML = strHTML

				// Support Info Content
				+ '<tr><td colspan="2">&nbsp;</td></tr>'
				+ '<tr><td colspan="2" bgcolor="#808080" style="color:white;font-weight:bold;">'
					+ 'Browser Details:</td></tr>'
;	alert( "showSupportInfo(680)" );	strHTML = strHTML
				+ '<tr><td nowrap>appName:</td><td>' + navigator.appName + '</td></tr>'
				+ '<tr><td nowrap>appVersion:</td><td>' + navigator.appVersion + '</td></tr>'
				+ '<tr><td nowrap>cookieEnabled:</td><td>' + thePage.cookieEnabled() + '</td></tr>'
;	strHTML = strHTML
				+ '<tr><td colspan="2">&nbsp;</td></tr>'
				+ '<tr><td colspan="2" bgcolor="#808080" style="color:white;font-weight:bold;">'
					+ 'Page Details:</td></tr>'
;	alert( "showSupportInfo(690)" );	
	var strHTML2 = 
				'<tr><td nowrap>URL:</td><td>' + document.URL + '(' + document.readyState + ')</td></tr>'
				+ '<tr><td nowrap>Referrer:</td><td>' + document.referrer + '</td></tr>'
				+ '<tr><td nowrap>Last Modified:</td><td>' + document.lastModified + '</td></tr>'
				+ '<tr><td nowrap>File Created:</td><td>' + document.fileCreatedDate + '</td></tr>'
				+ '<tr><td nowrap>File Modified:</td><td>' + document.fileModifiedDate + '</td></tr>'
				+ '<tr><td nowrap>File Size:</td><td>' + document.fileSize + '</td></tr>'
				+ '<tr><td nowrap>Design Mode:</td><td>' + document.designMode + '</td></tr>'
				+ '<tr><td nowrap>thePage Object:</td><td>'
					+ this.m_strName + ' (Version ' + MentorWebPage.m_strVersion + ')'
					+ '</td></tr>'

;	alert( "showSupportInfo(703)" );	strHTML2 = strHTML2

				+ '<tr><td colspan="2">&nbsp;</td></tr>'

				+ '</table>'
				+ '</td>'
				+ '<td width="10">&nbsp;</td>'
				+ '</tr></table>';
	alert( "showSupportInfo(711)" );
	// Show the info dialog.
	this.m_objSupportInfo.el.all("$$SupportInfoDetails").innerHTML = strHTML + strHTML2;
	this.m_objSupportInfo.style.display = 'block';
	this.m_objSupportInfo.centerInView();
}

///////////////////////////////////////////////////////////////////////

MentorWebPage.m_strVersion = "0.1.2";

///////////////////////////////////////////////////////////////////////

var thePage = new MentorWebPage("thePage");	// The one and only "thePage" object

///////////////////////////////////////////////////////////////////////
//
//	Signal that global.js has been included
//

thePage.scriptLoaded("global.js");





//////////////////////////////////////////////////////////////////////////////
//
//	tooltip.js - Copyright 2000 - Mentor Systems Ltd
//
//	Version 1.0.004
//
//	Mentor Tooltip Support
//
//	Author: Austin David France - adf@mentor-systems.com
//
//	Written for Microsoft Internet Explorer version 5.0
//
//	Comments & Suggestions to: adf@mentor-systems.com
//
//	Amendments:
//
//	07 April 2000 - Austin David France - Mentor Systems Ltd
//	- Added code to prevent tooltip going off edge of window causeing a scroll
//		bar to be produced.
//
//	05 May 2000 - Austin David France - Mentor Systems Ltd
//	- Rewritten to use global.js which define the API for web page development
//
//	05 May 2000 - Audtin David France - Mentor Systems Ltd
//	- Converted to use Element.getWindowRect() and current understanding of
//	  of to calculate element position and sizes.
//
//	08 May 2000 - Audtin David France - Mentor Systems Ltd
//	- Reworked the tooltip sizing and positioning to work in all situations
//	  based upon new understanding of the various size and position properties
//	  in the DOM (The MSDN Documentation contains incorrect information!).
//	  Also, now call moveIntoView() method of the Element object to bring the
//	  tip into view.  Sizing logic still done here.
//
//////////////////////////////////////////////////////////////////////////////

if (typeof(thePage) != 'object') {
	alert('tooltip.js requires /library/objects/global.js');
}

//
// This function is called if the mouse has not been moved for 
// a certain period of time so that the tip can be displayed.
//
function ToolTip_ShowToolTip()
{
	// Cancel the timer - it there is one active.
	if (this.timerId) {
		window.clearTimeout(this.timerId);
		this.timerId = null;
	}

	if (this.obj)
	{
		// whilst the cursor is over the item with a tooltip, show there is 
		// a tooltip by displaying the help cursor.
		try {
			this.obj.runtimeStyle.cursor = this.obj.style.cursor;
		}
		catch(e) { }
	}

	// Because the other frame may still be loading the page we may
	// not actually have a tooltip object at the moment so we test
	// again for it's presence.
	// We need to do this within a try catch handler so that we can
	// detect an access denied error which we might get if the document
	// in the target frame is not part of the same site.
	// This happens for example, if a page cannot be displayed and
	// IE displays one of it's standard error pages.
	var theDocument;
	try {
		theDocument = this.targetFrame.document;
	}
	catch(error) {
		theDocument = null;
	}
	
	// If we havnt got a document then simply don't do anything.
	if (theDocument)
	{
		// Get a reference to the document and document body
		// we will be manipulating
		var theDocBody  = theDocument.body;

		// If this currently loaded document does not have the
		// "$$tooltip$$" table, the give it one.
		if (!theDocument.all("$$tooltip$$"))
		{
			theDocBody.insertAdjacentHTML('BeforeEnd',this.html);
		}
		
		// Get a reference to the "$$tooltip$$" element and initialise
		// the position
		var tooltip = new Element(theDocument.all("$$tooltip$$"));

		//2000-12-12/erbp this.x + 30 to avoid that cursor hides tooltip
		tooltip.el.style.left = this.targetFrame == window ? this.x + 30: 0;
		tooltip.el.style.top = this.y;

		// Get a reference to the "tooltiptext" element and feed it the
		// HTML code to display.  Try and find it within the tooltip
		// object first, but if that fails (it seems to if $$tooltip$$ is
		// a DIV, but works if $$tooltip$$ is a TABLE??) then look in the
		// entire document for the tooltiptext.
		var tooltiptext = tooltip.all("$$tooltiptext$$");
		if (!tooltiptext) {
			tooltiptext = theDocument.all("$$tooltiptext$$");
		}

		// As long as there is somewhere to stick the tooltip text
		// then show it.
		if (tooltiptext)
		{
			var strTip = "";
			if (this.iconImg)
			{
				strTip += '<table cellspacing="0" cellpadding="2" border="0">'
								+ '<tr><td valign="top">'
								+ '<img border="0" align="absmiddle" src="' + this.iconImg + '">'
								+ '</td><td class="tooltip" valign="top" width="100%">';
			}
			strTip += this.tooltip;
			
			if (this.iconImg)
			{
				strTip += '</td></tr></table>';
			}
			tooltiptext.innerHTML = strTip;
		}

		// Unhide the tooltip - this will cause it's display size to be
		// calculated
		tooltiptext.style.width = null;
		tooltip.el.style.width = null;
		tooltip.el.style.height = null;
		tooltip.el.style.display = 'block';
		this.isVisible = true;

		// If the tooltip is just too wide, the force it to be a 3/4 of 
		// the visible body width
		var rc = tooltip.getWindowRect();
		if (rc.width > theDocBody.clientWidth) {
			tooltip.el.style.width = (theDocBody.clientWidth / 4) * 3;
			tooltiptext.style.width = null;
			rc = tooltip.getWindowRect();
		}

		// if the tooltip goes off the right of the window, then as
		// long as the width is still greater than the height, reduce
		// the width so the tip will fit.
		var right = theDocBody.scrollLeft + theDocBody.clientWidth;
		if (rc.right > right)
		{
			var nWidth = right - rc.left;
			if (nWidth > rc.height)
			{
				tooltip.el.style.width = nWidth;
				tooltiptext.style.width = null;

				// Reset rectangle after adjustment
				rc = tooltip.getWindowRect();
			}
		}

		// Try and force the tooltip into view.  For some reason, if
		// we don't actually set the width and height before we do the
		// move, IE seems to reserve the right to change it's mind about
		// the width and we get unpredictable results.  To avoid this
		// we set the final width and height (decided above) before we
		// try and move the element.
		tooltip.style.width = rc.width;				// IE5: IMPORTANT
		tooltip.style.height = rc.height;			// IE5: IMPORTANT
		tooltip.moveIntoView(document.body);

		// Arrange for the tooltip to automatically disappear after
		// a specified amount of time minutes
		var timeout = this.HideAfter ? this.HideAfter : 30000;
		var exec = this.toString() + '.Cancel();';
		this.timerId = window.setTimeout(exec, timeout, "JavaScript");
	}
}

//
// Called when the mouse moves over an item that may have a tooltip associated
// with it.
//
function ToolTip_MouseMove(obj)
{
	// Can't do anything if we have no frame to work in.
	if (!this.isVisible && this.targetFrame)
	{
		// Check this item really does have a tooltip.
		this.tooltip = obj.getAttribute(this.attrName);
		if (this.tooltip != null)
		{
			// whilst the cursor is over the item with a tooltip, show there is 
			// a tooltip by displaying the help cursor.
			try {
				obj.runtimeStyle.cursor = 'help';
			}
			catch(e) { }
			
			// Calculate where the tooltip should appear.  Store the mouse position
			// as a document.body origin relative co-ordinates.
			this.x = ((window.event.x - document.body.clientLeft) + document.body.scrollLeft);
			this.y = ((window.event.y - document.body.clientTop) + document.body.scrollTop);
			this.obj = obj;

			// Allow for the tooltip to be some java or VB script
			if (this.tooltip.substr(0,11).toLowerCase() == "javascript:"
				|| this.tooltip.substr(0,14).toLowerCase() == "javascript1.2:"
				|| this.tooltip.substr(0,8).toLowerCase() == "jscript:"
				|| this.tooltip.substr(0,9).toLowerCase() == "vbscript:")
			{
				this.tooltip = eval(this.tooltip);
			}

			// If there is currently a tooltip timer active for this tip
			// then clear it.
			if (this.timerId != null) {
				window.clearTimeout(this.timerId);
			}

			// Build method call to display the tooltip.
			var exec = this.toString() + '.ShowToolTip()';

			// Arrange for the method that will display the tooltip to
			// be called
			var timeout = this.PopUpAfter ? this.PopUpAfter : 10;
			this.timerId = window.setTimeout(exec, timeout, "JavaScript");
		}
	}
}

//
// Called to cancel the 
//
function ToolTip_Cancel()
{
	// Cancel and popup or hide timer that may be running
	if (this.timerId != null) {
		window.clearTimeout(this.timerId);
		this.timerId = null;
	}

	// Make sure it is hidden
	this.Hide();
}

//
// Called to hide the tooltip if displayed.
//
function ToolTip_Hide()
{
	// If the tooltip is visible
	if (this.isVisible)
	{
		if (this.targetFrame
			&& this.targetFrame.document
			&& this.targetFrame.document.all("$$tooltip$$"))
		{
			this.targetFrame.document.all("$$tooltip$$").style.display = "none";
			this.isVisible = false;
		}
	}
}

//
// Function to generate the complex HTML required for a fancy speach bubble.
//
// Synopsis:
//	var strHtml = ToolTip_MakeBubble(urlImage = null, urlBaseEdge = null, color = null);
//
// Description:
//	Call this method to generate the HTML required to procude a fancy speach
// 	bubble type popup window.
//
//	The "urlImage" optionally specified the URL of an image that will be
//	"speaking" the speach bubble.
//
//	The "urlBaseEdge" optionally specifies alternative images to use for the
//  edge of the speach bubble.
//
//	The "color" can be used to modify the background color of the speach 
//	bubble.  This should generally match the color used by the border images.
//
//	All arguments are option, and when left out cause the default values to
//	be used.
//
// Return Value:
//	The HTML code as a string.
//
function ToolTip_MakeBubble(img, base, color, style)
{
	// Default the base URL for the edges of the tooltip window 
	if (!base) base = "/library/objects/tooltip/images/tip-border-";
	if (!color) color = "#DCDC5E";

	// Arrange for the images referenced by the HTML just generated will
	// be pre-loaded so they appear quickly.
	window.status = 'Downloading images ...';
	var images = new Array(img ? 9 : 8);
	images[0] = new Image(); images[0].src = base + 'tl.gif';
	images[1] = new Image(); images[1].src = base + 't.gif';
	images[2] = new Image(); images[2].src = base + 'tr.gif';
	images[3] = new Image(); images[3].src = base + 'l.gif';
	images[4] = new Image(); images[4].src = base + 'r.gif';
	images[5] = new Image(); images[5].src = base + 'bl.gif';
	images[6] = new Image(); images[6].src = base + 'b.gif';
	images[7] = new Image(); images[7].src = base + 'br.gif';
	images[8] = new Image(); images[8].src = img;
	if (!document.tooltipImages) {
		document.tooltipImages = images;
	} else {
		var a = document.tooltipImages;
		document.tooltipImages = a.concat(images);
	}
	window.status = window.defaultStatus;

	// Build the table that will be used for the popup window.
	var strHtml =
		'<TABLE id="$$tooltip$$"'
			+ ' style="display:none; position:absolute; z-index: 32767;'
			+ (style ? style : 'width:400;') + '"'
			+ ' cellspacing="0" cellpadding="0">'
			+ '<TR>'

	// If an image url was supplied then we place it in a column to the left of the
	// actual tip.
	if (img) {
		strHtml += '<TD valign="bottom">'
					+ '<IMG border="0" src="' + img + '" align="center">'
					+ '</TD>';
	}

	// Using the standard images and color define the tip window.
	strHtml	+='<TD valign="top">'
			+ '<TABLE cellspacing="0" cellpadding="0">'
			+ '<TR>'
			+ '<TD width="10" height="10">'
			+ '<IMG border="0" src="' + base + 'tl.gif" width="10" height="10">'
			+ '</TD>'
			+ '<TD height="10" background="' + base + 't.gif">'
			+ '<IMG src="' + base + 't.gif" width="1" height="10">'
			+ '</TD>'
			+ '<TD width="15" height="10">'
			+ '<IMG border="0" src="' + base + 'tr.gif" width="15" height="10">'
			+ '</TD>'
			+ '</TR>'
			+ '<TR>'
			+ '<TD width="10" background="' + base + 'l.gif">'
			+ '<IMG src="' + base + 'l.gif" width="10" height="1">'
			+ '</TD>'
			+ '<TD bgcolor="' + color + '"><span class="tooltip" id="$$tooltiptext$$"></span></TD>'
			+ '<TD width="15" background="' + base + 'r.gif">'
			+ '<IMG src="' + base + 'r.gif" width="15" height="1">'
			+ '</TD>'
			+ '</TR>'
			+ '<TR>'
			+ '<TD width="10" height="10">'
			+ '<IMG border="0" src="' + base + 'bl.gif" width="10" height="10">'
			+ '</TD>'
			+ '<TD height="10" background="' + base + 'b.gif">'
			+ '<IMG src="' + base + 'b.gif" width="1" height="10">'
			+ '</TD>'
			+ '<TD width="15" height="10">'
			+ '<IMG border="0" src="' + base + 'br.gif" width="15" height="10">'
			+ '</TD>'
			+ '</TR>'
			+ '</TABLE></TD>';

	// Finally, terminate the table
	strHtml += '</TR></TABLE>';

	// Return the resulting HTML
	return strHtml
}

//
// ToolTip Event Handlers
//
//	The tooltip object installs these as object methods and arranges for
//	the document event handlers to call these methods on the actual tooltip
//	object receiving the event.  If there are several tooltip objects,
//
function ToolTip_OnMouseMove() {
	var obj = event.srcElement;
	if (obj.getAttribute(this.attrName)) {
		this.MouseMove(event.srcElement);
	}
}
function ToolTip_OnMouseOut() {
	var obj = event.srcElement;
	if (obj.getAttribute(this.attrName)) {
		this.Cancel();
	}
}
function ToolTip_OnClick() {
	var obj = event.srcElement;
	if (obj.getAttribute(this.attrName)) {
		this.Cancel();
	}
}

function ToolTip_OnDocLoad() {
	// Register this object for the following document events
	document.attachEvent("onmousemove", new Function( "return " + this.toString() + ".OnMouseMove();"));
	document.attachEvent("onmouseout",	new Function( "return " + this.toString() + ".OnMouseOut ();"));
	document.attachEvent("onclick",		new Function( "return " + this.toString() + ".OnClick    ();"));
}

//
// The tooltip object
//
// Synopsis:
//	var MyToolTips = new ToolTip(window = window, html = <standard tool tip>);
//
// Examples:
//	// Simply construction, provides default tooltip functionality.
//	var MyToolTips = new ToolTip();
//
//	// Allows control over where the tooltip will actually be displayed
//	var MyToolTips = new ToolTip(parent.frames.myframe);
//
//	// Create a tooltip using custom HTML.  Alows creation of fancy popup windows etc.
//	var MyToolTips = new ToolTip(null, strHtml);
//
//	// Optionaly control various timings.
//	MyToolTips.PopUpAfter = 1000;	// Popup after 1000 ms
//	MyToolTips.HideAfter = 30000;	// Hide after 30 seconds (30000 ms)
//	
function ToolTip(target, html, iconImg) {

	// Store a reference to this object in our global object pool
	thePage.addToObjectPool(this);

	// Initialise the object properties
	this.targetFrame = target ? target : window;
	this.timerId = null;
	this.iconImg = iconImg;

	// This allows support for multiple tooltip styles on one page by creating
	// several tooltip objects, and modifying this property to contain the
	// name of the attribute to use for the tooltip text.
	this.attrName = "tooltip";

	// Store the passed tooltip HTML or create our own simple tooltip style
	// popup window.
	this.html = html ? html
				: '<TABLE id="$$tooltip$$" cellspacing="0" cellpadding="1"'
					+ ' style="display:none; position:absolute;'
						+ ' z-index: 32767; border: 1px solid black;'
						+ ' background-color: INFOBACKGROUND;">'
					+ '<TR><TD><SPAN class="tooltip" id="$$tooltiptext$$">'
					+ '</SPAN></TD></TR></TABLE>';

	// Define the object methods
	this.MouseMove   = ToolTip_MouseMove;
	this.ShowToolTip = ToolTip_ShowToolTip;
	this.Hide		 = ToolTip_Hide;
	this.Cancel		 = ToolTip_Cancel;
	this.OnMouseMove = ToolTip_OnMouseMove;
	this.OnMouseOut  = ToolTip_OnMouseOut;
	this.OnClick     = ToolTip_OnClick;
	this.OnDocLoad   = ToolTip_OnDocLoad;

	// Arrange for this tooltip object to become active when the page has completed loading
	window.attachEvent("onload",		new Function( "return " + this.toString() + ".OnDocLoad  ();"));
}

////////////////////////////////////////////////////////////////////////////////////////
// Example Usage (Simple): This gives standard tooltip functionality with minimal effort.
////////////////////////////////////////////////////////////////////////////////////////
//
//	<script language="JavaScript">
//		var tips = new ToolTip();
//	</script>
//
//	<TABLE><TR>
//	<TD id=button tooltip="This is the text (HTML) of the tooltip">
//	</TD>
//	</TR></TABLE>
//

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Example Usage (Fancy):  This uses a fancy speach bubble style tip taken from on of our intranet sites.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Because there is not enough room in the contents frame which is what has the tips on our site, the tip 
// is actually displayed in the main frame of the site, virtically aligned with the object the tip is for.
// Because we use custom HTML for our tip window, this looks fine.  Looks a little odd (detached) if the
// standard tooltip HTML is used however.
//
// Note: The images referenced in the custom HTML are not included.  They are
//
//	tip-border-??.gif - Fancy rounded borders for the tooltip.  tl=top left, br=bottom right, and so on.
//	scribe-bug.gif	  - Our little "bug" character who helps you.  He visually speaks the tip in a speach bubble.
//
// The custom HTML must have two special id's.
//
//	 $$tooltip$$ is the main element.  This is used to control position and visibility.
//	 $$tooltiptext$$ is the element who's inner HTML will be set to the text (or HTML) of the tooltip.
//
// To simplify the creation of the HTML for a speach bubble, the tooltip script provides a method called
// ToolTip_MakeBubble() which can be used to generate the speach bubble HTML using the default images or
// custom ones supplied.  See the comments at the top of the function definition.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// <script language=JavaScript>
//
// // Define the tooltips for each button.  We pick this text up when showing the tooltip using the
// // embedded scripting facility provided by the tooltip object.
// var tipText = new Array(
//		'tip 1', 'tip 2', 'tip 3', 'tip 4', 'you get the idea'
//	);
//
// // Pick up the output frame (scribe) if it is defined.
// var frame = null;
// if (parent && parent.frames && parent.frames.output) {
// 	frame = parent.frames.output;
// }
//
// // Create our tooltip object.
// var objToolTip = new ToolTip(
//			frame,
//			ToolTip_MakeBubble("/scribe/images/scribe-bug.gif", "/scribe/images/tip-border-", "#DCDC5E")
//		);
// </script>
//
// ...
//
// <!-- The tooltip for this option is actually some javascript that resoves to some text -->
// <!-- In this example, we use a table cell.  However, a tooltip can be applied to any   -->
// <!-- type of element. -->
// <TR>
//   <TD id="button" tooltip="javascript:tipText[0]">Unclassified</TD>
// </TR>
// <!-- We could just as easily call a function to work out the tip text.  The return -->
// <!-- value should be the tip text to use. -->
// <TR>
//   <TD id="button" tooltip="javascript:GoFindTipText(this);">Unclassified</TD>
// </TR>
//
// ...
//




//*** End Of File *****************************************************/
