/* PTUtil.js */

function PTCommonUtil()
{
	return this;
}

var PTWSCLIENT_CCMODE_QUEUE 		= 'queue';		
var PTWSCLIENT_CCMODE_INTERRUPT 	= 'interrupt';	
var PTWSCLIENT_CCMODE_CANCEL 		= 'cancel';		
PTCommonUtil.VERSION = '121140';
PTCommonUtil.getIEVersion = function()
{
	var ua = new String(navigator.userAgent);
	if (ua.indexOf('MSIE ') == -1) { return 0; }
	var version = parseFloat(ua.substr(ua.indexOf('MSIE ') + 5));
	return version;
}

PTCommonUtil.getElementById = function(id)
{
	if (!document.all) { return document.getElementById(id); }
	var elem = PTCommonUtil.ElementCache[id];
	if (!elem || !elem.innerHTML)
	{
		PTCommonUtil.ElementCache[id] = document.getElementById(id);
	}
	return PTCommonUtil.ElementCache[id];
}

if (!window.PTCommonUtil.ElementCache) { PTCommonUtil.ElementCache = new Object(); }
PTCommonUtil.getServerFromURL = function(sURL)
{
	sURL = new String(sURL);
	var tmp = sURL;
	var protocol = sURL.indexOf('//');
	if (protocol == -1) { return ''; }
	tmp = sURL.substr(protocol + 2);
	var machineName = tmp.indexOf('/');
	if (machineName == -1) { return ''; }
	var server = protocol + machineName + 2;
	return sURL.substring(0,server);
}

PTCommonUtil.isDefined = function(obj)
{
	var type = typeof(obj);
	return (!(type == 'unknown') && !(type == 'undefined'));
}

PTCommonUtil.sortHashByKeys = function(hash,preserveFirstKey,isCaseInsensitive,doReverseSort)
{
	//: At present, sort options for isCaseInsensitive and doReverseSort are mutually exclusive.
	var keys 		= new Array();
	var sortedHash 	= new Array();
	var firstKey;
	var isNumericList = false;
	for (var key in hash) { firstKey = key; break; }
	var fkStr = new String(firstKey);
	if (!isNaN(parseInt(fkStr.charAt(0)))) { isNumericList = true; }
	for (var key in hash) { keys[keys.length] = key; }
	var sortedKeys;
	if (isNumericList)
	{
		sortedKeys = keys.sort(PTCommonUtil.sortNumeric);
		preserveFirstKey = false;
	}
	else if (isCaseInsensitive)
	{
		sortedKeys = keys.sort(PTCommonUtil.sortCaseInsensitive);
	}
	else if (doReverseSort)
	{
		sortedKeys = keys.sort(PTCommonUtil.sortReverse);
	}
	else
	{
		sortedKeys = keys.sort(PTCommonUtil.sortForward);
	}
	if (preserveFirstKey) { sortedHash[firstKey] = hash[firstKey]; }
	for (var i = 0; i < sortedKeys.length; i++)
	{
		if (preserveFirstKey && (sortedKeys[i] == firstKey)) { continue; }
		sortedHash[sortedKeys[i]] = hash[sortedKeys[i]];
	}
	return sortedHash;
}

PTCommonUtil.sortNumeric = function(a,b)
{
	var numa = parseInt(a);
	var numb = parseInt(b);
	if (!isNaN(numa) && !isNaN(numb))	{ return numa - numb; }
	else								{ return -1; }
}

PTCommonUtil.sortCaseInsensitive = function(aa,bb)
{
	var a = (new String(aa)).toLowerCase();
	var b = (new String(bb)).toLowerCase();
	if (a.valueOf() == b.valueOf()) { return 0; }
	var minLength = (a.length > b.length) ? b.length : a.length;
	var curPos = 0;
	while ((curPos < minLength) && (a.charCodeAt(curPos) == b.charCodeAt(curPos))) { curPos++; }
	var retValue = a.charCodeAt(curPos) - b.charCodeAt(curPos);
	if (isNaN(retValue))	{ return 0; }
	else					{ return retValue; }
}

PTCommonUtil.sortReverse = function(aa,bb)
{
	var a = new String(aa);
	var b = new String(bb);
	if (a.valueOf() == b.valueOf()) { return 0; }
	var minLength = (a.length > b.length) ? b.length : a.length;
	var curPos = 0;
	while ((curPos < minLength) && (a.charCodeAt(curPos) == b.charCodeAt(curPos))) { curPos++; }
	var retValue = b.charCodeAt(curPos) - a.charCodeAt(curPos);
	if (isNaN(retValue))	{ return 0; }
	else					{ return retValue; }
}

PTCommonUtil.sortForward = function(aa,bb)
{
	var a = new String(aa);
	var b = new String(bb);
	if (a.valueOf() == b.valueOf()) { return 0; }
	var minLength = (a.length > b.length) ? b.length : a.length;
	var curPos = 0;
	while ((curPos < minLength) && (a.charCodeAt(curPos) == b.charCodeAt(curPos))) { curPos++; }
	var retValue = a.charCodeAt(curPos) - b.charCodeAt(curPos);
	if (isNaN(retValue))	{ return 0; }
	else					{ return retValue; }
}

PTCommonUtil.getValueForStyleAttribute = function(s,attr)
{
	var s = new String(s);
	var attr = new String(attr);
	var attrPos = s.indexOf(attr);
	if (attrPos < 0) { return; }
	var s = s.substr(attrPos + attr.length + 1);
	while (s.charAt(0) == ' ') { s = s.substr(1); }
	var semiPos = s.indexOf(';');
	if (semiPos < 0) { semiPos = (s.length - 1); }
	s = s.substr(0,(semiPos));
	return s;
}

PTCommonUtil.getRelativePosition = function (childDiv,parentDiv,ignoreBorders)
{
	var pos = new Object();
	pos.x = 0;
	pos.y = 0;
	if (!childDiv) { return pos; }
	if (!parentDiv) { parentDiv = document.body; }
	while (1)
	{
		if (childDiv == parentDiv) { break; }
		pos.x -= parseInt(childDiv.scrollLeft);
		pos.y -= parseInt(childDiv.scrollTop);
		var bbw = parseInt(childDiv.style.borderBottomWidth);
		var ot = childDiv.offsetTop;
		pos.y += ot + ((bbw && !ignoreBorders) ? bbw : 0);
		var blw = parseInt(childDiv.style.borderLeftWidth);
		var ol = childDiv.offsetLeft;
		pos.x += ol + ((blw && !ignoreBorders) ? blw : 0);
		if (childDiv.offsetParent)	{ childDiv = childDiv.offsetParent; }
		else						{ break; }
	}
	return pos;
}

PTCommonUtil.scrollDivIntoView = function (object,container)
{
	if (!object) { return; }
	if (!container) { container = document.body; }
	var pos = PTCommonUtil.getRelativePosition(object,container,true);
	container.scrollTop = pos.y;
}

PTCommonUtil.getStyleClassFromDocument = function(doc,className)
{
	var re = new RegExp('\\.' + className + '$', 'gi');
	if (doc.all) {
		for (var s = 0; s < doc.styleSheets.length; s++) {
			for (var r = 0; r < doc.styleSheets[s].rules.length; r++) {
				if (doc.styleSheets[s].rules[r].selectorText.search(re) != -1) {
					return doc.styleSheets[s].rules[r].style;
				}
			}
		}
	} else if (doc.getElementById) {
		for (var s = 0; s < doc.styleSheets.length; s++) {
			for (var r = 0; r < doc.styleSheets[s].cssRules.length; r++) {
				if (doc.styleSheets[s].cssRules[r].selectorText.search(re) != -1) {
					doc.styleSheets[s].cssRules[r].sheetIndex = s;
					doc.styleSheets[s].cssRules[r].ruleIndex = s;
					return doc.styleSheets[s].cssRules[r].style;
				}
			}
		}
	} else if (doc.layers) {
		return doc.classes[className].all;
	} else {
		return false;
	}
}

PTCommonUtil.getStyleClass = function(className)
{
	return PTCommonUtil.getStyleClassFromDocument(document,className);
}

PTCommonUtil.getStyleClassProperty = function(className,attrName)
{
	var styleClass = PTCommonUtil.getStyleClass(className);
	return (styleClass) ? styleClass[attrName] : '';
}

PTCommonUtil.getRemoteStyleClassProperty = function(doc,className,attrName)
{
	var styleClass = PTCommonUtil.getStyleClassFromDocument(doc,className);
	return (styleClass) ? styleClass[attrName] : '';
}

PTCommonUtil.parseGet = function(url)
{
	var FORM_DATA = new Object();
	var separator = ',';
	var query;
	if (url) { query = url; }
	else {
		query = '' + top.document.location.href;
	}
	query = query.substring((query.indexOf('?')) + 1);
	if (query.length < 1) { return false; }  
	var keypairs = new Object();
	var numKP = 1;
	while (query.indexOf('&') > -1) {
		keypairs[numKP] = query.substring(0,query.indexOf('&'));
		query = query.substring((query.indexOf('&')) + 1);
		numKP++;
	}
	keypairs[numKP] = query;
	for (var i in keypairs) {
		var keyName = keypairs[i].substring(0,keypairs[i].indexOf('='));
		var keyValue = keypairs[i].substring((keypairs[i].indexOf('=')) + 1);
		while (keyValue.indexOf('+') > -1) {
			keyValue = keyValue.substring(0,keyValue.indexOf('+')) + ' ' + keyValue.substring(keyValue.indexOf('+') + 1);
		}
		keyValue = unescape(keyValue);
		if (FORM_DATA[keyName]) {
			FORM_DATA[keyName] = FORM_DATA[keyName] + separator + keyValue;
		} else {
			FORM_DATA[keyName] = keyValue;
		}
	}
	return FORM_DATA;
}

PTCommonUtil.wait = function(ms)
{
	var Start = new Date().valueOf();
	while ((new Date().valueOf() - Start) < ms) {}

}

PTCommonUtil.alertVersion = function()
{
	var str = '';
	var controls = new Array('PTCalendarControl','PTTableControl','PTTreeControl','PTTabularLayoutManager','PTCalendarManager');
	var foundControl = false;
	for (var i = 0; i < controls.length; i++)
	{
		if (typeof(eval('window.' + controls[i])) != 'undefined') { foundControl = controls[i]; break; }
	}
	if (foundControl)
	{
		var jscontrol = eval(foundControl);
		if (jscontrol.VERSION)
		{
			var version = jscontrol.VERSION;
			str += 'PTControls  (v. ' + version + ')\n';
			if (window.PTControls)
			{
				for (var obj in window.PTControls)
				{
					if (obj == 'properties') { continue; }
					var o = window.PTControls[obj];
					if (o && o.objName && o.className)
					{
						var type = ' (' + o.className + ')';
						str += '    ' + o.objName + type + '\n';
					}
				}
			}
		}
	}
	if (typeof PTDatepicker != 'undefined')
	{
		if (PTDatepicker.VERSION) { str += 'PTDatepicker  (v. ' + PTDatepicker.VERSION + ')\n'; }
	}
	if (typeof PTXMLWrapper != 'undefined')
	{
		if (PTXMLWrapper.VERSION) { str += 'PTXML (v. ' + PTXMLWrapper.VERSION + ')\n'; }
	}
	str += 'PTUtil  (v. ' + PTCommonUtil.VERSION + ')\n';
	str += '\n\u00A92003 Plumtree Software Inc., All Rights Reserved    \n';
	if (PTCommonUtil.isDefined(window.PT_DEBUG))
	{
		str += '\nDo you want to inspect an object?\n';
		var inspect = confirm(str);
		if (inspect)
		{
			var obj = prompt('Enter the name of the object you wish to inspect: \n','');
			if (obj)
			{
				var o = eval(obj);
				if (o)
				{
				}
				else
				{
				}
			}
		}
	}
	else { alert(str); }
}

PTCommonUtil.versions = function()
{
	if (document.all)
	{
		if (window.event.altKey && window.event.ctrlKey && window.event.shiftKey) {
			PTCommonUtil.alertVersion();
			return false;
		}
	}
}

PTCommonUtil.setUpVersions = function()
{
	if ((typeof document != 'undefined') && (PTCommonUtil.getIEVersion() >= 5.5))
	{
		if (document.all)
		{
			if (document.body) { document.body.onmouseleave = PTCommonUtil.versions;
			} else { window.setTimeout('PTCommonUtil.setUpVersions()',500); }
		}
	}
}

PTCommonUtil.setUpVersions();
function PTDate(datestring,date,language,dateFormat)
{
	this.datestring 	= (datestring) ? datestring : '';
	this.date			= (date) ? date : new Date();
	this.language		= (language) ? language : false;
	this.dateFormat		= (dateFormat) ? dateFormat : PTDate.defaultDateFormat;
	return this;
}

PTDate.VERSION = '121140';
PTDate.defaultLanguage		= 'en';
PTDate.defaultDateFormat	= new String('EEE MMM d HH:mm:ss yyyy');
PTDate.DEFAULT_LOCALE				= 'en';
PTDate.TIME_POLICY_ALLOW_TIMES		= 0;
PTDate.TIME_POLICY_REQUIRE_TIMES	= 1;
PTDate.TIME_POLICY_FORBID_TIMES		= 2;
PTDate.FORMAT_DEFAULT				= 0;
PTDate.FORMAT_SHORT					= 1;
PTDate.FORMAT_MEDIUM				= 2;
PTDate.FORMAT_LONG					= 3;
PTDate.FORMAT_FULL					= 4;
PTDate.PIVOT_DATE					= 50;  	
PTDate.formatDate = function (date,dateFormat,language)
{
	var d = new PTDate('',date,language,dateFormat);
	return d.format(dateFormat,d.language);
}

PTDate.validateDate = function (dateString, locale, alertOnFailure, timePolicy, formatList)
{
	return PTDateValidator.validateDate(dateString,locale,alertOnFailure,timePolicy,formatList);
}

PTDate.getNumberOfDaysInMonth = function(date)
{
	var m = date.getMonth();
	if ((m == 3) || (m == 5) || (m == 8) || (m == 10)) { return 30; }
	else if (m == 1)
	{
		var y = date.getFullYear();
		if ((!(y%4) && (y%100)) || !(y%400))
		{
			return 29;
		}
		else
		{
			return 28;
		}
	}
	else { return 31; }
}

PTDate.get2DigitYear = function (date)
{
	var y = date.getFullYear() % 100;
	if (y < 10) { y = '0' + y; }
	return '' + y;
}

PTDate.get2DigitMonth = function (date)
{
	var m = date.getMonth() + 1;
	if (m < 10) { m = '0' + m; }
	return '' + m
}

PTDate.get1DigitMonth = function (date)
{
	var m = date.getMonth() + 1;
	return '' + m
}

PTDate.get2DigitDayOfMonth = function (date)
{
	var d = date.getDate();
	if (d < 10) { d = '0' + d; }
	return '' + d;
}

PTDate.get1DigitDayOfMonth = function (date)
{
	var d = date.getDate();
	return '' + d;
}

PTDate.get2Digit1To12Hour = function (date)
{
	var h = date.getHours();
	h = h % 12;
	if (h == 0) { h = '12'; }
	else if (h < 10) { h = '0' + h; }
	return '' + h;
}

PTDate.get1Digit1To12Hour = function (date)
{
	var h = date.getHours();
	h = h % 12;
	if (h == 0) { h = '12'; }
	return '' + h;
}

PTDate.get2Digit0To23Hour = function (date)
{
	var h = date.getHours();
	if (h < 10) { h = '0' + h; }
	return '' + h;
}

PTDate.get2Digit0To11Hour = function (date)
{
	var h = date.getHours();
	h = h % 12;
	if (h < 10) { h = '0' + h; }
	return '' + h;
}

PTDate.get1Digit0To11Hour = function (date)
{
	var h = date.getHours();
	h = h % 12;
	return '' + h;
}

PTDate.get2Digit1To24Hour = function (date)
{
	var h = date.getHours() + 1;
	if (h < 10) { h = '0' + h; }
	return '' + h;
}

PTDate.get1Digit1To24Hour = function (date)
{
	var h = date.getHours() + 1;
	return '' + h;
}

PTDate.get2DigitMinutes = function (date)
{
	var m = date.getMinutes();
	if (m < 10) { m = '0' + m; }
	return '' + m;
}

PTDate.get1DigitMinutes = function (date)
{
	var m = date.getMinutes();
	return '' + m;
}

PTDate.get2DigitSeconds = function (date)
{
	var s = date.getSeconds();
	if (s < 10) { s = '0' + s; }
	return '' + s;
}

PTDate.get1DigitSeconds = function (date)
{
	var s = date.getSeconds();
	return '' + s;
}

PTDate.get3DigitMilliseconds = function (date)
{
	var m = date.getMilliseconds();
	if (m < 10) { m = '00' + m; }
	else if (m < 100) { m = '0' + m; }
	return '' + m;
}

PTDate.getAMPM = function (date,language)
{
	if (!language) { language = PTDate.defaultLanguage; }
	var h = date.getHours();
	var STR = PTDateStrings;
	if (language == 'en') { STR = PTDate.EnglishStrings; }
	var ampm = STR.ampm[0];
	if (h >= 12) { ampm = STR.ampm[1]; }
	return ampm;
}

PTDate.convert2DigitTo4DigitYear = function (year)
{
	if (year <= PTDate.PIVOT_DATE) { year += 100; }
	year += 1900;
	return year;
}

PTDate.getFormatListForLocale = function (locale,requireExactMatch)
{
	if (PTDate.formats[locale]) { return PTDate.formats[locale]; }
	if (requireExactMatch) { return false; }
	var language = locale.substring(0,2);
	if (PTDate.formats[language]) { return PTDate.formats[language]; }
	for (var loc in PTDate.formats)
	{
		if (loc.indexOf(language) > -1) { return PTDate.formats[loc]; }
	}
	return PTDate.formats[PTDate.DEFAULT_LOCALE];
}

PTDate.stripTimesFromFormat = function (format)
{
	format = format.replace(/a.*$/,'');
	format = format.replace(/h.*$/i,'');
	return format;
}

PTDate.prototype.format = function(dateFormat,language)
{
	dateFormat = (dateFormat) ? new String(dateFormat) : this.dateFormat;
	language = (language) ? language : false;
	var date = this.date;
	var STR = PTDateStrings;
	if (language == 'en') { STR = PTDate.EnglishStrings; }
	var patternStrings = {
		'yyyy'		: date.getFullYear(),
		'yy'		: PTDate.get2DigitYear(date),
		'MMMMM'		: STR.monthsLong[date.getMonth()],	
		'MMMM'	    : STR.monthsLong[date.getMonth()],  // whether long form for month is 4 or 5 M's.  Support both here.
		'MMM'		: STR.monthsShort[date.getMonth()],
		'MM'		: PTDate.get2DigitMonth(date),
		'M'			: PTDate.get1DigitMonth(date),
		'EEEE'		: STR.daysLong[date.getDay()],
		'EEE'		: STR.daysShort[date.getDay()],	
		'EE'	    : STR.daysShort[date.getDay()], // whether short form for day is 2 or 3 E's.  Support both here.
		'E'			: STR.daysInitial[date.getDay()],
		'dd'		: PTDate.get2DigitDayOfMonth(date),
		'd'			: PTDate.get1DigitDayOfMonth(date),
		'hh'		: PTDate.get2Digit1To12Hour(date),
		'h'			: PTDate.get1Digit1To12Hour(date),
		'HH'		: PTDate.get2Digit0To23Hour(date),
		'H'			: date.getHours(),
		'KK'		: PTDate.get2Digit0To11Hour(date),
		'K'			: PTDate.get1Digit0To11Hour(date),
		'kk'		: PTDate.get2Digit1To24Hour(date),
		'k'			: PTDate.get1Digit1To24Hour(date),
		'mm'		: PTDate.get2DigitMinutes(date),
		'm'			: PTDate.get1DigitMinutes(date),
		'ss'		: PTDate.get2DigitSeconds(date),
		's'			: PTDate.get1DigitSeconds(date),
		'SSS'		: PTDate.get3DigitMilliseconds(date),
		'a'			: PTDate.getAMPM(date,language),
		'z'		    : ''	    // z gets used a lot in PTDateValidatorFormats, but we really don't want any effect from it
	}
	var ph = new Array();
	var f = dateFormat;
	while (f.indexOf('\'') != f.lastIndexOf('\''))
	{
		var re = new RegExp("('[^']*')");
		var res = re.exec(f);
		var literal = RegExp.$1;
		var pStart = f.indexOf(literal);
		var pEnd = pStart + literal.length;
		var filler = '';
		for (var i = 0; i < literal.length; i++) { filler += '-'; }
		f = f.substring(0,pStart) + filler + f.substr(pEnd);
	}
	for (var pattern in patternStrings)
	{
		while (f.indexOf(pattern) > -1)
		{
			var pStart = f.indexOf(pattern);
			var pEnd = pStart + pattern.length;
			ph[pStart] = new Object();
			ph[pStart].string = patternStrings[pattern];
			ph[pStart].end = pEnd;
			var filler = '';
			for (var i = 0; i < pattern.length; i++) { filler += '-'; }
			f = f.substring(0,pStart) + filler + f.substr(pEnd);
		}
	}
	var convertedString = new String('');
	var i = 0;
	while (i < dateFormat.length)
	{
		if (ph[i])
		{
			convertedString += ph[i].string;
			i = ph[i].end;
		}
		else
		{
			if (dateFormat.charAt(i) == '\'')
			{
				if (dateFormat.charAt(i+1) == '\'')
				{
					convertedString += '\'';
					i = i + 2;
				}
				else { i++; }
				continue;
			}
			convertedString += dateFormat.charAt(i);
			i++;
		}
	}
	return PTStringUtil.trimWhitespace(convertedString,true,true);
}

PTDate.prototype.hasTime = function()
{
	return (this.datestring.indexOf(':') > -1);
}

PTDate.prototype.incrementMonth = function()
{
	var date = this.date;
	var month = date.getMonth();
	if (month < 11) {
		date.setMonth(month+1);
	}
	else {
		date.setMonth(0);
		date.setFullYear(date.getFullYear()+1);
	}
}

PTDate.prototype.incrementWeek = function()
{
	var date = this.date;
	var hours = date.getHours();
	date.setHours(12);
	var week = 1000*60*60*24*7;
	date.setTime(date.getTime()+week);
	date.setHours(hours);
}

PTDate.prototype.incrementDay = function()
{
	var date = this.date;
	var hours = date.getHours();
	date.setHours(12);
	var day = 1000*60*60*24;
	date.setTime(date.getTime()+day);
	date.setHours(hours);
}

PTDate.prototype.clone = function()
{
	return new PTDate(this.datestring,
					  new Date(this.date.getTime()),
					  this.language,
					  this.dateFormat);
}

PTDate.prototype.getNumberOfDaysInThisMonth = function() {
	return PTDate.getNumberOfDaysInMonth(this.date);
}

PTDate.EnglishStrings = new Object();
PTDate.EnglishStrings.monthsLong = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
PTDate.EnglishStrings.monthsShort = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
PTDate.EnglishStrings.daysLong = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
PTDate.EnglishStrings.daysShort = new Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
PTDate.EnglishStrings.daysInitial = new Array('S','M','T','W','T','F','S');
PTDate.EnglishStrings.ampm = new Array('am','pm');
if (!PTDate.formats)
{
	PTDate.formats = new Object();
}

PTDate.formats['en'] 	= new Array(
									'MMM d, yyyy h:mm:ss a',
									'M/d/yyyy h:mm a',
									'MMM d, yyyy h:mm:ss a',
									'MMMM d, yyyy h:mm:ss a z',
									'EEEE, MMMM d, yyyy h:mm:ss a z'
								);
PTDate.formats['de'] = new Array(
									'dd.MM.yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'dd.MM.yyyy HH:mm:ss',
									'd. MMMM yyyy HH:mm:ss z',
									'EEEE, d. MMMM yyyy H.mm\' Uhr \'z'
								);
PTDate.formats['de_AT'] = new Array(
									'dd.MM.yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'dd.MM.yyyy HH:mm:ss',
									'dd. MMMM yyyy HH:mm:ss z',
									'EEEE, dd. MMMM yyyy HH.mm\' Uhr \'z'
								);
PTDate.formats['de_CH'] = new Array(
									'dd.MM.yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'dd.MM.yyyy HH:mm:ss',
									'd. MMMM yyyy HH:mm:ss z',
									'EEEE, d. MMMM yyyy H.mm\' Uhr \'z'
								);
PTDate.formats['de_DE'] = new Array(
									'dd.MM.yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'dd.MM.yyyy HH:mm:ss',
									'd. MMMM yyyy HH:mm:ss z',
									'EEEE, d. MMMM yyyy H.mm\' Uhr \'z'
								);
PTDate.formats['de_LU'] = new Array(
									'dd.MM.yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'dd.MM.yyyy HH:mm:ss',
									'd. MMMM yyyy HH:mm:ss z',
									'EEEE, d. MMMM yyyy H.mm\' Uhr \'z'
								);
PTDate.formats['en_AU'] = new Array(
									'd/MM/yyyy HH:mm:ss',
									'd/MM/yyyy HH:mm',
									'd/MM/yyyy HH:mm:ss',
									'd MMMM yyyy H:mm:ss',
									'EEEE, d MMMM yyyy hh:mm:ss a z'
								);
PTDate.formats['en_CA'] = new Array(
									'd-MMM-yyyy h:mm:ss a',
									'dd/MM/yyyy h:mm a',
									'd-MMM-yyyy h:mm:ss a',
									'MMMM d, yyyy h:mm:ss z a',
									'EEEE, MMMM d, yyyy h:mm:ss \'o\'\'clock\' a z'
								);
PTDate.formats['en_GB'] = new Array(
									'dd-MMM-yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'dd-MMM-yyyy HH:mm:ss',
									'dd MMMM yyyy HH:mm:ss z',
									'dd MMMM yyyy HH:mm:ss \'o\'\'clock\' z'
								);
PTDate.formats['en_IE'] = new Array(
									'dd-MMM-yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'dd-MMM-yyyy HH:mm:ss',
									'dd MMMM yyyy HH:mm:ss z',
									'dd MMMM yyyy HH:mm:ss \'o\'\'clock\' z'
								);
PTDate.formats['en_NZ'] = new Array(
									'd/MM/yyyy HH:mm:ss',
									'd/MM/yyyy HH:mm',
									'd/MM/yyyy HH:mm:ss',
									'd MMMM yyyy H:mm:ss',
									'EEEE, d MMMM yyyy hh:mm:ss a z'
								);
PTDate.formats['en_US'] = new Array(
									'MMM d, yyyy h:mm:ss a',
									'M/d/yyyy h:mm a',
									'MMM d, yyyy h:mm:ss a',
									'MMMM d, yyyy h:mm:ss a z',
									'EEEE, MMMM d, yyyy h:mm:ss a z'
								);
PTDate.formats['en_ZA'] = new Array(
									'yyyy/MM/dd hh:mm:ss',
									'yyyy/MM/dd hh:mm',
									'yyyy/MM/dd hh:mm:ss',
									'dd MMMM yyyy hh:mm:ss',
									'dd MMMM yyyy hh:mm:ss a'
								);
PTDate.formats['es'] = new Array(
									'dd-MMM-yyyy H:mm:ss',
									'd/MM/yyyy H:mm',
									'dd-MMM-yyyy H:mm:ss',
									'd\' de \'MMMM\' de \'yyyy H:mm:ss z',
									'EEEE d\' de \'MMMM\' de \'yyyy HH\'H\'mm\'\' z'
								);
PTDate.formats['es_AR'] = new Array(
									'dd/MM/yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'dd/MM/yyyy HH:mm:ss',
									'd\' de \'MMMM\' de \'yyyy H:mm:ss z',
									'EEEE d\' de \'MMMM\' de \'yyyy HH\'h\'\'\'mm z'
								);
PTDate.formats['es_BO'] = new Array(
									'dd-MM-yyyy hh:mm:ss a',
									'dd-MM-yyyy hh:mm a',
									'dd-MM-yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_CL'] = new Array(
									'dd-MM-yyyy hh:mm:ss a',
									'dd-MM-yyyy hh:mm a',
									'dd-MM-yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_CO'] = new Array(
									'd/MM/yyyy hh:mm:ss a',
									'd/MM/yyyy hh:mm a',
									'd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_CR'] = new Array(
									'dd/MM/yyyy hh:mm:ss a',
									'dd/MM/yyyy hh:mm a',
									'dd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_DO'] = new Array(
									'MM/dd/yyyy hh:mm:ss a',
									'MM/dd/yyyy hh:mm a',
									'MM/dd/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_EC'] = new Array(
									'dd/MM/yyyy hh:mm:ss a',
									'dd/MM/yyyy hh:mm a',
									'dd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_GT'] = new Array(
									'd/MM/yyyy hh:mm:ss a',
									'd/MM/yyyy hh:mm a',
									'd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_HN'] = new Array(
									'MM-dd-yyyy hh:mm:ss a',
									'MM-dd-yyyy hh:mm a',
									'MM-dd-yyyy hh:mm:ss a',
									'dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_MX'] = new Array(
									'd/MM/yyyy hh:mm:ss a',
									'd/MM/yyyy hh:mm a',
									'd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_NI'] = new Array(
									'MM-dd-yyyy hh:mm:ss a',
									'MM-dd-yyyy hh:mm a',
									'MM-dd-yyyy hh:mm:ss a',
									'dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_PA'] = new Array(
									'MM/dd/yyyy hh:mm:ss a',
									'MM/dd/yyyy hh:mm a',
									'MM/dd/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_PE'] = new Array(
									'dd/MM/yyyy hh:mm:ss a',
									'dd/MM/yyyy hh:mm a',
									'dd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_PR'] = new Array(
									'MM-dd-yyyy hh:mm:ss a',
									'MM-dd-yyyy hh:mm a',
									'MM-dd-yyyy hh:mm:ss a',
									'dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_PY'] = new Array(
									'dd/MM/yyyy hh:mm:ss a',
									'dd/MM/yyyy hh:mm a',
									'dd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_SV'] = new Array(
									'MM-dd-yyyy hh:mm:ss a',
									'MM-dd-yyyy hh:mm a',
									'MM-dd-yyyy hh:mm:ss a',
									'dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE dd\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_UY'] = new Array(
									'dd/MM/yyyy hh:mm:ss a',
									'dd/MM/yyyy hh:mm a',
									'dd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['es_VE'] = new Array(
									'dd/MM/yyyy hh:mm:ss a',
									'dd/MM/yyyy hh:mm a',
									'dd/MM/yyyy hh:mm:ss a',
									'd\' de \'MMMM\' de \'yyyy hh:mm:ss a z',
									'EEEE d\' de \'MMMM\' de \'yyyy hh:mm:ss a z'
								);
PTDate.formats['fr'] = new Array(
									'd MMM yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'd MMM yyyy HH:mm:ss',
									'd MMMM yyyy HH:mm:ss z',
									'EEEE d MMMM yyyy HH\' h \'mm z'
								);
PTDate.formats['fr_BE'] = new Array(
									'dd-MMM-yyyy H:mm:ss',
									'd/MM/yyyy H:mm',
									'dd-MMM-yyyy H:mm:ss',
									'd MMMM yyyy H:mm:ss z',
									'EEEE d MMMM yyyy H\' h \'mm\' min \'ss\' s \'z'
								);
PTDate.formats['fr_CA'] = new Array(
									'yyyy-MM-dd HH:mm:ss',
									'yyyy-MM-dd HH:mm',
									'yyyy-MM-dd HH:mm:ss',
									'd MMMM yyyy HH:mm:ss z',
									'EEEE d MMMM yyyy H\' h \'mm z'
								);
PTDate.formats['fr_CH'] = new Array(
									'd MMM yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'd MMM yyyy HH:mm:ss',
									'd. MMMM yyyy HH:mm:ss z',
									'EEEE, d. MMMM yyyy HH.mm.\' h\' z'
								);
PTDate.formats['fr_FR'] = new Array(
									'd MMM yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'd MMM yyyy HH:mm:ss',
									'd MMMM yyyy HH:mm:ss z',
									'EEEE d MMMM yyyy HH\' h \'mm z'
								);
PTDate.formats['fr_LU'] = new Array(
									'd MMM yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'd MMM yyyy HH:mm:ss',
									'd MMMM yyyy HH:mm:ss z',
									'EEEE d MMMM yyyy HH\' h \'mm z'
								);
PTDate.formats['it'] = new Array(
									'd-MMM-yyyy H.mm.ss',
									'dd/MM/yyyy H.mm',
									'd-MMM-yyyy H.mm.ss',
									'd MMMM yyyy H.mm.ss z',
									'EEEE d MMMM yyyy H.mm.ss z'
								);
PTDate.formats['it_CH'] = new Array(
									'd-MMM-yyyy HH:mm:ss',
									'dd.MM.yyyy HH:mm',
									'd-MMM-yyyy HH:mm:ss',
									'd. MMMM yyyy HH:mm:ss z',
									'EEEE, d. MMMM yyyy H.mm\' h\' z'
								);
PTDate.formats['it_IT'] = new Array(
									'd-MMM-yyyy H.mm.ss',
									'dd/MM/yyyy H.mm',
									'd-MMM-yyyy H.mm.ss',
									'd MMMM yyyy H.mm.ss z',
									'EEEE d MMMM yyyy H.mm.ss z'
								);
PTDate.formats['ja'] = new Array(
									'yyyy/MM/dd H:mm:ss',
									'yyyy/MM/dd H:mm',
									'yyyy/MM/dd H:mm:ss',
									'yyyy/MM/dd H:mm:ss z',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' H\'\u6642\'mm\'\u5206\'ss\'\u79D2\'z'
								);
PTDate.formats['ja_JP'] = new Array(
									'yyyy/MM/dd H:mm:ss',
									'yyyy/MM/dd H:mm',
									'yyyy/MM/dd H:mm:ss',
									'yyyy/MM/dd H:mm:ss z',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' H\'\u6642\'mm\'\u5206\'ss\'\u79D2\'z'
								);
PTDate.formats['ko'] = new Array(
									'yyyy-MM-dd a h:mm:ss',
									'yyyy-MM-dd a h:mm',
									'yyyy-MM-dd a h:mm:ss',
									'yyyy\'\uB144\' M\'\uC6D4\' d\'\uC77C\' EE a hh\'\uC2DC\'mm\'\uBD84\'ss\'\uCD08\'',
									'yyyy\'\uB144\' M\'\uC6D4\' d\'\uC77C\' EEEE a hh\'\uC2DC\'mm\'\uBD84\'ss\'\uCD08\' z'
								);
PTDate.formats['ko_KR'] = new Array(
									'yyyy-MM-dd a h:mm:ss',
									'yyyy-MM-dd a h:mm',
									'yyyy-MM-dd a h:mm:ss',
									'yyyy\'\uB144\' M\'\uC6D4\' d\'\uC77C\' EE a hh\'\uC2DC\'mm\'\uBD84\'ss\'\uCD08\'',
									'yyyy\'\uB144\' M\'\uC6D4\' d\'\uC77C\' EEEE a hh\'\uC2DC\'mm\'\uBD84\'ss\'\uCD08\' z'
								);
PTDate.formats['pt'] = new Array(
									'd/MMM/yyyy H:mm:ss',
									'dd-MM-yyyy H:mm',
									'd/MMM/yyyy H:mm:ss',
									'd\' de \'MMMM\' de \'yyyy H:mm:ss z',
									'EEEE, d\' de \'MMMM\' de \'yyyy HH\'H\'mm\'m\' z'
								);
PTDate.formats['pt_BR'] = new Array(
									'dd/MM/yyyy HH:mm:ss',
									'dd/MM/yyyy HH:mm',
									'dd/MM/yyyy HH:mm:ss',
									'd\' de \'MMMM\' de \'yyyy H\'h\'m\'min\'s\'s\' z',
									'EEEE, d\' de \'MMMM\' de \'yyyy HH\'h\'mm\'min\'ss\'s\' z'
								);
PTDate.formats['pt_PT'] = new Array(
									'd/MMM/yyyy H:mm:ss',
									'dd-MM-yyyy H:mm',
									'd/MMM/yyyy H:mm:ss',
									'd\' de \'MMMM\' de \'yyyy H:mm:ss z',
									'EEEE, d\' de \'MMMM\' de \'yyyy HH\'H\'mm\'m\' z'
								);
PTDate.formats['zh'] = new Array(
									'yyyy-M-d H:mm:ss',
									'yyyy-M-d ah:mm',
									'yyyy-M-d H:mm:ss',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ahh\'\u65F6\'mm\'\u5206\'ss\'\u79D2\'',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' HH\'\u65F6\'mm\'\u5206\'ss\'\u79D2\' z'
								);
PTDate.formats['zh_CN'] = new Array(
									'yyyy-M-d H:mm:ss',
									'yyyy-M-d ah:mm',
									'yyyy-M-d H:mm:ss',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ahh\'\u65F6\'mm\'\u5206\'ss\'\u79D2\'',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' HH\'\u65F6\'mm\'\u5206\'ss\'\u79D2\' z'
								);
PTDate.formats['zh_HK'] = new Array(
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ahh:mm:ss',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ah:mm',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ahh:mm:ss',
									'yyyy\'\u5E74\'MM\'\u6708\'dd\'\u65E5\' EEEE ahh\'\u6642\'mm\'\u5206\'ss\'\u79D2\'',
									'yyyy\'\u5E74\'MM\'\u6708\'dd\'\u65E5\' EEEE ahh\'\u6642\'mm\'\u5206\'ss\'\u79D2\' z'
								);
PTDate.formats['zh_TW'] = new Array(
									'yyyy/M/d a hh:mm:ss',
									'yyyy/M/d a h:mm',
									'yyyy/M/d a hh:mm:ss',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ahh\'\u6642\'mm\'\u5206\'ss\'\u79D2\'',
									'yyyy\'\u5E74\'M\'\u6708\'d\'\u65E5\' ahh\'\u6642\'mm\'\u5206\'ss\'\u79D2\' z'
								);
function PTDateUtil()
{
	return this;
}

PTDateUtil.VERSION = '121140';
PTDateUtil.isSameDay = function (date1, date2)
{
	if (isNaN(date1) || isNaN(date2)) { return false; }
	if ((date1.getFullYear() == date2.getFullYear())
			&&
		(date1.getMonth() == date2.getMonth())
			&&
		(date1.getDate() == date2.getDate()))
	{
		return true;
	}
	else { return false; }
}

PTDateUtil.getDaysBetweenDates = function (date1, date2) {
	if (isNaN(date1) || isNaN(date2)) { return 0; }
	date1.setHours(12);
	date2.setHours(12);
	var millis = Math.abs(date2.getTime()-date1.getTime());
	return Math.round(millis/(1000*60*60*24));
}

PTDateUtil.formatTime = function(sTime, iMode)
{
	var err = false;
	var regTime = /\b\d\d?\b|\b\d\d?\B|\B\d\d?\b|\B\d\d?\B/g;
	var regAMPM = new RegExp('AM|am|Am|aM|PM|pm|Pm|pM|p.m.|p.m|P.M.|a.m.|a.m|A.M.');
	if (sTime == '') { return false; }
	if ((sTime.match(/\d\d?:\d/) == null) || (sTime.match(/:/) == null)) { return false; }
	var arrTime = sTime.match(regTime);
	var strAMPM = sTime.match(regAMPM);
	if (!arrTime[1]) { arrTime[1] = 0; }
	if (!arrTime[2]) { arrTime[2] = 0; }
	if ((arrTime[0] > 23) || (arrTime[1] > 59) || (arrTime[2] > 59) || (arrTime[0] == null) || (arrTime[0] < 0) || (arrTime[1] < 0) || (arrTime[2] < 0)) { err = true; }
	var strTempDigits;
	if (iMode == 0)
	{
		if ((strAMPM == 'PM') && (arrTime[0] < 12))			{ arrTime[0] += 12; }
		else if ((strAMPM == 'AM') && (arrTime[0] == 12))	{ arrTime[0] = 0; }
	}
	else
	{
		if (!strAMPM)
		{
			strAMPM = 'AM';
			if (arrTime[0] > 12)
			{
				arrTime[0] = arrTime[0] - 12;
				strAMPM = 'PM';
			}
			else if (arrTime[0] == 0)
			{
				arrTime[0] = 12;
				strAMPM = 'AM';
			}
		}
	}
	for (i = 0; i < 3; i++)
	{
		strTempDigits = '0' + arrTime[i];
		if (strTempDigits.length == 2) { arrTime[i] = strTempDigits; }
	}
	if (err)
	{
		alert(PTS_STR['PTU-Date-TimeFormatError']);
		return false;
	}
	else
	{
		sTime = arrTime[0] + ':' + arrTime[1] + ':' + arrTime[2];
		if (iMode == 1) { sTime += ' ' + strAMPM; }
		return sTime;
	}
}

PTDateUtil.validateDate = function(strDay, strMonth, strYear)
{
	var strInputDate = strDay + ' ' + strMonth + ' ' + strYear;
	var objDate = new Date(strInputDate);
	var strDate = objDate.toGMTString();
	var arrDate = strDate.split(' ');
	return (arrDate[2] != strMonth);
}

function PTDateValidator()
{
	return this;
}

PTDateValidator.VERSION = '121140';
PTDateValidator.TIME_POLICY_ALLOW_TIMES		= 0;
PTDateValidator.TIME_POLICY_REQUIRE_TIMES	= 1;
PTDateValidator.TIME_POLICY_FORBID_TIMES	= 2;
PTDateValidator.formatTokens	= new Array('a','d','E','h','H','k','K','m','M','s','S','y');
PTDateValidator.punctuation		= new Array(',','/',':','-','.');
PTDateValidator.closeSubstitutes =	{
											'\u00E1' : 'a',
											'\u00E4' : 'a',
											'\u00E7' : 'c',
											'\u00E9' : 'e',
											'\u00EC' : 'i',
											'\u00FB' : 'u',
											'\u2013' : '-',  
											'\u2212' : '-'
									 };
PTDateValidator.validateDate = function(dateString, locale, alertOnFailure, timePolicy, formatList)
{
	if (!dateString) { return false; }
	if (!locale)	 { locale 		= PTDate.DEFAULT_LOCALE; }
	if (!timePolicy) { timePolicy 	= PTDateValidator.TIME_POLICY_ALLOW_TIMES; }
	if (!formatList) { formatList 	= PTDate.getFormatListForLocale(locale); }
	var isValidDate = false;
	var numFormats = formatList.length;
	var dateData = false;
	var hash = PTDateValidator.getPunctuationHash();
	for (var f = 0; f < numFormats; f++)
	{
		var format = formatList[f];
		dateData = PTDateValidator.parseDateStringAgainstFormat(dateString,format,hash,locale);
		if (dateData != false)
		{
			if (PTNumberUtil.isInteger(dateData.day) && PTNumberUtil.isInteger(dateData.month) && PTNumberUtil.isInteger(dateData.year)) { break; }
		}
	}
	var date;
	var isValidDate = false;
	if (dateData != false)
	{
		if (dateData.ampm && (dateData.ampm == 'pm'))
		{
			if ((dateData.hour > 0) && (dateData.hour < 12)) { dateData.hour += 12; }
		}
		date = new Date(dateData.year, dateData.month, dateData.day, dateData.hour, dateData.minutes, dateData.seconds);
		if ((dateData.day == date.getDate()) &&
			(dateData.month == date.getMonth()) &&
			(dateData.year == date.getFullYear()))
		{
			isValidDate = true;
		}
	}
	if (!isValidDate) { alertOnFailure = PTDateValidator.alertOnFailure(alertOnFailure,formatList,timePolicy); }
	var isTimeValid = false;
	if (timePolicy == PTDateValidator.TIME_POLICY_ALLOW_TIMES)
	{
		if ((PTNumberUtil.isInteger(dateData.hour) && PTNumberUtil.isInteger(dateData.minutes)) ||
			(!PTNumberUtil.isInteger(dateData.hour) && !PTNumberUtil.isInteger(dateData.minutes)))
		{
			isTimeValid = true;
		} else { alertOnFailure = PTDateValidator.alertTimeFormatProblem(alertOnFailure,formatList,timePolicy); }
	}
	else if (timePolicy == PTDateValidator.TIME_POLICY_REQUIRE_TIMES)
	{
		if (PTNumberUtil.isInteger(dateData.hour) && PTNumberUtil.isInteger(dateData.minutes))
		{
			isTimeValid = true;
		} else { alertOnFailure = PTDateValidator.alertTimeRequired(alertOnFailure,formatList,timePolicy); }
	}
	else if (timePolicy == PTDateValidator.TIME_POLICY_FORBID_TIMES)
	{
		if (!PTNumberUtil.isInteger(dateData.hour) && !PTNumberUtil.isInteger(dateData.minutes))
		{
			isTimeValid = true;
		} else { alertOnFailure = PTDateValidator.alertTimeForbidden(alertOnFailure,formatList,timePolicy); }
	}
	if (timePolicy != PTDateValidator.TIME_POLICY_FORBID_TIMES)
	{
		if ((dateData.hour < 0) || (dateData.hour > 23))
		{
			isTimeValid = false;
			alertOnFailure = PTDateValidator.alertTimeFormatProblem(alertOnFailure,formatList,timePolicy);
		}
		else if ((dateData.minutes < 0) || (dateData.minutes > 59))
		{
			isTimeValid = false;
			alertOnFailure = PTDateValidator.alertTimeFormatProblem(alertOnFailure,formatList,timePolicy);
		}
		else if ((dateData.seconds < 0) || (dateData.seconds > 59))
		{
			isTimeValid = false;
			alertOnFailure = PTDateValidator.alertTimeFormatProblem(alertOnFailure,formatList,timePolicy);
		}
	}
	var returnValue = false;
	if (isValidDate && isTimeValid) { returnValue = date; }
	return returnValue;
}

PTDateValidator.parseDateStringAgainstFormat = function(dateString, format, hash, locale)
{
	dateString = (new String(dateString)).replace(/\'/g,'');
	format = format.replace(/\'\'/g,'');
	while (1)
	{
		var s = format.indexOf('\'');
		if (s == -1) { break; }
		var e = format.substr(s + 1).indexOf('\'');
		if (e == -1) { break; }
		e += s + 1;
		var literal = format.substring(s + 1,e);
		var percent = parseInt(((s / format.length) * 100),10);
		var matches = PTDateValidator.findAllMatches(literal, dateString, locale);
		var bestMatch = false;
		var bestDist = 100;
		for (var m = 0; m < matches.length; m++)
		{
			var match = matches[m];
			var dist = Math.abs(percent - match.pct);
			if (dist < bestDist) { bestMatch = match; }
		}
		if (bestMatch)
		{
			var start = bestMatch.loc;
			var end = start + literal.length;
			dateString = dateString.substring(0,start) + ' ' + dateString.substr(end);
		}
		format = format.substring(0,s) + ' ' + format.substr(e + 1);
	}
	dateString = PTStringUtil.substituteChars(dateString,hash);
	format = PTStringUtil.substituteChars(format,hash);
	dateString = PTStringUtil.trimWhitespace(dateString,true,true);
	format = PTStringUtil.trimWhitespace(format,true,true);
	var i = dateString.split(/\s+/);
	var f = format.split(/\s+/);
	var dateData = new _dateData();
	var numWords = Math.min(i.length,f.length);
	for (var w = 0; w < numWords; w++)
	{		
		var formatToken = f[w];
		var word = i[w];
		dateData = PTDateValidator.validateWordByTokenType(word,formatToken,dateData,locale);
		if (dateData == false) { return false; }
	}
	return dateData;
}

PTDateValidator.validateWordByTokenType = function(word, formatToken, dateData, locale)
{
	word = word.toLowerCase();
	var foundAmpm = false;
	var STR = PTDateStrings;
	if (locale.indexOf('en') == 0) { STR = PTDate.EnglishStrings; }
	if (formatToken.indexOf('a') > -1)
	{
		var strings = STR.ampm.length;
		for (var s = 0; s < strings; s++)
		{
			var ampmString = STR.ampm[s];
			var idx = word.indexOf(ampmString.toLowerCase());
			if (idx > -1)
			{
				dateData.ampm = (s) ? 'pm' : 'am';
				word = word.substring(0,idx) + word.substr(ampmString.length);
				while (formatToken.indexOf('a') > -1)
				{
					var pos = formatToken.indexOf('a');
					formatToken = formatToken.substring(0,pos) + formatToken.substr(pos + 1);
				}
				foundAmpm = true;
				break;
			}
		}
	}
	if (formatToken.charAt(0) == 'd')
	{
		if (!PTNumberUtil.isInteger(word)) { return false; }
		var n = word;
		if (parseInt(n,10) == 0) { n = parseInt(n,10); }
		else { n = parseInt(PTNumberUtil.trimLeadingZeros(word),10); }
		if (isNaN(n)) { return false; }
		dateData.day = n;
		return dateData;
	}
	else if (formatToken == 'E')
	{
		if (PTDateValidator.isWordLike(word,STR.daysInitial)) { return dateData; }
	}
	else if (formatToken.substring(0,2) == 'EE')
	{
		if (PTDateValidator.isWordLike(word,STR.daysLong.concat(STR.daysShort))) { return dateData; }
	}
	else if (formatToken.charAt(0).toLowerCase() == 'h')
	{
		if (!PTNumberUtil.isInteger(word)) { return false; }
		var n = word;
		if (parseInt(n,10) == 0) { n = parseInt(n,10); }
		else { n = parseInt(PTNumberUtil.trimLeadingZeros(word),10); }
		if (isNaN(n)) { return false; }
		dateData.hour = n;
		return dateData;
	}
	else if (formatToken.charAt(0).toLowerCase() == 'k')
	{
		if (!PTNumberUtil.isInteger(word)) { return false; }
		var n = word;
		if (parseInt(n,10) == 0) { n = parseInt(n,10); }
		else { n = parseInt(PTNumberUtil.trimLeadingZeros(word),10); }
		if (isNaN(n)) { return false; }
		dateData.hour = n;
		return dateData;
	}
	else if (formatToken.charAt(0) == 'm')
	{
		if (!PTNumberUtil.isInteger(word)) { return false; }
		var n = word;
		if (parseInt(n,10) == 0) { n = parseInt(n,10); }
		else { n = parseInt(PTNumberUtil.trimLeadingZeros(word),10); }
		if (isNaN(n)) { return false; }
		dateData.minutes = n;
		return dateData;
	}
	else if ((formatToken == 'M') || (formatToken == 'MM'))
	{
		if (!PTNumberUtil.isInteger(word)) { return false; }
		var n = word;
		if (parseInt(n,10) == 0) { n = parseInt(n,10); }
		else { n = parseInt(PTNumberUtil.trimLeadingZeros(word),10); }
		if (isNaN(n)) { return false; }
		n -= 1;
		dateData.month = n;
		return dateData;
	}
	else if (formatToken.substring(0,3) == 'MMM')
	{
		var m = PTDateValidator.isWordLike(word,STR.monthsLong.concat(STR.monthsShort));
		if (m)
		{
			if (parseInt(m,10) == 0) { dateData.month = 0; }
			else { dateData.month = parseInt(PTNumberUtil.trimLeadingZeros(m),10); }
			return dateData;
		}
	}
	else if (formatToken.charAt(0) == 's')
	{
		var n = word;
		if (parseInt(n,10) == 0) { n = parseInt(n,10); }
		else { n = parseInt(PTNumberUtil.trimLeadingZeros(word),10); }
		if (isNaN(n)) { dateData.seconds = 0; }
		else { dateData.seconds = n; }
		return dateData;
	}
	else if (formatToken.charAt(0) == 'S')
	{
		return dateData;
	}
	else if (formatToken.indexOf('yy') > -1)
	{
		if (!PTNumberUtil.isInteger(word)) { return false; }
		var n = parseInt(PTNumberUtil.trimLeadingZeros(word),10);
		if (isNaN(n)) { return false; }
		if (n < 100)
		{
			n = PTDate.convert2DigitTo4DigitYear(n);
		}
		dateData.year = n;
		return dateData;
	}
	else if (formatToken.charAt(0) == 'z')
	{
		return dateData;
	}
	if (foundAmpm)	{ return dateData }
	else			{ return false; }
}

PTDateValidator.isWordLike = function(word, matchArray)
{
	word = word + '';  
	var len = matchArray.length;
	for (var a = 0; a < len; a++)
	{
		var m = (new String(matchArray[a])).toLowerCase() + '';  
		if (m == word) { return new String(a); }
		if ((word.length >= 3) && (m.indexOf(word.substring(0,3)) == 0)) { return new String(a); }
		m = PTStringUtil.substituteChars(m,PTDateValidator.closeSubstitutes);
		if (m == word) { return new String(a); }
		if ((word.length >= 3) && (m.indexOf(word) == 0)) { return new String(a); }
	}
	return false;
}

PTDateValidator.findAllMatches = function(pattern, string, locale)
{
	var results = new Array();
	var tester = new String(string);
	var chopped = 0;
	var STR = PTDateStrings;
	if (locale.indexOf('en') == 0) { STR = PTDate.EnglishStrings; }
	while (tester.indexOf(pattern) > -1)
	{
		var loc = tester.indexOf(pattern);
		var pos = loc + chopped;
		var nogood = false;
		var fragment = (tester.substr(tester.indexOf(pattern))).replace(/\s.*$/,'');
		if (fragment.length > 0)
		{
			for (var i = 0; i < STR.monthsLong.length; i++)
			{
				if (STR.monthsLong[i].indexOf(fragment) > -1)
				{
					nogood = true;
					break;
				}
			}
		}
		if (!nogood)
		{
			var r = results[results.length] = new Object();
			r.loc = pos;
			r.pct = Math.round((pos / string.length) * 100);
		}
		tester = tester.substr(loc + 1);
		chopped += (loc + 1);
	}
	return results;
}

PTDateValidator.alertOnFailure = function(alertOnFailure, formatList, timePolicy)
{
	if (alertOnFailure)
	{
		var sb = new PTStringBuffer();
		sb.append(PTS_STR['PTU-DateV-DateFormatError'] + '\n\n');
		sb.append(PTS_STR['PTU-DateV-ExampleFormats'] + '\n\n');
		var m = new Array();
		var d = new Date();
		var startAt = 0;
		if (formatList[0] == formatList[2]) { startAt = 1; }
		for (var f = startAt; f < formatList.length; f++)
		{
			var format = formatList[f];
			if (timePolicy == PTDateValidator.TIME_POLICY_FORBID_TIMES) { format = PTDate.stripTimesFromFormat(format); }
			var formattedDate = PTDate.formatDate(d,format);
			if (m[formattedDate]) { continue; }
			else { m[formattedDate] = true; }
			sb.append('      ' + formattedDate + '\n');
		}
		sb.append('\n');
		alert(sb.toString());
	}
	return false;
}

PTDateValidator.alertTimeFormatProblem = function(alertOnFailure, formatList, timePolicy)
{
	if (alertOnFailure)
	{
		alert(PTS_STR['PTU-DateV-TimeFormatError']);
		return false;
	}
	return alertOnFailure;
}

PTDateValidator.alertTimeRequired = function(alertOnFailure, formatList, timePolicy)
{
	if (alertOnFailure)
	{
		alert(PTS_STR['PTU-DateV-TimeRequired']);
		return false;
	}
	return alertOnFailure;
}

PTDateValidator.alertTimeForbidden = function(alertOnFailure, formatList, timePolicy)
{
	if (alertOnFailure)
	{
		alert(PTS_STR['PTU-DateV-TimeForbidden']);
		return false;
	}
	return alertOnFailure;
}

PTDateValidator.getPunctuationHash = function()
{
	var hash = new Array();
	var chars = PTStringUtil.whitespaceChars.concat(PTDateValidator.punctuation);
	var len = chars.length;
	for (var c = 0; c < len; c++) { hash[chars[c]] = ' '; }
	return hash;
}

function _dateData()
{
	this.day		= false;
	this.month 		= false;
	this.year		= false;
	this.hour		= false;
	this.minutes	= false;
	this.seconds	= false;
	this.ampm		= false;
	return this;
}

function PTFormUtil() {}

PTFormUtil.VERSION = '121140';
PTFormUtil.getRadioValue = function(rads)
{
	if (!rads) { return; }
	var val;
	if (rads.length > 1) {
		for (var i = 0; i < rads.length; i++) {
			if (rads[i].checked) {
				val = rads[i].value;
				break;
			}
		}
	} else {
		val = rads.value;
	}
	return val;
}

PTFormUtil.setRadioValue = function(rads,val)
{
	var success = false;
	if (!rads) { return success; }
	if (rads.length > 1) {
		for (var i = 0; i < rads.length; i++) {
			if (rads[i].value == val) {
				rads[i].checked = true;
				success = true;
				break;
			}
		}
	} else {
		rads.checked = true;
		success = true;
	}
	return success;
}

PTFormUtil.setSelectValue = function(sel,val)
{
	var success = false;
	if (!sel) { return success; }
	if (sel.options.length < 1) { return success; }
	for (var i = 0; i < sel.options.length; i++) {
		var opt = sel.options[i];
		if (opt.value && opt.value == val) {
			sel.selectedIndex = i;
			success = true;
			break;
		}
	}
	return success;
}

PTFormUtil.fillSelect = function(sel,optionsInfo)
{
	if (!sel) { return; }
	if (!optionsInfo) { return; }
	if (!optionsInfo.length) { return; }
	var numOldOptions = sel.options.length;
	var numNewOptions = optionsInfo.length;
	for (var i = 0; i < numNewOptions; i++) {
		if (!optionsInfo[i]) { continue; }
		var curNewOption = optionsInfo[i];
		var newOptionText = curNewOption.text;
		var newOptionValue = curNewOption.value;
		var newOptionIndex = numOldOptions + i;
		sel.options[newOptionIndex] = new Option(newOptionText,newOptionValue);
	}
}

PTFormUtil.clearSelect = function(sel)
{
	if (!sel) { return; }
	var numOpts = sel.options.length;
	if (numOpts == 0) { return; }
	for (var i = (numOpts - 1); i >= 0; i--) {
		sel.options[i] = null;
	}
}

PTFormUtil.addItemToSelect = function(sel,val,txt,idx)
{
	if ((!idx && (idx != 0)) || (idx == -1)) {
		idx = sel.options.length;
		sel.options[idx] = new Option(txt,val);
	} else {
		var opts = sel.options;
		var len = opts.length;
		for (var i = len; i > idx; i--) {
			if (!opts[i]) {
				opts[i] = new Option(opts[i-1].text,opts[i-1].value);
			} else {
				opts[i].text = opts[i-1].text;
				opts[i].value = opts[i-1].value;
			}
		}
		opts[idx].text = txt;
		opts[idx].value = val;
	}
	return idx;
}

PTFormUtil.selectMoveItemUp = function(sel)
{
	idx = sel.selectedIndex;
	if (idx == -1) { return; }
	if (idx < 1) { return; }
	var swapText = sel.options[idx-1].text;
	var swapVal = sel.options[idx-1].value;
	sel.options[idx-1].text = sel.options[idx].text;
	sel.options[idx-1].value = sel.options[idx].value;
	sel.options[idx].text = swapText;
	sel.options[idx].value = swapVal;
	sel.selectedIndex = idx - 1;
}

PTFormUtil.selectMoveItemDown = function(sel)
{
	idx = sel.selectedIndex;
	if (idx == -1) { return; }
	if (idx >= (sel.options.length - 1)) { return; }
	var swapText = sel.options[idx+1].text;
	var swapVal = sel.options[idx+1].value;
	sel.options[idx+1].text = sel.options[idx].text;
	sel.options[idx+1].value = sel.options[idx].value;
	sel.options[idx].text = swapText;
	sel.options[idx].value = swapVal;
	sel.selectedIndex = idx + 1;
}

PTFormUtil.focusAndSelectText = function(input)
{
	if (!input || !input.focus || !input.select) { return; }
	input.focus();
	input.select();
}

PTFormUtil.focusFormFieldByName = function(fieldName)
{
	var field = eval(fieldName);
	if (field && field.focus) { field.focus(); }
}

PTFormUtil.hideAllSelects = function(doc)
{
	if (!doc) { doc = window.document; }
	var selects = doc.getElementsByTagName('select');
	for (var s = 0; s < selects.length; s++)
	{
		PTFormUtil.setSelectVisibility(selects[s],'hidden');
	}
}

PTFormUtil.showAllSelects = function(doc)
{
	if (!doc) { doc = window.document; }
	var selects = doc.getElementsByTagName('select');
	for (var s = 0; s < selects.length; s++)
	{
		PTFormUtil.setSelectVisibility(selects[s],'visible');
	}
}

PTFormUtil.setSelectVisibility = function(select,vis)
{
	if (!select) { return false; }
	select.style.visibility = vis;
}

function PTNumberFormatter(num)
{
	this.num;
	this.isGrouping;
	this.isCurrency;
	this.currencySymbol;
	this.currencySymbolBefore;
	this.groupingSeparator;
	this.decimalSeparator;
	this.decimalPlaces;
	this.negativePrefix;
	this.negativeSuffix;
	this.setNumber((num == null) ? 0 : num);
	this.setGrouping(true);
	this.setGroupingSeparator(',');
	this.setCurrency(false);
	this.setCurrencySymbol('');
	this.setCurrencySymbolBefore(true);
	this.setDecimalSeparator('.');
	this.setDecimalPlaces(-1);
	this.setNegativePrefix('-');
	this.setNegativeSuffix('');
}

PTNumberFormatter.VERSION = '121140';
PTNumberFormatter.prototype.INVALID = 'INVALID';
PTNumberFormatter.prototype.setNumber = _nf_setNumber;
PTNumberFormatter.prototype.toUnformatted = _nf_toUnformatted;
PTNumberFormatter.prototype.setGrouping = _nf_setGrouping;
PTNumberFormatter.prototype.setGroupingSeparator = _nf_setGroupingSeparator;
PTNumberFormatter.prototype.setCurrency = _nf_setCurrency;
PTNumberFormatter.prototype.setCurrencySymbol = _nf_setCurrencySymbol;
PTNumberFormatter.prototype.setCurrencySymbolBefore = _nf_setCurrencySymbolBefore;
PTNumberFormatter.prototype.setDecimalSeparator = _nf_setDecimalSeparator;
PTNumberFormatter.prototype.setDecimalPlaces = _nf_setDecimalPlaces;
PTNumberFormatter.prototype.setNegativePrefix = _nf_setNegativePrefix;
PTNumberFormatter.prototype.setNegativeSuffix = _nf_setNegativeSuffix;
PTNumberFormatter.prototype.toFormatted = _nf_toFormatted;
PTNumberFormatter.prototype.formatField = _nf_formatField;
PTNumberFormatter.prototype.validateValue = _nf_validateValue;
PTNumberFormatter.prototype.formatValue = _nf_formatValue;
PTNumberFormatter.prototype.getRounded = _nf_getRounded;
PTNumberFormatter.prototype.preserveZeros = _nf_preserveZeros;
PTNumberFormatter.prototype.invalidNumber = _nf_invalidNumber;
function _nf_setNumber(num)
{
	this.num = num;
}

function _nf_toUnformatted()
{
	return (this.num);
}

function _nf_setGrouping(isG)
{
	this.isGrouping = isG;
}

function _nf_setGroupingSeparator(gs)
{
	this.groupingSeparator = gs;
}

function _nf_setDecimalSeparator(ds)
{
	this.decimalSeparator = ds;
}

function _nf_setCurrency(isC)
{
	this.isCurrency = isC;
}

function _nf_setCurrencySymbol(cs)
{
	this.currencySymbol = cs;
}

function _nf_setCurrencySymbolBefore(csb)
{
	this.currencySymbolBefore = csb;
}

function _nf_setDecimalPlaces(p)
{
	this.decimalPlaces = p;
}

function _nf_setNegativePrefix(np)
{
	this.negativePrefix = np;
}

function _nf_setNegativeSuffix(ns)
{
	this.negativeSuffix = ns;
}

function _nf_toFormatted(num)
{
	if (num != null) {
		this.num = num;
	}
	if ((this.num == null) || (this.num == '') || (this.num.toString().length == 0)) {
		return '';
	}
	if (this.isCurrency == true)
	{
		var csRe1 = new RegExp(this.currencySymbol, 'gi');
		this.num = this.num.toString().replace(csRe1,'');
		var csRe2 = new RegExp('\\'+this.currencySymbol, 'gi');
		this.num = this.num.toString().replace(csRe2,'');
	}
	var gsRe = new RegExp('\\'+this.groupingSeparator, 'g');
	this.num = this.num.toString().replace(gsRe,'');
	if ((this.num.toString().indexOf('(') > -1) && (this.num.toString().indexOf(')') > -1)) {
		if (this.num.toString().indexOf(')') != this.num.toString().lastIndexOf(')')) {
			return this.invalidNumber();
		}
		if (this.num.toString().indexOf('(') != this.num.toString().lastIndexOf('(')) {
			return this.invalidNumber();
		}
		if (this.num.toString().indexOf(')') < this.num.toString().lastIndexOf('(')) {
			return this.invalidNumber();
		}
		var paRe1 = new RegExp('\\(', 'g');
		this.num = this.num.toString().replace(paRe1,'');
		var paRe2 = new RegExp('\\)', 'g');
		this.num = this.num.toString().replace(paRe2,'');
		if (this.num.toString().indexOf('-') == -1) {
			this.num = '-' + this.num.toString();
		}
	}
	if (this.num.toString().indexOf('-') != this.num.toString().lastIndexOf('-')) {
		return this.invalidNumber();
	}
	var mseRe = new RegExp('\\d\\D*-\\D*\\d', 'g');
	if (mseRe.test(this.num.toString())) {
		return this.invalidNumber();
	}
	if (this.num.toString().indexOf('-') != -1) {
		var msRe = new RegExp('-', 'g');
		this.num = this.num.toString().replace(msRe,'');
		this.num = '-' + this.num.toString();
	}
	dsRe = new RegExp('\\'+this.decimalSeparator, 'g');
	this.num = this.num.toString().replace(dsRe,'.');
	if (isNaN(this.num)) {
		return this.invalidNumber();
	}
	var pos;
	var nNum = this.num; 
	var nStr;			
	var absNum = this.num;
	if (absNum.toString().indexOf('-') == 0) {
		absNum = absNum.substring(1);
	}
	nNum = this.getRounded(nNum);
	nStr = this.preserveZeros(absNum);
	dotRe = new RegExp('\\.', 'g');
	nStr = nStr.replace(dotRe,this.decimalSeparator);
	if (this.isGrouping) {
		pos = nStr.indexOf(this.decimalSeparator);
		if (pos == -1) {
			pos = nStr.length;
		}
		while (pos > 0) {
			pos -= 3;
			if (pos <= 0) { break; }
			nStr = nStr.substring(0,pos) + this.groupingSeparator + nStr.substring(pos, nStr.length);
		}
	}
	if (this.isCurrency) {
		if (this.currencySymbolBefore) {
			nStr = this.currencySymbol + nStr;
		} else {
			nStr = nStr + this.currencySymbol;
		}
	}
	nStr = (nNum < 0) ? this.negativePrefix + nStr + this.negativeSuffix : nStr; 
	return (nStr);
}

function _nf_getRounded(val)
{
	if (this.decimalPlaces < 0) return val;
	var factor;
	var i;
	factor = 1;
	for (i=0; i<this.decimalPlaces; i++)
	{   factor *= 10; }
	val *= factor;
	val = Math.round(val);
	val /= factor;
	return (val);
}

function _nf_preserveZeros(val)
{
	var i;
	val = val + '';
	if (this.decimalPlaces < 0) return val; 
	var decimalPos = val.indexOf('.');
	if (decimalPos == -1 && this.decimalPlaces > 0)
	{
		val += this.decimalSeparator;
		for (i=0; i<this.decimalPlaces; i++)
		{
			val += '0';
		}
	}
	else
	{
		var actualDecimals = (val.length - 1) - decimalPos;
		var difference = this.decimalPlaces - actualDecimals;
		for (i=0; i<difference; i++)
		{
			val += '0';
		}
	}
	return val;
}

function _nf_invalidNumber()
{
	alert(PTS_STR['PTU-Number-AlertInvNumber']);
	return this.INVALID;
}

function _nf_formatField(field)
{
	var formatted = this.toFormatted(field.value);
	if (formatted == this.INVALID)
	{
		field.value = '';
		field.focus();
	}
	else
		field.value = formatted;
}

function _nf_validateValue(value)
{
	var formatted = this.toFormatted(value);
	if (formatted == this.INVALID)
		return false;
	else
		return true;
}

function _nf_formatValue(value)
{
	return this.toFormatted(value);
}

function PTNumberUtil() {}

PTNumberUtil.VERSION = '121140';
PTNumberUtil.isInteger = function(sNumber)
{
	sNumber = PTNumberUtil.trimLeadingZeros(sNumber);
	if (sNumber.length == 0)
	{
		return true;
	}
	var oString = new String(sNumber);
	var nString = new String(parseInt(new String(sNumber)));
	return (oString.valueOf() == nString.valueOf());
}

PTNumberUtil.isPositiveInteger = function(sNumber)
{	
	if (!PTNumberUtil.isInteger(sNumber)) { return false; }
	return (parseInt(sNumber) > 0);
}

PTNumberUtil.trimLeadingZeros = function(sNumber)
{
	sNumber = new String(sNumber);
	while (sNumber.charAt(0) == '0') { sNumber = sNumber.substr(1); }
	return sNumber;
}

function PTStringBuffer(str) {
	this.s = new Array();
	if (str && str.length && (str.length > 0))
	{
		this.s[0] = str;
	}
	return this;
}

PTStringBuffer.VERSION = '121140';
PTStringBuffer.prototype.append = function(str)
{
	this.s[this.s.length] = str;
}

PTStringBuffer.prototype.toString = function()
{
	return this.s.join('');
}

function PTStringUtil() {}

PTStringUtil.VERSION = '121140';
PTStringUtil.whitespaceChars = new Array(' ','\n','\r','\t');
PTStringUtil.isString = function(obj)
{
	if (obj == '') { return true; }
	return (typeof obj == 'string');
}

PTStringUtil.isValidHTTPString = function(str)
{
	var strHTTPPartA = str.substring(0,7);
	var strHTTPPartB = str.substring(0,8);
	if ((strHTTPPartA != 'http://') && (strHTTPPartB != 'https://')) { return false; }
	if (str.length < 8) { return false; }
	if (PTStringUtil.containsWhitespace(str)) { return false; }
	return true;
}

PTStringUtil.isValidUNCString = function(str, bCanBeNull)
{
	if (!str)								{ return false; }
	if (bCanBeNull && (strUNCString == ''))	{ return true; }
	if (strUNCString == '')					{ return false; }
	var strUNCPart = strUNCString.substring(0,2);
	if (strUNCPart != '\\\\' )				{ return false; }
	if (strUNCString.length < 3)			{ return false; }
	return true;
}

PTStringUtil.containsAngleBrackets = function(str)
{
	var angles = /[<>]/;
	return (angles.test(str));
}

PTStringUtil.containsWhitespace = function(str)
{
	var whitespaceChars = PTStringUtil.whitespaceChars;
	str = new String(str);
	for (var i = 0; i < str.length; i++) {
		var theChar = str.charAt(i);
		for (var j = 0; j < whitespaceChars.length; j++) {
			var white = whitespaceChars[j];
			if (theChar == white) {
				return true;
			}
		}
	}
	return false;
}

PTStringUtil.isAllWhitespace = function(str)
{
	var whitespaceChars = PTStringUtil.whitespaceChars;
	str = new String(str);
	STRING:
	for (var i = 0; i < str.length; i++) {
		var theChar = str.charAt(i);
		for (var j = 0; j < whitespaceChars.length; j++) {
			var white = whitespaceChars[j];
			if (theChar == white) {
				continue STRING;
			}
		}
		return false;
	}
	return true;
}

PTStringUtil.UCFirst = function(str) {
	var firstLetter = (new String(str)).substring(0,1);
	if (!firstLetter) { return str; }
	else {
		var restOfString = (new String(str)).substring(1);
		if (!restOfString) { restOfString = ''; }
		var ucFirst = firstLetter.toUpperCase() + restOfString;
		return ucFirst;
	}
}

PTStringUtil.stripChars = function(str,chars)
{  
	if (!chars || (chars.length < 1)) { return str; }
	str = new String(str);
	var newStr = new String();
	STRING:
	for (var i = 0; i < str.length; i++) {
		var theChar = str.charAt(i);
		for (var j = 0; j < chars.length; j++) {
			var strip = chars[j];
			if (theChar == strip) {
				continue STRING;
			}
		}
		newStr += theChar;
	}
	return newStr;
}

PTStringUtil.trimWhitespace = function(str,trimFront,trimRear)
{
	if (!str) { return; }
	str = new String(str);
	var whitespaceChars = PTStringUtil.whitespaceChars;
	if (trimFront) {
		var doTrim = true;
		while (doTrim) {
			var foundWhite = false;
			for (var w = 0; w < whitespaceChars.length; w++) {
				var c = whitespaceChars[w];
				if (c == str.charAt(0)) {
					foundWhite = true;
					break;
				}
			}
			if (foundWhite) {
				str = str.substr(1);
			} else {
				doTrim = false;
			}
		}
	}
	if (trimRear) {
		var doTrim = true;
		while (doTrim) {
			var foundWhite = false;
			for (var w = 0; w < whitespaceChars.length; w++) {
				var c = whitespaceChars[w];
				if (c == str.charAt(str.length - 1)) {
					foundWhite = true;
					break;
				}
			}
			if (foundWhite) {
				str = str.substring(0, (str.length - 1));
			} else {
				doTrim = false;
			}
		}
	}
	return str;
}

PTStringUtil.escapeHTML = function(str)
{
	str = new String(str);
	if (document.getElementById)
	{
		var nextChar = new RegExp('"','g');
		str = str.replace(nextChar, '&quot;');
		var nextChar = new RegExp('<','g');
		str = str.replace(nextChar, '&lt;');
		var nextChar = new RegExp('>','g');
		str = str.replace(nextChar, '&gt;');
		var newStr = str;
	}
	else
	{
		var escapes = {
			'"' : '&quot;',
			'<' : '&lt;',
			'>' : '&gt;'
		}
		var newStr = new String();
		STRING:
		for (var i = 0; i < str.length; i++) {
			var theChar = str.charAt(i);
			for (var j in escapes) {
				var esc = escapes[j];
				if (theChar == j) {
					newStr += esc;
					continue STRING;
				}
			}
			newStr += theChar;
		}
	}
	return newStr;
}

PTStringUtil.removeHTML = function(str)
{
	str = new String(str);
	while ((str.indexOf('<') > -1) && (str.indexOf('>') > str.indexOf('<')))
	{
		var start = str.indexOf('<');
		var end = str.indexOf('>');
		str = str.substr(0,start) + str.substring(end + 1,str.length);
	}
	return str;
}

PTStringUtil.escapeJS = function(str,useRegex)
{
	str = new String(str);
	if (document.getElementById)
	{
		var nextChar = new RegExp('\\\\','g');
		str = str.replace(nextChar, '\\\\');
		var nextChar = new RegExp('\n','g');
		str = str.replace(nextChar, '\\n');
		var nextChar = new RegExp('\'','g');
		str = str.replace(nextChar, '\\\'');
		var newStr = str;
	}
	else
	{
		var escapes = {
			'\n' : '\\n',
			'\'' : '\\\'',
			'\\' : '\\\\'
		}	
		var newStr = new String('');
		STRING:
		for (var i = 0; i < str.length; i++) {
			var theChar = str.charAt(i);
			for (var j in escapes) {
				var esc = escapes[j];
				if (theChar == j) {
					newStr += esc;
					continue STRING;
				}
			}
			newStr += theChar;
		}
	}
	return newStr;
}

PTStringUtil.encodeURL = function(str)
{
	if (str == null)
		return null;
	var theString = new String(str);
	var encoded = '';
	for (var i = 0; i < theString.length; i++ ) 
	{
		var theChar = theString.charAt(i);
		var charCode = theChar.charCodeAt(0);
		if(((charCode > 47)&&(charCode < 58))||
		   ((charCode > 64)&&(charCode < 91))||
		   ((charCode > 96)&&(charCode < 123)))
		{
			encoded += String.fromCharCode(charCode);
		}
		else if ((charCode <= 47)||
				 ((charCode >= 58)&&(charCode <= 64))||
				 ((charCode >= 91)&&(charCode <= 96))||
				 ((charCode >= 123)&&(charCode <= 127)))
		{
			var hex = charCode.toString(16);
			var len = hex.length;
			switch(len){
				case 0:
					hex = '00';
					break;
				case 1:
					hex = '0'+hex;
				case 2:
					break;
				defalt:
					hex = hex.substring((len-2), len);
					break;
			}
			encoded += '%'+hex;
		}
		else if ((charCode>127) && (charCode<2048))
		{
			encoded += '%' + ((charCode>>6)|192).toString(16).toUpperCase();
			encoded += '%' + ((charCode&63)|128).toString(16).toUpperCase();
		}
		else
		{
			var c1 = (charCode>>12)|224;
			var c2 = ((charCode>>6)&63)|128;
			var c3 = (charCode&63)|128;
			encoded += '%' + ((charCode>>12)|224).toString(16).toUpperCase();
			encoded += '%' + (((charCode>>6)&63)|128).toString(16).toUpperCase();
			encoded += '%' + ((charCode&63)|128).toString(16).toUpperCase();
		}
	}
	return encoded;
}

PTStringUtil.substituteChars = function(str,hash)
{
	str = new String(str);
	var newStr = new String();
	STRING:
	for (var i = 0; i < str.length; i++) {
		var theChar = str.charAt(i);
		for (var h in hash) {
			var subs = hash[h];
			if (theChar == h) {
				newStr += subs;
				continue STRING;
			}
		}
		newStr += theChar;
	}
	return newStr;
}

PTStringUtil.lineBreakToBR = function(str)
{
	str = new String(str);
	var br = /\n/g;
	str = str.replace(br,'<br>');
	return str;
}

function PTWindowUtil()
{
	return this;
}

PTWindowUtil.VERSION = '121140';
PTWindowUtil.defaultWidth = 650;
PTWindowUtil.defaultHeight = 450;
PTWindowUtil.helpWindowName = 'PTRoboHelp';
PTWindowUtil.openWindow = function(URL,name,height,width,isFullChrome)
{
	var isNN4 = (document.layers);
	if (!name) { name = 'PTWindow' + (new Date()).getTime(); }
	var winWidth = (width) ? width : PTWindowUtil.defaultWidth;
	var winHeight = (height) ? height : PTWindowUtil.defaultHeight;
	var scrWidth = (isNN4) ? screen.width : screen.availWidth;
	var scrHeight = (isNN4) ? screen.height : screen.availHeight;
	var leftPosVal = parseInt(scrWidth/2) - parseInt(winWidth/2);
	var topPosVal = parseInt(scrHeight/2) - parseInt(winHeight/2);
	var leftPos = (isNN4) ? 'screenX=' + leftPosVal : 'left=' + leftPosVal;
	var topPos = (isNN4) ? 'screenY=' + topPosVal : 'top=' + topPosVal;
	var winProps = 'width=' + winWidth + ',height=' + winHeight + ',' + leftPos + ',' + topPos + ',resizable=1';
	if (PTNumberUtil.isInteger(isFullChrome))
	{
		if (isFullChrome == 1) { winProps += ',scrollbars=1,status=0,toolbar=0,menubar=0,location=0'; }
	}
	else if (isFullChrome == true)
	{
		winProps += ',scrollbars=1,status=1,toolbar=1,menubar=1,location=1';
	}
	else
	{
		winProps += ',scrollbars=0,status=0,toolbar=0,menubar=0,location=0';
	}
	var winOpenedWindow = window.open(URL,name,winProps);
	winOpenedWindow.focus();
	return winOpenedWindow;
}

PTWindowUtil.openHelpWindow = function(URL,height,width,isFullChrome)
{
	return PTWindowUtil.openWindow(URL,PTWindowUtil.helpWindowName,height,width,isFullChrome);
}

function OpenSizedWindow(URL,name,height,width,isFullChrome)
{
	return PTWindowUtil.openWindow(URL,name,height,width,isFullChrome);
}
/**
 * PTDebugUtil
 * @author Legacy Code (Patrick Corcoran)
 * @lastmodified $DateTime: 2003/12/12 12:40:34 $
 * @lastmodifiedby $Author: PatrickC $
 * @version $Change: 120356 $
 */


/**
 * PTDebugUtil object constructor
 * @object
 */

function PTDebugUtil() {}

PTDebugUtil.debugWindow = false;
PTDebugUtil.debugCache = false;
PTDebugUtil.debugDeferred = false;

PTDebugUtil.debug = function(output,divName,color,doHTMLEscape)
{
	if (!PTCommonUtil.isDefined(window.PT_DEBUG) || !window.PT_DEBUG) { return; }
	
	if (!output) { output = ''; }
	if (!divName) { divName = 'debug'; }
	
	var div = document.getElementById(divName);
	
	if (!div)
	{
		if (!PTDebugUtil.debugCache) { PTDebugUtil.debugCache = new PTStringBuffer(); }
		PTDebugUtil.debugCache.append(output + '<br>');
		
		if (!PTDebugUtil.debugDeferred)
		{
			if (PTControls && !PTControls.onloadHandlerInitialized) { PTControls.prepareOnloadHandler(); }
			document.PCC.RegisterForWindowEvent('onload', 'new Function(\'PTDebugUtil.initDebug(\\\'' + divName + '\\\')\')');
			PTDebugUtil.debugDeferred = true;
		}
	}
	else
	{
		if (doHTMLEscape) { output = PTStringUtil.escapeHTML(output); }

		if (color) { output = '<font style="color:' + color + ';">' + output + '</font>'; }

		var spanid = '_debug_' + (new Date()).getTime() + '';
		output += '<span id="' + spanid + '"></span>';

		if (PTDebugUtil.debugCache)
		{
			output = PTDebugUtil.debugCache.toString() + output;
			PTDebugUtil.debugCache = false;
		}

		if (div.style.display == 'none') { div.style.display = 'block'; }
		div.innerHTML += output + '<br>';
	}
}

PTDebugUtil.initDebug = function(divName)
{
	if (!divName) { divName = 'debug'; }
	
	if (!document.getElementById(divName))
	{
		var newDiv = document.createElement('DIV');
		newDiv.className = 'PTFonts_9SystemBlack';
		newDiv.style.width = '100%';
		newDiv.style.backgroundColor = '#F5F5F5';
		newDiv.style.border = '1px solid black';
		newDiv.style.padding = '3px';
		newDiv.style.marginTop = '10px';
		newDiv.id = divName;
		document.body.appendChild(newDiv);
		div = newDiv;
		var version = (PTNumberUtil.isInteger(PTCommonUtil.VERSION)) ? 'v. ' + PTCommonUtil.VERSION : 'local build';
		div.innerHTML = PTDebugUtil.drawDebugControls();
		div.innerHTML += 'PTDebugUtil.js (' + version + ')<br>';
		div.innerHTML += 'PT_DEBUG = ' + PT_DEBUG + '<br>';
		div.innerHTML += '';
		if (document.all)
		{
			div.style.setExpression('display','(document.getElementById(\'debugLevelSelect\').selectedIndex = window.PT_DEBUG) ? \'block\' : \'none\'');
		}
		else
		{
			div.style.display = ((window.PT_DEBUG) ? 'block' : 'none');
		}
		
		PTDebugUtil.debug('Drawing debug DIV');
	}
}

PTDebugUtil.debug2 = function(output,divName,color,doHTMLEscape)
{
	if (!PTCommonUtil.isDefined(window.PT_DEBUG)) { return; }
	if (PT_DEBUG > 1) { PTDebugUtil.debug(output,divName,color,doHTMLEscape); }
}

PTDebugUtil.debug3 = function(output,divName,color,doHTMLEscape)
{
	if (!PTCommonUtil.isDefined(window.PT_DEBUG)) { return; }
	if (PT_DEBUG > 2) { PTDebugUtil.debug(output,divName,color,doHTMLEscape); }
}

PTDebugUtil.error = function(output,e)
{
	if (e && e.message)
	{
		PTDebugUtil.debug('<span style="color:red;">ERROR- ' + output + '</span> (' + e.message + ')');
	}
	else
	{
		PTDebugUtil.debug('<span style="color:red;">ERROR- ' + output + '</span>');
	}
}

PTDebugUtil.alert = function(msg)
{
	if (!PTCommonUtil.isDefined(window.PT_DEBUG)) { return; }
	alert(msg);
}

PTDebugUtil.clearDebug = function(divName)
{
	if (!PTCommonUtil.isDefined(window.PT_DEBUG)) { return; }
	if (!divName) { divName = 'debug'; }
	var div = document.getElementById(divName);
	if (div)	{ div.innerHTML = ''; }
	else		{ PTDebugUtil.debugWindow.document.body.innerHTML += ''; }
}

PTDebugUtil.inspectNum = 0;

PTDebugUtil.inspectObject = function(obj,name,disp,num)
{
	var sb = new PTStringBuffer();
	
	if (!disp)	{ disp = 'block'; }
	if (!num)	{ num = PTDebugUtil.inspectNum; }
	sb.append('<div id="debugDiv' + num + '" style="background-color:#F6F6FF;border:1px dotted #007;padding:10px;margin-bottom:5px;display:' + disp + ';">\n');

	if (!name)	{ name = ''; }
	else		{ name += ' - '; }
	var objText = obj;
	if (obj && obj.slice && obj.sort) { objText = 'Array'; }
	else if (obj.className) { objText = obj.className; }
	else if (obj.italics && obj.lastIndexOf) { objText = 'String'; }
	else if (objText == '[object Object]') { objText = 'Object'; }
	
	sb.append('<div style="font-weight:bold;background-color:white;font-size:15px;padding:5px;border:1px solid #BBB;">' + name + '<span style="color:salmon;">' + objText + '</span></div><br>');
	
	if (objText == 'String')
	{
		sb.append('<table border="0" cellpadding="0" cellspacing="0">\n<tr>\n<td>value<span style="color:#888;"> = ' + obj + '</span></td>\n</tr>\n</table>');
	}
	
	//if (obj && obj.slice && obj.sort && !obj.length) { obj = new Object(obj); }
	
	var data = new Object();
	for (var i in obj)
	{
		if (i == 'prototype') { continue; }
		if (i == 'className') { continue; }
		
		var prop = obj[i];
		var t = typeof(prop);
		if (!data[t]) { data[t] = new Array(); }
		data[t][i] = obj[i];
	}
	
	var typeList = new Array('object','string','number','boolean','function');
		
	for (var t = 0; t < typeList.length; t++)
	{
		var type = typeList[t];		
		if (!data[type]) { continue; }
		
		sb.append('<br><b>' + PTStringUtil.UCFirst(type) + 's:</b><br>');

		sb.append('<table border="0" cellpadding="0" cellspacing="0">\n');
		
		var typedItems = PTCommonUtil.sortHashByKeys(data[type],false,true,false);
		
		for (var itm in typedItems)
		{
			if ((itm == 'isArray') || (itm == 'itemValidation')) { continue; }
			if ((itm == 'xml') || (itm == 'xmlStack')) { continue; }
			if (itm == 'className') { continue; }
			
			sb.append('<tr>\n<td style="padding-right:5px;" valign="top">');
			
			if (itm == 'parent')
			{
				sb.append('parent<br>\n');
			}
			else if ((type == 'string') || (type == 'number') || (type == 'boolean'))
			{
				
				var val = obj[itm];
				if ((itm == 'responseText') || (itm == 'innerHTML'))
				{
					val = '<pre style="font-size:12px;color:#911;">\n' + PTStringUtil.escapeHTML(val) + '</pre>\n';
				}
				itm += '</td><td valign="top"><span style="color:#888;"> = ' + val + '</span>';
				sb.append(itm + '<br>\n');
				
			}
			else if (type == 'object')
			{
				PTDebugUtil.inspectNum++;
				sb.append('<a href="#" onclick="PTDebugUtil.inspectObjectToggle(this,\'debugDiv' + PTDebugUtil.inspectNum + '\'); return false" style="color:#007;">' + itm + '</a><br>\n');
				if (!obj[itm].className || (obj[itm].className != 'PTMenu'))
				{
					sb.append(PTDebugUtil.inspectObject(obj[itm],itm,'none',PTDebugUtil.inspectNum));
				}
			}
			else if (type == 'function')
			{
				if (obj && obj[itm] && obj[itm].length) {
					sb.append(itm + ' <span style="color:#888;">(' + obj[itm].length + ' arguments)</span><br>\n');
				} else {
					sb.append(itm + '<br>\n');
				}
			}
			else
			{
				sb.append(itm + '<br>\n');
			}
			
			sb.append('</td></tr>\n');
		}

		sb.append('</table>\n');
	}
	
	if (obj['xml'] && !obj['xmlStack'])
	{
		sb.append(PTDebugUtil.formatXML(obj['xml']));
	}
	else if (obj['xmlStack'])
	{
		for (var x = 0; x < obj['xmlStack'].length; x++)
		{
			var xml = obj['xmlStack'][x];
			sb.append(PTDebugUtil.formatXML(xml,'XML #' + (x + 1)));
		}
	}
	
	sb.append('</div>\n');
	
	return sb.toString();
}

PTDebugUtil.inspectObjectToggle = function(obj,id)
{
	var block = document.getElementById(id);
	if (!block) { return; }
	if (block.style.display == 'none')
	{
		block.style.display = 'block';
		obj.style.backgroundColor = '#007';
		obj.style.color = 'white';
		obj.style.padding = '0px 4px';
		obj.style.textDecoration = 'none';
	}
	else
	{
		block.style.display = 'none';
		obj.style.backgroundColor = '';
		obj.style.color = '#007';
		obj.style.padding = '0';
		obj.style.textDecoration = 'underline';
	}
}

PTDebugUtil.formatXML = function(xml,title)
{
	if (!title) { title = 'XML'; }
	var xmls = '<br><b>' + title + ':</b><br><textarea style="width:90%;height:100px;overflow:auto;background-color:white;" ondblclick="this.style.overflow = (this.style.overflow != \'visible\') ? \'visible\' : \'auto\';event.cancelBubble=true;" title="Double-Click to Expand">' + xml + '</textarea>\n';
	return xmls;
}

PTDebugUtil.perfCounters = new Object();
PTDebugUtil.perfStart = false;

PTDebugUtil.perfStack = new Object();
PTDebugUtil.perfStack.parent = PTDebugUtil.perfStack;
PTDebugUtil.perfStack.calls = new Array();
PTDebugUtil.stackPointer = PTDebugUtil.perfStack;

PTDebugUtil.debugPerfStart = function(eventText,restart)
{
	if (!window.PT_DEBUG || (window.PT_DEBUG < 2)) { return; }
	
	if (!PTDebugUtil.perfStart)
	{
		PTDebugUtil.perfStart = (new Date()).getTime();
	}
	if (!PTDebugUtil.perfCounters[eventText] || restart)
	{
		PTDebugUtil.perfCounters[eventText] = new Array();
	}
	var obj = PTDebugUtil.perfCounters[eventText];
	var idx = obj.length;
	obj[idx] = new Object();
	obj[idx].text = eventText;
	obj[idx].startTime = (new Date()).getTime();
	
	var obj = PTDebugUtil.stackPointer.calls[PTDebugUtil.stackPointer.calls.length] = new Object();
	obj.calls = new Array();
	obj.parent = PTDebugUtil.stackPointer;
	obj.startTime = (new Date()).getTime();
	obj.method = eventText;
	
	PTDebugUtil.stackPointer = obj;
}

PTDebugUtil.debugPerfEnd = function(eventText,index)
{
	if (!window.PT_DEBUG || (window.PT_DEBUG < 2)) { return; }
	
	var obj = PTDebugUtil.perfCounters[eventText];
	if (!obj)
	{
		obj = PTDebugUtil.perfCounters[eventText] = new Array();
		var idx = 0;
		obj[idx] = new Object();
		obj[idx].text = eventText;
	}
	else
	{
		if (index) { var idx = index; }
		else { var idx = obj.length - 1; }
	}

	obj[idx].endTime = (new Date()).getTime();
	
	var obj = PTDebugUtil.stackPointer;
	if (!obj.method)
	{
		PTDebugUtil.debug2('debugPerfEnd: ' + eventText + ' has no matching starting event.');
	}
	else if (obj.method != eventText)
	{
		PTDebugUtil.debug2('debugPerfEnd: ' + eventText + ' does not match with start method = ' + obj.method);
	}
	obj.endTime = (new Date()).getTime();
	if (!obj.startTime)
	{
		obj.time = false;
	}
	else
	{
		obj.time = obj.endTime - obj.startTime;
	}
	
	PTDebugUtil.stackPointer = obj.parent;
}

PTDebugUtil.debugOutputPerf = function()
{
	if (!window.PT_DEBUG || (window.PT_DEBUG < 2)) { return; }

	PTDebugUtil.stackTrace = PTDebugUtil.analyzePerf();
	
	var text = '';
	
	var numEvents = 0;
	for (counter in PTDebugUtil.perfCounters)
	{
		for (var evt = 0; evt < PTDebugUtil.perfCounters[counter].length; evt++) { numEvents++; }
	}

	var startTime = PTDebugUtil.perfStart;
	var endTime = (new Date()).getTime();
	var totalTime = (endTime - startTime) / 1000;
	
	text += '<div style="padding:10px;">\n';
	
	text += '<h5>Performance Summary:</h5>\n';
	
	text += '<table style="border:1px solid #036;font-size:9px;" cellpadding="3" cellspacing="0"><tr>\n';
	text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Event</b></td>\n';
	text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Time (seconds)</b></td>\n';
	text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>% of Total</b></td>\n';
	text += '</tr>\n';
	
	var e = 0;
	for (counter in PTDebugUtil.perfCounters)
	{
		var eventTime = 0;
		var eventFreq = 0;
		
		for (var i = 0; i < PTDebugUtil.perfCounters[counter].length; i++)
		{
			var stageStart = PTDebugUtil.perfCounters[counter][i].startTime;
			var stageEnd = PTDebugUtil.perfCounters[counter][i].endTime;
			eventTime += Math.round(((stageEnd - stageStart) / 1000) * 1000) / 1000;
			eventFreq++;
			e++;
		}
		eventTime = Math.round(eventTime * 1000) / 1000;
		var stagePct = (Math.floor((eventTime / totalTime) * 1000)) / 10;
		if (isNaN(eventTime))	{ eventTime = '<span style="color:#69A">n/a</span>'; }
		if (isNaN(stagePct))	{ stagePct = '<span style="color:#69A">n/a</span>'; }

		var style = ' style="background-color:#EED;border-bottom:1px dotted #BBA;padding:2px 8px;"';
		if (e == numEvents) { style = ' style="background-color:#EED;border-bottom:1px solid #036;padding:2px 8px;"'; }

		var evtText = counter;
		if (eventFreq > 1) { evtText += ' (<b>' + eventFreq + '</b> executions)'; }

		text += '<tr>\n';
		text += '<td' + style + '>' + evtText + '</td>\n';
		text += '<td' + style + '>' + eventTime + '</td>\n';
		text += '<td' + style + '>' + stagePct + '</td>\n';
		text += '</tr>\n';
	}
	
	text += '</tr>\n';
	text += '<td colspan="3" align="right"><a href="#" onclick="var w = window.open();w.document.open();w.document.write(PTDebugUtil.stackTrace);w.document.close();return false">Stack Trace Time Analysis</a></td>\n';
	text += '</tr>\n';

	text += '</table>\n</div>\n';
	
	if (PTDebugUtil.count)
	{
		text += '<br>\n';

		text += '<div style="padding:10px;">\n';
	
		text += '<h5>Count Summary:</h5>\n';
		
		text += '<table style="border:1px solid #036;font-size:9px;" cellpadding="3" cellspacing="0"><tr>\n';
		text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Item</b></td>\n';
		text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Number</b></td>\n';
		text += '</tr>\n';
	
		for (var counter in PTDebugUtil.count)
		{
			var count = PTDebugUtil.count[counter];
			
			var style = ' style="background-color:#EED;border-bottom:1px dotted #BBA;padding:2px 8px;"';

			text += '<tr>\n';
			text += '<td' + style + '>' + counter + '</td>\n';
			text += '<td' + style + '>' + count + '</td>\n';
			text += '</tr>\n';
		}
		
		text += '<tr>\n';
		text += '<td style="background-color:#EED;padding:2px 8px;"><b>&nbsp;</b></td>\n';
		text += '<td style="background-color:#EED;padding:2px 8px;"><b>&nbsp;</b></td>\n';
		text += '</tr>\n';
		
		text += '</table>\n</div>\n';
	}
	
	PTDebugUtil.debug(text);
	PTDebugUtil.debug('PTDebugUtil.debugOutputPerf: Number of Events: ' + numEvents);

	PTDebugUtil.perfCounters = new Object(); 
	PTDebugUtil.perfStart = false;
	
	PTDebugUtil.perfStack = new Object();
	PTDebugUtil.perfStack.parent = PTDebugUtil.perfStack;
	PTDebugUtil.perfStack.calls = new Array();
	PTDebugUtil.stackPointer = PTDebugUtil.perfStack;
}

PTDebugUtil.analyzePerf = function()
{
	var sb = new PTStringBuffer();
	sb.append('<html>\n<body>\n');
	sb.append('<script language="javascript">\n');
	sb.append('function toggleXMLNode(id) {\n');
	sb.append('var div = document.all[id];\n');
	sb.append('var span = document.all[id + \'_s\'];\n');
	sb.append('if (div.style.display == \'none\') { div.style.display = \'block\'; span.innerHTML = \'&#054;\' } else { div.style.display = \'none\'; span.innerHTML = \'&#052;\'  }\n');
	sb.append('}\n');
	sb.append('</scr' + 'ipt>\n');
	sb.append('<div style="font-family:tahoma;font-size:11px;cursor:default;">\n');
	sb.append('<h4>Stack Trace Time Analysis</h4>\n');

	for (var c in PTDebugUtil.perfStack.calls)
	{
		var obj = PTDebugUtil.perfStack.calls[c];
		sb.append(PTDebugUtil.analyzePerfObject(obj,0));
	}
	
	sb.append('</div>\n</body></html>');

	return sb.toString();
}

PTDebugUtil.analyzePerfObject = function(obj,level)
{
	var sb = new PTStringBuffer();
	
	var pad = '';
	for (var i = 0; i < level; i++)
	{
		pad += '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
	}
	if (obj.method)
	{
		var link = '';
		if (obj.calls.length > 0)
		{
			var linkid = 'xmlnode' + PTDebugUtil.perfNodeNum++;
			var chr = ((level >= 0) ? '&#052;' : '&#054;');
			var link = '<span id="' + linkid + '_s" style="font-weight:bold;font-family:webdings;font-size:14px;color:#BB2;cursor:hand;padding:3px;" onclick="toggleXMLNode(\'' + linkid + '\')">' + chr + '</span>';
		}
		else
		{
			var link = '<span style="font-weight:bold;font-family:webdings;font-size:14px;padding:3px;">&nbsp;&nbsp;</span>';
		}
		sb.append(pad + link + '<span style="color:#333;">' + obj.method + '</span> - <span style="font-weight:bold;">' + obj.time + '</span> ms<br>\n');
	}

	var disp = ((level >= 0) ? 'none' : 'block');
	sb.append('<div id="' + linkid + '" style="display:' + disp + ';">');
	for (var c = 0; c < obj.calls.length; c++)
	{
		var childObj = obj.calls[c];
		sb.append(PTDebugUtil.analyzePerfObject(childObj,(level + 1)));
	}
	sb.append('</div>\n');
	
	return sb.toString();
}

PTDebugUtil.perfNodeNum = 0;
PTDebugUtil.count = false;

PTDebugUtil.addCount = function(countName)
{
	if (!PTDebugUtil.count) { PTDebugUtil.count = new Object(); }
	if (!PTDebugUtil.count[countName]) { PTDebugUtil.count[countName] = 0; }
	PTDebugUtil.count[countName]++;
}

PTDebugUtil.registerGlobalObject = function(objName)
{
	if (!PTDebugUtil.globalObjects)
	{
		PTDebugUtil.globalObjects = new Object();
	}
	PTDebugUtil.globalObjects[objName] = eval(objName);
	PTDebugUtil.initGlobalObjectControls();
}

PTDebugUtil.initGlobalObjectControls = function()
{
	var objSel = document.getElementById('debugObjectSelect');
	if (objSel)
	{
		ADD_LOOP:
		for (var i in PTDebugUtil.globalObjects)
		{
			for (var j = (objSel.options.length - 1); j >= 0; j--)
			{
				if (objSel.options[j].text == i) { continue ADD_LOOP; }
			}
			objSel.options[objSel.options.length] = new Option(i,i);
		}
	}
	
	var lvlSel = document.getElementById('debugLevelSelect');
	if (lvlSel)
	{
		if (PTNumberUtil.isInteger(PT_DEBUG))
		{
			lvlSel.selectedIndex = PT_DEBUG;
		}
	}
}

PTDebugUtil.executeGlobalAction = function()
{
	var objSel = document.getElementById('debugObjectSelect');
	var actSel = document.getElementById('debugActionSelect');
	if (!objSel || !actSel) { return; }
	
	var objName = objSel.options[objSel.selectedIndex].value;
	var action = parseInt(actSel.options[actSel.selectedIndex].value);
	
	var obj = eval(objName);
	if (!obj) { PTDebugUtil.error('PTDebugUtil.executeGlobalAction: No object ' + objName); return; }
		
	if (action == 1)
	{
		if (!obj.xml) { PTDebugUtil.debug('<br><b>' + objName + ' XML:</b>' + obj.xml); }
		else
		{
			PTDebugUtil.debug(PTDebugUtil.formatXML(eval(objName).xml,objName));
		}
	}
	else if (action == 2)
	{
		PTDebugUtil.debug(PTDebugUtil.inspectObject(obj,objName));
	}
	else if (action == 3)
	{
		obj.reload();
	}
	else if (action == 4)
	{
		obj.draw();
	}
}

PTDebugUtil.drawDebugControls = function()
{
	var sb = new PTStringBuffer();

	sb.append('<div style="background-color:white;padding:9px;margin:7px 2px;border:1px solid black;display:expression(window.PT_DEBUG ? \'block\' : \'none\');">');
	sb.append('<nobr>');

	sb.append('<div style="font-family:tahoma;font-weight:bold;font-size:9px;padding:2px;display:inline;width:85%;color:black;">');
	sb.append('<input value="ptExplorer" id="evalThis" type="text" size="25" align="absmiddle" style="font-family:\'courier new\';font-size:10pt;" onkeyup="this.size = (Math.max(this.value.length+5,25))"> ');
	sb.append('&nbsp;<input type="button" value=" EVAL " onclick="var val = document.getElementById(\'evalThis\').value;PTDebugUtil.debug(val + \' = \' + eval(val))" align="absmiddle"> ');
	sb.append('&nbsp;');

	sb.append('&nbsp;&nbsp;');

	sb.append('<select id="debugObjectSelect" style="font-size:10px;background-color:#DDF;" align="absmiddle"></select>');
	sb.append('<select id="debugActionSelect" style="font-size:10px;background-color:#DDF;" align="absmiddle">');
	sb.append('<option value="2">Inspect Object</option>');
	sb.append('<option value="1">View Latest XML</option>');
	sb.append('<option value="3">.reload()</option>');
	sb.append('<option value="4">.draw()</option>');
	sb.append('</select>');
	sb.append('&nbsp;<input type="button" value=" DO " onclick="PTDebugUtil.executeGlobalAction()" align="absmiddle"> ');
	sb.append('&nbsp;<input type="button" value=" PERF " onclick="PTDebugUtil.debugOutputPerf()" align="absmiddle"> ');
	sb.append('&nbsp;');

	sb.append('</div>');

	sb.append('<div style="font-family:verdana;font-weight:bold;font-size:9px;padding:2px;display:inline;width:15%;color:black;" align="right">');
	sb.append('PT_DEBUG=<select id="debugLevelSelect" style="font-size:10px;background-color:#DDF;" align="absmiddle" onchange="PT_DEBUG=this.selectedIndex">');
	sb.append('<option>0</option>');
	sb.append('<option>1</option>');
	sb.append('<option>2</option>');
	sb.append('<option>3</option>');
	sb.append('</select>');
	sb.append('</div>');
	sb.append('</nobr>');
	sb.append('</div>');
	
	return sb.toString();
}

// Test objects and methods

PTDebugUtil.watch = function(watchKey, watchValue)
{
	if (!PTTestCase.current || !PTCommonUtil.isDefined(window.PTTestCaseWatches) || !window.PTTestCaseWatches[watchKey]) 
	{ 
		return; 
	}
	// get the watch
	var watch = window.PTTestCaseWatches[watchKey];
	// call the assertion
	watch.assertion(watchKey, watchValue, watch.arg1, watch.arg2, watch.arg3);	
	watch.hitCount++;
}

/**
 * PTTestCase object constructor
 * @object
 */
 
function PTTestCase(name) 
{
	// name
	this.name					= name;
	
	// timers
	this.startTime 				= new Date();
	this.endTime				= null;
	
	// logging
	this.watches				= new Array();
}

PTTestCase.current = null;

PTTestCase.load = function(testCaseFileURL)
{
	// load the test case file
	PTDebugUtil.debug('Loading test case file: ' + testCaseFileURL);
	var e = document.createElement('script');
   	e.src = testCaseFileURL;
   	e.type='text/javascript';
   	document.getElementsByTagName('head')[0].appendChild(e); 
}

PTTestCase.init = function(testCaseName)
{   	
	PTDebugUtil.debug('Initializing test case: ' + testCaseName);
	PTTestCase.current = new PTTestCase(testCaseName);
}

PTTestCase.watchSuccess = function(watchKey, assertion, message)
{
	// PTDebugUtil.debug('PTTestCase.watchSuccess: ' + watchKey + ' : ' + assertion + ' : ' + message);
	PTTestCase.current.watches[PTTestCase.current.watches.length] = {'watchKey' : watchKey, 'assertion' : assertion, 'message' : message, 'success' : true};
}

PTTestCase.watchFailure = function(watchKey, assertion, message)
{
	// PTDebugUtil.debug('PTTestCase.watchFailure: ' + watchKey + ' : ' + assertion + ' : ' + message);
	PTTestCase.current.watches[PTTestCase.current.watches.length] = {'watchKey' : watchKey, 'assertion' : assertion, 'message' : message, 'success' : false};
}

PTTestCase.end = function()
{
	var testCase = PTTestCase.current;
	var success = true;
	
	testCase.endTime = new Date();
	var testTime = testCase.endTime.getTime() - testCase.startTime.getTime();
	
	var text = '';		

	text += '<div style="padding:10px;">\n';	
	text += '<h5>Test Case:' + PTTestCase.current.name + '</h5>\n';
	
	text += '<table style="border:1px solid #036;font-size:9px;" cellpadding="3" cellspacing="0"><tr>\n';
	text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Watch</b></td>\n';
	text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Assertion</b></td>\n';
	text += '<td style="background-color:white;border-bottom:1px solid #036;padding:2px 8px;"><b>Result</b></td>\n';
	text += '</tr>\n';

	var successCount = 0;
	var failureCount = 0;
	
	for (var i=0; i<testCase.watches.length; i++)
	{
		var watch = testCase.watches[i];

		var style = ' style="background-color:#EED;border-bottom:1px dotted #BBA;padding:2px 8px;"';
		if (i == (testCase.watches.length - 1)) { style = ' style="background-color:#EED;border-bottom:1px solid #036;padding:2px 8px;"'; }

		var result;
		if (watch.success)
		{
			successCount++;
			result = '<span style="color:green">SUCCEEDED:</span>';
		}
		else
		{
			failureCount++;
			success = false;
			result = '<span style="color:red">FAILED:</span>';
		}
		if(watch.message.length > 50)
			watch.message = watch.message.substring(0,50) + "...";
		result += '&nbsp;' + PTStringUtil.escapeHTML(watch.message);

		text += '<tr valign="top">\n';
		text += '<td' + style + '>' + watch.watchKey + '</td>\n';
		text += '<td' + style + '>' + watch.assertion + '</td>\n';
		text += '<td' + style + '>' + result + '</td>\n';
		text += '</tr>\n';
	}

	var checkCount = successCount + failureCount;
	var missCount = 0;
	for (var watch in PTTestCaseWatches)
	{
		if (watch.hitCount == 0) { misCount++; }
	}
	if(missCount > 0)
		success = false;
	if((successCount == 0) && (failureCount == 0) && (missCount == 0))
		success = false;
	
	var successPct = (checkCount > 0) ? (100 * successCount / checkCount) : 0;
	var failurePct = (checkCount > 0) ? (100 * failureCount / checkCount) : 0;
	var missPct = (checkCount > 0) ? (100 * missCount / checkCount) : 0;
	
	text += '<tr>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>Total</b></td>\n';
	text += '<td align="right" style="background-color:#EED;padding:2px 8px;"><b>Successes</b></td>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>'+successCount+'</b>&nbsp;('+successPct+'%)</td>\n';
	text += '</tr>\n';
	text += '<tr>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;">&nbsp;</td>\n';
	text += '<td align="right" style="background-color:#EED;padding:2px 8px;"><b>Failures</b></td>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>'+failureCount+'</b>&nbsp;('+failurePct+'%)</td>\n';
	text += '</tr>\n';
	text += '<tr>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>&nbsp;</b></td>\n';
	text += '<td align="right" style="background-color:#EED;padding:2px 8px;"><b>Misses</b></td>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>'+missCount+'</b>&nbsp;('+missPct+'%)</td>\n';
	text += '</tr>\n';
	text += '<tr>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>&nbsp;</b></td>\n';
	text += '<td align="right" style="background-color:#EED;padding:2px 8px;"><b>Time</b></td>\n';
	text += '<td style="background-color:#EED;padding:2px 8px;"><b>'+testTime+' ms</b></td>\n';
	text += '</tr>\n';

	text += '</table>\n</div>\n';

	PTDebugUtil.debug(text);
	PTTestLog.append(text);
	PTTestLog.appendSummary(testCase.name, testTime, success);
	
	PTTestCase.current = null;
}

/**
 * PTTestCaseWatch object constructor
 */
function PTTestCaseWatch(assertion)
{
	this.assertion			= assertion;
	this.arg1			= PTTestCaseWatch.arguments[1];
	this.arg2			= PTTestCaseWatch.arguments[2];
	this.arg3			= PTTestCaseWatch.arguments[3];
	
	this.hitCount			= 0;
}

/**
 * PTTestAssertion object constructor
 */
function PTTestAssertion() {}

PTTestAssertion.equals = function(watchKey, watchValue, expectedValue)
{
	if (watchValue == expectedValue)
	{
		PTTestCase.watchSuccess(watchKey,'PTTestAssertion.equals', watchValue + ' == ' + expectedValue);
	}
	else
	{
		PTTestCase.watchFailure(watchKey,'PTTestAssertion.equals', 'Expected ' + expectedValue + ' but got ' + watchValue);
	}
}

PTTestAssertion.notEquals = function(watchKey, watchValue, expectedValue)
{
	if (watchValue != expectedValue)
	{
		PTTestCase.watchSuccess(watchKey,'PTTestAssertion.notEquals', watchValue + ' != ' + expectedValue);
	}
	else
	{
		PTTestCase.watchFailure(watchKey,'PTTestAssertion.notEquals', watchValue + ' == ' + expectedValue);
	}
}

PTTestAssertion.isDefined = function(watchKey, watchValue)
{
	if (PTCommonUtil.isDefined(watchValue))
	{
		PTTestCase.watchSuccess(watchKey,'PTTestAssertion.isDefined', watchValue + ' defined.');
	}
	else
	{
		PTTestCase.watchFailure(watchKey,'PTTestAssertion.isDefined', watchValue + ' undefined.');
	}
}


/**
 * PTTestLog singleton constructor
 */
function PTTestLog(suite, form)
{
	this.testsuite = suite;
	this.testresults = new Array();
	this.formname = form;
	this.forceCloseTimeoutId = null;
}

PTTestLog.logger = null;

PTTestLog.open = function(testsuite, formname, timeout)
{
	PTTestLog.logger = new PTTestLog(testsuite, formname);
	window.onunload=PTTestLog.forceClose;
	// timeout after 1 hour
	PTTestLog.logger.forceCloseTimeoutId = window.setTimeout(PTTestLog.forceClose, ((timeout) ? timeout : 3600000));
	var form = null;
	if(PTTestLog.logger.formname)
		form = document.getElementById(PTTestLog.logger.formname);
	else if(document.forms.length > 0)
		form = document.forms[0];
	if(form)
	{
		var logdiv = document.createElement('div');
		logdiv.id='PTTestLog_container';
		logdiv.style.display = 'none';
		text = '';
		text += '<textarea id="PTTestLog_log" name="PTTestLog_log" style="display: none"></textarea>\n';
		if(PTTestLog.logger.testsuite)
		{
			text += '<input style="display: none" type="hidden" id="PTTestLog_testsuite" name="PTTestLog_testsuite" value="';
			text += PTTestLog.logger.testsuite + '"/>\n';
			text += '<input style="display: none" type="hidden" id="PTTestLog_JSControlsVersion" ';
			text += 'name="PTTestLog_JSControlsVersion" value="' + PTControls.VERSION + '"/>\n';
			text += '<input style="display: none" type="hidden" id="PTTestLog_JSUtilVersion" ';
			text += 'name="PTTestLog_JSUtilVersion" value="' + PTCommonUtil.VERSION + '"/>\n';
			text += '<input style="display: none" type="hidden" id="PTTestLog_JSXMLVersion" ';
			text += 'name="PTTestLog_JSXMLVersion" value="' + PTXMLWrapper.VERSION + '"/>\n';
		}
		logdiv.innerHTML = text;
		form.appendChild(logdiv);
	}
}

PTTestLog.append = function(text)
{
	if(window.PT_TESTLOG && PTTestLog.logger)
	{
		var textarea = document.getElementById('PTTestLog_log');
		if(textarea)
		{
			textarea.value += text;
		}
	}
}


PTTestLog.appendSummary = function(testcasename, testtime, testresult)
{
	if(window.PT_TESTLOG && PTTestLog.logger)
	{
		var logdiv = document.getElementById('PTTestLog_container');
		if(logdiv)
		{
			var text = '<input  style="display: none" type="hidden" id="PTTestLog_time" name="PTTestLog_time_' + testcasename;
			text += '" value="' + testtime + '"/>\n';
			text += '<input  style="display: none" type="hidden" id="PTTestLog_result" name="PTTestLog_result_';
			text += testcasename + '" value="' + testresult + '"/>\n\n';
			logdiv.innerHTML += text;
		}
	}
}

PTTestLog.close = function()
{
	if(!PTTestLog.logger)
	{
		PTDebugUtil.debug('PTTestLog.init(form, logtextarea, summarytextarea) must be called before ending a test suite.', null, 'red');
		return;
	}
	if(window.PT_TESTLOG == 0)
		return;
		
	var aform = null;
	if(PTTestLog.logger.formname)
		aform = document.getElementById(PTTestLog.logger.formname);
	else if(document.forms.length > 0)
		aform = document.forms[0];
		
	if(PTTestLog.logger.forceCloseTimeoutId)
		window.clearTimeout(PTTestLog.logger.forceCloseTimeoutId);
	PTTestLog.logger = null;
	window.onunload=null;
	if(aform)
	{
		aform.submit();
	}
}

PTTestLog.forceClose = function()
{
	if(PTTestLog.logger)
	{			
		var aform = null;
		if(PTTestLog.logger.formname)
			aform = document.getElementById(PTTestLog.logger.formname);
		else if(document.forms.length > 0)
			aform = document.forms[0];
		if(PTTestLog.logger.forceCloseTimeoutId)
			window.clearTimeout(PTTestLog.logger.forceCloseTimeoutId);
		PTTestLog.logger = null;
		window.onunload=null;
		if(aform)
		{
			var win = window.open();
			win.document.write('<html>\n<head><title>PTTestLog.forceClose</title></head>\n<body>\n');
			win.document.write('<form name="PTTestLog_forceClose" action="' + aform.action + '" method="POST">\n');
			win.document.write(aform.innerHTML);
			win.document.write('<input type="text" name="PTTestLog_error" value="PTTestLog was not closed properly"/>\n');
			win.document.write('\n</form>\n');
			win.document.write('<script type="text/javascript">document.PTTestLog_forceClose.submit();</script>\n');
			win.document.write('</body>\n</html>');
		}
	}
}
