	//**********Calendar Class**************
	function CalendarCLS(name, params)
	{
		this.summerTime = summerTime();
		this.timeOffsetGMT = timeOffset() - 1;
		//*********** необходимо переделать. при хранении объектов, оказывается, что мы храним лишь копии, а не на встроенные в DoM элементы...
		this.name = name;
		this.maxDate = (params.maxDate) ? params.maxDate + 3600*this.timeOffsetGMT*1000 : 0; //+3gmt & +1 summertime - надо бы вообще посмотреть как работает js с часовыми поясами
		this.minDate = (params.minDate) ? params.minDate + 3600*this.timeOffsetGMT*1000 : 0;
		this.weekSelect = (params.weekSelect);
		var myDate = new Date();
		if (this.maxDate)
		{
			myDate.setTime(this.maxDate)
			this.maxDate = Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate() + 1) - 1000; //последня секунда дня
		}
		if (this.minDate)
		{
			myDate.setTime(this.minDate)
			this.minDate = Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate());
		}
		this.minWidth = 280;
		this.minHeight = (params.showTime) ? 220 : 200;
		
		this.width = (params.width < this.minWidth) ? this.minWidth : params.width;
		this.height = (params.height < this.minHeight) ? this.minHeight : params.height;
		this.topContainer = null;
		this.mainContainer = null;
		this.timeContainer = null;
		
		this.parentWin = add_window(this.name + 'Container', 'Календарь', this.width + 10, this.height, false);
		this.parentWin.setWidth(this.width + 25);
		this.parentWin.setHeight(this.height + 25);
					
		this.returnEndOfDay = params.returnEndOfDay;
		
		this.target = "";
		this.curentValueTarget = "";
		this.defaultVal = "";
		this.curDate = this.minDate;
		var calContainer;
		if (calContainer = getElem(this.parentWin.contentID))
		{
			
			var calendar = createElement('div', this.name);
			calendar.style.width = this.width + "px";
			calendar.style.height = this.height + "px";
			calendar.style.margin = "0px auto";
			//*********
			var topContainer = createElement('div');
			this.topContainer = topContainer;
			this.topContainer.className = "cal_top_container";
			this.topContainer.style.height = 20 + "px";
			//*********
			var mainContainer = createElement('div');
			this.mainContainer = mainContainer;
			this.mainContainer.className = "cal_main_container";
			this.mainContainer.style.height = (this.height - 20 - ( (params.showTime) ? 20 : 0 )) + "px";
		
			//*********
			/*if (params.showTime)
			{
				this.timeContainer = createElement('div');
				this.timeContainer.className = "cal_time_container";
				this.timeContainer.style.height = 20 + "px";
				this.timeContainer.appendChild(document.createTextNode("test"));
			}*/
			
			calendar.appendChild(this.topContainer);
			calendar.appendChild(this.mainContainer);
			/*if (params.showTime)
				calendar.appendChild(this.timeContainer);*/
			
			calContainer.innerHTML = "";
			calContainer.appendChild(calendar);
			
		//	this.topContainer = getElem(this.name).children[0];
			//this.mainContainer = getElem(this.name).children[1];
			//this.mainContainer = getElem(this.name).children[1];
			
			this.animate = new AnimatedDivCLS(getElem(this.name).children[1]);
		}
		this.parentWin.hide();
	}
	//*************************************
	CalendarCLS.prototype.show = function(calValueHolderID, calTextHolder)
	{
		calTextHolder = (calTextHolder) ? calTextHolder : false;
		this.setTarget(calValueHolderID, calTextHolder); 
		this.parentWin.show(); 
		this.loadMonth(); 
		if (this.target)
			this.parentWin.setPos_parent(this.target);
	}
	//*************************************
	CalendarCLS.prototype.setTarget = function(valTargetID, obj)
	{
		if (obj)
			this.target = obj;
		this.curentValueTarget = getElem(valTargetID);
		if (this.curentValueTarget)
			this.defaultVal = this.curentValueTarget.value*1000;
	}
	//*************************************
	CalendarCLS.prototype.loadDays = function(month, year, direction)
	{
		var myDate = new Date();
		var curMonth = myDate.getMonth();
		var curYear = myDate.getFullYear();
		var curDay = myDate.getDate();
		
		myDate.setFullYear(year, month, 1);
		var days = day_in_month(month, year);
		
		var curUTCDay = (this.returnEndOfDay) ? Date.UTC(curYear, curMonth, curDay, 23, 59, 59) : Date.UTC(curYear, curMonth, curDay)
		var FirstUTCDay = Date.UTC(year, month, 1);
		var LastUTCDay = Date.UTC(year, month, days);
		
		var startDay = myDate.getDay();
		if (startDay == 0)
			startDay = 7;
		var totalCells = 6*7; //всего ячеек отображено
		var prvMonthCells = startDay-1; //дней предыдущего месяца
		if (!prvMonthCells)
			prvMonthCells = 7;
		var prvMonthDays = day_in_month(month-1, year);
		//вычисляем недели данного листа
		var year1stDayDate = Date.UTC(year, 0, 1);
		myDate.setFullYear(year, 0, 1)
		var year1stDay = myDate.getDay();
		var Day_ms = 1000*60*60*24;
		var year1stWeekStarts = year1stDayDate - Day_ms*year1stDay; // UTC день, с которого начинается первая неделя нового года
		var curDate = Date.UTC(year, month-1, prvMonthDays - prvMonthCells + 1); // UTC день, который будет первым в текущем календаре
		var curWeek = parseInt((curDate - year1stWeekStarts)/(7*Day_ms)) + 1;
		var thisWeek = parseInt((curUTCDay - year1stWeekStarts)/(7*Day_ms));
		//*********************************
		var tbl = createElement('table');
		tbl.style.width = this.width + 'px';
		tbl.style.height = (this.height - 20) + 'px';
		var tBody = createElement('tbody');	
		//********
		var headerTR = createElement('tr');
		headerTR.style.fontWeight = 'bold';
		//********
		var numTD = createElement('td');
		numTD.style.borderRight = '1px solid #000';
		numTD.appendChild(document.createTextNode("N"));
		headerTR.appendChild(numTD);
		//********
		var td = null;
		for (var i = 1; i <= 7; i++)
		{
			td = createElement('td');
			td.appendChild(document.createTextNode(weekdays2text(i, true)));
			headerTR.appendChild(td);
		}
		tBody.appendChild(headerTR);
		myDate.setTime(Date.UTC(year, month, prvMonthDays - prvMonthCells + 1)); //первый день на листе
		var bold = "";
		var day = 0;
		var buff_result = "";
		var text = "";
		var week_clr = "";
		var clr = "";
		var weekText = "";
		var cnt = 1; //общий счетчик дней, отображенных на листе
		var tr = null;
		for (var i = 1 - prvMonthCells; cnt <= totalCells; i++, cnt++)
		{
			td = createElement('td');
			var calText = createElement('div');
			
			day = (this.returnEndOfDay) ? Date.UTC(year, month, i, 23, 59, 59) : Date.UTC(year, month, i);	
			myDate.setTime(day);
			if (day >= FirstUTCDay && day <= LastUTCDay)
				clr = week_clr = "#000";
			else
			{
				clr = "#9BB2C1";
				week_clr = "#000";
			}
			if (myDate.getUTCDate() == 1 && myDate.getUTCMonth() == 0) //если текущий день - начало года
				curWeek = 1;
			var ths = this;
			var dayEnable = ( day >= this.minDate && ( (day <= this.maxDate) || (!this.maxDate) ) );
			if (dayEnable && !this.weekSelect)  // если текущий день попадает в область допустимых дат
			{
				calText.appendChild(document.createTextNode(myDate.getUTCDate()));
				calText.className += 'cal_link';
				calText.title = day;				
				Event.add(calText, "click", function(e) { ths.return_date(this.title) });
				Event.add(calText, "mouseover", function(e) { this.className = this.className.replace(/cal_link/, 'cal_link_over'); });
				Event.add(calText, "mouseout", function(e) { this.className = this.className.replace(/cal_link_over/, 'cal_link'); });
			}
			else
			{
				calText.className += "cal_text";
				calText.appendChild(document.createTextNode(myDate.getUTCDate()));
			}
			if (day == curUTCDay) //если текущий день
			{
				calText.style.fontWeight = "bold";
				calText.style.border = "2px solid #000";
			}
			td.appendChild(calText);
			td.style.color = clr;
			td.style.padding = "3px";
			if (cnt%7 == 1)
			{
				tr = createElement('tr');
				var weekTD = createElement('td');
				weekTD.style.borderRight = "1px solid #000";
				weekTD.style.color = week_clr;
				if(thisWeek == curWeek)
					weekTD.style.fontWeight = "bold";
				weekTD.appendChild(document.createTextNode(curWeek));
				if(this.weekSelect && dayEnable)
				{
					weekTD.className += 'cal_week_link';
					weekTD.title = day;
					Event.add(tr, "click", function(e) { ths.return_date(this.children[0].title) });
					Event.add(tr, "mouseover", function(e) { 
															this.className = 'cal_week_link_over';
															this.children[0].className = this.children[0].className.replace(/cal_week_link/, 'cal_week_link_over');
															});
					Event.add(tr, "mouseout", function(e) { 
															this.className = this.className.replace(/cal_week_link_over/, '');
															this.children[0].className = this.children[0].className.replace(/cal_week_link_over/, 'cal_week_link');
															});
				}
				tr.appendChild(weekTD);
				tBody.appendChild(tr);
				
				curWeek++;
				week_clr = "";
			}
			tr.appendChild(td);
		}
		tbl.appendChild(tBody);
		/*var resultDiv = createElement('div');
		resultDiv.appendChild(tbl)*/
		this.animate.init(getElem(this.name).children[1], tbl, direction);
	}
	//*************************************
	CalendarCLS.prototype.loadMonth = function(month, year, direction)
	{
		if (!direction)
			direction = "top";
		var myDate = new Date();
		if (!month && month != 0)
		{
			if (this.defaultVal)
				myDate.setTime(this.defaultVal);
			month = myDate.getMonth();
		}
		if (!year)
		{
			if (this.defaultVal)
				myDate.setTime(this.defaultVal);
			year = myDate.getFullYear();
		}
		myDate.setFullYear(year, month, 1);
		month = myDate.getMonth();
		year = myDate.getFullYear();
		
		var ths = this;
		
		var leftMonth = createElement('span');
		leftMonth.className = "cal_std_link";
		leftMonth.title = month;
		leftMonth.appendChild(document.createTextNode("\<"));
		Event.add(leftMonth, "click", function(e) { ths.loadMonth(this.title - 1, year, "left"); });
		
		var rightMonth = createElement('span');
		rightMonth.className = "cal_std_link";
		rightMonth.title = month;
		rightMonth.appendChild(document.createTextNode("\>"));
		Event.add(rightMonth, "click", function(e) { ths.loadMonth(parseInt(this.title) + 1, year, "right"); });
		
		var yearLink = createElement('span');
		yearLink.className = "cal_std_link";
		yearLink.appendChild(document.createTextNode(month2text(month) + " " + year));
		Event.add(yearLink, "click", function(e) { ths.loadYear(year); });
		
		this.topContainer = getElem(this.name).children[0];
		//this.mainContainer = getElem(this.name).children[1];
		
		this.topContainer.innerHTML = "";
		this.topContainer.appendChild(leftMonth);
		
		this.topContainer.appendChild(document.createTextNode(" "));
		this.topContainer.appendChild(yearLink);
		this.topContainer.appendChild(document.createTextNode(" "));
		this.topContainer.appendChild(rightMonth);
		this.loadDays(month, year, direction);
	}
	//*************************************
	/*CalendarCLS.prototype.buildLink = function(text, val, clr)
	{
		var link = createElement('span');
		link.style.color = clr;
		link.appendChild(document.createTextNode(text));
		link.className = 'cal_link';
		
		var ths = this;
		
		Event.add(link, "click", function(e) { ths.return_date(val) });
		Event.add(link, "mouseover", function(e) { this.className = 'cal_link_over' });
		Event.add(link, "mouseout", function(e) { this.className = 'cal_link' });
		return link;
	}*/
	//*************************************
	CalendarCLS.prototype.return_date = function(val)
	{
		var myDate=new Date();
		myDate.setTime(val);
		if(this.weekSelect)
		{	
			if (this.target)
			{
				this.target.innerHTML = myDate.getUTCDate() + " " + month_padej(month2text(myDate.getUTCMonth())) + " " + myDate.getUTCFullYear();
				myDate.setTime(parseInt(val) + 6*24*3600*1000);
				this.target.innerHTML += " - " + myDate.getUTCDate() + " " + month_padej(month2text(myDate.getUTCMonth())) + " " + myDate.getUTCFullYear();
			}
		}
		else
		{
			if (this.target)
				this.target.innerHTML = myDate.getUTCDate() + " " + month_padej(month2text(myDate.getUTCMonth())) + " " + myDate.getUTCFullYear();
		}
		this.curDate = val;
		this.curentValueTarget.value = this.curDate/1000 - 3600*(this.timeOffsetGMT);
		this.parentWin.close();
	}
	//*************************************
	CalendarCLS.prototype.loadMonthCell = function(_year, direction)
	{
		var myDate=new Date();
		var year = _year;
		if (!_year)
			year = myDate.getFullYear();
		else
			year = _year;
		if (year == myDate.getFullYear())
			month = myDate.getMonth();
		else
			month = -1;
		var tbl = createElement('table');
		tbl.style.width = this.width + "px";
		tbl.style.height = (this.height - 20) + "px";
		tbl.style.textAling = "center";
		var tBody = createElement('tbody');
		var tr = td = null;
		for (var i = 0; i < 12; i++)
		{
			if (i % 4 == 0)
			{
				tr = createElement('tr');
				tBody.appendChild(tr);
			}
			td = createElement('td');
			td.className = "cal_std_link";
			td.style.textAling = "center";
			td.title = i;
			td.appendChild(document.createTextNode(month2text(i, true)));
			
			var ths = this;
			
			Event.add(td, "click", function(e) { ths.loadMonth(this.title, year); });
			if (i == month)
				td.style.fontWeight = "bold";
			tr.appendChild(td);
		}
		tbl.appendChild(tBody);
		this.animate.init(getElem(this.name).children[1], tbl, direction);
	}
	//*************************************
	CalendarCLS.prototype.loadYear = function(year, direction)
	{
		var myDate=new Date();
		if (!year)
			year = myDate.getFullYear();
			
		var leftYear = createElement('span');
		leftYear.className = "cal_std_link";
		leftYear.appendChild(document.createTextNode("\<"));
		
		var ths = this;
		
		Event.add(leftYear, "click", function(e) { ths.loadYear(year - 1, "left"); });
		
		var rightYear = createElement('span');
		rightYear.className = "cal_std_link";
		rightYear.appendChild(document.createTextNode("\>"));
		Event.add(rightYear, "click", function(e) { ths.loadYear(year + 1, "right"); });
		
		this.topContainer.innerHTML = "";
		this.topContainer.appendChild(leftYear);
		this.topContainer.appendChild(document.createTextNode(" " + year + " "));
		this.topContainer.appendChild(rightYear);
		this.loadMonthCell(year, direction);
	}
	//*************************************
	CalendarCLS.prototype.getPeriod = function(minDate, maxDate)
	{
		var minDay = 0;
		var maxDay = 0;
		if (this.maxDate >= minDate && this.maxDate <= maxDate && this.minDate <= minDate)
		{
			minDay = minDate;
			maxDay = this.maxDate;
		}
		else
		{
			if (this.minDate >= minDate && this.minDate <= maxDate && this.maxDate >= maxDate)
			{
				minDay = this.minDate;
				maxDay = maxDate;
			}
			else
			{
				if (this.minDate >= minDate && this.maxDate <= maxDate)
				{
					minDay = this.minDate;
					maxDay = this.maxDate;
				}
				else
				{
					if (this.minDate <= minDate && this.maxDate >= maxDate)
					{
						minDay = minDate;
						maxDay = maxDate;
					}
				}
			}
		}
		myDate = new Date();
		if (minDay)
		{
			myDate.setTime(minDay);
			minDay = myDate.getUTCDate();
		}
		if (maxDay)
		{
			myDate.setTime(maxDay);
			maxDay = myDate.getUTCDate();
		}
		return {minDay : minDay, maxDay : maxDay};
	}
	//*************************************
	function month2text(month, is_short)
	{
		var result;
		switch (month)
		{
			case 0: result = "Январь"; break;
			case 1: result = "Февраль"; break;
			case 2: result = "Март"; break;
			case 3: result = "Апрель"; break;
			case 4: result = "Май"; break;
			case 5: result = "Июнь"; break;
			case 6: result = "Июль"; break;
			case 7: result = "Август"; break;
			case 8: result = "Сентябрь"; break;
			case 9: result = "Октябрь"; break;
			case 10: result = "Ноябрь"; break;
			case 11: result = "Декабрь"; break;
			default: result = "Январь"; break;
		}
		if (is_short)
			return result.substr(0, 3);
		else
			return result;
	}
	//*************************************
	function month_padej(month)
	{
		if (month.substr(month.length - 1, 1) == "т")
			return month + "а";
		else
			return month.substr(0, month.length - 1) + "я";
	}
	//*************************************
	function weekdays2text(day, is_short)
	{
		if (!is_short)
		{
			switch (day)
			{
				case 1: result = "Понедельник"; break;
				case 2: result = "Вторник"; break;
				case 3: result = "Среда"; break;
				case 4: result = "Четверг"; break;
				case 5: result = "Пятница"; break;
				case 6: result = "Суббота"; break;
				case 7: result = "Воскресение"; break;
				case 0: result = "Воскресение"; break;
				default: result = "Понедельник"; break;
			}
		}
		{
			switch (day)
			{
				case 1: result = "Пн"; break;
				case 2: result = "Вт"; break;
				case 3: result = "Ср"; break;
				case 4: result = "Чт"; break;
				case 5: result = "Пт"; break;
				case 6: result = "Сб"; break;
				case 7: result = "Вс"; break;
				case 0: result = "Вс"; break;
				default: result = "Пн"; break;
			}
		}
		return result;
	}
	//*************************************
	function day_in_month(month, year)
	{
		if (month < 0)
		{
			month = 12 + month;
			year--;
		}
		var myDate=new Date();
		myDate.setFullYear(year, month + 1, 0);
		return myDate.getDate();
	}
	//*************************************
	function summerTime()
	{
		var winterDate = new Date(2011,0,11);
		var nowDate = new Date();
		return -(winterDate.getTimezoneOffset() - nowDate.getTimezoneOffset())/60;
	}
	//************************************
	function timeOffset()
	{
		var nowDate = new Date();
		return -nowDate.getTimezoneOffset()/60;
	}
