/*
 * Common JavaScript functions for AcmeBase
 *
 * Copyright (c) 2004 Mackley F. Pexton.  All rights reserved.
 */

/*
 * The following are common routines that should be included in every page
 * requiring interaction from the user. It defines a common event handler
 * capturing user's mouse clicks and key codes, and it includes the functions
 * used to open the multitude of different types of windows for the system.
 */

self.focus();	// Netscape gets confused which window should be on top
(new Image).src = "/images/wait.gif";	// Preload for Mozilla, otherwise image 
					// doesn't appear on the message window.

/*
 * Event handlers
 */

// Assign keypress event handler only if not assigned before
if (!window.document.onkeypress) window.document.onkeypress = common_keypress;

function common_keypress(evt) {
	evt = (evt) ? evt : ((window.event) ? window.event : null);

	var unicode = evt.charCode ? evt.charCode : evt.keyCode;
	switch (unicode) {
	case 27:	// escape key
		window.close();
		return true;

	case 32:		// space key
		/*
		 * Ctrl-Space bar displays the console screen.
		 */
		if (evt.ctrlKey) {
			if (typeof window.console == "function") {
				console();
				return false;
			}
		}
		return true;
	}
}

/*
 * Button functions
 */

consoleProg = "/cgi-bin/console.cgi";
consoleName = "console";

function console() {

	// Open console window.

	if (window.name == consoleName) {
		// Current window is console window.
		location.href = consoleProg;		// refresh
	}
	else {
		var settings = "menubar,status,resizable,scrollbars" + 
		  ",location,toolbar,width=660,height=640";

		var w = window.open("", consoleName, settings);
		w.focus();		// bring to forefront

		if (!w.isConsoleLoaded) {	// see console.cgi
			// Load new copy.
			w.location.href = consoleProg;
		}
	}
}

/*
 * Image highlight functions
 *
 * The following functions highlight images by swapping the source of the
 * image tag graphic with a file name that has the string '_hilite' appended
 * to its name.
 *
 * A four state button can be simulated simply by altering the global variables
 * hilite_image_obj and hilite_image_orig during an onClick event.
 */

var hilite_image_obj;		// image object highlight
var hilite_image_orig = "";	// image changed to highlight image (original)

function hilite(img) {

	if (hilite_image_orig != "") unhilite(img);	// safety

	hilite_image_obj = img;
	hilite_image_orig = img.src;

	img.src = hilite_image_orig.substring(0, hilite_image_orig.indexOf(".gif")) +
	  "_hilite.gif";
}

function unhilite(img) {
	
	if (hilite_image_orig != "") {
		hilite_image_obj.src = hilite_image_orig;
		hilite_image_orig = "";
	}
}

/*
 * Document element highlight functions.
 *
 * The following functions highlight document elements by adding and removing
 * the string "-hilite" (or the current setting of the HighlightString variable)
 * to their class attribute names. The actual highlight codes are defined in CSS.
 */

if (!window.NoHiLo) NoHiLo = false;	// flag usually defined elsewhere

if (!window.HighlightString) HighlightString = '-hilite';
var highlight_re = new RegExp(HighlightString+'$');

function hi(e) {
	// Highlight a document element by adding "-hilite" to its class name.
	// Note: because of increasing use of multiple class names, the suffix
	// is added to the first class name.

	if (NoHiLo) return;	// user option flag
	if (!e)  return;

	var class_name = e.className.replace(/(\s.*)/,'');
	e.className = (class_name == e.className)
		    ? class_name + HighlightString
		    : class_name + HighlightString + RegExp.$1;
}
function lo(e) {
	// Un-highlight an element by removing "-hilite" suffix from its class name.

	if (NoHiLo) return;	// user option flag
	if (!e)  return;

	e.className = e.className.replace(highlight_re,"");
}

/*
 * Automatically refresh screen after editing data.
 */

if (!window.AutoRefresh) AutoRefresh = false;	// user option flag set elsewhere

function auto_refresh() { if (AutoRefresh) self.location.reload(true) }

/*
 * Buffered output to document
 *
 * The following object buffers output to the document and then writes it
 * all at once when the flush() or close() method is invoked. Writing to
 * a window document is slow so this speeds it up when there are many calls
 * to document.write().
 */

function DocBuf(doc) {
	this.d = doc ? doc : self.document;
	this.buf = '';
}
DocBuf.prototype.open = function()	{ this.d.open(); }
DocBuf.prototype.close = function()	{ this.flush(); this.d.close();	}
DocBuf.prototype.write = function(s)	{ this.buf += s; }
DocBuf.prototype.writeln = function(s)	{ this.buf += s+'\n'; }
DocBuf.prototype.flush = function()	{ this.d.write(this.buf); this.buf = ''; }

/*
 * New target function
 *
 * Javascript routines are used to open windows so that different type of 
 * windows have a similar size and appearance. However, using the href
 * attribute in a <a> tag like:
 *	<a href="javascript:open_form(url,window_name)">Open Form</a>
 * causes the link to be inoperable whenever Javascript is turned off,
 * which usually happens in email.
 *
 * The new_target() function is designed to be used as an onClick event
 * in an <a> tag which opens a new window and then assigns the newly
 * opened window name to the target attribute of the <a> tag. This allows
 * the <a> links to operate when JavaScript is not available, but still
 * opens consistant type windows when it is.
 *
 * Example:
 *	<a href="/cgi-bin/form.cgi?form=test" onclick="new_target(this,'form')">
 *
 * Parameter:
 *	alink	-- the <a> link object (this)
 *	wintype	-- the type of window, 'list', 'view', 'form', 'message', ...
 *	message	-- message text displayed in the new window while getting url
 *		   Only used in a 'message' type window.
 *	options -- window options passed to window.open() Javascript function
 */

function new_target(alink,wintype,message,options,popup) {

	var url;	// empty, used as placeholder in open_*() calls
	var name;

	if (popup) PopUp = true;	// always use "normal" dimensions

	// Use time counter as a number to make a unique window name
	var unique = (new Date()).getTime().toString() + Math.floor(Math.random() * 100);

	if (wintype) {
		switch (wintype.toLowerCase()) {
		case "list":
			name = "List" + unique;
			open_list(url,name,options,message);
			break;

		case "view":
			name = "View" + unique;
			open_view(url,name,options,message);
			break;

		case "form":
			name = "Form" + unique;
			open_form(url,name,options,message);
			break;

		case "log":
			name = "Log" + unique;
			open_log(url,name,options,message);
			break;

		case "response":
			name = "Response" + unique;
			open_log_response(url,name,options,message);
			break;

		case "audit":
			name = "Audit" + unique;
			open_audit(url,name,options,message);
			break;

		case "options":
			name = "Options" + unique;
			if (!url) url = alink.href;
			open_options(url,name,options,message);
			break;

		case "help":
			name = "Help" + unique;
			open_help(url,name,options,message);
			break;

		case "doc":
			name = "Doc" + unique;
			open_doc(url,name,options,message);
			break;

		case "browse":
			name = "Browse" + unique;
			open_browse(url,name,options,message);
			break;

		case "print":
			name = "Print" + unique;
			open_print(url,name,options,message);
			break;

		case "calendar":
			name = "Calendar" + unique;
			open_calendar(n_months,url,name,options,message);
			break;

		case "day":
			name = "Day" + unique;
			open_day(url,name,options,message);
			break;

		case "message":
			name = "Message" + unique;
			var title;	// placeholder
			open_message(message, title, url, name, options);
			break;

		case "report":
			name = "Report" + unique;
			open_window(url,name,options,message);
			break;

		default:
			name = "Window" + unique;
			open_window(url,name,options,message);
		}
	}
	else {
		name = "Window" + unique;
		open_window(url,name,options,message);
	}

	// Re-assign new target window name
	if (alink) alink.target = name;

	PopUp = false;		// reset flag

	return true;
}

/*
 * Window functions
 *
 * The following functions are used to open different types of windows used
 * by the system. They enforce a common size and look for each type of window.
 * The open_*() functions do not return anything so that they can be used in
 * links like <a href="javascript:open_*()"> without having to use the void
 * operator. The new_*() functions return the window variable to the
 * calling programs.
 */

function new_window(url,name,options,message,title,noprogress) {

	if (!name) name = "";	// empty name makes a new window each time

	var settings = options ? options :
	  "copyhistory,directories,location,menubar" +
	  ",resizable,scrollbars,status,toolbar" +
	  window_size(800,600);

	// Open window without url so other scripts can close it.
	var w = window.open("", name, settings);
	if (FullScreen && ! PopUp) window_resize(w);
	w.focus();
	display_message(w, message, title, url, noprogress);
	return w;
}

function new_list(url,name,options,message,title,noprogress) {

	// Position new window up and to the right.
	var top  = next_window_top();
	var left = next_window_left();

	var settings = options ? options :
	  "copyhistory,directories,location,menubar" +
	  ",resizable,scrollbars,status,toolbar" +
	  window_size(800,600,left,top);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_view(url,name,options,message,title,noprogress) {

	// Position new window up and to the right.
	var top  = next_window_top();
	var left = next_window_left();

	var settings = options ? options :
	  "copyhistory,directories,location,menubar" +
	  ",resizable,scrollbars,status,toolbar" +
	  window_size(800,600,left,top);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_form(url,name,options,message,title,noprogress) {

	if (!name) name = "";

	// Position new window up and to the right.
	var top  = next_window_top();
	var left = next_window_left();

	var settings = options ? options :
	  "menubar,resizable,scrollbars,status" + ",location" +
	  window_size(800,600,left,top);

	var w = window.open("", name, settings);
	if (FullScreen && ! PopUp) window_resize(w);
	w.focus();				// bring to forefront

	if (url && w.location.href.indexOf("about") != 0) {

		// Just bring form to forefront if it is the same url.
		// Do not refresh screen and loose any edits user made.

		if (w.location.href == url) return w;

		var fullurl = w.location.protocol + '//' + w.location.hostname + url;
		if (w.location.href == fullurl) return w;
	}

	display_message(w, message, title, url, noprogress);
	return w;
}

function new_log(url,name,options,message,title,noprogress) {

	var settings = options ? options :
	  "menubar,resizable,scrollbars,status" +
	  window_size(800,600);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_log_response(url,name,options,message,title,noprogress) {

	var settings = options ? options :
	  "menubar,resizable,scrollbars,status" +
	  window_size(800,600);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_audit(url,name,options,message,title,noprogress) {

	// Position new window up and to the right.
	var top  = next_window_top();
	var left = next_window_left();

	var settings = options ? options :
	  "copyhistory,directories,location,menubar" +
	  ",resizable,scrollbars,status,toolbar" +
	  window_size(800,600,left,top);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_options(url,name,options,message,title,noprogress) {

	if (!name) name = "options";

	var opt,w,h;
	if (url.match(/#(.*)/)) opt = RegExp.$1;

	// Size window according to desired option
	if (! opt)			  { w = 800; h = 500; }
	else if (opt == "banner_picture") { w = 800; h = 400; }
	else				  { w = 800; h = 280; }

	var settings = options ? options :
	  "menubar,location,status,resizable,scrollbars,toolbar" +
	  window_size(w,h);

	var w = window.open("",name, settings);
	if (FullScreen && ! PopUp) window_resize(w);
	w.focus();
	if (!w.isOptionsLoaded || opt) {	// see options.htm
		// load new copy
		display_message(w, message, title, url, noprogress);
	}
	return w;
}

function options_return(w) {
	// Return from saving options
	// Execute Javascript statements setting user preferences that
	// were stored in the popup window by options.cgi.

	if (w && w.user_prefs) eval(unescape(w.user_prefs));
}

function new_help(url,name,options,message,title,noprogress) {

	var settings = options ? options :
	  "copyhistory,directories,location,menubar" +
	  ",resizable,scrollbars,status,toolbar" +
	  window_size(800,700);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_doc(url,name,options,message,title,noprogress) {

	var settings = options ? options :
	  "copyhistory,directories,location,menubar" +
	  ",resizable,scrollbars,status,toolbar" +
	  window_size(800,600);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_browse(url,name,options,message,title,noprogress) {

	var settings = options ? options :
	  "menubar,resizable,scrollbars,status" +
	  window_size(800,600);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_print(url,name,options,message,title,noprogress) {

	if (!name) name = "";

	// Set screen width and height.
	var width  = 80;
	var height = 80;

	// Position new window up and to the right.
	var top  = 100;
	var left = 100;

	// Set window to small size
	var settings = options ? options : "resizable" +
	  ",width="+width+",height="+height +
	  ",top="+top+",left="+left;

	var w = window.open("", name, settings);

	if (!title)   title   = "Printing...";
	if (!message) message = "Printing...";

	var d = new DocBuf(w.document);
	//var d = w.document;
	d.open();
	d.writeln('<html>');
	d.writeln('<head>');
	d.writeln('<title>' + title + '</title>');
	d.writeln('<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">');
	d.writeln('<style>.message{font-family:"Comic Sans MS" serif; font-size:12px; padding:10px 6px;}</style>');
	d.writeln('<script language="JavaScript" type="text/javascript">');
	d.writeln('window.document.onkeypress = do_keypress;');
	d.writeln('function do_keypress(evt) {');
	d.writeln(' evt = (evt) ? evt : ((window.event) ? window.event : null);');
	d.writeln(' var unicode = evt.charCode ? evt.charCode : evt.keyCode;');
	d.writeln(' switch (unicode) {');
	d.writeln(' case 27: self.close(); return true;');
	d.writeln('}}');
	d.writeln('</script>');
	d.writeln('</head>');
	d.writeln('<body>');
	d.writeln('<div class="message">');
	d.writeln('<p>' + message + '</p>');
	d.writeln('</div>');
	d.writeln('</body>');
	d.writeln('</html>');
	d.close();

	if (url) w.location.href = url;
	return w;
}

function new_calendar(n_months,url,name,options,message,title,noprogress) {

	if (!n_months) n_months = 1;	// default
	if (!name) name = "";

	var settings = options;

	if (!settings) {
		var w,h;
		settings = "resizable,scrollbars,status";

		if (n_months > 1) {
			settings = "copyhistory,directories,location,menubar" +
			  ",resizable,scrollbars,status,toolbar";
		}

		if (n_months > 6)       { w=880; h=1020;}
		else if (n_months > 3)  { w=880, h=780; }
		else if (n_months > 1)  { w=880, h=300; }
		else if (n_months == 1) { w=305, h=260; }

		settings += window_size(w,h);
	}

	return new_window(url,name,settings,message,title,noprogress);
}

function new_day(url,name,options,message,title,noprogress) {

	if (typeof name == "undefined") name = "Day";	// reuse same window

	var settings = options ? options :
	  "menubar,resizable,scrollbars,status" +
	  window_size(530,600);

	return new_window(url,name,settings,message,title,noprogress);
}

function new_message(message, title, url, name, options, noprogress) {

	// Print the given message with a "Please wait..." appended.
	// Open a message window to be filled in by cgi routine 
	// (such as saving a form message).

	if (!name) name = "Message";

	var width  = 650;
	var height = 300;

	var settings = options ? options :
	  "resizable,scrollbars,width="+width+",height="+height;

	// Center new window
	var w_width  = window.innerWidth
		     ? window.innerWidth
		     : window.document.body.parentNode.offsetWidth
		     ? window.document.body.parentNode.offsetWidth
		     : window.document.body.offsetWidth;
	var w_height = window.innerHeight
		     ? window.innerHeight
		     : window.document.body.parentNode.offsetHeight
		     ? window.document.body.parentNode.offsetHeight
		     : window.document.body.offsetHeight;
	var left = window.screenX    ? window.screenX
		 : window.screenLeft ? window.screenLeft
		 : 0;
	var top  = window.screenY    ? window.screenY
		 : window.screenTop  ? window.screenTop
		 : 0;
	left += (w_width/2  - width/2);
	top  += (w_height/2 - height/2);
	if (top > 0 && left > 0) settings += ",top="+top+",left="+left;

	var w = window.open("", name, settings);

	// Resize in case an old window opened instead of opening a new one.
	// Arbitrary factors are computed for IE5.
	if (!options) w.resizeTo(width+12, height+44);

	w.focus();

	display_message(w, message, title, url, noprogress);
	return w;
}

function open_window(url,name,options,message,title,noprogress)  {
	  new_window(url,name,options,message,title,noprogress)  }
function open_list(url,name,options,message,title,noprogress)    {
          new_list(url,name,options,message,title,noprogress)    }
function open_view(url,name,options,message,title,noprogress)    {
          new_view(url,name,options,message,title,noprogress)    }
function open_form(url,name,options,message,title,noprogress)    {
          new_form(url,name,options,message,title,noprogress)    }
function open_log(url,name,options,message,title,noprogress)     {
          new_log(url,name,options,message,title,noprogress)     }
function open_log_response(url,name,options,message,title,noprogress) {
          new_log_response(url,name,options,message,title,noprogress) }
function open_audit(url,name,options,message,title,noprogress)   {
          new_audit(url,name,options,message,title,noprogress)   }
function open_options(url,name,options,message,title,noprogress) {
          new_options(url,name,options,message,title,noprogress) }
function open_help(url,name,options,message,title,noprogress)    {
          new_help(url,name,options,message,title,noprogress)    }
function open_doc(url,name,options,message,title,noprogress)     {
          new_doc(url,name,options,message,title,noprogress)     }
function open_browse(url,name,options,message,title,noprogress)  {
          new_browse(url,name,options,message,title,noprogress)  }
function open_print(url,name,options,message,title,noprogress)   {
          new_print(url,name,options,message,title,noprogress)   }
function open_calendar(n_months,url,name,options,message,title,noprogress)  {
	  new_calendar(n_months,url,name,options,message,title,noprogress)  }
function open_day(url,name,options,message,title,noprogress)  {
	  new_day(url,name,options,message,title,noprogress)  }
function open_message(message, title, url, name, options, noprogress) {
	  new_message(message, title, url, name, options, noprogress) }

/*
 * Print command hook for brain-dead browsers.
 */

function print_window() {
	if (window.print != null) {
		window.print();
		return true;
	} else {
		alert("Your browser does not support this shortcut.\n" +
		      "Please select Print from the File menu.");
		return false;
	}
}

/*
 * Determine user's preference for window sizes.
 */

if (! window.FullScreen) FullScreen = false;	// user options flag set elsewhere
PopUp = false;					// FullScreen override flag

function window_size(w,h,l,t) {
	// Return a string like ",width=800,height=600" that can be appended
	// to the window features string (third argument) of window.open().
	// The left and top arguments l and t are optional.

	var a = window_dim(w,h,l,t);
	if (navigator.userAgent.match(/Gecko/)) {
		a[0] -= 10;	// guess browser's window chrome width
		a[1] -= 175;	// guess browser's window chrome height
	}

	var s = ",width="+a[0]+",height="+a[1];
	if (a[2] != null) s += ",left="+a[2];
	if (a[3] != null) s += ",top="+a[3];
	return s;
}

function window_resize(win,w,h) {
	// Resize current window to given dimensions or to full screen.

	var a = window_dim(w,h);
	if (a[2] != null && a[3] != null) win.moveTo(a[2],a[3]);
	win.resizeTo(a[0],a[1]);
}

function window_dim(w,h,l,t) {
	// Return window dimensions as an array.

	if (FullScreen && ! PopUp) {
		// Redifine dimensions for pseudo full screen
		w = screen.availWidth;
		h = screen.availHeight;
		l = (screen.availLeft != null ? screen.availLeft : 0),
		t = (screen.availTop  != null ? screen.availTop  : 0)
	}

	return [ w,h,l,t ];
}

function next_window_top() {
		var top  = window.screenTop  ? window.screenTop
			 : window.screenY    ? window.screenY
			 : 0;
		return top + 15;
}

function next_window_left() {
		var left = window.screenLeft ? window.screenLeft
			 : window.screenX    ? window.screenX
			 : 0;
		return left + 15;
}

/*
 * Display messages and wait signs.
 */

function display_message(w, message, title, url, noprogress) {
	// Display message in specified window.

	if (! w) w = self;
	if (! message) message = "&nbsp;";
	if (! title)   title   = "Message";

	// Security Note: The following can cause a security fault in Konqueror
	// or a security warning in Netscape 7.1 because when a window is first
	// opened it has the url "about:blank" (even if window.open() is passed
	// a url). This document usually has a url like http:www.domain.com, and
	// that causes a security issue because a script writing to another
	// window needs to be from the same domain. We cannot simply check if
	// self.location.protocol == w.location.protocol because just accessing
	// the other window's protocol causes IE to fault.
	if (navigator.userAgent.indexOf('Konq') >= 0) return;

	// Another security note: popup window blockers that are now common
	// because of damn spammers cause the following code to choke.

	var d = new DocBuf(w.document);
	//var d = w.document;
	d.open();
	d.writeln('<html>');
	d.writeln('<head>');
	d.writeln('<title>' + title + '</title>');
	d.writeln('<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">');
	// The following does not work in IE5.5. Hard-wire the CSS styles.
	//d.writeln('<link rel="stylesheet" href="/styles/message.css" type="text/css">');
	d.writeln('<style>\nbody{background-color:#EEEEEE;}\n.message{font-family:Arial,Helvetica,sans-serif; font-size:16px; text-align:left; padding:5ex 2ex 2ex 62px; margin:4ex 2ex; border:solid #CCCCCC 2px; background-color:#FFFFFF; background-image:url(/images/wait.gif); background-repeat:no-repeat; background-position:20px 5ex; width:500px; min-height:150px; }\n.message p{margin:0px;} .message table{margin-top:40px;}\n</style>');
	d.writeln('<script language="JavaScript" type="text/javascript">');
	d.writeln('window.document.onkeypress = do_keypress;');
	d.writeln('function do_keypress(evt) {');
	d.writeln(' evt = (evt) ? evt : ((window.event) ? window.event : null);');
	d.writeln(' switch (evt.keyCode) {');
	d.writeln(' case 27: self.close(); return true;');
	d.writeln('}}');
	if (url) {

		// Put protocol and hostname in url because Netscape sometimes
		// opens a window with a href of "about:blank" and uses that
		// as a default for protocol and hostname, and then it issues
		// an error for a url like: about:blank/cgi-bin/form.cgi....

		if (! url.match(/:/)) {
			if (! url.match(/^\w+\.\w+/)) {
				url = self.location.hostname +
				  (url.indexOf('/') == 0 ? '' : '/') + url;
			}
			url = self.location.protocol + '//' + url;
		}
		d.writeln('window.onload=new Function(\'self.location.replace("'+url+'")\');');
	}
	d.writeln('</script>');
	d.writeln('</head>');
	d.writeln('<body>');
	d.writeln('<center><div class="message">');
	d.writeln('<p>' + message + '</p>');
	d.writeln('<p>Please wait...</p>');
	if (! noprogress) d.writeln(progress_bar('center'));
	d.writeln('</div></center>');
	d.writeln('</body>');
	d.writeln('</html>');
	d.close();
}

/*
 * Progress Bar
 */

function progress_bar(alignment,color) {
	if (!alignment) alignment = 'center';
	if (!color)     color     = '#CCCCCC';

	return '\n'
  + '<!-- Begin Progress Bar -->\n'
  + '<table align="'+alignment+'"><tr><td>\n'
  + '<div style="text-align:center; font-size:12px; padding:2px">'
  + '<span id="progress1">&nbsp; &nbsp;</span>'
  + '<span id="progress2">&nbsp; &nbsp;</span>'
  + '<span id="progress3">&nbsp; &nbsp;</span>'
  + '<span id="progress4">&nbsp; &nbsp;</span>'
  + '<span id="progress5">&nbsp; &nbsp;</span>'
  + '<span id="progress6">&nbsp; &nbsp;</span>'
  + '<span id="progress7">&nbsp; &nbsp;</span>'
  + '<span id="progress8">&nbsp; &nbsp;</span>'
  + '<span id="progress9">&nbsp; &nbsp;</span>'
  + '</div>\n'
  + '</td></tr></table>\n'
  + '<script language="JavaScript" type="text/javascript">\n'
  + 'var progressEnd = 9;\n'
  + 'var progressColor = "'+color+'";\n'
  + 'var progressInterval = 500;\n'
  + '\n'
  + 'var progressAt = 0;\n'
  + 'var progressDir = 1;\n'
  + 'var progressTimer;\n'
  + 'function progress_clear() {\n'
  + '	for (var i = 1; i <= progressEnd; i++) document.getElementById("progress"+i).style.backgroundColor = "transparent";\n'
  + '	progressAt = 0;\n'
  + '	progressDir = 1;\n'
  + '}\n'
  + 'function progress_update() {\n'
  + '	progressAt += progressDir;\n'
  + '	if (progressAt < 1)           { progressAt = 1;           progressDir = 1;  }\n'
  + '	if (progressAt > progressEnd) { progressAt = progressEnd; progressDir = -1; }\n'
  + '	if (progressDir == 1)  document.getElementById("progress"+progressAt).style.backgroundColor = progressColor;\n'
  + '	if (progressDir == -1) document.getElementById("progress"+progressAt).style.backgroundColor = "transparent";\n'
  + '	progressTimer = setTimeout("progress_update()",progressInterval);\n'
  + '}\n'
  + 'function progress_stop() {\n'
  + '	clearTimeout(progressTimer);\n'
  + '	progress_clear();\n'
  + '}\n'
  + 'progress_update()\n'
  + '</script>\n'
  + '<!-- End Progress Bar -->\n';
}

