///////////////////////////////////////////////////////////////////////////////
// objxcore.js library
// Version 1.027
// Copyright (c) 2006 Nathan S. Bawden, all rights reserved.
// The code in this library can be used freely by anyone as long as this
// entire header and copyright notice remains intact.  You may add additional
// "free use" copyright notices to give you credit if you improve the code.
//
// input.n variables come from form or url input and persist within pages of a directory
// app.n variables persist witin all pages of a directory
// site.n variables exist for all pages at a website
// Variables are stored on the top.document in a frameset and also in browser cookies
//	with the advantage of the frameset being faster and not having size limitations but
//	the disadvantage of not persisting if the browser leaves the frameset.  Both are
//	automatically stored and the most efficient is automatically used.


// FIGURE OUT THE BROWSER

var OBJXVERS = 1.027;
var OBJXINITED = false;

if (! top.objx || top.objx.version < OBJXVERS) {
	OBJXINITED = true;
	top.objx = new Object();
	top.objx.version = OBJXVERS;
	top.objx.appVersion = parseFloat(navigator.appVersion);
	top.objx.hasReplaceBug = true;	// Does not have replace() bug
	top.objx.hasFilters = false;	// Does not have style filters
	top.objx.hasLayers = false;		// Use layers instead of css for pop-ups
	top.objx.hasStyles = false;		// Does not have object style properties
	top.objx.bAllowed = false;		// Browser version not allowed

	var bidx;
	while (true) {
		bidx = navigator.userAgent.indexOf(' Opera ');
		if (bidx != -1) {
			top.objx.browser = 'OP';
			break;
		}
		bidx = navigator.userAgent.indexOf(' MSIE ');
		if (bidx != -1) {
			top.objx.browser = 'IE';
			break;
		}
		bidx = navigator.userAgent.indexOf('Mozilla');
		if (bidx != -1) {
			top.objx.browser = 'NS';
			break;
		}
		top.objx.browser = '';
		break;
	};
	switch (top.objx.browser) {
	case 'IE':
		top.objx.bVersion = parseFloat(navigator.userAgent.substr(bidx+6));
		top.objx.bName = 'Internet Explorer';
		if (top.objx.bVersion >= 5.5) {
			top.objx.bAllowed = true;
			top.objx.hasReplaceBug = false;
		};
		top.objx.hasFilters = true;
		top.objx.hasStyles = true;
		break;
	case 'NS':
		top.objx.bVersion = top.objx.appVersion;
		top.objx.bName = 'Netscape';
		if (top.objx.bVersion >= 4) top.objx.bAllowed = true;
		if (top.objx.bVersion >= 4.5) top.objx.hasReplaceBug = false;
		top.objx.hasLayers = true;
		if (top.objx.bVersion >= 6) top.objx.hasStyles = true;
		break;
	case 'OP':
		top.objx.bVersion = parseFloat(navigator.userAgent.substr(bidx+7));
		top.objx.bName = 'Opera';
		if (top.objx.bVersion >= 5.02) top.objx.bAllowed = true;
		break;
	default:
		top.objx.bVersion = top.objx.appVersion;
		top.objx.bName = navigator.appName;
		break;
	};
}


// Array Routines /////////////////////////////////////////////////////////////

function NamedArrayFind(ar,nm) {
	var ln = ar.length;
	for (var i=0;i<ln;i++) {
		if (ar[i].name == nm) return i;
	}
	return -1;
}

// Form Element routines //////////////////////////////////////////////////////

function setFormElement(fmArr,nn,vv) {
	var j = NamedArrayFind(fmArr,nn);
	var tp = new String();
	var ln = 0;
	var i = 0;
	if (j != -1) {
		tp = fmArr[j].type;
		tp.tolowercase;
		switch (tp) {
		case 'radio':
			while (fmArr[j].name == nn) {
				if (fmArr[j].value == vv) {fmArr[j].checked = true; break;}
				j++;
			}
			break;
		case 'checkbox':
			if (fmArr[j].value != '') {
				if (fmArr[j].value == vv) fmArr[j].checked = true;
				else fmArr[j].checked = false;
			}
			else {
				if (vv == 'on' || vv == true) fmArr[j].checked = true;
				else fmArr[j].checked = false;
			}
			break;
		case 'select-one':
			ln = fmArr[j].options.length;
			for (i=0;i<ln;i++) {
				if (fmArr[j].options[i].value == vv) {fmArr[j].selectedIndex = i; break;}
			}
			break;
		case 'select-multiple':
			ln = fmArr[j].options.length;
			for (i=0;i<ln;i++) {
				if (isInSlot(vv,',',fmArr[j].options[i].value)) fmArr[j].options[i].selected = true;
			}
			break;
		case 'button': break;
		case 'submit': break;
		case 'hidden': break; // Cannot set hidden for security.
		case 'file': break;	// Cannot set file for security.
		default:
			fmArr[j].value = vv;
			break;
		}
	}
}

function collectInput(fm) {
	var st = new String();
	var ln = fm.elements.length;
	var j = 0;
	for (var i=0;i<ln;i++) {
		var nn = fm.elements[i].name;
		var vv = fm.elements[i].value;
		if (! isBlack(nn)) continue;
		st = fm.elements[i].type;
		switch (st.toLowerCase()) {
		case 'radio':
			if (fm.elements[i].checked == true || fm.elements[i].checked == '1') input[nn] = vv;
			break;
		case 'checkbox':
			if (fm.elements[i].checked == true) {
				if (vv != '') input[nn] = vv;
				else input[nn] = 'on';
			} else input[nn] = '';
			break;
		case 'select-one':
			input[nn] = fm.elements[i].options[fm.elements[i].selectedIndex].value;
			break;
		case 'select-multiple':
			var oln = fm.elements[i].options.length;
			delete input[nn];
			for (j=0;j<oln;j++) {
				if (fm.elements[i].options[j].selected == true) {
					input[fm.elements[i].name] = addSlot(input[fm.elements[i].name],',',fm.elements[i].options[j].value);
				}
			}
			break;
		case 'submit': break;
		case 'button': break;
		case 'file': break;
		default:
			input[nn] = txtValue(vv);
			break;
		}
	}
}


function clearForms() {
	var ln = document.forms.length;
	var i = 0;
	var j = 0;
	for (i=0;i<ln;i++) {
		var fm = document.forms[i];
		var ln2 = fm.elements.length;
		for (j=0;j<ln2;j++) {
			setFormElement(fm,fm.elements[j].name,'');
		}
	}
}

function isAnyRadio(fm,name) {
	var ln = fm.elements.length;
	for (var i=0;i<ln;i++) {
		if (fm.elements[i].name == name && isYes(fm.elements[i].checked)) return true;
	}
	return false;
}

// FORM INPUT ROUTINES ////////////////////////////////////////////////////////

function rb(t) {
	var f = "document." + t.form.name + "." + t.name + ".value = '" + t.value + "'";
	alert(f);
//	eval(f);
}

// Optionally move selected value to named form element
// and reload input and cookie from the new form values.
function selChange(ele,nm) {
	var ff = new String();
	if (arguments.length > 1) {
		ff = 'ele.form.' + nm + '.value=ele.options[' + ele.selectedIndex + '].value';
		eval(ff);
	}
	collectInput(ele.form);
	saveCookie();
}

function optionList(list) {
	return eachSlot(list,',','writeOption(this.slot)');
}

function writeOption(vv) {
	var rt = '<option value="' + vv + '">' + vv + '</option>';
	return rt;
}


// SUBMIT ROUTINES ////////////////////////////////////////////////////////////

function evalForm(fm) {
	collectInput(fm);
	if (! isBlack(fm.action)) fm.action = URL;
	fm.method = 'GET';
	if (URL.length > 512) alert("New URL too long. Data may be lost!");
	saveCookie();
	if (! verifyAll()) return false;
	if (altFormAction != '') fm.action = altFormAction;
	if (isBlack(fm.action)) document.location = fm.action;
	else document.location = URL;
	return false;
}

function altSubmit(loc,vSkip) {
	altFormAction = loc;
	if (arguments.length > 1) verifyOn = vSkip;
}

function Reload() {
	saveCookie();
	incUni();
	document.location = addQuery(document.location,'uu',site.uni);
}

// VERIFICATION FUNCTIONS /////////////////////////////////////////////////////

function verifyNotNull(name,failMsg) {
	verifyEval += 'if (! isBlack(input["' + name + '"])) {verifyMsg += "' + escape((failMsg || name + ' is not filled') + '\r\n') + ',' + '"};\n';
}

function verifyExact(name,value,failMsg) {
	verifyEval += 'if (input["' + name + '"] != unescape("' + escape(value) + '")) {verifyMsg += "' + escape((failMsg || name + ' is not valid') + '\r\n') + ',' + '"};\n';
}

function verifyEquals(name,value,failMsg) {
	verifyEval += 'if (input["' + name + '"] && input["' + name + '"] != eval(unescape("' + escape(value) + '"))) {verifyMsg += "' + escape((failMsg || name + ' is not valid') + '\r\n') + ',' + '"};\n';
}

function verifyLessThan(name,value,failMsg) {
	verifyEval += 'if (input["' + name + '"] && input["' + name + '"] >= eval(unescape("' + escape(value) + '"))) {verifyMsg += "' + escape(failMsg + '\r\n') + ',' + '"};\n';
}

function verifyGreaterThan(name,value,failMsg) {
	verifyEval += 'if (input["' + name + '"] && input["' + name + '"] <= eval(unescape("' + escape(value) + '"))) {verifyMsg += "' + escape(failMsg + '\r\n') + ',' + '"};\n';
}

function verifyAll() {
	if (! verifyOn) return true;
	var ic = true;
	var ii = new String('');
	verifyMsg = '';
	if (verifyEval != '') eval(verifyEval);
	ic = ifValid();
	if (! ic) alert(eachSlot(verifyMsg,',','this.slot'));
	return ic;
}

function ifValid() {
	if (verifyMsg == '') return true;
	return false;
}


function msOv(ths,color,bgcolor) {
	if (! ths.style) return;
	ths.myFg = ths.style.color;
	if (color != '') ths.style.color = color;
	ths.myBg = ths.style.backgroundColor;
	if (arguments.length > 2) ths.style.backgroundColor = bgcolor;
}

function msOt(ths) {
	if (! ths.style) return;
	ths.style.color = ths.myFg;
	ths.style.backgroundColor = ths.myBg;
}

// SUPPORT FUNCTIONS //////////////////////////////////////////////////////////

function show(txt) {document.write(txt)}

function uuch(ch) {if (ch == '+') return '%20'; return ch}
function unurlize(txt) {
	var uu = eachChar(txt,'uuch(this.ch)');
	return unescape(uu);
}

function isBlack(nn) {if (nn && nn != '') return true; return false;}
function txtValue(vv) {if (vv) return vv; return '';}
function isYes(vv) {if (vv && (vv == true || '1yYtT'.indexOf(vv) != -1)) return true; return false;}

function isInSlot(lst,delim,vv) {
	vv = escape(vv.trim());
	var ln = lst.length;
	while (--ln > 0) {	// Trim trailing delimts
		if (lst.charAt(ln) == delim) {lst = lst.substr(0,ln); continue;}
		break;
	}
	var s = lst.split(delim);
	ln = s.length;
	for (var i=0;i<ln;i++) {
		if (s[i] == undefined) s[i] = '';
		if (s[i] == vv) return true;
	}
	return false;
}

String.prototype.trim = function() {
	if (! top.objx.hasReplaceBug) return this.replace(/(^\s*)|(\s*$)/g, "");
	var i = 0;
	var ln = this.length;
	while (" \r\n\t".indexOf(this.charAt(i)) != -1 && i < ln) i++;
	var j = this.length - 1;
	while (" \r\n\t".indexOf(this.charAt(j)) != -1 && j > -1) j--;
	if (i <= j) return this.substring(i,j+1);
	return '';
}

String.prototype.toParaCase = function() {
	var c = new String(this.substr(0,1));
	return c.toUpperCase() + this.substr(1,this.length-1);
}

String.prototype.fwdSlash = function() {
	var rt = '';
	var ch;
	for (var i=0;i<this.length;i++) {
		ch = this.charAt(i); 
		if (ch == '\\') rt += '/';
		else rt += ch;
	}
	return rt;
}

String.prototype.pathFront = function() {
	var s = this.fwdSlash();
	var i = s.length - 1;
	while (s.charAt(i) != '/' && i > 0) i--;
	if (i < 0) return '';
	return s.substr(0,i);
}

String.prototype.pathEnd = function() {
	var s = this.fwdSlash();
	var i = s.length - 1;
	while (s.charAt(i) != '/' && i > 0) i--;
	if (i < 0) return s;
	return s.substr(i+1);
}

function paraCase(str) {return str.toParaCase()}
function upperCase(str) {return str.toUpperCase()}
function lowerCase(str) {return str.toLowerCase()}

function incUni() {site.uni = parseInt(site.uni) + 1}

function showBol(label) {
	if (! label) return "";
	var ss = new String();
	var obj = eval(label);
	var x = 300;
	ss += '<font size=3><xmp>';
	for (var i in obj) {
		ss += label + '.' + i + ' = ' + obj[i] + '\r\n';
		if (--x < 0) break;
	}
	if (ss.length > 50000) ss = ss.substr(1,50000);
	ss += '</xmp></font>';
	return ss;
}

// Add a slot to a value that contains a slot list
var SltRt;
var SltVV;
function addSlot(lst,delim,vv) {
	var vx = new String(vv);
	vv = vx.trim();
	SltRt = 0;
	if (lst) {
		SltVV = vv;
		eachSlot(lst,delim,'if (this.slot == SltVV) SltRt = 1');
	} else lst = '';
	if (SltRt == 0) lst += escape(vv) + delim;
	return lst;
}

function remSlot(lst,delim,vv) {
	var vx = new String(vv);
	vv = vx.trim();
	if (lst) {
		SltVV = vv;
		SltRt = new String;
		eachSlot(lst,delim,'if (this.slot != SltVV) SltRt += escape(this.slot) + delim');
		lst = SltRt;
	}
	return lst;
}

function addQuery(uu,nn,vv) {
	var rt = new String(uu);
	if (rt.indexOf('?') == -1) rt += '?';
	else rt += '&';
	rt += escape(nn) + '=' + escape(vv);
	return rt;
}

function processLinks() {
	var ln = document.links.length;
	for (var i=0;i<ln;i++) {
		var hh = document.links[i];
		if (hh.search) {
			var qq = new nvp(hh.search.substr(1));
			if (qq.call) {
				delete qq.call;
				qq.caller = document.callback;
				hh.search = '?' + nvpList(qq);
			}
		}
		if (hh.pathname.pathEnd().toUpperCase() == 'BACK' && document.caller) {
			hh.href = document.caller;
		}
	}
}

function mouseOverLinks(color,bgcolor) {
	var ln = document.links.length;
	if (arguments.length > 1) {
		for (var i=0;i<ln;i++) {
			if (document.links[i].onmouseover) continue;
			document.links[i].onmouseover = new Function("msOv(this,'" + color + "','" + bgcolor + "')");
			document.links[i].onmouseout = new Function("msOt(this)");
		}
	}
	else {
		for (var i=0;i<ln;i++) {
			if (document.links[i].onmouseover) continue;
			document.links[i].onmouseover = new Function("msOv(this,'" + color + "')");
			document.links[i].onmouseout = new Function("msOt(this)");
		}
	}
}

function mouseOverButtons(color,bgcolor) {
	var ln1 = document.forms.length;
	var ln2 = 0;
	var ele;
	var i = 0;
	var j = 0;
	if (arguments.length > 1) {
		for (i=0;i<ln1;i++) {
			ele = document.forms[i].elements;
			ln2 = ele.length;
			for (j=0;j<ln2;j++) {
				if (ele[j].type != 'submit' || ele[j].onmouseover) continue;
				ele[j].onmouseover = new Function("msOv(this,'" + color + "','" + bgcolor + "')");
				ele[j].onmouseout = new Function("msOt(this)");
			}
		}
	}
}

// EACH ITERATIONS ////////////////////////////////////////////////////////////

function eachChar(ww, ff, sep) {
	if (! ww) return '';
	var ln = ww.length;
	var rt = new String();
	if (arguments.length > 2) {
		for (var i=0;i<ln;i++) {
			if (i > 0) rt += sep;
			this.ch = ww.substr(i,1);
			this.idx = i;
			rt += eval(ff);
		}
	}
	else {
		for (var i=0;i<ln;i++) {
			this.ch = ww.substr(i,1);
			this.idx = i;
			rt += eval(ff);
		}
	}
	return rt;
}

function eachWord(list,func,sep) {eachSlot(list,' ',func,sep)}

function eachSlot(lst, delim, func, sep) {
	if (! lst) return '';
	var ln = lst.length;
	while (--ln > 0) {	// Trim trailing delimts
		if (lst.charAt(ln) == delim) {lst = lst.substr(0,ln); continue;}
		break;
	}
	var lla = lst.split(delim);
	ln = lla.length;
	var rt = new String();
	if (arguments.length > 3) {
		for (var i=0;i<ln;i++) {
			if (i > 0) rt += sep;
			this.slot = unescape(lla[i]);
			this.idx = i;
			rt += eval(func);
		}
	}
	else {
		for (var i=0;i<ln;i++) {
			this.slot = unescape(lla[i]);
			this.idx = i;
			rt += eval(func);
		}
	}
	return rt;
}

function eachArray(arr, ff) {
	if (arr == undefined) return '';
	var ln = arr.length;
	var rt = new String();
	for (var i=0;i<ln;i++) {
		this.idx = i;
		this.ar = arr[i];
		rt += eval(ff);
	}
	return rt;
}


// NVP Routines ///////////////////////////////////////////////////////////////

function nvp(list) {
	if (list && list != '') nvpLoad(this,list);		// nvp object constructor
}

function nvpReset(obj,list) {
	for (var i in obj) delete obj[i];
	if (list != undefined) nvpLoad(obj,list);
}

function nvpShow(obj,nn) {
	if (obj[nn]) document.write(obj[nn]);
}

function nvpParaShow(obj,nn) {
	if (obj[nn]) document.write(obj[nn].toParaCase());
}

// Returns empty text when value is undefiend
//function nvpValue(obj,nn) {return txtValue(obj[nn]);}

function nvpLoad(obj,list) {
	if (! list || list == '') return;
	var ls = list.split('&');
	var ln = ls.length;
	for (var i=0;i<ln;i++) {
		var pp = ls[i].split('=');
		obj[unurlize(pp[0])] = unurlize(pp[1]);
	}
}

function nvpList(obj) {
	var ls = new String();
	for (var i in obj) {
//		if (obj[i] == '') continue;
		if (ls != '') ls += '&';
		ls += escape(i) + '=' + escape(txtValue(obj[i]));
	}
	return ls;
}

function nvpWipe(obj,nn) {
	var lst = nn.split(',');
	var ln = lst.length;
	for (var j=0;j<ln;j++) {
		if (obj[lst[j]]) delete obj[lst[j]];
	}
}

function nvpShowDebug(label) {
	if (! label) return;
	document.write('<dl><dt><b>' + upperCase(label) + ' VARIABLES</b>' + ' [<a href="javascript: nvpReset(' + label + '); site.debug = \'y\'; Reload()">clear</a>]' + '</dt><dd>');
	document.write(showBol(label));
	document.write('</dd></dl>');
}

function nvpLoadForm(fmArr,obj) {
	for (var i in obj) setFormElement(fmArr,i,txtValue(obj[i]));
}


// NVP ARRAY Routines /////////////////////////////////////////////////////////

function NvpArray(list) {
	alert("NvpArray discontinued");
}

///////////////////////////////////////////////////////////////////////////////
// COOKIE ROUTINES ////////////////////////////////////////////////////////////
// Max storage 4K/cookie; 20 cookies/site; 300 cookies total

function cookieKey() { return document.location.pathname.pathFront().pathEnd(); }

function saveCookie() {
	// put the url into the cookie
	var ky = cookieKey();
	if (! top.document.myCookie) top.document.myCookie = new Object();
	top.document.myCookie[ky] = 'frameset';
	var co = new String();
	var ce = new String();
	var date = new Date();
	date.setTime(date.getTime()-(30*24*60*60*1000));
	var ckDelete = '; expires=' + date.toGMTString();
	date = new Date();
	date.setTime(date.getTime()+(366*24*60*60*1000));
	var ckExpiry = '; expires=' + date.toGMTString();
	var ckPath = '; path=' + document.location.pathname.pathFront();
	var ckExp = ckExpiry;

	top.document.myInput = nvpList(input);
	if (top.document.myInput.length > 0) ckExp = ckExpiry; else ckExp = ckDelete;
	co = 'jx/' + ky + '/input=' + top.document.myInput;
	ce = ckExp + ckPath;
	top.document.myCookie[ky] += '; ' + co;
	document.cookieOut = co + ce;
	document.cookie = co + ce;
	document.coLen = co.length;
	if (co.length > 4096) alert('ERROR: input cookie too long');

	top.document.myApp = nvpList(app);
	if (top.document.myApp.length > 0) ckExp = ckExpiry; else ckExp = ckDelete;
	co = 'jx/' + ky + '/app=' + top.document.myApp;
	ce = ckExp + ckPath;
	top.document.myCookie[ky] += '; ' + co;
	document.cookieOut += '; ' + co + ce;
	document.cookie = co + ce;
	document.coLen += co.length;
	if (co.length > 4096) alert('ERROR: app cookie too long');

	top.document.mySite = nvpList(site);
	if (top.document.mySite.length > 0) ckExp = ckExpiry; else ckExp = ckDelete;
	co = 'jx/site=' + top.document.mySite;
	ce = ckExp + '; path=/';
	top.document.myCookie.site = co;
	document.cookieOut += '; ' + co + ce;
	document.cookie = co + ce;
	document.coLen += co.length;
	if (co.length > 4096) alert('ERROR: site cookie too long');
}

function readAppCookie(name) {
	return readRawCookie(('jx/' + cookieKey() + '/' + name), document.cookieIn);
}

function readRawCookie(nm,ck) {
	var ar;
	nm += '=';
	if (ck) ar = ck.split(';');
	else ar = new Array();
	var ln = ar.length;
	var nl = nm.length;
	var i;
	document.coCnt = ln;
	for (i=0;i<ln;i++) {	// clip any leading space
		if (ar[i].substr(0,1) == ' ') ar[i] = ar[i].substr(1,ar[i].length-1);
	}
	for (i=0;i<ln;i++) {
		if (ar[i].substr(0,nl) == nm) return ar[i].substr(nl);
	}
	return '';
}


// DEBUG FUNCTIONS ////////////////////////////////////////////////////////////

function arrayList(txt,delim) {
	var ar = txt.split(delim);
	var ln = ar.length;
	var out = new String;
	for (var i=0;i<ln;i++) out += ar[i] + '<br>';
	return out;
}

function Debug(lbl,txt) {
	if (dbout == '') {
		dbout += '<table width=100% border=0 cellpadding=1 cellspacing=0><tr><td width=100% bgcolor="#88AACC"><font size=-1><b>Debug() STATEMENT OUTPUT</b></font></td></tr></table>';
	}
	dbout += '<table width=100% border=0 cellpadding=0 cellspacing=0><tr><td height=1 bgcolor="#000000"></td></tr></table>';
	if (arguments.length < 2) {
		dbout += '<table width=100% border=0 cellpadding=1 cellspacing=0><tr><td bgcolor="#CCCCCC"><font size=-1 family="courier new">' + lbl + '</font></td></tr></table>';
	}
	else {
		dbout += '<table width=100% border=0 cellpadding=1 cellspacing=0><tr><td align=right valign=top width=15% bgcolor="#CCCCCC"><nobr><font size=-1><b>&nbsp;' + lbl + '&nbsp;</b></font></nobr></td><td width=85% bgcolor="#FFFFFF"><font size=-1 family="courier new">' + txt + '</font></td></tr></table>';
	}
}

function ShowDebug(color) {
	if (arguments.length < 1) color = '#CCCCCC';
	document.write('<p><table width="100%"><tr><td bgcolor="' + color + '">');
	document.write('<font face="courier new" size=2>');
	document.write('<table width=100% border=0 cellpadding=1 cellspacing=0><tr><td width=100% bgcolor="#88AACC"><b><u>JX DEBUG OUTPUT</u></b> [<a href="javascript: site.debug=\'n\'; Reload()">close</a>]</td></tr></table>');
	document.write("<b>URL: </b>" + document.location + "<br>");
	document.write("<b>BROWSER: </b>" + navigator.appName + "<br>");
	document.write("<b>VERSION: </b>" + navigator.appVersion + "<br>");
	document.write("<b>AGENT: </b>" + navigator.userAgent + "<br>");
	nvpShowDebug('input');
	nvpShowDebug('app');
	nvpShowDebug('site');
//	nvpShowDebug('top.objx');
	nvpShowDebug('top.document.myCookie');
	document.write("<b>COOKIE SIZE: </b>" + document.coLen + ' <b>TOTAL COOKIES: </b> ' + document.coCnt + "<br>");
	document.write("<b>COOKIE &nbsp;IN: </b><br>" + arrayList(document.cookieIn,';'));
	document.write("<b>COOKIE OUT: </b><br>" + arrayList(document.cookieOut,';'));
	if (dbout != '') show(dbout);
	document.write("</p></font></td></tr></table></p>");
}


// PAGE END ROUTINES //////////////////////////////////////////////////////////


function pageEnd() {
	simpleEnd(true);
	if (bottomTxt != '') document.write(bottomTxt);
	if (showdebug == 'y' && site.debug == 'y') ShowDebug();
//	ShowDebug();
	if (finishActions != '') eval(finishActions);
}

function simpleEnd() {
	var ln = document.forms.length;
	if (autofill == 'y') for (var i=0;i<ln;i++) {
		nvpLoadForm(document.forms[i],input);
	}
	processLinks();
	saveCookie();
}


function toBottom(txt) {
	if (txt) bottomTxt += txt;
}

function finishAction(action) {
	finishActions += '(' + action + ');\n';
}

///////////////////////////////////////////////////////////////////////////////
// ENVIRONMENT INITIALIZATION /////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

// Option variables

var autofill = 'y';
var showdebug = 'y';
var bottomTxt = new String('');

// Helper variables

var btnBg;							// button background color
var btnFg;							// button foreground color
var altFormAction = new String('');	// alternate form action from submit buttons
var finishActions = new String('');	// document finish actions
var verifyEval = new String('');	// verify routine eval functions
var verifyMsg = new String('');		// verify routine failure messages
var verifyOn = true;
var objxInited;						// Value 'y' when objx library has been initialized
var BrName;
var BrVers;
var privacy_statement;

// Document location and query string parser
var dbout = new String();
var ANCHOR = unescape(document.location.hash.substr(1));
var URL = document.location.protocol + document.location.hostname + document.location.pathname;

document.myUrl = URL;
document.myName = document.location.pathname.pathEnd();

// NVP arrays
var input = new nvp();
var site = new nvp();
var app = new nvp();
var global = app;	// For backwards compatibility

// Extra functions that should be local

function registerDocument() {
	window.xName = document.location.pathname.pathFront().pathEnd() + '/' + document.location.pathname.pathEnd();
	if (top != window) {
		top.xSubWindow = window;
//		alert('top.' + top.xName + '\r\nwindow.' + window.xName); 
	}
	else top.xSubWindow = null;
//	if (!top.Links) top.Links = new Links;
	top.Links = new Links;
}

function Links() {
	this.links = new Object;
}

Links.prototype.add = function(href,label) {
	this.links[label] = href;
}

Links.prototype.make = function() {
	var ss = new String;
	for (var i in this.links) {
		ss += '[ <a href="' + this.links[i] + '">' + i + '</a> ] ';
	}
	return ss;
}

function initObjx() {
	if (objxInited == 'y') return;
	objxInited = 'y';

	BrName = navigator.appName;
	BrVers = parseInt(navigator.appVers);

	if (OBJXINITED && (! top.objx.bAllowed)) {
		var msg = 'Your browser does not support all JavaScript features in use at this website.\nRequires at least Internet Explorer 5.5 or Netscape 4.0\nOpera browser does not support the features.\nYour browser is: ';
		msg += top.objx.bName + ' ' + top.objx.bVersion;
		alert(msg);
	}

	var ky = cookieKey();
	if (top.document.myCookie && top.document.myCookie[ky])
		document.cookieIn = top.document.myCookie[ky];
	else if (document.cookie)
		document.cookieIn = document.cookie;
	else
		document.cookieIn = '';
	nvpLoad(input,readAppCookie('input'));
	nvpLoad(input,document.location.search.substr(1));
	nvpLoad(app,readAppCookie('app'));
	if (top.document.myCookie && top.document.myCookie.site)
		nvpLoad(site,readRawCookie('jx/site',top.document.myCookie.site));
	else
		nvpLoad(site,readRawCookie('jx/site',document.cookieIn));

	if (input.debug == 'y') site.debug = 'y';
	if (input.debug == 'n') site.debug = 'n';
	nvpWipe(input,'debug,uu');

	document.callback = document.location.protocol + "//" + document.location.hostname + document.location.pathname + document.location.hash;
	if (input.caller) {
		app.caller = input.caller;
		delete input.caller;
	}
	if (app.caller) document.caller = app.caller;


	if (! site.uni) site.uni = 0;
	incUni();
	registerDocument();
	document.write('<script src="local.js"></script>');
	privacy_statement = '<b>Privacy statement:</b> This application is written in client side JavaScript allowing all information to be stored <b>on your computer only</b>. To give you complete privacy, no information is submitted to the remote web site.';

}

var JUNK = initObjx();


