﻿DebtX = {
			Formatting: {
			Numeric: function() {
			
		this.Format = function(Value, Precision, ThousandsSeparator, DecimalSymbol) {
			
		if (ThousandsSeparator == null) ThousandsSeparator = ",";
	
		if (DecimalSymbol == null) DecimalSymbol = ".";
	
					Value = Value.toString();
					if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
					
					var DecimalPos = Value.lastIndexOf(".");
					var WholeDigits, Decimals, Negative;
					
					if(DecimalPos != -1) {
						if(!isNaN(parseInt(Precision))) {
							Value = (Math.round(parseFloat(Value) * Math.pow(10, Precision)) / Math.pow(10, Precision)).toString();
							DecimalPos = Value.lastIndexOf(".");
						}
					}
					if(DecimalPos == -1) {
						Decimals = "";
						WholeDigits = Value;
					}
					else {
						WholeDigits = Value.substring(0, DecimalPos);
						Decimals = Value.substring(DecimalPos + 1, Value.length);
					}
					if(!isNaN(parseInt(Precision))) {
						for (var i = Decimals.length; i < Precision; i++) {
							Decimals += "0";
						}
					}
					if(Decimals.length > 0) {
						Decimals = DecimalSymbol + Decimals;
					}
					Negative = (parseFloat(Value) < 0);
					WholeDigits = WholeDigits.replace(/\-/g, "");
					
					for (var i = 0; i < Math.floor((WholeDigits.length-(1+i))/3); i++) {
						WholeDigits = WholeDigits.substring(0, WholeDigits.length-(4*i+3))+ ThousandsSeparator + WholeDigits.substring(WholeDigits.length-(4*i+3));
					}
					if (Negative) WholeDigits = "-" + WholeDigits;
					if (isNaN(parseInt(WholeDigits))) WholeDigits = "0";
					return(WholeDigits + Decimals);
				
		};
	
		this.Unformat = function(Value, DecimalSymbol) {
			
		if (DecimalSymbol == null) DecimalSymbol = ".";
	
					Value = Value.toString();
					if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
					
					var re = new RegExp("[^-0123456789\\" + DecimalSymbol + "]", "g");
					
					Value = Value.replace(re, "").replace(DecimalSymbol, ".");
					
					// Screen out all hyphens except for the leading one (indicating a negative number).
					var re_allHyphen = new RegExp('[-]', 'g');
					var Sign = Value.substr(0, 1);
					return(Sign == '-' ? Sign : '') + Value.replace(re_allHyphen, '');
				
		};
	
		}, Currency: function() {
			
		this.Currencies = {};
	
		this.Format = function(Value, CurrencyCode, Precision, IncludeCode, ForceCode) {
			
		if (CurrencyCode == null) CurrencyCode = "Generic";
	
					var CurrencyFormatter = this.GetCurrencyFormatter(CurrencyCode);
					return CurrencyFormatter.Format(Value, Precision, IncludeCode, ForceCode);
				
		};
	
		this.Unformat = function(Value, CurrencyCode) {
			
		if (CurrencyCode == null) CurrencyCode = "Generic";
	
					var CurrencyFormatter = this.GetCurrencyFormatter(CurrencyCode);
					return CurrencyFormatter.Unformat(Value);
				
		};
	
		this.GetCurrencyFormatter = function(CurrencyCode) {
			
		if (CurrencyCode == null) CurrencyCode = "Generic";
	
					var obj = null, cachedObjectRetrieved;
					
					try {
						// Try to get the object from cache.
						obj = this.Currencies[CurrencyCode];
						
						if (obj == null) {
							
								obj = new DebtX.Formatting.Currencies[CurrencyCode]();
							
							
							this.Currencies[CurrencyCode] = obj;
						}
					}
					catch (e) {
						// An error most likely occurred because of an empty or invalid currency code. 
						// Use generic currency formatter.
						obj = new DebtX.Formatting.Currencies.Generic();
					}
					
					return(obj);
				
		};
	
		}, FullDateTime: function() {
			
		this.DefaultFormatString = "%Y-%M-%D  %i:%N %p";
	
		this.Format = function(Value, FormatString) {
			
					var checkValue = Value.toString();
					if(checkValue.toUpperCase() == "NAV" || checkValue.toUpperCase() == "NAP" || checkValue == "") return(checkValue.toUpperCase());
					if (typeof(Value) != 'Date') Value = new Date(Date.parse(Value.toString()));
					
					if(isNaN(Value)) {
						//If it's not a valid date, but it contains a colon, then it might be a simple time string.
						//JScript can't parse a standalone time string.  It needs a date, so just give it today's date.
						if(checkValue.indexOf(":") != -1) {
							var CurrentDate = new Date();
							var DateString = CurrentDate.getYear() + "/" + CurrentDate.getMonth() + 1 + "/" + CurrentDate.getDate();
							// Do a little processing to the time string, to make it easier to input (allows "a" or "p" to be used as shorthand for AM and PM respectively).
							var TimeString = checkValue.replace(/(([ap])m?)/gi, "$2m");
							var DateTimeString = DateString + " " + TimeString;
							Value = new Date(DateTimeString);
						}
					}
					
					if(isNaN(Value) && checkValue != null) {
						// If it's still not a valid date, it might be plain YYYY-MM-DD format
						var matches = checkValue.match(/(\d{4})-(\d{1,2})-(\d{1,2})/);
						if (matches != null) {
							Value = new Date(matches[2] + "/" + matches[3] + "/" + matches[1]);
						}
					}
					
					if(isNaN(Value)) {
						// If we still can't figure it out, then just return whatever string was passed in.
						return(checkValue);
					}
					
					// Lastly, check if the user entered a two-digit year, and perform Y2K adjustments.
					var year = Value.getFullYear();
					if(checkValue.indexOf(year) == -1) {
						year -= 1900;
						if(year >= 50) 
							Value.setYear(year + 1900);
						else
							Value.setYear(year + 2000);
					}
					
					var FinalValue = '', Pos, CodeChar;
					
					if (FormatString == null) FormatString = this.DefaultFormatString;
					
					while (FormatString.length > 0) {
						// Get everything before next format code.
						Pos = FormatString.indexOf('%');
						
						if (Pos > -1) {
							// Format code found. Move everything before the '%' into the final string.
							if (Pos > 0) FinalValue += FormatString.substr(0, Pos);
							
							// Pop the code char.
							CodeChar = FormatString.substr(Pos + 1, 1);
							
							FormatString = FormatString.substr(Pos + 2);
							
							// Translate format code into value;
							switch(CodeChar) {
								case 'Y':
									FinalValue += Value.getFullYear();
									break;
								
								case 'M':
									var month = Value.getMonth();
									FinalValue += (month < 9 ? "0" : "") + (month + 1);
									break;
								
								case 'D':
									var day = Value.getDate();
									FinalValue += (day < 10 ? "0" : "") + day;
									break;
								
								// Hour (24-hour format)
								case 'H':
									var hour = Value.getHours();
									FinalValue += (hour < 10 ? '0' : '') + hour + '';
									break;
								
								// Hour (12-hour format)
								case 'I': // Upper case "I" adds a leading 0 to the hour if it's less than 10.
								case 'i':
									var hour = Value.getHours();
									if (hour == 0) {
										FinalValue += '12';
									} else if (hour <= 12) {
										FinalValue += (hour < 10 && CodeChar == 'I' ? '0' : '') + hour + '';
									} else {
										hour = hour - 12;
										FinalValue += (hour < 10 && CodeChar == 'I' ? '0' : '') + hour + '';
									}
									break;
								
								// Minute
								case 'N':
									var minute = Value.getMinutes();
									FinalValue += (minute < 10 ? '0' : '') + minute + '';
									break;
								
								// Locale's am/pm indicator (English version only, at the moment)
								case 'p':
									var hour = Value.getHours();
									FinalValue += (hour >= 12 ? 'PM' : 'AM');
									break;
								
								// Second
								case 'S':
									var second = Value.getSeconds();
									FinalValue += (second < 10 ? '0' : '') + second + '';
									break;
							}
							
						} else {
							// No more format codes; move the rest of the string to the output.
							FinalValue += FormatString;
							FormatString = '';
						}
					}
					
					return FinalValue;
				
		};
	
		}, DateOnly: function() {
			DebtX.Formatting.FullDateTime.call(this); // Inherit DebtX.Formatting.FullDateTime class.
			
		this.DefaultFormatString = "%Y-%M-%D";
	
		}, TimeOnly: function() {
			DebtX.Formatting.FullDateTime.call(this); // Inherit DebtX.Formatting.FullDateTime class.
			
		this.DefaultFormatString = "%i:%N %p";
	
		}, Percent: function() {
			
		this.NumericFormatter = new DebtX.Formatting.Numeric();
	
		this.Format = function(Value, Precision, ThousandsSeparator, DecimalSymbol) {
			
		if (ThousandsSeparator == null) ThousandsSeparator = ",";
	
		if (DecimalSymbol == null) DecimalSymbol = ".";
	
					Value = Value.toString();
					if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
					
					if (isNaN(Value)) return(Value);
					
					var numericValue = parseFloat(Value);
					numericValue *= 100;
					
					return(NumericFormatter.Format(numericValue, Precision, ThousandsSeparator, DecimalSymbol) + "%");
				
		};
	
		this.Unformat = function(Value, DecimalSymbol) {
			
		if (DecimalSymbol == null) DecimalSymbol = ".";
	
					Value = Value.toString();
					if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
					
					var numericValue = NumericFormatter.Unformat(Value);
					
					if (isNaN(numericValue)) return(Value)
					
					numericValue /= 100;
					return(numericValue);
				
		};
	
		}, PhoneNumber: function() {
			
		this.PhoneNumbers = {};
	
		this.Format = function(Value, PhoneCode) {
			
		if (PhoneCode == null) PhoneCode = "Generic";
	
					var PhoneNumberFormatter = this.GetPhoneNumberFormatter(PhoneCode);
					return PhoneNumberFormatter.Format(Value);
				
		};
	
		this.Unformat = function(Value, PhoneCode) {
			
		if (PhoneCode == null) PhoneCode = "Generic";
	
					var PhoneNumberFormatter = this.GetPhoneNumberFormatter(PhoneCode);
					return PhoneNumberFormatter.Unformat(Value);
				
		};
	
		this.GetPhoneNumberFormatter = function(PhoneCode) {
			
		if (PhoneCode == null) PhoneCode = "Generic";
	
					var obj = null, cachedObjectRetrieved;
					
					try {
						// Try to get the object from cache.
						obj = this.PhoneNumbers[PhoneCode];
						
						if (obj == null) {
							
								obj = new DebtX.Formatting.PhoneNumbers[PhoneCode]();
							
							
							this.PhoneNumbers[PhoneCode] = obj;
						}
					}
					catch (e) {
						// An error most likely occurred because of an empty or invalid code. 
						// Use generic formatter.
						obj = new DebtX.Formatting.PhoneNumbers.Generic();
					}
					
					return(obj);
				
		};
	
		}, SSN: function() {
			
		this.Format = function(Value) {
			
					Value = Value.toString();
					if(Value == "") return(Value);

					var unformattedSSN = Value.replace(/-/g,'');

					if(unformattedSSN.toUpperCase() == "NAV" || unformattedSSN.toUpperCase() == "NAP" || unformattedSSN == "") return(Value);
					if (isNaN(unformattedSSN)) return(Value);
					if (unformattedSSN.length != 9) return(Value);
					
					var validChars = "0123456789";
					for (var i = 0; i < unformattedSSN.length; i++) {
						if (validChars.indexOf(unformattedSSN.charAt(i)) == -1) return(Value);
					}
					
					return (unformattedSSN.substring(0,3)+"-"+unformattedSSN.substring(3,5)+"-"+unformattedSSN.substring(5));
				
		};
	
		this.Unformat = function(Value) {
			
					// Do we need this?
				
		};
	
		}, Currencies: {
			Generic: function() {
			
		this.NumericFormatter = new DebtX.Formatting.Numeric();
	
		this.Description = "Generic Currency Format";
	
		this.Code = "";
	
		this.Symbol = "";
	
		this.SymbolInFront = true;
	
		this.NeverShowCode = false;
	
		this.DefaultPrecision = 2;
	
		this.ThousandsSeparator = ",";
	
		this.DecimalSymbol = ".";
	
		this.Format = function(Value, Precision, IncludeCode, ForceCode) {
			
		if (IncludeCode == null) IncludeCode = false;
	
		if (ForceCode == null) ForceCode = false;
	
						Value = Value.toString();
						if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
						
						// Calculate precision.
						var FinalPrecision = this.DefaultPrecision;
						if(typeof(Precision) == "string") {
							if(!isNaN(parseInt(Precision))) {
								FinalPrecision = parseInt(Precision);
							}
						}
						if(typeof(Precision) == "number") {
							FinalPrecision = Precision;
						}
						
						var Sign;
						
						// Extract possible negative sign.
						Sign = Value.substr(0, 1);
						if (Sign == '-') {
							Value = Value.substr(1);
						} else {
							Sign = '';
						}
						
						return(
							(Sign == "-" ? "(" : Sign)
							+ (this.SymbolInFront ? this.Symbol : "")
							+ this.NumericFormatter.Format(Value, FinalPrecision, this.ThousandsSeparator, this.DecimalSymbol)
							+ (this.SymbolInFront ? "" : this.Symbol)
							+ (
								ForceCode || (IncludeCode && !this.NeverShowCode)
									? " (" + this.Code + ")"
									: ""
							)
							+ (Sign == "-" ? ")" : "")
						);
					
		};
	
		this.Unformat = function(Value) {
			
						Value = Value.toString();
						if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
						
						return(this.NumericFormatter.Unformat(Value.replace(/\(/g, "-").replace(/\)/g, ""), this.DecimalSymbol));
					
		};
	
		}, USD: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Description = "US Dollars";
	
		this.Code = "USD";
	
		this.Symbol = "$";
	
		this.NeverShowCode = true;
	
		}, CAD: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Description = "Canadian Dollars";
	
		this.Code = "CAD";
	
		this.Symbol = "$";
	
		}, EUR: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Description = "Euro";
	
		this.Code = "EUR";
	
		this.Symbol = "€";
	
		}, GBP: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Description = "British Pound";
	
		this.Code = "GBP";
	
		this.Symbol = "₤";
	
		}, JPY: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Description = "Japanese Yen";
	
		this.Code = "JPY";
	
		this.Symbol = "¥";
	
		}, INR: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Description = "Indian Rupee";
	
		this.Code = "INR";
	
		this.Symbol = "Rs ";
	
		}, VAR: function() {
			DebtX.Formatting.Currencies.Generic.call(this); // Inherit DebtX.Formatting.Currencies.Generic class.
			
		this.Format = function(Value, Precision, IncludeCode, ForceCode) {
			
						return("NAV");
					
		};
	
		this.Unformat = function(Value) {
			
						return("NAV");
					
		};
	
		}
		}, PhoneNumbers: {
			Generic: function() {
			
		this.Format = function(Value) {
			
						return(Value.toString());
					
		};
	
		this.Unformat = function(Value) {
			
						return(Value.toString());
					
		};
	
		}, USCA: function() {
			DebtX.Formatting.PhoneNumbers.Generic.call(this); // Inherit DebtX.Formatting.PhoneNumbers.Generic class.
			
		this.Format = function(Value) {
			
						var Extension    = "";
						var ExtensionPos = -1;
						var PlusOne	  = "";
						var FirstChar = "";
						var ValueOrig = "";
						
						ValueOrig = Value.toString();
						Value = Value.toString();
						if(Value.toUpperCase() == "NAV" || Value.toUpperCase() == "NAP" || Value == "") return(Value.toUpperCase());
						
						// if phone number is blank, no need to go any further
						if (Value.replace(/\ /g, "") == "") 
							return Value;
						
						// if phone number doesn't start with a digit, leave it alone
						FirstChar = Value.substr(0,1);
						if (FirstChar == "+")
							return Value;
						
						// look for "ex", "x"
						ExtensionPos = Value.toLowerCase().indexOf("ex");
						if ( ExtensionPos < 0 ) 
							ExtensionPos = Value.toLowerCase().indexOf("x");
						
						if ( ExtensionPos > 0 ) {
							Extension = " " + Value.substr(ExtensionPos);
							Value = Value.substr(0, ExtensionPos);
						}
						
						// remove formatting characters
						// +-( )
						Value = Value.replace(/[^0-9]/g, "");
						
						// after these operations should have ended up with 10 digits or 11 digits(if 1 is first)
						// otherwise not a US phone number
						if ( Value.length != 10 && Value.length != 11 ) {
							return ValueOrig;
						}
						
						// if length is 11, must start with a 1
						// otherwise not a US phone number
						if ( Value.length == 11 )
							if (Value.charAt(0) != "1") 
								return ValueOrig;
							else {
								PlusOne = "1-"
								Value = Value.substr(1);
							}
						
						return PlusOne + Value.replace(/(\d{3})(\d{3})/,'$1'+'-'+'$2'+'-') + Extension;
					
		};
	
		}
		}
		}
		};
		
		
		// Global functions
		
		
		var NumericFormatter = new DebtX.Formatting.Numeric();
	
		var CurrencyFormatter = new DebtX.Formatting.Currency();
	
		var PercentFormatter = new DebtX.Formatting.Percent();
	
		var DateTimeFormatter = new DebtX.Formatting.FullDateTime();
	
		var DateFormatter = new DebtX.Formatting.DateOnly();
	
		var TimeFormatter = new DebtX.Formatting.TimeOnly();
	
		var PhoneNumberFormatter = new DebtX.Formatting.PhoneNumber();
	
		var SSNFormatter = new DebtX.Formatting.SSN();
	
		function dxFormatCurrency(CurrencyCode, Value, Precision, IncludeCode, ForceCode) {
			
					return CurrencyFormatter.Format(Value, CurrencyCode, Precision, IncludeCode, ForceCode).toString();
				
		}
	
		function dxUnFormatCurrency(CurrencyCode, Value) {
			
					return CurrencyFormatter.Unformat(Value, CurrencyCode).toString();
				
		}
	
		function dxGetCurrencySymbol(CurrencyCode) {
			
					return CurrencyFormatter.GetCurrencyFormatter(CurrencyCode).Symbol.toString();
				
		}
	
		function dxFormatNumber(Value, Precision, ThousandsSeparator, DecimalSymbol) {
			
					return NumericFormatter.Format(Value, Precision, ThousandsSeparator, DecimalSymbol).toString();
				
		}
	
		function dxUnFormat(Value, DecimalSymbol) {
			
					return NumericFormatter.Unformat(Value, DecimalSymbol).toString();
				
		}
	
		function dxFormatDateTime(Value, FormatString) {
			
					return DateTimeFormatter.Format(Value, FormatString).toString();
				
		}
	
		function dxFormatDate(Value, FormatString) {
			
					return DateFormatter.Format(Value, FormatString).toString();
				
		}
	
		function dxFormatTime(Value, FormatString) {
			
					return TimeFormatter.Format(Value, FormatString).toString();
				
		}
	
		function dxFormatPercent(Value, Precision, ThousandsSeparator, DecimalSymbol) {
			
					return PercentFormatter.Format(Value, Precision, ThousandsSeparator, DecimalSymbol);
				
		}
	
		function dxFormatPhoneNumber(PhoneCode, Value) {
			
					return PhoneNumberFormatter.Format(Value, PhoneCode);
				
		}
	
		function dxFormatSSN(Value) {
			
					return SSNFormatter.Format(Value);
				
		}
	