/* 
В форме можно создавать несколько объектов календаря.

Объекты создаются так:
var calendarInput=new InitCalendarInput(document);
После создания объект автоматически добавляется в глобальный массив объектов calendarsInput и ему 
присваивается очередной индекс начиная с 0 (см.поле объекта this.index).
SELECT-ам объектов присваиваются имена: определенный префикс + уникальный индекс объекта,  например ci_year0.
Обработчику событий onchange передается только индекс текущего объекта, сами объекты
берутся обработчиком из глобального массива calendarsInput.

В объекте есть метод GetDateTimeString(aDateTimeDelimiter), который отдает выбранные дату-время в
строковом вормате гггг.дд.мм чч:мм:сс, разделитель между датой и временем: по умолчанию пробел,
а если разделитель задан в аргументе метода (строка), то заданный разделитель.

*/

var calendarsInput = new Array(0); // Массив календарей.


// ---------------------



function InitCalendarInput(doc)
{ // конструктор объектов календаря. Созданные объекты автоматически
  // добавляются в глобальный массив calendarsInput.

  this.index=calendarsInput.length; // начинается с 0

  this.dt = new Date(); // текущая дата
  this.months = new Array('январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 
		'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь');  

  this.maxDay=31; // сначала
  this.minYear=1900;
  this.maxYear=this.dt.getFullYear()+1;  

  this.drawn=false; // пока
  this.doc=doc; // сохранить здесь ссылку на document

  // здесь будут сохранены ссылки на тэги (результат вызова doc.getElementById(...)), 
  // для уменьшения кол-ва операций в методах
  this.o_year=null;
  this.o_month=null;
  this.o_day=null;
  this.o_hour=null;
  this.o_minute=null;
  this.o_second=null;

  // и добавить себя в массив календарей
  calendarsInput.push(this);

  // отладка
  //alert(calendarsInput.length);
  //alert(this.index);


  this.DrawCalendarInput=function(aMinYear, aMaxYear, aHideYear, aHideMonth, 
					    aHideDay, aHideHour, aHideMinute, aHideSecond
					   )
	{// Полностью нарисовать тэги <SELECT> </SELECT> для года-месяца-дня-часа-минуты-секунды,
	 // отобразив в их id-ах свой индекс в массиве календарей.


       var minYear=this.minYear;
	 var maxYear=this.maxYear;

       var hideYear=false;
       var hideMonth=false;
	 var hideDay=false;
	 var hideHour=false;
	 var hideMinute=false;
	 var hideSecond=false;
 
       
        if (null==this.doc)
		{alert('Календарь номер: ' + String(this.index) + ' - нулевая ссылка на документ!');
		 return false;
		}

         // разборки с параметрами - их может и не быть
         if (null!=aMinYear)
		minYear=Number(aMinYear);

         if (null!=aMaxYear)
		maxYear=Number(aMaxYear);
				

	   if (minYear>maxYear)
		{alert('Календарь номер: ' + String(this.index) + ' - неверные параметры aMinYear, aMaxYear');
		 return false;
		}
         
         this.minYear=minYear;
	   this.maxYear=maxYear;


	   if (null!=aHideYear)
		hideYear=Boolean(aHideYear);

	   if (null!=aHideMonth)
		hideMonth=Boolean(aHideMonth);

	   if (null!=aHideDay)
		hideDay=Boolean(aHideDay);

	   if (null!=aHideHour)
		hideHour=Boolean(aHideHour);

	   if (null!=aHideMinute)
		hideMinute=Boolean(aHideMinute);

	   if (null!=aHideSecond)
		hideSecond=Boolean(aHideSecond);

          

         // собственно рисовка селектов

         // ----------------
         // год рисуется начиная в обратном порядке c maxYear по minYear - и прицепить к нему onChange, 
	   // чтобы правильно менять кол-во дней месяца this.maxDays         
	   this.doc.writeln('<SELECT title="год" id="ci_year' + String(this.index) + 
			'" name="ci_year' + String(this.index) + 
			'" onchange="return window.YMChanged('+ String(this.index) +');" ' + 
		      (hideYear?'style="visibility:hidden"':'') + ' >\r\n');

	   for (var i=this.maxYear; i>=this.minYear; i--)
		this.doc.writeln('<OPTION value="' + String(i) +'">' + String(i) + '</OPTION>\r\n');

	   this.doc.writeln('</SELECT>\r\n'); 


         // ----------------
         // месяцы --  тоже прицепить onChange, чтобы правильно менять maxDays
	   this.doc.writeln('<SELECT title="месяц" id="ci_month' + String(this.index) + 
		'" name="ci_month' + String(this.index) + 
		'" onchange="return window.YMChanged('+ String(this.index) +');" '+ 
		(hideMonth?'style="visibility:hidden"':'') + ' >\r\n');


	   for (var i=1; i<=12; i++)
		// массив месяцев - от 0 до 11! у меня от 0 до 12, поэтому months[i-1]
		this.doc.writeln('<OPTION value="' + String(i) +'">' + this.months[i-1] + '</OPTION>\r\n'); 
	   this.doc.writeln('</SELECT>\r\n');

         
         // -----------------
	   // дни - от 1 до this.maxDay !!!
	   this.doc.writeln('<SELECT title="день" id="ci_day'  + String(this.index) + 
		'" name="ci_day' + String(this.index) + '" ' + (hideDay?'style="visibility:hidden"':'') + ' >\r\n');

	   for (var i=1; i<=this.maxDay; i++)
		 this.doc.writeln('<OPTION value="' + String(i) +'">' +(i<10?'0':'') + String(i) + '</OPTION>\r\n');
	   this.doc.writeln('</SELECT>&nbsp; &nbsp; \r\n'); // 2 &nbsp; в конце селекта для отделения от времени
	

         // -----------------
         // часы
	   this.doc.writeln('<SELECT title="час" id="ci_hour'  + String(this.index) + 
		'" name="ci_hour' + String(this.index) + '" ' + (hideHour?'style="visibility:hidden"':'') + 
		' >\r\n');

	   for (var i=0; i<=23; i++)
		this.doc.writeln('<OPTION value="' + String(i) +'">' + (i<10?'0':'') + String(i) + '</OPTION>\r\n');
	   this.doc.writeln('</SELECT><b></b>\r\n'); 


         // -----------------
         // минуты
	   this.doc.writeln('<SELECT title="минута" id="ci_minute' + String(this.index) + 
		'" name="ci_minute' + String(this.index) + '" ' + (hideMinute?'style="visibility:hidden"':'') + 
		' >\r\n');

	   for (var i=0; i<=59; i++)
		this.doc.writeln('<OPTION value="' + String(i) +'">' + (i<10?'0':'') + String(i) + '</OPTION>\r\n');
	   this.doc.writeln('</SELECT><b></b>\r\n');

         // -----------------
         // секунды
	   this.doc.writeln('<SELECT title="секунда" id="ci_second' + String(this.index) + 
		'" name="ci_second' + String(this.index) + '" ' + (hideSecond?'style="visibility:hidden"':'') + 
		' >\r\n');

	   for (var i=0; i<=59; i++)
		this.doc.writeln('<OPTION value="'+ String(i) +'">' + (i<10?'0':'') + String(i) + '</OPTION>\r\n');
	   this.doc.writeln('</SELECT>\r\n');	         
               

         // -----------------
         // индикатор, что опции отрисованы и можно вызывать всякие select и проч.
	   this.drawn=true;
	   
         // сохранить объекты в переменных, для облегчения работы
         this.o_year=this.doc.getElementById('ci_year'+String(this.index));
         this.o_month=this.doc.getElementById('ci_month'+String(this.index));
         this.o_day=this.doc.getElementById('ci_day'+String(this.index));
         this.o_hour=this.doc.getElementById('ci_hour'+String(this.index));
         this.o_minute=this.doc.getElementById('ci_minute'+String(this.index));
         this.o_second=this.doc.getElementById('ci_second'+String(this.index));

         // сразу установить кол-во дней на нужное

	   // считаем возможные макс. значения дня месяца СНАЧАЛА ДЛЯ января МАКСиМАЛЬНОГО ГОДА!!!
         // потому что сначала будет выставлена именно эта дата (1 января максимального года).
         // Потом когда будет выставлена реальная дата, будут сделаны нужные пересчеты.

     	   this.maxDay=this.GetDays(this.maxYear, 1); // январь года this.maxYear
         // onchange отрабатывает только при нажатии...
	   window.YMChanged(this.index);

         return true;
	}


   this.DrawCurrentDate=function()
	{if (!this.drawn)
		{alert('Календарь номер: ' + String(this.index) + '- невозможно показать текущую дату, опции не созданы! Вызовите сначала DrawCalendarInput()!');
	       return false;
		}
       
       // устанавливаем на текущую дату
       this.dt=new Date(); // обновление даты
       
	 // теперь выставить все option-ы
       this.o_year.value=String(this.dt.getFullYear());
	 this.o_month.value=String(this.dt.getMonth()+1);
	 this.o_day.value=String(this.dt.getDate());
	 this.o_hour.value=String(this.dt.getHours());
	 this.o_minute.value=String(this.dt.getMinutes());
	 this.o_second.value=String(this.dt.getSeconds());

       // onchange отрабатывает только при нажатии...
	 window.YMChanged(this.index);
	 
       return true;
	}


   this.DrawDate=function(year, month, day, hour, minute, second)
	{if (!this.drawn)
		{alert('Календарь номер: ' + String(this.index) + '- невозможно показать текущую дату, опции не созданы! Вызовите сначала DrawCalendarInput()!');
	       return false;
		}

      // посмотреть значения на предмет вхождения в диапазоны
       var y=Number(year);
       var m=Number(month);
       var d=Number(day);
       var h=Number(hour);
       var mn=Number(minute);
       var s=Number(second);
       
       if (y<this.minYear || y>this.maxYear || m<1 || m>12 || d<1 || d>this.GetDays(y, m)
	     || h<0 || h>23 || mn<0 || mn>59 || s<0 || s>59
	    ) 
	   {alert('Календарь номер: ' + String(this.index) + '- невозможно установить запрошенные дату/время, плохие параметры!');
	    return false;
         }	

	 this.o_year.value=String(y);
	 this.o_month.value=String(m);
	 this.o_day.value=String(d);
	 this.o_hour.value=String(h);
	 this.o_minute.value=String(mn);
	 this.o_second.value=String(s); 
   
       // onchange отрабатывает только при нажатии...
	 window.YMChanged(this.index);
 
       return true; 
	}
   

   /* что-то пока не работает, можно воспользоваться DrawCalendarInput(...)
   this.SetVisibleElement=function(aElementId, is_visible)
	{//спрятать или показать например секунды, или год, или любой из select-ов (Id select-а=aElementId)
       if (null==this.doc || null==aElementId)  
		return;
       //alert('aaa')
  	 this.doc.getElementById(aElementId+String(this.index)).visibility= (is_visible?"visible":"hidden");
	}
   */	

   
   this.GetDays=function(year, month)
	{// макс. кол-во дней в месяцаХ. учитывая високосные годы
       var days=0; 
	 switch (Number(month))
		{case 1: case 3: case 5: case 7: case 8: case 10: case 12:
		    days=31;
		 break;
	       case 2:
			days=(this.IsLeapYear(year)? 29 :28);
	       break;
 		 default:
			days=30;
             break;
		}
	  return days;
	}


   this.IsLeapYear=function(year)
	{if (0!=year%4)
		return false;
       else if (0!=year%100)
		return true;
       else
		return (0==year%400);
	}


   this.GetDateTimeString=function(aDateTimeDelimiter)
	{// отдать дату/время, выбранные в календаре, в формате гггг.мм.дд чч.мм.сс 
	 //(в середине - aDateTimeDelimiter!)
       var delimiter=' '; // по умолчанию - пробел
       if (null!=aDateTimeDelimiter)       
		delimiter=aDateTimeDelimiter;        

	 var s = this.o_year.value+'.'+ 
		   (Number(this.o_month.value)<10?'0':'') + this.o_month.value + '.' +
		   (Number(this.o_day.value)<10?'0':'') + this.o_day.value + delimiter +
		   (Number(this.o_hour.value)<10?'0':'') + this.o_hour.value + ':' +
	  	   (Number(this.o_minute.value)<10?'0':'') + this.o_minute.value + ':' +
		   (Number(this.o_second.value)<10?'0':'') + this.o_second.value 
		;
       return s;
	}


} // конец InitCalendarInput()


// -------------------------------------

YMChanged=function(index) // индекс в массиве календарей 
{// обработчик onchange для select-ов года и месяца, чтобы правильно выдавать кол-во дней в месяце.
// Это сделано в window, т.к. конкретный селект не может передать текущий объект calendarInput 
// в свой обработчик onchange


var ci_object=null;

 if (0>index || index>=calendarInput.length) 
	{alert('YMChanged: неверный индекс массива календарей: ' + String(index) +' !');
	 return false;
	}

 ci_object=calendarsInput[index];


 if (null==ci_object)
	{alert('YMChanged: Неверный объект-календарь с индексом: ' + String(this.index) );
	 return false;
	}

 if (null==ci_object.doc || !ci_object.drawn)
   {alert('YMChanged: невозможно показать дни месяца, не созданы опции для календаря номер '+ String(index) +'! Вызовите сначала DrawCalendarInput()!');
    return false;
   }        

 //alert('called');

 // вычислить новое значение maxDay в соответствии с изменениями
 ci_object.maxDay=ci_object.GetDays(Number(ci_object.o_year.value), Number(ci_object.o_month.value));

/*
 alert('maxDay=' + ci_object.maxDay + ' year= ' + 
	 ci_object.o_year.value + '  month=' + ci_object.o_month.value 
	);
*/     
 // устанавливаем элементы option для ci_day от 1 до maxDay, остальные будут уничтожены или добавлены

 var opt=ci_object.o_day.options;

 if (opt.length==ci_object.maxDay)
	return true; // ничего не менять
 else if (opt.length<ci_object.maxDay)
	{for (var i=opt.length; i<ci_object.maxDay; i++)
	   opt.add(new Option(i+1, (i+1<10?'0':'')+String(i+1)));//i+1,т.к. нумерация дней c 1, а массива с 0.
	}
 else if (opt.length>ci_object.maxDay)
       opt.length=ci_object.maxDay;	

 return true;
}



