﻿//vs 030110
Type.registerNamespace('Infragistics.Web.UI');

$IG.WebTextEditor = function(elem)
{
	/// <summary>Class which implements client side functionality of WebTextEditor.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebTextEditor.initializeBase(this, [elem]);
}
$IG.WebTextEditor.prototype =
{
	_thisType:'edit',
	initialize:function()
	{
		/// <summary>Initializes instance of WebTextEditor.</summary>
		$IG.WebTextEditor.callBaseMethod(this, 'initialize');
		var prop0 = this._get_clientOnlyValue('prop1');
		/* WebTextEditor uses Text property directly (because of possible new-line characters) */
		/* all other editors uses preformatted array */
		this._prop1 = (this._thisType == 'edit') ? [prop0] : eval(prop0);
		prop0 = this._get_clientOnlyValue('prop').split(',');
		var buts = this._get_clientOnlyValue('buts');
		/* browser-back navigation contains value which match with ClientState on server and defined by _saveAdditionalClientState */
		/* [0] - postbackEnter, [1] - (1-enabled)+(2-readOnly)+(4-focus), [2...] - value */
		var backState = this._backState = this._getBackState(0);
		var flags = backState ? backState.charCodeAt(1) - 48 : 0;
		var elem = this._element;
		j = elem.title;
		if(j && j.indexOf('{0}') >= 0)
			this._dt = j;
		var id = this._id;
		this._state = 0;
		this._fix = 1;
		this._fcs = -1;
		this._e_elemID = -10;
		/* 0-no post, 1-post Enter, 2-post CustomButton */
		this._postFlag = 0;
		this._bad = 0;
		this._eventList = [
		/*0,1,2,3,4,5,6,7,8,9*/
		'KeyDown','KeyPress','KeyUp','MouseDown','MouseUp','MouseMove','MouseOver','MouseOut','Focus','Blur',
		/*10,11,12,13,14,15*/
		'ValueChanging','ValueChanged','TextChanged','InvalidValue','Spin','CustomButtonClick'];
		var o, ii, j = -1, i = 0, elems = this._elements, e = buts ? elems[3] : null;
		var list = this._get_clientOnlyValue('list');
		if(list && list.indexOf('|') >= 0)
		{
			this._list = list = list.split('|');
			this._listIndex = -1;
			while(++j < list.length)
				list[j] = list[j].replace(/&pipe;/g, '|');
		}
		if(!e)
			e = elem;
		this._ta = e.nodeName == 'TEXTAREA';
		/* If INPUT element contains member Validators, then it means that it has dot-net validators. */
		/* 1. move that variable to "this" (that will be used to raise ValidatorOnChange) */
		/* 2. remove dot-net-validator listeners (onchange, onblur) */
		/* 3. call dot-net-validator notification explicitly by ValidatorOnChange */
		/* 4. create a dummy SPAN (this._elemMSV), because validators use document.getElementById */
		/*    set it reference (id) to controltovalidate for all validators */
		/*    create/adjust member 'SPAN.value' to trick validators about current value-to-validate */
		o = e.Validators;
		if(o && typeof ValidatorOnChange == 'function')
		{
			j = o.length;
			/* ii is id of SPAN */
			ii = this._id + ':v:';
			while(j-- > 0)
			{
				if(o[j].controltovalidate == this._id)
					o[j].controltovalidate = ii;
				/* that may happen when this is used as EditorProvider in WebDataGrid */
				else
					j = -2;
			}
			if(j > -2)
			{
				this.Validators = o;
				e.Validators = e.onchange = e.onblur = e.onkeypress = e.onkeydown = null;
				/* check for async postback: maybe SPAN with id already exists */
				var span = $get(ii);
				if(!span)
				{
					span = document.createElement('SPAN');
					span.id = ii;
					o = span.style;
					o.position = 'absolute';
					o.display = 'none';
					o.visibility = 'hidden';
					document.body.appendChild(span);
				}
				this._elemMSV = span;
				span.value = '';
			}
		}
		this._elem = e;
		this._nullable = !$util.isEmpty(prop0[i++]);//0
		ii = this._int_i(prop0, i++);//1
		this._postValue = ii & 3;/* bits 1-2 */
		this._postEnter = (ii >> 2) & 3;/* bits 3-4 */
		this._postCustom = (ii >> 4) & 3;/* bits 5-6 */
		this._causeValidation = (ii & 64) != 0;/* bit 7 */
		this._validationGroup = this._val_i(prop0, i++);/* 2-ValidationGroup */
		this._maxLen = this._int_i(prop0, i++);/* 3-MaxLength */
		this._spDelta = parseFloat(prop0[i++]);/* 4-SpinDelta */
		this._spArrows = !$util.isEmpty(prop0[i++]);/* 5-SpinOnArrows */
		this._spinOnlyOneField = !$util.isEmpty(prop0[i++]);/* 6-SpinOneField */
		this._hideEnter = !$util.isEmpty(prop0[i++]);/* 7-HideEnter */
		this._selOnFoc = this._int_i(prop0, i++) - 1;/* 8-SelectionOnFocus */
		this._altDigit = !$util.isEmpty(prop0[i++]);/* 9-AltDigits */
		this._initFoc = !$util.isEmpty(prop0[i++]);/* 10-SetFocusOnInit */
		this._readOnly = !$util.isEmpty(prop0[i++]);/* 11-ReadOnly */
		if(!this._readOnly && (!backState || (flags & 2) == 0))
			e.readOnly = '';
		if(backState)
			e.disabled = (flags & 1) == 0;
		this._disabled = e.disabled;
		this._spRoll = !$util.isEmpty(prop0[i++]);/* 12-RollOverOnSpin */
		ii = 1;
		if((o = this._int_i(prop0, i++)) < 0)/* 13-SpinSpeedUp */
			ii = 8;
		else
		{
			while(o++ < 3)
				ii /= 2;
			while(o-- > 4)
				ii *= 2;
		}
		this._spSpeedUp = ii;
		this._spOnRead = !$util.isEmpty(prop0[i++]);/* 14-SpinOnReadOnly */
		this._spDelay = this._int_i(prop0, i++);/* 15-SpinSpeedUpDelay */
		this._spFocus = !$util.isEmpty(prop0[i++]);/* 16-FocusOnSpin */
		/* 17-HotKeys for CustomButton */
		if(!$util.isEmpty(o = prop0[i++]))
		{
			o = o.split(':');
			for(ii = 0; ii < o.length; ii++)
				o[ii] = parseInt(o[ii]);
			this._hotKeys = o;
		}
		/* 18-focus css for elem */
		var css = this._val_i(prop0, i++);
		o = elem.className;
		/* note: this._css is used by TextEditorProvider, so, name and order should not be changed */
		/* css: 0-normal, 1-hover, 2-?, 3-disabled, 4-focus, 5-hover+focus */
		this._css = o = [o, o, o, o, o, o];
		if(!$util.isEmpty(css))
			/* css: 4-focus, 5-hover+focus */
			o[4] = (o[5] += ' ' + css);
		/* 19-hover css for elem */
		if(!$util.isEmpty(css = this._val_i(prop0, i++)))
		{
			/* css: 1-hover, 5-hover+focus */
			o[1] += ' ' + css;
			o[5] += ' ' + css;
		}
		/* 20-null text css */
		this._nullCss = this._val_i(prop0, i++);
		/* 21-focus css for inner elem */
		css = this._val_i(prop0, i++);
		if(css)
		{
			o = e.parentNode.className;
			/* css: 0-normal, 1-hover, 2-?, 3-disabled, 4-focus, 5-hover+focus */
			this._cssI = o = [o, o, o, o, o, o];
			if(!$util.isEmpty(css))
				/* css: 4-focus, 5-hover+focus */
				o[4] = (o[5] += ' ' + css);
			/* 22-hover css for inner elem */
			if(!$util.isEmpty(css = this._val_i(prop0, i++)))
			{
				/* css: 1-hover, 5-hover+focus */
				o[1] += ' ' + css;
				o[5] += ' ' + css;
			}
		}
		this._nullText = this._get_clientOnlyValue('nt');
		$addHandlers(e, {'keydown':this._onEvt, 'keypress':this._onEvt, 'keyup':this._onEvt, 'focus':this._onEvt, 'blur':this._onEvt}, this);
		$addHandlers(elem, {'mousedown':this._onEvt, 'mouseup':this._onEvt, 'mousemove':this._onEvt, 'mouseover':this._onEvt, 'mouseout':this._onEvt}, this);
		e._editID = -1;
		this._k0 = this._sel0 = 0;
		if(buts)
		{
			buts = buts.split(',');
			/* note: i is incremented for evry value passed from server */
			/* i==[0,1,2,3] css classes for extra states, [4,5,6,7], etc. are images */
			i = 0;
			/* css: 0-normal, 1-hover, 2-press, 3-disabled, 4-focus, 5-hover+focus, 6-press+focus */
			css = new Array(7);
			/* i==0-hover css, 1-press css, 2-disabled css, 3-focus css */
			for(ii = 0; ii < 4; ii++)
			{
				if(!$util.isEmpty(o = this._val_i(buts, i++)))
					o = ' ' + o;
				css[ii + 1] = o;
			}
			/* build merged css for focus+hover and focus+pressed */
			/* o-focus css, i==4-hover+focus css, 5-press+focus css */
			while(ii++ < 6)
				css[ii] = css[ii - 4] + o;/* space separator is already included in o */
			this._butPressed = -1;
			this._butMouse = 1;
			this._buttons = new Array(3);
			for(j = 0; j < 3; j++)
			{
				e = elems[j];
				if(!e)
					continue;
				e._editID = j + 1;
				/* o.img contains array of images for every state, o._css contains array of css for every state */
				this._buttons[j] = o = {elem:e, img:new Array(4), _css:new Array(7), _state:0};
				this._initBut(e, o, true);
				/* 0-normal img, 1-hover img, 2-press img, 3-disabled img */
				/* i==[4,5,6] or [7,8,9] or [10,11,12] */
				for(ii = 1; ii < 4; ii++)
					o.img[ii] = this._val_i(buts, i++);
				var cn = e.className;
				/* css: 0-normal, 1-hover, 2-press, 3-disabled, 4-focus, 5-hover+focus, 6-press+focus */
				for(ii = 0; ii < 7; ii++)
					o._css[ii] = (ii == 0) ? cn : cn + css[ii];/* space separator is already included in css[ii] */
				if(!this.get_enabled())
					this._butState(j, 3);
			}
		}
		this._spinField = -1;
		/* Check for redirect under Mozilla. */
		/* Mozilla updates values in <input>s before running init javascript (I wish IE did similar). */
		/* Note:redirect for IE is done while processing load event */
		/* value passed to server (flag if control triggered postback) */
		if(this._onTimer())/* no need to process first paint */
			delete this._onTimer;
		else/* enable processing first paint */
			ig_ui_timer(this);
		if(this._thisType == 'edit')
			this._initEnd();
	},
	_initEnd:function()
	{
		this._fix = 1;
		/* If it is redirect, then use current value in editor, but not value from javascript */
		var val = this._backState;
		/* if it is redirect and mask-edit, then use set_value with full-value-type mode */
		var mask = (this._thisType == 'mask' && val) ? 3 : null;
		if(val)
			this._vs0 = this._vs = val = val.substring(2);
		else
			val = this._prop1[0];
		this.set_value(val, mask);
		delete this._prop1;
		this._fcs = this._np = 0;
		this._dtt();
		this._backState = null;
		/* VS 12/15/2009 Bug 25652: initialize value for validators */
		if(this._elemMSV)
			this._msV(this._enterTxt());
		var fixCss = this._negCss;
		if(this._val() == '' && !this._initFoc)
		{
			this._text = this._elem.value = this._focTxt('', false, '');
			fixCss = true;
		}
		if(fixCss)
			this._fixCss(-1, -1);
		this._lastText = this._val();
		this._raiseClientEvent('Initialize');
	},
	/* support for browser "navigate-back" feature */
	/* to protect from exceptions on unexpected postback: use final format for '_clientState', */
	/* which is '[[[[]],[],[]],[{},[]],"??????"]' */
	_setVS:function(val)
	{
		if(val != null)
		{
			this._vs = val;
			/* BR23139: fix for "reset" button */
			if(this._vs0 == null)
				this._vs0 = val;
		}
		/* [0] - postbackEnter, [1] - (1-enabled)+(2-readOnly)+(4-focus), [2...] - value */
		this._setBackState(0, this._saveAdditionalClientState());
		return val;
	},
	_onSubmitOtherHandler:function(e)
	{
		if(this._fcs == 2)
			this._update();
		$IG.WebTextEditor.callBaseMethod(this, '_onSubmitOtherHandler', [e]);
	},
	/* initialize member variables if element is valid (has offsetWidth/Height) */
	_onTimer:function()
	{
		var elem = this._element;
		/* size (offsetWidth/Height) of control */
		if(this._once || !elem)
			return true;
		var width = elem ? elem.offsetWidth : 0;
		if(width == 0)
			return false;
		/* IE may fail to stretch height of <input> to its container */
		this._fixSize();
		this._once = true;
		this._fixSel = ($util.IsOpera || $util.IsSafari) ? 2 : (($util.IsFireFox) ? 1 : 0);
		if(this._initFoc)// || foc)
			this.focus();
		return true;
	},
	/* used by _onTimer and by TextEditorProvider of grid */
	_fixSize:function(width, height)
	{
		var elem = this._element, el = this._elem;
		var style = elem.style;
		if (height)
		{
			style.width = width;
			style.height = height;
		}
		else
			height = style.height;
		var but = this._buttons;
		if(!but)
			return;
		/* IE may fail to stretch height of <input> to its container */
		if(height && height.indexOf('px') > 0)
		{
			height = $util.toInt(height, 0);
			var h = 0, he = el.offsetHeight, hp = el.parentNode.clientHeight;
			if(he + 2 < hp)
				h = hp - 2;
			else if(height < he)
				h = height - 2;
			if(h > 2 && h < height)
				el.style.height = h + 'px';
		}
		/* IE/Opera do not stretch content of TD to 100% height, if another TD in TR has borders. */
		/* That happens when outer borders are moved into TD-container-of-input and height of */
		/* container-table-of-spin-buttons becomes smaller than height of control. */
		/* Try to increase height of content-table-of-spin-buttons beyond 100% to fill gaps above and below. */
		but = but[1];
		if(width || !but)/* || !($util.IsIE || $util.IsOpera))*/
			return;
		el = but.elem;
		while(el.nodeName != 'TABLE')
			if(!(el = el.parentNode))
				return;
		height = elem.clientHeight;
		var dif = height - el.offsetHeight;
		if(dif < 2 || height < 10 || $util.getStyleValue(null, 'height', el) != '100%')
			return;
		if($util.IsOpera)
			dif++;
		el.style.height = (100 + dif * 100 / height) + '%';
	},
	_val_i:function(o, i)
	{
		o = (o == null || o.length <= i) ? null : o[i];
		return (o == null) ? '' : o;
	},
	_int_i:function(o, i)
	{
		return $util.isEmpty(o = this._val_i(o, i)) ? -1 : parseInt(o);
	},
	_replace:function(str, v1, v2)
	{
		while(str.indexOf(v1) >= 0)
			str = str.replace(v1, v2);
		return str;
	},
	_initBut:function(e, o, once)
	{
		if(!e)
			return;
		var n = e.nodeName, i = -1;
		if(n && n.length < 4)
			e.unselectable = 'on';
		if(n == 'IMG')
		{
			o.imgE = e;
			return;
		}
		if(once && (n = e.childNodes) != null)
			while(++i < n.length)
				this._initBut(n[i], o);
	},
	_val:function()
	{
		return this._nullT ? '' : this._elem.value;
	},
	/* sets nullText if control has no focus and adjusts nullTextCss and negativeCss */
	_fixNull:function()
	{
		var nullTxt = this._nullText;
		if(!this._negCss && !nullTxt)
			return;
		var txt = this._val();
		this._nullT = null;
		if(txt == '' && nullTxt && this._fcs < 1)
		{
			this._nullT = true;
			this._elem.value = nullTxt;
		}
		this._fixCss(-1, -1);
	},
	/* return NullText or t and adjust NullText flag */
	_focTxt:function(t, foc, e)
	{
		this._nullT = null;
		if(!foc && t == '' && e != null && this._nullText)
		{
			t = this._nullText;
			this._nullT = true;
		}
		return t;
	},
	_focusTxt:function(foc, e)
	{
		if(e != null && !foc)
			this._valid(this._setVS(this._val()));
		return this._focTxt(this._val(), foc, e);
	},
	_repaint:function()
	{
		if(this._val() == this._text)
			return;
		this._elem.value = this._text;
	},
	get_inputElement:function()
	{
		/// <summary>Gets reference to edit field. Reference to INPUT or TEXTAREA html element.</summary>
		return this._elem;
	},
	get_spinUpElement:function()
	{
		/// <summary>Gets reference to upper spin button. Reference to TD html element or null.</summary>
		return this._elements[0];
	},
	get_spinDownElement:function()
	{
		/// <summary>Gets reference to lower spin button. Reference to TD html element or null.</summary>
		return this._elements[1];
	},
	get_maxLength:function()
	{
		/// <summary>
		/// Gets sets maximum length of text.
		/// Value of 0, means that maximum length is not set.
		/// Note: new value does not persist to server.
		/// </summary>
		return this._maxLen;
	},
	set_maxLength:function(val)
	{
		this._maxLen = val;
	},
	get_spinOnArrows:function()
	{
		/// <summary>
		/// Gets sets ability of up/down arrow keys to trigger spin actions.
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spArrows;
	},
	set_spinOnArrows:function(val)
	{
		this._spArrows = val;
	},
	get_spinEnsureFocus:function()
	{
		/// <summary>
		/// Gets sets ability to set input focus to control when buttons are clicked.
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spFocus;
	},
	set_spinEnsureFocus:function(val)
	{
		this._spFocus = val;
	},
	get_spinSpeedUp:function()
	{
		/// <summary>
		/// Gets sets rate to increase frequency of spin events if spin button is kept pressed.
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spSpeedUp;
	},
	set_spinSpeedUp:function(val)
	{
		this._spSpeedUp = val;
	},
	get_spinOnReadOnly:function()
	{
		/// <summary>
		/// Gets sets ability to modify value in controls by spin actions when read only is enabled.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spOnRead;
	},
	set_spinOnReadOnly:function(val)
	{
		this._spOnRead = val;
	},
	get_spinDelay:function()
	{
		/// <summary>
		/// Gets sets value in milliseconds which is used to delay next spin action when spin button is kept pressed.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spDelay;
	},
	set_spinDelay:function(val)
	{
		this._spDelay = val;
	},
	get_hideEnter:function()
	{
		/// <summary>
		/// Gets sets option to hide the Enter keydown event from browser.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._hideEnter;
	},
	set_hideEnter:function(val)
	{
		this._hideEnter = val;
	},
	get_autoPostBackOnEnterKeyDown:function()
	{
		/// <summary>
		/// Gets sets option to trigger postback when Enter key was pressed.<br />
		/// Not 0 value means that full (1) or async (2) postback will be raised when Enter key is pressed.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._postEnter;
	},
	set_autoPostBackOnEnterKeyDown:function(val)
	{
		this._postEnter = val;
	},
	get_autoPostBackOnCustomButtonClick:function()
	{
		/// <summary>
		/// Gets sets option to trigger postback on CustomButton click.<br />
		/// Not 0 value means that full (1) or async (2) postback will be raised when Enter key is pressed.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._postCustom;
	},
	set_autoPostBackOnCustomButtonClick:function(val)
	{
		this._postCustom = val;
	},
	get_autoPostBackOnValueChange:function()
	{
		/// <summary>
		/// Gets sets option to trigger postback when value was changed (after lost focus or similar).<br />
		/// Not 0 value means that full (1) or async (2) postback will be raised when Enter key is pressed.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._postValue;
	},
	set_autoPostBackOnValueChange:function(val)
	{
		this._postValue = val;
	},
	get_selectionOnFocus:function()
	{
		/// <summary>
		/// Gets sets option which is used for selection when control gets focus.<br />
		/// Possible values: 0 - select all text, 1 - unselect all and set caret to the beginning, 2 - unselect all and set caret to the end, 3 - browser default.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._selOnFoc + 1;
	},
	set_selectionOnFocus:function(val)
	{
		this._selOnFoc = val - 1;
	},
	get_enabled:function()
	{
		/// <summary>Gets sets enabled state of control.</summary>
		return !this._elem.disabled;
	},
	set_enabled:function(val)
	{
		/// <summary>Enables or disables control.</summary>
		if(this._elem.disabled == !val)
			return;
		this._elem.disabled = !(this._disabled = val);
		for(var i = 0; i < 3; i++)
			this._butState(i, val ? 0 : 3);
		this._setVS();
	},
	get_readOnly:function()
	{
		/// <summary>Gets sets read-only state of control.</summary>
		return this._readOnly;
	},
	set_readOnly:function(val)
	{
		this._readOnly = val;
		this._elem.readOnly = (val || this._calNoEdit) ? 'readonly' : '';
		this._setVS();
	},
	get_nullText:function()
	{
		/// <summary>
		/// Gets sets text which is used when value is not set (null or empty string) and control has no focus.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._nullText ? this._nullText : '';
	},
	set_nullText:function(val)
	{
		this._nullText = val;
	},
	get_text:function()
	{
		/// <summary>Gets sets text in control.</summary>
		var v = this._val();
		this._msV(v);
		return v;
	},
	set_text:function(val)
	{
		this._setVS(this._text = val);
		this._repaint();
		if(this._fix == 1)
			this._old = this._instant(true);
	},
	_instant:function(){ return this.get_text(); },
	get_value:function()
	{
		/// <summary>Gets sets value in control.</summary>
		return this._instant();
	},
	set_value:function(val)
	{
		this.set_text('' + ((val == null) ? '' : val));
		this._fixNull();
	},
	_spin:function(v)
	{
		if(this._fcs < 1 && (this._spFocus || this._nullText))
		{
			this.setFocus();
			if(this._fcs < 1)
			{
				this._focSpin = v;
				return;
			}
		}
		if(this._fireEvt(14, null, v))
			return;
		/* case when readOnly+spinOnReadOnly */
		if(this._nullT)
		{
			this._nullT = null;
			this._fixCss(-1, -1);
		}
		var t = this._val();
		this.spin(v);
		if(this._val() == t && this._spRoll && this._min != null && this._max != null)
		{
			var sel = this._sel0, fac = this._factor;
			if(!fac)
				fac = 1;
			v = this._limits(this.get_value(true) * fac, true);
			this.set_value(v / fac);
			this.select(sel);
		}
		if(this._val() != t)
		{
			this._spinPost = this._postValue;
			this._fireEvt(12);
			this._spinPost = false;
		}
		this._dtt();
	},
	_spinList:function(v)
	{
		var list = this._list;
		if(!list)
			return false;
		v = (v > 0) ? 1 : -1;
		var len = list.length, index = this._listIndex + v;
		if(index >= len)
		{
			if(!this._spRoll)
				return true;
			index = 0;
		}
		if(index < 0)
		{
			if(!this._spRoll)
				return true;
			index = len - 1;
		}
		var val = this._instant(true);
		if(val == list[index])
		{
			if((index += v) < 0)
			{
				if(!this._spRoll)
					return true;
				index = len - 1;
			}
			if(index >= len)
			{
				if(!this._spRoll)
					return true;
				index = 0;
			}
		}
		val = list[this._listIndex = index];
		if(this._date7)
			val = this._date7(val, -1);
		else if(this._toNum)
			val = parseFloat(val);
		this._fix = 0;
		this.set_value(val);
		this._fix = 1;
		return true;
	},
	spin:function(val)
	{
		/// <summary>Triggers spin event.</summary>
		/// <param name="val" type="Number">Value which is used to increment value in control. It can be positive or negative.</param>
		this._spinList(val);
	},
	_doKey:function(k, c, t, len, sel0, sel1)
	{
		if(sel0 != sel1)
		{
			t = t.substring(0, sel0) + t.substring(sel1);
			sel1 = sel0;
			len = t.length;
		}
		/* 7-del,8-back */
		else if(k == 7)
		{
			if(sel1++ >= len || len == 0)
				return;
			/* get around IE mess with new lines in textarea: delete 2 characters instead of 1 */
			if(this._ta && t.charCodeAt(sel1 - 1) == 13 && t.charCodeAt(sel1) == 10)
				sel1++;
		}
		else if(k == 8)
		{
			if(sel0-- < 1)
				return;
			/* get around IE mess with new lines in textarea: delete 2 characters instead of 1 */
			if(this._ta && t.charCodeAt(sel0) == 10 && t.charCodeAt(sel0 - 1) == 13)
				sel0--;
		}
		if(k < 9 || this._maxLen == 0 || this._maxLen > len)
		{
			if(k > 8 && sel1 >= len)
				t += c;
			else t = t.substring(0, sel0) + c + t.substring(sel1);
		}
		else k = 0;
		this._elem.value = t;
		this.select((k > 10) ? sel1 + 1 : sel0);
	},
	/* undo/redo value while focus */
	_undo:function(redo)
	{
		var val = this._old;
		if(redo)
		{
			if(!this._canRedo)
				return;
			val = this._redo;
			this._canRedo = false;
		}
		else
		{
			var old = this._instant(true);
			if(old == val)
				return;
			this._canRedo = true;
			this._redo = old;
		}
		this._fix = 0;
		this.set_value(val);
		this._fix = 1;
		this._text = this._focusTxt(false);
	},
	_doKey0:function(e, a)
	{
		var t0 = this._text, t1 = this._val(), k = this._key;
		/* that is request from key-down on Ctrl+V: validate current value in field */
		if(!e)
		{
			if(t0 != t1)
				this.paste(t1);
			return;
		}
		/* Special keys in NumPad of Opera break all filters and go into input (42,43,45,46,47) */
		if(this._thisType != 'edit' && $util.IsOpera && k > 41 && k < 48)
		{
			if(a == 0)
				this._noKey = k;
			else if(this._noKey == k)
				$util.cancelEvent(e);
		}
		if(a != 1)
			this._np = 2 - a;
		else if(this._np != 2)
			this._np = 1;
		if(k == 9)
			this._k0 = (a == 2) ? 0 : 9;
		if(k == 0 || this._fcs != 2 || (k == 114 && a != 1) || k == 9)
			return;
		if(this._bad > 2)
		{
			if(a == 0)
				this._bad = 2;
			if(a == 2)
				this._bad -= 3;
		}
		if(a == 0 && k == 229)
			if(t0 != t1)
				this._bad = 2;
			else
				this._bad += 3;
		/* Japanese Enter keyup in WebMaskEditor (fake "save-client-state" action) */
		if(k == 13 && this._k0 == 229 && this._thisType == 'mask')
			this._txt = this._setTxt(this._val(), 5, true);
		/* Ctrl+Z/Y undo/redo actions */
		if(a == 0 && e.ctrlKey && (k == 90 || k == 89))
		{
			this._undo(k == 89);
			return;
		}
		if(this._bad == 2 || (a == 1 && e.ctrlKey))
			return;
		/* (Ctrl+V) or (Shift+Insert) set request to validate value in editor and do paste */
		if(a == 0 && ((e.ctrlKey && k == 86) || (e.shiftKey && k == 45)))
			setTimeout(Function.createDelegate(this, this._doKey0), 1);
		if(a != 1 && (e.ctrlKey || e.altKey || k == 17))
		{
			if(e.altKey)
				this._k0 = -1;
			else if(t0 != t1 && (k == 86 || (k == 17 && a == 2)))
			{
				this.paste(t1);
				this._np = 1;
			}
			else if(k == 17)
				this.getSelectedText();
			if(a == 0 && (k == 38 || k == 40))
				this._doBut(e, a, 0);
			return;
		}
		if(a == 0)
			this._k0 = k;
		if(a == 2)
		{
			if(this._k0 > 0)
				this._k0 = 0;
			this._spinField = -1;
		}
		var len = t1.length, bad = this._bad != 0;
		if(k <= 46)
		{
			switch(k)
			{
				case 8: case 46:/* back del */
					if(this._k0 == k && a == 1)
						a = 2;
					if(a == 0)
					{
						a = 1;
						if(k == 46)
							k = 7;
					}
					break;
				case 27:
					$util.cancelEvent(e);
					if(a == 0)
						this._undo();
					return;
				case 13:/* enter */
					if(this._hideEnter)
						$util.cancelEvent(e);
					return;
				case 38: case 40:/* up down */
					if(this._ta)
						break;
					if(a == 0 && this._spArrows && !e.shiftKey)
						this._spin((k == 38) ? this._spDelta : -this._spDelta);
					if(this._k0 == k)
						a = 2;
					break;
			}
		}
		if(a == 1 && k == this._k0 && ((k < 48 && k > 9 && k != 32) || k > 90))
			return;
		if(!bad)
		{
			if(a != 0 && k != 9)
				$util.cancelEvent(e);
			if(a == 1 && this._k0 == -1)
			{
				this._k0 = 0;
				if(this._altDigit != 0)
					this.getSelectedText();
				else
					return;
			}
			if(a == 0 || k < 9)
				this.getSelectedText();
		}
		if(a == 1 && k > 6)
		{
			if(k > 31)
			{
				if(this._fireEvt(1, e, k))
				{
					if(bad)
						$util.cancelEvent(e);
					return;
				}
				k = this._key;
			}
			this._doKey(k, (k < 10) ? '' : String.fromCharCode(k), t1, len, this._sel0, this._sel1, bad, e);
		}
	},
	paste:function(val, bad)
	{
		/// <summary>Triggers paste action in control.</summary>
		/// <param name="val" type="String">Pasted text.</param>
		var m = this._maxLen;
		if(this._nullT || this._np == 1)
			return;
		if(m > 0 && m < val.length)
			val = val.substring(0, m);
		this._text = '';
		this._fix = 0;
		this.set_text(val, bad ? null : this._sel0);/* mask */
		this._fix = 1;
		this._fireEvt(12);
	},
	_onMouseUp:function(e)
	{
		this._butPressed = -1;
		this._clearSpin(true);
		if(e && e.target)
			this._fireEvt(4, e.rawEvent);
		if(this._upOn)
			$removeHandler(document, 'mouseup', this._upHandler);
		this._upOn = false;
	},
	_spinHandler:function(b, o)
	{
		var z = 0;
		if(o != null)
		{
			if(!o._upHandler)
				o._upHandler = Function.createDelegate(o, o._onMouseUp);
			if(!o._upOn)
			{
				$addHandler(document, 'mouseup', o._upHandler);
				o._upOn = true;
			}
			o.delay = o._spDelay;
			$util._edit_o = o;
			z++;
			o._spinField = -1;
			if(o._fcs < 1 && o._spFocus)
			{
				o._evt0Spin1 = 1;
				o.setFocus();
			}
		}
		else
		{
			if((o = $util._edit_o) == null)
				return;
			b = o._buttons;
			if(b)
				b = b[0] && b[0]._state == 2;
			if(o._spSpeedUp > 1)
			{
				if(o.delay > o._spDelay / o._spSpeedUp)
					z = o.delay = Math.ceil(o.delay * 6 / 7);
			}
			if(o._spSpeedUp < 1)
			{
				if(o.delay < o._spDelay / o._spSpeedUp)
					z = o.delay = Math.ceil(o.delay * 7 / 6);
			}
		}
		o._spin(b ? o._spDelta : -o._spDelta);
		if(z == 0)
			return;
		o._clearSpin();
		$util._edit_f = window.setInterval(o._spinHandler, o.delay);
	},
	/* 0-normal, 1-hover, 2-press, 3-disabled */
	_butState:function(id, state)
	{
		var e, i = -1, but = this._buttons;
		if(but)
			but = but[id];
		if(!but || but._state == state)
			return;
		while(i++ < 3)
			if(i != id && (e = this._buttons[i]) != null) if(e._state == 1 || e._state == 2)
				this._butState(i, 0);
		if(id < 2 && (state == 2 || but._state == 2))
		{
			this._clearSpin(true);
			if(state == 2)
				this._spinHandler(id == 0, this);
		}
		this._fixCss(id, state);
		/* reference to IMG */
		e = but.imgE;
		if(!e)
			return;
		/* list of image-src for different states */
		but = but.img;
		/* verify image for normal state */
		if(!but[0])
			but[0] = e.src;
		/* image for required state */
		i = but[state];
		/* use normal image as back-up */
		if(!i)
			i = but[0];
		if(e.src != i)
		{
			e.src = i;
			/* IE bug: it does not keep src as it was set */
			but[state] = e.src;
		}
	},
	/* fix css for elem id: -1-control, 0-upper button, 1-lower button, 2-custom button */
	_fixCss:function(id, state)
	{
		var css, elem = this._element, obj = this._buttons;
		if(id < 0)
			obj = this;
		else
		{
			obj = obj ? obj[id] : null;
			if(!obj)
				return;
			elem = obj.elem;
		}
		if(state < 0)
			state = obj._state;
		else
			obj._state = state;
		/* _css: 0-normal css, 1-hover css, 2-press css, 3-disabled css, 4-focus css, 5-hover+focus css, 6-press+focus css */
		if(!obj._css)
			return;
		var css = obj._css[state = (this._fcs > 0) ? (state + 4) : state];
		/* check for extra/special css like nullText and negative number */
		var cssNeg = this._negCss, css2 = this._nullCss;
		if(id < 0 && (this._nullText || cssNeg))
		{
			/* css should be set only to INPUT */
			var edit = this._elem;
			/* build value of extra css2 (inluding space separator in front of it) */
			/* control has nullText and no focus */
			if(this._nullT)
				css2 = ' ' + css2;
			/* control may have negative number */
			else if(cssNeg)
			{
				var v = this._instant(true);
				css2 = (!v || v >= 0) ? '' : ' ' + cssNeg;
			}
			/* INPUT does not need extra css */
			else
				css2 = '';
			/* if main element is INPUT, then append extra css */
			if(elem == edit)
				css += css2;
			/* if main element not INPUT (table), then adjust css of INPUT */
			else
			{
				/* original css of INPUT */
				if(!this._cssElem)
					this._cssElem = edit.className;
				css2 = this._cssElem + css2;
				if(edit.className != css2)
					edit.className = css2;
			}
		}
		if(elem.className != css)
			elem.className = css;
		/* check for css of inner object */
		if(!obj._cssI)
			return;
		css = obj._cssI[state];
		elem = this._elem.parentNode;
		if(elem.className != css)
			elem.className = css;
	},
	/* a: 3-MouseDown, 4-MouseUp, 5-MouseMove, 6-MouseOver, 7-MouseOut */
	_doBut:function(e, a, id)
	{
		if(a == 3)
			$util.cancelEvent(e);
		if(!this.get_enabled() || id > 2)
			return;
		if(id < 2 && this._readOnly && !this._spOnRead)
			return;
		/* a: 3-MouseDown, 4-MouseUp */
		if(a == 4)
			this._butPressed = -1;
		else if(a != 3 && e.button != 0 && this._butPressed < 0)
			return;
		var b = this._buttons[id];
		if(!b)
			return;
		/* a: 7-MouseOut, check for inner element of button */
		if(a == 7 && !$util.isOut(e, b.elem))
			return;
		b = this._butPressed;
		/* a: 3-MouseDown */
		if(a == 3)
		{
			if(b >= 0)
				this._butState(b, 0);
			this._butPressed = -2;
			if(e.button < 2)
			{
				this._butPressed = id;
				this._butMouse = e.button;
				this._butState(id, 2);
			}
			/* toggle drop-down calendar */
			if(this._cal)
				this._doCal(e);
			else if(id == 2)
				this._customBut(e);
			return;
		}
		if(e.button == 0 && b < -1)
			b = this._butPressed = -1;
		/* a: 5-MouseMove */
		if(b >= 0 && a == 5) if(e.button != this._butMouse)
		{
			b = this._butPressed = -1;
			this._butState(id, 1);
			return;
		}
		if(b < -1 || (b >= 0 && b != id))
			return;
		/* a: 7-MouseOut */
		this._butState(id, (a == 7) ? 0 : ((b >= 0) ? 2 : 1));
	},
	_enterTxt:function(){ return this._val(); },
	_update:function(post)
	{
		if(this._lock)
			return;/*BR29871: process valueChanged with alert(), enter part value in mask, keep mouse within text, press enter: 2 alerts.*/
		this._lock = true;
		this._text = this._focusTxt(false, (this._fcs == 2 || this._hadFocus) ? '' : null);//''-still focus
		var v = this._instant(true);
		var old = this._old;
		if(v != null && old != null)
			if(v.getTime != null && v.getTime() == old.getTime())
				v = old;
		if(v != old || this._bad == 2)
		{
			this._val10 = v;
			if(this._fireEvt(10, null, v, old))
			{
				this._fix = 0;
				this.set_value(old);
				this._fix = 1;
				this._text = this._focusTxt(false);
			}
			else
			{
				if(v != this._val10)
					this.set_value(this._val10);
				/* if application calls get_text() within ValueChanged event, then text can be wrong */
				this._repaint();
				v = this._instant(true);
				this._fireEvt(11, null, v, old);
				if(!this._posted) if(this._k0 != 13 || this._postEnter > 0 || this._postValue == 0)
					this._old = v;
				this._dtt();
			}
		}
		this._lock = false;
	},
	/* return 1 if k is hot key to trigger custom button click */
	_doHotKey:function(e, k)
	{
		var keys = this._hotKeys;
		var i = (keys && k < 999 && k > 0) ? keys.length : 0;
		if(i == 0)
			return;
		if(e.shiftKey)
			k += 1000;
		if(e.ctrlKey)
			k += 2000;
		if(e.altKey)
			k += 4000;
		while(i-- > 0)
			if(keys[i] == k)
				break;
		if(i < 0)
			return;
		this._customBut(e);
		return 1;
	},
	_customBut:function(e)
	{
		if(this._fireEvt(15, e))
			return;
		/* show drop-down calendar */
		if(this._calID)
			this._doCal(e, true);
	},
	_onEvt:function(evt)
	{
		var e = evt ? evt.rawEvent : null;
		if(!e || !this.get_enabled())
			return;
		var src = evt.target;
		var v = src ? src._editID : -1;
		if(!v)
			v = src.parentNode._editID;
		if(!v)
			v = -1;
		if(v > 0) v--;
		this._e_elemID = v;
		var type = this._eventList.length, s = e.type.toLowerCase();
		while(type-- > 0)
			if(this._eventList[type].toLowerCase() == s)
				break;
		/* 0-KeyDown, 1-KeyPress, 2-KeyUp, 3-MouseDown, 4-MouseUp, 5-MouseMove, 6-MouseOver, 7-MouseOut, 8-Focus, 9-Blur */
		if(type < 0)
			return;
		if(this._evt0Spin1 == null)
		{
			try
			{
				if(this._elem.selectionStart != null)
					this._tr = 1;
			}catch(ex){}
			if(this._tr != 1)
				this._tr = (this._elem.createTextRange != null) ? this._elem.createTextRange() : null;
			this._bad = (this._tr == null) ? 1 : 0;
		}
		this._evt0Spin1 = 0;
		/* cut from mask */
		/* 5-MouseMove */
		if(type == 5 && this._fcs == 2 && e.button == 1)
			this.getSelectedText();
		var k, time = (new Date()).getTime();
		/* 0-KeyDown, 1-KeyPress, 2-KeyUp */
		if(type < 3)
		{
			k = e.keyCode;
			if(k == 0 || k == null)
				if((k = e.which) == null)
					k = 0;
			/* that may happen in grid-editor under Opera on "+" key */
			/* k=86: skip possible paste by Ctrl+V */
			if(type == 2 && this._k0 == 0 && k > 0 && k != 86 && this._text != this._val())
			{
				this._elem.value = this._text;
				return;
			}
			if(this._calKey && this._calKey(e, k, type))
				return;
			if(type == 0 && this._doHotKey(e, k) == 1)
				return;
			this._key = k;
			this._time = time;
		}
		/* 1-KeyPress */
		if(type != 1) if(this._fireEvt(type, e)) if(type < 8)
		{
			if(type < 4)
				$util.cancelEvent(e);
			return;
		}
		/* 5-MouseMove, 6-MouseOver, 7-MouseOut */
		if(type > 4 && type < 8)
		{
			var over = (type != 7 || !$util.isOut(e, this._element)) ? 1 : 0;
			if(over != this._state)
				this._fixCss(-1, over);
		}
		if(v >= 0)
		{
			this._doBut(e, type, v);
			return;
		}
		/* close drop-down calendar */
		/* 3-MouseDown */
		if(type == 3 && this._calID)
			this._doCal(e);
		var foc = this._focTime;
		/* 4-MouseUp */
		if(type == 4)
		{
			/* if focus was set by mouse click, then validate selectionOnFocus, */
			/* because mouseup under Mozilla may set caret and distroy selection */
			if(foc && foc + 500 > time)
				this._select();
			/* clear for double click */
			this._focTime = 0;
		}
		if(type < 3)
			this._doKey0(e, type);
		var val = this._val();
		/* 2-KeyUp */
		if(type == 2)
		{
			this._last = val;
			/* Firefox has list of last strings (like paste) and new value may come from nowhere on mousedown or enter */
			if(this._key == 13 && this._fixSel == 1 && this._text != val)
			{
				this.set_text(val);
				this._fireEvt(12, e);
				this._update(this._postValue);
			}
		}
		/* 8-Focus, 9-Blur */
		if(type >= 8)
		{
			if(this._bad > 2)
				this._bad = 2;
			this._spinField = -1;
			foc = (type == 8);
			if(foc == (this._fcs > 0))
				return;
			v = (!this._elem.readOnly && this.get_enabled()) ? 2 : 1;
			this._np = 0;
			this._fcs = foc ? v : 0;
			if(v == 1)
				return;
			this._hadFocus = !foc;
			if(foc)
			{
				this._k0 = 0;
				if(this._nullT)
					val = this._last = this._text = this._elem.value = '';
				this._nullT = null;
				if(this._bad > 1)
					this._bad = 0;
				if(val != this._text)
				{
					this.getSelectedText();
					this.paste(val);
				}
				this._lastText = this._last = this._text = this._focusTxt(foc, e);
				this._focTime = time;
				$util._focusedCtl = this;
			}
			else
			{
				$util._focusedCtl = null;
				this._canRedo = null;
				/* temporary enable focus state, because set_text may fail. Remove, this._fix=1 to disable this._old-change (ValueChange+fast-Tab). */
				if(this._last != val || this._bad != 0)
				{
					v = this._fix;
					this._fix = 0;
					this._fcs = 2;
					this.set_text(val);
					this._fcs = 0;
					this._fix = v;
				}
				this._update(this._postValue);
				/* close drop-down calendar */
				if(this._cal)
					this._doCal(e);
			}
			this._repaint();
			/* adjust focus css for input and buttons */
			for(v = -1; v < 3; v++)
				this._fixCss(v, -1);
			/* this._gridKey is flag/keyCode set by GridEditBase.__internalEnterEditMode->TextEditorProvider.set_value */
			/* which tells that edit mode was started by keypress */
			/* fake keypress action */
			if(foc && this._gridKey)
			{
				/* select all text in order to remove old text */
				this._sel0 = 0;
				this._sel1 = this._text.length;
				/* use dummy not 0 and not equal to this._key value to trick validation logic for keypress */
				this._k0 = 20;
				/* fake keypress with key */
				this._key = this._gridKey;
				this._doKey0({}, 1);
			}
			/* _selOnFoc: -1-select all, 0-caret to start, 1-caret to end, 2-browser default */
			else if(foc && this._selOnFoc < 2)
			{
				this.select(this._selOnFoc * 10000);
				/* if focus is set by Tab, then under Mozilla select() may fail */
				/* and default whole text will be selected: select with delay */
				this._select();
			}
			this._hadFocus = false;
			this._dtt();
			if(foc && this._doCal && this._calOnFoc)
				this._doCal(e, true);
			/* _focSpin is a flag set by the _spin, when no-focus-spin is not allowed */
			/* so, when focus is received, then send "continue" spin logic back to its sender _spin function */
			if(foc && this._focSpin)
				this._spin(this._focSpin);
			this._gridKey = this._focSpin = null;
			return;
		}
		if(!this._nullT && val != this._text)
		{
			/* 4-MouseUp, 5-MouseMove, 6-MouseOver', 7-MouseOut */
			if(type > 3 && this._k0 == 0)
			{
				this.paste(val, 1);
				return;
			}
			this._text = val;
			this._fireEvt(12, e);
		}
	},
	/* event raised by end animation of drop-down calendar (or another future animation) */
	_stop:function(show)
	{
		/* 0-event, 1-postBackAction, 2-open or close action */
		this._raiseClientEvent('CalendarAnimationStopped', 'DatePickerAnimationStopped', null, null, show);
	},
	_fireEvt:function(id, evnt, arg, a2)
	{
		var postFlag = null, evtClass = null, name = this._eventList[id];
		/* 12-TextChanged */
		if(id == 12)
		{
			if((a2 = this._lastText) == (arg = this._val()))
				return false;
			evtClass = 'TextEditor' + name;
			this._lastText = this._text = arg;
			if(this._fcs < 2 && this._evt0Spin1 != 1)
				this._update();
			if(this._negCss)
				this._fixCss(-1, -1);
		}
		/* mouseup */
		if(id == 4)
		{
			/* resolve local and global mouseup events: raise only once */
			var last = this._lastUp, time = (new Date()).getTime();
			if(last && last + 50 > time)
				return;
			this._lastUp = time;
		}
		var cancel = false;
		/* 13-InvalidValue */
		if(id == 13)
		{
			if(this._thisType == 'num')
				evtClass = 'Numeric';
			else if(this._thisType == 'date')
				evtClass = 'DateTime';
			else if(this._thisType == 'mask')
				evtClass = 'Mask';
			else
				return false;
			evtClass += 'EditorInvalidValue';
		}
		/* 15-CustomButton */
		else if(id == 15)
		{
			evtClass = 'Cancel';
			if((postFlag = this._postCustom) > 0)
			{
				this._update();
				/* 0-no post, 1-post Enter, 2-post CustomButton */
				this._postFlag = 2;
			}
		}
		/* 14-spin */
		else if(id == 14)
		{
			evtClass = 'TextEditorSpin';
		}
		/* 12-TextChanged */
		else if((id < 3 || id > 9) && id != 12)
		{
			evtClass = 'TextEditor' + ((id == 0 || id == 2) ? 'Key' : name);
			if(id < 3)
			{
				arg = this._key;
				/* enter keydown */
				if(arg == 13 && id == 0)
				{
					if((postFlag = this._postEnter) > 0)
					{
						this._valid(this._enterTxt());
						this._update();
						/* 0-no post, 1-post Enter, 2-post CustomButton */
						this._postFlag = 1;
					}
				}
			}
			if(id == 11)
			{
				if(this._fcs == 2)
					this._update();
				/*
				else if(this._fcs == 0 && this._k0 != 9) try
				{
					if(document.activeElement)
						document.activeElement.fireEvent('onblur');
					else
						window.blur();
				}
				catch(ex){}
				*/
			}
		}
		/* mousedown */
		else if(id < 4)
			evtClass = 'Cancel';
		var args = this._raiseClientEvent(name, evtClass, evnt, postFlag, arg, a2);
		/* check for cancel/change by user */
		if(args)
		{
			if(args.get_cancel && args.get_cancel())
			{
				cancel = true;
				/* validate for post event, because, it can be another event after "post" */
				if(postFlag)
					/* 0-no post, 1-post Enter, 2-post CustomButton */
					this._postFlag = 0;
			}
			else
			{
				if(id == 10)
					this._val10 = args.get_value();
				if(id < 3)
					this._key = args.get_keyCode();
			}
		}
		return cancel;
	},
	/* MS validators */
	_msV:function(v)
	{
		this._vld = 0;
		var span = this._elemMSV;
		if(span)
			span.value = v;
		return span;
	},
	getSpinButtonID:function()
	{
		/// <summary>Gets index of spin button which is involved in current mouse event of browser. That can be used while processing mouse events of control.</summary>
		/// <returns type="Number">0: upper spin button, 1: lower spin button, -1: no spin button is related to current event.</returns>
		return this._e_elemID;
	},
	/* that can be called by WebTab in order to validate instant value in control */
	_onValidate:function()
	{
		this._valid(this._enterTxt());
	},
	/* notify dot-net validators, etc. */
	_valid:function(v)
	{
		/* after initialization and control has validators */
		if(this._prop1 || !this._elemMSV || !this._msV(v))
			return;
		/* flag for WebMaskEditor to build empty text for empty value */
		this._non = true;
		var v = this._instant(true);
		this._non = false;
		var old = this._old;
		/* Dates are never equal, so to compare, use their ticks */
		if(v != null && old != null)
			if(v.getTime != null && v.getTime() == old.getTime())
				v = old;
		if(v == old)
			return;
		/* check for focus-on-error validator and mimic default dot-net implementation */
		v = this.Validators;
		/* dot-net sets focus back only once and uses Page_InvalidControlToBeFocused as flag */
		var i = (v && window['Page_InvalidControlToBeFocused'] == null) ? v.length : 0;
		/* notify validators about change */
		ValidatorOnChange({ srcElement: this });
		/* if validator failed and it should keep focus on error, then set focus back to editor */
		while(i-- > 0)
		{
			if(v[i].focusOnError == 't' && v[i].isvalid === false)
			{
				window['Page_InvalidControlToBeFocused'] = this._elem;
				this._elem.focus();
				break;
			}	
		}
	},
	_select:function(x)
	{
		/* used for Mozilla */
		/* _selOnFoc: -1-select all, 0-caret to start, 1-caret to end, 2-browser default */
		var elem = this._elem, sel0 = this._selOnFoc;
		if(this._tr != 1 || sel0 > 1)
			return;
		/* flag to set timer */
		if(!x)
		{
			window.setTimeout("try{ig_controls['" + this._id + "']._select(1);}catch(e){}", 0);
			return;
		}
		var sel1 = elem.value.length;
		/* -1: select all, 0:caret to start, 1:caret to end */
		if(sel0 == 0)
			sel1 = 0;
		else if(sel0 < 0)
			sel0 = 0;
		else
			sel0 = sel1;
		if(sel0 != elem.selectionStart || sel1 != elem.selectionEnd)
			this.select(sel0, sel1);
	},
	select:function(sel0, sel1)
	{
		/// <summary>Sets selection and caret position in control.</summary>
		/// <param name="sel0" type="Number" optional="true" mayBeNull="true">Start selection. If it is missing, then all text in control is selected.</param>
		/// <param name="sel1" type="Number" optional="true" mayBeNull="true">End selection. If it is missing, then caret is set at start selection.</param>
		var elem = (this._fcs == 2) ? this._elem : null;
		if(!elem || elem.offsetWidth < 2)
			return;
		var val = elem.value;
		var i = val.length, tr = this._tr;
		if(sel1 == null)
		{
			sel1 = sel0;
			if(sel0 == null || sel0 < 0)
			{
				sel0 = 0;
				sel1 = i;
			}
		}
		if(sel1 >= i)
			sel1 = i;
		else if(sel1 < sel0)
			sel1 = sel0;
		if(sel0 > sel1)
			sel0 = sel1;
		this._sel0 = sel0;
		this._sel1 = sel1;
		/* Mozilla */
		if(tr == 1)
		{
			if(this._fixSel == 1)
				elem.readOnly = 'readonly';
			elem.selectionStart = sel0;
			elem.selectionEnd = sel1;
			if(this._fixSel == 1)
				elem.readOnly = '';
			return;
		}
		/* try:IE8+UpdatePanel+TAB_key have problems with selection object */
		try
		{
			/* unknown selection model or error */
			if(!tr)
			{
				if(sel0 != sel1)
					elem.select();
				return;
			}
			/* all below is IE */
			if(this._ta)
			{
				/* get around IE-TEXTAREA mess with '\t' */
				var fix0 = 0, fix1 = 0, j = sel1;
				while(j-- > 0) if(val.charCodeAt(j) == 10)
				{
					if(j < sel0)
						fix0++;
					fix1++;
				}
				sel0 -= fix0;
				sel1 -= fix1;
			}
			sel1 -= sel0;
			if(this._ta)
				tr.moveToElementText(elem);
			else
				tr.move('textedit', -1);
			tr.move('character', sel0);
			if(sel1 > 0)
				tr.moveEnd('character', sel1);
			/* Bug 23061. IE8 may raise exception on next line */
			tr.select();
		}
		catch(ex){}
	},
	getSelectedText:function()
	{
		/// <summary>Gets selected text. It also calculates internal variable for end and start selection.</summary>
		/// <returns type="String">Selected text.</returns>
		var txt = '', elem = this._elem, tr = this._tr;
		var sel0 = this._sel0 = this._sel1 = 0;
		/* unknown selection model or error */
		if(tr == null)
			return txt;
		/* Mozilla */
		if(tr == 1)
		{
			if((this._sel0 = elem.selectionStart) < (this._sel1 = elem.selectionEnd))
				txt = elem.value.substring(this._sel0, this._sel1);
			return txt;
		}
		/* all below is IE */
		/* try:IE8+UpdatePanel+TAB_key have problems with selection object */
		try
		{
			/* Bug 23061. IE8 may raise exception on next line */
			var range = document.selection.createRange(), val = elem.value;
			var i = val.length;
			tr = range.duplicate();
			if(this._ta)
				tr.moveToElementText(elem);
			else
				tr.move('textedit', -1);
			try
			{
				while(tr.compareEndPoints('StartToStart', range) < 0)
				{
					tr.moveStart('character', 1);
					sel0++;
					/* get around IE-TEXTAREA mess with '\t' */
					if(this._ta && val.charCodeAt(sel0) == 10)
						sel0++;
					if(sel0 > i)
						break;
				}
			}
			catch(ex){}
			txt = range.text;
		}
		catch(ex){}
		this._sel0 = sel0;
		this._sel1 = sel0 + txt.length;
		return txt;
	},
	getSelection:function(start)
	{
		/// <summary>Gets position of start or end selection. Note: that method calls getSelectedText().</summary>
		/// <param name="start" type="Boolean">Value of true: return start selection, false: return end selection.</param>
		/// <returns type="Number">Position of selection.</returns>
		this.getSelectedText();
		return start ? this._sel0 : this._sel1;
	},
	focus:function(delay)
	{
		/// <summary>Ses input focus to control with delay.</summary>
		/// <param name="delay" type="Number">Delay in milliseconds.</param>
		window.setTimeout("try{ig_controls['" + this._id + "'].setFocus();}catch(e){}", delay ? delay : 0);
	},
	setFocus:function()
	{
		/// <summary>Ses input focus to control without delay.</summary>
		try{this._elem.focus();}catch(i){}
	},
	hasFocus:function()
	{
		/// <summary>Checks if control has input focus.</summary>
		/// <returns type="Boolean">Value of true means that control has focus.</returns>
		return this._fcs > 0;
	},
	_jpn:function(k){ return(this._sTxt == 1 && k > 65295 && k < 65306) ? (k - 65248) : k; },
	_dtt:function()
	{
		if(!this._dt)
			return;
		var val = this._val();
		if(val == '' && this._nullText)
			val = this._nullText;
		this._element.title = this._elem.title = this._elem.alt = this._dt.replace('{0}', val);
	},
	_clearSpin:function(o)
	{
		if(!$util._edit_f)
			return;
		window.clearInterval($util._edit_f);
		$util._edit_f = null;
		if(o)
			$util._edit_o = null;
	},
	/* persist values to server in chars-format */
	/* [0] - postbackEnter, [1] - (1-enabled)+(2-readOnly)+(4-focus), [2...] - value */
	_saveAdditionalClientState:function()
	{
		/* 0-no post, 1-post Enter, 2-post CustomButton */
		var val = '' + this._postFlag;
		val += ((this._disabled ? 0 : 1) + (this._readOnly ? 2 : 0) + (this.hasFocus() ? 4 : 0));
		return val + this._vs;
	},
	dispose:function()
	{
		/// <summary>Disposes object and event handlers.</summary>
		/* input field */
		var elem = this._element, e = this._elem;
		if(!e || !elem)
			return;
		this._elem = null;
		$clearHandlers(elem);
		if(e != elem)
			$clearHandlers(e);
		this._onMouseUp();
		if(this._doCal)
			this._doCal();
		if(this._animation)
			this._animation.dispose();
		/* possible shared-default-editor provider used by grid */
		e = elem.control;
		/* dispose shared-default-editor provider */
		if(e && e._getWrapper)
			/* 2-flag to dispose */
			e.dispose(2);
		$IG.WebTextEditor.callBaseMethod(this, 'dispose');
	}
}
$IG.WebTextEditor.registerClass('Infragistics.Web.UI.WebTextEditor', $IG.ControlMain);

$IG.WebMaskEditor = function(elem)
{
	/// <summary>Class which implements client side functionality of WebMaskEditor.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebMaskEditor.initializeBase(this, [elem]);
}
$IG.WebMaskEditor.prototype =
{
	_thisType:'mask',
	initialize:function()
	{
		/// <summary>Initializes instance of WebMaskEditor.</summary>
		$IG.WebMaskEditor.callBaseMethod(this, 'initialize');
		var prop1 = this._prop1;
		prop1[0] = this._replace(prop1[0], '~^+=', '\03');/* Atlas chocks on \03,- restore server-flag */
		var prop = this._val_i(prop1, 2);
		this._prompt = prop.charAt(0);
		this._pad = prop.charAt(1);
		this._empty = prop.charAt(2);
		this._mode = parseInt(prop.charAt(3));
		this._minFields = parseInt(prop.charAt(4));
		var i = parseInt(prop.charAt(5));
		this._good = (i & 1) != 0;
		this._reduce = (i & 2) != 0;
		this._cutMask = (i & 4) != 0;
		i = parseInt(prop.charAt(6));
		this._calOnFoc = (i & 1) != 0;
		this._cal_key = (i & 2) != 0;
		if((i & 4) != 0)
		{
			this._elem.readOnly = 'readonly';
			this._calNoEdit = true;
		}
		prop = this._val_i(prop1, 1);
		if(prop1.length > 3)
			prop = this._getMask(prop);
		this._setMask(prop);
		if(this._thisType == 'mask')
			this._initEnd();
	},
	_maskFlag:function(c, u)
	{
		switch(c)
		{
			case '>': return -1;
			case '<': return -2;
			case '&': c = 1;break;
			case 'C': c = 2; break;
			case 'A': c = 7; break;
			case 'a': c = 8; break;
			case 'L': c = 13; break;
			case '?': c = 14; break;
			case '0': return 19;
			case '9': return 20;
			case '#': return 21;
			default: return 0;
		}
		return c + u * 2;
	},
	_maskFilter:function(flag, s, i, sf)
	{
		if(i >= s.length)
			return sf;
		var c = s.charCodeAt(i), f = Math.floor((flag - 1) / 6);
		s = s.charAt(i);
		if(c < 22)
			return sf;
		if(f == 1 || f == 3) if(c > 100) if((c = this._jpn(c)) < 100)
			s = String.fromCharCode(c);
		switch(f)
		{
			case 0: break;
			case 1: if(c > 47 && c < 58) return s;
			case 2: if(c > 255 || s.toUpperCase() != s.toLowerCase()) break;
				return sf;
			/* flag==21==# optional and allows digits and +/-, it should be replaced by Space */
			case 3: return ((flag == 21 && (s == '-' || s == '+')) || (c > 47 && c < 58)) ? s : sf;
		}
		if((flag = Math.floor((flag - 1) / 2) % 3) == 0)
			return s;
		return (flag == 2) ? s.toLowerCase() : s.toUpperCase();
	},
	_getTxt:function(vt, prompt, t)
	{
		var flag, mask = this._mask, o = '', non = (t != null);
		if(!non)
			t = (this._bad != 0 && this._fcs > 1) ? this._val() : this._txt;
		if(non || this._fcs < 0)
			non = this._minFields == 0;
		/* flag which was set while validation for MSValidators */
		if(this._non)
			non = true;
		if(t == null || mask == null)
			return o;
		var len = mask.length;
		var iLast = (this._fcs > 1 && this._cutMask) ? -1 : len;
		for(var i = 0; i < len; i++) if((flag = mask.charCodeAt(i)) < 22)
		{
			if(i < t.length && t.charCodeAt(i) >= 22)
			{
				o += t.charAt(i);
				if(i > iLast)
					iLast = i;
				non = false;
			}
			else if(vt % 3 == 2 || (vt % 3 == 1 && (flag & 1) == 1))
				/* flag==21==# optional and allows digits and +/-, it should be replaced by Space */
				o += (flag == 21 && prompt == '') ? this._pad : prompt;
		}
		else if(vt >= 3)
		{
			o += mask.charAt(i);
			if(i == iLast + 1)
			{
				if(this._selK == i)
					this._selK++;
				iLast++;
			}
		}
		if(iLast++ < len)
			o = o.substring(0, iLast);
		return non ? '' : o;
	},
	_setTxt:function(v, vt, render)
	{
		var c, flag, j = 0, i = -1, mask = this._mask, t = this._mask;
		if(v != null) while(++i < mask.length)
		{
			if(vt == 1000 + j)
				vt = this._mode;
			if(j >= v.length)
				break;
			if((flag = mask.charCodeAt(i)) < 22)
			{
				if((c = this._maskFilter(mask.charCodeAt(i), v, j)) != null)
					t = t.substring(0, i) + c + t.substring(i + 1);
				j++;
			}
			else if(vt >= 3)
				j++;
		}
		if(render)
			return t;
		this._txt = t;
		this._text = this._focusTxt(this._fcs > 1, ' ');
		this._repaint();
	},
	get_inputMask:function()
	{
		/// <summary>Gets input mask.</summary>
		/// <returns type="String">Input mask.</returns>
		return this._m0;
	},
	_setMask:function(mask)
	{
		if(mask == null)
			mask = '';
		this._m0 = mask;
		var x, c, i, i0 = 0, u = 0, n = '', t = '', t0 = this._getTxt(0);
		for(i = 0; i < mask.length; i++)
		{
			if((x = this._maskFlag(c = mask.charAt(i), u)) != 0)
			{
				if(x < 0)
				{
					u = (u == -x) ? 0 : -x;
					continue;
				}
				n += (c = String.fromCharCode(x));
				c = this._maskFilter(x, t0, i0++, c);
			}
			else if(c == '\\' && i + 1 < mask.length && this._maskFlag(mask.charAt(i + 1), 0) != 0)
				n += (c = mask.charAt(++i));
			else
				n += c;
			t += c;
		}
		this._txt = t;
		this._mask = n;
	},
	/* build mask for date editor */
	_getMask:function(v, d)
	{
		if(this._field0IDs == null)
			this._field0IDs = new Array();
		if(this._field1IDs == null)
			this._field1IDs = new Array();
		if(v == null)
			v = '';
		var x, i, i0 = 0, flag = -1, t = '';
		for(i = 0; i < v.length; i++)
		{
			x = v.charCodeAt(i);
			if(x < 48 || x > 57)
			{
				if(d == true && (flag = v.charAt(i)) == '\\' && i + 1 < v.length)
				{
					if((x = v.charAt(++i)) == '\\')
						continue;
					if(x == '0' || x == '9')
						t += flag;
					t += x;
				}
				else
					t += v.charAt(i);
				continue;
			}
			flag = (x - 48) * 10 + v.charCodeAt(++i) - 48;
			if(d == true)
			{
				this._field1IDs[i0++] = flag;
				t += '\01';
				continue;
			}
			this._field0IDs[i0++] = flag;
			if(flag == 14)
				t += 'L';
			else if(flag == 15)
				t += 'LL';
			else if(flag == 22)
				t += '0';
			else
			{
				t += '00';
				if(flag == 3)
					t += '00';
				while(flag-- > 23)
					t += '0';
			}
		}
		return t;
	},
	_focusTxt:function(foc, e)
	{
		var t = null;
		if(e != null && !foc)
		{
			e = e !== '';
			if(e && this._bad != 0)
				this._txt = this._setTxt(this._val(), 5, true);
			t = this._txt;
			var inv = t.length;
			if(!e && this._hadFocus)
			{
				var iL = inv - this._val().length, s0 = this._sel0, s1 = this._sel1;
				if(iL > 0 && s1 - s0 == iL)
					this._txt = t = t.substring(0, s0) + this._mask.substring(s0, s1) + t.substring(s1);
			}
			while(inv-- > 0)
			{
				var c = t.charCodeAt(inv);
				/* flag==21==# optional and allows digits and +/-, it should be replaced by Space */
				/* skip 21 for validation of required character */
				if(c < 21 && (c & 1) == 1)
					break;
			}
			if(!e && inv >= 0)
			{
				var val = this.get_value();
				this._fireEvt(13, null, inv = {value:val});
				if(val != inv.value)
					this.set_value(inv.value);
			}
			/* BR29103. Get around following bug in IE7: when input.value is set to [013] or [010] char, then it replaces it by 2 chars [013][010]. */
			/* That nice new feature kills architecture of mask, when it contains L or > flag. */
			/* So, below logic replaces 13 or 10 by 14. */
			/* Logic on server ignores flags in postback mask, so, replacing 13 or 10 by any other 1..28 flag should not bring problem. */
			this._setVS(this._replace(this._replace(t = this._txt, String.fromCharCode(13), String.fromCharCode(14)), String.fromCharCode(10), String.fromCharCode(14)));
			this._valid(this._getTxt(this._mode, ''));
		}
		return this._focTxt(this._getTxt(foc ? 5 : 4, foc ? this._prompt : this._pad, t), foc, e);
	},
	_enterTxt:function()
	{
		return this._getTxt(this._mode, '');
	},
	set_text:function(val, s)
	{
		this._sTxt = 1;
		this._setTxt(val, (s == null) ? 5 : (1000 + s));
		this._sTxt = 0;
		if(this._fix == 1)
			this._old = this._instant(true);
	},
	_maskKey:function(k, c, t, i, s, mask){ return -2; },
	_doKey:function(k, c, t, i, sel0, sel1, bad, e)
	{
		var mask = this._mask;
		i = mask ? mask.length : 0;
		if(i < 1 || k < 7 || (k > 8 && k < 32))
			k = 0;
		if(bad)
		{
			if(k == 0 || (this._ampm && !(mask.indexOf(c) > 0 || this._ampm().indexOf(c) >= 0 || this._ampm(true).indexOf(c) >= 0 || (k >= 48 && k <= 57))))
				$util.cancelEvent(e);
			return;
		}
		if(k == 0)
			return;
		t = this._txt;
		if(sel0 != sel1)
		{
			while(--sel1 >= sel0)
				t = t.substring(0, sel1) + mask.charAt(sel1) + t.substring(sel1 + 1);
			sel1++;
		}
		else if(k == 7)/*del*/
		{
			while(sel1 < i && mask.charCodeAt(sel1) >= 22)
				sel1++;
			if(sel1 >= i)
				return;
			t = t.substring(0, sel1) + mask.charAt(sel1) + t.substring(sel1 + 1);
			sel1++;
		}
		else if(k == 8)/*back*/
		{
			while(sel1 > 0 && mask.charCodeAt(sel1 - 1) >= 22)
				sel1--;
			if(sel1-- < 1)
				return;
			t = t.substring(0, sel1) + mask.charAt(sel1) + t.substring(sel1 + 1);
		}
		if(k > 8 && sel1 < i)
		{
			if(sel1 >= i)
				return;
			if((sel0 = this._maskKey(k, c, t, i, sel1, mask)) >= 0)
			{
				t = this._txt;
				sel1 = sel0;
			}
			else
			{
				if(sel0 == -1)
					return;
				while(mask.charCodeAt(sel1) >= 22)
					if(++sel1 >= i)
						return;
			}
			if(sel0 >= 0)
			{
				t = this._txt;
				sel1 = sel0;
			}
			else
			{
				if((c = this._maskFilter(mask.charCodeAt(sel1), c, 0)) == null)
					return;
				t = t.substring(0, sel1) + c + t.substring(sel1 + 1);
				sel1++;
			}
		}
		this._txt = t;
		this._selK = sel1;
		this._elem.value = this._focusTxt(true);
		this.select(this._selK);
		this._selK = 10000;
	},
	getValueByMode:function(mode, v)
	{
		/// <summary>Gets text according to DataMode.</summary>
		/// <param name="mode" type="Number">DataMode which matches with enum on server.</param>
		/// <param name="v" optional="true" mayBeNull="true">Internal use only.</param>
		/// <returns type="String">Text in control.</returns>
		return this._getTxt(mode, v ? '' : this._empty);
	},
	_instant:function(v)
	{
		return this.getValueByMode(this._mode, v);
	},
	get_promptChar:function()
	{
		/// <summary>
		/// Gets sets prompt character. String with length of 1.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._prompt;
	},
	set_promptChar:function(val)
	{
		this._prompt = val;
	},
	get_padChar:function()
	{
		/// <summary>
		/// Gets sets pad character. String with length of 1.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._pad;
	},
	set_padChar:function(val)
	{
		this._pad = val;
	},
	get_emptyChar:function()
	{
		/// <summary>
		/// Gets sets empty-position character. String with length of 1.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._empty;
	},
	set_emptyChar:function(val)
	{
		this._empty = val;
	},
	get_dataMode:function()
	{
		/// <summary>
		/// Gets DataMode of editor. Integer value which matches with corresponding enum on server.<br />
		/// </summary>
		return this._mode;
	},
	get_value:function()
	{
		/// <summary>Gets sets current value in editor according to DataMode.</summary>
		this._msV(this._getTxt(this._mode, ''));
		return this._instant();
	},
	set_value:function(val, mode)
	{
		this._setTxt(val, mode ? mode : ((this._fcs < 0) ? 2 : this._mode));
		if(this._fix == 1)
			this._old = this._instant(true);
		this._fixNull();
	}
}
$IG.WebMaskEditor.registerClass('Infragistics.Web.UI.WebMaskEditor', $IG.WebTextEditor);

$IG.WebNumericEditor = function(elem)
{
	/// <summary>Class which implements client side functionality of WebNumericEditor.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebNumericEditor.initializeBase(this, [elem]);
}
$IG.WebNumericEditor.prototype =
{
	_thisType:'num',
	initialize:function()
	{
		/// <summary>Initializes instance of WebNumericEditor.</summary>
		$IG.WebNumericEditor.callBaseMethod(this, 'initialize');
		var prop1 = this._prop1;
		var i = 1, j = -1, v = this._val_i(prop1, i++);
		var n = v.length;
		if(n < 1)
			v = '.';
		if(n < 2)
		{
			n = 2;
			v += v;
		}
		this.dec_vld = v.substring(n >>= 1);
		this._decSep = v.substring(0, n);
		this._grSep = this._val_i(prop1, i++);
		v = this._val_i(prop1, i++);
		if(v.length < 1)
			v = '-';
		this._minus = v;
		this._symbol = this._val_i(prop1, i++);
		this._posPattern = this._val_i(prop1, i++);
		this._negPattern = this._val_i(prop1, i++);
		this._mode = this._val_i(prop1, i++);
		this._dec = this._val_i(prop1, i++);
		this._minDec = this._val_i(prop1, i++);
		this._factor = this._val_i(prop1, i++);
		v = this._val_i(prop1, i++);
		if(v == 1)
			this._min = this._val_i(prop1, i++);
		v = this._val_i(prop1, i++);
		if(v == 1)
			this._max = this._val_i(prop1, i++);
		v = this._val_i(prop1, i++);
		if(v == 1)
			this._nullVal = this._val_i(prop1, i++);
		this._negCss = this._val_i(prop1, i++);
		this._posCss = this._elem.className;
		this._groups = new Array();
		while(++j < 6)
		{
			if((v = this._val_i(prop1, i++)) > 0)
				this._groups[j] = v;
			else
				break;
		}
		if(this._thisType == 'num')
			this._initEnd();
	},
	get_spinDelta:function()
	{
		/// <summary>
		/// Gets sets value which is used to increment decrement value in control on spin events.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spDelta;
	},
	set_spinDelta:function(val)
	{
		this._spDelta = val;
	},
	get_dataMode:function()
	{
		/// <summary>
		/// Gets sets DataMode. Integer value which matches with corresponding enum on server.<br />
		/// Notes: That method will adjust min/max limits, decimal places and MaxLength.
		/// However, control will not be repainted and current value in editor will not be modified.<br />
		/// New value does not persist to server.
		/// </summary>
		return this._mode;
	},
	set_dataMode:function(val)
	{
		if(val < 0 || val > 11 || this._mode == val)
			return;
		this._mode = val;
		if(val < 4)
		{
			this._dec = 15;
			this._min = this._max = null;
			this._maxLen = 0;
			return;
		}
		this._dec = 0;
		/* byte */
		var min = 0, max = 127, len = 3;
		/* long */
		if(val < 6)
		{
			max = 9223372036854775807;
			len = 19;
		}
		/* int */
		else if(val < 8)
		{
			max = 2147483647;
			len = 10;
		}
		/* short */
		else if(val < 10)
		{
			max = 32767;
			len = 5;
		}
		/* unsigned */
		if((val & 1) == 1)
			max = max * 2 + 1;
		else
		{
			min = -max - 1;
			len++;
		}
		this._min = min;
		this._max = max;
		this._maxLen = len;
	},
	get_nullable:function()
	{
		/// <summary>
		/// Gets sets option to allow null value.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._nullable;
	},
	set_nullable:function(val)
	{
		this._nullable = val;
	},
	get_decimalSeparator:function()
	{
		/// <summary>
		/// Gets sets decimal separator character. String with length of 1.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._decSep;
	},
	set_decimalSeparator:function(val)
	{
		this._decSep = val;
	},
	get_groupSeparator:function()
	{
		/// <summary>
		/// Gets sets group/thousand separator character. String with length of 1.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._grSep;
	},
	set_groupSeparator:function(val)
	{
		this._grSep = val;
	},
	get_minus:function()
	{
		/// <summary>
		/// Gets sets minus sign character. String with length of 1.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._minus;
	},
	set_minus:function(val)
	{
		this._minus = val;
	},
	get_symbol:function()
	{
		/// <summary>
		/// Gets sets symbol string, which is used when control has no focus.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._symbol;
	},
	set_symbol:function(val)
	{
		this._symbol = val;
	},
	get_positivePattern:function()
	{
		/// <summary>
		/// Gets sets pattern for positive numbers, which is used when control has no focus.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._posPattern;
	},
	set_positivePattern:function(val)
	{
		this._posPattern = val;
	},
	get_negativePattern:function()
	{
		/// <summary>
		/// Gets sets pattern for negative numbers, which is used when control has no focus.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._negPattern;
	},
	set_negativePattern:function(val)
	{
		this._negPattern = val;
	},
	get_decimals:function()
	{
		/// <summary>
		/// Gets sets maximum number of decimal digits, which is used when control has no focus.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._dec;
	},
	set_decimals:function(val)
	{
		this._dec = val;
	},
	get_minDecimals:function()
	{
		/// <summary>
		/// Gets sets minimum number of decimal digits, which is used when control has no focus.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._minDec;
	},
	set_minDecimals:function(val)
	{
		this._minDec = val;
	},
	get_groups:function()
	{
		/// <summary>
		/// Gets sets sizes of groups/thousands, which is used when control has no focus. That is array of numbers.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._groups;
	},
	set_groups:function(val)
	{
		this._groups = val;
	},
	get_maxValue:function()
	{
		/// <summary>
		/// Gets sets maximum value.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		var val = this._max;
		return val ? val / this._factor : val;
	},
	set_maxValue:function(val)
	{
		val = this._toNum(('' + val == 'NaN') ? null : val, false);
		this._max = val ? val * this._factor : val;
	},
	get_minValue:function()
	{
		/// <summary>
		/// Gets sets minimum value.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		var val = this._min;
		return val ? val / this._factor : val;
	},
	set_minValue:function(val)
	{
		val = this._toNum(('' + val == 'NaN') ? null : val, false);
		this._min = val ? val * this._factor : val;
	},
	get_nullValue:function()
	{
		/// <summary>
		/// Gets value which used instead of null.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._nullVal;
	},
	_toNum:function(t, limit, fire)
	{
		var c, num = null, i = -1, div = 1, dec = -1, iLen = 0;
		if(t === '')
			t = null;
		if(t == null || t.length == null)
			num = t;
		else
		{
			var neg = false, dot = this._decSep.charCodeAt(0);
			if(t)
			{
				c = this._symbol;
				if(c.length > 0)
					if((iLen = t.indexOf(c)) >= 0)
						t = t.substring(0, iLen) + t.substring(iLen + c.length);
				if(!t.toUpperCase)
					t = t.toString();
				iLen = t.length;
			}
			while(++i < iLen)
			{
				if(this._isMinus(c = this._jpn(t.charCodeAt(i))))
				{
					if(neg)
						break;
					neg = true;
				}
				/* japanese ".","'.","(" */
				if(c == dot || c == 12290 || c == 65294 || (c == 12289 && dot == 44))
				{
					if(dec >= 0)
						break;
					dec = 0;
				}
				if(c < 48 || c > 57)
					continue;
				if(num == null)
					num = 0;
				if(dec < 0)
					num = num * 10 + c - 48;
				else
				{
					dec = dec * 10 + c - 48;
					div *= 10;
				}
			}
			if(num != null)
			{
				if(dec > 0)
					num += dec / div;
				if(neg)
					num = -num;
			}
		}
		var val = limit ? this._limits(num) : num;
		if(!fire && this._vs != null)
			return val;
		c = '';
		if(fire) if(val != num || (val == null && iLen > 0))
		{
			var valOld = val;
			if(val)
				val /= this._factor;
			fire = {value:val, text:t, type:(num == null) ? ((iLen == 0) ? 2 : 0) : 1};
			c = String.fromCharCode(30);
			c += t + c + fire.type;
			this._fireEvt(13, null, fire);
			if(val === fire.value)
				val = valOld;
			else
			{
				val = fire.value;
				if('' + val == 'NaN')
					val = null;
				else if(val)
					val *= this._factor;
			}
		}
		this.value = val;
		this._setVS(this._toTxt(val, true, null, '-', '.') + c);
		if(fire)
			this._valid(this._toTxt(val, true, null, '-', this.dec_vld));
		return val;
	},
	_enterTxt:function()
	{
		return this._toTxt(null, true, this._val(), '-', '.');
	},
	_focusTxt:function(foc, e)
	{
		if(e != null && !foc)
			this.value = this._toNum(this._val(), true, this._fcs >= 0);
		return this._focTxt(this._toTxt(this.value, foc), foc, e);
	},
	_toTxt:function(v, foc, t, m, dec)
	{
		if(t == null)
		{
			if(v == null)
				return '';
			var neg = v < 0;
			if(neg)
				v = -v;
			try
			{
				t = v.toFixed(this._dec);
			}
			catch(ex)
			{
				t = '' + v;
			}
			return this._toTxt(neg, foc, t.toUpperCase(), (m == null) ? this._minus : m, (dec == null) ? this._decSep : dec);
		}
		var c, i = -1, iL = t.length;
		if(v == null)
		{
			if(iL == 0)
				return foc ? t : '';
			if(v = this._isMinus(t.charCodeAt(0)))
				t = t.substring(1);
		}
		var iE = t.indexOf('E');
		if(iE < 0)
			iE = 0;
		else
		{
			iL = parseInt(t.substring(iE + 1));
			t = t.substring(0, iE);
			iE = iL;
		}
		iL = t.length;
		while(++i < iL)/* remove dot */
		{
			c = t.charCodeAt(i);
			if(c < 48 || c > 57)
			{
				t = t.substring(0, i) + t.substring(i + 1);
				iL--;
				break;
			}
		}
		/* if dot,remove trailing 0s */
		while(i < iL)
		{
			if(t.charCodeAt(iL - 1) != 48)
				break;
			t = t.substring(0, --iL);
		}
		if(iE != 0)
		{
			while(iE-- > 0) if(i++ >= iL)
				t += '0';
			if(++iE < 0)
			{
				if(i == 0)
					t = '0' + t;
				while(++iE < 0)
					t = '0' + t;
				t = '0' + t;
				i = 1;
			}
		}
		iL = i;
		var iDec = 0;
		if(this._dec > 0 && iL < t.length)
		{
			iDec = t.length - iL;
			t = t.substring(0, iL) + dec + t.substring(iL);
			iL += dec.length + this._dec;
		}
		if(iL < t.length)
			t = t.substring(0, iL);
		if((iL = this._minDec) !=0 )
		{
			if(iDec == 0)
				t += dec;
			while(iL-- > iDec)
				t += '0';
		}
		if(foc)
			return v ? (m + t) : t;
		var g0 = (this._groups.length > 0) ? this._groups[0] : 0;
		var ig = 0, g = g0;
		while(g > 0 && --i > 0) if(--g == 0)
		{
			t = t.substring(0, i) + this._grSep + t.substring(i);
			g = this._groups[++ig];
			if(g == null || g < 1)
				g = g0;
			else
				g0 = g;
		}
		var txt = v ? this._negPattern : this._posPattern;
		txt = txt.replace('$', this._symbol);
		return txt.replace('n', t);
	},
	set_text:function(val)
	{
		/// <summary>Sets value from text.</summary>
		this._sTxt = 1;
		this.set_value(val);
		this._sTxt = 0;
	},
	_isMinus:function(k)
	{
		/* japanese "'-","-","(" */
		return k == this._minus.charCodeAt(0) || k == 45 || k == 40 || k == 12540 || k == 65293 || k == 65288;
	},
	_doKey:function(k, c, t, i, sel0, sel1, bad, e)
	{
		if(bad)
		{
			if(!(k < 9 || this._isMinus(k) || (k >= 48 && k <= 57) || k == this._decSep.charCodeAt(0)))
				$util.cancelEvent(e);
			return;
		}
		if(sel0 != sel1)
		{
			t = t.substring(0, sel0) + t.substring(sel1);
			sel1 = sel0;
			i = t.length;
		}
		/* 7-del,8-back */
		else if(k == 7)
		{
			if(sel1++ >= i || i == 0)
				return;
		}
		else if(k == 8)
		{
			if(sel0-- < 1)
				return;
		}
		if(k < 9 || this._maxLen == 0 || this._maxLen > i)
		{
			var dot = k == this._decSep.charCodeAt(0);
			var ok = (k > 47 && k < 58) || (sel0 == 0 && this._isMinus(k)) || (dot && this._dec > 0);
			if(i > 0 && sel0 == 0) if(this._isMinus(t.charCodeAt(0)))
				ok = false;
			if(k > 8 && !ok)
				return;
			if(dot) if((dot = t.indexOf(this._decSep)) >= 0)
			{
				if(dot == sel0 || dot == sel0 - 1)
					return;
				i--;
				if(dot < sel0)
					sel0 = --sel1;
				t = t.substring(0, dot) + t.substring(dot + 1);
			}
			if(k > 8 && sel1 >= i)
				t += c;
			else
				t = t.substring(0, sel0) + c + t.substring(sel1);
		}
		else
			k = 0;
		this._elem.value = t;
		this.select((k > 10) ? sel1 + 1 : sel0);
	},
	_limits:function(v, r)
	{
		if(v == null && !this._nullable)
		{
			v = this._nullVal;
			/* DataMode: Text-0, Double-1, Float-2, Decimal-3, etc. */
			if(!v && this._mode > 2)
				v = 0;
		}
		if(v != null)
		{
			var n = this._min, x = this._max;
			if(n !=null && v <= n)
				return r ? x : n;
			if(x != null && v >= x)
				return r ? n : x;
		}
		return v;
	},
	get_number:function()
	{
		/// <summary>
		/// Gets value in editor as Number.<br />
		/// </summary>
		var val = this._instant(true, true, true);
		if(val)
			val /= this._factor;
		return (val == null) ? Number.NaN : val;
	},
	_instant:function(num, limit, v)
	{
		v = (this._fcs == 2 || v) ? this._toNum(this._val(), limit == true) : this.value;
		if(this._vld == 1)
			this._msV(this._toTxt(v, true, null, '-', this.dec_vld));
		return (num || this._mode > 0) ? v : this._toTxt(v, true);
	},
	get_value:function(num)
	{
		/// <summary>Gets sets value in editor according to DataMode.</summary>
		this._vld = 1;
		var val = this._instant(num, true, true);
		if(val && typeof val == 'number')
			val /= this._factor;
		if(val == null && !this._nullable)
			return (this._mode == 0) ? '' : Number.NaN;
		return val;
	},
	set_value:function(val)
	{
		if('' + val == 'NaN')
			val = null;
		if(val && typeof val == 'number' && this._fix != 0 && !this._prop1)
			val *= this._factor;
		this._text = this._toTxt(this.value = this._toNum(val, true, this._fcs >= 0), this._fcs == 2);
		this._repaint();
		this.select(1000);
		if(this._fix == 1)
			this._old = this._instant(true);
		this._fixNull();
	},
	spin:function(delta)
	{
		/// <summary>Increments or decrements value in editor.</summary>
		/// <param name="delta" type="Number" mayBeNull="false">Increment for old value.</param>
		if(this._spinList(delta))
			return;
		var val = this._toNum(this._val());
		if(val == null)
			val = 0;
		this._fix = 0;
		this.set_value(val + delta);
		this._fix = 1;
	}
}
$IG.WebNumericEditor.registerClass('Infragistics.Web.UI.WebNumericEditor', $IG.WebTextEditor);

$IG.WebCurrencyEditor = function(elem)
{
	/// <summary>Class which implements client side functionality of WebCurrencyEditor.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebCurrencyEditor.initializeBase(this, [elem]);
}
$IG.WebCurrencyEditor.registerClass('Infragistics.Web.UI.WebCurrencyEditor', $IG.WebNumericEditor);

$IG.WebPercentEditor = function(elem)
{
	/// <summary>Class which implements client side functionality of WebPercentEditor.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebPercentEditor.initializeBase(this, [elem]);
}
$IG.WebPercentEditor.registerClass('Infragistics.Web.UI.WebPercentEditor', $IG.WebNumericEditor);

$IG.WebDateTimeEditor = function(elem)
{
	/// <summary>Class which implements client side functionality of WebDateTimeEditor.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebDateTimeEditor.initializeBase(this, [elem]);
}
$IG.WebDateTimeEditor.prototype =
{
	_thisType:'date',
	initialize:function()
	{
		/// <summary>Initializes instance of WebDateTimeEditor.</summary>
		$IG.WebDateTimeEditor.callBaseMethod(this, 'initialize');
		var prop1 = this._prop1;
		this._mask1 = this._getMask(this._val_i(prop1, 3), true);
		this._2029 = prop1[4];
		this._yearFix = prop1[5];
		this._calID = prop1[6];
		this._names = this._val_i(prop1, 7).split(',');
		if(!$util.isEmpty(prop1 = this._val_i(prop1, 8)))
			this._animation = new $IG.SlideFadeAnimation(prop1);
		this._date = new Date();
		this._isNull = false;
		this.d_s = 10;
		if(this._thisType == 'date')
			this._initEnd();
	},
	get_spinDelta:function()
	{
		/// <summary>
		/// Gets sets value which is used to increment decrement value in control on spin events.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._spDelta;
	},
	set_spinDelta:function(val)
	{
		this._spDelta = val;
	},
	get_nullable:function()
	{
		/// <summary>
		/// Gets sets option to allow null date.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._nullable;
	},
	set_nullable:function(val)
	{
		this._nullable = val;
	},
	get_minimumNumberOfValidFields:function()
	{
		/// <summary>
		/// Gets sets minimum number of fields entered by user in order to consider date as valid. Missing fields are filled internally.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._minFields;
	},
	set_minimumNumberOfValidFields:function(val)
	{
		this._minFields = val;
	},
	get_useLastGoodDate:function()
	{
		/// <summary>
		/// Gets sets option to use last good date, when invalid date was entered.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._good;
	},
	set_useLastGoodDate:function(val)
	{
		this._good = val;
	},
	get_centuryThreshold:function()
	{
		/// <summary>
		/// Gets sets year which is used to separate dates which belong to 20th or 21st century, when user entered less than 3 digits in year field.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._2029;
	},
	set_centuryThreshold:function(val)
	{
		this._2029 = val;
	},
	get_maxValue:function()
	{
		/// <summary>
		/// Gets sets maximum value.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._max;
	},
	set_maxValue:function(val)
	{
		if(val != null && !val.getTime)
			val = this._toDate(val.toString(), true);
		this._max = val;
	},
	get_minValue:function()
	{
		/// <summary>
		/// Gets sets minimum value.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._min;
	},
	set_minValue:function(val)
	{
		if(val != null && !val.getTime)
			val = this._toDate(val.toString(), true);
		this._min = val;
	},
	_ampm:function(a)
	{
		var v = this._val_i(this._names, a ? 0 : 1);
		return (v.length > 0) ? v : (a ? 'AM':'PM');
	},
	get_am:function()
	{
		/// <summary>
		/// Gets sets string 2 characters long which represents AM.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._ampm(true);
	},
	set_am:function(val)
	{
		return this._names[0] = val;
	},
	get_pm:function()
	{
		/// <summary>
		/// Gets sets string 2 characters long which represents PM.<br />
		/// Note: new value does not persist to server.
		/// </summary>
		return this._ampm();
	},
	set_pm:function(val)
	{
		return this._names[1] = val;
	},
	getMonthNameAt:function(i)
	{
		/// <summary>Gets string which represents name of month.</summary>
		/// <param name="i" type="Number">Index of month in range between 0 and 11.</param>
		/// <returns type="String">Name of month.</returns>
		return this._val_i(this._names, 2 + i % 12);
	},
	setMonthNameAt:function(val, i)
	{
		/// <summary>Sets string which represents name of month. Note: new value does not persist to server.</summary>
		/// <param name="val" type="String">Name of month.</param>
		/// <param name="i" type="Number">Index of month in range between 0 and 11.</param>
		return this._names[2 + i % 12] = val;
	},
	getDowNameAt:function(i)
	{
		/// <summary>Gets string which represents name of day of the week.</summary>
		/// <param name="i" type="Number">Index of day of the week in range between 0 and 6.</param>
		/// <returns type="String">Name of day of the week.</returns>
		return this._val_i(this._names, 14 + i % 7);
	},
	setDowNameAt:function(val, i)
	{
		/// <summary>Sets string which represents name of day of the week. Note: new value does not persist to server.</summary>
		/// <param name="val" type="String">Name of day of the week.</param>
		/// <param name="i" type="Number">Index of day of the week in range between 0 and 6.</param>
		return this._names[14 + i % 7] = val;
	},
	set_text:function(val)
	{
		/// <summary>Sets value in editor from string.</summary>
		this._sTxt = 1;
		this.set_value(val, true);
		this._sTxt = 0;
	},
	/* f:flag of field, d:Date, e:focus, c:fill-up character*/
	_fieldVal:function(f, d, e, c)
	{
		/* 1-y,2-yy,3-yyyy,4-M,5-MM,6-MMM,7-MMMM,8-d,9-dd */
		/* 10-h,11-hh,12-H,13-HH,14-t,15-tt,16-m,17-mm,18-s,19-ss */
		/* 20-ddd,21-dddd,22-f,23-ff,24-fff,25=ffff,26-fffff,27-ffffff,28-fffffff */
		var v, i = (f & 1) * 2;
		if(f < 4)
		{
			v = d.getFullYear() + this._yearFix;
			if(f == 3)
				i = 4;
			else
			{
				v %= 100;
				i = (f == 2) ? 2 : 0;
			}
		}
		else if(f < 8)
		{
			this.d_s = 2;
			v = d.getMonth() + 1;
			if(f > 5)
			{
				f = this.getMonthNameAt(v - 1);
				if(f.length > 0)
					return f;
			}
		}
		else if(f < 10)
			v = d.getDate();
		else if(f < 16)
		{
			v = d.getHours();
			if(f > 13)//ampm
			{
				v = this._ampm(v < 12);
				if((f -= 13) == (i = v.length))
					return v;
				if(i < f)
					v += ' ';
				return v.substring(0, f);
			}
			if(f < 12)
			{
				v %= 12;
				if(v == 0)
					v = 12;
			}
		}
		else if(f < 18)
			v = d.getMinutes();
		else if(f < 20)
			v = d.getSeconds();
		else if(f < 22)
			return this.getDowNameAt(d.getDay());
		else
		{
			v = d.getMilliseconds();
			var j = i = f - 21;
			while(j-- > 3)
				v *= 10;
			while(j++ < 2)
				v = Math.floor(v / 10);
		}
		v = '' + v;
		if(f < 20 || f > 22)
		{
			f = v.length;
			if(e)
			{
				if(i == 0)
					i = 2;
				else
					e = false;
			}
			if(i > 0)
			{
				if(i < f)
					v = v.substring(0, i);
				else
					while(f++ < i)
						v = (e ? c : '0') + v;
			}
		}
		return v;
	},
	_limits:function(d, r)
	{
		if(d == null)
			return d;
		var v = d.getTime(), n = this._min, x = this._max;
		if(n != null)
			n = n.getTime();
		if(x != null)
			x = x.getTime();
		if(n != null && (v < n || (r && v == n)))
		{
			d.setTime(r ? x : n);
			return d;
		}
		if(x != null && (v > x || (r && v == x)))
		{
			d.setTime(r ? n : x);
			return d;
		}
		return null;
	},
	/* convert t to Date */
	/* foc: focus state */
	/* limit: validate min/max limits */
	/* fire: request to fire invalid event */
	/* fixNull: request to set value of _isNull */
	_toDate:function(t, foc, limit, fire, fixNull)
	{
		var fields = (foc && fire) ? this._fields0(t) : this._fields1(t, foc);
		/* n: 3-ymd,8-invalid,16-limit,32-less than min number of fields */
		var n = 0, i = -1, j = -1, y = -1, mo = -1, day = -1, h = -2, m = -2, s = -2, ms = -2, pm = -1;
		var v, i0, c, iLen = fields.length, any = false, arg = new Object();
		while(++i < iLen)
		{
			j++;
			v = fields[i];
			i0 = foc ? this._field0IDs[i] : this._field1IDs[i];
			if(i0 < 4)
			{
				if(v > 100 && v > this._yearFix)
					v -= this._yearFix;
				if((arg.year = y = v) < 0)
					n |= 8;
				else
				{
					n++;
					c = this._2029;
					if(v < 100)
					{
						if(i0 < 3 && c < 0)
							c = 29;
						if(c >= 0)
							y += (v > c) ? 1900 : 2000;
					}
				}
			}
			else if(i0 < 8)
			{
				arg.month = mo = v;
				if(v < 1 || v > 12)
					n |= 8;
				else
					n++;
			}
			else if(i0 < 10)
			{
				arg.day = day = v;
				if(v < 1 || v > 31)
					n |= 8;
				else
					n++;
			}
			else if(i0 < 14)
			{
				if(v == 24)
					v = 0;
				if(i0 > 11)
					pm = -4;
				else
				{
					if(v == 12)
						v = 0;
					if(v > 12)
						n |= 8;
				}
				arg.hours = h = v;
				if(v > 23 || v < 0)
					n |= 8;
			}
			else if(i0 < 16)
			{
				j--;
				if(v > 0)
					pm++;
				continue;
			}
			else if(i0 < 18)
			{
				arg.minutes = m = v;
				if(v > 59 || v < 0)
					n |= 8;
			}
			else if(i0 < 20)
			{
				arg.seconds = s = v;
				if(v > 59 || v < 0)
					n |= 8;
			}
			else if(i0 < 22)
			{
				j--;
				continue;
			}
			else
			{
				while(i0++ < 24)
					v *= 10;
				while(i0-- > 25)
					v = Math.floor(v / 10);
				arg.milliseconds = ms = v;
				if(v > 999 || v < 0)
					n |= 8;
			}
			if(v >= 0)
				any = true;
			if(j < this._minFields && n > 7)
				n |= 32;
		}
		if(pm == 0 && h >= 0 && h < 12)
			arg.hours = (h += 12);
		var inv = fire ? (':' + y + ',' + mo + ',' + day + ',' + h + ',' + m + ',' + s + ',' + ms + ',') : '';
		var d = null;
		if(!this._nullable || n < 30) if((n & 3) == 3)
		{
			d = new Date(y, mo - 1, day);
			if(y < 100)
				d.setFullYear(y);
		}
		else
		{
			d = new Date();
			if(this._date)
				d.setTime(this._date.getTime());
			if(day > 0)
				d.setDate(day);
			if(y >= 0)
				d.setFullYear(y);
			if(mo > 0)
				d.setMonth(mo - 1);
		}
		n &= 15;
		if(day > 0 && d) if(day != d.getDate())
			n |= 8;
		day = this._good ? this._goodD : null;
		if(fire && !d && !this._nullable)
		{
			d = day;
			if(!d || d.getTime == null)
			{
				d = new Date();
				n |= 8;
			}
			else
				n |= 32;
		}
		if(d)
		{
			if(h > -2)
				d.setHours((h < 0) ? 0 : h);
			if(m > -2)
				d.setMinutes((m < 0) ? 0 : m);
			if(s > -2)
				d.setSeconds((s < 0) ? 0 : s);
			if(ms > -2)
				d.setMilliseconds((ms < 0) ? 0 : ms);
			if(limit)
			{
				if((d = this._limits(i = d)) != null)
					n = 16;
				else
					d = i;
			}
		}
		if(fire)
		{
			if(any && !d && t.length > 0 && day)
			{
				d = day;
				n = 32;
			}
			arg.date = d;
			if(n < 8 || (n == 8 && !any && this._nullable))
				inv = '';
			else
			{
				inv += (arg.type = (n == 16) ? 1 : (any ? 0 : 2));
				if(this._reduce && d && arg.type == 0 && d.getDate() < 5 && arg.day > 27)
				{
					d.setDate(0);
					arg.date = d;
				}
				this._fireEvt(13, null, arg);
				d = arg.date;
			}
			/* _isNull must be fixed before _updatePost */
			if(fixNull) if(!(this._isNull = (d == null)))
				this._date = d;
			this._updatePost(d, inv);
			if(d && this._good)
				this._goodD = d;
		}
		if(fixNull) if(!(this._isNull = (d == null)))
			this._date = d;
		return d;
	},
	_updatePost:function(d, inv)
	{
		if(d != null)
			inv = '' + d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + '-' + d.getHours() + '-' + d.getMinutes() + '-' + d.getSeconds() + '-' + d.getMilliseconds() + inv;
		this._setVS(inv);
		this._valid((d == null) ? '' : this._toTxt(d, true, ''));
	},
	_enterTxt:function()
	{
		var d = this._toDate(this._val(), true);
		return (d == null) ? '' : this._toTxt(d, true, '');
	},
	_toTxt:function(d, foc, prompt, txt)
	{
		var t = '', mask = foc ? this._mask : this._mask1;
		if(d == null)
			return foc ? this._getTxt(5, prompt, txt ? (this._txt = mask) : mask) : '';
		var ids = foc ? this._field0IDs : this._field1IDs;
		var c, k, i = -1, f0 = 0;
		this.d_s = 6;/* seconds */
		while(++i < mask.length)
		{
			c = mask.charAt(i);
			if((k = mask.charCodeAt(i)) < 22)
			{
				t += this._fieldVal(ids[f0++], d, foc, c);
				if(foc)
					while(i + 1 < mask.length)
						if(mask.charCodeAt(i + 1) == k)
							i++;
						else
							break;
			}
			else
				t += c;
		}
		if(!foc)
			return t;
		if(txt)
			this._txt = t;
		return this._getTxt(5, prompt, t);
	},
	_focusTxt:function(foc, e, t)
	{
		var d = null, prompt = '';
		if(t == null)
		{
			prompt = this._prompt;
			/* key-press */
			if(e == null && foc)
				return this._getTxt(5, prompt);
			/* ""-from _update=lostFocus */
			if(e != null && !foc)
				/* last-param: request to set this._isNull */
				d = this._toDate(this._val(), e === '', true, this._fcs >= 0, 1);
			else if(!this._isNull)
				d = this._date;
		}
		else
			d = this._toDate(t, foc, true);
		return this._focTxt(this._toTxt(d, foc, prompt, e != null), foc, e);
	},
	_fields1:function(t, foc)
	{
		var ids = foc ? this._field0IDs : this._field1IDs;
		var iLen = ids.length;
		var j, i = -1, v = -1, field = 0, fields = new Array(iLen);
		while(++i < iLen)
			fields[i] = -1;
		if(t==null)
			return fields;
		t = t.toUpperCase();
		i = -1;
		while(++i < t.length && field < iLen)
		{
			var k = this._jpn(t.charCodeAt(i)) - 48, j = ids[field];
			if(j == 20 || j == 21)
				j = ids[++field];//dow
			if(j == 14 || j == 15)//ampm
			{
				if(k >= 0 && k <= 9)
				{
					v = -1;
					field++;
					i--;
					continue;
				}
				if(this._ampm().charAt(0).toUpperCase() == t.charAt(i))
				{
					fields[field++] = 1;
					v = -1;
				}
			}
			else
			{
				if(k >= 0 && k <= 9)
				{
					if(v < 0)
						v = k;
					else
						v = v * 10 + k;
				}
				else
				{
					if(v >= 0)
					{
						fields[field++] = v;
						v = -1;
					}
					else if(j == 6 || j == 7) while(v-- > -3)//MMM
					{
						for(k = 0; k < 12; k++)
						{
							var m = this.getMonthNameAt(k).toUpperCase();
							if((j = m.length) < 1)
								continue;
							if(v == -3)
							{
								if(j < 4)
									continue;
								m = m.substring(0, 3);
							}
							if((j = t.indexOf(m) - 1) > -2)
								if(j < 0 || t.charAt(j).toLowerCase() == t.charAt(j))
									break;
						}
						if(k < 12)
						{
							fields[field++] = k + 1;
							break;
						}
					}
				}
			}
		}
		if(field < iLen)
			fields[field] = v;
		return fields;
	},
	_fields0:function(t)
	{
		var fields = new Array();
		if(t == null)
			t = '';
		var x, k, j = -1, i = -1, v = -1, field = -1, n = 22, m = this._mask;
		while(++i < m.length)
		{
			j++;
			if((x = m.charCodeAt(i)) > 21 && n > 21)
				continue;
			if(x > 21)
			{
				if(field >= 0)
					fields[field] = v;
			}
			else
			{
				if(n > 21)
				{
					v = -1;
					field++;
				}
				if(j < t.length) if(x > 18)
				{
					k = this._jpn(t.charCodeAt(j)) - 48;
					if(k >= 0 && k <= 9)
					{
						if(v < 0)
							v = k;
						else
							v = v * 10 + k;
					}
					else if(i + 1 < m.length && t.charAt(j) == m.charAt(i + 1))
						j--;
				}
				else if(n != x) if(this._ampm().charAt(0).toUpperCase() == t.charAt(j).toUpperCase())
					v = 1;
			}
			n = x;
		}
		fields[field] = v;
		return fields;
	},
	_curField:function(s, mask)
	{
		var x, n = 22, field = this._n0 = this._n1 = -1;
		for(var i = 0; i < mask.length; i++)
		{
			if(((x = mask.charCodeAt(i)) > 21) == (n > 21))
				continue;
			if(x > 21)
			{
				if(i >= s)
					break;
			}
			else
			{
				this._n0 = i;
				field++;
			}
			n = x;
		}
		if(this._n0 >= 0)
			this._n1 = i;
		if((field = this._field0IDs[field]) == null)
			return -1;
		if(field < 8)
			return (field < 4) ? 0 : 1;
		if(field < 20)
			return Math.floor((field - 4) / 2);
		return (field > 21) ? 8 : -1;
	},
	_maskKey:function(k, c, t, i, s, mask)
	{
		var n = 0, v = -1, field = this._curField(s, mask);
		if(s >= this._n1) if(t.charCodeAt(--s) > 21)
			return this._maskKey(k, c, t, i, s + 2, mask);
		if(field < 0)
			return -1;
		if(field == 5)/*ampm*/
		{
			if(s <= this._n0)
			{
				v = this._ampm();
				if(v.charAt(0).toUpperCase() != c.toUpperCase())
					v = this._ampm(true);
				if(this._n1 == this._n0 + 1)
					v = v.charAt(0);
				else if((i = v.length) < 2)
					v += ' ';
				else if(i > 2)
					v = v.substring(0, 2);
				this._txt = t.substring(0, this._n0) + v + t.substring(this._n1);
			}
			return this._n1;
		}
		if(k < 48 || k > 57)
		{
			if(s == 0 || (k != 47 && k != 58 && (k < 44 || k > 57)))
				return -1;
			if(mask.charCodeAt(s - 1) >= 22 || this._n1 == i)
				return s;
			while(s < i)
			{
				if(mask.charCodeAt(s++) >= 22)
					break;
				t = t.substring(0, s - 1) + mask.charAt(s - 1) + t.substring(s);
			}
			this._txt = t;
			return s;
		}
		k -= 48;
		if(this._n0 == s)
		{
			v = t.charCodeAt(s + 1) - 48;
			/* 0-y,1-M,2-d,3-h,4-H,5-AMPM,6-m,7-s,8-ms */
			switch(field)
			{
				case 4: k--; v -= 2;
				case 3: case 1:
					if(k > 1)
						n = 1;
					else if(k == 1 && v > 2)
						n = 2;
					break;
				case 2:
					if(k > 3)
						n = 1;
					else if(k == 3 && v > 1)
						n = 2;
					break;
				case 6: case 7:
					if(k > 6)
						n = 1;
					else if(k == 6 && v > 0)
						n = 2;
					break;
				default: break;
			}
		}
		if(this._n0 + 1 == s)
		{
			v = t.charCodeAt(s - 1) - 48;
			switch(field)
			{
				case 4: v--; k -= 2;
				case 3: case 1:
					if(v > 1 || (v == 1 && k > 2))
						n = 3;
					break;
				case 2:
					if(v > 3 || (v == 3 && k > 1))
						n = 3;
					break;
				case 6: case 7:
					if(v > 6 || (v == 6 && k > 0))
						n = 3;
					break;
				default: break;
			}
		}
		if(n == 1)
		{
			t = t.substring(0, s) + mask.charAt(s) + t.substring(s + 1);
			s++;
		}
		if(n == 2)
			t = t.substring(0, s + 1) + mask.charAt(s + 1) + t.substring(s + 2);
		if(n == 3)
		{
			while(++s < i)
				if(mask.charCodeAt(s) < 22)
					break;
			if(s >= i)
				return -1;
			return this._maskKey(k + 48, c, t, i, s, mask);
		}
		this._txt = t.substring(0, s) + c + t.substring(s + 1);
		return ++s;
	},
	spin:function(v)
	{
		if(this._cal)
			return;
		if(this._spinList(v))
			return;
		var x, i = this._spinField, d = new Date();
		d.setTime(this._date.getTime());
		if(i < 0 || i > 8)
		{
			if(this._fcs == 2)
			{
				this.getSelectedText();
				i = this._curField(this._sel0, this._mask);
				if((d = this._toDate(this._val(), true, true, this._fcs >= 0)) == null)
					d = new Date();
				this._spinField = i;
			}
			else this._spinField = i = this.d_s;
		}
		/* 0-y,1-M,2-d,3-h,4-H,5-AMPM,6-m,7-s,8-ms */
		if(i == 5)
			v = (v > 0) ? 12 : -12;
		x = this._spinOnlyOneField;
		switch(i)
		{
			case 0:
				d.setFullYear(v += d.getFullYear());
				if(x && v != d.getFullYear())
					i = -1;
				break;
			case 1:
				d.setMonth(v += d.getMonth());
				if(x && v != d.getMonth())
					i = -1;
				break;
			case 2:
				d.setDate(v += d.getDate());
				if(x && v != d.getDate())
					i = -1;
				break;
			case 3: case 4: case 5:
				i = d.getDate();
				d.setHours(v += d.getHours());
				if(x && i != d.getDate())
					i = -1;
				break;
			case 6:
				d.setMinutes(v += d.getMinutes());
				if(x && v != d.getMinutes())
					i = -1;
				break;
			case 7:
				d.setSeconds(v += d.getSeconds());
				if(x && v != d.getSeconds())
					i = -1;
				break;
			case 8:
				for(i = this._n1 - this._n0; i++ < 3;)
					v *= 10;
				d.setMilliseconds(v += d.getMilliseconds());
				if(x && v != d.getMilliseconds())
					i = -1;
				break;
		}
		if(i < 0)
			return;
		if((v = this._limits(d)) != null)
			d = v;
		this._text = this._toTxt(d, this._fcs == 2, this._prompt, true);
		this._date = d;
		this._isNull = false;
		this._updatePost(d, '');
		this._repaint();
		this.select(this._sel0);
		if(this._fcs == 2)
			this._last = this._val();
	},
	get_date:function()
	{
		/// <summary>
		/// Gets value in editor as Date.<br />
		/// </summary>
		return this._instant(true);
	},
	getValueByMode:function(mode, limit)
	{
		/// <summary>Gets value according to DataMode.</summary>
		/// <param name="mode" type="Number">DataMode which matches with enum on server.</param>
		/// <param name="limit" optional="true" mayBeNull="true">Internal use only.</param>
		/// <returns mayBeNull="true">Value in control.</returns>
		var d = (this._fcs < 2) ? (this._isNull ? null : this._date) : this._toDate(this._val(), true, limit);
		if(this._vld == 1)
			this._msV(d ? this._toTxt(d, true, '') : '');
		if(mode == 0)
			return d;
		return this._toTxt(d, mode == 1, this._empty);
	},
	_instant:function(date, limit)
	{
		return this.getValueByMode(date ? 0 : this._mode, limit == true);
	},
	_date7:function(v, monthFix)
	{
		if(v.length < 10)
			return null;
		var y, o = v.split('-');
		if(o.length < 7)
			return null;
		if(monthFix == null)
			monthFix = this._backState ? -1 : 0;
		v = new Date(y = this._int_i(o, 0), this._int_i(o, 1) + monthFix, this._int_i(o, 2), this._int_i(o, 3), this._int_i(o, 4), this._int_i(o, 5), this._int_i(o, 6));
		if(y < 100)
			v.setFullYear(y);
		return v;
	},
	get_value:function(date)
	{
		/// <summary>Gets value in editor according to DataMode.</summary>
		this._vld = 1;
		return this._instant(date, true);
	},
	set_value:function(val, o)
	{
		if(val != null && !val.getTime)
		{
			if(this._fcs < 0)
			{
				if(val.length < 8)
					val = '';
				o = val.split(',');
				if(o.length > 2)
					this._max = this._date7(o[2]);
				if(o.length > 1)
					this._min = this._date7(o[1]);
				val = this._date7(o[0]);
			}
			else
				val = this._toDate(val.toString(), this._mode < 2 && o != true);
		}
		o = val;
		if((val = this._limits(val)) == null)
			val = o;
		this._txt = this._mask;
		if(this._isNull = (val == null))
			val = new Date();
		else
			this._toTxt(val, true, '', true);
		this._date = val;
		if(this._good)
			this._goodD = val;
		this._text = this._focusTxt(this._fcs > 1);
		this._updatePost(this._isNull ? null : val, '');
		this._repaint();
		if(this._fix == 1)
			this._old = this._instant(true);
		this._fixNull();
	}
}
$IG.WebDateTimeEditor.registerClass('Infragistics.Web.UI.WebDateTimeEditor', $IG.WebMaskEditor);

$IG.WebDatePicker = function(elem)
{
	/// <summary>Class which implements client side functionality of WebDatePicker.</summary>
	/// <param name="elem" type="Object">Reference to html element.</param>
	$IG.WebDatePicker.initializeBase(this, [elem]);
}
$IG.WebDatePicker.prototype =
{
	setCalendarOpened:function(show, update)
	{
		/// <summary>Opens or closes drop-down calendar.</summary>
		/// <param name="show" type="Boolean">Value of true is request to open calendar, false: close.</param>
		/// <param name="update" type="Boolean">Value of true is the request to update editor with value selected in calendar. It has effect only if calendar was opened.</param>
		this._doCal(null, show, update);
	},
	getCalendarOpened:function()
	{
		/// <summary>Checks if drop-down calendar is opened.</summary>
		/// <returns type="Boolean">True if calendar is opened.</returns>
		this._cal != null;
	},
	get_calendar:function()
	{
		/// <summary>
		/// Gets reference to currently opened WebMonthCalendar.<br />
		/// Note: the calendar cannot be used for actions which will conflict with default behavior of WebDatePicker. For example,
		/// set_selectedDate(date), setFocus() and similar actions are not supported.
		/// </summary>
		return this._cal;
	},
	get_animation:function()
	{
		/// <summary>Gets reference to SlideFadeAnimation which is a container of properties related to animation.</summary>
		return this._animation;
	},
	/* process key events: pass them to calendar */
	_calKey:function(e, k, a)
	{
		var cal = this._cal;
		/* allow to enter 0123456789/.,:-+ */
		if(!cal || k == 9 || (this._cal_key && (k == 8 || k == 46 || (k > 185 && k < 192) || (k > 43 && k < 60) || (k > 95 && k < 106))))
			return false;
		$util.cancelEvent(e);
		var close = k == 27 && cal._listID < 1;
		if(a == 0)
			cal._doKey(e);
		if(close)
			this._doCal(e);
		return true;
	},
	/* process global mouseup event to close calendar */
	_onDocMouse:function(e)
	{
		var elem = e ? e.target : null, cal = this._cal;
		if(elem) if((cal && $util.isChild(cal._element, elem)) || $util.isChild(this._element, elem))
			return;
		this._doCal(e);
	},
	_doCal:function(e, show, update)
	{
		var cal = this._cal, id = this._calID;
		if(!show && !cal)
			return;
		if(!cal && !$util.isEmpty(id))
			if(!(cal = $find(id)))
				cal = $util.findControl(id);
		if(!cal || !cal.set_selectedDate)
			return;
		var args = null, d = this._timeFix, old = cal._master;
		if(old)
		{
			if(old != this)
				old._doCal(e);
			else if(show)
				return;
		}
		if(show)
		{
			if(this._readOnly)
				return;
			if(this._fcs < 1)
				this.focus();
			this._cal = cal;
			if(e)
				args = this._raiseClientEvent('CalendarOpening', 'Cancel', e);
			if(args && args.get_cancel())
			{
				this._cal = null;
				return;
			}
			this.select();
			/* save old date as this._timeFix for time portion of date */
			cal._drop(this, this._timeFix = d = this.get_date());
			/* attempt to close calendar when mouse is clicked on other elements */
			/* mousedown can be canceled, so, it cannot be processed: try mouseup */
			if(!this._docMouseFn)
				this._docMouseFn = Function.createDelegate(this, this._onDocMouse);
			/* if that validation failed, then it means drop-down logic was crashed: at least avoid exception */
			if(!this._hasDocUp)
				$addHandler(document, 'mouseup', this._docMouseFn);
			this._hasDocUp = true;
			if(e)
				this._raiseClientEvent('CalendarOpened', null, e);
			return;
		}
		/* if that validation failed, then it means drop-down logic was crashed: at least avoid exception */
		if(this._hasDocUp)
			$removeHandler(document, 'mouseup', this._docMouseFn);
		this._hasDocUp = null;
		cal._drop();
		this._cal = cal._master = null;
		var date = update ? cal.get_selectedDate() : null;
		args = e ? this._raiseClientEvent('CalendarClosed', 'TextEditorValueChanging', e, 0, date, d) : null;
		if(args)
		{
			if(args.get_cancel())
				update = false;
			var d2 = args.get_value();
			if(d2 && d2.getDay)
				date = d2;
		}
		if(!update)
			return;
		/* restore time portion of date */
		if(d)
		{
			date.setHours(d.getHours());
			date.setMinutes(d.getMinutes());
			date.setSeconds(d.getSeconds());
			date.setMilliseconds(d.getMilliseconds());
			if(d.getTime() == date.getTime())
				return;
		}
		this._fix = 0;
		this.set_value(date);
		/* disable validation for modified value on lost focus */
		this._last = this._val();
		this._fix = 1;
		this._fireEvt(12, e);
	}
}
$IG.WebDatePicker.registerClass('Infragistics.Web.UI.WebDatePicker', $IG.WebDateTimeEditor);

/* event which is fired before value is changed */
$IG.TextEditorValueChangingEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events before value change in WebTextEditor.</summary>
	$IG.TextEditorValueChangingEventArgs.initializeBase(this);
}
$IG.TextEditorValueChangingEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-new value, 3-old value */
	get_value:function()
	{
		/// <summary>Gets sets new value.</summary>
		return this._props[2];
	},
	get_oldValue:function()
	{
		/// <summary>Gets old value.</summary>
		return this._props[3];
	},
	set_value:function(val)
	{
		this._props[2] = val;
	}
}
$IG.TextEditorValueChangingEventArgs.registerClass('Infragistics.Web.UI.TextEditorValueChangingEventArgs', $IG.CancelEventArgs);

/* event which is fired after value in editor was changed */
$IG.TextEditorValueChangedEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after value change in WebTextEditor.</summary>
	$IG.TextEditorValueChangedEventArgs.initializeBase(this);
}
$IG.TextEditorValueChangedEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-new value, 3-old value */
	get_value:function()
	{
		/// <summary>Gets new value.</summary>
		return this._props[2];
	},
	get_oldValue:function()
	{
		/// <summary>Gets old value.</summary>
		return this._props[3];
	}
}
$IG.TextEditorValueChangedEventArgs.registerClass('Infragistics.Web.UI.TextEditorValueChangedEventArgs', $IG.PostBackEventArgs);

/* event which is fired after text in editor was changed */
$IG.TextEditorTextChangedEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after text change in WebTextEditor.</summary>
	$IG.TextEditorTextChangedEventArgs.initializeBase(this);
}
$IG.TextEditorTextChangedEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-new text, 3-old text */
	get_text:function()
	{
		/// <summary>Gets new text.</summary>
		return this._props[2];
	},
	get_oldText:function()
	{
		/// <summary>Gets old text.</summary>
		return this._props[3];
	}
}
$IG.TextEditorTextChangedEventArgs.registerClass('Infragistics.Web.UI.TextEditorTextChangedEventArgs', $IG.EventArgs);

/* event which is fired before key event was processed */
$IG.TextEditorKeyEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after value change in WebTextEditor.</summary>
	$IG.TextEditorKeyEventArgs.initializeBase(this);
}
$IG.TextEditorKeyEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-keyCode */
	get_keyCode:function()
	{
		/// <summary>Gets keyCode of key event.</summary>
		return this._props[2];
	}
}
$IG.TextEditorKeyEventArgs.registerClass('Infragistics.Web.UI.TextEditorKeyEventArgs', $IG.CancelEventArgs);

/* event which is fired before keypress was processed */
$IG.TextEditorKeyPressEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after value change in WebTextEditor.</summary>
	$IG.TextEditorKeyPressEventArgs.initializeBase(this);
}
$IG.TextEditorKeyPressEventArgs.prototype =
{
	get_char:function()
	{
		/// <summary>Gets sets character of key event.</summary>
		return String.fromCharCode(this._props[2]);
	},
	set_char:function(val)
	{
		if(!$util.isEmpty(val))
			this._props[2] = val.charCodeAt(0);
	},
	set_keyCode:function(val)
	{
		/// <summary>Sets new value for keyCode.</summary>
		if(val && typeof val == 'number')
			this._props[2] = val;
	}
}
$IG.TextEditorKeyPressEventArgs.registerClass('Infragistics.Web.UI.TextEditorKeyPressEventArgs', $IG.TextEditorKeyEventArgs);

/* event which is fired when invalid value was entered in WebNumericEditor */
$IG.NumericEditorInvalidValueEventArgs = function()
{
	/// <summary>Base class for object used as parameter while raising client events related to postback action.</summary>
	$IG.NumericEditorInvalidValueEventArgs.initializeBase(this);
}
$IG.NumericEditorInvalidValueEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-invalid args(value,text,type) */
	isLimit:function()
	{
		/// <summary>Checks if number is out of minimum or maximum limit.</summary>
		/// <returns type="Boolean">True - value is out of limits.</returns>
		return this._props[2].type == 1;
	},
	isNull:function()
	{
		/// <summary>Checks if number is null when EnableNull is disabled.</summary>
		/// <returns type="Boolean">True - null value.</returns>
		return this._props[2].type == 2;
	},
	isInvalidText:function()
	{
		/// <summary>Checks if text in editor can not be converted to number.</summary>
		/// <returns type="Boolean">True - invalid text.</returns>
		return this._props[2].type == 0;
	},
	/* this._props: 0-event, 1-postBackAction, 2-invalid args(value,text,type) */
	get_text:function()
	{
		/// <summary>Gets text displayed in editor.</summary>
		return this._props[2].text;
	},
	/* this._props: 0-event, 1-postBackAction, 2-invalid args(value,text,type) */
	get_value:function()
	{
		/// <summary>Gets sets new value.</summary>
		return this._props[2].value;
	},
	set_value:function(val)
	{
		this._props[2].value = val;
	}
}
$IG.NumericEditorInvalidValueEventArgs.registerClass('Infragistics.Web.UI.NumericEditorInvalidValueEventArgs', $IG.EventArgs);

/* event which is fired when invalid value was entered in WebDateTimeEditor */
$IG.DateTimeEditorInvalidValueEventArgs = function()
{
	/// <summary>Base class for object used as parameter while raising client events related to postback action.</summary>
	$IG.DateTimeEditorInvalidValueEventArgs.initializeBase(this);
}
$IG.DateTimeEditorInvalidValueEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-invalid args(type,date,year,month,etc..) */
	isLimit:function()
	{
		/// <summary>Checks if date is out of minimum or maximum limit.</summary>
		/// <returns type="Boolean">True - date is out of limits.</returns>
		return this._props[2].type == 1;
	},
	isNull:function()
	{
		/// <summary>Checks if date is null when EnableNull is disabled.</summary>
		/// <returns type="Boolean">True - null value.</returns>
		return this._props[2].type == 2;
	},
	isInvalidText:function()
	{
		/// <summary>Checks if text in editor can not be converted to date.</summary>
		/// <returns type="Boolean">True - invalid text.</returns>
		return this._props[2].type == 0;
	},
	/* this._props: 0-event, 1-postBackAction, 2-invalid args(type,date,year,month,etc..) */
	get_year:function()
	{
		/// <summary>Gets value entered in year field or null.</summary>
		return this._props[2].year;
	},
	get_month:function()
	{
		/// <summary>Gets value entered in month field or null.</summary>
		return this._props[2].month;
	},
	get_day:function()
	{
		/// <summary>Gets value entered in day-of-month field or null.</summary>
		return this._props[2].day;
	},
	get_hours:function()
	{
		/// <summary>Gets value entered in hours field in 24-hour format (adjusted for possible AM/PM) or null.</summary>
		return this._props[2].hours;
	},
	get_minutes:function()
	{
		/// <summary>Gets value entered in minutes field or null.</summary>
		return this._props[2].minutes;
	},
	get_seconds:function()
	{
		/// <summary>Gets value entered in seconds field or null.</summary>
		return this._props[2].seconds;
	},
	get_milliseconds:function()
	{
		/// <summary>Gets value entered in milliseconds field or null.</summary>
		return this._props[2].milliseconds;
	},
	/* this._props: 0-event, 1-postBackAction, 2-invalid args(type,date,year,month,etc..) */
	get_value:function()
	{
		/// <summary>Gets sets new value.</summary>
		return this._props[2].date;
	},
	set_value:function(val)
	{
		return this._props[2].date = val;
	}
}
$IG.DateTimeEditorInvalidValueEventArgs.registerClass('Infragistics.Web.UI.DateTimeEditorInvalidValueEventArgs', $IG.EventArgs);

/* event which is fired after value in editor was changed */
$IG.MaskEditorInvalidValueEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after value change in WebTextEditor.</summary>
	$IG.MaskEditorInvalidValueEventArgs.initializeBase(this);
}
$IG.MaskEditorInvalidValueEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-value */
	get_value:function()
	{
		/// <summary>Gets sets new value.</summary>
		return this._props[2].value;
	},
	set_value:function(val)
	{
		return this._props[2].value = val;
	}
}
$IG.MaskEditorInvalidValueEventArgs.registerClass('Infragistics.Web.UI.MaskEditorInvalidValueEventArgs', $IG.EventArgs);

/* event which is fired before key event was processed */
$IG.TextEditorSpinEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after value change in WebTextEditor.</summary>
	$IG.TextEditorSpinEventArgs.initializeBase(this);
}
$IG.TextEditorSpinEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-delta */
	get_delta:function()
	{
		/// <summary>
		/// Gets delta of spin event. That is used to increment current value in editor.
		/// In case of WebTextEditor it can be +1 or -1.
		/// In case of numeric and date editors it can be positive or negative value defined by get_spinDelta().
		/// </summary>
		return this._props[2];
	}
}
$IG.TextEditorSpinEventArgs.registerClass('Infragistics.Web.UI.TextEditorSpinEventArgs', $IG.CancelEventArgs);

/* event which is fired after animation of drop-down calendar was stopped */
$IG.DatePickerAnimationStoppedEventArgs = function()
{
	/// <summary>Class used as EventArgs while raising events after animation of drop-down calendar was stopped.</summary>
	$IG.DatePickerAnimationStoppedEventArgs.initializeBase(this);
}
$IG.DatePickerAnimationStoppedEventArgs.prototype =
{
	/* this._props: 0-event, 1-postBackAction, 2-open or close action */
	get_opened:function()
	{
		/// <summary>Checks if drop-down calendar was opened or closed.</summary>
		return this._props[2];
	}
}
$IG.DatePickerAnimationStoppedEventArgs.registerClass('Infragistics.Web.UI.DatePickerAnimationStoppedEventArgs', $IG.EventArgs);
