if (!Array.prototype.addItem)
{
    Array.prototype.addItem = function(elem)
    {
        this[this.length] = elem;
    }
}

var EventManager =
{
    _registry: null,

    Initialize: function()
    {
        if (this._registry == null)
        {
            this._registry = [];

            // Register the cleanup handler on page unload.
            EventManager.AttachEvent(window, "unload", this.CleanUp);
        }
    },

    /**
     * Registers an event and handler with the manager.
     *
     * @param  obj   Object handler will be attached to.
     * @param  type  Name of event handler responds to.
     * @param  fn    Handler function.
     *
     * @return True if handler registered, else false.
     */
    AttachEvent: function(obj, type, fn)
    {
        this.Initialize();

        // If a string was passed in, it's an id.
        if (typeof obj == "string")
            obj = document.getElementById(obj);
            
        if (obj == null || fn == null)
            return false;

        // Mozilla/W3C listeners?
        if (obj.addEventListener)
        {
            obj.addEventListener(type, fn, true);
            this._registry.addItem({obj: obj, type: type, fn: fn});
            return true;
        }

        // IE-style listeners?
        if (obj.attachEvent && obj.attachEvent("on" + type, fn))
        {
            this._registry.addItem({obj: obj, type: type, fn: fn});
            return true;
        }

        return false;
    },

    /**
     * Cleans up all the registered event handlers.
     */
    CleanUp: function()
    {
        for (var i = 0; i < EventManager._registry.length; i++)
        {
            with (EventManager._registry[i])
            {
                // Mozilla/W3C listeners?
                if (obj.removeEventListener)
                    obj.removeEventListener(type, fn, false);
                // IE-style listeners?
                else if (obj.detachEvent)
                    obj.detachEvent("on" + type, fn);
            }
        }

        // Kill off the registry itself to get rid of the last remaining
        // references.
        EventManager._registry = null;
    }
};



function DataInputHookupControlId(ctlId, ctlType){
	var ctl = document.getElementById(ctlId);
	
	if(ctl != null){
		DataInputHookupControl(ctl, ctlType);
	}
}


function DataInputHookupControl(ctl, ctlType){
	switch(ctlType){
		case "Numeric":
			HookupNumericControl(ctl);
			break;
		
		case "Date":
			HookupDateControl(ctl);
			break;
			
		case "MaskedInput":
			HookupMaskedInputControl(ctl);
			break;
		
		case "Time":
			HookupTimeControl(ctl);
	}
}

function HookupTimeControl(ctl){
	EventManager.AttachEvent(ctl, "keypress", TimeControl_OnKeyPress);
	EventManager.AttachEvent(ctl, "blur", TimeControl_OnBlur);
}

function HookupDateControl(ctl){
	EventManager.AttachEvent(ctl, "keypress", DateControl_OnKeyPress);
	EventManager.AttachEvent(ctl, "blur", DateControl_OnBlur);
	EventManager.AttachEvent(ctl, "focus", DateControl_OnFocus);
}

function HookupNumericControl(ctl){
	EventManager.AttachEvent(ctl, "keypress", NumericControl_OnKeyPress);
	EventManager.AttachEvent(ctl, "blur", NumericControl_OnBlur);
	EventManager.AttachEvent(ctl, "paste", NumericControl_OnPaste);
	
	DataInputFormatNumberCtl(ctl);
}


function HookupMaskedInputControl(ctl){
	EventManager.AttachEvent(ctl, "keypress", MaskControl_OnKeyPress);
	EventManager.AttachEvent(ctl, "dblclick", MaskControl_OnDblClick);
	EventManager.AttachEvent(ctl, "keydown", MaskControl_OnKeyDown);
	EventManager.AttachEvent(ctl, "click", MaskControl_OnClick);
	EventManager.AttachEvent(ctl, "focus", MaskControl_OnFocus);
	EventManager.AttachEvent(ctl, "blur", MaskControl_OnBlur);
	EventManager.AttachEvent(ctl, "paste", MaskControl_OnPaste);
}

function DataInputIsNavChar(keycode){
	switch(keycode){
		case 8: // backspace
		case 9: // tab
		case 27: // esc
		case 33: // page up
		case 34: // page down
		case 36: // home
		case 35: // end
		
		case 39: // right arrow
		case 37: // left
		case 38: // up
		case 40: // down 
			return true;
		
		default:
			return false;
	}
}

function TimeControl_OnKeyPress(ev){
	if(ev == null)
		ev = window.event;
	
	 
	var src = (ev.srcElement) ? ev.srcElement : ev.target;
	var key = (ev.which) ? ev.which : ev.keyCode;
	
	var keyVal = String.fromCharCode(key);
	var val = src.value;
	
	var CurPos = DataInputGetCursorPosition(src);
	var EndCurPos = DataInputGetSelectionEnd(src);
	
	var IsTextSelected = (CurPos != EndCurPos);
	var SelectedText = val.substring(CurPos, EndCurPos);

	var TimeSeperator = ":";
	var SepPos = val.indexOf(TimeSeperator);

	var InHour = (CurPos <= SepPos || SepPos == -1);
	var InMin = (CurPos > SepPos && SepPos != -1);
	
	if(DataInputIsNavChar(key)){
		return true;
	}
		
	if(keyVal == TimeSeperator){
		if(SepPos != -1){ // Seperator already exists.
			if(!IsTextSelected){
				DataInputCancelEvent(ev);
				return false;
			}
			else if(SelectedText.indexOf(TimeSeperator) == -1){ 
				DataInputCancelEvent(ev);
				return false;
			}
		}
	}
	else{
		if((key < 48 || key > 57)){
			DataInputCancelEvent(ev);
			return false;
		}
		
		if(SepPos == -1){
			if(val.length > 3 && !IsTextSelected){
				DataInputCancelEvent(ev);
				return false;
			}
		}
		else{
			var TimeParts = val.split(TimeSeperator);
			
			if(InHour){
				if(TimeParts[0].length > 1 && !IsTextSelected){
					DataInputCancelEvent(ev);
					return false;
				}
			}
			else if(InMin){
				if(TimeParts[1].length > 1 && !IsTextSelected){
					DataInputCancelEvent(ev);
					return false;
				}
			}
		}
		
	}
	
	return true;
}


function TimeControl_OnBlur(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	DataInputFormatTimeCtl(ctl);
	
	if(ctl.fireEvent)
		ctl.fireEvent("onchange");
	else
		eval(ctl.onchange);
}


function DataInputFormatTimeCtl(ctl){
	ctl.value = DataInputFormatTime(ctl.value);
}


function DataInputFormatTime(val){
	val = DataInputTrimValue(val);
	
	var TimeSeperator = ":";
	var SepPos = val.indexOf(TimeSeperator);
		
	if(val.length > 0 && SepPos == -1){
		if(val.length > 2){
			return val.substring(0, val.length - 2) + ":" + val.substring(val.length - 2, val.length);
		}
		else{
			return val + ":00";
		}
	}
	else{
		if(val.length > 0){
			var arrParts = val.split(TimeSeperator);
				
			if(arrParts[1].length < 1){
				val += "00";
			}
			else if(arrParts[1].length < 2){
				val += "0";
			}
		}
		return val;
	}
}

/**********************************************************************
Start Time Support Methods
***********************************************************************/


function DataInputValidateTimeCtl(ctl){
	var val = DataInputTrimValue(ctl.value);
	
	if(val == null || val.length == 0)
		return true;
	
	val = DataInputFormatTime(val);
	
	var AMPMCtl = document.getElementById(ctl.id + "_ampm");
	if(AMPMCtl != null)
		val += " " + AMPMCtl.value;
	
	return DataInputValidateTime(val);
}


function DataInputValidateTime(val){
	// Check hour and minute values.
	var tme = new DataInput_Time(val);
	
	if(tme.Hour > 12)
		return false;
	else if(tme.Minute > 59)
		return false;
		
	return true;
}


function ValidateTimeFormat(src, args){
	args.IsValid = true;
	
	var ctl = document.getElementById(src.controltovalidate);
	if(ctl != null){
		args.IsValid = DataInputValidateTimeCtl(ctl);
	}
}


function ValidateTimeMinValue(src, args){
	args.IsValid = true;
	
	var ctl = document.getElementById(src.controltovalidate);
	if(ctl != null){
		var MinValue = ctl.MinTime;
	
		if(MinValue != null && MinValue.length > 0){
			var strTime = DataInputGetTimeString(ctl);
			
			args.IsValid = (DataInputCompareTimes(strTime, MinValue) != -1);
		}
	}
}


function ValidateTimeMaxValue(src, args){
	args.IsValid = true;
	
	var ctl = document.getElementById(src.controltovalidate);
	if(ctl != null){
		var MaxValue = ctl.MaxTime;
		if(MaxValue != null && MaxValue.length > 0){
			var strTime = DataInputGetTimeString(ctl);
			
			args.IsValid = (DataInputCompareTimes(strTime, MaxValue) != 1);
		}
	}
}


function ValidateTimeCompare(src, args){
	args.IsValid = true;
	
	var ctl = document.getElementById(src.controltovalidate);
	var ctlCompare = document.getElementById(src.controltocompare);
	
	if(ctl != null && ctlCompare != null){
		var strTime = DataInputGetTimeString(ctl);
		var strTimeCompare = DataInputGetTimeString(ctlCompare);
		
		var iCompare = (DataInputCompareTimes(strTime, strTimeCompare));
		
		 switch (src.compareoperator) {
			case "NotEqual":
				args.IsValid = (iCompare != 0);
				break;
			case "GreaterThan":
				args.IsValid = (iCompare == 1);
				break;
			case "GreaterThanEqual":
				args.IsValid = (iCompare != -1);
				break;
			case "LessThan":
				args.IsValid = (iCompare == -1);
				break;
			case "LessThanEqual":
				args.IsValid = (iCompare != 1);
				break;
			default:
				args.IsValid = (iCompare == 0);
				break;
		}
	}
}


// Returns a time object based on the value of a time control
function DataInputGetTimeString(ctl){
	var val = DataInputTrimValue(ctl.value);
	val = DataInputFormatTime(val);

	var AMPMCtl = document.getElementById(ctl.id + "_ampm");
	if(AMPMCtl != null)
		val += " " + AMPMCtl.value;

	return val;
}


// Returns: 
//		-1 if strTime1 < strTime2
//		0 if strTime1 = strTime2
//		1 if strTime1 > strTime2
function DataInputCompareTimes(strTime1, strTime2){
	var tme1 = new DataInput_Time(strTime1);
	var tme2 = new DataInput_Time(strTime2);
	
	return tme1.CompareTo(tme2);
}


function DataInput_Time(strTime){
	this.Hour   = 0;
	this.Minute = 0;
	this.AMPM   = "";
	
	this.ToMilitaryTime = DataInput_ConvertToMilitaryTime;
	this.CompareTo = DataInput_CompareTime;
		
	var arrValues = strTime.split(" ");
	if(arrValues.length == 2)
		this.AMPM = arrValues[1].toUpperCase();
		
	arrValues = arrValues[0].split(":");
	if(arrValues.length > 1){
		this.Hour   = arrValues[0] - 0;
		this.Minute = arrValues[1] - 0;
	}
}

// Returns: 
//		-1 if strTime1 < strTime2
//		0 if strTime1 = strTime2
//		1 if strTime1 > strTime2
function DataInput_CompareTime(time){
	var tmeTime1  = this.ToMilitaryTime();
	var tmeTime2 = time.ToMilitaryTime();
	
	if(tmeTime1.Hour == tmeTime2.Hour && tmeTime1.Minute == tmeTime2.Minute)
		return 0;
	else if(tmeTime1.Hour > tmeTime2.Hour)
		return 1;
	else if(tmeTime1.Hour < tmeTime2.Hour)
		return -1;
	else if(tmeTime1.Minute > tmeTime2.Minute)
		return 1;
	else
		return -1;
}


function DataInput_ConvertToMilitaryTime(){
	var iHour = this.Hour;
	
	if(this.AMPM == "AM"){
		if(iHour == 12)
			iHour = 0;
	}
	else{
		if(iHour != 12)
			iHour += 12;
	}
	
	return new DataInput_Time(iHour + ":" + this.Minute);
}


/**********************************************************************
End Time Support Methods
***********************************************************************/


function DateControl_OnKeyPress(e){
	var ev = (e == null) ? event : e;
	 
	var src = (ev.srcElement) ? ev.srcElement : ev.target;
	var key = (ev.which) ? ev.which : ev.keyCode;
	
	if(DataInputIsNavChar(key)){
		return true;
	}
	
	var keyVal = String.fromCharCode(key);
	var val = src.value;
	
	var CurPos = DataInputGetCursorPosition(src);
	var EndCurPos = DataInputGetSelectionEnd(src);
		
	var IsTextSelected = (CurPos != EndCurPos);
	
	var NumbersOnly = DataInputStripCharsNotInBag(val, "0123456789");
	
	// Don't allow to exceed a complete date value.
	if((key < 47 || key > 57) || (NumbersOnly.length > 8 && !IsTextSelected)){
		DataInputCancelEvent(ev);
		return;
	}
	
	if(key == 47){
		if(CurPos == 0 || val.charAt(CurPos - 1) == "/"){
			DataInputCancelEvent(ev);
			return;
		}
		else{
			var DateParts = val.split("/");
			
			if(DateParts.length == 3 && !IsTextSelected){
				DataInputCancelEvent(ev);
				return;
			}
		}	
	}
	else{
		var DateParts = val.split("/");
		
		var iFirstSlash = val.indexOf("/");
		var iSecondSlash = val.indexOf("/", iFirstSlash + 1);
		
		
		var InMonth = (CurPos <= iFirstSlash || iFirstSlash == -1);
		var InDay = (iFirstSlash != -1 && CurPos > iFirstSlash && (CurPos <= iSecondSlash || iSecondSlash == -1));
		var InYear = (CurPos > iSecondSlash && iSecondSlash != -1);
		
		var iMonthPartIdx = 0;
		var iDayPartIdx = 1;
		var iYearPartIdx = 2;
		
		
		var fmt = src.getAttribute("DateOrder");
		if(fmt == null || fmt == "")
			fmt = "MDY";
		
		// Reset values based on the format we are to display
		switch(fmt){
			case "DMY":
				var tmpInMonth = InMonth;
				InMonth = InDay;
				InDay = tmpInMonth;		
				
				iMonthPartIdx = 1;
				iDayPartIdx = 0;
				iYearPartIdx = 2;
				
				break;
				
			case "YMD":
				var tmpInYear = InYear;
				InYear = InMonth;
				InMonth = InDay;
				InDay = tmpInYear;	
				
				iMonthPartIdx = 1;
				iDayPartIdx = 2;
				iYearPartIdx = 0;		
				break;
		}
		
		if(InMonth){
			if(DateParts[iMonthPartIdx].length > 1 && !IsTextSelected){
				DataInputCancelEvent(ev);
				return;
			}
		}
		else if(InDay){
			if(DateParts[iDayPartIdx].length > 1 && !IsTextSelected){
				DataInputCancelEvent(ev);
				return;
			}
		}
		else if(InYear){
			if(DateParts[iYearPartIdx].length > 3 && !IsTextSelected){
				DataInputCancelEvent(ev);
				return;
			}
		}
		
	}
}


function DateControl_OnFocus(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	ctl.setAttribute("OriginalValue", ctl.value);
}


function DateControl_OnBlur(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	DataInputFormatDateCtl(ctl);
	
	if(ctl.fireEvent && ctl.getAttribute("OriginalValue") != ctl.value)
		ctl.fireEvent("onchange");
}




function DataInputFormatDateCtl(ctl){
	try{
		ctl.value = DataInputFormatDate(ctl.value, ctl.getAttribute("MinDate"), ctl.getAttribute("MaxDate"), ctl.getAttribute("DateOrder"));
	}
	catch(e){
		//ctl.value = "";
		
		//event.returnValue = false;
		//ctl.focus();	

		//alert(e);
	}
}


function DataInputFormatDate(val, MinDate, MaxDate, DateOrder){
	val = DataInputTrimValue(val);
	if(val == "")
		return "";
	
	if(MinDate == null)
		MinDate = "";
	
	if(MaxDate == null)
		MaxDate = "";
	
	var Seperator = "/";
	
	var DateParts = val.split(Seperator);
	
	var iMonth = 0;
	var iDay = 0;
	var iYear = 0;
	
	var dtCurrent = new Date();
	var currentYear = dtCurrent.getFullYear();
	
	if(DateOrder == null || DateOrder == "")
		DateOrder = "MDY";
	
	var iMonthPartIdx = 0;
	var iDayPartIdx = 1;
	var iYearPartIdx = 2;
	
	// Reset values based on the format we are to display
	switch(DateOrder){
		case "MDY":
			iMonth = parseInt(DateParts[0], 10);
			iDay = (DateParts.length > 1) ? parseInt(DateParts[1], 10) : 0;
			iYear = (DateParts.length > 2) ? parseInt(DateParts[2], 10) : 0;
			break;
			
		case "DMY":
			iDay = parseInt(DateParts[0], 10);
			iMonth = (DateParts.length > 1) ? parseInt(DateParts[1], 10) : 0;
			iYear = (DateParts.length > 2) ? parseInt(DateParts[2], 10) : 0;			
			break;
			
		case "YMD":			
			iYear = parseInt(DateParts[0], 10);
			iMonth = (DateParts.length > 1) ? parseInt(DateParts[1], 10) : 0;
			iDay = (DateParts.length > 2) ? parseInt(DateParts[2], 10) : 0;	
			break;
	}
	
	if(isNaN(iMonth) || iMonth == 0){
		iMonth = 1;
	}
	
	if(isNaN(iDay) || iDay == 0){
		iDay = 1;
	}
	
	if(isNaN(iYear) || iYear == 0){
		iYear = currentYear;
	}
	else{
		if(iYear > 9999){
			iYear -= 10000;
		} 
		
		if(iYear < 50){
			iYear += 2000;
		}
		else if(iYear < 100){
			iYear += 1900;
		}
		else if(iYear < 1000){
			iYear += 1000;
		}
	}
	
	val = DataInputFormatDateValue(iMonth, iDay, iYear, DateOrder);	
	
	return val;
}

function DataInputFormatDateValue(iMonth, iDay, iYear, DateOrder){
	var Month = (iMonth > 9) ? iMonth : "0" + iMonth;
	var Day = (iDay > 9) ? iDay : "0" + iDay;
	var Year = iYear;
	var Seperator = "/";
	
	var dt = "";
	
	// Reset values based on the format we are to display
	switch(DateOrder){
		case "MDY":
			dt = Month + Seperator + Day + Seperator + Year;
			break;
			
		case "DMY":
			dt = Day + Seperator + Month + Seperator + Year;			
			break;
			
		case "YMD":			
			dt = Year + Seperator + Month + Seperator + Day;
			break;
		
		default:
			dt = Month + Seperator + Day + Seperator + Year;
			break;
	}
	
	return dt;
}


function NumericControl_OnKeyPress(e){
	var ev = (e == null) ? event : e;
	 
	var src = (ev.srcElement) ? ev.srcElement : ev.target;
	var key = (ev.which) ? ev.which : ev.keyCode;
	
	if(DataInputIsNavChar(key)){
		return true;
	}
	
	var keyVal = String.fromCharCode(key);
	var val = src.value;
	
	var decSymbol = src.getAttribute("DecimalSymbol");
	if(decSymbol == null)
		decSymbol = "";
	
	var CurPos = DataInputGetCursorPosition(src);
	var EndCurPos = DataInputGetSelectionEnd(src);
		
	var IsTextSelected = (CurPos != EndCurPos);
	
	
	var DecimalPlaces = src.getAttribute("DecimalPlaces");
	if(DecimalPlaces == null )
		DecimalPlaces = "";
	
	var Precision = src.getAttribute("pr");
		if(Precision == null || Precision == "")
			Precision = 15;
	
	var ThousandsSymbol = src.getAttribute("ThousandsSymbol");
	if(ThousandsSymbol == null)
		ThousandsSymbol = "";

	if(keyVal == ThousandsSymbol && ThousandsSymbol != ""){
		// Allow the thousands symbol anytime.
		return;
	}	
	else if(keyVal == decSymbol && decSymbol != ""){ // .
		if(DecimalPlaces == 0){
			DataInputCancelEvent(ev);
			return;
		}
		else{
			var DecPos = val.indexOf(decSymbol);
			
			if(DecPos != -1){ // Decimal already exists.
				if(!IsTextSelected){
					DataInputCancelEvent(ev);
					return;
				}
				else{
					if(DecPos < CurPos || DecPos >= EndCurPos){
						DataInputCancelEvent(ev);
						return;
					}
				}
			}
			else{
				// Check to see if the decimal is being 
				// inserted into a position before the 
				// number of allowed decimal places.
				var AllowedDecimalPos = (val.length - DecimalPlaces);
				if(CurPos < AllowedDecimalPos){
					DataInputCancelEvent(ev);
					return;
				}
			}			
		}
	}
	else{
		var CurrencySymbol = src.getAttribute("CurrencySymbol");
		if(CurrencySymbol == null) CurrencySymbol = "";
		
		var MinValue = src.getAttribute("MinValue");
		if(MinValue == null) MinValue = "";
		
		var bIsCur = (CurrencySymbol != "");
		var bCanBeNeg = (MinValue == "" || MinValue < 0);
		
		if(bIsCur){
			if(keyVal == CurrencySymbol){ // $
				if((CurPos == 0) || (CurPos == 1 && bCanBeNeg)){
					var SymbPos = val.indexOf(CurrencySymbol);
					
					if(SymbPos != -1){ // Currency symbol already exists.
						if(IsTextSelected){
							if(SymbPos < CurPos || SymbPos >= EndCurPos){
								DataInputCancelEvent(ev);
								return;
							}	
						}		
						else{
							DataInputCancelEvent(ev);
							return;
						}			
					}
				}
				else{
					DataInputCancelEvent(ev);
				}
				
				return;
			}
			else if(bCanBeNeg && key == 40){ // (
				var IsFirstPos = (CurPos == 0);
				
				if(!(IsFirstPos && ((val.indexOf("(") == -1) || IsTextSelected))){
					DataInputCancelEvent(ev);
				}
				return;
			}
			else if(bCanBeNeg && key == 45){ // -
					if(CurPos != 0){
						DataInputCancelEvent(ev);
						return;
					}
					else{
						if(!((val.indexOf("-") == -1) || IsTextSelected)){
							DataInputCancelEvent(ev);
						}
						return;
					}
				}
			else if(bCanBeNeg && key == 41){ // )
				var IsLastPos = (EndCurPos > 1) && (EndCurPos == val.length);
				
				if(!(CurPos > 1 && IsLastPos && ((val.indexOf(")") == -1) || IsTextSelected))){
					DataInputCancelEvent(ev);
				}
				return;
			}
		}
		else{ // Not Currency
			if(bCanBeNeg){
				if(key == 45){ // -
					if(CurPos != 0){
						DataInputCancelEvent(ev);
						return;
					}
					else{
						if(!((val.indexOf("-") == -1) || IsTextSelected)){
							DataInputCancelEvent(ev);
						}
						return;
					}
				}
			}
		}

	
		var DecPos = (decSymbol == "") ? -1 : val.indexOf(decSymbol);
		var PreDecDigits = DataInputCountDigitsBeforeToken(val, decSymbol);
	
		
		if(DecPos != -1){
			// Check to see if we are on the right
			// or left of the decimal.
			if(CurPos > DecPos){
				var Digits = DataInputCountDecimalDigits(val, decSymbol);
				
				if(Digits >= DecimalPlaces && (!IsTextSelected && (CurPos > DecPos || EndCurPos > DecPos))){
					DataInputCancelEvent(ev);
					return;
				}
			}
			else{
				if(PreDecDigits >= (Precision - DecimalPlaces) && (!IsTextSelected  || IsTextSelected && (CurPos > (DecPos - 1))) ){
					DataInputCancelEvent(ev);
					return;
				}
			}
		}
		else{
			if(PreDecDigits >= (Precision - DecimalPlaces) && !IsTextSelected){
				DataInputCancelEvent(ev);
				return;
			}
		}
		
		
		if(bIsCur){
			if(CurPos < 2){
				var ch = val.charAt(CurPos);
				
				if(IsTextSelected)
					ch = val.charAt(EndCurPos);
				
				if(ch == "(" || ch == CurrencySymbol){
					DataInputCancelEvent(ev);
					return;
				}
			}		
			else if(CurPos == val.length){
				if(val.substring(val.length-1, val.length) == ")"){
					DataInputCancelEvent(ev);
					return;
				}
			}
		}
		
		if(!(key >= 48 && key <= 57)){
			DataInputCancelEvent(ev);
		}
	}
}

function NumericControl_OnBlur(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	DataInputFormatNumberCtl(ctl);
}


function DataInputFormatNumberCtl(ctl){
	var CurrencySymbol = ctl.getAttribute("CurrencySymbol");
	var ThousandsSymbol = ctl.getAttribute("ThousandsSymbol");
	var DecimalPlaces = ctl.getAttribute("DecimalPlaces");
	var DecimalSymbol = ctl.getAttribute("DecimalSymbol");
	var Precision = ctl.getAttribute("Precision");
	var MinValue = ctl.getAttribute("MinValue");
	var MaxValue = ctl.getAttribute("MaxValue");
	
	try{
		ctl.value = DataInputFormatNumber(ctl.value, CurrencySymbol, ThousandsSymbol, DecimalSymbol, DecimalPlaces, Precision, MinValue, MaxValue);
	}
	catch(e){
		try{
			var ev = (e == null) ? event : e;
			
			DataInputCancelEvent(ev);
			
			alert(e);
			ctl.focus();
			
		}catch(e2){
		}	
	}
}


function NumericControl_OnPaste(e) {
	if(!window.clipboardData)
		return;
		
	var ev = (e == null) ? event : e;
	var src = (ev.srcElement) ? ev.srcElement : ev.target;
	
	DataInputCancelEvent(ev);
  
    src.value = window.clipboardData.getData("Text");
    DataInputFormatNumberCtl(src);
}


function DataInputFormatNumber(value, CurrencySymbol, ThousandsSymbol, DecimalSymbol, DecimalPlaces, Precision, MinValue, MaxValue){
	var val = DataInputTrimValue(value.toString());
	
	if(val == "" )
		return "";
	
	if(CurrencySymbol == null)
		CurrencySymbol = "";
	
	if(ThousandsSymbol == null)
		ThousandsSymbol = "";
	
	if(DecimalSymbol == null)
		DecimalSymbol = "";
		
	if(DecimalPlaces == null || DecimalPlaces == "")
		DecimalPlaces = 0;
	
	if(Precision == null || Precision == "")
		Precision = 0;
	
	if(MinValue == null)
		MinValue = "";
	
	if(MaxValue == null)
		MaxValue = "";
	
	var CanBeNeg = (MinValue == "" || MinValue < 0);
	var IsCur = (CurrencySymbol != "");
	var IsNeg = false;
	
	var ch = val.substring(0,1);
	IsNeg = ((ch == "(") || (ch == "-"));
		
	var BagOfValidChars = "0123456789";
	
	if(DecimalPlaces > 0){
		BagOfValidChars += DecimalSymbol;
	}
	else{
		var DecPos = val.indexOf(DecimalSymbol);
		if(DecPos != -1){
			val = val.substring(0, DecPos);
		}
	}
	
	val = DataInputStripCharsNotInBag(val, BagOfValidChars);
	val = parseFloat(val);
	
	if(IsNeg){
		val = val * - 1;
		
		if(!CanBeNeg)
			IsNeg = false;
	}
	
	if(MinValue != "" && val < MinValue){
		//val = MinValue;
		throw "Value cannot be less than " + MinValue + ".";
	}
	
	if(MaxValue != "" && val > MaxValue){
		//val = MaxValue;
		throw "Value cannot be more than " + MaxValue + ".";
	}
	
	val = Math.abs(val);
	
	val = val.toString();
		
	if(isNaN(val))
		return "";
	
	if(DecimalPlaces > 0){
		var Digits = DataInputCountDecimalDigits(val, DecimalSymbol);
		
		if(Digits == 0){
			val += ".";
		}
		
		if(Digits < DecimalPlaces){
			val += DataInputRepeat(0, (DecimalPlaces - Digits));
		}			
		
		if(Digits > DecimalPlaces){
			var ExtraDigits = Digits - DecimalPlaces;
			
			val = val.substring(0, val.length - ExtraDigits);
		}
	}
	
	if(ThousandsSymbol != ""){
		var regEx = /(-?\d+)(\d{3})/;
		
		var num = val;
		
		var end = (num.indexOf(DecimalSymbol) < 0) ? "" : num.substring(num.indexOf(DecimalSymbol), num.length);
		num = (end) ? num.substring(0, num.length - end.length) : num;
		
		while(regEx.test(num)) {
			num = num.replace(regEx, "$1,$2")
		}
		
		var result = num + end;
		val = result;
	}
	
	if(IsCur){
		val = CurrencySymbol + val;
	}
	
	if(IsNeg){
		if(IsCur){
			val = "(" + val + ")";
		}
		else{
			val = "-" + val;
		}
	}
	
	return val;
}


function DataInputTrimValue(s){
	if(s == null || s == "")
		return "";
	
    var m = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
    return (m == null) ? "" : m[1];
}


function DataInputRepeat(val, i){
	var s='';
	for(var c=0;c<i;c++)
		s+=val;

	return s;
}

function DataInputCountDigitsBeforeToken(val, token){
	var bag='0123456789';
	var ch;
	var c=0;
	
	for(var i = 0; i < val.length; i++){
		ch = val.charAt(i);
		if(bag.indexOf(ch) != -1)		
			c++;
			
		if(ch == token)
			break;
	}	
	
	return c;
}

function DataInputCountDecimalDigits(val, symbol){
	if(symbol == null)
		symbol = ".";
		
	var pos = val.indexOf(symbol);
	if(pos == -1)
		return 0;
	
	var bag='0123456789';
	var ch;
	var c=0;
	
	for(var i = (pos + 1); i < val.length; i++){
		ch = val.charAt(i);
		if(bag.indexOf(ch) == -1)
			break;
		
		c++;
	}	
	
	return c;
}

function DataInputGetPrecisionCount(val){
	var bag='0123456789';
	var ch='';
	var c=0;
	
	for(var i=0; i < val.length; i++){
		ch = val.charAt(i);
		
		if(bag.indexOf(ch) != -1)
			c++;
	}
	
	return c;
}

function DataInputCleanValue(val, keepDecimal, decimalSymbol){
	var bag='0123456789';
	if(keepDecimal)
		bag += decimalSymbol;
			
	var c = '';
	var s = '';
	var i = 0;
	var l = val.length;
	var f = false;
		
	while(i < l){
		c = val.charAt(i);
		if(bag.indexOf(c) != -1){
			if(c != '0' || f){
				s += c;
				f = true;
			}
		}
		else if(c == decimalSymbol)
			break;
	
		i++;
	}
	
	return s;
}


function DataInputIsTextSelected(ctl){
	var start = DataInputGetSelectionStart(ctl);
	var end = DataInputGetSelectionEnd(ctl);
	
	if(start != end)
		return true;
	else
		return false;
}


function DataInputGetCursorPosition(ctl){
	return DataInputGetSelectionStart(ctl);
}

function DataInputGetSelectionStart(ctl){
	if(ctl.createTextRange){
		var len = ctl.value.length;
		var sel = document.selection.createRange().duplicate();
		sel.moveEnd('character', len);
			
		return (sel.text.length == 0) ? len : ctl.value.lastIndexOf(sel.text);
	}
	else{
		return ctl.selectionStart;
	}
}

function DataInputGetSelectionEnd(ctl){
	if(ctl.createTextRange){
		var len = ctl.value.length;
		var sel = document.selection.createRange().duplicate();
		sel.moveStart('character',-len);
		
		var pos = sel.text.length;
		sel.moveEnd('character', len);
		
		return pos;
	}
	else{
		return ctl.selectionEnd;
	}
}


function DataInputStripCharsNotInBag(s, bag) {
	var i;
	var returnString = "";

	// Search through string's characters one by one.
	// If character is in bag, append to returnString.
	for (i = 0; i < s.length; i++)  {   
		// Check that current character isn't whitespace.
		var c = s.charAt(i);
		if (bag.indexOf(c) != -1) returnString += c;
	}

	return returnString;
}


function DataInputShowCalendar(src, e){
	var fld = document.getElementById(src);
	if(fld == null || fld.disabled)
		return;
		
	window.DateField = fld;

	var iDialogWidth = 205;
	var iDialogHeight = 225;
	
	var strURL = CalendarDialogUrl + '?date=' + fld.value + '&mindate=' + fld.getAttribute("MinDate") + '&maxdate=' + fld.getAttribute("MaxDate") + '&dateorder=' + fld.getAttribute("DateOrder");
	var OpenInDialog = fld.getAttribute("OpenInDialog");
	
	if(OpenInDialog != null && OpenInDialog.toLowerCase() == "true"){
		DataInputOpenCalendarDialog(strURL, iDialogWidth, iDialogHeight);
	}
	else{
		var ev = (e == null) ? event : e;
		
		var OpenOnTop = fld.getAttribute("OpenOnTop");
		
		OpenOnTop = (OpenOnTop != null && OpenOnTop.toLowerCase() == "true");
		
		DataInputOpenCalendarFrame(strURL, iDialogWidth, iDialogHeight, OpenOnTop, ev);
	}
	
}

function EnableCalendar(ctl, enable){
	ctl.disabled = !enable;
	
	var ctlName = ctl.id;

	var imgHref = document.getElementById(ctlName + "_imgCalendar");
	var img		= imgHref.children[0];
	
	if(img == null)
		return;
		
	if(enable){
		imgHref.href = imgHref.orHref;
		imgHref.href = "javascript:DataInputShowCalendar('" + ctl.id + "');";
		img.src = "../images/calendar.gif";
	}
	else{
		imgHref.orHref = imgHref.href;
		imgHref.removeAttribute("href");
		img.src = "../images/calendar_dis.gif";
	}
}

var CalFrameEventAttached = false;

function DataInputOpenCalendarFrame(strURL, iDialogWidth, iDialogHeight, bOpenOnTop, e){
	var oCalFrame = document.getElementById("DataInputCalFrame");
	
	var ctl = (e.srcElement) ? e.srcElement : e.target;
	
	// Cancel the click from bubbling up to the document.
	e.cancelBubble = true;
	DataInputCancelEvent(e);
	
	// Clicking twice will cause have a toggling effect.
	if(oCalFrame.style.display != "none"){
		oCalFrame.style.display = "none";
		return;
	}
	
	// Set the width and height of the calendar frame.		
	oCalFrame.style.width  = iDialogWidth + "px";
	oCalFrame.style.height = iDialogHeight + "px";
	
	
	var iClickX = e.clientX;
	var iClickY = e.clientY;
	
	var iLeft = iClickX;	
	var iTop = (iClickY + document.body.scrollTop);
	
	var targetField = document.getElementById(ctl.parentNode.id.replace("_imgCalendar", ""));
	if(targetField != null){
		iLeft = DataInputGetLeftPos(targetField);
		
		iTop = DataInputGetTopPos(targetField);
	}
	
	if(bOpenOnTop){
		iTop -= iDialogHeight;
		
		iTop -= 5;
	}
	else{
		if(!isNaN(ctl.clientHeight))
			iTop += ctl.clientHeight;
		
		iTop += 5;
	}
	
	if(isNaN(iLeft))
		iLeft = iClickX;
	
	var iRight = (iLeft + iDialogWidth);
	var iBodyWidth = document.body.clientWidth;
	if(iRight > iBodyWidth){
		iLeft -= (iRight - iBodyWidth);
	}
	
	
	// Setup the calendar...
	oCalFrame.style.left = iLeft;
	oCalFrame.style.top = iTop;
	oCalFrame.src = strURL;
	oCalFrame.style.display = "inline";
	
	
	if(!CalFrameEventAttached){
		CalFrameEventAttached = true;
		
		EventManager.AttachEvent(document, "click", DataInputCloseCal);
	}
}


function DataInputGetLeftPos(oElement){
	var iLeftPos = oElement.offsetLeft;
	var oParent = oElement.offsetParent;
	while(oParent){
		iLeftPos += oParent.offsetLeft;
		oParent = oParent.offsetParent;
	}
	return iLeftPos;
}


function DataInputGetTopPos(oElement){
	var iScrollTop = 0;
	
	var iTopPos = oElement.offsetTop;
	var oParent = oElement.offsetParent;
	
	while(oParent){
		if(oParent.tagName.toUpperCase() != "BODY")
			iScrollTop += oParent.scrollTop;
		
		iTopPos += oParent.offsetTop;
		oParent = oParent.offsetParent;
	}
	
	return iTopPos - iScrollTop;
}

function DataInputCloseCal(e){
	var oCalFrame = document.getElementById("DataInputCalFrame");
	if(oCalFrame == null)
		return;
		
	if(oCalFrame.style.display != "none"){
		oCalFrame.style.display = "none";
	}
}


function DataInputOpenCalendarDialog(strURL, iDialogWidth, iDialogHeight){
	var iScreenWidth = screen.availWidth;
	var iScreenHeight = screen.availHeight;
	
	var iTop = (iScreenHeight - iDialogHeight) / 2;
	var iLeft = (iScreenWidth - iDialogWidth) / 2;
	
	var strOptions = 'top=' + iTop + ', left=' + iLeft + ', width=' + iDialogWidth + ', height=' + iDialogHeight;

	var win = window.open(strURL, 'CalendarDialog', strOptions, true);
	win.focus();
}


function MaskControl_OnDblClick(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	DataInputSelectAll(ctl);			
}

function MaskControl_OnKeyPress(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	var k = (ev.which) ? ev.which : ev.keyCode;
	var c = String.fromCharCode(k);
	var b = DataInputGetSelectionStart(ctl);
	
	if(k == 9){
		return true;
	}
	
	DataInputCancelEvent(ev);
	
	if(k >= 48 && k <= 57){
		var e = DataInputGetSelectionEnd(ctl);
		
		var mask = ctl.getAttribute("mask");
		
		if((e-b) == mask.length){
			ctl.value = mask;
			
			DataInputPutCaretPos(ctl, 0);
			DataInputSetupCaretPos(ctl);
			b = DataInputGetSelectionStart(ctl);
		}
		
		
		DataInputKeyNumber(ctl, b, c);
	}	
}

function MaskControl_OnKeyDown(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	var k = (ev.which) ? ev.which : ev.keyCode;

	if(k==8 || k==37 || k==39 || k==46 || k==36 || k==35){
		DataInputCancelEvent(ev);
		
		var mask = ctl.getAttribute("mask");
		
		switch(k){
			case 8:{
				var s = DataInputGetSelectionStart(ctl)
				var e = DataInputGetSelectionEnd(ctl);
				
				if(s == 0 && e == mask.length){
					ctl.value = '';
					DataInputDisplayMask(ctl);
					DataInputPutCaretPos(ctl, 0);
					DataInputSetupCaretPos(ctl);
				}
				else{
					DataInputKeyBackspace(ctl, s);
				}
				
				break;
			}
			case 35:{
				DataInputPutCaretPos(ctl, mask.length);
				DataInputSetupCaretPos(ctl);
				
				break;
			}
			case 36:{
				DataInputPutCaretPos(ctl,0);
				DataInputSetupCaretPos(ctl);
				
				break;
			}
			case 37:{
				DataInputPushCaretPos(ctl, 0);
				
				break;
			}
			case 39:{
				DataInputPushCaretPos(ctl, 1);
				
				break;
			}
			case 46:{
				var s = DataInputGetSelectionStart(ctl)
				var e = DataInputGetSelectionEnd(ctl);
				
				if(s == 0 && e == mask.length){
					ctl.value = '';
					DataInputDisplayMask(ctl);
					DataInputPutCaretPos(ctl, 0);
					DataInputSetupCaretPos(ctl);
				}
				else{
					DataInputKeyDelete(ctl,s);
					DataInputPushCaretPos(ctl, 1);
				}
				
				break;
			}
		}
	}
}

function MaskControl_OnClick(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	var s = DataInputGetSelectionStart(ctl);
	
	DataInputPutCaretPos(ctl, s);
	DataInputSetupCaretPos(ctl);
}

function MaskControl_OnFocus(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	ctl.enterval = ctl.value;
	
	DataInputDisplayMask(ctl);
	DataInputSelectAll(ctl);
}

function MaskControl_OnBlur(e){
	var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	if(ctl.value == ctl.getAttribute("mask"))
		ctl.value = '';
		
	if(ctl.fireEvent && ctl.enterval != ctl.value)
		ctl.fireEvent("onchange");
}

function MaskControl_OnPaste(e) {
    if(!window.clipboardData)
		return;
	
    var ev = (e == null) ? event : e;
	var ctl = (ev.srcElement) ? ev.srcElement : ev.target;
	
	DataInputCancelEvent(ev);
	
    var strValue = window.clipboardData.getData("Text");

	var s = DataInputGetSelectionStart(ctl);
	var e = DataInputGetSelectionEnd(ctl);

	if((e-s) == ctl.getAttribute("mask").length){
		DataInputPutCaretPos(ctl,0);
		DataInputSetupCaretPos(ctl);
		s = DataInputGetSelectionStart(ctl);
	}
    
    for(var i = 0; i < strValue.length; i++){
		var k = strValue.charCodeAt(i);
		var c = strValue.charAt(i);
		
		if(k >= 48 && k <= 57){		
			DataInputKeyNumber(ctl, s, c);
		}
    }
}

function DataInputIsValidDataAtCaretPos(ctl, pos){
	if(pos >= 0){
		var c = ctl.value.charCodeAt(pos);
		return(c >= 48 && c <= 57);
	}
	else{
		return false;
	}
}

function DataInputKeyNumber(ctl, pos, c){
	DataInputCutMask(ctl, pos, 1);
	DataInputInsertChar(ctl, c, pos);
	DataInputPutCaretPos(ctl, pos);
	DataInputPushCaretPos(ctl, 1);
}

function DataInputKeyDelete(ctl, pos){
	DataInputCutMask(ctl, pos, 1);
	DataInputInsertChar(ctl, '_', pos);
	DataInputPutCaretPos(ctl, pos - 1);
}

function DataInputKeyBackspace(ctl, pos){
	var c = DataInputCharAtCaretPos(ctl, pos);
	
	if(DataInputIsValidDataAtCaretPos(ctl, pos)){
		DataInputCutMask(ctl, pos + 1, 0);

		DataInputInsertChar(ctl, '_', pos);
		DataInputPutCaretPos(ctl, pos - 1);
	}
	else if(c == '_'){
		DataInputPutCaretPos(ctl, pos - 1);
	}
	
	pos--;
	
	while(pos > 0){
		c = DataInputCharAtCaretPos(ctl, pos);
		
		if(!DataInputIsValidDataAtCaretPos(ctl, pos) && c != '_'){
			DataInputPutCaretPos(ctl, pos - 1);
		}
		else{
			break;
		}
		
		pos--;
	}
	
	if(pos == 0)
		DataInputSetupCaretPos(ctl);
}

function DataInputPushCaretPos(ctl, dir){
	var s = DataInputGetSelectionStart(ctl);
	var c = DataInputCharAtCaretPos(ctl, s);
	var l = ctl.value.length - 1;
	
	do{
		if(dir == 0){
			if(s > 0)
				DataInputPutCaretPos(ctl, --s);
		}
		else{
			if(s < l)
				DataInputPutCaretPos(ctl, ++s);
		}
		
		c = DataInputCharAtCaretPos(ctl, s)
	}
		
	while(c != '_' && s < l && s != 0 && !DataInputIsValidDataAtCaretPos(ctl, s))
		DataInputSetupCaretPos(ctl);
}


function DataInputInsertChar(ctl, c, pos){
	var v = ctl.value;
	var s = v.substring(0, pos);
	var e = v.substring(pos, v.length);
	
	ctl.value = s + c + e;
}

function DataInputCutMask(ctl, pos, dir){
	var v = ctl.value;
	var s = "";
	var e = "";
	
	if(dir == 0){
		s = v.substring(0, pos - 1);
		e = v.substring(pos, v.length);
	}
	else{
		s = v.substring(0, pos);
		e = v.substring(pos + 1, v.length);
	}
	
	ctl.value = s + e;
}

function DataInputCharAtCaretPos(ctl, pos){
	var v = ctl.value;
	if(pos >= 0 && pos < v.length)
		return v.charAt(pos);
	else{
		return '';
	}
}

function DataInputSetupCaretPos(ctl){
	var s = DataInputGetSelectionStart(ctl);
	var i = false;
	var l = ctl.value.length - 1;
	
	while(s < l && i == false){
		var c = DataInputCharAtCaretPos(ctl, s);
		
		if(DataInputIsValidDataAtCaretPos(ctl, s) || c == '_'){
			DataInputPutCaretPos(ctl, s);
			i = true;
		}
		
		s++;
	}
	
	if(!i){
		while(s >= 0 && i == false){
			var c = DataInputCharAtCaretPos(ctl, s);
			
			if(DataInputIsValidDataAtCaretPos(ctl, s) || c == '_'){
				DataInputPutCaretPos(ctl, s);
				i = true;
			}
			
			s--;
		}
	}
	
	if(!i){
		if(ctl.type == 'text'){
			ctl.value = ctl.getAttribute("mask");
		}
	}
}

function DataInputPutCaretPos(ctl, pos){
	if(pos <= 0)
		pos = 0;
		
	if(ctl.createTextRange){
		var r = ctl.createTextRange();
		r.moveStart('character', pos);
		r.moveEnd('character',pos + 1 - (ctl.value.length ));
		r.select();
	}
	else if(ctl.setSelectionRange){
		ctl.setSelectionRange(pos, pos + 1);
	}
}

function DataInputSelectAll(ctl){
	if(ctl.createTextRange){
		var r = ctl.createTextRange();
		r.moveStart('character',0);
		r.moveEnd('character', ctl.value.length);
		r.select();
	}
	else if(ctl.setSelectionRange){
		ctl.setSelectionRange(0, ctl.value.length);
	}
}

function DataInputDisplayMask(ctl){
	var strMask = ctl.getAttribute("mask");
	
	if(ctl.value == ''){
		ctl.value = strMask;	
	}
	else if(ctl.value.length != strMask.length){
		// Something is wrong, so we need to fix it.
		var val = ctl.value;
		
		ctl.value = strMask;
		DataInputPutCaretPos(ctl,0);
		DataInputSetupCaretPos(ctl);
				
		for(var i = 0; i < val.length; i++){
			var k = val.charCodeAt(i);
			var ch = val.charAt(i);
			
			if(k >= 48 && k <= 57){
				DataInputKeyNumber(ctl,DataInputGetSelectionStart(ctl), ch);
			}			
		}
	}
}



function DataInputCancelEvent(ev){
	if (ev.preventDefault) {
		ev.preventDefault();
	}
	
	ev.returnValue = false;
}

// This function will show all properties for the object passed in...
function DisplayObjProperties(o) {
	var result = ""
	var count = 0
	for (var i in o) {
		result += o + "." + i + "=" + o[i] + "\n"
		count++
		if (count == 10) {
			alert(result)
			result = ""
			count = 0
		}
	}
	
	alert(result)
}
