/**
 * *******************************************************************
 * Core Javascript Classes and Function
 * @copyright 2002-2004 Centricity Systems, Inc. All Rights Reserved
 * Use of these scripts is allowed provided all copyright and
 * authorship is acknowledged and displayed as part of the code.
 * @version 1.0
 * *******************************************************************
 */
/** ************************************
 * GLOBAL VARIABLES
 ** ************************************
 */
/* set the string prototype to support the trim function */
String.prototype.csapiTrim = function() {
    return(this.replace(/^\s+/,'').replace(/\s+$/,''));
}
/**
 * @var MAC defines if browser is Macintosh version
 */
var MAC = (navigator.appVersion.indexOf('Mac')!=-1)?1:0;
/**
 * @var NS4 defines if browser is Netscape version 4 or less
 */
var NS4 = (typeof(document.layers)!="undefined"&&parseInt(navigator.appVersion)<=4)?1:0;
/**
 * @var NS6 defines if browser is Netscape version 6 or above
 */
var NS6 = ((document.getElementById)&&(navigator.appName=='Netscape'))?1:0;
/**
 * @var NS defines if browser is Netscape version
 */
var NS = (NS4||NS6)?1:0;
/**
 * @var IE defines if browser is Internet Explorer version
 */
var IE = (document.all)?1:0;
/**
 * @var IE4 defines if browser is Internet Explorer version 4
 */
var IE4 = (IE&&navigator.userAgent.indexOf("Opera")==-1)?1:0;
/**
 * @var OP defines if browser is Opera
 */
var OP = (navigator.userAgent.indexOf("Opera")!=-1)?1:0;
/**
 * @var OP4 defines if browser is Opera version 4 or 5 or 6
 */
var OP4 = (OP&&!document.all&&document.getElementById)?1:0;
/**
 * @var OP7 defines if browser is Opera version 7 or above
 */
var OP7 = (OP&&document.all&&document.getElementById)?1:0;
/**
 * @var cmdHidden defines the object property for the hide object (make object or layer hidden)
 */
var cmdHidden = (IE||NS6)?"hidden":"hide";
/**
 * @var cmdVisible defines the object property for the show object (make object or layer visible)
 */
var cmdVisible = (NS)?"show":"visible";
/**
 * @var cmdHideShowToggle defines the object property for the hide and show object toggle condition
 */
var cmdHideShowToggle = cmdVisible;
/**
 * @var onclick_set identifies if the onclick event has been set to hide menu. Automatically set
 * when menu content is introduced to the menu object.
 */
var onclick_set = false;
/**
 * @var mnu sets up the main menu object arrays
 */
var mnu = new Array();
/**
 * @var mObj sets up the menu object
 */
mObj = new Object();
/**
 * @var pref sets up the main menu preference object
 */
var mnuPref = new Array();
/**
 * @var tip sets up the main tool tip object arrays
 */
var tip = new Array();
/**
 * @var tObj sets up the tool tip object
 */
tObj = new Object();
/**
 * @var tipPref sets up the main tool tips preference object
 */
var tipPref = new Array();
/**
 * Dynamic HTML functions
 */
var dhtml = new Array();
/* the dhtml object variable */
dhtml = new setDHTML();
/**
 * Primary Date Object
 */
var date = new Array();
/* the date object variable */
date = new dateObject();

var implementIFrame = false;

/* code for disabling ENTER key in forms */
var nav = window.Event ? true : false;
if (nav) {
  window.captureEvents(Event.KEYDOWN);
	// If NS -- that is, !IE -- then set up for mouse capture
	window.captureEvents(Event.MOUSEOVER);
  window.onkeydown = NetscapeEventHandler_KeyDown;
  window.onmouseover = NetscapeEventHandler_MouseOver;
} else {
  document.onkeydown = MicrosoftEventHandler_KeyDown;
  document.onmouseover = MicrosoftEventHandler_MouseOver;
}

var cursorposition = {x:0,y:0};

function NetscapeEventHandler_MouseOver(e) {
  cursorposition = {x:e.pageX,y:e.pageY};
  return true;
}
function MicrosoftEventHandler_MouseOver() {
  cursorposition = {x:event.clientX,y:event.clientY};
  return true;
}
function NetscapeEventHandler_KeyDown(e) {
  if (e.which == 13 && e.target.type != 'textarea' && e.target.type != 'submit') { return false; }
  return true;
}

function MicrosoftEventHandler_KeyDown() {
  if (event.keyCode == 13 && event.srcElement.type != 'textarea' && event.srcElement.type != 'submit')
    return false;
  return true;
}

/**
 * House cleaning
 */
if ( typeof(NS4)=="undefined"&&typeof(IE)=="undefined" ) {
	NS4 = (typeof(document.layers)!="undefined"&&parseInt(navigator.appVersion)<=4)?1:0;
	NS6 = ((document.getElementById)&&(navigator.appName=='Netscape'))?1:0;
	NS = (NS4||NS6)?1:0;
	IE = (document.all)?1:0;
	IE4 = (IE&&navigator.userAgent.indexOf("Opera")==-1)?1:0;
	OP = (navigator.userAgent.indexOf("Opera")!=-1)?1:0;
	OP4 = (OP&&!document.all&&document.getElementById)?1:0;
	OP7 = (OP&&document.all&&document.getElementById)?1:0;
	cmdHidden = (NS)?"hide":"hidden";
	cmdVisible = (NS)?"show":"visible";
}
// fix some stuff so it works without code changes
if ( OP7 ) { IE4 = 1; }
/**
 ***************************************************************
 * Javascript DHTML Class
 * @copyright 2004 Centricity Systems, Inc. All Rights Reserved
 * @version 1.0
 ***************************************************************
 */
/**
 * Used to populate browser agent information
 */
function setDHTML() {
	this.agent = new setAgent();
	this.allowDHTML = (IE||NS||NS6||OP7)?1:0;
	this.setContent = new Function("id","str","dhtmlSetContent(id,str)");
	this.setVisibility = new Function("id","v","e","dhtmlSetVisibility(id,v,e)");
	this.setDisplay = new Function("id","d","dhtmlSetDisplay(id,d)");
	this.setPosition = new Function("id","x","y","dhtmlSetPosition(id,x,y)");
	this.setPositionX = new Function("id","x","dhtmlSetPosition(id,x)");
	this.setPositionY = new Function("id","y","dhtmlSetPosition(id,null,y)");
	this.getPositionX = new Function("id","action","return dhtmlGetPosition(id,\"x\")");
	this.getPositionY = new Function("id","action","return dhtmlGetPosition(id,\"y\")");
	this.getRefById = new Function("id","return dhtmlGetReference(id)");
	this.getBrowserDisplayHeight = new Function("return dhtmlGetBrowserDisplayHeight()");
	this.getBrowserDisplayWidth = new Function("return dhtmlGetBrowserDisplayWidth()");
	this.addElement = new Function("id","str","ex","ref","dhtmlAddElement(id,str,ex,ref)");
}

function setAgent() {
	// set some version breakouts
	this.name = (OP?"Opera":(NS6?"Netscape Gecko":(NS?"Netscape":(IE?"Internet Explorer":"Unknown"))));
	this.id =  (OP7?"OP7":(OP4?"OP4":(OP?"OP":(NS6?"NS6":(NS4?"NS4":(NS?"NS":(IE4?"IE4":(IE?"IE":""))))))));
	this.agentString = navigator.appVersion;
	this.isOpera = new Function("return(OP?true:false)");
	this.isIE = new Function("return(IE?true:false)");
	this.isNetscape = new Function("return(NS?true:false)");
	this.isGecko = new Function("return(NS6?true:false)");
	this.isMac = new Function("return(MAC?true:false)");
}

function dhtmlGetBrowserDisplayHeight() {
	return dhtmlGetBrowserDisplay("height");
}

function dhtmlGetBrowserDisplayWidth() {
	return dhtmlGetBrowserDisplay("width");
}

function dhtmlGetBrowserDisplay(action) {
	if ( typeof(window.innerWidth) == "number" ) {
		return (action=="height"?window.innerHeight:window.innerWidth);
	}
	doc = document.documentElement;
	if ( doc && (doc.clientWidth || doc.clientHeight) ) {
		// IE 6+ in 'standards compliant mode'
		return (action=="height"?doc.clientHeight:doc.clientWidth);
	}
	doc = document.body;
	if ( doc && (doc.clientWidth || doc.clientHeight) ) {
		// IE 4 compatible
		return (action=="height"?doc.clientHeight:doc.clientWidth);
	}
	return false;
}

function dhtmlSetContent(id,str) {
	// get a reference
	ref = dhtmlGetReference(id.toString());
	if ( !ref ) { return; }
	if ( typeof(ref.innerHTML) != "undefined" ) {
		// used by IE, Konqueror, Opera 7+ and Gecko agents
		ref.innerHTML = str;
	} else if ( ref.document && ref.document != window.document ) {
		// used by layer agents
		ref.document.open();
		ref.document.write(str);
		ref.document.close();
	} else {
		// need to get the frame id I think, so comment out for now
		//if ( window.frames && window.frames.length && window.frames['nameOfIFrame'] ) {
			// used by Opera 6 and the like
		//	ref = window.frames['nameOfIFrame'].window;
		//	ref.document.open();
		//	ref.document.write(str);
		//	ref.document.close();
		//}
	}
}

function dhtmlSetElementBgColor(color,ref) {
	if ( ref.style ) { ref = ref.style; }
	if ( ref.background ) { ref.background = color; }
	else if ( ref.backgroundColor ) { ref.backgroundColor = color; }
	else if ( ref.bgColor ) { ref.bgColor = color; }
	else { /* failed to do anything */ return; }
}

function dhtmlAddElement(id,str,extra) {
	vN = (extra.visible=="hidden"?"hide":(extra.visible=="visible"?"show":extra.visible));
	v = (extra.visible=="hide"?"hidden":(extra.visible=="show"?"visible":extra.visible));
	isSub = (dhtmlAddElement.arguments.length==4?true:false);
	ref = (isSub?dhtmlAddElement.arguments[3]:null);
	// check if layer (Netscape stuff)
	if ( document.layers && window.Layer && document.classes ) {
		if ( isSub ) { document.layers[id.toString()] = new Layer(extra.width,ref); }
		else { document.layers[id.toString()] = new Layer(extra.width); }
		// write its contents
		document.layers[id.toString()].document.open();
		document.layers[id.toString()].document.write(str);
		document.layers[id.toString()].document.close();
		// set position if not null
		if ( extra.x != null ) { document.layers[id.toString()].left = extra.x; }
		if ( extra.y != null ) { document.layers[id.toString()].top = extra.y; }
		if ( extra.position != null ) { document.layers[id.toString()].position = extra.position; }
		if ( extra.bgcolor ) { dhtmlSetElementBgColor(extra.bgcolor,document.layers[id.toString()]); }
		if ( extra.zIndex != null ) { document.layers[id.toString()].zIndex = extra.zIndex; }
		if ( extra.mouseOver ) { document.layers[id.toString()].mouseOver = extra.mouseOver; }
		if ( extra.mouseOut ) { document.layers[id.toString()].mouseOut = extra.mouseOut; }
		// set visibility
		if ( vN ) { document.layers[id.toString()].visibility = vN; }
	} else if ( document.body ) {
		s = ""; m = ""; i = "";
		if ( extra.position ) { s += "position:"+extra.position+";"; i = s; }
		if ( extra.x != null ) { s += "left:"+extra.x+"px;"; i = s; }
		if ( extra.y != null ) { s += "top:"+extra.y+"px;"; i = s; }
		if ( extra.width != null ) { s += "width:"+extra.width+(extra.width.indexOf("%")?"":"px")+";"; i=s; }
		if ( extra.visible ) { s += "visibility:"+extra.visible+";"; i=s; }
		if ( extra.lineHeight ) { s += "line-height:"+extra.lineHeight+"px;"; i=s; }
		if ( extra.bgcolor ) { s += "background-color:"+extra.bgcolor+";"; i=s; }
		if ( extra.zIndex ) {
			s += "z-index:"+extra.zIndex+";";
			i += "z-index:"+(extra.zIndex-1)+";";
		}
		if ( s ) { s = " style=\""+s+"\""; i = " style=\""+i+"display:none;\"";}
		if ( extra.mouseOver ) { m += " onmouseover=\""+extra.mouseOver+"\""; }
		if ( extra.mouseOut ) { m += " onmouseout=\""+extra.mouseOut+"\""; }
		divStr = "<div id=\""+id+"\""+s+m+">"+str+"</div>"
		if ( IE4 && implementIFrame ) {
			divStr += "<iframe id=\"if"+id+"\" src=\"javascript:false;\" scrolling=\"no\" ";
			divStr += "frameborder=\"0\""+i+"></iframe>";
		}
		if ( extra.write ) { document.write(divStr); }
		else if ( typeof(document.body.innerHTML)!="undefined" ) {
			document.body.innerHTML += divStr;
		} else if ( document.body.insertAdjacentHTML ) {
			document.body.insertAdjacentHTML("beforeEnd",divStr);
		} else {
			// not working in this browser
		}
	} else {
		// not working in this browser
	}
}
function dhtmlSetPositionY(id,y) {
	dhtmlSetPosition(id,null,y);
}

function dhtmlSetPositionX(id,x) {
	dhtmlSetPosition(id,x);
}

function dhtmlSetPosition(id) {
	x = (dhtmlSetPosition.arguments.length==2?dhtmlSetPosition.arguments[1]:null);
	y = (dhtmlSetPosition.arguments.length==3?dhtmlSetPosition.arguments[2]:null);
	px = (document.childNodes)?"px":0;
	ref = dhtmlGetReference(id.toString());
	if ( !ref ) { return; }
	if ( ref.style ) { ref = ref.style; }
	// set coordinates based on passed values
	if ( x != null ) { ref.left = x + px; }
	if ( y != null ) { ref.top = y + px; }
}

function dhtmlGetPosition(id,action) {
	px = (document.childNodes)?"px":0;
	ref = dhtmlGetReference(id.toString());
	if ( !ref ) { return; }
	if ( ref.style ) { ref = ref.style; }
	val = (action == "x")?ref.left:ref.top;
	if ( !val ) { return 0; }
	x = val.indexOf("px");
	if ( x == -1 ) { return val; }
	// strip the px from end
	return val.substr(0,x);
}

function dhtmlGetReference(id) {
	oDoc = (dhtmlGetReference.arguments.length==2?dhtmlGetReference.arguments[1]:document);
	id = id.toString();
	if ( document.layers ) {
		// refers to netscape only layers support
		if ( oDoc.layers[id] ) { return oDoc.layers[id]; }
		// might be layer within layer, so loop through
		for(var x=0,y; !y && x < oDoc.layers.length; x++) {
			// if found, return the layer info, otherwise return nothing
			y = dhtmlGetReference(id,oDoc.layers[x].document);  // recurse through layers
		}
		return y;
	}
	if ( document.getElementById ) {
		// refers to DOM, IE5, NS6, Mozilla, and Opera
		return oDoc.getElementById(id);
	}
	if ( document.all ) {
		// refers to proprietary DOM and IE4
		return oDoc.all[id];
	}
	if ( document[id] ) {
		// refers to a netscape alternative
		return oDoc[id];
	}
	// nothing found, return false
	return false;
}

function dhtmlSetVisibility(id,v) {
	extra = (dhtmlSetVisibility.arguments.length>2)?dhtmlSetVisibility.arguments[2]:null;
	vN = (v=="hidden"?"hide":(v=="visible"?"show":v));
	v = (v=="hide"?"hidden":(v=="show"?"visible":v));
	// get a reference
	ref = dhtmlGetReference(id.toString());
	if ( !ref ) { return false; }
	if ( ref.style ) {
		dhtmlSetStyleAttributes(ref.style,extra);
		ref.style.visibility = v;  // DOM and proprietary DOM
	} else if ( ref.visibility ) {
		dhtmlSetStyleAttributes(ref,extra);
		ref.visibility = vN; // Netscape specific
	} else { return false; }
	return true;
}

function dhtmlSetStyleAttributes(ref,e) {
	if (!ref || !e) { return; }
	if ( e.x ) { ref.left = e.x+"px;"; }
	if ( e.y ) { ref.top = e.y+"px;"; }
	if ( e.position ) { ref.position = e.position; }
	if ( e.width ) { ref.width = e.width+(e.width.indexOf("%")?"":"px"); }
	if ( e.lineHeight ) { ref.lineHeight = e.lineHeight+"px"; }
	if ( e.bgcolor ) { ref.bgcolor=e.bgcolor; ref.backgroundColor=e.bgcolor; ref.background=e.bgcolor; }
	if ( e.zIndex ) { ref.zIndex = e.zIndex; }
}

function dhtmlSetDisplay(id,d) {
	// choices for d are: 'none', 'block', 'inline', 'list-item' or '' (empty)
	// get a reference
	ref = dhtmlGetReference(id.toString());
	if ( !ref ) { ref = new Object(); }
	if ( !ref ) { /* not supported or page hasn't loaded yet */ return; }
	if ( ref.style ) { ref = ref.style; }
	bad = (typeof(ref.display)=="undefined"&&!(window.ScriptEngine&&ScriptEngine().indexOf("inScrip")+1));
	if ( bad ) {
		// browser does not support the display element
		return;
	}
	// OK if reached here, so make the change
	ref.display = d;
}
/**
 * Special 'Click to Enlarge' javascript picture.
 * @param string title The title of the window that will open
 * @param string img_src The source of the image
 * @param integer width The width of the window
 * @param integer height The height of the window
 * @param boolean cls <i>optional</i> TRUE (default) if a close button should be present, FALSE for none
 * @param boolean rsz <i>optional</i> TRUE (default) if window can be resized.
 * @param boolean scrl <i>optional</i> TRUE (default) if scroll bars should be present.
 */
function enlarge(title,img_src,width,height) {
	cls = (enlarge.arguments.length==5?(enlarge.arguments[4]===false?false:true):true);
	rsz = (enlarge.arguments.length==6?(enlarge.arguments[5]===false?false:true):true);
	scrl = (enlarge.arguments.length==7?(enlarge.arguments[6]===false?false:true):true);
	img = "<img src=\""+img_src+"\" width=\""+width+"\" height=\""+height+"\">";
	popWindowSrc(title,img,true,width,height,cls,rsz,scrl);
}
/**
 * Calls the {@link popWindow()} function to display a new window with the param::src as content.
 * @param string title The title of the new window when displayed.
 * @param string src The source content to display in the window.
 * @param boolean center <i>optional</i> Identifies if the window should be centered when displayed.
 * False by default.
 * @param mixed width <i>optional</i> The width of the window to open. If not specified, opens to the
 * width of the users available display width.
 * @param mixed height <i>optional</i> The height of the window to open. If not specified, opens to the
 * height of the users available display height.
 * @param boolean close <i>optional</i> Identifies if a close button should be added to the bottom
 * of the content window. FALSE by default.
 * @param boolean resizable <i>optional</i> Identifies if the window should be allowed to be resized.
 * TRUE by default.
 * @param boolean scrollbars <i>optional</i> Identifies if the window should be allowed scrollbars if
 * content is wider or higher than window display. TRUE by default.
 * @param string bgcolor <i>optional</i> Identifies the background color of the window. Default is white
 * or #ffffff.
 */
function popWindowSrc() {
	popWindow("src",popWindowSrc.arguments);
}
/**
 * Calls the {@link popWindow()} function to display a new window with the param::url as content.
 * @param string url The URL to open in the new window.
 * @param boolean center <i>optional</i> Identifies if the window should be centered when displayed.
 * False by default.
 * @param mixed width <i>optional</i> The width of the window to open. If not specified, opens to the
 * width of the users available display width.
 * @param mixed height <i>optional</i> The height of the window to open. If not specified, opens to the
 * height of the users available display height.
 * @param boolean close <i>optional</i> Identifies if a close button should be added to the bottom
 * of the content window. FALSE by default.
 * @param boolean resizable <i>optional</i> Identifies if the window should be allowed to be resized.
 * TRUE by default.
 * @param boolean scrollbars <i>optional</i> Identifies if the window should be allowed scrollbars if
 * content is wider or higher than window display. TRUE by default.
 * @param boolean toolbar <i>optional</i> Identifies if the window should display the browser toolbar.
 * TRUE by default.
 * @param boolean menubar <i>optional</i> Identifies if the window should display the browser menubar.
 * TRUE by default.
 * @param boolean location <i>optional</i> Identifies if the window should display the browser location
 * or address field. TRUE by default.
 * @param boolean status <i>optional</i> Identifies if the window should display the browser status bar.
 * TRUE by default.
 */
function popWindowUrl() {
	popWindow("url",popWindowUrl.arguments);
}
/**
 * Pops up a new window with source content or to a URL.<br/>
 * <b>WARNING:</b> This function can not be called directly! Call {@link popWindowUrl()} or
 * {@link popWindowSrc()} to open a new window.
 * @param string type The type of window to open. Options are 'url' or 'src'.
 * @param object args An object containing arguments passed to prior calling function. See 
 * {@link popWindowUrl()} and {@link popWindowSrc()} for the parameters.
 */
function popWindow(type) {
	shoriz = (NS?15:0);
	svert = (NS?20:0);
	if ( !type || popWindow.arguments.length<2 ) { return; }
	args = popWindow.arguments[1];	// array of arguments from previous calling function
	i = 0;
	h = dhtmlGetBrowserDisplayHeight();
	w = dhtmlGetBrowserDisplayWidth();
	win_left = ",left=0,screenX=0";
	win_top = ",top=0,screenY=0";
	extra = new Array("height="+h,"width="+w,"left=0","screenX=0","top=0","screenY=0");
	center=false; cls=false;
	winId = "_popwin";
	if ( type == "url" ) {
		if ( !args[0] ) { return; }
		for(i=0; i<args.length; i++ ) {
			switch ( true ) {
				case (i==0) 				: param1=args[i]; break;
				case (i==1)					: center=args[i]; break;
				case (i==2&&args[i]>0): w=args[i]; extra[1]="width="+args[i]; break;
				case (i==3&&args[i]>0): h=args[i]; extra[0]="height="+args[i]; break;
				case (i==4) 				: cls=args[i]; break;
				case (i==5)					: extra[extra.length]="resizable="+((args[i]===false)?"no":"yes"); break;
				case (i==6)					: extra[extra.length]="scrollbars="+((args[i]===false)?"no":"yes"); break;
				case (i==7)					: extra[extra.length]="toolbar="+((args[i]===false)?"no":"yes"); break;
				case (i==8)					: extra[extra.length]="menubar="+((args[i]===false)?"no":"yes"); break;
				case (i==9)					: extra[extra.length]="location="+((args[i]===false)?"no":"yes"); break;
				case (i==10)				: extra[extra.length]="status="+((args[i]===false)?"no":"yes"); break;
			}
		}
	} else {
		param1 = "";
		src = "";
		title = "";
		use_scroll = true;
		bgclr = "bgcolor=\"#ffffff\"";
		lt="<"; gt=">"; gtlt=gt+lt;
		center = true;
		if ( !args[1] ) { return; }
		for(i=0; i<args.length; i++ ) {
			switch ( true ) {
				case (i==0) 			: title=args[i]; break;
				case (i==1) 			: src=args[i]; break;
				case (i==2)				: center=args[i]; break;
				case (i==3&&args[i]>0): w=args[i]; extra[1]="width="+args[i]; break;
				case (i==4&&args[i]>0): h=args[i]; extra[0]="height="+args[i]; break;
				case (i==5) 			: cls=args[i]; break;
				case (i==6)				: extra[extra.length]="resizable="+((args[i]===false)?"no":"yes"); break;
				case (i==7)				: extra[extra.length]="scrollbars="+((args[i]===false)?"no":"yes");
														use_scroll=((args[i]===false)?false:true); break;
				case (i==8)				: bgclr="bgcolor=\""+(args[i]?args[i]:"#ffffff")+"\""; break;
			}
		}
		// build source wrapping
		head = "";
		foot = "";
		htmlClose = false;
		bodyClose = false;
		switch ( true ) {
			case (src.substring(0,6)!=lt+"html"+gt) : head += lt+"html"+gt; htmlClose = true;
			case (src.substring(0,6)!=lt+"head"+gt) : head += lt+"title"+gt+title+lt+"/title"+gt;
			case (src.substring(0,5)!=lt+"body") :
				head += lt+"body marginheight=\"0\" marginwidth=\"0\" leftmargin=\"0\"";
				head += " rightmargin=\"0\" topmargin=\"0\" "+bgclr+gt; bodyClose = true;
		}
		btn_style = "{font-size:11px;}";
		para_style = "{font-family:verdana,arial,helvetica;font-size:12px;}";
		if ( cls && bodyClose ) {
			foot += lt+"form"+gt;
			foot += lt+"p"+gt+lt+"div align=\"center\""+gt;
			foot += lt+"hr size=\"1\" width=\"100%\"/"+gt;
			foot += lt+"input type=\"button\" name=\"close\" value=\"Close Window\"";
			foot += " onclick=\"window.close()\" style=\""+btn_style+"\"/"+gtlt+"/div"+gtlt+"/p"+gt;
			foot += lt+"/form"+gt;
		}
		foot += (bodyClose?lt+"/body"+gt:"")+(htmlClose?lt+"/html"+gt:"");
		if ( cls && bodyClose ) {
			extra[0]="height="+(parseInt(h)+(use_scroll?100+svert:60+svert));
			extra[1]="width="+(parseInt(w)+(use_scroll?shoriz:0));
		}
		extra[extra.length] = "dependent=yes";
		src = head+src+foot;
	}
	if ( center ) {
		l = popWindowCenterLeft(w);
		t = popWindowCenterTop(h);
		extra[2]="left="+l;
		extra[3]="screenX="+l;
		extra[4]="top="+t;
		extra[5]="screenY="+t;
	}
	// set props
	props = "";
	for(i=0; i<extra.length; i++) { props += ((props=="")?"":",")+extra[i]; }
	if ( type == "url" ) { window.open(param1,winId,props); return; }
	if ( typeof(win) == "undefined" || win.closed ) {
		win = window.open("",winId,props);
		win.document.write(src);
	}
	win.focus();
}
/**
 * Helper function that sets the window center left location
 * @param mixed width The width of the screen
 * @return string Returns the centered left or 0 (zero) if center left is greater than or equal
 * to screen width.
 */
function popWindowCenterLeft(width) {
	bw = dhtmlGetBrowserDisplayWidth();
	if ( width >= bw ) { return 0; }
	return (bw - width) / 2;
}
/**
 * Helper function that sets the window center top location
 * @param mixed height The height of the screen
 * @return string Returns the center top or 0 (zero) if center top is greater than or equal
 * to screen height.
 */
function popWindowCenterTop(height) {
	bh = dhtmlGetBrowserDisplayHeight();
	if ( height >= bh ) { return 0; }
	return (bh - height) / 2;
}
/**
 * Sets the desired image to show. Used primarily by mouseover/mouseout/etc events
 * @param string imgname The name of the image to set
 * @param string img The image to replace with
 */
function csapiSwapImg(imgname,img) {
	if ( imgname == '' ) { return; }
	// do dom
	path = dir(document.images[imgname].src);
	newImg = path + '/' + img;
	document.images[imgname].src = newImg;
}
/**
 * Sets the desired image to show. Used primarily by mouseover/mouseout/etc events
 * @param object _this The calling object (typically an <a> tag)
 * @param string name The name of the image to set
 * @param string img The image to replace with
 */
function showimg(_this,img) {
	if ( img == '' ) { return; }
	// get the path to the images
	path = dir(_this.src);
	newImg = path+'/'+img;	
	// change image
	document.images[_this.name].src = newImg;
}
/**
 * @param string path The path to return the file from
 * @return string Returns the directory only (no file)
 */
function dir() {
	if ( dir.arguments.length>=1 ) { path = dir.arguments[0]; }
	else { path = window.location.pathname;	}
	if ( path == "" ) { return path; }
	arr = path.split("/");
	file = (arr.length==0?"":arr.pop());
	f_ = file.split(".");
	if ( f_.length <= 1 ) { return path; }
	return (arr.length==0?"":arr.join("/"));
}
/**
 * Unscrambles a previously scrambled data string. This function is available exclusive to
 * xb:SiteServer code which may perform an initial scramble and required Javascript to perform
 * the descramble.
 * @param string str The string to unscramble.
 * @return string Returns the unscrambled string
 */
function unscramble(str) {
	b = '@abcdefg_hijklMNOPQRSTUVWXYZAB.CDEFGHIJKL-mnopqrstuvwxyz0123456789';
	a = 'nopqrstuvwxyzabc-defghijklmNOPQRSTUVWXY_ZABCDEFGHIJKLM9876543210.@';
	l = a.length; sl = str.length;
	i = 0; j = 0;
	s = '';
	for(i=0;i<sl;i++) {
		c = str.charAt(i);
		for(j=0;j<l;j++) { if ( a.charAt(j) == c ) { c = b.charAt(j); break; } }
		s += c;
	}
	return s;
}
/**
 * Special 'mailto' descrambler. Upon unscrambling, launches the mailto link.
 * @param string data Scrambled mailto string
 */
function jsm(data) {
	u = unscramble(data);
	location.href='mailto:'+escape(u.substr(7));
}
/**
 ***************************************************************
 * Dynamic Menu and Tool Tip
 * @copyright 2004 Centricity Systems, Inc. All Rights Reserved
 * @version 1.0
 ***************************************************************
 */
/**
 * Dynamic Menu Preferences. Must be called before calling {@link setMenu()} to setup global variables.
 * @param string id The ID or name of the dynamic layer associated with this popup. By default
 * the menu layer is identified as 'popmenu'.
 * @param boolean hideCntls <i>optional</i> identify if window controls in IE need to be hidden from
 * view. The default is FALSE.
 * Starting position is relative to where the mouse is located at the time of the popup call and
 * the x offset identifies how far from the mouse the left side of the pop window will display.
 * By default, the x offset is set to 0 (zero), or the most left side of the pop window will be
 * immediately at the mouse location.
 * @param integer offsetX <i>optional</i> default offset for X (or left) starting position.
 * Starting position is relative to where the mouse is located at the time of the popup call and
 * the x offset identifies how far from the mouse the left side of the pop window will display.
 * By default, the x offset is set to 0 (zero), or the most left side of the pop window will be
 * immediately at the mouse location.
 * @param integer offsetY <i>optional</i> default offset for Y (or top) starting position.
 * Starting position is relative to where the mouse is located at the time of the popup call and
 * the y offset identifies how far from the mouse the top side of the pop window will display.
 * By default, the y offset is set to 8 (eight pixels), or the top border of the pop window will be
 * 8 pixels away from the mouse location.
 * @param string bgcolor <i>optional</i> The default background color for the popup area. By default
 * the menus have a 'menu gray' background.
 * @param string width <i>optional</i> The default width of menu window to be displayed. By default
 * the window width of the popup window is 165 pixels wide.
 * @param integer delay <i>optional</i> The default time, in milliseconds, for how long the popup
 * window remains visible when not active. By default, the delay is set to 250 milliseconds.
 * @param string delayFunc <i>optional</i> The name of the function which handles the timeout or
 * display timer to hide the popup window upon timeout or delay inactivity. By default the name of
 * the function is 'hideMenu'. Note: This should not be changed unless you know what you're doing.
 */
function setMenuPref() {
	args = setMenuPref.arguments;
	return new setPref("menu",args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
}
/**
 * Tool Tip Preferences. Must be called before calling {@link setTip()} to setup global variables.
 * @param string id The ID or name of the dynamic layer associated with this popup. By default
 * the tips layer is identified as 'poptip'.
 * @param boolean hideCntls <i>optional</i> identify if window controls in IE need to be hidden from
 * view. The default is FALSE.
 * @param integer offsetX <i>optional</i> default offset for X (or left) starting position.
 * Starting position is relative to where the mouse is located at the time of the popup call and
 * the x offset identifies how far from the mouse the left side of the pop window will display.
 * By default, the x offset is set to 0 (zero), or the most left side of the pop window will be
 * immediately at the mouse location.
 * @param integer offsetY <i>optional</i> default offset for Y (or top) starting position.
 * Starting position is relative to where the mouse is located at the time of the popup call and
 * the y offset identifies how far from the mouse the top side of the pop window will display.
 * By default, the y offset is set to 2 (two pixels), or the top border of the pop window will be
 * 2 pixels away from the mouse location.
 * @param string bgcolor <i>optional</i> The default background color for the popup area. By default
 * the tips have a light yellow background.
 * @param string width <i>optional</i> The default width of tool tip window to be displayed. By default
 * the window width of the popup window is 250 pixels wide.
 * @param integer delay <i>optional</i> The default time, in milliseconds, for how long the popup
 * window remains visible when not active. By default, the delay is set to 250 milliseconds.
 * @param string delayFunc <i>optional</i> The name of the function which handles the timeout or
 * display timer to hide the popup window upon timeout or delay inactivity. By default the name of
 * the function is 'hideTip'. Note: This should not be changed unless you know what you're doing.
 */
function setTipPref() {
	args = setTipPref.arguments;
	return new setPref("tip",args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
}
/**
 * Sets the pop window preferences.<br/>
 * <b>NOTE: </b>This should not be called directly. Call {@link setTipPref()} or {@link setMenuPref()}
 * @param string type The type of preference object being created. Options are 'tip' or 'menu'.
 * @param object args The arguments passed into the calling function and passed through to this function.
 */
function setPref(type) {
	/* args = id, hideCntls, xpos, ypos, bgclr, width, delay, delayFunc */
	args = setPref.arguments;
	var delay = 250;
	var vOffset;
	var def_id;
	var bgc;
	var func;
	var width;
	if ( type == "tip" ) {
		def_id = "poptip";
		bgc = "#ffffd5";	// yellow
		func = "hideTip()";
		width = "250";
		vOffset = 2;
		hOffset = 10;
	} else if ( type == "menu" ) {
		def_id = "popmenu";
		bgc = "menu";	// menu gray
		func = "hideMenu()";
		width = "165";
		vOffset = 8;
		hOffset = 0;
	} else { return null; }
	this.type = type;
	this.id = (args[1]||args[1]==0)?args[1]:def_id;
	this.hideWinControls = (!IE)?false:(args[2]===true)?true:false;
	this.x = (args[3]>=0)?args[3]:null;
	this.y = (args[4]>=0)?args[4]:null;
	this.bgcolor = (args[5])?args[5]:bgc;
	this.width = (args[6])?args[6]:width;
	this.delay = (args[7])?args[7]:delay;
	this.delayFunction = (args[8])?args[8]:func;
	this.timeout = setTimeout(this.delayFunction,this.delay);
	this.vOffset = vOffset;
	this.hOffset = hOffset;
	this.horiz = false;
	this.table = false;
	// not used by tool tips
  this.setMenuStyle = new Function("style","setMenuStyleDefault(style,this)");
  this.useTable = new Function("b","this.table=b");
	this.Class = null;
	this.Style = new setStyleObj(this.width);
  this.setVerticalOffset = new Function("y","this.vOffset=y");
  this.setHorizontalOffset = new Function("x","this.hOffset=x");
  this.setStylePosition = new Function("pos","stylePosition(pos,this)");
  this.setStyleBgColor = new Function("c","styleBgColor(c,this)");
  this.setStyleWidth = new Function("w","styleWidth(w,this)");
  this.setStyleLineHeight = new Function("h","styleLineHeight(h,this)");
  this.setStyleFont = new Function("f","s","w","c","styleFont(f,s,w,c,this)");
  this.setStyleLinkFont = new Function("f","s","w","c","d","styleLinkFont(f,s,w,c,d,this)");
  this.setStyleLinkClass = new Function("c","styleLinkClass(c,this)");
  this.setStyleTextDecoration = new Function("d","styleDecoration(d,this)");
  this.setStyleBorder = new Function("s","t","c","styleBorder(s,t,c,this)");
  this.setStyleZIndex = new Function("z","styleZIndex(z,this)");
	this.setStylePadding = new Function("l","r","t","b","stylePadding(l,r,t,b,this)");
	return this;
}

function setStyleObj(width) {
	this.width = (width>0?width:"165");
	this.string = null;
	this.bgcolor = "menu";
	this.position = "absolute";
	this.lineHeight = "18";
	this.font = new setFontObj("verdana","12px","normal","#000000");
	this.alink = new setLinkObj("verdana","12px","normal","blue","underline");
	this.textDecoration = "none";
	this.border = new setBorderObj("2px","solid","#000000");
	this.zIndex = 100;
	this.padding = new setPaddingObj("10","10");
}

function setFontObj(f,s,w,c) {
	this.family = f;
	this.size = s;
	this.weight = w;
	this.color = c;
}

function setLinkObj(f,s,w,c,t) {
	this.family = f;
	this.size = s;
	this.weight = w;
	this.color = c;
	this.textDecoration = t;
	this.className = null;
}

function setBorderObj(s,t,c) {
	this.size = s;
	this.type = t;
	this.color = c;
}

function setPaddingObj(l,r,t,b) {
	this.left = l;
	this.right = r;
	this.top = t;
	this.bottom = b;
}

function setMenuStyleDefault(style,parent) {
	parent.horiz = (style=="horizontal"||style=="horiz"||style==1);
}

function styleWidth(w,parent) {
	parent.Style.width = w;
	parent.width = w;
	parent.Style.string = null;
}

function styleBgColor(c,parent) {
	parent.Style.bgcolor = c;
	parent.bgcolor = c;
	parent.Style.string = null;
}

function stylePosition(pos,parent) {
	parent.Style.position = pos;
	parent.Style.string = null;
}

function styleLineHeight(h,parent) {
	parent.Style.lineHeight = h;
	parent.Style.string = null;
}

function styleDecoration(t,parent) {
	parent.Style.textDecoration = t;
	parent.Style.string = null;
}

function styleZIndex(z,parent) {
	parent.Style.zIndex = z;
	parent.Style.string = null;
}

function styleFont(f,s,w,c,parent) {
	if ( typeof(parent.Style.font) != "object" ) { parent.Style.font = new Object(); }
	if ( f ) { parent.Style.font.family = f; }
	if ( s ) { parent.Style.font.size = s; }
	if ( w ) { parent.Style.font.weight = w; }
	if ( c ) { parent.Style.font.color = c; }
	parent.Style.string = null;
}

function styleLinkFont(f,s,w,c,d,parent) {
	if ( typeof(parent.Style.alink) != "object" ) { parent.Style.alink = new Object(); }
	if ( f ) { parent.Style.alink.family = f; }
	if ( s ) { parent.Style.alink.size = s; }
	if ( w ) { parent.Style.alink.weight = w; }
	if ( c ) { parent.Style.alink.color = c; }
	if ( d ) { parent.Style.alink.textDecoration = d; }
}

function styleLinkClass(c,parent) {
	if ( typeof(parent.Style.alink) != "object" ) { parent.Style.alink = new Object(); }
	if ( c ) { parent.Style.alink.className = c; }
}

function styleBorder(s,t,c,parent) {
	if ( typeof(parent.Style.border) != "object" ) { parent.Style.border = new Object(); }
	if ( s ) { parent.Style.border.size = s; }
	if ( t ) { parent.Style.border.type = t; }
	if ( c ) { parent.Style.border.color = c; }
	parent.Style.string = null;
}

function stylePadding(l,r,t,b,parent) {
	if ( typeof(parent.Style.padding) != "object" ) { parent.Style.padding = new Object(); }
	if ( l ) { parent.Style.padding.left = l; }
	if ( r ) { parent.Style.padding.right = r; }
	if ( t ) { parent.Style.padding.top = t; }
	if ( b ) { parent.Style.padding.bottom = b; }
	parent.Style.string = null;
}

function setStyleDefaults(parent) {
	parent.setStylePosition("absolute");
	parent.setStyleBgColor("menu");
	parent.setStyleWidth("165");
	parent.setStyleLineHeight("18");
	parent.setStyleFont("verdana","12px","normal","#000000");
	parent.setStyleLinkFont("verdana","12px","normal","blue","underline");
	parent.setStyleTextDecoration("none");
	parent.setStyleBorder("2px","solid","#000000");
	parent.setStyleZIndex(100);
	parent.setStylePadding("20","20","20","20");
}

function setClass(c) {
	mnuPref.Class = c;
}

function setStyleString() {
	if ( typeof(setStyleString.arguments[0])!= "object") { return; }
	setStyleStrText(setStyleString.arguments[0]);
}

function setStyleStrText(o) {
	var rtn = "";
	var famRun = false;
	for (var name in o) {
		if ( typeof(o[name]) != "object" || !o[name] ) { continue; }
		for ( var key in o[name] ) {
			val = o[name][key];
			switch (key) {
				case "bgcolor"	: rtn += "background-color:"+val+";"; break;
				case "width"		: rtn += "width:"+val+((val.indexOf("%"))?"":"px")+";"; break;
				case "position"	: rtn += "position:"+val+";"; break;
				case "font"			:
					font = "";
					for (var n in val) {
						if ( n == "color" ) { rtn += "color:"+val[n]+";"; continue; }
						font += ((font)?" ":"")+val[n];
					}
					rtn += ((font)?"font:"+font+";":""); break;
				case "border"		:
					brdr = "";
					for (var n in val) { brdr += ((brdr)?" ":"")+val[n]; }
					rtn += "border:"+brdr+";"; break;
				case "padding"	:
					for (var n in val) { rtn += "padding-"+n+":"+val[n]+"px;"; }
					break;
				case "lineHeight": rtn += "line-height:"+val+"px;"; break;
				case "textDecoration": rtn += "text-decoration:"+val+";"; break;
				case "zindex": rtn += "z-index:"+val+";"; break;
			}
		}
	}
	rtn += "visibility:"+cmdHidden+";";
	if ( typeof(o.Stylestring)!="undefined" ) { o.Style.string = rtn; }
	else { o.string = rtn; }
}

function getLinkFontStyleStr(obj) {
	style = "";
	for (var n in obj) {
		switch (n) {
			case "color"		: style += "color:"+obj[n]+";"; break;
			case "textDecoration"	: style += "text-decoration:"+obj[n]+";"; break;
			case "family"		: style += "font-family:"+obj[n]+";"; break;
			case "size"			: style += "font-size:"+obj[n]+";"; break;
			case "weight"		: style += "font-weight:"+obj[n]+";"; break;
		}
	}
	return style;
}

function setDivStyleString(type) {
	oPref = (type=="tip")?tipPref:mnuPref;
	obj = oPref.Style.font;
	style = "";
	for (var n in obj) {
		switch (n) {
			case "color"		: style += "color:"+obj[n]+";"; break;
			case "family"		: style += "font-family:"+obj[n]+";"; break;
			case "size"			: style += "font-size:"+obj[n]+";"; break;
			case "weight"		: style += "font-weight:"+obj[n]+";"; break;
		}
	}
	if ( oPref.Style.textDecoration ) {
		style += "text-decoration:"+oPref.Style.textDecoration+";";
	}
	if ( style ) { style = " style=\""+style+"\""; }
	return style;
}

function setMenuDiv() { insertDiv("menu"); }

function setTipDiv() { insertDiv("tip"); }

function insertDiv(type) {
	oPref = (type=="tip")?tipPref:mnuPref;
	// before processing, make sure div hasn't already been set
	if ( !oPref.id || dhtmlGetReference(oPref.id) ) { return; }
	// not set yet, so continue
	mOver = (type=="tip")?"clearTips();":"clearMenus();highlightmenu(event,'on');";
	mOut = (type=="tip")?"closeTip(event);":"highlightmenu(event,'off');closeMenu(event);";
	if ( !oPref.Style.string ) { setStyleString(oPref.Style); }
	style = "";
	if ( oPref.Class ) { style = " class=\""+oPref.Class+"\""; }
	else if ( oPref.Style.string ) { style = " style=\""+oPref.Style.string+"\""; }
	// set up an object with style and other info
	e = new Object();
	e.width = oPref.Style.width;
	e.position = "absolute";
	e.visible = cmdHidden;
	e.mouseOver = mOver;
	e.mouseOut = mOut;
	e.lineHeight = oPref.Style.lineHeight;
	e.zIndex = oPref.Style.zIndex;
	e.bgcolor = oPref.Style.bgcolor;
	e.write = true;	// tell it to write out the first layer/div to page
	dhtml.addElement(oPref.id,"",e);
	dhtml.setDisplay(oPref.id,"none");
}
/* params optional id, hideCntls, horiz|(vert), subItem, offsetX, offsetY */
function setMenu() {
	idx = mnu.length;	// sets the next level in the index unless subItem has a value
	// set object info
	args = setMenu.arguments;
	this.id = (args[0])?args[0]:mnuPref.id;
	this.hideWinControls = (!IE)?false:(args[1]===true)?true:mnuPref.hideWinControls;
	this.horiz = (!args[2])?mnuPref.horiz:(args[2].substr(0,5)=="horiz"||args[2]==1)?true:false;
	this.x = (args[4])?args[4]:mnuPref.x;
	this.y = (args[5])?args[5]:mnuPref.y;
	this.parent = args[3];
	this.items = new Array();
  this.index=(args[3])?args[3].index:idx;
  this.addItem=new Function("text","url","this.items[this.items.length]=new setMenuItem(text,url,this)");
	// set array index with this object or submenu -- whatever is applicable
	if ( !args[3] ) { mnu[idx] = this; }
	else { args[3].subMenu = this; }
	// set the onclick event handler
	if ( !onclick_set ) { setOnClick(); }
	return this;
}
/* params optional id, hideCntls, offsetX, offsetY */
function setTip() {
	idx = tip.length;
	args = setTip.arguments;
	this.id = (args[0])?args[0]:tipPref.id;
	this.hideWinControls = (!IE)?false:(args[1]===true)?true:tipPref.hideWinControls;
	this.x = (args[2]>0)?args[2]:tipPref.x;
	this.y = (args[3]>0)?args[3]:tipPref.y;
	this.items = new Array();
	this.horiz = false;
	this.index = idx;
  this.addItem=new Function("name","text","width","hide","x","y","this.items[name]=new setTipItem(text,width,hide,x,y)");
	tip = this;
	return this;
}

function setMenuItem(text, url, parent) {
  this.text=text;
  this.url=url;
  this.parent=parent;
  this.subMenu=null;
}

function setTipItem(text) {
	args = setTipItem.arguments;
  this.text=text;
  this.width=(args[1])?args[1]:tipPref.Style.width;
  this.hide=(args[2])?args[2]:tipPref.hideWinControls;
  this.x=(args[3])?args[3]:tipPref.x;
  this.y=(args[4])?args[4]:tipPref.y;
}

function isNS6(a,b) {
	// Determines if 1 element in contained in another- by Brainjar.com
	while (b.parentNode) { if ( (b = b.parentNode) == a ) { return true; } }
	return false;
}

function closeMenu(e) { closePop("menu",e); }

function closeTip(e) { closePop("tip",e); }

function closePop(type,e) {
	obj = (type=="tip")?tObj:mObj;
	if ( (IE4) && !obj.contains(e.toElement) ) { hidePop(type); }
	else if ( NS6 && e.currentTarget != e.relatedTarget && !isNS6(e.currentTarget, e.relatedTarget) ) {
		hidePop(type);
	}
}

function clearMenus() { clearPops("menu"); }

function clearTips() { clearPops("tip"); }

function clearPops(type) {
	obj = (type=="tip")?tipPref:mnuPref;
	if ( obj.delay ) { clearTimeout(obj.timeout); }
}

function removeMenu() { removePop("menu"); }

function removeTip() { removePop("tip"); }

function removePop(type) {
	if ( IE4 || NS4 || NS6 ) {
		obj = (type=="tip")?tipPref:mnuPref;
		obj.timeout = setTimeout(obj.delayFunction,obj.delay);
	}
}

function hideMenu() { hidePop("menu"); }

function hideTip() { hidePop("tip"); }

function hidePop(type) {
	obj = (type=="tip")?tObj:mObj;
	if (window.obj && typeof(obj.thestyle) != "undefined") {
		iframe_id = "if"+obj.id;
		dhtml.setVisibility(obj.id,'hide');
		dhtml.setDisplay(obj.id,'none');
		if ( implementIFrame ) {
			dhtml.setVisibility(iframe_id,'hide');
			dhtml.setDisplay(iframe_id,'none');
		} else {
			// show window control objects
			if ( cmdHideShowToggle == cmdHidden ) {
				setWinControlsVisibility("select",cmdVisible);
			}
		}
	}
}

function showMenu(e,index) {
	if ( mnu.length-1 < index || index < 0 || (!NS && !IE) ) { return; }
	// hide any currently open pop up menu
	clearMenus();
	// set object we are working with
	m = mnu[index];
	// determine if menu is being displayed as fixed horizontal or dynamic vertical scroll
	// set divs
	setMenuObject(m.id,wrapMenu(m));
	showPopUp('menu',m,e);
}

function showTip(e,index) {
	if ( (!NS && !IE) ) { return; }
	// hide any currently open pop up tip
	clearTips();
	// set divs
	setTipObject(tip.id,wrapTip(tip,index));
	itemObj = tip.items[index];
	showPopUp('tip',tip,e,itemObj);
}

function showPopUp(type,m,e) {
	var item = null;
	if ( type=="tip" ) { item = showPopUp.arguments[3]; }
	obj = (type=="tip")?tObj:mObj;
	oPref = (type=="tip")?tipPref:mnuPref;
	if ( !m.horiz ) {
		// set content width info
		obj.contentwidth = getContentWidth(oPref);
		obj.contentheight = (IE4||NS6)?obj.offsetHeight:0;
		eventX = (IE4)?event.clientX:(NS6)?e.clientX:e.x;
		eventY = (IE4)?event.clientY:(NS6)?e.clientY:e.y;
		// Find out how close the mouse is to the corner of the window
		var rightedge = dhtml.getBrowserDisplayWidth()-eventX;
		var bottomedge = dhtml.getBrowserDisplayHeight()-eventY;
		// If horizontal distance isn't enough to accomodate the width of the context menu
		if ( rightedge < obj.contentwidth ) {
			// move the horizontal position of the menu to the left by it's width
			if ( IE4 ) {
				obj.thestyle.left = document.body.scrollLeft+eventX-obj.contentwidth;
			} else if ( NS6 ) {
				obj.thestyle.left = window.pageXOffset+eventX-obj.contentwidth;
			} else {
				obj.thestyle.left = eventX-obj.contentwidth;
			}
		} else {
			// position the horizontal position of the menu where the mouse was clicked
			if ( IE4 ) {
				obj.thestyle.left = document.body.scrollLeft+eventX;
			} else if ( NS6 ) {
				obj.thestyle.left = window.pageXOffset+eventX;
			} else {
				obj.thestyle.left = eventX;
			}
		}
		// same concept with the vertical position
		if ( bottomedge < obj.contentheight ) {
			if ( IE4 ) {
				obj.thestyle.top = document.body.scrollTop+eventY-obj.contentheight;
			} else if ( NS6 ) {
				obj.thestyle.top = window.pageYOffset+eventY-obj.contentheight;
			} else {
				obj.thestyle.top = eventY-obj.contentheight;
			}
		} else {
			if ( IE4 ) {
				obj.thestyle.top = document.body.scrollTop+event.clientY;
			} else if ( NS6 ) {
				obj.thestyle.top = window.pageYOffset+eventY;
			} else {
				obj.thestyle.top = eventY;
			}
		}
		// set vertical offset to mouse if vOffset is set
		var itemY = (item&&item.y?item.y:0);
		var t = parseInt(dhtml.getPositionY(m.id))+(itemY!=0?itemY:oPref.vOffset);
		dhtml.setPositionY(m.id,t);
		// set horizontal offset to mouse if hOffset is set
		var itemX = (item&&item.x?item.x:0);
		t = parseInt(dhtml.getPositionX(m.id))+(itemX!=0?itemX:oPref.hOffset);
		dhtml.setPositionX(m.id,t);
	} else {
		// set for horizontal
		obj.thestyle.left = m.x;
		obj.thestyle.top = m.y;
	}
	//	set visibility;
	iframe_id = "if"+m.id;
	dhtml.setVisibility(m.id,cmdVisible);
	dhtml.setDisplay(m.id,"");
	var hideCntrls = (item?item.hide:m.hideWinControls);
	if ( implementIFrame ) {
		dhtml.setVisibility(iframe_id,cmdVisible);
		dhtml.setDisplay(iframe_id,"block");
	} else if (hideCntrls) {
		// hide objects
		setWinControlsVisibility("select",cmdHidden);
	}
	return false;
}

function setWinControlsVisibility(tag, action) {
	if ( !IE4 || !document.all.tags ) { return; }
	cmdHideShowToggle = action;
	for (i=0; i<document.all.tags(tag).length; i++) {
		obj = document.all.tags(tag)[i];
		if (!obj || !obj.offsetParent)  { continue; }
		obj.style.visibility = action;
	}
}

function wrapMenu(m) {
	style = setDivStyleString("menu");
	div = "";
	divO = "<div"+style+" width=\""+mnuPref.width+"\""+((m.horiz)?" align=\"center\"":"")+">";
	divC = "</div>";
	tblO = "<table width=\""+mnuPref.width+"\"";
	tblO += " cellpadding=\"0\" cellspacing=\"0\" border=\"0\" bgcolor=\""+mnuPref.bgcolor+"\">";
	trO = "<tr>";
	trC = "</tr>";
	tdO = "<td align=\""+((m.horiz)?"center":"left")+"\"";
	tdO += ((mnuPref.Style.lineHeight)?" height=\""+mnuPref.Style.lineHeight+"\"":"")+">";
	tdC = "</td>";
	tblC = "</table>";
	var i;
	if ( m.horiz ) {
		if ( mnuPref.useTable && !NS6 ) {
			// set as horizontal
			div = tblO+trO+tdO;
			for(i=0;i<m.items.length;i++) {
				div += setAnchor(m.items[i].text,m.items[i].url);
				// separator
				if ( i < (m.items.length-1) ) { div += "&nbsp;|&nbsp;"; }
			}
			div += tdC+trC+tblC;
		} else {
			// set as horizontal
			div = divO;
			for(i=0;i<m.items.length;i++) {
				div += setAnchor(m.items[i].text,m.items[i].url);
				// separator
				if ( i < (m.items.length-1) ) { div += "&nbsp;|&nbsp;"; }
			}
			div += divC;
		}
	} else {
		if ( mnuPref.useTable ) {
			// set as vertical
			div = tblO;
			for(i=0;i<m.items.length;i++) {
				div += trO+tdO;
				div += setAnchor(m.items[i].text,m.items[i].url)+tdC+trC;
				// separator
				if ( i < (m.items.length-1) ) {
					div += trO;
					div += "<td height=\"1\" width=\"100%\" bgcolor=\"menu\" ";
					div += "style=\"font-size:2px;line-height:2px;\">&nbsp;</td>";
					div += trC;
				}
			}
			div += tblC;
		} else {
			// set as vertical
			div = "";
			for(i=0;i<m.items.length;i++) {
				div += divO;
				div += setAnchor(m.items[i].text,m.items[i].url);
				// separator
				if ( i < (m.items.length-1) ) { div += "<hr/>"; }
				div += divC;
			}
		}
	}
	return div;
}

function wrapTip(m,index) {
	style = setDivStyleString("tip");
	divStyle = (tipPref.useTable)?"":style;
	tblStyle = (tipPref.useTable)?style:"";
	style = "";
	divO = "<div"+divStyle+" width=\""+tipPref.width+"\""+((m.horiz)?" align=\"center\"":"")+">";
	divC = "</div>";
	tblO = "<table width=\""+tipPref.width+"\"";
	tblO += " cellpadding=\""+(tipPref.Style.padding.left?tipPref.Style.padding.left:0);
	tblO += "\" cellspacing=\"0\" border=\"0\" bgcolor=\""+tipPref.bgcolor+"\">";
	trO = "<tr>";
	trC = "</tr>";
	tdO = "<td align=\""+((m.horiz)?"center":"left")+"\"";
	tdO += ((tipPref.Style.lineHeight)?" height=\""+tipPref.Style.lineHeight+"\"":"")+tblStyle+">";
	tdC = "</td>";
	tblC = "</table>";
	return (tipPref.useTable)?tblO+trO+tdO+m.items[index].text+tdC+trC+tblC:divO+m.items[index].text+divC;
}

function setMenuObject(id,divLayer) {
	mObj = dhtml.getRefById(id);
	mObj.thestyle = (mObj.style)?mObj.style:mObj;
	dhtml.setContent(id,divLayer);
}

function setTipObject(id,divLayer) {
	tObj = dhtml.getRefById(id);
	tObj.thestyle = (tObj.style)?tObj.style:tObj;
	dhtml.setContent(id,divLayer);
}

function getContentWidth(pref) {
	if ( pref.width.indexOf("%") != -1) {
		return dhtml.getBrowserDisplayWidth()*pref.width;
	}
	return pref.width;
}

function setAnchor(text,url) {
	s = "";
	if ( mnuPref.Style.alink.className ) {
		s += " class=\""+mnuPref.Style.alink.className+"\"";
	} else {
		if ( mnuPref.Style.alink ) {	s += getLinkFontStyleStr(mnuPref.Style.alink);	}
		if ( s ) { s = " style=\""+s+"\""; }
	}
	rtn = "<a href=\""+url+"\""+s+">"+text+"</a>";
	return rtn;
}

function highlightmenu(e,state) {
	if ( IE ) { source_el = event.srcElement; }
	return;
/*
	else if ( NS6 ) {
		source_el = e.target;
		if ( source_el.id=="popmenu" ) {
			source_el.id = (state=="on")?"mouseoverstyle":"";
		}
	} else {
		while(source_el.id!="popmenu") {
			source_el = (NS6)?source_el.parentNode:source_el.parentElement;
			if ( source_el.className=="menuitems" ) {
				source_el.id = (state=="on")?"mouseoverstyle":"";
			}
		}
	}
*/
}

function setOnClick() {
	if (IE4||NS6) { document.onclick = hideMenu; }
	onclick_set = true;
}
/**
 ***************************************************************
 * Javascript Date Class
 * @copyright 2004 Centricity Systems, Inc. All Rights Reserved
 * @version 1.0
 ***************************************************************
 */
/**
 * Date Object containing all methods and properties for handling dates
 * @copyright 2003 Centricity Systems, All Rights Reserved
 * @version 1.0
 */
function dateObject() {
	var t = new Date();
	this.month = dateGetMonth(t);
	this.year = dateGetYear(t);
	this.day = dateGetDay(t);
	this.date = dateGetDayOfMonth(t);
	this.ordinal = monthOrdSuffix(t);
	this.writeDate = new Function("format","dateWriteDate(format)");
	this.date = new Function("format","return dateGetDate(format)");
	this.timestamp = new Function("return new Date()");
}
/**
 * Writes a date formatted to screen
 * @param string format Format string for date
 * @param time timestamp <i>optional</i> Pass in a timestamp to use, otherwise a current timestamp
 * is created.
 */
function dateWriteDate(format) {
	document.write(dateGetDate(format,dateWriteDate.arguments[1]));
}
/**
 * dateString dateGetDate(format [,timestamp])
 * @param string format Format string for date
 * @param time timestamp <i>optional</i> Pass in a timestamp to use, otherwise a current timestamp
 * is created.
 * @rturn string Returns a date string formatted according to param::format.
 */ 
function dateGetDate(format) {
	args = dateGetDate.arguments;
	timestamp = (args.length>1?args[1]:new Date());
	s = "";
	for(i=0;i<format.length;i++) {
		switch( format.charAt(i) ) {
			// lowercase Ante or Post meridiem
			case "a"	: s += dateGetMeridiem(timestamp); break;
			// uppercase Ante or Post meridiem
			case "A"	: s += dateGetMeridiem(timestamp,true); break;
			// day of month, 2 digits with leading zero
			case "d"	: s += dateGetDayOfMonth(timestamp,true); break;
			// Textual representation of day, three letters
			case "D"	: s += dateGetDay(timestamp,1); break;
			// full textual representation of month
			case "F"	: s += dateGetMonth(timestamp,2); break;
			// 12-hour format of hour w/o leading zero
			case "g"	: s += dateGetHours(timestamp); break;
			// 24-hour format of hour w/o leading zero
			case "G"	: s += dateGetHours(timestamp,false,true); break;
			// 12-hour format of hour w/ leading zero
			case "h"	: s += dateGetHours(timestamp,true); break;
			// 24-Hour format of hour w/ leading zero
			case "H"	: s += dateGetHours(timestamp,true,true); break;
			// Minutes w/ leading zero
			case "i"	: s += dateGetMinutes(timestamp,true); break;
			// Day of month w/o leading zero
			case "j"	: s += dateGetDayOfMonth(timestamp); break;
			// Full textual representation of day of week (Sunday through Saturday)
			case "l"	: s += dateGetDay(timestamp,2); break;
			// Whether it's a leap year (1 if is, 0 if not)
			case "L"	: s += dateIsLeapYear(timestamp); break;
			// Numeric representation of month w/ leading zero
			case "m"	: s += dateGetMonth(timestamp,0,true); break;
			// Short textual representation of month, three letter
			case "M"	: s += dateGetMonth(timestamp,1); break;
			// Numeric representation of month w/o leading zero
			case "n"	: s += dateGetMonth(timestamp,0); break;
			// Seconds w/ leading zero
			case "s"	: s += dateGetSeconds(timestamp,true); break;
			// English ordinal suffix for day of month, 2 char (st, nd, rd, th)
			case "S"	: s += monthOrdSuffix(timestamp); break;
			// Number of days in the given month (28 through 31)
			case "t"	: s += dateGetMonthDays(timestamp); break;
			// Seconds since the Unix Epoch (January 1, 1970 00:00:00 GMT)
			case "U"	: s += dateGetSecondsFromEpoch(timestamp); break;
			// Numeric representation of the day of week (0 for Sun, 6 for Sat)
			case "w"	: s += dateGetDay(timestamp); break;
			//case "W"	: s += ""; break; // Week number of year
			// Full numeric representation of year, 4 digits
			case "Y"	: s += dateGetYear(timestamp); break;
			// Two digit representation of year
			case "y"	: s += dateGetYear(timestamp,false); break;
			//case "z"	: s += ""; break; // Day of year (starting from 0) (0 through 365)
			default		: s += format.charAt(i); break; // leave alone, let it pass through
		}
	}
	return s;
}

function dateGetSecondsFromEpoch() {
	args = dateGetSecondsFromEpoch.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	// turn into datestring
	datestr = timestamp.toUTCString();
	ms = Date.parse(datestr);
	return (ms/1000);
}

function dateGetMeridiem() {
	args = dateGetMeridiem.arguments;
	upper = (args.length>1?args[1]:false);
	timestamp = (args.length>0?args[0]:new Date());
	morn = false;
	if ( timestamp.getHours() <= 11 ) { morn = true; }
	return (morn&&upper)?"AM":(morn&&!upper)?"am":(!morn&&upper)?"PM":"pm";
}

function dateGetDayOfMonth() {
	args = dateGetDayOfMonth.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	leading_zero = (args.length>1?args[1]:false);
	dm = timestamp.getDate();
	if ( dm <= 9 && leading_zero ) { return "0"+dm.toString(); }
	return dm.toString();
}

function dateGetDay() {
	args = dateGetDay.arguments;
	timestamp = (args.length>0&&args[0]?args[0]:new Date());
	type = (args.length>1?args[1]:0);
	full = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
	abrv = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
	d = timestamp.getDay();
	switch ( type ) {
		case 1	: return abrv[d];
		case 2	: return full[d];
		default	: return d.toString();
	}
}

function dateGetMonth() {
	args = dateGetMonth.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	type = (args.length>1?args[1]:0);
	leading_zero = (args.length>2?args[2]:false);
	full = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
	abrv = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
	m = timestamp.getMonth();
	switch ( type ) {
		case 1	: return abrv[m];
		case 2	: return full[m];
		default	:
			s = (m+1);
			if ( leading_zero && s <= 9 ) { return "0"+s.toString(); }
			return s.toString();
	}
}

function dateGetHours() {
	args = dateGetHours.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	leading_zero = (args.length>1?args[1]:false);
	twentyfour = (args.length>2?args[2]:false);
	h = timestamp.getHours();
	hh = (h>=13?h-12:h);
	if ( !twentyfour ) {
		if ( leading_zero && hh <= 9 ) { return "0"+hh.toString(); }
		return hh.toString();
	} else {
		if ( leading_zero && h <= 9 ) { return "0"+h.toString(); }
		return h.toString();
	} 
}

function dateGetMinutes() {
	args = dateGetMinutes.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	leading_zero = (args.length>1?args[1]:false);
	m = timestamp.getMinutes();
	if ( leading_zero && m <= 9 ) { return "0"+m.toString(); }
	return m.toString();
}

function dateGetSeconds() {
	args = dateGetSeconds.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	leading_zero = (args.length>1?args[1]:false);
	m = timestamp.getSeconds();
	if ( leading_zero && m <= 9 ) { return "0"+m.toString(); }
	return m.toString();
}

function monthOrdSuffix() {
	args = monthOrdSuffix.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	m = dateGetDayOfMonth(timestamp);
	ii = parseInt(m);
	if ( m.length == 2 ) { s = m.charAt(1); }
	else { s = m.charAt(0); }
	i = parseInt(s);
	if ( ii >= 11 && ii <= 13 ) { return "th"; }
	switch (i) {
		case 1	: return "st";
		case 2	: return "nd";
		case 3	: return "rd";
		default	: return "th";
	}
}

function dateGetYear() {
	args = dateGetYear.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	full = (args.length>1?args[1]:true);
	y = timestamp.getYear();
	if ( y >= 2000 ) { yy = y; y = (yy-2000); }
	else { yy = (1900+y); }
	return (full?yy.toString():(y<=9?"0":"")+y);
}

function dateIsLeapYear () {
	args = dateIsLeapYear.arguments;
	timestamp = (args.length>0?args[0]:new Date());
	y = year(timestamp);
	yy = parseInt(y);
	if ( ((yy % 4)==0) && ((yy % 100)!=0) || ((yy % 400)==0) ) { return 1; }
  return 0;
}

function dateGetMonthDays() {
	args = dateGetMonthDays.arguments;
	mos = new Array(0,31,0,31,30,31,30,31,31,30,31,30,31);
	timestamp = (args.length>0?args[0]:new Date());
	m = month(timestamp);
	i = parseInt(m);
	if ( i == 2 ) {
		if ( dateIsLeapYear(timestamp) ) { return 29; }
		else { return 28; }
	} else { return mos[i]; }
}

function time(datestr) {
	return new Date(datestr);
}
/**
 ***************************************************************
 * Javascript Utilities Class
 * @copyright 2004 Centricity Systems, Inc. All Rights Reserved
 * @version 1.0
 ***************************************************************
 */
/**
 * formats a number according to format
 * @param mixed value The value to format
 * @param integer decimals Number fo decimal places. Default is 0
 * @param string separator Separator to use if more than three digits. Default is none ("")
 * @param string symbol Symbol to prepend to value
 * @return string Returns formatted string
 */
function number_format() {
	args = number_format.arguments;
	sym = "";
	sep = "";
	dec = 0;
	val = "";
	switch ( args.length ) {
		case 4:	sym = args[3];
		case 3:	sep = args[2];
		case 2:	dec = args[1];
		case 1:	val = args[0]; break;
		default: return "";
	}
	return sym + precision(val,dec,sep);
}
/**
 * adds commas in number at appropriate values. Assumes the number has no decimal or other non-
 * integer values
 * @param mixed num The number to add commas to
 * @param string sep The separator. Default is comma (,)
 * @return string Returns the string representation of number with commas added
 */
function commafy(num) {
	sep = ",";
	if ( commafy.arguments.length == 2 ) { sep = commafy.arguments[1]; }
	s = '';
	c = 0;
	d = 3;
	n = num.toString();
	if ( n.length <= d ) { return n; }
	for(i=n.length;i>=0;i--) { s = (c++==d?sep:'')+n.charAt(i)+s; }
	return s;
}
/**
 * Sets a number to a precise decimal level
 * @param mixed val The number to be converted
 * @param integer r The precision (number of decimals). Default is 2
 * @param string sep <i>optional</i> Separator (e.g. comma). Default  is ","
 */
function precision(val,r) {
	sep = ",";
	if ( precision.arguments.length == 3 ) { sep = precision.arguments[2]; }
	v = strToNum(val);
	sv = v.toString();
	a = sv.split('.');
	n = commafy(parseInt(a[0]),sep);
	if ( r == 0 ) { return n; }
	// more than one decimal place
	s = n+'.';
	if ( a.length == 1 ) {
		s += str_repeat("0",r);
	} else if ( a[1].length > r ) {
		// first round the digits precision + 1
		f = Math.round(parseInt(a[1].substr(0,r+1)));
		// turn into decimal string
		fs = f.toString();
		// capture precision length
		fs += str_repeat("0",(r-fs.length));
		// reduce to precision if longer
		s += fs.substr(0,r);
	} else {
		s += a[1]+str_repeat("0",(r-a[1].length));
	}
	return s;
}
/**
 * Converts a string value to a number
 * @param string val The value to convert
 * @return float Returns the value as a number. If value could not be converted to a number, then
 * 0 (zero) is returned.
 */
function strToNum(val) {
	rgx = /[^0-9\.]/ig;
	if ( val == 'NaN' || val == '' || typeof(val) == "undefined" ) { return 0; }
	s = val+'';
	n = s.replace(rgx,'');
	if ( n == '' | n == '.') { n = 0; }
	return n;
}
/**
 * Trim function
 * @param string val The string to convert
 * @return string Returns the value trimmed
 */
function trimStr(val) {
	if ( typeof(val) != "string" ) { return val; }
	return (val==""?val:val.csapiTrim());
}
/**
 ***************************************************************
 * Javascript Form Class
 * @copyright 2004 Centricity Systems, Inc. All Rights Reserved
 * @version 1.0
 ***************************************************************
 */
/**
 * Form object for handling forms
 * example:
 *   form = new formObject([formname],[default_error_message],[validateHiddenFields]);
 * to validate a form, place in onsubmit of form tag:
 *   <form name="..." onsubmit="form.validate(this,[anyfunctions_return_a_boolean])">...</form>
 * to validate a credit card field:
 *   form.cc.validate(card_number,card_type,[card_code]);
 * to validate an email address field:
 *   form.email.validate(email_address);
 * to validate a URL field:
 *   form.url.validate(url_string);
 * to strip protocol (http or www) from front of URL:
 *   form.url.stripProtocol(url_string or field_object)  if field object, then TRUE is returned and
 * object is updated, otherwise the updated url_string is returned.
 */
function formObject() {
	var defMsg = " field requires a value for this form to process correctly!";
	arg = formObject.arguments;
	if ( arg.length > 1 ) { defMsg = arg[1]; }
	this.msg = defMsg;
	this.userMsg = null;
	this.msgChanged = false;
	this.formName = arg[0];
	this.showHiden = (arg[2])?true:false;
	this.submitted = false;
	this.isErr = false;
	// sets credit card object for handling credit cards
	this.cc = new setCC(this);
	// set email object for handling email addresses
	this.email = new setEmail(this);
	// set url object for handling URLs
	this.url = new setUrl(this);
	this.validateHiddenFields = new Function("b","this.showHidden=b");
	this.resetSubmitted = new Function("this.submitted=false");
	this.setFormName = new Function("n","this.formName=n");
	this.setUserMsg = new Function("msg","this.userMsg=msg;this.msgChanged=true");
	this.setDefaultMsg = new Function("msg","this.msg=msg");
	this.validate = new Function("a","b","return formValidate(this,a,b)");
}

function setCC(parent) {
	this.parent = parent;
	this.verify = true;
	this.ccMsg = "Card number is missing or invalid!";
	this.typeMsg = "Card type is missing or does not match card number!";
	this.codeMsg = "Security card code is missing or invalid!";
	this.setVerify = new Function("v","this.verify=v");
	this.setCardErrorMsg = new Function("msg","this.ccMsg=msg");
	this.setTypeErrorMsg = new Function("msg","this.typeMsg=msg");
	this.setCodeErrorMsg = new Function("msg","this.codeMsg=msg");
	this.validate = new Function("num","type","code","return ccValidate(this,num,type,code)");
}

function setEmail(parent) {
	this.parent = parent;
	this.verify = false;	// not by default
	this.errMsg = "Email address is missing or malformed!";
	this.setVerify = new Function("v","this.verify=v");
	this.setErrorMsg = new Function("msg","this.errMsg=msg");
	this.validate = new Function("addr","return emailValidate(this,addr)");
}

function setUrl(parent) {
	this.parent = parent;
	this.verify = false;	// not by default
	this.domainErrMsg = "Domain is missing or malformed!";
	this.urlErrMsg = "The URL is missing or malformed!";
	this.setVerify = new Function("v","this.verify=v");
	this.setDomainErrMsg = new Function("msg","this.domainErrMsg=msg");
	this.setUrlErrMsg = new Function("msg","this.urlErrMsg=msg");
	this.validate = new Function("url","return urlValidate(this,url)");
	this.stripProtocol = new Function("url","return urlStripProtocol(this,url)");
	this.getTLD = new Function("url","return urlGetTLD(this,url)");
	this.getCLD = new Function("url","return urlGetCLD(this,url)");
}
/**
 * Standard routine for checking the validity of an entered email address to insure the
 * address is formed correctly before passing on to a form processing agent. If malformed or
 * error, an alert message will be displayed and the focus will be set to the field.
 * @param object _this The object of the field to be tested.
 * @return boolean Returns TRUE if no error, FALSE if error. On error, an
 * alert message is displayed before returning.
 */
function emailValidate(parent,addr) {
	filter = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
	if ( !filter.test(addr) ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.errMsg); return false;
	}
	return true;
}
/**
 * Standard routine for checking the validity of an entered email address to insure the
 * address is formed correctly before passing on to a form processing agent. If malformed or
 * error, an alert message will be displayed and the focus will be set to the field.
 * @param string email The object of the field to be tested.
 * @return boolean Returns TRUE if no error, FALSE if error.
 */
function emailIsValid(email) {
	filter = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
	return filter.test(email);
}
/**
 * This script derived from: Practical Javascript for the Usable Web (ISBN: 1904151051)
 * by Paul Wilton, Stephen Williams, and Sing Li.<br/>
 * Validates known credit cards. Allows spaces or no spaces. the following table is checked for
 * valid credit card numbers.<br/>
 * <table border="1" cellpadding="3" cellspacing="0">
 * <tr><td>Card Type</td><td>Prefix</td><td>Length</td></tr>
 * <tr><td>MasterCard</td><td>51-55</td><td>16</td></tr>
 * <tr><td>Visa</td><td>4</td><td>13 or 16</td></tr>
 * <tr><td>Discover</td><td>6011</td><td>16</td></tr>
 * <tr><td>Diners Club</td><td>300-305, 36, 38</td><td>14</td></tr>
 * <tr><td>Carte Blanche</td><td>300-305, 36, 38</td><td>14</td></tr>
 * <tr><td>AMEX</td><td>34, 37</td><td>15</td></tr>
 * </table>
 * @param string ccNum The credit card number to check
 * @param string ccType The type of credit card this number is from (e.g. mastercard, visa, ...)
 * @return boolean Returns either valid (TRUE) or not valid (FALSE). This does not determine if
 * a credit card is valid in the sense of able to purchase goods. It only tests for a valid number
 * scheme.
 */
function ccValidate(parent) {
	var args = ccValidate.arguments;
	var ccNum = "";
	var ccType = "";
	var verify = parent.verify;
	switch ( args.length ) {
		case 4 : ccCode = args[3];
		case 3 : ccType = args[2];
		case 2 : ccNum = args[1]; break;
		default :
				parent.parent.isErr = true; parent.parent.msgChanged = true;
				alert(parent.ccMsg); return false;
	}
	if ( verify && !ccCode ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.codeMsg); return false;
	}
	if ( !ccNum ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.ccMsg); return false;
	}
	if ( !ccType ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.typeMsg); return false;
	}
  var isValid = false;
  var ccCheckRegExp = /[^\d ]/;
  isValid = !ccCheckRegExp.test(ccNum);
	if ( !isValid ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.ccMsg); return false;
	}
  var ccNumOnly = ccNum.replace(/ /g,"");
  var ccNumLen = ccNumOnly.length;
  var lengthIsValid = false;
  var prefixIsValid = false;
  var prefixRegExp;
  switch(ccType.toLowerCase()) {
    case "mastercard":
		case "m":
      lengthIsValid = (ccNumLen == 16);
      prefixRegExp = /^5[1-5]/;
      break;
    case "visa":
		case "v":
      lengthIsValid = (ccNumLen == 16 || ccNumLen == 13);
      prefixRegExp = /^4/;
      break;
    case "amex":
		case "a":
		case "american express":
      lengthIsValid = (ccNumLen == 15);
      prefixRegExp = /^3(4|7)/;
      break;
    case "discover":
		case "d":
      lengthIsValid = (ccNumLen == 16);
      prefixRegExp = /^6011/;
      break;
		case "diners club":
		case "i":
		case "carte blanche":
		case "c":
      lengthIsValid = (ccNumLen == 14);
      prefixRegExp = /^3(00|01|02|03|04|05|6|8)/;
      break;
    default:
			parent.parent.isErr = true; parent.parent.msgChanged = true;
			alert(parent.ccMsg); return false;
  }
  prefixIsValid = prefixRegExp.test(ccNumOnly);
  isValid = (prefixIsValid && lengthIsValid);
	if ( !isValid ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.ccMsg); return false;
	}
  var numberProduct;
  var numberProductDigitIndex;
  var checkSumTotal = 0;
  for (digitCounter=ccNumLen-1;digitCounter>=0;digitCounter--) {
    checkSumTotal += parseInt (ccNumOnly.charAt(digitCounter));
    digitCounter--;
    numberProduct = String((ccNumOnly.charAt(digitCounter) * 2));
    for (var productDigitCounter=0;productDigitCounter<numberProduct.length;productDigitCounter++) {
      checkSumTotal += parseInt(numberProduct.charAt(productDigitCounter));
    }
  }
  if ( !(checkSumTotal % 10 == 0) ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.ccMsg); return false;
	}
	if ( verify && !ccCodeValidate(ccCode,ccType) ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.codeMsg); return false;
	}
	return true;
}
/**
 * Verifies security card code
 * @param object _this The object of the field to be tested.
 * @param string ccType The type of credit card this number is from (e.g. mastercard, visa, ...)
 */
function ccCodeValidate(ccCode,ccType) {
  l = 0;
	cl = ccCode.length;
	switch(ccType.toLowerCase()) {
    case "mastercard"				:
		case "m"								:
		case "mc"								:
    case "visa"							:
		case "v"								:
		case "vs"								:
    case "discover"					:
		case "d"								: l = 3; break;
    case "amex"							:
		case "a"								:
		case "am"								:
		case "american express"	: l = 4; break;
    default: break;
  }
	return (cl>0&&l==cl);
}
/**
 * validates all form fields for valid data
 * @param object form The form being processed (passed as the object 'this')
 * @param boolean passThru <i>optional</i> Identifies the results of any functions run before
 * running this. Place function calls in this parameter or leave empty. If nothing passed,
 * defaults to TRUE.
 * @return boolean Returns TRUE if all fields validate correctly, otherwise returns FALSE and
 * generates a message error dialog box.
 */
function formValidate(parent) {
	var args = formValidate.arguments;
	var warn = '';
	if (parent.submitted) {
		warn = "WARNING! This form has already been submitted for processing and can not be ";
		warn += "submitted again.";
		alert(warn); return false;
	}
	var passThru = true;	// param 3
	switch ( args.length ) {
		case 3: passThru = (typeof(args[2])=="undefined"?true:args[2]);
						if ( !passThru ) { if ( parent.msgChanged ) { alert(parent.userMsg); } return false; }
		case 2: frm = args[1].elements; break; // param 1
		default: return false;
	}
	for(i=0;i<frm.length;i++) {
		if ( field_error(frm[i],parent) ) { return handleErr(frm[i],parent); }
	}
	parent.submitted = true;
	return true;
}

function handleErr(field,parent) {
	f = (field.title)?field.title:field.name;
	if ( f.substr(0,9).toLowerCase()=="override:" ) { f = f.substr(9); }
	else if ( f.substr(0,3).toLowerCase()=="..." ) { f = f.substr(3); }
	else if ( f.substr(0,1)==":" && f!=":" ) { f = f.substr(1); }
	else if ( f.substr(0,1)==" " && f!=" " ) { f = f.substr(1); }
	else { f = f + parent.msg; }
	if ( parent.msg.length > 0 ) {
		if ( !parent.msgChanged ) { alert(f); } else { alert(parent.userMsg); }
	}
	try { field.select(); }
	catch (e) { }
	try { field.focus(); }
	catch (e) { }
	return false;
}

function field_error(frm,parent) {
	id = frm.id.toLowerCase();
	if ( id != "required" && id.substr(0,9) != "required?" ) { return false; }
	type = frm.type.toLowerCase();
	field_empty = true;
	switch (type) {
		case "radio" 		: break;
		case "checkbox"	: field_empty = (!frm.checked); break;
		default : if ( type == "hidden" && !parent.showHidden ) { return false; }
							field_empty = (trim(frm.value)=="");
							break;
	}
	error = (id == "required" && field_empty);
	if ( error ) { return true; }
	// test required? evaluation of terms
	arr = frm.id.split("?");
	if ( arr.length == 2 ) {
		// set 'this' object to current setting
		find = /\bthis\b/gi;
		src = arr[1];
		arr[1] = src.replace(find, 'frm');
		// handle the parameter evaluation for required
		parent.msgChanged = false;
		parent.isErr = false;
		// a true evaluation means that the field is required
		// a false evaluation means that the field is not required
		required = eval("("+arr[1]+")");
		if ( !required ) { return false; }
		// if required, then test for empty field or isErr
		// isErr is set if the evaluation included a function call
		// empty fields are not allowed in 'required' fields
		error = (field_empty+parent.isErr);
	}
	return error;
}
/**
 * Strips protocol and leading www., ww1, ww2, ... or http://***. or https://***, ftp, etc. from
 * URL.
 * @param object parent The parent object.
 * @param mixed url The URL to be stripped passed as an object or as a string.
 * @return mixed Returns boolean TRUE if object passed, otherwise returns the stripped URL as string.
 */
function urlStripProtocol(parent,url) {
	isObj = (typeof(url)=="object");
	if ( isObj ) { obj = url; }
	else { obj = new Object(); obj.value = url; }
	if ( !obj.value ) { return (isObj)?true:obj.value; }
	// test first for any leading protocol or top level domain (e.g. www or ww#)
	reg = /^(((htt|ft|nt)p)[s]?:(\/\/)?)?(ww([0-9]+|w)\.)?/i;
	obj.value = obj.value.replace(reg,'');
	return (isObj)?true:obj.value;;
}

function urlValidate(parent,url) {
	isObj = (typeof(url)=="object");
	if ( isObj ) { obj = url; }
	else { obj = new Object(); obj.value = url; }
	regx = /^(((htt|ft|nt)p)[s]?:(\/\/)?)?(ww([0-9]+|w)\.)?((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
	if ( !regx.test(obj.value) ) {
		parent.parent.isErr = true; parent.parent.msgChanged = true;
		alert(parent.urlErrMsg); return false;
	}
	return true;
}

function urlGetTLD(parent,url) {
	isObj = (typeof(url)=="object");
	if ( isObj ) { obj = url; }
	else { obj = new Object(); obj.value = url; }
	regx = /^(?:(?:(?:htt|ft|nt)p)[s]?:(?:\/\/)?)?(?:ww(?:[0-9]+|w)\.)?(?:(?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
	found = obj.value.match(regx);
	if ( !found ) { return ''; }
	return found[1];
}

function urlGetCLD(parent,url) {
	isObj = (typeof(url)=="object");
	if ( isObj ) { obj = url; }
	else { obj = new Object(); obj.value = url; }
	regx = /^(?:(?:(?:htt|ft|nt)p)[s]?:(?:\/\/)?)?(?:ww(?:[0-9]+|w)\.)?(?:(?:[\w-]+\.)*\w[\w-]{0,66})\.(?:[a-z]{2,6}(\.[a-z]{2})?)$/i;
	found = obj.value.match(regx);
	if ( !found ) { return ''; }
	return found[1];
}
/**
 * Static.
 * Sets the url (domain name) to acceptable name (strips the front protocol if true)
 * @param object _this The field object to be tested and corrected if necessary.
 * @param boolean trimu TRUE if protocol is to be stripped, otherwise keep protocol
 */
function set_url(_this) {
	if ( _this.value == "" ) { return; }
	trimu = false;
	if ( set_url.arguments.length > 1 ) { trimu = set_url.arguments[1]; }
	new_url = _this.value;
	if ( trimu ) { new_url = trim_url(_this); }
	reg = /\.[a-zA-Z]+$/;
	tld = new_url.match(reg);
	if ( !tld || tld.toString().length <= 2 ) {
		m = "Domain is missing the top level domain (TLD) [e.g. .com, .net, .biz, ...]\n";
		m += "Top level domain must be present for domain name to be accepted.";
		alert(m); _this.select(); _this.focus(); return;
	}
	urlbody = new_url.replace(reg,"");
	reg = /^[a-zA-Z][A-Za-z0-9-]*?$/;
	if (!reg.test(urlbody) || urlbody.length <= 1 ) {
		m = "Domain is malformed! Check length and that appropriate characters are used.";
		alert(m); _this.select(); _this.focus(); return;
	}
	_this.value = new_url;
	return;
}
/**
 * Static.
 * Same as {@link trim_url} excepts sets field value (no returned string). Trims leading www.
 * or http://***. or https://***. from a url entry
 * @param object _this The field object to be tested and corrected if necessary.
 */
function set_base_domain(_this) {
	if ( typeof(_this) =="undefined" || _this.value == "" ) { return; }
	str = _this.value;
	// test first for any leading protocol or top level domain (e.g. wwx)
	reg = /((?:(?:htt|ft|nt)p)s?:\/\/|www\.)*/i;
	_this.value = str.replace(reg, '');
}
/**
 * Static.
 * Standard url trimmer removes the leading www. or http://***. or https://***. from a url entry
 * @param object _this The field object to be tested and corrected if necessary.
 * @return string Returns trimmed string
 */
function trim_url(_this) {
	m = "This url/domain name is malformed or invalid! ";
	m += "Please correct before continuing.";
	if ( _this.value == "" ) { return; }
	// test first for any leading protocol or top level domain (e.g. wwx)
	reg = /^(((htt|ft|nt)p)[s]?:(\/\/)?)?(ww([0-9]+|w)\.)?/i;
	str = _this.value;
	return str.replace(reg, '');
}
/**
 * Show properties of an object. Call this rather than an alert message.
 * @param string msg The message in front of object list
 * @param object obj The object.
 */
function alertObject(msg,obj) {
	result = msg;
	for (var i in obj) { result += "." + i + " = " + obj[i] + "\n"; }
	alert(result);
}

/**
 ***************************************************************
 * Javascript Security Class
 * @copyright 2004 Centricity Systems, Inc. All Rights Reserved
 * Other copyrights specified where applicable
 * @version 1.0
 ***************************************************************
 */
/**
 * Generates a unique id based on pool and length
 * @param integer length <i>optional</i> The length of the unique id to be returned. If not
 * specified, the default of 32 is used.
 * @param string pool <i>optional</i> The pool of characters to use to build the id.
 * If not specified, the default characters:
 * 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' are used.
 * @param boolean $append <i>optional</i> If set to TRUE, then any passed 'pool' characters are
 * appended to the default 'pool' of characters. If set to FALSE, then any passed in 'pool'
 * is used by itself. If 'pool' is empty, then the default 'pool' is used.
 * @param boolean hash <i>optional</i> If set to TRUE, then the id is hashed using MD5 hashing
 * algorithm, else the id is returned.
 * @return string Returns the unique id
 */ 
function unique_id() {
	l = 32;
	p = "";
	append = false;
	hash = false;
	switch ( unique_id.arguments.length ) {
		case 4 : hash = unique_id.arguments[3];
		case 3 : append = unique_id.arguments[2];
		case 2 : p = unique_id.arguments[1];
		case 1 : l = unique_id.arguments[0];
	}
	// set pool of possible char
	if(p == "" || append) {
		p += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		p += "abcdefghijklmnopqrstuvwxyz";
		p += "0123456789";
	} // end if
	 
	u_id = ""; 
	for (i=0; i<l; i++) {
	 	u_id += p.substr((Math.floor(Math.random()*p.length) % p.length), 1); 
	} // end for
	if ( hash ) { u_id = hex_md5(u_id); }
	return u_id;
} 
/**********************************************************************
 * Copyright (C) 2003, Centricity Systems, Inc. All Rights Reserved
 **********************************************************************/
/*
 * Process an internal xbSiteServer login form. Takes a known key and md5's it with
 * username and password and submits back. The following global variables are expected
 * to have been set prior to calling this function:
 * string u The name of the field to use for 'username'
 * string p The name of the field to use for 'password'
 * string kv The random 'key' value.
 * @param object f [required] the form object passed using the 'this' (no quotes) reserved word.
 */
function loginSubmit(f) {
	if ( !form.validate(f) ) { return; }
	// trim the fields
	var uv = trim(f.elements[u].value);
	var pv = trim(f.elements[p].value);
	if ( kv.length != 32 ) {
		alert("Form is malformed for login. Can not continue. Refresh page to continue.");
		return false;
	}
	// set and submit
	/* 1. Hash password */
	var xPwd = md5(pv+kv);
	/* 2. Combine username,hashed password,and key */
	var munged = md5(uv+xPwd+kv);
	/* 3. Set the password field with the new munged data */
	f.elements[p].value = munged;
	// submit
	return true;
}

/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 *
 * The JavaScript code implementing the algorithm is derived from the C code in
 * RFC 1321 and is covered by the following copyright:
 * Copyright (C) 1991-1992, RSA Data Security, Inc. Created 1991. All rights reserved.
 * License to copy and use this software is granted provided that it is identified as 
 * the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning
 * or referencing this software or this function.
 *
 * License is also granted to make and use derivative works provided that such works are
 * identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in
 * all material mentioning or referencing the derived work.
 *
 * RSA Data Security, Inc. makes no representations concerning either the merchantability of
 * this software or the suitability of this software for any particular purpose. It is provided
 * "as is" without express or implied warranty of any kind.
 *
 * These notices must be retained in any copies of any part of this documentation and/or software.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

/* 
 * Perform a simple self-test to see if the VM is working 
 */
function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;
  
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
 
    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);
  
}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++) 
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}
/**
 * @class
 * Associative Array object. Use similar to array accept allows
 * text indexes.
 * @example:<code>
 * // setting up an empty associative array and then populating
 * var arr = new AssocArray();
 * arr["myindex"] = "myvalue";
 * arr["mynextindex"] = "mynextval";
 * var cnt = arr.length();	// returns length/count. This example returns 2.
 * var cnt2 = arr.count();	// returns length/count. This example returns 2.
 * var indexSet = arr.isset("myindex");	// returns boolean true.
 * var indexSet = arr.isset("notindex");	// returns boolean false.
 * <br/><br/>
 * // setting up an associative array and adding indexes at the same time.
 * // note the =&gt; sign used to separate the index from the value all in
 * // a single string.
 * var arr = new AssocArray("myindex=>myvalue","mynextindex=>mynextval");
 * var cnt = arr.length();	// returns length/count. This example returns 2.
 * var cnt2 = arr.count();	// returns length/count. This example returns 2.
 * var indexSet = arr.isset("myindex");	// returns boolean true.
 * var indexSet = arr.isset("notindex");	// returns boolean false.
 * </code>
 * @constructor
 * Creates a new Associative Array object
 * @return {Object} Returns an AssocArray object
 */
function csapiAssocArray() {
	/**
	 * Returns number of indexes for this Associative Array object.
	 * Identical to {@link csapiAssocArray.count()}. Note this is a method "()" not a property.
	 * @return {Integer} Returns 0 if empty, otherwise the number of indexes.
	 * @see csapiAssocArray.count()
	 */
	this.length = function() {
		var idx;
		var cnt = 0-6;	// removes the other methods and properties from count
		for (var idx in this) { cnt += 1; }
		return (cnt==0?0:cnt);
	}
	/**
	 * Returns number of indexes for this Associative Array object.
	 * Identical to {@link csapiAssocArray.length()}. Note this is a method "()" not a property.
	 * @return {Integer} Returns 0 if empty, otherwise the number of indexes.
	 * @see csapiAssocArray.length()
	 */
	this.count = function() { return this.length(); }
	/**
	 * Identifies if a particular index has been set in the object.
	 * @param {String} indextext The index text value of the associative array
	 * to test.
	 * @return {Boolean} Returns true if exists, otherwise false.
	 */
	this.isset = function(indextext) {
		if (indextext==null || indextext=="") { return false; }
		return (eval("typeof(this."+indextext+")")=='undefined'?false:true);
	}
	/**
	 * Removes an existing index from the associative array.
	 * @param {String} indextext The index text value of the associative array
	 * to remove/unset.
	 * @return {void}
	 */
	this.unset = function(indextext) {
		if ( this.isset(indextext) ) { eval("delete this."+indextext+";"); }
	}
	/**
	 * Returns a string separated by param::separator, or if empty separated by comma,
	 * with the values shown as name=&gt;value.
	 * @param {String} separator <i>optional</i> the char or chars used to separate
	 * each name/value pair. If not provided, comma is used.
	 * @return {String} Returns the delimited string with name/value pairs between delimiter
	 * in the form name=&gt;value.
	 */
	this.join = function() {
		var sep = (this.join.arguments.length>0?this.join.arguments[0]:",");
		var str = "";
		for (var idx in this) {
			switch(idx) {
				case "length"			:
				case "count"			:
				case "isset"			:
				case "join"				:
				case "explode"		:
				case "unset"			:
					continue;
					break;
			}
			str += (str.length==0?"":sep)+idx+"=>"+this[idx];
		}
		return str;
	}
	/**
	 * Returns an array of name/value pairs in the format of name=&gt;value for each element.
	 * @param {String} [action] Returns 'text'|'name' or 'value' only in array.
	 * @return {Array} Returns an array of name/value pairs in format: name=&gt;value
	 */
	this.explode = function() {
		var arr = new Array();
		var only = (this.explode.arguments.length>0?this.explode.arguments[0]:"");
		only = ""+only;
		only = only.toLowerCase();
		for (var idx in this) {
			switch(idx) {
				case "length"			:
				case "count"			:
				case "isset"			:
				case "join"				:
				case "explode"		:
				case "unset"			:
					continue;
					break;
			}
			switch(only) {
				case 'name'	:
				case 'text'	:
					arr[arr.length] = idx; break;
				case 'value':
					arr[arr.length] = this[idx]; break;
				default	:
					arr[arr.length] = new Array(idx,this[idx]);
			}
		}
		return arr;
	}
	/*
	 * Used to set indexes passed in as parameters
	 * during constructor stage. Note that these parameters must
	 * use the =&gt; as a separator of the index and value. If
	 * this separator is not present, the whole string is set as
	 * the index and the value is set to null.
	 */
	for(var i=0; i<AssocArray.arguments.length; i++) {
		var sp = AssocArray.arguments[i];
		var s = sp.split("=>");
		if ( s.length == 1 ) { s[1] = null; }
		this[s[0]] = s[1];
	}
}
/**
 * @class
 * The main form object for handling forms on a page.
 * @constructor
 * @param {String} formName The name of the form
 * @param {String} formId The form Id
 * @param {String} [errSectionDivId] {optional} The DIV id for the
 * error section container.
 * @param {String} [errListDivId] {optional} The DIV id for the error
 * list (e.g. the UL-LI list).
 * @return {csapiForm}
 */
function csapiForm() {
	this.formName = null;
	this.form = null;
	this.delim = '~|~';
	this.exclude = "|xb_formid|xb_formpart|xb_formtype|xb_formrequest|xb_cardnumber|xb_cardcode|xb_cardexpmonth|xb_cardexpyear|xbsubmit|btn_set_ship|";
	this.bsFields = new Array();
	this.errSection = null;
	this.errList = null;
	this.cardCodeHelpPopupSet = false;
	
	this.empty = function(v) { return (v==null||v==""?true:false); }
	
	this.initialize = function(_args) {
		this.formId = _args[0];
		this.formName = _args[1];
		if ( _args.length > 3 ) {
			this.errSection = _args[2];
			this.errList = _args[3];
		}
		this.form = document.getElementById(this.formName);
		this.bsFieldInit();
		if ( !this.form ) { return; }
		this.loadFormFieldsFromCookie();
	}
	
	this.bsFieldInit = function() {
		this.clearBillToShipToFields();
		this.mapBillToShipToFields('xb_fname','xb_shipto_fname');
		this.mapBillToShipToFields('xb_lname','xb_shipto_lname');
		this.mapBillToShipToFields('xb_address','xb_shipto_address');
		this.mapBillToShipToFields('xb_address2','xb_shipto_address2');
		this.mapBillToShipToFields('xb_city','xb_shipto_city');
		this.mapBillToShipToFields('xb_state','xb_shipto_state');
		this.mapBillToShipToFields('xb_postal','xb_shipto_postal');
		this.mapBillToShipToFields('xb_country','xb_shipto_country');
		this.mapBillToShipToFields('xb_tel','xb_shipto_tel');
		this.mapBillToShipToFields('xb_email','xb_shipto_email');
	}

	this.serialize = function(arr) {
		if ( !arr ) { return ""; }
		if ( arr.length == 0 ) { return ""; }
		return arr.join(this.delim);
	}

	this.unserialize = function(v) {
		var rtnArr = new Array();
		if ( !v || this.empty(v) ) { return rtnArr; }
		return v.split(this.delim);
	}
	
	this.setFormCookie = function(v) {
    var date = new Date();
    date.setTime(date.getTime()+(365*24*60*60*1000));
    var _args = this.setFormCookie.arguments;
    var ckArr = new Array();
    ckArr[0] = this.formName+'='+v;
    ckArr[1] = "expires="+(_args.length>1?_arg[1]:date.toGMTString());
    ckArr[2] = "path=/";
	  document.cookie = ckArr.join("; ");
	}
	
	this.readFormCookie = function() {
	  var ca = document.cookie.split(';');
	  for(var i=0; i < ca.length; i++) {
	    var c = ""+ca[i];
	    c = c.csapiTrim();
	    if (c.indexOf(this.formName) == 0) {
	    	return c.substring(this.formName.length+1, c.length);
	    }
	  }
	  return null;
	}
	
	this.deleteFormCookie = function() { this.setFormCookie("",-1); }
	
	this.excludedField = function(v) {
		return (this.exclude.indexOf('|'+v+'|')>=0?true:false);
	}
	
	this.getFormFieldValue = function(field) {
		var rtnVal = "";
		switch ( field.type ) {
			case "select-one"	:
				rtnVal = field.options[field.selectedIndex].value;
				break;
			case "text"				:
			case "checkbox"		:
			case "hidden"			:
				rtnVal = field.value;
				break;
		}
		return rtnVal;
	}
	
	this.setFormField = function(field,val) {
		var indx = -1;
		switch(field.type.toLowerCase()) {
			case 'select-one'	:
				for(var i=0; i<field.options.length; i++) {
					if ( field.options[i].value == val ) {
						field.selectedIndex = i;
						break;
					}
				}
				break;
			case 'checkbox'		:
				field.checked = (val=='T'?true:false);
				break;
			default						:
				field.value = val;
				break;
		}
	}
	
	this.loadFormFieldsFromCookie = function() {
		if ( !this.form ) { return; }
		var vals = this.unserialize(this.readFormCookie());
		if ( !vals || vals.length == 0 ) { return; }
		var nv;
		for(var i=0; i<vals.length; i++) {
			nv = vals[i].split('=');
			if ( this.excludedField(nv[0]) ) { continue; }
			if ( !this.form.elements[nv[0]] ) { continue; }
			this.setFormField(this.form.elements[nv[0]],nv[1]);
		}
	}
	
	this.saveFormFieldsToCookie = function() {
		if ( !this.form ) { return; }
		var val;
		var out = new Array();
		for(var i=0; i<this.form.elements.length; i++) {
			if ( this.excludedField(this.form.elements[i].name) ) { continue; }
			val = this.getFormFieldValue(this.form.elements[i]);
			out[out.length] = this.form.elements[i].name+"="+val;
		}
		this.setFormCookie(this.serialize(out));
	}
	
	this.checkRequiredFields = function() {
		var errs = new Array();
		var rtn = true;
		if ( !this.form ) { return rtn; }
		var rqdAttr;
		var lblAttr;
		var val;
		for(var i=0; i<this.form.elements.length; i++) {
			try {
				rqdAttr = this.form.elements[i].getAttribute('required');
				lblAttr = this.form.elements[i].getAttribute('label');
				if ( !lblAttr ) { lblAttr = this.form.elements[i].name; }
				if ( !rqdAttr || rqdAttr == null ) { continue; }
				if ( rqdAttr != 'true' ) { continue; }
				// test for empty
				val = ""+this.getFormFieldValue(this.form.elements[i]);
				if ( this.empty(val.csapiTrim()) ) {
					errs[errs.length] = lblAttr+": required field can not be empty.";
				}
			} catch(e) {}
		}
		// check for error count
		if ( errs.length > 0 ) {
			alert("Please complete all required fields before submitting!");
			if ( this.errSection && this.errList ) {
				// process errors
				var dm = document.getElementById(this.errList);
				if ( dm ) {
					if ( dm.nodeName == 'TABLE' ) {
            var tbl = document.createElement('table');
            for(var i=0; i<errs.length; i++) {
              var tr = dm.insertRow(-1);
              var td = tr.insertCell(0);
              td.setAttribute('valign','top');
              var txt = document.createTextNode('- ');
              td.appendChild(txt);
              td = tr.insertCell(1);
              td.setAttribute('valign','top');
              txt = document.createTextNode(errs[i]);
              td.appendChild(txt);
            }
          } else {
            // original code
            dm.innerHTML = "<li>"+errs.join("</li><li>")+"</li>";
          }
					var d = document.getElementById(this.errSection);
					if ( d ) { d.style.display = "block"; }
				}
			}
			location.href="#";
			rtn = false;
		} else {
			this.saveFormFieldsToCookie();	// save the form fields to a cookie
		}
		errs = null;
		return rtn;
	}
	
	this.clearBillToShipToFields = function() {
		this.bsFields = new Array();
	}
	
	this.mapBillToShipToFields = function(billToField,shipToField) {
		this.bsFields[this.bsFields.length] = new Array(billToField,shipToField);
	}
	
	this.copyBillToShip = function() {
		if ( !this.form ) { return; }
		if ( this.bsFields.length == 0 ) { return; }
		// first check if ship fields have data in case we might overwrite them
		if ( !this.shipFieldsEmpty() ) {
			if ( !confirm("You are about to overwrite existing data in the shipping fields!\n\nAre you sure you want to do this?") ) {
				return;
			}
		}
		// now do the copy if made it to here
		for(var i=0; i<this.bsFields.length; i++) {
			this.copyBSField(this.bsFields[i]);
		}
	}
	
	this.copyBSField = function(arr) {
		try {
			if ( !arr || arr.length < 2 ) { return; }
			var bt = this.form.elements[arr[0]];
			var st = this.form.elements[arr[1]];
			if ( !st || !bt ) { return; }
			var val = this.getFormFieldValue(bt);
			this.setFormField(st,val);
		} catch(e) {}
	}
	
	this.shipFieldsEmpty = function() {
		if ( !this.form ) { return true; }
		if ( this.bsFields.length == 0 ) { return true; }
		var val = null;
		var obj = null;
		for(var i=0; i<this.bsFields.length; i++) {
			try {
				obj = this.form.elements[this.bsFields[i][1]];
				if ( !obj ) { continue; }
				val = ""+this.getFormFieldValue(obj);
				if ( !this.empty(val.csapiTrim()) ) { return false; }
			} catch(e) {}
		}
		return true;
	}

	this.setCCCodeHelpPopup = function(id,html) {
		// tipPref is a global variable
		tipPref = new setTipPref("poptip");
		tipPref.setMenuStyle("horiz");
		tipPref.setStyleWidth("275");
		tipPref.setVerticalOffset(-250);
		tipPref.setStyleLineHeight("20");
		tipPref.setStyleBgColor("#e1fcff");
		tipPref.setStyleFont("verdana,arial,helvetica","11px");
		tipPref.setStyleLinkFont("verdana","10px","normal","#ff0000","underline");
		tipPref.setStyleBorder("1px","solid","black");
		// set the tip html
		var t = new setTip();
		t.addItem(id,html);
		this.cardCodeHelpPopupSet = true;
	}
	
	this.ccCodePopup = function(_event,name) {
		if ( !this.cardCodeHelpPopupSet ) { return; }
		showTip(_event,name);
	}
	
	this.ccCodePopupRemove = function() { removeTip(); }
	/*
	 * Initialization
	 */
	this.initialize(csapiForm.arguments);	
}	// end class

function float_image(id,w,h) {
	var scrolledX;
	var scrolledY;
	var centerX;
	var centerY;
	var leftoffset;
	var topoffset;
	if( self.pageYoffset ) {
		scrolledX = self.pageXoffset;
		scrolledY = self.pageYoffset;
	} else if( document.documentElement && document.documentElement.scrollTop ) {
		scrolledX = document.documentElement.scrollLeft;
		scrolledY = document.documentElement.scrollTop;
	} else if( document.body ) {
		scrolledX = document.body.scrollLeft;
		scrolledY = document.body.scrollTop;
	}
	// Next, determine the coordinates of the center of browser's window
	if( self.innerHeight ) {
		centerX = self.innerWidth;
		centerY = self.innerHeight;
	} else if( document.documentElement && document.documentElement.clientHeight ) {
		centerX = document.documentElement.clientWidth;
		centerY = document.documentElement.clientHeight;
	} else if( document.body ) {
		centerX = document.body.clientWidth;
		centerY = document.body.clientHeight;
	}
	var o=document.getElementById(id);
	if ( !o ) { return; }
	// Xwidth is thewidth of the div, Yheight is the height of the
	// div passed as arguments to the function:
//alert('centerX: '+centerX+"\ncenterY: "+centerY+"\nScrollX: "+scrolledX+"\nScrollY: "+scrolledY+"\nwidth: "+w+"\nheight: "+h);
	leftoffset = (scrolledX + (centerX - w)) / 2;
	topoffset = (scrolledY + (centerY - h)) / 2;
//alert('left: '+leftoffset+"\ntop: "+topoffset);
	// The initial width and height of the div can be set in the
	// style sheet with display:none; divid is passed as an argument to // the function
	var r = o.style;
	r.position='absolute';
	r.zIndex = 10000;
	r.top = topoffset + 'px';
	r.left = leftoffset + 'px';
	r.display = "block";
}

function float_help(id) {
	var o=document.getElementById(id);
	if ( !o ) { return; }
	var _args = float_help.arguments;
	var offsetTop = (_args.length>1?_args[1]:50);
	var offsetLeft = (_args.length>2?_args[2]:10);
	var r = o.style;
	var scrolledY;
	if( self.pageYoffset ) {
		scrolledY = self.pageYoffset;
	} else if( document.documentElement && document.documentElement.scrollTop ) {
		scrolledY = document.documentElement.scrollTop;
	} else if( document.body ) {
		scrolledY = document.body.scrollTop;
	}
	var tempY;
	if (IE) {
		cursorposition.x = event.clientX + document.body.scrollLeft;
    cursorposition.y = event.clientY + document.body.scrollTop;
    tempY = cursorposition.y+scrolledY;
	} else {
		tempY = cursorposition.y;
	}
	r.left = parseInt(cursorposition.x-offsetLeft)+'px';
	r.position='absolute';
	r.visibility = 'hidden';
	r.display = "block";
	var h = o.offsetHeight;
	r.top = parseInt(tempY-h-offsetTop)+'px';
//alert('init test: '+o.offsetHeight+'; top: '+r.top+'; cursor y self: '+cursorposition.y+'; cursor y: '+tempY);
	r.zIndex = 10000;
	r.visibility = 'visible';
}

function csapiGetWindowSize() {
	var _width = 0;
	var _height = 0;

	if (!window.innerWidth) {
		// IE non-compliant
		if (!(document.documentElement.clientWidth == 0)) {
			// strict mode
			_width = document.documentElement.clientWidth;
			_height = document.documentElement.clientHeight;
		} else {
			// quirks mode
			_width = document.body.clientWidth;
			_height = document.body.clientHeight;
		}
	} else {
		// W3C
		_width = window.innerWidth;
		_height = window.innerHeight;
	}
	return {width:_width,height:_height};
}
/**
 * @param {Integer} obj_widthX The width of the object to center
 * @param {Integer} obj_heightY The height of the object to center
 * @param {Object} [winsize] {optional} Object coordinates from csapiGetWindowSize
 * @return {Object} Returns an object x and y
 */
function csapiGetWindowCenterCoords(wX,hY) {
	var _args = csapiGetWindowCenterCoords.arguments;
	var hWnd = (_args.length>2&&_args[2]!=null?_args[2]:{width:0,height:0});
	var _x = 0;
	var _y = 0;
	var offsetX = 0;
	var offsetY = 0;
	//IE
	if (!window.pageYOffset) {
		// IE  non-compliant
		if (!(document.documentElement.scrollTop == 0)) {
			// strict mode
			offsetY = document.documentElement.scrollTop;
			offsetX = document.documentElement.scrollLeft;
		} else {
			// quirks mode
			offsetY = document.body.scrollTop;
			offsetX = document.body.scrollLeft;
		}
	} else {
		// W3C
		offsetX = window.pageXOffset;
		offsetY = window.pageYOffset;
	}

	_x = ((wX-hWnd.width)/2)+offsetX;
	_y = ((hY-hWnd.height)/2)+offsetY;
	return {x:_x,y:_y};
}
