// See http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
// If you are curious why the XMLHTTP versions specified are and why others are not.
var ajax_call_counter = 0;
var safariRateLimited;
var isWebKit = (navigator.userAgent.toLowerCase().indexOf('webkit') > -1);

// Copies value in stringVal to the clipboard, displaying the successMessage if hideAlert is false.
function toClipboardEx(stringVal, hideAlert, successMessage) {
	if (window.clipboardData) {		// Internet Explorer
		if (!window.clipboardData.setData("Text", stringVal) && !hideAlert)
			hideAlert = true;
	}
	else if (window.netscape) {	// Mozilla Firefox and derivitives (Netscape, Seamonkey)...
		try {
			// Request full access to the XPCOM (Cross-Platform COM) API.
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		}
		catch (e) {
			// Unable to obtain access, user rejected or setting in about:config not set right.
			alert('Please type "about:config" in your browser and press enter. Type "signed.applets.codebase_principal_support" in Filter. Double click to change the value to "true". Then come back and click on the link again.\n\nIf you have already performed this action, make sure when you are asked whether to allow or deny the browser permission, that you are allowing it.');
			return;
		}

		// Create an instance of the clipboard class.
		var clipBoard = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);

		// Create an instance of the Transferable class (used to talk to the clipboard).
		var clipTrans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);

		// Set clipboard format for text only.
		clipTrans.addDataFlavor('text/unicode');

		// Create XPCOM string, set data to copy of stringVal.
		var clipString = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
		var copyText = stringVal;
		clipString.data = copyText;

		// Set data to transfer to the clipboard (length * 2, since 1 char is 2 bytes in UTF-16).
		clipTrans.setTransferData("text/unicode", clipString, copyText.length * 2);

		// Transfer data to the global clipboard.
		clipBoard.setData(clipTrans, null, clipBoard.kGlobalClipboard);
	}

	if (!hideAlert)
		alert(successMessage);

	return true;
}

function toClipboard(stringVal, hideAlert) {
	return toClipboardEx(stringVal, hideAlert, "The link has been copied to your clipboard.");
}

function getClipboard() {
	if (window.clipboardData) {
		return window.clipboardData.getData('Text');
	} else if (window.netscape) {
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		}
		catch (e) {
			alert('Please type "about:config" in your browser and press enter. Type "signed.applets.codebase_principal_support" in Filter. Double click to change the value to "true". Then come back and click on the link again.\n\nIf you have already performed this action, make sure when you are asked whether to allow or deny the browser permission, that you are allowing it.');
			return;
		}

		// Create instances of the Clipboard and Transferable objects.
		var clipBoard = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
		var clipTrans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);

		// Get data from global clipboard, place in clipTrans object.
		clipTrans.addDataFlavor('text/unicode');
		clipBoard.getData(clipTrans, clipBoard.kGlobalClipboard);

		// Create objects to pass to getTransferData, which uses XPCOM String
		// and Integer classes instead of those normally used by JavaScript.
		var objStr = new Object(); var objNumBytes = new Object();
		try {
			clipTrans.getTransferData('text/unicode', objStr, objNumBytes);
		}
		catch (error) {
			return '';
		}

		// Query whichever interface is available, opting to use nsISupportsWString.
		if (objStr) {
			if (Components.interfaces.nsISupportsWString)
				objStr = objStr.value.QueryInterface(Components.interfaces.nsISupportsWString);
			else if (Components.interfaces.nsISupportsString)
				objStr = objStr.value.QueryInterface(Components.interfaces.nsISupportsString);
			else
				objStr = null;
		}

		// Get data out of the XPCOM string and into a normal JS string.
		if (objStr)
			return (objStr.data.substring(0, objNumBytes.value / 2));
	}
	return;
}

// Gets the computed style of an element (browser-independent).
var getCurrentStyle = (document.defaultView ?
	function(elem) {
		return document.defaultView.getComputedStyle(elem, '');
	} :
	function(elem) {
		return elem.currentStyle;
	}
);

// Gets children nodes of an HTML DOM element matching the tag name specified.
function getChildNodesByTag(domElement, tagName) {
	var cn = domElement.childNodes;
	var nodesPresent = 0, retVal = new Array();
	retVal.length = cn.length;

	tagName = tagName.toUpperCase();
	for (var cv = 0; cv < cn.length; cv++) {
		if (cn[cv].nodeType == 1 && cn[cv].nodeName == tagName)
			retVal[nodesPresent++] = cn[cv];
	}

	return retVal.slice(0, nodesPresent);
}

// Returns true on Safari browsers 1.3.4 and older (bad date object behavior in old Safari).
var isSafariVersion13OrOlder = (isWebKit ?
	function() {
		var navAppVersion = navigator.appVersion;
		var phraseToFind = 'AppleWebKit/';
		var foundStartAt = navAppVersion.indexOf(phraseToFind) + phraseToFind.length;
		var foundEndAt = navAppVersion.indexOf(' ', foundStartAt + 1);
		return (parseInt(navAppVersion.substring(foundStartAt, foundEndAt)) < 320);
	} :
	function() {
		return false;
	}
);

// Returns true on Safari browsers 2.0.4 and older (textbox/button not stylable before 3.x).
var isSafariVersion20OrOlder = (isWebKit ?
	function() {
		var navAppVersion = navigator.appVersion;
		var phraseToFind = 'AppleWebKit/';
		var foundStartAt = navAppVersion.indexOf(phraseToFind) + phraseToFind.length;
		var foundEndAt = navAppVersion.indexOf(' ', foundStartAt + 1);
		return (parseInt(navAppVersion.substring(foundStartAt, foundEndAt)) < 525);
	} :
	function() {
		return false;
	}
);

// Returns true if an event fired too soon after another event.
// Mechanism used on older Safari browsers to prevent 
// double-fire problems (especially with key presses).
function safariEventRateLimitBlock() {
	if (isWebKit && isSafariVersion13OrOlder()) {
		if (safariRateLimited != 0)
			return true;
		else {
			safariRateLimited = setTimeout('safariRateLimited = 0;', 10);
			return false;
		}
	}
}

// Get coordinates relative to document (works out container issues).
// Wrote this so it works in quirks or standards mode. -KB
function getDocumentCoordinates(element) {
	var htmlElem = document.body.parentNode;
	var bodyElem = document.body;
	var pos = { "x": 0, "y": 0 };
	pos.toString = function() { return this.x + ', ' + this.y; }
	while (element != null) {
		pos.x += element.offsetLeft;
		pos.y += element.offsetTop;
		switch (element.offsetParent) {
			case htmlElem:
			case bodyElem:
			case null:
				return pos;
		}
		element = element.offsetParent;
	}
}

// Attach an event handler to an object (browser-independent).
// First clause is W3C DOM method, second is DHTML (IE).
function addEvent(obj, evType, fn, useCapture) {
	try {
		if (obj.addEventListener) {
			obj.addEventListener(evType, fn, useCapture);
			return true;
		}
		else if (obj.attachEvent) {
			var r = obj.attachEvent("on" + evType, fn);
			return r;
		}
	}
	catch (e) { }
}

// Release an event handler from an object (browser-independent).
// First clause is W3C DOM method, second is DHTML (IE).
function removeEvent(obj, evType, fn, useCapture) {
	if (obj.removeEventListener) {
		obj.removeEventListener(evType, fn, useCapture);
		return true;
	}
	else if (obj.detachEvent) {
		obj.detachEvent("on" + evType, fn);
		return true;
	}
}

// Stops a DOM event from propagating further than the current handler.
// Note: Returning false from event handlers in IE 6 & 7 does the same thing.
function stopEventPropagation(evObj) {
	if (evObj.preventDefault)
		evObj.preventDefault();
	// Calling cancelButton after stopPropagation
	// may negate the stopPropagation so do not do it. -KB
	if (evObj.stopPropagation)
		evObj.stopPropagation();
	else if (evObj.cancelBubble)
		evObj.cancelBubble();
}

//Pads the left of a string.
function LPad(string, chr, num) {
	string += '';
	if (string.length < num) {
		var buffer = "";
		for (var i = 0; i < num - string.length; i++)
			buffer += chr;
		return buffer + string;
	}
	else
		return string;
}

//Combines date and time into a castable SQL date.
function FormatSQLDate(theDate, theTime, theAMPM) {
	var arrDate = theDate.split('/');
	var arrTime = theTime.split(':');
	var amPm = theAMPM.toLowerCase();

	if (amPm == "pm" && parseInt(arrTime[0]) < 12)
		arrTime[0] = (parseInt(arrTime[0]) + 12) + '';
	if (amPm == "am" && arrTime[0] == "12")
		arrTime[0] = "00";

	return (LPad(arrDate[0], '0', 2) + '/' + LPad(arrDate[1], '0', 2) + '/' + arrDate[2] + " " + LPad(arrTime[0], '0', 2) + ":" + LPad(arrTime[1], '0', 2) + ":00");
}

//Displays a countdown that is updated every second.
//e.g. for christmas 2007: countdown_clock(2007, 12, 25, 00, 00, 1);
function countdown_clock(year, month, day, hour, minute, format) {
	html_code = '<div id="countdown"></div>';
	document.write(html_code);

	countdown(year, month - 1, day, hour, minute, format);
}

//Helper function for countdown_clock().
function countdown(year, month, day, hour, minute, format) {
	var Today = new Date();
	var Target = new Date(year, month, day, hour, minute, 0, 0);
	var elemCountDown = document.getElementById('countdown');

	//Convert both todays date and the target date into milliseconds.
	var Todays_Date = Today.getTime();
	var Target_Date = Target.getTime();

	//Find their difference, and convert that into seconds.
	var Time_Left = Math.round((Target_Date - Todays_Date) / 1000);
	if (Time_Left < 0)
		Time_Left = 0;

	switch (format) {
		case 1:
			//More detailed.
			var days = Math.floor(Time_Left / 86400); // 60 * 60 * 24
			Time_Left %= 86400;
			var hours = Math.floor(Time_Left / 3600); // 60 * 60
			Time_Left %= 3600;
			var minutes = Math.floor(Time_Left / 60);
			Time_Left %= 60;
			var seconds = Time_Left;

			//'ps' is short for plural suffix.
			var dps = (days == 1 ? '' : 's');
			var hps = (hours == 1 ? '' : 's');
			var mps = (minutes == 1 ? '' : 's');
			var sps = (seconds == 1 ? '' : 's');

			elemCountDown.innerHTML = days + ' day' + dps + ' <br>' +
				hours + ' hour' + hps + ' <br>' +
				minutes + ' minute' + mps + ' <br>' +
				seconds + ' second' + sps;
			break;
		default:
			elemCountDown.innerHTML = Time_Left + ' seconds';
	}

	setTimeout('countdown(' + year + ',' + month + ',' + day + ',' + hour + ',' + minute + ',' + format + ');', 1000);
}

//This function assists in obscuring email addresses.
function mailTo(obj) {
	//alert('mailto:'+eval(obj.getAttribute('id')));
	obj.setAttribute('href', 'mailto:' + eval(obj.getAttribute('id')));
}

function js_mail(obj, Emails) {
	var mail_link = Emails[0];
	for (var email = 1; email < Emails.length; email++)
		if (Emails[email] != null && Emails[email] != '' && Emails[email].substr(1, 4) != 'href') mail_link = mail_link + Emails[email];

	obj.setAttribute('href', 'mailto:' + mail_link);
}

function antiContextMenuHook() {
	// Note: Opera is not hookable.
	var showAlert = function() { alert('All images are protected by Copyright. Do not use without permission.'); }
	var mdClick = function(e) {
		if (!document.all) {
			if (e.button == 2 || e.button == 3)
				showAlert();
		}
		else if (event && event.button == 2)
			showAlert();
	}
	var cmClick = function(e) {
		if (navigator.userAgent.toLowerCase().indexOf('khtml') > -1) {
			// Safari, Konquerer
			if (e.preventDefault)
				e.preventDefault();
			showAlert();
		}
		if (e.stopPropagation)
			e.stopPropagation(); // Mozilla Firefox 2.0
		return false; // IE 6.0 and 7.0
	}
	document.onmousedown = mdClick;
	document.oncontextmenu = cmClick;
}

// Form validation functions:
function RegExValidate(expression, value, param) {
	var re = new RegExp(expression, param);
	if (value.match(re)) return true;
	else return false;
}

// JavaScript version of CivicplusCMS.Validation.IsValidEmailAddress();
function emailValidate(emailAddress) {
    if (TrimString(emailAddress + "") != "")
    {
        var parts = emailAddress.splitRemoteEmpties('@');
        if (parts.length == 2)
        {
            for (var i = 0; i < parts.length; i++)
            {
                if (parts[i][0] == '.' || parts[i][(parts[i].length - 1)] == '.' || (!RegExValidate('^[A-Z0-9_%-\\.]+$', parts[i], 'i')))
                    return false;
            }
            var lastDotPos = parts[1].lastIndexOf('.');
            if (lastDotPos < 0 || parts[1].substr(lastDotPos).length < 3)
                return false;
            else
                return true;
        }
        else
            return false;
    }
    else
        return false;
}

// Returns: 0 - success, 1 - illegal value, 2 - too large, 3 - too small, 4 - blank.
function intValidateWithRange(value, min, max) {
	if (value == '' || value == null) return 4;
	if (RegExValidate('^(-|)[0-9]*$', value, 'i')) {
		try { var pint = parseInt(value); } catch (ex) { return 1; }
		if (pint < min) return 3; else if (pint > max) return 2; return 0;
	} else
		return 1;
}

// javascript equivalent of the function in globalfunctionsdetail.asp
function SQLSafe(strInput) {
	return strInput.replace(/\'/g, "&#39").replace(/\"/g, "&#34");
}

// returns true if the string is empty
function FieldIsEmpty(strInput) {
	return TrimString(strInput).length == 0;
}

// split function that remotes empty entries
String.prototype.splitRemoteEmpties = function(separator, howmany) {
	var splitArr;
	var returnArr = new Array();
	
	if (arguments.length == 2)
		splitArr = this.split(separator, howmany);
	else
		splitArr = this.split(separator);
	
	for (var i = 0; i < splitArr.length; i++) {
		if (splitArr[i] != '')
			returnArr.push(splitArr[i]);
	}
	
	return returnArr;
}

// removes leading and trailing white space from a string
function TrimString(strInput) {
	return strInput.replace(/^\s+/g, "").replace(/\s+$/g, "");
}

// returns true if the value is an integer value
function isInteger(strInput) {
	return (strInput == parseInt(strInput).toString());
}

// returns true if the value is a real number
function isRealNumber(strInput) {
	return (strInput == parseFloat(strInput));
}

function dateValidator() {
	this.firstValidDate = new Date('01/01/1753');
	this.lastValidDate = new Date('01/01/3000');
	this.strStartDateID = 'Start Date';
	this.strEndDateID = 'End Date';
	this.strStartTimeID = 'Start Time';
	this.strEndTimeID = 'End Time';
	this.ysnRequireStartDateIfEndSpecified = false;
	this.ysnStartDateRequired = false;
	this.ysnEndDateRequired = false;
	this.ysnStartTimeRequired = false;
	this.ysnEndTimeRequired = false;
	this.ysnAllowEqualDates = false;
	this.ysnCent = false; //Allow only four digit years
	var dtiEndDate;
	var dtiStartDate;

	this.setStartDate = function(date) {
		dtiStartDate = this.cleanDate(date);
	}

	this.setEndDate = function(date) {
		dtiEndDate = this.cleanDate(date);
	}

	this.cleanDate = function(date) {
		if (date) {
			if (RegExValidate('^([0-9\-\\\/]*?)([0-9]{2,4})$', date, 'i')) {
				var year = RegExp.$2;
				if (year.length == 2) {
					if (year >= 50) date = RegExp.$1 + "19" + year;
					else date = RegExp.$1 + "20" + year;
				}
				date = date.replace('\-', '/', 'g');
			}
		}
		return date;
	}

	this.dateValidate = function(dtiDate, ysnRequired, strID) {
		if (!ysnRequired && dtiDate == '') return true;
		else if (ysnRequired && dtiDate == '') {
			if (strID) this.error = strID + ' is required';
			else this.error = ' is required';
			this.errorNumber = 1;
			return false;
		}
		else if (RegExValidate('^(1[0-2]|0?[1-9])(\/|\-)(0?[1-9]|[1-2][0-9]|3[0-1])\\2([0-9]{4}|[0-9]{2})$', dtiDate, 'i')) {
			var month = RegExp.$1;
			var day = RegExp.$3;
			var year = RegExp.$4;

			if (year.length == 2 && this.ysnCent == true) {
				if (strID) this.error = strID + ' requires a four digit year';
				else this.error = 'Please use a four digit year';
				return false;
			}
			if (year.length == 4 && (year > 3000 || year < 1753)) {
				this.error = dtiDate + '\nis outside of the date range.';
				this.errorNumber = 2;
				return false;
			}
			if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) {
				this.error = 'This month doesn\'t have 31 days';
				this.errorNumber = 3;
				return false;
			}
			if (day >= 30 && month == 2) {
				this.error = 'February doesn\'t have ' + day + ' days';
				this.errorNumber = 4;
				return false;
			}
			if (month == 2 && day == 29 && !(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
				this.error = 'This is not a leap year\nFebruary doesn\'t have 29 days.';
				this.errorNumber = 5;
				return false;
			}
			return true;
		}
		else {
			if (strID) this.error = strID + ' is not a valid date format.\nPlease use mm/dd/yyyy.';
			else this.error = dtiDate + '\n is an invalid date format.\nPlease use mm/dd/yyyy.';
			this.errorNumber = 6;
			return false;
		}
		return false;
	}

	this.dateOrderValidate = function() {
		if (this.dateValidate(dtiStartDate, this.ysnStartDateRequired, this.strStartDateID) && this.dateValidate(dtiEndDate, this.ysnEndDateRequired, this.strEndDateID)) {
			if (this.ysnRequireStartDateIfEndSpecified && !dtiStartDate && dtiEndDate) {
				this.error = 'A start date must be specified if an end date was entered.'
				this.errorNumber = 9; return false;
			}
			if (!dtiStartDate || !dtiEndDate) return true;
			else {
				var StartDate = new Date(dtiStartDate);
				var EndDate = new Date(dtiEndDate);
			}
			if (StartDate.getTime() < EndDate.getTime()) return true;
			else if (StartDate.getTime() == EndDate.getTime() && this.ysnAllowEqualDates == true) {
				this.ysnDatesAreEqual = true;
				return true;
			}
			else {
				this.error = 'The end date must be after the start date.';
				this.errorNumber = 7; return false;
			}
		}
		else return false;
	}

	this.format = function(format, date) {
		if (!date) var date = new Date();
		var day = date.getDate();
		var month = date.getMonth() + 1;
		var year = date.getFullYear();
		return format.replace(/dd/g, day).replace(/mm/g, month).replace(/y{1,4}/g, year)
	}

	this.timeValidate = function(ditTime, ysnRequired, strID) {
		if (!ysnRequired && ditTime == '') return true;
		else if (ysnRequired && ditTime == '') {
			if (strID) this.error = strID + ' is required';
			else this.error = 'Time is required';
			this.errorNumber = 1;
			return false;
		}
		else if (RegExValidate('^(1[0-2]|0?[1-9]):([0-5]?[0-9])(:([0-5][0-9]))?$', ditTime, 'i')) return true;
		else {
			if (strID) this.error = strID + ' is not valid.';
			else this.error = ' is not valid.';
			this.errorNumber = 8;
			return false;
		}
		return false;
	}

	this.timeOrderValidate = function() {
		if (!this.ysnAllowTimeOnly && ((!dtiStartDate && this.dtiStartTime) || (!dtiEndDate && this.dtiEndTime))) {
			this.error = 'You only submited a time.\nPlease provide a day as well.';
			this.errorNumber = 10;
			return false;
		}
		if (this.timeValidate(this.dtiStartTime, this.ysnStartTimeRequired, this.strStartTimeID) && this.timeValidate(this.dtiEndTime, this.ysnEndTimeRequired, this.strEndTimeID)) {
			if (!this.ysnDatesAreEqual) return true;

			var dtiStartTime = this.convertTo24Hour(this.dtiStartTime, this.strStartAMPM, dtiStartDate);
			var dtiEndTime = this.convertTo24Hour(this.dtiEndTime, this.strEndAMPM, dtiEndDate);

			if (dtiStartTime.getTime() < dtiEndTime.getTime()) return true;
			else if (dtiStartTime.getTime() == dtiEndTime.getTime() && this.ysnAllowEqualTimes == true) {
				this.ysnTimesAreEqual = true;
				return true;
			}
			else {
				this.error = 'The End Time must be after the Start Time if the Start and End Dates are the same.'
				this.errorNumber = 9;
				return false;
			}
			return false;
		}
		return false;
	}

	this.convertTo24Hour = function(time, AMPM, date) {
		if (!date) date = "1/1/70"
		time = new Date(date + " " + time);
		if (AMPM == 'AM' && time.getHours() == 12) time.setHours(0);
		else if (AMPM == 'PM' && time.getHours() != 12) time.setHours(time.getHours() + 12);
		return time;
	}
}

function inputEmailValidate(obj, required) {
	if (required == null || required == false)
		return (obj.value == '' || emailValidate(obj.value) == true)
	else
		return (obj.value != '' && emailValidate(obj.value) == true)
}

function inputAlert(call, obj, required, errorMessage) {
	call = eval('input' + call + 'Validate');
	if (call(obj, required) == false) {
		if (errorMessage == null)
			errorMessage = 'Please enter a single valid email address without any extra body, subject, etc. information (ie user@domain.com).';
		obj.setAttribute('autocomplete', 'off');
		obj.focus();
		obj.setAttribute('autocomplete', 'on');
		alert(errorMessage);
		return false;
	}
	else
		return true;
}
// End Form Validation functions.

// Begin AJAX functions:
function makeErrorRequest(url, status) {
	var http_error_request = false;
	var origin = location.pathname;

	if (window.XMLHttpRequest) { // Mozilla, Safari, IE7
		http_error_request = new XMLHttpRequest();
		if (http_error_request.overrideMimeType)
			http_error_request.overrideMimeType("text/html");
	} else if (window.ActiveXObject) { // IE6
		try {
			http_error_request = new ActiveXObject("Msxml2.XMLHTTP.6.0");
		} catch (e) {
			try {
				http_error_request = new ActiveXObject("Msxml2.XMLHTTP"); // Version 3.0
			} catch (e) { }
		}
	}

	http_error_request.onreadystatechange = function() { }
	http_error_request.open("GET", "/AJAX-error.asp?url=" + escape(url) + "&status=" + status + "&origin=" + escape(origin), true);
	http_error_request.send(null);
	//if(status == 403) 
	//window.location = '/admin/AccessDenied.asp?fromURL=' + window.location.pathname.substr(7);
}

// Note: It's YOUR responsibility as a developer to make sure data 
// placed in formData is formatted as it should be. Form data should be 
// in Query String format with the value portions escape()'d. -KB
function makeHttpRequestEx(URL, formData, callbackFunc, ysnReturnXML) {
	var xmlHttpRequest, sendMethod;

	if (window.XMLHttpRequest) { // Mozilla, Safari, IE7
		xmlHttpRequest = new XMLHttpRequest();
		if (xmlHttpRequest.overrideMimeType && !ysnReturnXML)
			xmlHttpRequest.overrideMimeType("text/html");
	} else if (window.ActiveXObject) { // IE6
		try {
			xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP.6.0");
		} catch (e) {
			try {
				xmlHttpRequest = new ActiveXObject("MSxml2.XMLHTTP"); // Version 3
			} catch (e) { }
		}
	}

	window.callbackFunc = callbackFunc;
	xmlHttpRequest.onreadystatechange = function() {
		if (xmlHttpRequest.readyState == 4)
			window.callbackFunc(xmlHttpRequest);
	}

	if (formData != null) {
		xmlHttpRequest.AddHeader("content-type", "application/x-www-form-urlencoded");
		sendMethod = "POST";
	}
	else
		sendMethod = "GET";

	xmlHttpRequest.open(sendMethod, URL, true);
	xmlHttpRequest.send(formData);

	return xmlHttpRequest;
}

function makeHttpRequest(url, callback_function, return_xml) {
	var http_request = false;

	if (window.XMLHttpRequest) { // Mozilla, Safari, IE7
		http_request = new XMLHttpRequest();
		if (http_request.overrideMimeType && !return_xml)
			http_request.overrideMimeType("text/html");
	} else if (window.ActiveXObject) { // IE6
		try {
			http_request = new ActiveXObject("Msxml2.XMLHTTP.6.0");
		} catch (e) {
			try {
				http_request = new ActiveXObject("MSxml2.XMLHTTP"); // Version 3
			} catch (e) { }
		}
	}

	if (!http_request) {
		alert("Unfortunately, your browser doesn't support this feature.");
		return false;
	}

	http_request.onreadystatechange = function() {
		if (http_request.readyState == 4) {
			--ajax_call_counter;

			try {
				if (http_request.status == 200) {
					if (return_xml)
						eval(callback_function + ', http_request.responseXML)');
					else {
						if (http_request.responseText.search(/<form action='error.asp' method=post>/i) < 0)
							eval(callback_function + ', http_request.responseText)');
						else
							makeErrorRequest(url, http_request.status);
					}
				}
				else if (http_request.status)
					makeErrorRequest(url, http_request.status);
			} catch (e) {
				// If this happens, there is no way to notify anyone
				// of the previous error. It might be their connection died,
				// or failed in some other way.

				//alert('An error occured while reporting the previous error.');
				//var USER_EXPLAIN_ERR_EN = '\n\nTechnical Details:\n' + e.name + ' - ';
				// IE 6 & 7: No Line Number, No Filename
				//if (document.all && !window.opera) { 
				//	alert(USER_EXPLAIN_ERR_EN + e.description + ' (line unavailable, code: ' + e.number + ')' + '\n\nJavaScript Callback:\n' + callback_function + ', <responseData>);');
				//} 
				// Opera and Firefox 1.5+: Line Number + Filename
				//else {
				//	alert(USER_EXPLAIN_ERR_EN + e.message + '\n' + e.fileName + ', line ' + e.lineNumber + '\n\nJavaScript Callback:\n' + callback_function + ', <responseData>);');
				//}
			}

			http_request = null;
		}
	}

	http_request.open("GET", url, true);
	http_request.send(null);
}
// Invoked on window.onunload for pages using synchronous AHAH.
// Catches switches to different pages and window closes.
// -=-=-=-=-
// Note: It is synchronous instead of asynchronous to ensure 
// the operation completes before a close. This is SHAH.
//
function destroyAHAH(e) {
	var http_request;

	if (window.XMLHttpRequest) { // Mozilla, Safari, IE7
		http_request = new XMLHttpRequest();
		if (http_request.overrideMimeType) {
			http_request.overrideMimeType("text/html");
		}
	} else if (window.ActiveXObject) { // IE6
		try {
			http_request = new ActiveXObject("MSXML2.XMLHTTP.6.0");
		} catch (e) {
			try {
				http_request = new ActiveXObject("MSXML2.XMLHTTP"); // Version 3
			} catch (e) { }
		}
	}

	if (!http_request) return;
	http_request.open("GET", 'http://' + window.location.host + '/AJAX-nmenuLoader.aspx?clearCache=1', false);
	http_request.send(null);
	//alert(http_request.status + ': if 200, the session cache object was term\'d where needed be.');
}
// End AJAX functions.

//  
//  slideShow class
//  vars:
//  slideShowId						constructor param for the id of the image that will have the Slide Show 
//  slideShowLink					constructor param for the id of the link that will be around the image that has Slide Show, use '' for no link
//  slideShowSpeed					optional constructor param for the speed of the slide show, default = 5000
//  filterName						optional constructor param for the IE filter, default = blendTrans
//  filterAttr1						optional constructor param for the IE filter, default = duration=3
//  filterAttr2						optional constructor param for the IE filter
//  filterAttr3						optional constructor param for the IE filter
//  j								counter for the object
//  picArr							array of pictures
//  altArr							array of alt text
//  linkArr							array of links
//  methods:
//  addImage(n, img, alt, link)		add an image with alt text and a link, n specifies which postion in the arrays
//  runSlideShow()					continually calls nextSlide to run the Slide Show
//  nextSlide()						applies the transition and advances the Slide Show image 1 spot in the arrays
//  
function slideShow(slideShowId, slideShowLink, slideShowSpeed, filterName, filterAttr1, filterAttr2, filterAttr3) {
	this.slideShowId = document.getElementById(slideShowId);
	
	this.picArr = new Array();
	this.altArr = new Array();
	this.linkArr = new Array();
	
	// If junk data causes one slideshow to fail the others should not.
	if (this.slideShowId == null) {
		this.addImage = function(n, img, alt, link) { }
		this.runSlideShow = function() { }
		this.nextSlide = function() { }
		return;
	}
	
	var tmpElem = document.createElement('a');
	if (slideShowLink && slideShowLink != '')
		tmpElem.href = slideShowLink;
	else
		tmpElem.removeAttribute('href');
	
	tmpElem.style.border = 'none';
	tmpElem.style.background = 'transparent';
	tmpElem.id = slideShowId + '_link';
	this.slideShowLink = tmpElem;
	this.slideShowId.parentNode.insertBefore(tmpElem, this.slideShowId);
	this.slideShowId.parentNode.removeChild(this.slideShowId);
	this.slideShowLink.appendChild(this.slideShowId);

	this.j = 1;
	if (slideShowSpeed == null || slideShowSpeed == '')
		this.slideShowSpeed = 4000;
	else
		this.slideShowSpeed = slideShowSpeed * 1000;
	if (filterAttr1 == null || filterAttr1 == '')
		filterAttr1 = 2;
	if (filterName == null || filterName == '' || filterName.toLowerCase() == 'blendtrans')
		this.filterName = 'BlendTrans(duration=' + filterAttr1;
	else if (filterName.toLowerCase() != 'none')
		this.filterName = 'progid:DXImageTransform.Microsoft.' + filterName + ', duration=' + filterAttr1;
	if (filterAttr2 != null && filterAttr2 != '')
		this.filterName = this.filterName + ',' + filterAttr2;
	if (filterAttr3 != null && filterAttr3 != '')
		this.filterName = this.filterName + ',' + filterAttr3;
	this.filterName = this.filterName + ')';
	
	this.addImage = function(n, img, alt, link) {
		this.picArr[n] = new Image();
		this.picArr[n].src = img;
		this.altArr[n] = alt;
		this.linkArr[n] = link;
	}

	this.runSlideShow = function() {
		if (this.picArr.length > 1) {
			var self = this; 					//  reference to get around context loss of this during setTimeout()
			this.timeoutId = setTimeout(function() { self.nextSlide(); self.runSlideShow(); }, this.slideShowSpeed);
		}
	}

	this.nextSlide = function() {
		if (document.all && this.slideShowId.filters && filterName.toLowerCase() != 'none') {
			this.slideShowId.style.filter = this.filterName;
			this.slideShowId.filters.item(0).apply();
		}
		this.slideShowId.setAttribute('src', this.picArr[this.j].src);
		this.slideShowId.setAttribute('alt', this.altArr[this.j]);

		var slideLink = this.linkArr[this.j]
		if (slideLink && slideLink != '')
			tmpElem.href = slideLink;
		else
			tmpElem.removeAttribute('href');

		if (document.all && this.slideShowId.filters && filterName.toLowerCase() != 'none')
			this.slideShowId.filters.item(0).play();

		this.j++;
		if (this.j >= this.picArr.length)
			this.j = 0;
	}
}

//el is the pointer to the input type="file"
//example usage: <input type="file" size="38" name="txtFile" onChange="validateFileUpload(this);">
function validateFileUpload(el) {
	var val = el.value;
	var cbox = document.getElementById(el.name + "_pdf");
	if (cbox) {
		cbox.disabled = true;
		cbox.checked = false;
	}
	if (val.length > 0) {
		if (!isAllowedFileExtension(val)) {
			alert("The file you are trying to upload is not an allowed file type.");
			el.focus();
			return false;
		}
		if (cbox) {
			cbox.disabled = !isAllowedFileExtensionPDF(val);
			if (cbox.disabled) cbox.checked = false;
		}
	}
	return true;
}
function isAllowedFileExtension(filename) {
	//cut out the path portion
	while (filename.indexOf("/", 0) > 0)
		filename = filename.substr(filename.indexOf("/", 0) + 1, filename.length - filename.indexOf("/", 0))
	while (filename.indexOf("\\", 0) > 0)
		filename = filename.substr(filename.indexOf("\\", 0) + 1, filename.length - filename.indexOf("\\", 0))

	var lastPeriod, i, fileExtension;
	lastPeriod = filename.indexOf(".", 0);
	i = lastPeriod;
	while (lastPeriod > 0) {
		i = lastPeriod;
		lastPeriod = filename.indexOf(".", i + 1);
	}

	if (i > 0)
		fileExtension = filename.substr(i + 1, filename.length - i).toUpperCase();
	else
		fileExtension = "";

	switch (fileExtension) {
		case "ASA":
		case "ASAX":
		case "ASBX":
		case "ASCX":
		case "ASP":
		case "ASPX":
		case "BAT":
		case "CAB":
		case "CF":
		case "CFM":
		case "CGI":
		case "COM":
		case "CONFIG":
		case "DLL":
		case "EXE":
		case "HTA":
		case "LHA":
		case "LHZ":
		case "MIM":
		case "PIF":
		case "PL":
		case "SYS":
		case "UUE":
		case "VBS":
		case "VXD":
		case "WEBINFO":
		case "WIZ":
		case "WSH":
			{
				return false;
				break;
			}
		default:
			{
				return true;
				break;
			}
	}
}
function isAllowedFileExtensionPDF(filename) {
	//cut out the path portion
	while (filename.indexOf("/", 0) > 0)
		filename = filename.substr(filename.indexOf("/", 0) + 1, filename.length - filename.indexOf("/", 0))
	while (filename.indexOf("\\", 0) > 0)
		filename = filename.substr(filename.indexOf("\\", 0) + 1, filename.length - filename.indexOf("\\", 0))

	var lastPeriod, i, fileExtension;
	lastPeriod = filename.indexOf(".", 0);
	i = lastPeriod;
	while (lastPeriod > 0) {
		i = lastPeriod;
		lastPeriod = filename.indexOf(".", i + 1);
	}

	if (i > 0)
		fileExtension = filename.substr(i + 1, filename.length - i).toUpperCase();
	else
		fileExtension = "";

	switch (fileExtension) {
		case "GIF":
		case "JPG":
		case "JPEG":
		case "PNG":
		case "HTM":
		case "HTML":
		case "DOC":
		case "DOCX":
		case "XLS":
		case "XLSX":
		case "TXT":
			{
				return true;
				break;
			}
		default:
			{
				return false;
				break;
			}
	}
}
// returns true if it is a valid US or Canadian zip code.
// supports ZIP, ZIP+4 and Canadian zip code format
function isZipCode(strInput, intCountryCode) {
	var re
	if (intCountryCode == 840)
		re = /^\d{5}([\-]\d{4})?$/;
	else if (intCountryCode == 124)
		re = /^[A-Z]\d[A-Z][- |]\d[A-Z]\d$/i;
	return (re.test(strInput));
}
// options for cardType
//  V = Visa
//  M = MasterCard
//  A = American Express
//  D = Discover
//  J = JCB
//  C = Diner's Club
function isValidCreditCardNumber(cardNumber, cardType) {
	var isValid = false;
	var ccCheckRegExp = /[^\d ]/;
	isValid = !ccCheckRegExp.test(cardNumber);

	if (isValid) {

		var cardNumbersOnly = cardNumber.replace(/ /g, "");
		var cardNumberLength = cardNumbersOnly.length;
		var lengthIsValid = false;
		var patternIsValid = false;
		var patternRegExp;

		switch (cardType) {
			case "V":
				{ // visa
					lengthIsValid = (cardNumberLength == 13 || cardNumberLength == 16);
					patternRegExp = /^4/;
					break;
				}
			case "M":
				{ // mastercard
					lengthIsValid = (cardNumberLength == 16);
					patternRegExp = /^5[1-5]/;
					break;
				}
			case "A":
				{ // amercian express
					lengthIsValid = (cardNumberLength == 15);
					patternRegExp = /^3[4,7]/;
					break;
				}
			case "D":
				{ // discover
					lengthIsValid = (cardNumberLength == 16);
					patternRegExp = /^6011/;
					break;
				}
			case "J":
				{ // jcb
					lengthIsValid = (cardNumberLength == 15) || (cardNumberLength == 16);
					patternRegExp = /^[3,1800,2131]/;
					break;
				}
			case "C":
				{ // diner's club
					lengthIsValid = (cardNumberLength == 14);
					patternRegExp = /^3[0,6,8]/;
					break;
				}
			default:
				patternRegExp = /^$/;
		}
		patternIsValid = patternRegExp.test(cardNumbersOnly);
		isValid = patternIsValid && lengthIsValid;
	}

	if (isValid) {
		var numberProduct;
		var numberProductDigitIndex;
		var checkSumTotal = 0;

		for (digitCounter = cardNumberLength - 1; digitCounter >= 0; digitCounter--) {
			checkSumTotal += parseInt(cardNumbersOnly.charAt(digitCounter));
			digitCounter--;
			numberProduct = String((cardNumbersOnly.charAt(digitCounter) * 2));
			for (var productDigitCounter = 0; productDigitCounter < numberProduct.length; productDigitCounter++)
				checkSumTotal += parseInt(numberProduct.charAt(productDigitCounter));

		}

		isValid = (checkSumTotal % 10 == 0);
	}

	return isValid;
}
function isDate(varDateToCheck) {
	var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{4})$/;
	var matchArray = varDateToCheck.match(datePat);
	if (matchArray == null)
		return false;

	// Parse date into variables
	month = matchArray[1];
	day = matchArray[3];
	year = matchArray[4];

	if (month < 1 || month > 12 || day < 1 || day > 31)
		return false;
	if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11))
		return false;
	if (month == 2) { // Check for february 29th
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day > 29 || (day == 29 && !isleap))
			return false;
	}
	return true;
}

function debugDisplayMembers(obj) {
	var getters = new Array();
	var setters = new Array();
	var others = new Array();
	var sKey;

	for (var key in obj) {
		sKey = key + "";
		if (!((sKey.length > 0) && (sKey[0] == '_'))) {
			switch (sKey.substr(0, 4)) {
				case 'get_':
					getters.push(key);
					break;
				case 'set_':
					setters.push(key);
					break;
				default:
					others.push(key);
			}
		}
	}

	getters.sort();
	setters.sort();
	others.sort();

	alert(others.join(", ") + "\r\n\r\n" +
		getters.join(", ") + "\r\n\r\n" +
		setters.join(", "));
}