onReady = (function(ie){
	var d = document;
	var func = false;
	if ( d.addEventListener ){
		func = function(c){
			d.addEventListener("DOMContentLoaded", c, false);
		}
	}
	else if ( ie ){
		func = function(c){
			var n = d.firstChild,
			f = function(){
				try{
					c(n.doScroll('left'))
				}catch(e){
					setTimeout(f, 10)
				}
			}; f()
		}
	}
	else if ( /webkit|safari|khtml/i.test(navigator.userAgent) ){
		func = function(c){
			var f = function(){
				/loaded|complete/.test(d.readyState) ? c() : setTimeout(f, 10)
			}; f()
		}
	}
	else {
		func = function(c){
			d.addEventListener("DOMContentLoaded", c, false);
		}
	}
	//alert( ie );
	//alert( func );
	return func;
	
})(/*@cc_on 1@*/);

/* ------------------------- Inheritance -------------------------------- */

Function.prototype.inheritsFrom = function( superClass ) {	/* Механизм наследования: добавляет всем Object поле superClass ( ссылается на родительский конструктор ) и метод inheritsFrom( superClass ) */
	var Inheritance = function(){};
	Inheritance.prototype = superClass.prototype;
	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	this.superClass = superClass;
}

/* ---------------------------------------------------------------------- */
/* ------------------------------ IL ------------------------------------ */
/* ---------------------------------------------------------------------- */

IL = function() {											/* Базовый конструктор, поле stack хранит ссылки на все екземпляры унаследованных классовб поле Observers хранит подписчиков */
	IL.stack[ IL.stack.length ] = this;
	this.Observers = new Array();
}

window.onunload = function() {

	//var timeBefore = new Date();
	//this.inf.innerHTML = 'b = ' + timeBefore.getTime();
	IL.removeFromStack();
	//var timeAfter = new Date();
	//var workTime = timeAfter.getTime() - timeBefore.getTime();
	//this.inf.innerHTML = workTime;
}

IL.stack = new Array();

/* ---------------------------------------------------------------------- */

IL.removeUnitFromStack = function( i ) {					/* Удаляет из стэка объект, отписывает всех подписчиков и снимает обработчики событий */
	var cO = this.stack[i];									/* i( String/Int ) -> индекс удаляемого объекта */

	for( var ev in cO.Observers ) {
		cO.Observers[ ev ];
		for( var j = cO.Observers[ev].length; j; j-- ) {
			var cObs = cO.Observers[ev][ j - 1 ];
			cO.detachObserver( ev, cObs.Action, cObs.Context );
			cObs = null;
		}
	}
	cO.Observers = null;

	for( var c in cO ) {
		if( cO[c] != null && cO[c].handlers ) {
			for( var ev in cO[c].handlers ) {
				for( var j = cO[c].handlers[ ev ].length; j > 0; j-- ) {
					var cH = cO[c].handlers[ ev ][ j - 1 ];
					//var tS = '';
					//for ( var ttt in cH.context ) {
					//	if ( ttt != 'addHandler' && ttt != 'attachObserver' && ttt != 'detachObserver'){
					//		tS += ttt + ' = '  + cH.context[ ttt ] +  ';'
					//	}
					//}
					//alert( c + '\n' + tS );
					if( cH.context.removeHandler ){
						cH.context.removeHandler( cO[c], ev, cH.handler, cH.arguments, cH.capture );
					}
				}
			}
		}
		//var rrr = typeof cO[c];
		if ( typeof cO[c] != 'function' ) cO[c] = null;
	}
	cO = null;
	//this.stack[ i ] = null;
	//alert( 'stack = ' + this.stack[ i ] + '\n' + 'cO = ' + cO );
}

/* ---------------------------------------------------------------------- */

IL.removeFromStack = function( obj ) {						/* Удаляет из стэка все объекты( при obj = false )/объект переданный в obj, отписывает всех подписчиков и снимает обработчики событий */
	if( obj ) {												/* оbj( Object ) */
		for( var i = this.stack.length; i > 0; i-- ) {
			if( obj === this.stack[ i - 1 ] ) break;
		}
		
		this.removeUnitFromStack( i - 1 );
		this.stack.splice( i - 1, 1 );
	}
	else
	{
		for( var i = this.stack.length; i > 0; i-- ) {
			this.removeUnitFromStack( i - 1 );
		}
		this.stack = [];
	}
}

/* --------------------- Get HTML Element By ID ------------------------- */

IL.prototype.getEl = function( id ) {						/* Ищет DOM элемен по ID */
	if( !id ) return false;									/* id( String ) */
	return document.getElementById( id ) || false;
}

/* -------------------------- Add Handler ------------------------------- */
/* Навешивает обработчик событий */
/* el( DOM element ) Элемент, на который будет повешено событие */
/* event( String ) Название события без 'on'. Например: 'click', 'blur', 'load'*/
/* handler( Function ) Метод контекста, либо анонимная функция */
/* params( Object ) Объект параметров, который будет передан в обработчик */
/* capture( Boolean ) */

IL.prototype.addHandler = function( el, event, handler, params, capture ) {
	if( !el ) return false;
	if( !el.handlers ) el.handlers = new Array();
	if( !el.handlers[ event ] ) {
		el.handlers[ event ] = new Array();
	} else {
		for( var c in el.handlers[ event ] ) {
			var cH = el.handlers[ event ][ c ];
			if( cH.handler == handler && cH.context == this ) {
				return false;
			}
		}
	}

	capture = capture || false;
	el.handlers[ event ][ el.handlers[ event ].length ] = {
		handler: handler,
		arguments: params,
		capture: capture,
		context: this
	}

	if( !el.handle ) {
		el.handle = function( ev ) {
			return IL.commonHandler( ev, el );
		}
	}
	
	if( document.addEventListener ) {
		el.addEventListener( event, el.handle, capture );
	} else {
		if( capture ) el.releaseCapture();
		el.attachEvent( 'on' + event, el.handle );
	}
}

/* ------------------------- Remove Handler ----------------------------- */
/* Навешивает обработчик событий */
/* el( DOM element ) Элемент, на который повешено событие */
/* event( String ) Название события без 'on'. Например: 'click', 'blur', 'load'*/
/* handler( Function ) Обработчик */
/* params( Object ) Объект параметров, который передан в обработчик */
/* capture( Boolean ) */

IL.prototype.removeHandler = function( el, event, handler, params, capture ) {
	if( !el || !el.handlers || !el.handlers[ event ] ) return false;

	var cH = false;
	for( var c in el.handlers[ event ] ) {
		cH = el.handlers[ event ][ c ];
		if( cH.handler == handler && cH.context == this ) break;
	}

	if( cH ) {
		if( document.removeEventListener ) {
			el.removeEventListener( event, el.handle, cH.capture );
		} else {
			if( cH.capture ) el.releaseCapture();
			el.detachEvent( 'on' + event, el.handle );
		}

		cH.handler = null;
		cH.arguments = null;
		cH.capture = null;
		el.handlers[ event ][ c ] = null;
		el.handlers[ event ].splice( c, 1 );
	}

	//alert( el.handles );
	if( el.handlers[ event ] && el.handlers[ event ].length == 0 ) delete el.handlers[ event ];
	for( var any in el.handlers ) return false;
	el.handlers = false;
	if ( el.handle )	el.handle = false;
}

/* ------------------------- Common Handler ----------------------------- */
/* Исполнение обработчика в конексте с передачей параметров */
/* ev( Event ) */
/* el( DOM element ) Элемент, в котором произошло событие */

IL.commonHandler = function( ev, el ) {
	var eventHandlers = el.handlers[ ev.type ];
	for( var c in eventHandlers ) {
		var cH = eventHandlers[ c ];
		if( cH.handler ) cH.handler.call( cH.context, cH.arguments, ev );
	}
}

/* ----------------------- Prevent Default ------------------------------ */

IL.prototype.preventDefault = function( ev ) {				/* Блокировка действия по умолчанию браузера */
	ev = ev || window.event;								/* ev( Event ) */
	if( !ev ) return false;
	ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
}

/* ----------------------- Stop Propagaion ------------------------------ */

IL.prototype.stopPropagation = function( ev ) {				/* Блокировка всплытия события */
	ev = ev || window.event;								/* ev( Event ) */
	if( !ev ) return false;
	ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;
}

/* ----------------------- Attach Observer ------------------------------ */
/* Добавление подписчика */
/* sEv( String ) Название custom события */
/* Action( Function ) Метод контекста или анонимная функция */
/* Context( Object ) Контекст исполнения */

IL.prototype.attachObserver = function( sEv, Action, Context ) {
	Context = Context || this;
	if( !( Action instanceof Object ) || !( Context instanceof Object ) ) return;
	if( !this.Observers[ sEv ] ) this.Observers[ sEv ] = new Array();	

	Action = {
		Context: Context,
		Action: Action
	};

	this.Observers[ sEv ].push( Action );
}

/* ----------------------- Detach Observer ------------------------------ */
/* Удаление подписчика */
/* sEv( String ) Название custom события */
/* Action( Function ) Обработчик. Метод контекста или анонимная функция */
/* Context( Object ) Контекст исполнения */

IL.prototype.detachObserver = function( sEv, Action, Context ) {
	Context = Context || this;
	if( !( Action instanceof Object ) || !( Context instanceof Object ) ) return;
	if( this.Observers[ sEv ] ) {
		for( var c in this.Observers[ sEv ] ) {
			var cA = this.Observers[ sEv ][c];
			if( cA.Action == Action && cA.Context == Context ) break;
		}
		this.Observers[ sEv ].splice( c, 1 );
	}
}

/* ---------------------------- Notify ---------------------------------- */
/* Оповещение подписчиков */
/* sEv( String ) Название custom события */
/* params( Object ) Объект параметров передаваемый в обработчик */

IL.prototype.notify = function( sEv, params ) {
	if( !(this.Observers && this.Observers[ sEv ]) ) return;

	for( var c in this.Observers[ sEv ] ) {
		var cA = this.Observers[ sEv ][c];
		cA.Action.call( cA.Context, params, this );
	}
}

/* ---------------------------- Remove ---------------------------------- */

IL.prototype.remove = function() {					/* Удаление объекта */
	IL.removeFromStack( this );
}

IL.prototype.toString = function() {
	return this.Id;
}
/* ---------------------------------------------------------------------- */

IL.prototype.getCookie = function( a ) {			/* Значение куки */
	var b = document.cookie;
	var c = a + "=";
	var d = b.indexOf( "; " + c );
	
	if( d == -1 ) {
		d = b.indexOf( c );
		if( d != 0 ) return null;
	} else {
		d += 2;
	}

	var e = document.cookie.indexOf( ";", d );
	if( e == -1 ) e = b.length;
	return unescape( b.substring( d + c.length, e ) );
}

/* ---------------------------------------------------------------------- */

IL.prototype.setCookie = function( a, b, c, d, e, f ) {	/* Установить куку */
	var g = a + '=' + escape( b ) + (  c ? '; expires=' + c.toGMTString() : '' )+( d ? '; path=' + d : '' ) + ( e ? '; domain=' + e : '' ) + ( f ? '; secure' : '' );
	document.cookie = g;
}

/* ---------------------------------------------------------------------- */

IL.prototype.getError = function() { return 'Ошибка'; } /* Абстрактный метод */

/* ---------------------------------------------------------------------- */
/* Функция форматирующая дату */
/* date( Date ) Js объект даты */
/* возвращает строку в формате дд-мм-гггг*/

function formatDate( date ) {
	if( !date || !( date instanceof Date ) ) return false;
	var year = date.getFullYear();
	var month = ( date.getMonth() + 1 ) < 10 ? '0' + ( date.getMonth() + 1 ) : ( date.getMonth() + 1 );
	var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();

	//return date.getFullYear() + '-' + ( date.getMonth() + 1 ) + '-' + date.getDate();
	return year + '-' + month + '-' + day;
}

//----------------------------------------------------------------------------//
/* Функция форматирующая числа */
/* value( String/Int ) Число или строка */
/* afterDot( Boolean ) Флаг на копейки */
/* возвращает строку в формате '# ### ###(.##)'*/

function stringWhiteParse( value, afterDot ) {
	if( afterDot ) {
		var v = parseInt( value );
		var f = value - v;
	} else {
		var v = Math.ceil( value );
	}

	if( isNaN( v ) ) return false;
	var s = new String( v );
	var len = s.length;
	
	if ( len > 4 ) {
		var frtLen = len % 3;
		var parseResult = '';
		if (frtLen != 0) parseResult = s.substr(0, frtLen) + '&nbsp;';
		if (frtLen != len) {
			parseResult += s.substr(frtLen, 3);
			for ( var i = 1; i < Math.floor(len / 3); i++ )	{
				parseResult += '&nbsp;' + s.substr(frtLen + i*3, 3);
			}
		}
	} else {
		parseResult = v;
	}
	
	if( afterDot && f > 0 ){
		parseResult += ',' + ( f.toFixed( 2 ) + '' ).substr( 2 );
	}
	return String( parseResult );
}

// -------------------------------------------------------------------------- //
/* Функция выводящая существительное после числа в подходящем роде */
/* count( Int ) Число */
/* variants( Array ) массив из 3х значений */
/* возвращает строку в формате 'Число Существительное в нужном падеже */
/* Пример: 1 день, 2 дня, 5 дней */

function wordByCount( count, variants ) {
	var string = count + '';

	var last = Number( string.substr( string.length - 1, 1 ) );
	var prelast = string.length > 1 ? Number( string.substr( string.length - 2, 1 ) ) : NaN;

	var type = 2;
	if(
		isNaN( prelast ) ||
		prelast != 1
	) {
		if( last == 1 ) type = 0;
		else if(
			last > 1 &&
			last < 5
		) type = 1;
	}
	return variants[ type ];
}

