/**
 *  author:		Timothy Groves - http://www.brandspankingnew.net
 *	version:	1.2 - 2006-11-17
 *              1.3 - 2006-12-04
 *              2.0 - 2007-02-07
 *
 */
var useBSNns;

if (useBSNns) {
	if (typeof(bsn) == "undefined") {
		bsn = {}
	}
	_bsn = bsn;
} else {
	_bsn = this;
}

if (typeof(_bsn.Autosuggest) == "undefined") {
	_bsn.Autosuggest = {}
}

_bsn.AutoSuggest = function (fldID, param, callback) {
	// no DOM - give up!
	//
	if (!document.getElementById) {
		return false;
	}
	
	// get field via DOM
	//
	this.fld = _bsn.DOM.getElement(fldID);

	if (!this.fld) {
		return false;
	}
	
	// Set the callback
	this.callback = callback;
	
	// init variables
	//
	this.sInput 		= "";
	this.nInputChars 	= 0;
	this.aSuggestions 	= [];
	this.iHighlighted 	= 0;
	
	// parameters object
	//
	this.oP = (param) ? param : {};
	
	// defaults	
	//
	if (!this.oP.minchars)									this.oP.minchars = 1;
	if (!this.oP.method)									this.oP.meth = "get";
	if (!this.oP.varname)									this.oP.varname = "input";
	if (!this.oP.className)									this.oP.className = "autosuggest";
	if (!this.oP.timeout)									this.oP.timeout = 2500;
	if (!this.oP.delay)										this.oP.delay = 500;
	if (!this.oP.offsety)									this.oP.offsety = -5;
	if (!this.oP.shownoresults)								this.oP.shownoresults = true;
	if (!this.oP.noresults)									this.oP.noresults = "No results!";
	if (!this.oP.hinttext)									this.oP.hinttext = "Select an option below";
	if (!this.oP.maxheight && this.oP.maxheight !== 0)		this.oP.maxheight = 250;
	if (!this.oP.cache && this.oP.cache != false)			this.oP.cache = true;
	
	// set keyup handler for field
	// and prevent autocomplete from client
	//
	var pointer = this;
	
	// NOTE: not using addEventListener because UpArrow fired twice in Safari
	//_bsn.DOM.addEvent( this.fld, 'keyup', function(ev){ return pointer.onKeyPress(ev); } );
	
	this.fld.onkeypress 	= function(ev){ return pointer.onKeyPress(ev); }
	this.fld.onkeyup 		= function(ev){ return pointer.onKeyUp(ev); }
	
	this.fld.setAttribute("autocomplete","off");
}

_bsn.AutoSuggest.prototype.onKeyPress = function(ev) {
	
	var key = (window.event) ? window.event.keyCode : ev.keyCode;

	// set responses to keydown events in the field
	// this allows the user to use the arrow keys to scroll through the results
	// ESCAPE clears the list
	// TAB sets the current highlighted value
	//
	var RETURN = 13;
	var TAB = 9;
	var ESC = 27;
	
	var bubble = true;

	switch(key) {

		case RETURN:
			this.setHighlightedValue();
			bubble = false;
			break;
		case ESC:
			this.clearSuggestions();
			break;
	}

	return bubble;
}

_bsn.AutoSuggest.prototype.onKeyUp = function(ev) {
	var key = (window.event) ? window.event.keyCode : ev.keyCode;
	
	// set responses to keydown events in the field
	// this allows the user to use the arrow keys to scroll through the results
	// ESCAPE clears the list
	// TAB sets the current highlighted value
	//

	var ARRUP = 38;
	var ARRDN = 40;
	
	var bubble = true;

	switch(key) {
		case ARRUP:
			this.changeHighlight(key);
			bubble = false;
			break;
		case ARRDN:
			this.changeHighlight(key);
			bubble = false;
			break;
		default:
			this.getSuggestions(this.fld.value);
	}
	return bubble;
}

_bsn.AutoSuggest.prototype.getSuggestions = function (val) {
	
	// if input stays the same, do nothing
	//
	if (val == this.sInput) {
		return false;
	}
	
	// input length is less than the min required to trigger a request
	// reset input string
	// do nothing
	//
	if (val.length < this.oP.minchars) {
		this.sInput = "";
		return false;
	}
	
	// if caching enabled, and user is typing (ie. length of input is increasing)
	// filter results out of aSuggestions from last request
	//
	if (val.length>this.nInputChars && this.aSuggestions.length && this.oP.cache) {
		var arr = [];
		for (var i=0;i<this.aSuggestions.length;i++) {
			if (this.aSuggestions[i].value.substr(0,val.length).toLowerCase() == val.toLowerCase())
				arr.push( this.aSuggestions[i] );
		}
		
		this.sInput = val;
		this.nInputChars = val.length;
		this.aSuggestions = arr;
		
		this.createList(this.aSuggestions);

		return false;
	} else {
		// do new request
		//
		this.sInput = val;
		this.nInputChars = val.length;

		var pointer = this;
		clearTimeout(this.ajID);
		this.ajID = setTimeout( function() { pointer.doAjaxRequest() }, this.oP.delay );
	}

	return false;
}

_bsn.AutoSuggest.prototype.doAjaxRequest = function () {
	var pointer = this;
	
	// create ajax request
	var url = this.oP.script+this.oP.varname+"="+escape(this.fld.value);
	//alert(this.oP.script + "-"+ url);
	var meth = this.oP.meth;
	
	var onSuccessFunc = function (req) { pointer.setSuggestions(req) };
	var onErrorFunc = function (status) { alert("AJAX error: "+status); };

	var myAjax = new _bsn.Ajax();

	myAjax.makeRequest( url, meth, onSuccessFunc, onErrorFunc );
}

_bsn.AutoSuggest.prototype.setSuggestions = function (req) {
	this.aSuggestions = [];
	
	if (this.oP.json) {
		//alert("json="+req.responseText);
		var jsondata = eval('(' + req.responseText + ')');
		for (var i=0;i<jsondata.results.length;i++) {
			this.aSuggestions.push(  { 'id':jsondata.results[i].id, 'value':jsondata.results[i].value, 'info':jsondata.results[i].info }  );
		}
	} else {

		// traverse xml
		//
		if (false && req.responseXML) {
			//alert("req.responseXML="+req.responseXML);
			var results = req.responseXML.getElementsByTagName('results')[0].childNodes;
	
			for (var i=0;i<results.length;i++) {
				if (results[i].hasChildNodes()) {
					this.aSuggestions.push(  { 'id':results[i].getAttribute('id'), 'value':results[i].childNodes[0].nodeValue, 'info':results[i].getAttribute('info') }  );
				}
			}
		} else if (req.responseText) {
			//alert("req.responseText="+req.responseText);
			var rootElement = Xparse(req.responseText);
			//alert(rootElement.contents.length + ", type="+rootElement.type+",name="+rootElement.name);
			rootElement = rootElement.contents[0];
			for (var i = 0; i < rootElement.contents.length; i++) {
				var childNode = rootElement.contents[i];
				if (childNode.type == "element" && childNode.name.toLowerCase() == "rs") {
					
					var id = childNode.attributes["id"];
					id = (id != null && id != undefined) ? id : null;

					var info = childNode.attributes["info"];
					info = (info != null && info != undefined) ? info : "";
					
					var value = null;
					for (var j = 0; j < childNode.contents.length; j++) {
						if (childNode.contents[j].type == "chardata") {
							value = childNode.contents[j].value;
							break;
						}
					}
					if (id != null && value != null) {
						this.aSuggestions.push(  { 'id':id, 'value':value, 'info':info }  );
					}
				}
			}
		}
	
	}
	
	this.idAs = "as_"+this.fld.id;
	this.createList(this.aSuggestions);
}

_bsn.AutoSuggest.prototype.createList = function(arr) {
	var pointer = this;
	
	
	// get rid of old list
	// and clear the list removal timeout
	//
	_bsn.DOM.removeElement(this.idAs);
	this.killTimeout();
	
	// create holding div
	//
	var div = _bsn.DOM.createElement("div", {id:this.idAs, className:this.oP.className});	
	
	var hcorner = _bsn.DOM.createElement("div", {className:"as_corner"});
	var hbar = _bsn.DOM.createElement("div", {className:"as_bar"});
	var header = _bsn.DOM.createElement("div", {className:"as_header"});
	header.appendChild(hcorner);
	header.appendChild(hbar);
	div.appendChild(header);
	
	// create and populate ul
	//
	var ul = _bsn.DOM.createElement("ul", {id:"as_ul"});

	// show hint text
	if (arr.length > 0) {	
		var lix 			= _bsn.DOM.createElement(  "li", {className:""}, this.oP.hinttext  );
		ul.appendChild( lix );
	}
	
	// loop throught arr of suggestions
	// creating an LI element for each suggestion
	//
	for (var i=0;i<arr.length;i++) {
		// format output with the input enclosed in a EM element
		// (as HTML, not DOM)
		//
		var val = arr[i].value;
		var st = val.toLowerCase().indexOf( this.sInput.toLowerCase() );
		var output = val.substring(0,st) + "<em>" + val.substring(st, st+this.sInput.length) + "</em>" + val.substring(st+this.sInput.length);
		
		
		var span 		= _bsn.DOM.createElement("span", {}, output, true);
		if (arr[i].info != "") {
			var br			= _bsn.DOM.createElement("br", {});
			span.appendChild(br);
			var small		= _bsn.DOM.createElement("small", {}, arr[i].info);
			span.appendChild(small);
		}
		
		var a 			= _bsn.DOM.createElement("a", { href:"#" });
		
		var tl 		= _bsn.DOM.createElement("span", {className:"tl"}, " ");
		var tr 		= _bsn.DOM.createElement("span", {className:"tr"}, " ");
		a.appendChild(tl);
		a.appendChild(tr);
		
		a.appendChild(span);
		
		//a.name = i+1;
		// Added by Niyi 2010-01-29
		a.name = i+2;
		a.onclick = function () { pointer.setHighlightedValue(); return false; }
		a.onmouseover = function () { pointer.setHighlight(this.name); }
		
		var li 			= _bsn.DOM.createElement(  "li", {}, a  );
		
		ul.appendChild( li );
	}
	
	// no results
	if (arr.length == 0) {
		var li 			= _bsn.DOM.createElement(  "li", {className:"as_warning"}, this.oP.noresults  );
		ul.appendChild( li );
	}

	div.appendChild( ul );

	var fcorner = _bsn.DOM.createElement("div", {className:"as_corner"});
	var fbar = _bsn.DOM.createElement("div", {className:"as_bar"});
	var footer = _bsn.DOM.createElement("div", {className:"as_footer"});
	footer.appendChild(fcorner);
	footer.appendChild(fbar);
	div.appendChild(footer);

	// get position of target textfield
	// position holding div below it
	// set width of holding div to width of field
	//
	var pos = _bsn.DOM.getPos(this.fld);
	
	div.style.left 		= pos.x + "px";
	div.style.top 		= ( pos.y + this.fld.offsetHeight + this.oP.offsety ) + "px";
	div.style.width 	= this.fld.offsetWidth + "px";
	
	// set mouseover functions for div
	// when mouse pointer leaves div, set a timeout to remove the list after an interval
	// when mouse enters div, kill the timeout so the list won't be removed
	//
	div.onmouseover 	= function(){ pointer.killTimeout() }
	div.onmouseout 		= function(){ pointer.resetTimeout() }

	// add DIV to document
	//
	document.getElementsByTagName("body")[0].appendChild(div);
	
	// currently no item is highlighted
	//
	this.iHighlighted = 0;
	
	// remove list after an interval
	//
	var pointer = this;
	this.toID = setTimeout(function () { pointer.clearSuggestions() }, this.oP.timeout);
}

_bsn.AutoSuggest.prototype.changeHighlight = function(key) {	
	var list = _bsn.DOM.getElement("as_ul");
	if (!list) {
		return false;
	}
	// Added by Niyi 2010-01-29
	this.iHighlighted = (this.iHighlighted > 0) ? this.iHighlighted : 1;
	var n;

	if (key == 40) {
		n = this.iHighlighted + 1;
	} else if (key == 38) {
		n = this.iHighlighted - 1;
	}
	
	if (n > list.childNodes.length) {
		n = list.childNodes.length;
	}
	if (n < 1) {
		n = 1;
	}
	
	this.setHighlight(n);
}

_bsn.AutoSuggest.prototype.setHighlight = function(n) {
	var list = _bsn.DOM.getElement("as_ul");
	if (!list) {
		return false;
	}
	
	if (this.iHighlighted > 0) {
		this.clearHighlight();
	}
	
	this.iHighlighted = Number(n);
	
	list.childNodes[this.iHighlighted-1].className = "as_highlight";
	this.killTimeout();
}

_bsn.AutoSuggest.prototype.clearHighlight = function() {
	var list = _bsn.DOM.getElement("as_ul");
	if (!list) {
		return false;
	}
	
	if (this.iHighlighted > 0) {
		list.childNodes[this.iHighlighted-1].className = "";
		this.iHighlighted = 0;
	}
}

_bsn.AutoSuggest.prototype.setHighlightedValue = function () {
	if (this.iHighlighted) {
		// Added by Niyi 2010-01-29
		this.iHighlighted--;
		var label = this.aSuggestions[ this.iHighlighted-1 ].value + ", " + this.aSuggestions[ this.iHighlighted-1 ].info;
		//this.sInput = this.fld.value = this.aSuggestions[ this.iHighlighted-1 ].value;
		//this.sInput = this.fld.value = this.aSuggestions[ this.iHighlighted-1 ].id;
		this.sInput = this.fld.value = label;
		//this.fld.valueid = this.aSuggestions[ this.iHighlighted-1 ].id;
		//this.fld.setAttribute("valueid", this.fld.valueid);
		if (this.callback) {
			this.callback(this.aSuggestions[ this.iHighlighted-1 ].id, label);
		}
		//alert(this.fld.getAttribute("valueid"));
		// move cursor to end of input (safari)
		//
		this.fld.focus();
		if (this.fld.selectionStart) {
			this.fld.setSelectionRange(this.sInput.length, this.sInput.length);
		}

		this.clearSuggestions();
		
		// pass selected object to callback function, if exists
		//
		if (typeof(this.oP.callback) == "function") {
			this.oP.callback( this.aSuggestions[this.iHighlighted-1] );
		}
		// Added by Niyi 2010-01-29
		this.iHighlighted++;
	}
}

_bsn.AutoSuggest.prototype.killTimeout = function() {
	clearTimeout(this.toID);
}

_bsn.AutoSuggest.prototype.resetTimeout = function() {
	clearTimeout(this.toID);
	var pointer = this;
	//this.toID = setTimeout(function () { pointer.clearSuggestions() }, 1000);
	this.toID = setTimeout(function () { pointer.clearSuggestions() }, 5000);
}

_bsn.AutoSuggest.prototype.clearSuggestions = function () {
	
	this.killTimeout();
	
	var ele = _bsn.DOM.getElement(this.idAs);
	var pointer = this;
	if (ele) {
		//var fade = new _bsn.Fader(ele,1,0,250,function () { _bsn.DOM.removeElement(pointer.idAs) });
		var fade = new _bsn.Fader(ele,1,0,100,function () { _bsn.DOM.removeElement(pointer.idAs) });
	}
}

// AJAX PROTOTYPE _____________________________________________
if (typeof(_bsn.Ajax) == "undefined") {
	_bsn.Ajax = {}
}
_bsn.Ajax = function () {
	this.req = {};
	this.isIE = false;
}
_bsn.Ajax.prototype.makeRequest = function (url, meth, onComp, onErr) {
	
	if (meth != "POST") {
		meth = "GET";
	}
	
	this.onComplete = onComp;
	this.onError = onErr;
	
	var pointer = this;
	
	// branch for native XMLHttpRequest object
	if (window.XMLHttpRequest) {
		this.req = new XMLHttpRequest();
		this.req.onreadystatechange = function () { pointer.processReqChange() };
		this.req.open("GET", url, true); //
		this.req.send(null);
	// branch for IE/Windows ActiveX version
	} else if (window.ActiveXObject) {
		this.req = new ActiveXObject("Microsoft.XMLHTTP");
		if (this.req) {
			this.req.onreadystatechange = function () { pointer.processReqChange() };
			this.req.open(meth, url, true);
			this.req.send();
		}
	}
}
_bsn.Ajax.prototype.processReqChange = function() {
	
	// only if req shows "loaded"
	if (this.req.readyState == 4) {
		// only if "OK"
		if (this.req.status == 200) {
			this.onComplete( this.req );
		} else {
			this.onError( this.req.status );
		}
	}
}

// DOM PROTOTYPE _____________________________________________

if (typeof(_bsn.DOM) == "undefined") {
	_bsn.DOM = {}
}
_bsn.DOM.createElement = function ( type, attr, cont, html ) {
	var ne = document.createElement( type );
	if (!ne) {
		return false;
	}
	for (var a in attr) {
		ne[a] = attr[a];
	}	
	if (typeof(cont) == "string" && !html) {
		ne.appendChild( document.createTextNode(cont) );
	} else if (typeof(cont) == "string" && html) {
		ne.innerHTML = cont;
	} else if (typeof(cont) == "object") {
		ne.appendChild( cont );
	}
	return ne;
}

_bsn.DOM.clearElement = function ( id ) {
	var ele = this.getElement( id );
	
	if (!ele) {
		return false;
	}
	
	while (ele.childNodes.length) {
		ele.removeChild( ele.childNodes[0] );
	}
	return true;
}

_bsn.DOM.removeElement = function ( ele ) {
	var e = this.getElement(ele);
	
	if (!e) {
		return false;
	} else if (e.parentNode.removeChild(e)) {
		return true;
	} else {
		return false;
	}
}
_bsn.DOM.replaceContent = function ( id, cont, html ) {
	var ele = this.getElement( id );
	
	if (!ele) {
		return false;
	}
	this.clearElement( ele );
	
	if (typeof(cont) == "string" && !html) {
		ele.appendChild( document.createTextNode(cont) );
	} else if (typeof(cont) == "string" && html) {
		ele.innerHTML = cont;
	} else if (typeof(cont) == "object") {
		ele.appendChild( cont );
	}
}

_bsn.DOM.getElement = function ( ele ) {
	if (typeof(ele) == "undefined") {
		return false;
	} else if (typeof(ele) == "string") {
		var re = document.getElementById( ele );
		if (!re) {
			return false;
		} else if (typeof(re.appendChild) != "undefined" ) {
			return re;
		} else {
			return false;
		}
	} else if (typeof(ele.appendChild) != "undefined") {
		return ele;
	} else {
		return false;
	}
}
_bsn.DOM.appendChildren = function ( id, arr ) {
	var ele = this.getElement( id );
	
	if (!ele) {
		return false;
	}
	if (typeof(arr) != "object") {
		return false;
	}
		
	for (var i=0;i<arr.length;i++) {
		var cont = arr[i];
		if (typeof(cont) == "string") {
			ele.appendChild( document.createTextNode(cont) );
		} else if (typeof(cont) == "object") {
			ele.appendChild( cont );
		}
	}
}
_bsn.DOM.getPos = function ( ele ) {
	var ele = this.getElement(ele);

	var obj = ele;

	var curleft = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	} else if (obj.x) {
		curleft += obj.x;
	}

	var obj = ele;
	
	var curtop = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	} else if (obj.y) {
		curtop += obj.y;
	}

	return {x:curleft, y:curtop}
}

// FADER PROTOTYPE _____________________________________________
if (typeof(_bsn.Fader) == "undefined") {
	_bsn.Fader = {}
}
_bsn.Fader = function (ele, from, to, fadetime, callback) {	
	if (!ele) {
		return false;
	}
	
	this.ele = ele;
	
	this.from = from;
	this.to = to;
	
	this.callback = callback;
	
	this.nDur = fadetime;
		
	this.nInt = 50;
	this.nTime = 0;
	
	var p = this;
	this.nID = setInterval(function() { p._fade() }, this.nInt);
}
_bsn.Fader.prototype._fade = function() {
	this.nTime += this.nInt;
	
	var ieop = Math.round( this._tween(this.nTime, this.from, this.to, this.nDur) * 100 );
	var op = ieop / 100;
	
	if (this.ele.filters) {
		// internet explorer
		try {
			this.ele.filters.item("DXImageTransform.Microsoft.Alpha").opacity = ieop;
		} catch (e) { 
			// If it is not set initially, the browser will throw an error.  This will set it if it is not set yet.
			this.ele.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+ieop+')';
		}
	} else {
		// other browsers
		this.ele.style.opacity = op;
	}
	
	
	if (this.nTime == this.nDur) {
		clearInterval( this.nID );
		if (this.callback != undefined) {
			this.callback();
		}
	}
}
_bsn.Fader.prototype._tween = function(t,b,c,d) {
	return b + ( (c-b) * (t/d) );
}// Countdown Javascript
// copyright 20th April 2005, 17th November 2006 by Stephen Chapman
// permission to use this Javascript on your web page is granted
// provided that all of the code in this script (including these
// comments) is used without any alteration
// you may change the start function if required
var pageLoaded = 0; window.onload = function() {pageLoaded = 1;}
function loaded(i,f) {if (document.getElementById && document.getElementById(i) != null) f(); else if (!pageLoaded) setTimeout('loaded(\''+i+'\','+f+')',100);
}
function setCountdown(month,dow,day,hour,minute,second,tz) {/*alert('month='+month+',dow='+dow+',day='+day+',hour='+hour+',minute='+minute+',second='+second+', tz='+tz);*/var m = month; if (month=='*') m = 0;  var c = setC(m,dow,day,hour,minute,second,tz); if (month == '*' && c < 0)  c = setC('*',dow,day,hour,minute,second,tz); return c;} function setC(month,dow,day,hour,minute,second,tz) {var toDate = new Date();if (day.substr(0,1) == '+') {var day1 = parseInt(day.substr(1));toDate.setDate(toDate.getDate()+day1);} else{toDate.setDate(day);}if (month == '*')toDate.setMonth(toDate.getMonth() + 1);else if (month > 0) { if (month <= toDate.getMonth())toDate.setFullYear(toDate.getFullYear() + 1);toDate.setMonth(month-1);}
if (dow >0) toDate.setDate(toDate.getDate()+(dow-1-toDate.getDay())%7);
toDate.setHours(hour);toDate.setMinutes(minute-(tz*60));toDate.setSeconds(second);var fromDate = new Date();fromDate.setMinutes(fromDate.getMinutes() + fromDate.getTimezoneOffset());var diffDate = new Date(0);diffDate.setMilliseconds(toDate - fromDate);return Math.floor(diffDate.valueOf()/1000);}
var countdownTimer = null;
function displayCountdown(countdn,cd) {if (document.getElementById(cd) && countdn >= 0) {var secs = countdn % 60; if (secs < 10) secs = '0'+secs;var countdn1 = (countdn - secs) / 60;var mins = countdn1 % 60; if (mins < 10) mins = '0'+mins;countdn1 = (countdn1 - mins) / 60;var hours = countdn1 % 24;var days = (countdn1 - hours) / 24;document.getElementById(cd).innerHTML = hours+' hours '+mins+' mins '+secs+' secs'/* days+' days + '+hours+' : '+mins+' : '+secs */;if (countdownTimer) { clearTimeout(countdownTimer); countdownTimer = null; } countdownTimer = setTimeout('displayCountdown('+(countdn-1)+',\''+cd+'\');',999);}}/**
 * SUBMODAL v1.5
 * Used for displaying DHTML only popups instead of using buggy modal windows.
 *
 * By Seth Banks
 * http://www.subimage.com/
 *
 * Contributions by:
 * 	Eric Angel - tab index code
 * 	Scott - hiding/showing selects for IE users
 *	Todd Huss - inserting modal dynamically and anchor classes
 *
 * Up to date code can be found at http://www.subimage.com/dhtml/subModal
 * 
 *
 * This code is free for you to use anywhere, just keep this comment block.
 */
// Popup code
var gPopupMask = null;
var gPopupContainer = null;
var gPopFrame = null;
var gReturnFunc;
var gPopupIsShown = false;
var gDefaultPage = getRoot() + "/popups/loading/";
var gHideSelects = false;
var gReturnVal = null;
var gTabIndexes = new Array();
// Pre-defined list of tags we want to disable/enable tabbing into
var gTabbableTags = new Array("A","BUTTON","TEXTAREA","INPUT","IFRAME", "OBJECT");	
// If using Mozilla or Firefox, use Tab-key trap.
if (!document.all) {
	document.onkeypress = keyDownHandler;
}
/**
 * Initializes popup code on load.	
 */
function initPopUp() {
	// Add the HTML to the body
	theBody = document.getElementsByTagName('BODY')[0];
	popmask = document.createElement('div');
	popmask.id = 'popupMask';
	popcont = document.createElement('div');
	popcont.id = 'popupContainer';
	popcont.innerHTML = '' +
		'<div id="popupInner">' +
			'<div id="popupTitleBar">' +
				'<div id="popupTitle"></div>' +
				'<div id="popupControls">' +
					'<img src="'+getCDN()+'/images/close.gif" onclick="hidePopWin(false);" id="popCloseBox" />' +
				'</div>' +
			'</div>' +
			'<iframe src="'+ gDefaultPage +'" style="width:100%;height:100%;background-color:transparent;" scrolling="auto" frameborder="0" allowtransparency="true" id="popupFrame" name="popupFrame" width="100%" height="100%"></iframe>' +
		'</div>';
	theBody.appendChild(popmask);
	theBody.appendChild(popcont);
	
	gPopupMask = document.getElementById("popupMask");
	gPopupContainer = document.getElementById("popupContainer");
	gPopFrame = document.getElementById("popupFrame");	
	
	// check to see if this is IE version 6 or lower. hide select boxes if so
	// maybe they'll fix this in version 7?
	var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
	if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE") > -1) {
		gHideSelects = true;
	}
	
	// Add onclick handlers to 'a' elements of class submodal or submodal-width-height
	var elms = document.getElementsByTagName('a');
	for (i = 0; i < elms.length; i++) {
		if (elms[i].className.indexOf("submodal") == 0) { 
			// var onclick = 'function (){showPopWin(\''+elms[i].href+'\','+width+', '+height+', null);return false;};';
			// elms[i].onclick = eval(onclick);
			elms[i].onclick = function(){
				// default width and height
				var width = 400;
				var height = 200;
				// Parse out optional width and height from className
				params = this.className.split('-');
				if (params.length == 3) {
					width = parseInt(params[1]);
					height = parseInt(params[2]);
				}
				showPopWin(this.href,width,height,null); return false;
			}
		}
	}
}
addEvent(window, "load", initPopUp);
 /**
	* @argument width - int in pixels
	* @argument height - int in pixels
	* @argument url - url to display
	* @argument returnFunc - function to call when returning true from the window.
	* @argument showCloseBox - show the close box - default true
	*/
function showPopWin(url, width, height, returnFunc, showCloseBox) {
	//alert('url='+url+', width='+width+', height='+height+', returnFunc='+returnFunc);
	// show or hide the window close widget
	if (showCloseBox == null || showCloseBox == true) {
		document.getElementById("popCloseBox").style.display = "block";
	} else {
		document.getElementById("popCloseBox").style.display = "none";
	}
	gPopupIsShown = true;
	disableTabIndexes();
	gPopupMask.style.display = "block";
	gPopupContainer.style.display = "block";
	// calculate where to place the window on screen
	centerPopWin(width, height);
	
	var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);


	gPopupContainer.style.width = width + "px";
	gPopupContainer.style.height = (height+titleBarHeight) + "px";
	
	setMaskSize();

	// need to set the width of the iframe to the title bar width because of the dropshadow
	// some oddness was occuring and causing the frame to poke outside the border in IE6
	gPopFrame.style.width = parseInt(document.getElementById("popupTitleBar").offsetWidth, 10) + "px";
	gPopFrame.style.height = (height) + "px";
	
	// set the url
	gPopFrame.src = url;
	
	gReturnFunc = returnFunc;
	// for IE
	if (gHideSelects == true) {
		toggleElementsByTagName('SELECT', false);
	}
	toggleElementsByTagName('OBJECT', false);
	toggleElementsByTagName('EMBED', false);
	
	window.setTimeout("setPopTitle();", 1500);
}
//
var gi = 0;
function centerPopWin(width, height) {
	if (gPopupIsShown == true) {
		if (width == null || isNaN(width)) {
			width = gPopupContainer.offsetWidth;
		}
		if (height == null) {
			height = gPopupContainer.offsetHeight;
		}
		
		//var theBody = document.documentElement;
		var theBody = document.getElementsByTagName("BODY")[0];
		//theBody.style.overflow = "hidden";
		var scTop = parseInt(getScrollTop(),10);
		var scLeft = parseInt(theBody.scrollLeft,10);
	
		setMaskSize();
		
		//window.status = gPopupMask.style.top + " " + gPopupMask.style.left + " " + gi++;
		
		var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);
		
		var fullHeight = getViewportHeight();
		var fullWidth = getViewportWidth();
		
		gPopupContainer.style.top = (scTop + ((fullHeight - (height+titleBarHeight)) / 2)) + "px";
		gPopupContainer.style.left =  (scLeft + ((fullWidth - width) / 2)) + "px";
		//alert(fullWidth + " " + width + " " + gPopupContainer.style.left);
	}
}
addEvent(window, "resize", centerPopWin);
addEvent(window, "scroll", centerPopWin);
window.onscroll = centerPopWin;
/**
 * Sets the size of the popup mask.
 *
 */
function setMaskSize() {
	var theBody = document.getElementsByTagName("BODY")[0];
			
	var fullHeight = getViewportHeight();
	var fullWidth = getViewportWidth();
	
	// Determine what's bigger, scrollHeight or fullHeight / width
	if (fullHeight > theBody.scrollHeight) {
		popHeight = fullHeight;
	} else {
		popHeight = theBody.scrollHeight;
	}
	
	if (fullWidth > theBody.scrollWidth) {
		popWidth = fullWidth;
	} else {
		popWidth = theBody.scrollWidth;
	}
	
	gPopupMask.style.height = popHeight + "px";
	gPopupMask.style.width = popWidth + "px";
}
/**
 * @argument callReturnFunc - bool - determines if we call the return function specified
 * @argument returnVal - anything - return value 
 */
function hidePopWin(callReturnFunc, returnVal) {
	//alert('callReturnFunc='+callReturnFunc+', gReturnFunc='+gReturnFunc+', returnVal='+returnVal); 
	gPopupIsShown = false;
	var theBody = document.getElementsByTagName("BODY")[0];
	theBody.style.overflow = "";
	restoreTabIndexes();
	if (gPopupMask == null) {
		return;
	}
	gPopupMask.style.display = "none";
	gPopupContainer.style.display = "none";
	if (callReturnFunc == true && gReturnFunc != null) {
		// Set the return code to run in a timeout.
		// Was having issues using with an Ajax.Request();
		gReturnVal = returnVal != undefined ? returnVal : window.frames["popupFrame"].returnVal;
		window.setTimeout('gReturnFunc(gReturnVal);', 1);
	}
	gPopFrame.src = gDefaultPage;
	// display all select boxes
	if (gHideSelects == true) {
		toggleElementsByTagName('SELECT', true);
	}
	toggleElementsByTagName('OBJECT', true);
	toggleElementsByTagName('EMBED', true);
}
document.hidePopup = hidePopWin;
/**
 * Sets the popup title based on the title of the html document it contains.
 * Uses a timeout to keep checking until the title is valid.
 */
function setPopTitle() {
	//return;
	if (window.frames["popupFrame"].document.title == null) {
		window.setTimeout("setPopTitle();", 10);
	} else {
		document.getElementById("popupTitle").innerHTML = window.frames["popupFrame"].document.title;
	}
}
// Tab key trap. iff popup is shown and key was [TAB], suppress it.
// @argument e - event - keyboard event that caused this function to be called.
function keyDownHandler(e) {
    if (gPopupIsShown && e.keyCode == 9)  return false;
}
// For IE.  Go through predefined tags and disable tabbing into them.
function disableTabIndexes() {
	if (document.all) {
		var i = 0;
		for (var j = 0; j < gTabbableTags.length; j++) {
			var tagElements = document.getElementsByTagName(gTabbableTags[j]);
			for (var k = 0 ; k < tagElements.length; k++) {
				gTabIndexes[i] = tagElements[k].tabIndex;
				tagElements[k].tabIndex="-1";
				i++;
			}
		}
	}
}
// For IE. Restore tab-indexes.
function restoreTabIndexes() {
	if (document.all) {
		var i = 0;
		for (var j = 0; j < gTabbableTags.length; j++) {
			var tagElements = document.getElementsByTagName(gTabbableTags[j]);
			for (var k = 0 ; k < tagElements.length; k++) {
				tagElements[k].tabIndex = gTabIndexes[i];
				tagElements[k].tabEnabled = true;
				i++;
			}
		}
	}
}
/**
* Hides all drop down form select boxes on the screen so they do not appear above the mask layer.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*
* Thanks for the code Scott!
*/
function toggleElementsByTagName(tagName, showElement) {
	var elements = document.documentElement.getElementsByTagName(tagName);
	for (var i = 0; i < elements.length; i++) {
		elements[i].style.visibility = (showElement) ? "visible" : "hidden";
	}
}