var months = [ 'янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек' ];
var monthsFN = [ 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' ];

// -------------------------------------------------------------------------- //
// ----------------------- Поля ввода и выбора ------------------------------ //
// -------------------------------------------------------------------------- //
// переделан input_new. Настройки полей берутся из файла

if( window.HTMLGlif ) {

NInput = function( data ) {
	NInput.superClass.apply( this, arguments );
	this.settings = data[ 'settings' ];

	this.Id = 'NInput';
	this.type = data[ 'type' ] || 'text';			// text, select, date, predicate
	this.iType = data[ 'iType' ] || 'text';			// text или password

	this.name = data[ 'name' ];
	this.label = this.settings[ 'label' ];

	this.tip = this.settings[ 'tip' ];				// подсказка
	this.required = this.settings[ 'required' ] || false;	// требуемое ли поле
	this.disabled = this.settings[ 'disabled' ] || false;
	this.cls = data[ 'cls' ] || '';					// дополнительный класс
	this.data = null;								// данные

	var isMadeFromXSL = ( data[ 'madeFromXSL' ] ? true : false );

	if ( isMadeFromXSL ){
		this.elementParent = this.getEl( data[ 'idBlock' ] );
		this.setClassName( this.type + ' ' + this.cls, true, this.elementParent );
		this.element = this.elementParent.firstChild;
		this.elementInner = this.element.firstChild;
		this.elementInput = this.elementInner.firstChild;
		this.elementInput.type = this.iType;
		this.elementInput.name = this.name;
		this.elementInput.value = this.iType != 'password' ? this.label : '';
		this.elementTip = this.elementInner.lastChild;
	} else {
		this.elementParent = this.createNode( 'div', { 'class': this.type + ' ' + this.cls }, data[ 'target' ] );
		this.element = this.createNode( 'fieldset', false, this.elementParent );
		this.elementInner = this.createNode( 'div', { 'class': 'inner' }, this.element );
		this.elementInput = this.createNode( 'input',
			{ type: this.iType, name: this.name, value: ( this.iType != 'password' ? this.label : '' ) }, this.elementInner );
		this.elementTip = this.createNode( 'span', { 'class': 'tip' }, this.elementInner );
	}
	
	this.active = false;							// в данный момент активное ли поле
	this.error = false;								// есть ли ошибка
	this.touched = false;							// если чел вошел и что-то написал
	this.status = false;
	this.setted = false;							// заполнено ли поле, для отображения

	this.addHandler( this.element, 'mouseover', this.hoverIn );
	this.addHandler( this.element, 'mouseout', this.hoverOut );
}
NInput.inheritsFrom( HTMLGlif );

NInput.prototype.toString = function(){
	return this.Id + ' (' + this.status + ')';
}
// -------------------------------------------------------------------------- //

NInput.prototype.hoverIn = function( flag, e ) {
	if ( e == undefined ) return;
	if( this.active ) return;
	var selfEl = this.element;
	var p = e.fromElement || e.relatedTarget;	// с какого элемента пришел курсор
	while ( p && p != selfEl ) try { p = p.parentNode } catch(e) { p = selfEl; };
	if ( p === null ) {
		this.setClassName( 'hover', true );
	}
}

NInput.prototype.hoverOut = function( flag, e ) {
	if ( e == undefined ) return;
	var selfEl = this.element;
	var p = e.toElement || e.relatedTarget;		// на какой элемент перешел курсор
	while ( p && p != selfEl ) try { p = p.parentNode } catch(e) { p = selfEl; };
	if ( p === null ) {
		this.setClassName( 'hover', false );
	}
}

NInput.prototype.getValue = function() {
	return this.elementInput.value;
}

NInput.prototype.setValue = function( sValue ) {
	sValue = sValue || '';
	if( typeof( sValue ) != 'string' ) {}
	else if (this.elementInput) {
		this.elementInput.value = sValue;
	}
}

NInput.prototype.getData = function( prop ) {
	if( prop != undefined ) {
		return this.data[ prop ];
	} else {
		return this.data;
	}
}

NInput.prototype.setData = function( data ) {
	this.data = ( data == undefined ? false : data );
}

NInput.prototype.set = function( data, value ) {
	if( !data && !value ) return;
	this.setData( data );
	this.setValue( value );
	this.notify( 'inputSetted' );
}

NInput.prototype.clear = function(){
	this.setData( false );
	this.setValue( '' );
	this.showLabel( true );
	//this.check();				//???
	this.touched = false;
	this.setSetted( false );
	this.status = false;
}

NInput.prototype.setSetted = function( flag ){
	this.setted = flag;
	this.setClassName( 'setted', this.setted );
}

NInput.prototype.setTip = function( flag ) {
	this.setContent( ( flag ? this.tip : this.label ), this.elementTip );
}

NInput.prototype.showLabel = function( flag ){
	if ( this.iType != 'password'){
		this.setValue( flag ? this.label : false );
		this.setData( false );
	}
}

NInput.prototype.showTip = function( flag ) {
	if ( this.iType == 'password' ) { flag = true; }
	this.setClassName( 'hidden', !flag, this.elementTip );
}

NInput.prototype.setError = function( flag, text ) {
	this.error = flag;
	this.setClassName( 'error', flag );
	if ( this.error ){
		this.setContent( text, this.elementError );
		this.setClassName( 'hidden', false, this.elementError );
	}
	else{
		this.setClassName( 'hidden', true, this.elementError );
		this.setContent( '', this.elementError );
	}
	
}

NInput.prototype.setDefault = function( data, value ){
	this.set( data, value );
	if ( this.Id == 'NPredicateInput' ){
		this.checkLabelValue();
		this.checkPatternAndNotifyStatus();
		this.setTip( false );		// находится в setActive
		this.setSetted( this.status );
	}
	else {
		this.blur();
	}
}

// -------------------------------------------------------------------------- //
// ------------------------- OLOLOLO Text Input ----------------------------- //
// -------------------------------------------------------------------------- //

NTextInput = function( obj ) {
	NTextInput.superClass.apply( this, arguments );

	this.Id = 'NTextInput';
	
	this.data = '';
	this.inputPattern = this.settings.patterns[ 'Typing' ] || /^.*$/;
	this.pattern = this.settings.patterns[ 'Submit' ];
	

	this.errorInputText = this.settings.messages[ 'IncorrectOnTyping' ];
	this.errorPatternText = this.settings.messages[ 'Incorrect' ];
	this.errorEmptyText = this.settings.messages[ 'Empty' ];
	this.errorControllerText = '';
	
	this.controlDelete = obj[ 'controlDelete' ] || false;

	if ( this.iType == 'password' ) {
		this.setTip( false );
	}
	
	if ( !this.required ){
		this.setClassName( 'not_required', true );
	}
	
	if ( this.controlDelete ){
		this.setRemovable();
	}
	this.elementError = this.createNode( 'div', { 'class': 'error_tip hidden' }, this.element );
	
	this.addHandler( this.element, 'click', this.focusElement );
	this.addHandler( this.elementInput, 'click', function( params, ev ) {
		this.stopPropagation( ev );
	});
		
	this.addHandler( this.elementInput, 'focus', this.focusInput );
	this.addHandler( this.elementInput, 'blur', this.blur );
	this.addHandler( this.elementInput, 'keyup', this.typing );
	this.addHandler( this.elementInput, 'change', this.typing );


	if ( this.disabled ){
		this.setDisabled();
	}
}
NTextInput.inheritsFrom( NInput );

// -------------------------------------------------------------------------- //

NTextInput.prototype.focusElement = function(){
	this.elementInput.focus();
}

NTextInput.prototype.focusInput = function(){
	this.setActive( true );
	this.checkLabelValue();
	this.showTip( true );
	this.setSetted( false );
}

NTextInput.prototype.blur = function(){
	this.setActive( false );
	this.checkLabelValue();
	this.checkPatternAndNotifyStatus();
	if ( !this.touched ){
		this.showTip( false );
		this.setSetted( false );
	}
	else {
		this.showTip( this.status );
		this.setSetted( this.status );
	}
}

NTextInput.prototype.checkLabelValue = function(){
	var value = this.getValue();
	var flag = ( value === this.label );
	this.touched = ! ( ( value === this.label ) || ( value == '' ) );
	if( flag && this.active ) {
		this.setValue( false );
		this.showLabel( false );
	} else if( ( flag || value == '' ) && !this.active ) {
		this.setValue( false );
		this.showLabel( true );
	}
	return flag;
}

NTextInput.prototype.checkInput = function() {
	this.status = false;

	this.status = this.inputPattern.test( this.getValue() );
	this.setError( !this.status, this.errorInputText );
	return this.status;
}

NTextInput.prototype.checkPattern = function() {
	if ( !this.touched ){
		this.status = false;
		return false;
	} else {
		var oS = this.status;
		this.status = false;

		this.status = this.pattern.test( this.getValue() );
		this.setError( !this.status, this.errorPatternText );
	}
	return this.status;
}

NTextInput.prototype.checkPatternAndNotifyStatus = function(){
	this.checkPattern();
	this.notify( 'inputStatusChange' );
}

NTextInput.prototype.checkToSubmit = function() {
	if( this.required ) {
		if ( !this.touched ) {
			if(
				!this.checkLabelValue() &&
				this.getValue()
			) {
				this.setData( this.getValue() );
				this.checkPatternAndNotifyStatus();
			} else {
				this.setError( true, this.errorEmptyText );
			}
		} else {
			if(
				!this.checkLabelValue() &&
				this.getValue() &&
				!this.getData()
			) {
				this.setData( this.getValue() );
			}
			this.checkPatternAndNotifyStatus();
		}
		return this.status;
	} else {
		return true;
	}
}

NTextInput.prototype.typing = function( params, ev ) {
	var cVal = this.getValue();

	this.setData( cVal );
	this.checkInput();
	if ( this.status )	this.notify( 'inputSetted' );
	return true;
}

NTextInput.prototype.setRequired = function( flag ) {
	this.required = flag;
	this.setClassName( 'not_required', !flag );
}

NTextInput.prototype.setActive = function( flag ) {
	this.active = flag;
	this.setClassName( 'active', this.active );
	this.hoverOut();
	this.setTip( flag );
}

NTextInput.prototype.setRemovable = function(){
	if (!this.elementControl) {
		this.elementControl = this.createNode( 'span', { 'class': 'control delete' },
				this.elementInner,
				'<img class="png" src="/images/fields/close.png" alt="удалить поле" title="удалить поле" width="96" height="48" />' );
		this.addHandler( this.elementControl, 'click', this.removeInput );
	}
	else {
		this.removeHandler( this.elementControl, 'click', this.removeInput );
		this.elementControl.parentNode.removeChild( this.elementControl ); 
		this.elementControl = false;
	}
}

NTextInput.prototype.removeInput = function( params, ev ){
	this.notify( 'RemoveMe', this );
	this.stopPropagation( ev );
}

NTextInput.prototype.setDisabled = function() {
	this.disabled = true;
	this.elementInput.setAttribute( 'disabled', 'disabled' );
	this.elementInput.readOnly = true;
	this.removeHandler( this.element, 'mouseover', this.hoverIn, true );
	this.removeHandler( this.element, 'mouseout', this.hoverOut, false );
	this.removeHandler( this.elementInput, 'keyup' );		//Убрать обработчики событий для disabled поля
	this.removeHandler( this.elementInput, 'change' ); 
}

NTextInput.prototype.getValueToParam = function(){
	//var data = this.getData();
	return ( this.getValue() != this.label ? this.getValue() : '' );		//( !data ? '' : data );
}


// -------------------------------------------------------------------------- //
// --------------------------- Date Input ----------------------------------- //
// -------------------------------------------------------------------------- //

NDateInput = function( obj ){
	NDateInput.superClass.apply( this, arguments );
	
	this.Id = 'DateInput';
	this.errorMinMaxText = this.settings.messages[ 'MinMax' ];
	this.controlDelete = obj[ 'controlDelete' ];

	this.min = obj[ 'min' ] || false;
	this.max = obj[ 'max' ] || false;
	this.mask = 'дд.мм.гггг';
	
	this.lastValidDate = null;

	this.showThisYear = obj[ 'showThisYear' ] || false;
	
	this.patternWithMask = /^[0-9д]{2}.[0-9м]{2}.[0-9г]{4}$/;
	this.patternWithoutMask = /^[0-9]{2}.[0-9]{2}.[0-9]{4}$/;
	
	this.setClassName( 'side', true, this.elementTip );

	if ( this.controlDelete ){
		this.elementControl = this.createNode( 'span', { 'class': 'control delete' },
			this.elementInner, '<img class="png" src="/images/fields/close.png" alt="удалить поле" width="96" height="48" />' );
	}
	
	if ( this.min ) this.setMin( this.min );
	if ( this.max ) this.setMax( this.max );
	
	this.array = new Array();
	
	this.addHandler( this.elementInput, 'keypress', this.onKeyPress );
	this.addHandler( this.elementInput, 'keydown', this.onKeyDown );
}
NDateInput.inheritsFrom( NTextInput );

// -------------------------------------------------------------------------- //

NDateInput.prototype.setMin = function( data ) {
	if( !( data instanceof Date ) ) return;
	this.min = data;
}

NDateInput.prototype.setMax = function( data ) {
	if( !( data instanceof Date ) ) return;
	this.max = data;
}

// -------------------------------------------------------------------------- //
// преобразование строки в объект дата
NDateInput.prototype.formateToDate = function( data ) {
	if( data instanceof Date ) return data;
	if( typeof data != 'string' ) return false;

	var array = data.split( '.' );

	if( !array || !array[0] || !array[1] || !array[2] ) return false;
	if( array[2].length != 4 || array[1].length != 2 || array[0].length != 2 ) return false;
	
	var year = new Number( array[2] );
	var month = new Number( array[1] ) - 1;
	var day = new Number( array[0] );

	if( 0 >= day || day > 31 || 0 > month || month > 11 || 1900 > year || year > 2100 ) return false;

	var result = new Date( year, month, day ) || false;
	if( result.getDate ) {
		if( result.getDate() != day ) return false;
	} else {
		return false;
	}
	return result;
}
// форматирование даты к виду dd.MM.YYYY
NDateInput.prototype.formateToDDMMYYY = function( date ){
	var year = date.getFullYear();
	var month = ( ( ( date.getMonth() + 1 ) < 10 ) ? '0' : '' ) + ( date.getMonth() + 1 );
	var day = ( ( date.getDate() < 10 ) ? '0' : '' ) + date.getDate();
	var datestr = day + '.' + month + '.' + year;
	return datestr;	
}
// форматирование даты к виду 2001-02-03
NDateInput.prototype.setFormatedDigitalValue = function(){
	var date = this.getData();
	if ( !( date instanceof Date ) ) return;
	var datestr = this.formateToDDMMYYY( date );
	this.setValue( datestr );
}
// форматирование даты к виду 3 апреля 2010
NDateInput.prototype.setFormatedLetterValue = function(){
	var date = this.getData();
	if( !( date instanceof Date ) ) return;
	//var now = new Date();
	var showYear = false;
	if ( now.getFullYear() != date.getFullYear() || this.showThisYear ){
		showYear = true;
	}
	var datestr = date.getDate() + ' ' + monthsFN[ date.getMonth() ] + ( showYear ? ' ' + date.getFullYear() : '' );
	this.setValue( datestr );
}

// -------------------------------------------------------------------------- //

NDateInput.prototype.focusInput = function(){
	this.setFormatedDigitalValue();
	NDateInput.superClass.prototype.focusInput.apply(this, arguments);
}

NDateInput.prototype.blur = function(){
	if( !this.status ) {
	
	}
	this.setFormatedLetterValue();
	
	NDateInput.superClass.prototype.blur.apply(this, arguments);
	if ( this.status )	this.notify( 'inputSetted' );
}

NDateInput.prototype.checkLabelValue = function() {
	var value = this.getValue();
	var flag = ( value == this.label );
	this.touched = ! ( ( value === this.label ) || ( value === this.mask ) || ( value == '' ) );
	if( flag && this.active ) {
		this.showLabel( false );
		this.setValue( this.mask );
		this.moveCaretTo( 0 );
	}
	else if ( ( flag || value == '' || value == this.mask || value == this.label ) && !this.active ) {
		this.setValue( false );
		this.showLabel( true );
	}
	else if ( !flag && this.active ){
		this.elementInput.select();
		this.selected = true;
	}
}

NDateInput.prototype.checkInput = function() {
	this.status = false;

	this.status = this.patternWithMask.test( this.getValue() );
	this.setError( !this.status, this.errorInputText );
}

NDateInput.prototype.checkPattern = function() {
	if ( !this.touched ) return;
	if ( this.error ) return;
	
	var oS = this.status;
	this.status = false;

	if( this.data instanceof Date ) this.status = true;
	if( this.status ){
		if( ( this.min && this.min.valueOf && this.min.valueOf() > this.data.valueOf() ) || 
			( this.max && this.max.valueOf && this.max.valueOf() < this.data.valueOf() ) ){
			this.errorMinMax = true;
			this.status = false;
		}
		else {
			this.errorMinMax = false;
		}
	}
	
	this.setError( !this.status, ( this.errorMinMax ? this.errorMinMaxText : this.errorPatternText ) );
}

NDateInput.prototype.checkPatternAndNotifyStatus = function(){
	this.checkPattern();
	//if ( !( oS === this.status ) )
	this.notify( 'inputStatusChange' );	
}

NDateInput.prototype.checkToSubmit = function() {
	if ( this.required ){
		if ( !this.status )	{
			if ( !this.touched ) this.setError( true, this.errorEmptyText );
			else {
				this.checkPattern();
			}
		}
		return this.status;
	}
	else {
		return true;
	}
}

NDateInput.prototype.setData = function( data ) {
	this.data = false;
	if( data instanceof Date ) {
		this.data = data;
		return;
	}

	if ( this.patternWithoutMask.test( data ) ){
		this.data = this.formateToDate( data ); 
		return;
	}
}

NDateInput.prototype.set = function( data ){
	this.setData( data );
	if ( this.active ) {
		this.setFormatedDigitalValue();
	} else {
		this.setFormatedLetterValue();
		this.setSetted( true );
	}

	if ( data instanceof Date ){
		this.touched = true;
		this.setError( false );
	}
}

NDateInput.prototype.typing = function( params, ev ) {		// вызвать setData и checkInput
	var cVal = this.getValue();

	var e = ev || window.event;
	var code = e.keyCode;		//e.charCode || 
	if ( e.ctrlKey || e.altKey ) return true;

	if ( code == 27 ) return false;		// esc

	if ( code == 35 || code == 36 || code == 37 || code == 39 ) return true;			// end, home, left, right
	if( code == 8 ) {
		var cVal = this.getValue();
		var start = this.getSelectionStart();
		var end = this.getSelectionEnd();
		if( start == end ) start--;
		var key = this.mask.substring( start, end );
		if ( key == '.' ){
			start--;
			end--;
			key = this.mask.substring( start, end );
		}

		var nVal = ( ( start > 0 ) ? cVal.substring( 0, start ) : '' ) + key.toString() + cVal.substring( end, cVal.length );
		this.setValue( nVal );
		if ( this.mask.substring( start - 1, start ) == '.' ){
			this.moveCaretTo( start - 1 );
		}
		else {
			this.moveCaretTo( start );
		}
	}
	else if ( code == 46 ) {
		var cVal = this.getValue();
		var start = this.getSelectionStart();
		var end = this.getSelectionEnd();
		if( start == end ) end++;
		var key = this.mask.substring( start, end );
		nVal = ( ( start > 0 ) ? cVal.substring( 0, start ) : '' ) + key.toString() + cVal.substring( end, cVal.length );
		this.setValue( nVal );
		this.moveCaretTo( start );
	}
	else {
		this.setData( cVal );	// если дата полностью введена, то data заполняется, если нет, то false
	}
	this.checkInput();
	return true;
}

NDateInput.prototype.onKeyDown = function( params, ev ) {		// предотвратить нажатие после 10 цифр
	ev = ev || window.event;
	var code = ev.keyCode;		//ev.charCode || 
	if( ev.ctrlKey || ev.altKey ) return false;

	// разрешить выполнение клавиш "стрелочки", tab и enter всегда
	if ( code == 35 || code == 36 || code == 37 || code == 39 || code == 9 || code == 13 ){
		this.selected = false;
		return true;
	}
	
	var sel = this.getSelectionStart();

	// запретить действия по-умолчанию для del и backspace и после 10-го символа
	if (
		code == 8 ||
		code == 46 ||
		sel == 10
	){
		this.preventDefault( ev );
		return false;
	}
	return true;
}

NDateInput.prototype.onKeyPress = function( params, ev ) {
	ev = ev || window.event;
	if ( ev.ctrlKey || ev.altKey ) return false;

	var code = ev.charCode || ev.keyCode;
	if ( code == 27 ) {
		this.elementInput.blur();
		return false;
	}

	if ( code < 32 && code != 8 ) return true;
	if ( code == 35 || code == 36 || code == 37 || code == 39 /*|| code == 9 || code == 13*/ ){	// end, home, left, right
		return true;
	}

	if( ( code >= 48 && code <= 57 ) || ( code >= 96 && code <= 105 ) ) {
		var sel = this.getSelectionStart();
		var cVal = this.getValue();
		if( sel == 10 ) {
			this.preventDefault( ev );
			return false;
		}

		if( cVal.substr( sel, 1 ) == '.' ) {
			sel++;
			this.moveCaretTo( sel );
		}

		var key = String.fromCharCode( ( ( code < 96 ) ? code : ( code - 48 ) ) );
		nVal = ( ( sel > 0 ) ? cVal.substring( 0, sel ) : '' ) + key.toString() + cVal.substring( sel + 1, cVal.length );
		this.setValue( nVal );
		sel++;
		this.moveCaretTo( sel );

		if( cVal.substr( sel, 1 ) == '.' ) {
			sel++;
			this.moveCaretTo( sel );
		}
	}
	
	this.preventDefault( ev );
	return true;
}

NDateInput.prototype.getSelectionStart = function() {
	if( this.elementInput.selectionStart ) return this.elementInput.selectionStart;
	else if ( document.selection && 'v' == '\v' ) {
		var sel = document.selection.createRange();
		var clone = this.elementInput.createTextRange();
		clone.setEndPoint( 'EndToStart', sel );
		return clone.text.length;
	}
	return 0;
}

NDateInput.prototype.getSelectionEnd = function() {
	if( this.elementInput.selectionEnd ) return this.elementInput.selectionEnd;
	else if ( document.selection && 'v' == '\v' ) {
		var sel = document.selection.createRange();
		var clone = this.elementInput.createTextRange();
		clone.setEndPoint( 'EndToEnd', sel );
		return clone.text.length;
	}
	return 0;
}

// -------------------------------------------------------------------------- //

NDateInput.prototype.moveCaretTo = function( position ) {
	if( this.elementInput.setSelectionRange ) {
		this.elementInput.setSelectionRange( position, position );
	} else {
		var rng = this.elementInput.createTextRange();
		rng.collapse( true );
		rng.move( 'character', position );
		rng.select();
	}
}

NDateInput.prototype.getValueToParam = function(){
	return formatDate( this.getData() );
}

// -------------------------------------------------------------------------- //
// -------------------------- Predicate Input ------------------------------- //
// -------------------------------------------------------------------------- //

NPredicateInput = function( obj ) {
	NPredicateInput.superClass.apply( this, arguments );

	this.Id = 'NPredicateInput';
	this.command = obj[ 'command' ] || 'SearchAirLocation';
	this.expanded = false;
	this.listOfExamples = obj[ 'examples' ] || false;
	this.timer = false;
	this.errorFromController = false;
	
	if ( this.listOfExamples ){
		this.setExamples();
	}
	
	this.elementParent.setAttribute( 'id', this.name );
	this.elementInput.setAttribute( 'autocomplete', 'off' );
	
	this.pad = new Pad({ list: false, target: this.elementParent });
	this.pad.attachObserver( 'Selected', this.selected, this );
	
	this.store = new Store( '/ajax/cities.html', { 'Commander.Command': this.command, 'Top': 7 } );
	this.store.attachObserver( 'Loaded', this.storeLoaded, this ); 	

	this.addHandler( this.pad.element, 'mouseover', this.toggleHoverPad, true );
	this.addHandler( this.pad.element, 'mouseout', this.toggleHoverPad, false );
	
	this.removeHandler( this.elementInput, 'change', this.typing );
}
NPredicateInput.inheritsFrom( NTextInput );

// -------------------------------------------------------------------------- //

NPredicateInput.prototype.toggleHoverPad = function( flag ){
	this.setClassName( 'hoverPad', flag );
	if ( !flag ) this.pad.current = false;
}

NPredicateInput.prototype.focusElement = function( params, ev ) {
	this.elementInput.focus();
	this.stopPropagation( ev );
}

NPredicateInput.prototype.focusInput = function( params, ev ) {
	this.setActive( true );
	this.checkLabelValue();
	this.showTip( true );
	this.setSetted( false );
	if ( this.getValue() != '' ) this.elementInput.select();
}

NPredicateInput.prototype.blur = function(){
	var objInput = this;
	window.setTimeout( function() {
		if ( !objInput.data && objInput.pad.rows.length > 0 ){
			objInput.pad.getIndexOfCurrent();
			var cR = objInput.pad.currentIndex;
			if ( cR < 0 ) cR = 0;
			objInput.set( objInput.pad.rows[ cR ].data, objInput.pad.rows[ cR ].data[ 'Name' ] );
		}
		objInput.showPad( false );
		objInput.pad.removeList();
		objInput.setActive( false );
		objInput.checkLabelValue();
		objInput.checkPatternAndNotifyStatus();
		if ( !objInput.touched ) objInput.setExamples();
		objInput.setSetted( objInput.status );
	
	}, 200 );
}

NPredicateInput.prototype.setActive = function( flag ) {
	this.active = flag;
	this.setClassName( 'active', this.active );
	this.hoverOut();
	this.setTip( flag );		// показывает код аэропорта и страну или подсказку
}

NPredicateInput.prototype.showPad = function( flag ){
	this.expanded = flag;
	if ( this.pad ) this.pad.show( flag );
	this.setClassName( 'expanded', flag, this.elementParent );
}

NPredicateInput.prototype.selected = function( data ){
	this.set( data, data[ 'Name' ] );		// вызывет 'inputSetted'
	this.blur();
}

NPredicateInput.prototype.setExamples = function() {
	this.setContent( 'например: ', this.elementTip );
	this.examples = new Array();
	for ( var i = 0, len = this.listOfExamples.length; i < len; i++ ){
		var el = this.createNode( 'span', { 'class': 'example' }, this.elementTip, this.listOfExamples[ i ][ 'Name' ] );
		if ( i < len - 1 ){
			this.elementTip.appendChild( document.createTextNode( ', ' ) );
		}
		this.addHandler( el, 'click', this.setExample, this.listOfExamples[ i ] );
		this.examples[ i ] = el;
	}
}

NPredicateInput.prototype.setExample = function( data, ev ){
	this.set( data, data[ 'Name' ] );
	for ( var i = this.listOfExamples.length; i > 0; i-- ){
		this.removeHandler( this.examples[ i ], 'click', this.setExample, this.listOfExamples[ i ] );
		this.examples.splice( i - 1, 1 );
	}
	this.stopPropagation( ev );
	this.blur();
}

NPredicateInput.prototype.setTip = function( flag ) {
	var val = ( this.data && this.data[ 'Code' ] != '' ?
				this.data[ 'Code' ] +
				( ( this.data[ 'Country' ] != undefined && this.data[ 'Country' ] != '' ) ?
					', ' + this.data[ 'Country' ] :
					'' )
				: '' );
	this.setContent( ( flag ? this.tip : val ), this.elementTip );
}

NPredicateInput.prototype.checkPattern = function() {
	var oS = this.status;
	
	this.status = false;
	if ( this.touched ) {
		if( ( this.data && this.data instanceof Object ) ) this.status = true;
		if ( this.errorFromController ) this.status = false;

		this.setError( !this.status, ( this.errorFromController) ? this.errorControllerText : this.errorPatternText );

	}
}

NPredicateInput.prototype.checkPatternAndNotifyStatus = function(){
	this.checkPattern();
	//if( !( oS === this.status ) )
	this.notify( 'inputStatusChange' );
}

NPredicateInput.prototype.checkToSubmit = function() {
	if ( this.required ){
		if ( !this.status )	{
			if ( !this.touched ) this.setError( true, this.errorEmptyText );
			else {
				this.checkPattern();
			}
		}
		return this.status;
	}
	else {
		return true;
	}
}

NPredicateInput.prototype.typing = function( params, ev ) {
	var e = ev || window.event;
	var code = e.charCode || e.keyCode;
	if ( e.altKey ) return true;

	if ( code == 27 ){		//esc
		this.elementInput.blur();
		return false;
	}
	if ( code !== 0 && code < 32 && code != 8 && code != 13 ) return true;
	if ( code == 35 || code == 36 || code == 37 || code == 39 ) return true;	// end, home, left, right

	if ( code != 38 && code != 40 && code != 13 && code != 27 && code != 9 ) {	// up, dowm, enter, escape, tab
		if( this.active ) this.typingLetters();//this.notify( 'Typing' );
	} else {
		this.pad.specialKeyPressed( code );
	}
	return true;
}

NPredicateInput.prototype.typingLetters = function(){
	var value = this.getValue();
	this.setData( false );
	this.setTip( true );
	this.errorFromController = false;
	this.setError( false );

	if( value ) {
		if ( this.timer) {
			clearTimeout( this.timer );
			this.timer = false;
		}
		var obj = this;
		this.timer = window.setTimeout( function() { loadData( obj.store, obj ); }, 500 );
	} else {
		this.pad.removeList();
	} 
}

NPredicateInput.prototype.removeDuplicates = function( result ){
	var newResult = [];
	for (var i = 0, l = result.length; i < l; i++) {
		if ( newResult.length == 0 ) {
			newResult[i] = result[i];
		}
		else {
			for (var j = 0, le = newResult.length; j < le; j++) {
				if (result[i].Code == newResult[j].Code) break;
				if (j + 1 == le) newResult[le] = result[i];
			}
		}
	}
	return newResult;
}

NPredicateInput.prototype.storeLoaded = function( result ){
	this.showPad( false );
	this.setData( false );
	this.pad.removeList();
	result = this.removeDuplicates( result );
	this.pad.addList( result );
	if ( this.pad.rows.length > 0 ){
		this.showPad( true );
	}
}

function loadData( store, input ) {
	var value = input.getValue();
	store.addParams( { Word: value } );
	store.load();
}

NPredicateInput.prototype.reset = function(){
	this.clear();
	this.setError( false );
	this.errorFromController = false;
	this.setExamples();
}

NPredicateInput.prototype.getValueToParam = function(){
	return this.getData( 'Id' );
}

// -------------------------------------------------------------------------- //
// ------------------------------- Select ----------------------------------- //
// -------------------------------------------------------------------------- //

NSelect = function( obj ) {
	NSelect.superClass.apply( this, arguments );
	
	this.Id = 'NSelect';
	this.list = obj[ 'list' ];
	this.initialValue = obj[ 'initialValue' ] || false;
	this.controlBrowse = true;
	this.expanded = false;

	this.errorEmptyText = ( this.settings.messages && this.settings.messages[ 'Empty' ] ? this.settings.messages[ 'Empty' ] : 'Необходимо заполнить поле' );
	this.errorControllerText = '';
	
	this.elementInput.readOnly = true;
	this.setClassName( 'side', true, this.elementTip );
	if ( this.controlBrowse ){
		this.elementControl = this.createNode( 'span', { 'class': 'control browse' },
			this.elementInner, '<img class="png" src="/images/fields/browse' +
			( obj[ 'color' ] == 'green' ? '-green' : '' ) + '.png" alt="показать список" ' +
			'height="48" width="' + ( obj[ 'color' ] == 'green' ? '48' : '72' ) + '" />' );
	}

	this.elementError = this.createNode( 'div', { 'class': 'error_tip hidden' }, this.element );	

	this.pad = new Pad({ list: this.list, target: this.elementParent });

	this.elementDocumentBody = document.body;
	this.addHandler( this.elementDocumentBody, 'click',
		function( params, ev ){
			this.showPad( false );
			this.stopPropagation( ev );
		});
	
	this.addHandler( this.element, 'click', this.focusElement );
	this.addHandler( this.elementInput, 'click', function( params, ev ) { this.stopPropagation( ev ); });
	this.addHandler( this.elementInput, 'focus', this.focusInput );
	this.addHandler( this.elementInput, 'blur', this.blur );
	this.addHandler( this.elementInput, 'keydown', this.onKeyDown );

	this.addHandler( this.elementControl, 'click', function( params, ev ) {
		this.stopPropagation( ev );
		if ( !this.expanded )
			this.elementInput.focus();
		else
			this.elementInput.blur();
	});
	
	this.pad.attachObserver( 'Selected', this.selected, this );
	this.pad.attachObserver( 'Scrolled', this.scrolled, this );
	this.addHandler( this.pad.element, 'mouseover', this.toggleHoverPad, true );
	this.addHandler( this.pad.element, 'mouseout', this.toggleHoverPad, false );

	if ( !this.required ){
		this.setClassName( 'not_required', true );
		this.setInitialValue( this.list[ 0 ][ 'value' ] );
	}

	if ( this.initialValue ){
		this.setInitialValue( this.initialValue );
	}

}
NSelect.inheritsFrom( NInput );

// -------------------------------------------------------------------------- //

NSelect.prototype.toggleHoverPad = function( flag ){
	this.setClassName( 'hovpad', flag );
}

NSelect.prototype.focusElement = function( params, ev ){
	this.stopPropagation( ev );
	this.elementInput.focus();
}

NSelect.prototype.focusInput = function( params, ev ) {
	this.scrolled = false;
	this.setActive( true );
	this.showTip( true );
	this.setSetted( false );
	this.setError( false );
	this.showPad( true );
}

NSelect.prototype.scrolled = function(){
	this.scrolled = true;
}

NSelect.prototype.blur = function( params, ev ){
	var objInput = this;
	window.setTimeout( function() {
		if ( objInput.scrolled ) return;
		objInput.setActive( false );
		objInput.showPad( false );

		objInput.check();
		objInput.setSetted( objInput.getData() ? true : false );
	}, 200 );
}

NSelect.prototype.setActive = function( flag ) {
	this.active = flag;
	this.setClassName( 'active', this.active );
	this.hoverOut();
	this.setTip( flag );
}

NSelect.prototype.showPad = function( flag ){
	this.expanded = flag;
	this.setClassName( 'hidden', !flag, this.pad.element );
	this.setClassName( 'expanded', flag, this.elementParent );
}

NSelect.prototype.selected = function( data ){
	if ( this.data ){
		for ( var i = 0; i < this.pad.rows.length; i++ ){
			if ( this.pad.rows[ i ].data != data ){
				this.pad.rows[ i ].unsetData();
			}
		}
	}
	this.set( data, data[ 'Name' ] );
	this.scrolled = false;
	this.blur();
}

NSelect.prototype.setInitialValue = function( val ){
	var data = false;
	for ( var i = 0; i < this.pad.list.length; i++ ){
		if ( this.pad.list[ i ][ 'Value' ] == val ){
			data = this.pad.list[ i ];
			this.setClassName( 'current', true, this.pad.rows[ i ].elementTD );
			break;
		}
		else {
			this.pad.rows[ i ].unsetData();
		}
	}
	this.set( data, data[ 'Name' ] );
	this.setTip( false );
	this.check();
	this.setSetted( true );
}

NSelect.prototype.onKeyDown = function( params, ev ) {
	var e = ev || window.event;
	var code = e.keyCode;

	if ( code == 13 || code == 38 || code == 40 ) {
		this.pad.specialKeyPressed( code );
		this.stopPropagation( ev );
		this.preventDefault( ev );
	}
}

NSelect.prototype.check = function() {
	var oS = this.status;

	this.status = false;

	if ( this.data )	this.status = true;
	if ( !( oS === this.status ) ) this.notify( 'inputStatusChange' );
}

NSelect.prototype.checkToSubmit = function() {
	if ( this.required ){
		if ( !this.status )	{
			if ( !this.data ) this.setError( true, this.errorEmptyText );
			else {
				this.check();
			}
		}
		return this.status;
	}
	else {
		return true;
	}
}

NSelect.prototype.getValueToParam = function(){
	return this.getData( 'Value' );
}


// -------------------------------------------------------------------------- //
// -------------------------------- Pad ------------------------------------- //
// -------------------------------------------------------------------------- //

Pad = function( obj ){
	Pad.superClass.apply( this, arguments );
	
	this.Id = 'Pad';
	this.list = new Array();
	//obj[ 'list' ];
	
	this.element = this.createNode( 'div', { 'class': 'pad hidden' }, obj[ 'target' ] );
	this.elementInner = this.createNode( 'div', { 'class': 'inner' }, this.element );
	if ( obj[ 'list' ].length > 7 ){
		var elScroll = this.createNode( 'div', { 'class': 'scroll' }, this.elementInner );
		this.elementInner = elScroll;
		this.addHandler( this.elementInner, 'scroll', function() { this.notify( 'Scrolled' ); } )
	}
	this.elementTable = this.createNode( 'table', false, this.elementInner );
	this.elementTBody = this.createNode( 'tbody', false, this.elementTable );
	this.rows = new Array();
	
	this.current = false;
	this.currentIndex = -1;
	
	//this.removeList();
	this.addList( obj[ 'list' ] );
}

Pad.inheritsFrom( HTMLGlif );

Pad.prototype.show = function( flag ){
	this.setClassName( 'hidden', !flag );
}

Pad.prototype.addList = function( list ){
	//this.list = list;	// || this.list;
	for ( var i = 0; i < list.length; i++ ){
		this.list[ i ] = list[ i ];
		this.rows[ i ] = new PadRow({ data: list[ i ], target: this.elementTBody });
		this.rows[ i ].attachObserver( 'Selected', function( data ){ this.notify( 'Selected', data ) }, this );
		this.rows[ i ].attachObserver( 'CurrentRow', function( obj ){ this.current = obj; }, this );
	}
}

Pad.prototype.removeList = function(){
	if ( !this.rows || this.rows.length == 0 ) return;
	for( var i = this.rows.length; i; i-- ) {
		this.rows[ i - 1 ].detachObserver( 'Selected', function( data ){ this.notify( 'Selected', data ) }, this );
		this.rows[ i - 1 ].detachObserver( 'CurrentRow', function( obj ){ this.current = obj; }, this );
		this.rows[ i - 1 ].remove();
		this.rows.splice( i - 1, 1 );
		this.list.splice( i - 1, 1 );
	}
	this.show( false );
	//this.list = false;
}

Pad.prototype.getIndexOfCurrent = function(){
	this.currentIndex = -1;
	for ( var i = 0, len = this.rows.length; i < len; i++ ){
		if ( this.rows[ i ] == this.current ){
			this.currentIndex = i;
		}
	}
}

Pad.prototype.specialKeyPressed = function( code ) {
	if( this.rows.length == 0 ) return;
	this.getIndexOfCurrent();
	if ( code == 38 && this.currentIndex == 0 ){}
	//up
	if ( code == 38 && this.currentIndex > 0 ){
		this.rows[ this.currentIndex ].notify( 'hoverRow', false );
		this.rows[ this.currentIndex - 1 ].notify( 'hoverRow', true );
	}
	// down
	if ( code == 40 && this.currentIndex < ( this.rows.length - 1 ) ) {
		if ( this.currentIndex != -1 ) this.rows[ this.currentIndex ].notify( 'hoverRow', false );
		this.rows[ this.currentIndex + 1 ].notify( 'hoverRow', true );
	}
	// enter
	if ( code == 13 ){
		if ( this.currentIndex < 0 ){
			this.currentIndex = 0;
		}
		if ( this.rows[ this.currentIndex ] ) {
			this.notify( 'Selected', this.rows[ this.currentIndex ].data );
		}
	}
}

// -------------------------------------------------------------------------- //
// ----------------------------- Pad Row ------------------------------------ //
// -------------------------------------------------------------------------- //

PadRow = function( obj ){
	PadRow.superClass.apply( this, arguments );
	
	this.Id = 'PadRow';
	this.data = obj[ 'data' ];
	
	this.element = this.createNode( 'tr', false, obj[ 'target' ] );
	
	var HTML = '';
	for( var c in this.data['HTML'] ) {
		HTML += this.data['HTML'][ c ];
	}
	this.elementTD = this.createNode( 'td', false, this.element, '<div>' + HTML + '</div>' );

	this.addHandler( this.element, 'mouseover', this.toggleHover, true );
	this.addHandler( this.element, 'mouseout', this.toggleHover, false );
	this.attachObserver( 'hoverRow', this.toggleHover, this );
	
	this.addHandler( this.element, 'click', this.setData );
}
PadRow.inheritsFrom( HTMLGlif );

// -------------------------------------------------------------------------- //

PadRow.prototype.toggleHover = function( flag ) {
	this.current = flag;
	if ( this.current ) this.notify( 'CurrentRow', this );
	this.setClassName( 'hover', flag );
}

PadRow.prototype.setData = function(){
	this.setClassName( 'current', true, this.elementTD );
	this.notify( 'Selected', this.data );
}

PadRow.prototype.unsetData = function(){
	this.setClassName( 'current', false, this.elementTD );
}

// -------------------------------------------------------------------------- //
// --------------------------- Checkbox ------------------------------------- //
// -------------------------------------------------------------------------- //

Checkbox = function( obj ) {
	Checkbox.superClass.apply( this, arguments );
	
	this.Id = 'CheckBox';
	this.type = 'checkbox';
	this.name = obj[ 'name' ];
	this.label = obj[ 'label' ];
	this.checked = obj[ 'checked' ] || false;
	this.required = obj[ 'required' ] || false;
	this.disabled = obj[ 'disabled' ] || false;
	this.cls = obj[ 'cls' ] || '';
	this.big = obj[ 'big' ] || false;
	this.data = false;

	this.elementParent = this.createNode( 'div', { 'class': this.type + ' ' + this.cls }, obj[ 'target' ] );
	if ( this.big ){
		this.element = this.createNode( 'fieldset', false, this.elementParent );
		this.elementInner = this.createNode( 'div', { 'class': 'inner' }, this.element );
		this.elementImg = this.createNode( 'img',
			{ src: '/images/fields/checkbox_tick.png', 'class': 'png', width: 36, height: 36, alt: 'Выбрать' }, this.elementInner );

		this.addHandler( this.element, 'mouseover', this.hoverIn );
		this.addHandler( this.element, 'mouseout', this.hoverOut );
	}
	else {
		this.element = this.createNode( 'span', false, this.elementParent );
	}
	this.elementLabel = this.createNode( 'p', { 'class': 'label' + ( this.big ? ' big' : '' ) }, this.elementParent, this.label );

	this.setData( this.checked );
	
	this.active = false;
	this.status = this.checked;
	this.setted = false;

	this.addHandler( this.element, 'click', this.toggle );
	this.addHandler( this.elementLabel, 'click', this.toggle );

/*	
	this.element = this.createNode( 'div', { 'class': 'checkbox' }, obj[ 'target'] );
	this.elementCheckbox = this.createNode( 'span', false, this.element );
	this.elementLabel = this.createNode( 'p', { 'class': 'label' }, this.element, obj[ 'label' ] );
	//this.value = obj[ 'value' ] || false;
	this.status = true;
	this.required = obj[ 'required' ] || false;
	
	this.addHandler( this.elementCheckbox, 'click', this.toggle );
	this.addHandler( this.elementLabel, 'click', this.toggle );
*/
}
Checkbox.inheritsFrom( HTMLGlif );

// -------------------------------------------------------------------------- //

Checkbox.prototype.hoverIn = function( flag, e ) {
	if ( e == undefined ) return;
	if( this.active ) return;
	var selfEl = this.element;
	var p = e.fromElement || e.relatedTarget;	// с какого элемента пришел курсор
	while ( p && p != selfEl ) try { p = p.parentNode } catch(e) { p = selfEl; };
	if ( p === null ) {
		this.setClassName( 'hover', true );
	}
}

Checkbox.prototype.hoverOut = function( flag, e ) {
	if ( e == undefined ) return;
	var selfEl = this.element;
	var p = e.toElement || e.relatedTarget;		// на какой элемент перешел курсор
	while ( p && p != selfEl ) try { p = p.parentNode } catch(e) { p = selfEl; };
	if ( p === null ) {
		this.setClassName( 'hover', false );
	}
}

Checkbox.prototype.setRequired = function( flag ) {
	this.required = flag;
}

Checkbox.prototype.setDisabled = function( flag ) {
	this.disabled = flag;
	if ( flag ){
		this.removeHandler( this.element, 'click', this.toggle );
		this.removeHandler( this.elementLabel, 'click', this.toggle );
		this.setClassName( 'disabled', true, this.elementParent );
	}
	else {
		this.addHandler( this.element, 'click', this.toggle );
		this.addHandler( this.elementLabel, 'click', this.toggle );
		this.setClassName( 'disabled', false, this.elementParent );
	}
}

Checkbox.prototype.toggle = function() {
	this.setData( !this.value );
}

Checkbox.prototype.setData = function( flag ) {
	this.value = flag;
	this.notify( 'inputSetted' );
	this.setClassName( 'setted', flag );
	this.check();
}

Checkbox.prototype.getData = function() {
	return this.value;
}

Checkbox.prototype.check = function() {
	this.checkToSubmit();
	/*var oS = this.status;
	if( this.required ) {
		this.status = this.value;
	}
	else {
		this.status = true;
	}
	
	if( !( oS === this.status ) ) this.notify( 'inputStatusChange' );
	return this.status;*/
}

Checkbox.prototype.checkToSubmit = function() {
	var oS = this.status;
	if( this.required ) {
		this.status = this.value;
	}
	else {
		this.status = true;
	}
	
	if( !( oS === this.status ) ) this.notify( 'inputStatusChange' );
	return this.status;
}

Checkbox.prototype.getValueToParam = function(){
	return this.getData();
}

// конец условия показа класса HTMLGlif на странице
}
