//v.2.5 build 090904

/*
Copyright DHTMLX LTD. http://www.dhtmlx.com
You allowed to use this component or parts of it under GPL terms
To use it on other terms or get Professional edition of the component please contact us at sales@dhtmlx.com
*/
/**
*  @desc:  dhtmlxDblCalendarObject constructor (double dhtmlxCalendarObject)
*  @param: {String} id - attribute of HTML Element
*  @param: isAutoDraw - is auto draw calendar
*  @param: options - an associate array of options
*  @type: public
*  @topic: 0
*/
function dhtmlxDblCalendarObject(contId, isAutoDraw, options){
  this.scriptName = 'dhtmlxcalendar.js';
  this.entObj = document.createElement("DIV");
  this.winHeader = null
  this.style = "dhtmlxdblcalendar";
  this.uid = 'sc&dblCal'+Math.round(1000000*Math.random());
  this.numLoaded = 2;
  this.options = {
    isWinHeader: false,
    headerText: 'dhtmlxDblCalendarObject',
    headerButtons: '',  // T - set date pointer on today,
              // M - Minimize/Normalize window,
              // X - hide window.
              
    isWinDrag: false,
    msgClose:   "Close",
    msgMinimize: "Minimize",
    msgToday:   "Today",
    msgClear:   "Clear"
  }
  
  if (options)
    for (x in options) 
      this.options[x] = options[x];
      
  this.entBox = document.createElement("TABLE");
  this.entBox.cellPadding = "0px";
  this.entBox.cellSpacing = "0px";
  this.entBox.className = this.style;
  this.entObj.appendChild(this.entBox);
 
  var entRow = this.entBox.insertRow(0);
  var calLeft = entRow.insertCell(0);
    calLeft.style.paddingRight = '2px';
  var calRight = entRow.insertCell(1);

  this.leftCalendar = new dhtmlxCalendarObject(calLeft, false, this.options);
  this.leftCalendar._dblC = this;
  this.leftCalendar.setOnClickHandler(this.doOnCLeftClick);

  this.rightCalendar = new dhtmlxCalendarObject(calRight, false, this.options);
  this.rightCalendar._dblC = this;
  this.rightCalendar.setOnClickHandler(this.doOnCRightClick);
 
  this.doOnClick = null;
  this.onLanguageLoaded = null;
  this.getPosition = this.leftCalendar.getPosition;
  this.startDrag = this.leftCalendar.startDrag;
  this.stopDrag = this.leftCalendar.stopDrag;
  this.onDrag = this.leftCalendar.onDrag;
  this.drawHeader = this.leftCalendar.drawHeader;
 
  dhtmlxEventable(this);

  var self = this;
  
  if (typeof(contId) != 'string') this.con = contId;
  else this.con = document.getElementById(contId);  
  
  if (isAutoDraw)
    this.draw ();
}
dhtmlXDblCalendarObject = dhtmlxDblCalendarObject;
/**
*  @desc:  set header in calendar
*  @param: isVisible - is header visible
*  @param: isDrag - can calendar be dragged
*  @param: isDrag - can calendar be dragged
*  @param: btnsOpt - the header buttons string
*  @type: public
*  @topic: 2
*/
dhtmlxDblCalendarObject.prototype.setHeader = function(isVisible, isDrag, btnsOpt){
    this.leftCalendar.options.isWinHeader = this.options.isWinHeader = isVisible;
    this.leftCalendar.options.isWinDrag = this.options.isWinDrag = isDrag;
    if (btnsOpt)
      this.options.headerButtons = this.leftCalendar.options.headerButtons = btnsOpt;
    if   (this.isAutoDraw)
      this.drawHeader();
}

/**
*  @desc:  set years range
*  @param: minYear - low bound
*  @param: maxYear - upper bound
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.setYearsRange = function(minYear, maxYear){
  var cs = [this.leftCalendar, this.rightCalendar];
  for (var ind=0; ind < cs.length; ind++) {
    cs[ind].options.yearsRange = [parseInt(minYear), parseInt(maxYear)];
    cs[ind].allYears = [];
    for (var i=minYear; i <= maxYear; i++)
      cs[ind].allYears.push(i);
  }
}

/**
*  @desc:  show calendar 
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.show = function(){
  this.parent.style.display = 'block';
}

/**
*  @desc:  hide calendar
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.hide = function(){
  this.parent.style.display = 'none';
}

/**
*  @desc:  create structure of calendar
*  @type: private
*  @topic: 0
*/
dhtmlxDblCalendarObject.prototype.createStructure = function(){
  if (this.options.isWinHeader) { // CREATING WinHeader
    var headerRow = this.entBox.insertRow(0).insertCell(0);
    headerRow.colSpan = 2;
    headerRow.align = 'right';
    this.winHeader = document.createElement('DIV');
    headerRow.appendChild(this.winHeader);
  }
  
  this.setParent(this.con);
}
/**
*  @desc:  draw calendar
*  @type: public
*  @topic: 2
*/
dhtmlxDblCalendarObject.prototype.draw = function(){
  if (!this.parent) this.createStructure();

  this.drawHeader();
  this.leftCalendar.draw();
  this.rightCalendar.draw();
  this.isAutoDraw = true;
}

/**
*  @desc:  Set new language interface for calendar
*  @param: lang - language (ex: en-us|ru|by)
*  @param: userCBfunction - function called after language loaded
*  @type: public
*  @topic: 0
*/
dhtmlxDblCalendarObject.prototype.loadUserLanguage = function(lang, userCBfunction){
  this.numLoaded = 0;
  if (userCBfunction)
    this.onLanguageLoaded = userCBfunction;
  this.leftCalendar.loadUserLanguage(lang, this.languageLoaded);
  this.rightCalendar.loadUserLanguage(lang, this.languageLoaded);
}



dhtmlxDblCalendarObject.prototype.languageLoaded = function(status){
  var self = this._dblC;
  self.numLoaded ++;
  if (self.numLoaded == 2) {
    for (param in this.options) 
      self.options[param] = this.options[param];
    if (this.isAutoDraw)
      self.drawHeader();
    if (self.onLanguageLoaded)
      self.onLanguageLoaded(status);
  }
}

/**
*  @desc:  set parent node  for calendar
*  @param: newParent - {Object} parent node (container) for calendar
*  @type: public
*  @topic: 0
*/
dhtmlxDblCalendarObject.prototype.setParent = function(newParent){
  if (newParent) {
    this.parent = newParent;
    this.parent.style.display = 'block';
    this.parent.appendChild(this.entObj);
  }
}

/**
*  @desc:  set onClick event handler
*  @param: func - function called after onClick event occured
*  @type: public
*  @topic: 5
*/
dhtmlxDblCalendarObject.prototype.setOnClickHandler = function(func){
  this.doOnClick = func;
}

/**
*  @desc:   doOnCLeftClick event for Left Calendar
*  @param:  date - {Data} selected date
*  @result: {Boolean}
*  @type: private
*  @topic: 5
*/
dhtmlxDblCalendarObject.prototype.doOnCLeftClick = function(date){
  date = new Date (date)
  this._dblC.rightCalendar.setSensitive(date, null);
  if (this._dblC.doOnClick)
    this._dblC.doOnClick(date, this, "left");
  return true;
}

/**
*  @desc:   doOnCLeftClick event for right Calendar
*  @param:  date - {Data} selected date
*  @result: {Boolean}
*  @type: private
*  @topic: 5
*/
dhtmlxDblCalendarObject.prototype.doOnCRightClick = function(date){
  this._dblC.leftCalendar.setSensitive(null, date);
  if (this._dblC.doOnClick)
    this._dblC.doOnClick(date, this, "right");
  return true;
}

/**
*  @desc:  set sensitive range for calendar
*  @param: {Function} function handler
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.setSensitive = function(){
  this.rightCalendar.setSensitive(null, this.leftCalendar.date[0]);
  this.leftCalendar.setSensitive(this.rightCalendar.date[0], null);
}
/**
*  @desc:  minimize calendar
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.minimize = function(){
  if (!this.winHeader) return;
  var tr = this.winHeader.parentNode.parentNode.nextSibling;
  tr.parentNode.parentNode.style.width = parseInt(tr.parentNode.parentNode.offsetWidth) + 'px';
  if (tr)
    tr.style.display = (tr.style.display == 'none')? 'block': 'none';
}
/**
*  @desc: select date in calendar
*  @param: dateFrom - {Data} date for left calendar
*  @param: dateTo - {Data} date for right calendar
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.setDate = function(dateFrom,dateTo){
  this.leftCalendar.setDate(dateFrom);
  this.rightCalendar.setDate(dateTo);
  this.leftCalendar.setSensitive(null, this.rightCalendar.date[0]);
  this.rightCalendar.setSensitive(this.leftCalendar.date[0], null);
}

/**
*  @desc: set date format for input/output
*  @param: format - format of date to use. see single calendar method description for details
*  @type: public
*  @topic: 1
*/
dhtmlxDblCalendarObject.prototype.setDateFormat = function(format){
  this.leftCalendar.setDateFormat(format);
  this.rightCalendar.setDateFormat(format);
}

/**
*  @desc: get visibility state
*  @type: public
*  @topic: 4
*  @return: state of visibility (false - unvisible, true - visible)
*/
dhtmlxDblCalendarObject.prototype.isVisible = function(){
  return (this.parent.style.display == 'block'?true:false);
}

/**
*  @desc: set holidays dates
*  @type: public
*  @topic: 4
*/
dhtmlxDblCalendarObject.prototype.setHolidays = function(dates){
  this.leftCalendar.setHolidays(dates);
  this.rightCalendar.setHolidays(dates);
}

/*_TOPICS_               
@0:Initialization
@1:Format control
@2:Add/delete
@4:Appearence control
@5:Event Handlers
@6:Selection control
*/



/***
*  @desc:  dhtmlxCalendarObject constructor
*  @param: {String} base - object/object id, init object
*  @param: isAutoDraw - is auto draw calendar
*  @param: options - an associate array of options
*  @type: public
*  @topic: 0
*/

function dhtmlxCalendarObject (base, isAutoDraw, options){
  // init by object
  
  if (typeof(base) == "object" && !base.tagName)
  {
    options = {};
    for (i in base)
      options [i] = base [i];
  }
   
	this.isAutoDraw = base.autoDraw || isAutoDraw || false;
	this.contId = base.parent || base;
	this.scriptName = 'dhtmlxcalendar.js';
	this.date = [this.cutTime(new Date())];
	this.selDate = [this.cutTime(new Date())];
	this.curDate = this.cutTime(new Date());
	this.entObj = document.createElement("DIV");
	this.monthPan = document.createElement("TABLE");
	this.dlabelPan = document.createElement("TABLE");
	this.daysPan = document.createElement("TABLE");
//	this.timePan = document.createElement("TABLE");
	this.parent = null;
	this.style = "dhtmlxcalendar";
	this.skinName = dhtmlx.skin || "";
	this.doOnClick = null;
	this.sensitiveFrom = null;
	this.sensitiveTo = null;
	this.insensitiveDates = null;
	this.activeCell = null;
	this.hotCell = null;
	this.winHeader = null
	this.onLanguageLoaded = null;
	this.dragging = false;
	this.minimized = false;
	this.uid = 'sc&Cal'+Math.round(1000000*Math.random());
	this.holidays = null;
  this.time = false;
  this.daysCells = {};
  this.weekCells = {};
  this.con = [];
  this.conInd = [];
  this.activeCon = null;
  this.activeConInd = 0;
  this.userPosition = false;
  this.useIframe = true;
  this._c = this;
  dhtmlxEventable(this);
                 
	this.options = {
		btnPrev:	"&laquo;",
		btnBgPrev:	null,
		btnNext:	"&raquo;",
		btnBgNext:	null,
		yearsRange:	[1900, 2100],
		
		isMonthEditable: false,
		isYearEditable: false,
		
		isWinHeader: false,
    headerText : 'Calendar header',
		headerButtons: 'TMX',	// T - set date pointer on today,
								// M - Minimize/Normalize window,
								// X - hide window.
		isWinDrag: true
	}                  
	defLeng = {
		langname:	'en-us',
		dateformat:	'%d-%m-%y',
		monthesFNames:	["Janeiro", "Fevereiro", "Marco", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
		monthesSNames:	["Jan", "Fev", "Mai", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
		daysFNames:	["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sabado"],
		daysSNames:	["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa"],
		weekend:	[0, 6],
		weekstart:	0,
		msgClose:	 "Fechar",
		msgMinimize: "Minimizar",
		msgToday:	 "Hoje",
		msgClear:	 "Limpar"
	}
	if (!window.dhtmlxCalendarLangModules) window.dhtmlxCalendarLangModules = {};
	window.dhtmlxCalendarLangModules['en-us'] = defLeng;
    
	if (window.dhtmlxCalendarObjects) window.dhtmlxCalendarObjects[window.dhtmlxCalendarObjects.length] = this;
	else window.dhtmlxCalendarObjects = [this];

  dhtmlxEvent(document.body,"click",function(ev){
    for (cal in window.dhtmlxCalendarObjects)
    {
      var wCal = window.dhtmlxCalendarObjects[cal];
      if (wCal.con[0].nodeName == 'INPUT')
        wCal.hide ()
    }
  });
    
	for (lg in defLeng) 
		this.options[lg] = defLeng[lg];

	if (options)
		for (param in options) 
			this.options[param] = options[param];
                                       
	// Load options for detected language settings
  this.loadUserLanguage();
	//duplicate (so need)
	if (options)
		for (param in options) 
			this.options[param] = options[param];
	                                      
	this.allYears = Array();
	with (this.options)
		for (var i=yearsRange[0]; i <= yearsRange[1]; i++)
			this.allYears.push(i);
  
	if(isAutoDraw !== false) this.draw(options);
	return this;
}
dhtmlXCalendarObject = dhtmlxCalendarObject;

dhtmlxCalendarObject.prototype={
  /**
  *  @desc:  create structure of calendar
  *  @type: private
  *  @topic: 0
  */
  createStructure:function(){
	  // Create Structure
	  var self = this;
	  if (!this.entObj.className)
		  this.setSkin (this.skinName);

	  this.entObj.style.position = "relative";
	  if (this.options.isWinHeader) {
		  this.winHeader = document.createElement('DIV');
		  this.entObj.appendChild(this.winHeader);
	  }

	  this.entBox = document.createElement("TABLE");
	  this.entBox.className = "entbox";
	  with (this.entBox) {
		  cellPadding = "0px";
		  cellSpacing = "0px";
		  width = '100%';
	  }
	   
	  this.entObj.appendChild(this.entBox);
	  var monthBox = this.entBox.insertRow(0).insertCell(0);
	  with (this.monthPan) {
		  cellPadding = "0px";
		  cellSpacing = "0px";
		  width = '100%';
		  align = 'center';
	  }
	  this.monthPan.className = "dxcalmonth";
	  monthBox.appendChild(this.monthPan);

	  var dlabelBox = this.entBox.insertRow(1).insertCell(0);
	  dlabelBox.appendChild(this.dlabelPan);
	  with (this.dlabelPan) {
		  cellPadding = "0px";
		  cellSpacing = "0px";
		  width = '100%';
		  align = 'center';
	  }
	  this.dlabelPan.className = "dxcaldlabel";
	   
	  var daysBox = this.entBox.insertRow(2).insertCell(0);
	  daysBox.appendChild(this.daysPan);
	  with (this.daysPan) {
		  cellPadding = "1px";
		  cellSpacing = "0px";
		  width = '100%';
		  align = 'center';
	  }
	  if(_isIE || _isKHTML)
		  this.daysPan.className = "dxcaldays_ie";
	  else
		  this.daysPan.className = "dxcaldays";
	  this.daysPan.onmousemove = function (e) {
		  self.doHotKeys(e);
	  }
	  this.daysPan.onmouseout = function () {
		  self.endHotKeys();
	  }
	       
  //	var timeBox = this.entBox.insertRow(2).insertCell(0);
  //	timeBox.appendChild(this.timePan);

    
    
	  if (typeof(this.contId) != 'string') {
      if (!this.contId.nodeName)
      {
        for (i in this.contId) {
          this.con [i] = document.getElementById(this.contId [i]);
          this.selDate [i] = this.cutTime(new Date());
          this.conInd [this.contId [i]] = i;
        }
      }
      else {
        this.con [0] = this.contId;
        this.conInd [this.contId.id] = 0;
      }
    }
    else 
    {
      this.con [0] = document.getElementById(this.contId);
      this.conInd [this.contId] = 0;
    }
                     
    this.activeCon =  this.con[0];
         
	  if (this.con[0].nodeName == 'INPUT') {
		  var div = document.createElement('DIV');
		  with (div.style) {
			  position = 'absolute';
			  display = 'none';
			  zIndex = "99";
		  }    
		  this.setParent(div);
		  //this.con.parentNode.insertBefore(div, this.con);
      
      // changed to document.body, because when calendar attached to some window it's invisible
		  document.body.appendChild(div);
		  conOnclick = function (e) {
		  	  if (self.isVisible())
		  		  self.hide()
		  	  else {
            if (self.activeCon != self.con[self._activeConInd (this.id)]) {
              self.activeCon = self.con[self.activeConInd];
              var val = self.activeCon.value.split (" ");
              if (self.time)    
                self.setFormatedTime(null, val [1]);
              self.setDate(self.getFormatedDate(val [0]));
            }
            self.show(this.id);
				  }
          if (this.id != self.activeCon.id)
            self.show(this.id);
          e = (e||event);
          (e||event).cancelBubble=true;
		  }
       
		  this.doOnClick = function (date) {
			  self.hide();
			  self.activeCon.focus();//b.80131
			  return true;
		  }
		  //added in b.80131 to turn on some key events
		  conOnkeydown = function(e){
			  if((e||window.event).keyCode==27)
				  self.hide();
			  else if((e||window.event).keyCode==13)
				  self.show();
		  }
      
      for (i in this.con) {
        this.con [i].onclick = conOnclick;
        this.con [i].onkeydown = conOnkeydown;
      }

	  } else this.setParent(this.con [0]);

	  if(_isIE && this.useIframe){//add iframe under calendard in IE (IE 6 issue with select box fix)
		  if(this.parent.style.zIndex==0){
			  this.parent.style.zIndex = 100;
		  }
      
		  if(this.ifr == undefined && this._dblC == undefined){
			  this.ifr = document.createElement("IFRAME");
			  this.ifr.style.position = "absolute";
			  this.ifr.style.zIndex = 1;
			  this.ifr.frameBorder = "no";
  //		this.ifr.src = window.dhx_globalImgPath+"/blank.html"
		    this.ifr.style.top =  this.entObj.offsetTop + 'px';
			  this.ifr.style.left = this.entObj.offsetLeft + 'px'; //<---- тут умирает наверное дела с entObj
        this.ifr.scrolling = 'no';
			  this.ifr.style.display = this.parent.style.display;
			  this.ifr.className = this.style + (this.skinName?'_':"") + this.skinName + "_ifr";
			  this.parent.appendChild(this.ifr)//document.body.appendChild(this.ifr);
		  }
	  }
    this.entObj.onclick = function (e) {
          e = e||event;
          if (e.stopPropagation) e.stopPropagation();
          else e.cancelBubble = true;
     }
    if (!this.entObj.className)
      this.setSkin (this.skinName);
  },

  /**
  *     @desc: create header
  *     @type: private
  *     @topic: 0  
  */
  drawHeader:function(){
		  if (this._dblC  // exit when calendar is element of duple claendar
		  || !this.options.isWinHeader 
      || !this.winHeader)
        return
		  var self = this;
		  
		  while (this.winHeader.hasChildNodes())
			  this.winHeader.removeChild(this.winHeader.firstChild);
		  
		  this.winHeader.className = 'winHeader';
		  this.winHeader.onselectstart=function(){ return false};

		  this.headerLabel = document.createElement('div');	// WINDOW TITLE
		  this.headerLabel.className = 'winTitle';
		  this.headerLabel.appendChild(document.createTextNode(this.options.headerText));
		  this.headerLabel.setAttribute('title', this.options.headerText);
		  this.winHeader.appendChild(this.headerLabel);
		  if (this.options.isWinDrag) {				// DRAG & DROP
			  this.winHeader.onmousedown = function(e) {
				  self.startDrag(e);
			  }
		  }

		  if (this.options.headerButtons.indexOf('X')>=0) {
			  var btnClose = document.createElement('DIV'); // CLOSE BUTTON
			  btnClose.className = 'btn_close';
			  btnClose.setAttribute('title', this.options.msgClose);
        btnClose.onmousedown =function (e) {(e||event).cancelBubble=true;}
			  btnClose.onclick = function (e) {
				  (e||event).cancelBubble=true;
				  self.hide();
			  }
			  this.winHeader.appendChild(btnClose);
		  }					

		  if (this.options.headerButtons.indexOf('M')>=0) {
			  var btnMin = document.createElement('DIV'); // MINIMIZE BUTTON
			  btnMin.className = 'btn_mini';
			  btnMin.setAttribute('title', this.options.msgMinimize);
        btnMin.onmousedown =function (e) {(e||event).cancelBubble=true;}
			  btnMin.onclick = function(e) {
          this.className = this.className == 'btn_mini' ? 'btn_maxi' : 'btn_mini';
				  (e||event).cancelBubble=true;
				  self.minimize();
			  }
			  this.winHeader.appendChild(btnMin);
		  }

		  if (this.options.headerButtons.indexOf('C')>=0) {  
			  var btnClear = document.createElement('DIV');	// TO CLEAN INPUT
			  btnClear.className = 'btn_clear';
			  btnClear.setAttribute('title', this.options.msgClear);
        btnClear.onmousedown =function (e) {(e||event).cancelBubble=true;}
			  btnClear.onclick = function(e) {
          (e||event).cancelBubble=true;
				  self.con.value = "";
				  self.hide();				
			  }
			  this.winHeader.appendChild(btnClear);
		  }
		  
		  if (this.options.headerButtons.indexOf('T')>=0) {
			  var btnToday = document.createElement('DIV');	// GOTO TODAY
			  btnToday.className = 'btn_today';
			  btnToday.setAttribute('title', this.options.msgToday);
        btnToday.onmousedown =function (e) {(e||event).cancelBubble=true;}
			  btnToday.onclick = function(e) {
          (e||event).cancelBubble=true;
				  self.setDate(new Date());
          /*this.callEvent("onClick", [new Date()]);*/
			  }
			  this.winHeader.appendChild(btnToday);
		  }
  },
  
  /**
  *     @desc: create month row
  *     @type: private
  *     @topic: 0  
  */
  drawMonth:function(){
	  var self = this;
	  if (this.monthPan.hasChildNodes())  
		  this.monthPan.removeChild(this.monthPan.firstChild);
	  var row = this.monthPan.insertRow(0);

	  var cArLeft = row.insertCell(0);
	  var cContent = row.insertCell(1);
	  var cArRight = row.insertCell(2);
	  
	  cArLeft.align = "left";
	  cArLeft.className = 'month_btn_left';
	  var btnLabel = document.createElement("div");
	  btnLabel.innerHTML = " ";
	  cArLeft.appendChild(btnLabel);
	  cArLeft.onclick = function(){ self.prevMonth() }
    cArLeft.onselectstart = function () {return false}
	  
	  cArRight.align = "right";
	  cArRight.className = 'month_btn_right';
	  var btnLabel = document.createElement("div");
	  btnLabel.innerHTML = " ";
	  cArRight.appendChild(btnLabel);
	  cArRight.onclick = function(){ self.nextMonth() }
    cArRight.onselectstart = function () {return false}
	  
	  cContent.align = 'center';
	  var mHeader = document.createElement("TABLE");
	  with (mHeader) {
		  cellPadding = "0px";
		  cellSpacing = "0px";
		  align = "center";
	  }
	  var mRow = mHeader.insertRow(0);
	  var cMonth = mRow.insertCell(0);
	  var cComma = mRow.insertCell(1);
	  var cYear = mRow.insertCell(2);
	  
	  cContent.appendChild(mHeader);
	  var date = this.date[this._activeConInd()];
    //console.log(this.selDate);
    //console.log(this._activeConInd())
    
	  this.planeMonth = document.createElement('DIV');
	  this.planeMonth._c = this;
	  this.planeMonth.appendChild(document.createTextNode(this.options.monthesFNames[date.getMonth()]));
	  this.planeMonth.className = 'planeMonth';
	  cMonth.appendChild(this.planeMonth);
	  if (this.options.isMonthEditable) {
		  this.planeMonth.style.cursor = 'pointer';
		  this.editorMonth = new dhtmlxRichSelector({
			  nodeBefore: this.planeMonth,
			  valueList: [0,1,2,3,4,5,6,7,8,9,10,11],
			  titleList: this.options.monthesFNames,
			  activeValue: this.options.monthesFNames[date.getMonth()],
			  onSelect: this.onMonthSelect,
        isAllowUserValue: false
		  });
		  this.editorMonth._c = this;
	  }

	  cComma.appendChild(document.createTextNode(","));
	  cComma.className = 'comma';

	  this.planeYear = document.createElement('DIV');
	  this.planeYear._c = this;
	  this.planeYear.appendChild(document.createTextNode(date.getFullYear()));
	  this.planeYear.className = 'planeYear';
	  cYear.appendChild(this.planeYear);
	  if (this.options.isYearEditable) {
		  this.planeYear.style.cursor = 'pointer';
		  this.editorYear = new dhtmlxRichSelector({
			  nodeBefore: this.planeYear,
			  valueList: this.allYears,
			  titleList: this.allYears,
			  activeValue: date.getFullYear(),
			  onSelect: this.onYearSelect,
			  isOrderedList: true,
			  isNumbersList: true,
			  isAllowUserValue: true
		  });
		  this.editorYear._c = this;
	  }
  },

  /**
  *     @desc: create week days row
  *     @type: private
  *     @topic: 0 
  */
  drawDayLabels:function() {
	  var self = this;
	  if(!this.dlabelPan.hasChildNodes()) 
    {
	    var row = this.dlabelPan.insertRow(-1);
	    row.className = "daynames";
	    for(var i=0; i<7; i++){
		    (this.weekCells [i] = row.insertCell(i)).appendChild(document.createTextNode(this.getDayName(i)))
	    }
    } 
    else 
    {
      for(var i=0; i<7; i++)
        this.weekCells[i].childNodes [0].nodeValue = this.getDayName(i);
    }
  },

  /**
  *     @desc: create days in calendar 
  *     @type: private
  *     @topic: 0 
  */
  drawDays:function() {
	  var self = this;
    /*
	  if(this.daysPan.childNodes.length>0)
		  this.daysPan.removeChild(this.daysPan.childNodes[0]);
    */     
    var row = {}, cell;
    
    if(!this.daysPan.hasChildNodes()) 
    {
      for (var weekNumber=0; weekNumber<6; weekNumber++) 
      {
        row = this.daysPan.insertRow(-1);
        this.daysCells [weekNumber] = {};
        for (var i=0; i<7; i++) 
        {
          (this.daysCells [weekNumber] [i] = row.insertCell(-1)).appendChild(document.createTextNode("")); 
        }
      }
    }
	  
	  
    var date = this.date[this._activeConInd()], tempDate = new Date(date);
    var selectedDate = this.selDate[this.activeConInd].toDateString();
    tempDate.setDate(1);
    var day1 = (tempDate.getDay() - this.options.weekstart) % 7;

    if (day1 <= 0) day1 += 7;
      tempDate.setDate(- day1);
	  tempDate.setDate(tempDate.getDate() + 1);
    if (tempDate.getDate() < tempDate.getDay()) 
	    tempDate.setMonth(tempDate.getMonth() - 1);
    var curDay = null;
	  //set days
	  for (var weekNumber=0; weekNumber<6; weekNumber++) {
		  for (var i=0; i<7; i++) {
        if (curDay == tempDate.getDate())
          tempDate.setDate(tempDate.getDate() + 1);
        curDay = tempDate.getDate();
        
        cell = this.daysCells [weekNumber] [i];
			  cell.setAttribute('id', this.uid+tempDate.getFullYear()+tempDate.getMonth()+tempDate.getDate());
        cell.childNodes [0].nodeValue = tempDate.getDate();
			  cell.thisdate = tempDate.toString();
			  cell.className = "thismonth";
        cell.onclick = null;
        
			  if(tempDate.getMonth()!=date.getMonth())
				  cell.className = "othermonth";
				  
			  if (this.insensitiveDates) {
				  var c = false;
				  for (var j=0; j<this.insensitiveDates.length; j++) {		  	
					  var s = /\.|\-/.exec(this.insensitiveDates[j])
					  if (s)
						  var f = (this.insensitiveDates[j].split (s).length == 2 ? '%m'+s+'%d' : '%Y'+s+'%m'+s+'%d');
					  if (s && this.getFormatedDate(f, tempDate) == this.insensitiveDates[j] || tempDate.getDay () == this.insensitiveDates[j]) {
						  this.addClass(cell, "insensitive");
			        tempDate.setDate(tempDate.getDate() + 1);
   		        c = true;
   		        break;
					  }
				  }
				  if (c) continue;
			  }
				  

			  if (this.sensitiveFrom && this.sensitiveFrom instanceof Array) {
				  var c = true;
				  for (var j=0; j<this.sensitiveFrom.length; j++) {
					  var s = /\.|\-/.exec(this.sensitiveFrom[j]);
					  var f = (this.sensitiveFrom[j].split (s).length == 2 ? '%m'+s+'%d' : '%Y'+s+'%m'+s+'%d');
					  
					  if (this.getFormatedDate(f, tempDate) == this.sensitiveFrom[j])
					    c = false;
				  }
				  if (c) {
					  this.addClass(cell, "insensitive");
		        tempDate.setDate(tempDate.getDate() + 1);					
					  continue;
				  }
			  }
			  
			  if ((this.sensitiveFrom && (tempDate.valueOf() < this.sensitiveFrom.valueOf()))
            || (this.sensitiveTo && (tempDate.valueOf() > this.sensitiveTo.valueOf()))) {
				  this.addClass(cell, "insensitive");
	        tempDate.setDate(tempDate.getDate() + 1);
				  continue;
			  }

			  if (this.isWeekend(i) && tempDate.getMonth()==date.getMonth()) 
				  cell.className = "weekend";
          if (tempDate.toDateString() == this.curDate.toDateString())
				    this.addClass(cell, "current");

			  if (tempDate.toDateString() == selectedDate) {
          //console.log (this.selDate,this.activeCon.id);
				  this.activeCell = cell;
				  this.addClass(cell, "selected");
			  }
						  
			  if (this.holidays)
				  for (var j=0; j<this.holidays.length; j++) {				
					  var s = /\.|\-/.exec(this.holidays[j]);
					  var f = (this.holidays[j].split (s).length == 2 ? '%m'+s+'%d' : '%Y'+s+'%m'+s+'%d');
					  if (this.getFormatedDate(f, tempDate) == this.holidays[j])
						  this.addClass(cell, "holiday");
				  }
            
			  cell.onclick = function(){
          var date = this.thisdate;
          self.setDate (date);
				  if(!self.doOnClick || self.doOnClick(date)){
            self.callEvent("onClick", [date]);
                       /*
                      if (self.activeCell) self.resetClass(self.activeCell);
                      self.addClass(this, "selected");
                      self.activeCell = this;                                 
                      */
				  }
			  }

        tempDate.setDate(tempDate.getDate() + 1);
      }
    }
  },

  /**
  *     @desc: draw calendar 
  *     @type: public
  *     @topic: 2 
  */
  draw:function(){
    if (!this.parent) this.createStructure();
    
	  var self = this;
	  if (this.loadingLanguage){
		  setTimeout(function() {
			  self.draw();
			  return;
		  }, 20);
		  return;
		}
    
	  // Set constructor options
    if (this.winHeader && !this.winHeader.hasChildNodes())
	    this.drawHeader();
	  this.drawMonth();
	  this.drawDayLabels();
	  this.drawDays();
	  this.isAutoDraw = true;
  },

  /**
  *  @desc:  Set new language interface for calendar
  *  @param: lang - language (ex: en-us|ru|by)
  *  @param: userCBfunction - function called after language loaded
  *  @type: public
  *  @topic: 0
  */
  loadUserLanguage:function(language, userCBfunction){ 
	  if (userCBfunction)
		  this.onLanguageLoaded = userCBfunction;
	  // define user (system) language
	  if (!language){
		  language="en-us";
	  }      
	  // mark this object
	  this.loadingLanguage = language;
	  // language not defined       
	  if (!language) {
		  this.loadUserLanguageCallback(false);
		  return;
	  }
	  // break if current Language
	  if (language == this.options.langname) { 
		  this.loadUserLanguageCallback(true);
		  return;
	  }

	  // if language module already exist...
	  var __lm = window.dhtmlxCalendarLangModules;
	  if (__lm[language]) {
		  for (lg in __lm[language])
			  this.options[lg] = __lm[language][lg];
		  this.loadUserLanguageCallback(true);
		  return;
	  }
	  // define language module path
	  var src, path = null;
	  var scripts = document.getElementsByTagName('SCRIPT');
	  for (var i=0; i<scripts.length; i++)
		  if(src = scripts[i].getAttribute('src'))
			  if (src.indexOf(this.scriptName) >= 0) {
				  path = src.substr(0, src.indexOf(this.scriptName));
				  break;
			  }
	  // path to language module file not defined
	  if (path === null) {	
		  this.loadUserLanguageCallback(false);
		  return;
	  }
	  this.options.langname = language;
	  var langPath = path + 'lang/' + language + '.js';
	  // if language module already linked (loading now) ...
	  for (var i=0; i<scripts.length; i++)
		  if(src = scripts[i].getAttribute('src'))
			  if (src == langPath) return;
	  // load language module
	  var script = document.createElement('SCRIPT');
	  script.setAttribute('language', "Java-Script");
	  script.setAttribute('type', "text/javascript");
	  script.setAttribute('src', langPath);
	  document.body.appendChild(script);
  },

  loadUserLanguageCallback:function(status) {
	  this.loadingLanguage = null;
	  if (this.isAutoDraw) this.draw();
	  if (this.onLanguageLoaded && (typeof(this.onLanguageLoaded) == 'function'))
		  this.onLanguageLoaded(status);
  },

  loadLanguageModule:function(langModule) {
	  var __c = window.dhtmlxCalendarObjects;
	  for (var i=0; i<__c.length; i++) {
		  if (__c[i].loadingLanguage == langModule.langname) {
			  for (lg in langModule)
				  __c[i].options[lg] = langModule[lg];
			  __c[i].loadUserLanguageCallback(true);
		  }
	  }
	  window.dhtmlxCalendarLangModules[langModule.langname] = langModule;
  },

  /**
  *  @desc:  show calendar 
  *  @type: public
  *  @topic: 4
  */

  show:function(conId){
    this.activeCon = this.con[this._activeConInd(conId)];
    this.parent.style.display = '';
    this.parent.style.visibility = 'hidden';
	  if (this.activeCon.nodeName == 'INPUT' && !this.userPosition) {
      if( typeof window.innerWidth == 'number' ) {
        docWidth  = window.innerWidth;
        docHeight = window.innerHeight;
      } else {
        docWidth  = document.body.offsetWidth;
        docHeight = document.body.offsetHeight;
      }

       var aLeft = getAbsoluteLeft( this.activeCon);
       var aTop = getAbsoluteTop( this.activeCon) - (this.activeCon.parentNode.scrollTop);;
      
      if (aTop + this.parent.offsetHeight > docHeight) 
        this.parent.style.top = aTop - this.parent.offsetHeight +  this.activeCon.offsetHeight + 'px'; 
      else
        this.parent.style.top = aTop + 'px';

        
      if (aLeft + this.parent.offsetWidth +  this.activeCon.offsetWidth > docWidth)
        this.parent.style.left = aLeft + 'px';
      else
		    this.parent.style.left = aLeft +  this.activeCon.offsetWidth + 'px';
	  }	
    
	  if (this.ifr != undefined) 
	  {
	    this.ifr.style.top = this.entObj.offsetTop + 'px';
		  this.ifr.style.left = this.entObj.offsetLeft + 'px';
		  this.ifr.style.display = 'block';
	  }	
    
    if (this.time && !this.minimized) {
      this.tp.setPosition (getAbsoluteLeft (this.parent) + 30, getAbsoluteTop (this.parent) + 147);   
                                                                                                 
      this.tp.show ();
    }
    this.parent.style.visibility = 'visible';
    
    return this;
  },

  /**
  *  @desc:  hide calendar
  *  @type: public
  *  @topic: 4
  */
  hide:function(){
	  this.parent.style.display = 'none';
	  if(this.ifr!=undefined)
		  this.ifr.style.display = 'none';
    if (this.time)
      this.tp.hide();
    return this;
  },

  /**
  *  @desc:  set date format
  *  @param: format - {String} dateformat string contained next sings:
  %e	Day of the month without leading zeros (1..31)
  %d	Day of the month, 2 digits with leading zeros (01..31)
  %j	Day of the year, 3 digits with leading zeros (001..366)
  %a	A textual representation of a day, two letters
  %W	A full textual representation of the day of the week

  %c	Numeric representation of a month, without leading zeros (1..12)
  %m	Numeric representation of a month, with leading zeros (01..12)
  %b	A short textual representation of a month, three letters (Jan..Dec)
  %M	A full textual representation of a month, such as January or March (January..December)

  %y	A two digit representation of a year (93..03)
  %Y	A full numeric representation of a year, 4 digits (1993..2003)
  *  @type: public
  *  @topic: 1
  */
  setDateFormat:function(format){
	  this.options.dateformat = format;
  },



  /**
  *     @desc: create object of Date class
  *	  @param: date - selected date
  *     @type: private
  *     @return: date
  *     @topic: 6 
  */  
  cutTime:function(date) {
	  date = new Date(date);
	  var ndate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
	  return ndate;
  },


  /**
  *     @desc: set new parent object for calendar
  *	    @param: newParent - {Object} new parent object for calendar
  *     @type: public
  *     @return: date
  *     @topic: 0 
  */  
  setParent:function(newParent){
	  if (newParent) {
		  this.parent = newParent;
		  this.parent.appendChild(this.entObj);
	  }
  },
  /**
  *  @desc: select date in calendar
  *  @param: date - {Data} current date
  *  @type: public
  *  @topic: 4
  */
  setDate:function(date, conId){
  
    tmpDate = date;

    conId = this._activeConInd (conId);
    //console.log('setdate' + conId);
    this.activeCon = this.con [conId];

    if (typeof date != "Object")
      date = this.setFormatedDate(null ,tmpDate);
   
    if (isNaN(date))
      date = new Date (tmpDate);

    if (!isNaN(date)) {
		  this.date[conId] = new Date(this.cutTime(date));
		  this.selDate[conId] = new Date(this.cutTime(date));
    }
  
    if (this.isAutoDraw) {
      //console.log('DRAW!');
	    this.draw();	
    }
    
    if (this.activeCon.nodeName == 'INPUT')
      this.activeCon.value = this.getFormatedDate(this.options.dateformat, date) + (this.time ? " " + this.getFormatedTime () : "");
  },
  /**
  *  @desc: add class for object
  *  @param: obj - {Object} object
  *  @param: styleName - {String} style name
  *  @type: private
  *  @topic: 4
  */
  addClass:function(obj, styleName) {
	  obj.className += ' ' + styleName;
  },

  /**
  *  @desc: reset class for object
  *  @param: obj - {Object} object
  *  @type: private
  *  @topic: 4
  */
  resetClass:function(obj) {
	  obj.className = obj.className.toString().split(' ')[0];
  },

  resetHotClass:function(obj) {
	  obj.className = obj.className.toString().replace(/hover/, '');
  },

  /**
  *  @desc: add class to caledar 
  *  @param: newSkin - {String} class name
  *  @type: private
  *  @topic: 4
  */
  setSkin:function(newSkin) {
	  this.skinName = newSkin;
    var mode = "";
    mode = (this.minimized
           ? "_mini" 
           : (this.time 
             ? "_long"
             : (this.options.isWinHeader
               ? "_maxi"
               : ""
               )
             )
           );
    
    this.entObj.className = this.style + (newSkin ? '_' + newSkin : '');
    if (mode)
      this.entObj.className += " " + this.entObj.className + mode;

	  if(this.ifr!=undefined) {
		  this.ifr.className = this.style + (newSkin ? '_' + newSkin : '') + mode + "_ifr";
      
	  }
    if (this.time)
      (this.isVisible () && !this.minimized) ? this.tp.show () : this.tp.hide ();
  },
  
  /**
  *  @desc: get selected items date
  *  @returns: selected items date
  *  @type: public
  *  @topic: 6
  */
  getDate:function(conId)
  {
	  return this.selDate[this._activeConInd(conId)].toString();
  },
  
  /**
  *  @desc: draw next month
  *  @type: private
  *  @topic: 0
  */

  nextMonth:function(){
    var date = this.date[this._activeConInd()], month;
    date.setDate(1);
	  date.setMonth(month = date.getMonth() + 1);
	  this.callEvent ("onChangeMonth",[(month+1 > 12 ? 1 : month+1), month || 12]);	
	  if (this.isAutoDraw) this.draw();
  },
  
  /**
  *  @desc: draw previos month
  *  @type: private
  *  @topic: 0
  */
  prevMonth:function(){
    var date = this.date[this._activeConInd()], month;
    date.setDate(1);
	  date.setMonth(month = date.getMonth()-1);
	  this.callEvent ("onChangeMonth",[month+1 || 12,month+2 > 12 ? 1 : (month+2 || 12)]);
	  if (this.isAutoDraw) this.draw();
  },
  /**
  *  @desc: set onClick event handler
  *  @param: func - function called when the date selected 
  *  @type: public
  *  @topic: 5
  */
  setOnClickHandler:function(func){
    this.attachEvent("onClick",func);
  },

  /**
  *  @desc:  get formated date
  *  @param: dateformat - {String} dateformat string
  *  @param: date - date which should be formated
  *  @type: public
  *  @topic: 1
  */

  getFormatedDate:function (dateformat, date, conInd) {
	  if(!dateformat) dateformat = this.options.dateformat
	  if(!date) date = this.selDate[this._activeConInd(conInd)];
	  date = new Date(date);
	  var out = '';
	  var plain = true;
	  for (var i=0; i<dateformat.length; i++) {
		  var replStr = dateformat.substr(i, 1);
		  if (plain) {
			  if (replStr == '%') {
				  plain = false;				
				  continue;
			  }
			  out += replStr;
		  } else {
			  switch (replStr) {
  //	---	Day	---
			    case 'e':
			  	  replStr = date.getDate();
				  break;
			    case 'd':
			  	  replStr = date.getDate();
				  if (replStr.toString().length == 1)
					  replStr='0'+replStr;
				  break;
			    case 'j':
				  var x = new Date(date.getFullYear(), 0, 0, 0, 0, 0, 0);
				  replStr = Math.ceil((date.valueOf() - x.valueOf())/1000/60/60/24 - 1);
				  while (replStr.toString().length < 3)
					  replStr = '0' + replStr;
				  break;
			    case 'a':
			  	  replStr = this.options.daysSNames[date.getDay()];
				  break;
			    case 'W':
			  	  replStr = this.options.daysFNames[date.getDay()];
				  break;
  //	---	Month	---
			    case 'c':
			  	  replStr = 1 + date.getMonth();
				  break;
			    case 'm':
			  	  replStr = 1 + date.getMonth();
				  if (replStr.toString().length == 1)
					  replStr = '0' + replStr;
				  break;
			    case 'b':
			  	  replStr = this.options.monthesSNames[date.getMonth()];
				  break;
			    case 'M':
			  	  replStr = this.options.monthesFNames[date.getMonth()];
				  break;
  //	---	Year	---
			    case 'y':
			  	  replStr = date.getFullYear();
				  replStr = replStr.toString().substr(2);
				  break;
			    case 'Y':
			  	  replStr = date.getFullYear();
			  }
			  out += replStr;
			  plain = true;
		  }
	  }

	  return out;
  },

  /**
  *  @desc:  set formated date
  *  @param: dateformatarg - {String} dateformat string contained next sings:
  %e	Day of the month without leading zeros (01..31)
  %d	Day of the month, 2 digits with leading zeros (01..31)
  %j	Day of the year, 3 digits with leading zeros (001..366)
  %a	A textual representation of a day, two letters
  %W	A full textual representation of the day of the week

  %c	Numeric representation of a month, without leading zeros (0..12)
  %m	Numeric representation of a month, with leading zeros (00..12)
  %b	A short textual representation of a month, three letters (Jan..Dec)
  %M	A full textual representation of a month, such as January or March (January..December)

  %y	A two digit representation of a year (93..03)
  %Y	A full numeric representation of a year, 4 digits (1993..03)
  *  @param: date - date which should be formated
  *  @type: public
  *  @topic: 1
  */


  setFormatedDate: function(dateformatarg, date, conInd){
  	if (!date || !typeof date == 'string' || this.getFormatedDate(dateformatarg).length != date.length) return date;
        
    if (self.time) 
    {            
      self.time.setFormatedTIme(null, date.split(" ")[1]);
    }
                
	  if(!dateformatarg) dateformatarg = this.options.dateformat;
    //if (this.time) // check it
	    date = date.split(" ")[0];
	  function parseMonth(val){
		  var tmpAr = new Array(this.options.monthesSNames,this.options.monthesFNames);
		  for(var j=0;j<tmpAr.length;j++){
			  for (var i=0; i<tmpAr[j].length; i++)
				  if (tmpAr[j][i].indexOf(val) == 0)
					  return i;
		  }
		  return -1;
	  }
	  var outputDate = new Date(2008, 0, 1);//default date 2008.01.01
	  var j=0;//position in date
	  for(var i=0;i<dateformatarg.length;i++){
		  
		  var _char = dateformatarg.charAt(i);
		  if(_char=="%"){
			  var _cd = dateformatarg.charAt(i+1);//code of format item
			  var _nextpc = dateformatarg.indexOf("%",i+1);
			  var _nextDelim = dateformatarg.substr(i+2,_nextpc-i-1-1);
			  var _nDelimInDatePos = date.indexOf(_nextDelim,j);
			  if(_nextDelim=="")
				  _nDelimInDatePos = date.length
			  if(_nDelimInDatePos==-1)
				  return null;
			  var value = date.substr(j, _nDelimInDatePos-j);//value in date
        
			  if (_cd != 'M' && _cd != 'b') 
				  value -= 0;
			  j=_nDelimInDatePos+_nextDelim.length
			  switch (_cd) {
  //	---	Day	---
			    case 'd':
			    case 'e':
			  	  outputDate.setDate(parseFloat(value));
				  break;
  //	---	Month	---
			  case "c":
			  case "m":
				  outputDate.setMonth(parseFloat(value) - 1);
				  break;
			  case "M":
				  var val = parseMonth.call(this,value);
				  if(val!=-1)
					  outputDate.setMonth(parseFloat(val));
				  else 
					  return null;
				  break;
			  case "b":
				  var val = parseMonth.call(this,value);
				  if(val!=-1)
					  outputDate.setMonth(parseFloat(val));
				  else 
					  return null;
				  break;
  //	---	Year	---
			    case 'Y':
			  	  outputDate.setFullYear(parseFloat(value));
			  	  break;
			    case 'y':
			  	  var year=parseFloat(value);
			  	  outputDate.setFullYear(((year>20)?1900:2000) + year);
			  	  break;			  	
			  }
		  }
	  }
  if (isNaN(outputDate))
    outputDate = new Date(this.selDate[this._activeConInd]);

	  this.setDate (outputDate, conInd);
	  return this.selDate[this. activeConInd];
  },

  /**
  *     @desc: return if day is weekend
  *    @param: k - position of the day in a week
  *     @type: private
  *     @return: node state (1 - weekend, 0 -workaday)
  *     @topic: 1 
  */      
  isWeekend:function(k){
    var q = k + this.options.weekstart;
    if (q > 6) q -= 7;
    for (var i=0; i<this.options.weekend.length; i++)
      if (this.options.weekend[i] == q)
        return true;
    return false;
  },

  /**
  *     @desc: get day name
  *    @param: k - position of the day in a week
  *     @type: private
  *     @return: day name
  *     @topic: 1 
  */  
  getDayName:function(k){
    var q = k + this.options.weekstart;
    if (q > 6) q = q - 7;
    return this.options.daysSNames[q];
  },

  /**
  *  @desc: get visibility state
  *  @type: public
  *  @topic: 4
  *  @return: state of visibility (false - invisible, true - visible)
  */
  isVisible: function(){
	  return this.parent.style.display != 'none';
  },
  doHotKeys:function(e){
      e = e||event;
      var cell = e.target || e.srcElement;
      if (cell.className.toString().indexOf('insensitive') >=0 ) {
        this.endHotKeys();
      } else {
        if (this.hotCell) this.resetHotClass(this.hotCell);
        this.addClass(cell, 'hover');
        this.hotCell = cell;
      }
    },

  endHotKeys:function(){
    if (this.hotCell) {
      this.resetHotClass(this.hotCell);
      this.hotCell = null;
    }
  },
  _activeConInd:function(ind){
    if (!this.parent) this.createStructure();
    return (this.activeConInd = (this.conInd[ind]==0?'0':this.conInd[ind]) || (ind==0?'0':ind) || this.conInd[this.activeCon.id] || 0);
  }
}

  // #################################################################################################

  /**
  *  @desc: Create Editable Selector as Node
  *  param: parametres - an associate array of parametres
  *  @type: private
  *  @topic: 0      
  */
  function dhtmlxRichSelector(parametres) {
    for (x in parametres)
      this[x] = parametres[x];
    
    this.initValue = this.activeValue;
    if (!this.selectorSize)  this.selectorSize = 7;
    
    var self = this;
    this.blurTimer = null;

    this.nodeBefore.onclick = function() {
      self.show();
    }

    this.editor = document.createElement('TEXTAREA');
    this.editor.value = this.activeValue;
    this.editor._s = this;
    this.editor.className = 'dhtmlxRichSelector';

    this.editor.onfocus = this.onFocus;
    this.editor.onblur = this.onBlur;

    this.selector = document.createElement('SELECT');
    this.selector.size = this.selectorSize;
    this.selector.className = 'dhtmlxRichSelector';

    if (this.valueList)
      for (var i = 0; i < this.valueList.length; i++)
        this.selector.options[i] = new Option(this.titleList[i], this.valueList[i], false, false);
      
    this.selector._s = this;
    
    this.selector.onfocus = this.onFocus;
    this.selector.onblur = this.onBlur;
    this.selector.onclick = function () {
            window.t = self;
      self.onSelect(self.selector.value);
      clearTimeout(self.blurTimer);
    }

    this.selector.getIndexByValue = function (Value, isFull) {
      var Select = this;
      Value = Value.toString().toUpperCase();
      if (!isFull) isFull=false;
      for (var i=0; i<Select.length; i++) {
        var i_value = Select[i].text.toUpperCase();
        if (isFull) {
          if(i_value == Value) return i;
        } else {
          if (i_value.indexOf(Value) == 0) return i;
        }
      }
      if (Select._s.isOrderedList) {
        if (Select._s.isNumbersList)
          if (isNaN(Value)) return -1;
        // first
        i_value = Select[0].text.substring(0, Value.length).toUpperCase();
        if (i_value > Value) return 0;
        // last
        i_value = Select[Select.length-1].text.substring(0, Value.length);
        if (i_value < Value) return Select.length-1;
      }
      return -1;
    }
    
    this.con = document.createElement('DIV')
    this.con.className = 'dhtmlxRichSelector';
    with (this.con.style) {
      width = 'auto';
      display = 'none';
    }

    this.con.appendChild(this.editor);
    this.con.appendChild(this.selector);
    this.nodeBefore.parentNode.insertBefore(this.con, this.nodeBefore);
    return this;
  }

  /**
  *  @desc: Show selector
  *  @type: public
  *  @topic: 0      
  */
  dhtmlxRichSelector.prototype.show = function() {
    this.con.style.display = 'block';

    with (this.selector.style) {
      marginTop = parseInt(this.nodeBefore.offsetHeight)+'px';
      width = 'auto';
    }
    with (this.editor.style) {
      width = parseInt(this.nodeBefore.offsetWidth)+15+'px';
      height = parseInt(this.nodeBefore.offsetHeight)+'px';
    }
    this.selector.selectedIndex = this.selector.getIndexByValue(this.activeValue);
    this.editor.focus();
  }
  /**
  *  @desc: Hide selector
  *  @type: public
  *  @topic: 2    
  */
  dhtmlxRichSelector.prototype.hide = function() {
    this.con.style.display = 'none';
  }
  /**
  *  @desc: set onBlur event handler
  *  @type: private
  *  @topic: 0      
  */
  dhtmlxRichSelector.prototype.onBlur = function() {
    var self = this._s;
    self.blurTimer = setTimeout(function(){
      if (self.isAllowUserValue) {
        if (self.onSelect(self.editor.value))
           self.activeValue = self.editor.value;
      } else {
        if (self.onSelect(self.selector.value))
           self.activeValue = self.selector.value;
      }
    }, 10);
  }
  /**
  *  @desc: set onFocus event handler
  *  @type: private
  *  @topic: 0    
  */
  dhtmlxRichSelector.prototype.onFocus = function() {
    var self = this._s;
    if(self.blurTimer) {
      clearTimeout(self.blurTimer);
      self.blurTimer = null;
    }
    if (this === this._s.selector)
      self.editor.focus();
  }
  
/**
*  @desc:  set header in calendar
*  @param: isVisible - is header visible
*  @param: isDrag - can calendar be dragged
*  @param: isDrag - can calendar be dragged
*  @param: btnsOpt - the header buttons string
*  @type: public
*  @topic: 2
*/
dhtmlxCalendarObject.prototype.setHeader = function(isVisible, isDrag, btnsOpt){
  with (this.options) {
    isWinHeader = isVisible;
    isWinDrag = isDrag;
    if (btnsOpt) headerButtons = btnsOpt;
  }
  this.setSkin (this.skinName);
}

/**
*  @desc:  set years range
*  @param: minYear - low bound
*  @param: maxYear - upper bound
*  @type: public
*  @topic: 4
*/
dhtmlxCalendarObject.prototype.setYearsRange = function(minYear, maxYear){
  this.options.yearsRange = [parseInt(minYear), parseInt(maxYear)];
  this.allYears = [];
  for (var i=minYear; i <= maxYear; i++)
    this.allYears.push(i);
}

/**
*     @desc: start drag handler 
*     @type: private
*     @topic: 5  
*/
dhtmlxCalendarObject.prototype.startDrag = function(e) {
  e = e||event;
  if ((e.button === 0) || (e.button === 1)) {
    if (this.dragging) {
      this.stopDrag(e);
    }
  
    this.drag_mx = e.clientX;
    this.drag_my = e.clientY;


    this.drag_spos = this.getPosition(this.parent);
    document.body.appendChild(this.parent);
    with (this.parent.style) {
      left = this.drag_spos[0] + 'px';
      top = this.drag_spos[1] + 'px';
      margin = '0px';
      position = 'absolute';
    }
    
    if (this.ifr) {
      this.ifr.style.top =  '0px';
      this.ifr.style.left = '0px';
    }
    this.bu_onmousemove = document.body.onmousemove;
    var self = this;
    document.body.onmousemove = function (e) {
      self.onDrag(e);
    }
    this.bu_onmouseup = document.body.onmouseup;
    document.body.onmouseup = function (e) {
      self.stopDrag(e);
    }

    this.dragging = true;
  }

}

/**
*     @desc: onDrag handler 
*     @type: private
*     @topic: 5 
*/
dhtmlxCalendarObject.prototype.onDrag = function(e) {
  e = e||event;
  if ((e.button === 0) || (e.button === 1)) {
    var delta_x = this.drag_mx - e.clientX;
    var delta_y = this.drag_my - e.clientY;
    this.parent.style.left = this.drag_spos[0] - delta_x + 'px';
    this.parent.style.top = this.drag_spos[1] - delta_y + 'px';
    if (this.time) {
      this.tp.setPosition (getAbsoluteLeft (this.parent) + 30, getAbsoluteTop (this.parent) + 160);   
    }
    //iframe dragging (fix for IE6)
    if(this.ifr != undefined) {
      this.ifr.style.left = 0;//this.parent.offsetLeft + 'px';
      this.ifr.style.top = 0;//this.parent.offsetTop + 'px';
    }
    
  } else {
    this.stopDrag(e);
  }
}

/**
*     @desc: stop drag handler 
*     @type: private
*     @topic: 5  
*/

dhtmlxCalendarObject.prototype.stopDrag = function(e) {
  e = e||event;   
  document.body.onmouseup = (this.bu_onmouseup === window.undefined)? null: this.bu_onmouseup;
  document.body.onmousemove = (this.bu_onmousemove === window.undefined)? null: this.bu_onmousemove;
  this.dragging = false;
}



/**
*  @desc:  minimize calendar
*  @type: public
*  @topic: 4
*/
dhtmlxCalendarObject.prototype.minimize = function(){
  if (!this.winHeader) return;
  this.minimized = !this.minimized;
  this.entBox.style.display = (!this.minimized) ? '' : 'none';
  
  this.setSkin (this.skinName);
}

dhtmlxCalendarObject.prototype.onYearSelect = function(value) {
  if (!isNaN(value))
  {
    this._c.date[this._c._activeConInd()].setFullYear(
      Math.min 
      (
        Math.max 
        (
          value, 
          this._c.allYears[0]
        ), 
        this._c.allYears.slice(-1)
      )
    );    
  }
  this._c.draw();
  return (!isNaN(value));
}

dhtmlxCalendarObject.prototype.onMonthSelect = function(value) {
  this._c.date[this._c._activeConInd()].setMonth(value);
  this._c.draw();
  return true;
}

/**
*  @desc: set position for calendar object
*  @type: public
*  @topic: 0
*/
dhtmlxCalendarObject.prototype.setPosition = function(argA,argB,argC){
  if(typeof(argA)=='object'){
    var posAr = this.getPosition(argA)
    var left = posAr[0]+argA.offsetWidth+(argC||0);
    var top = posAr[1]+(argB||0);
  }
  this.parent.style.position = "absolute";
  this.parent.style.top = (top||argA)+"px";
  this.parent.style.left = (left||argB)+"px";
  if (this.ifr != undefined) {
    this.ifr.style.left = '0px';
    this.ifr.style.top = '0px';
  }
  if (this.time)
    this.tp.setPosition (getAbsoluteLeft (this.parent) + 30, getAbsoluteTop (this.parent) + 160);   
}

/**
*  @desc: hide calendar
*  @type: public
*  @topic: 2
*/
dhtmlxCalendarObject.prototype.close = function(func){
  this.hide ();
}

/**
*  @desc: get position one object concerning another
*  @desc: oNode - object
*  @desc: pNode - parent object
*  @type: public
*  @topic: 0
*/
dhtmlxCalendarObject.prototype.getPosition = function(oNode,pNode) { 
   if(!pNode)
       var pNode = document.body
   var oCurrentNode=oNode;
   var iLeft=0;
   var iTop=0;
                  while ((oCurrentNode)&&(oCurrentNode!=pNode)){//.tagName!="BODY"){ 
               iLeft+=oCurrentNode.offsetLeft-oCurrentNode.scrollLeft;
               iTop+=oCurrentNode.offsetTop-oCurrentNode.scrollTop;
               oCurrentNode=oCurrentNode.offsetParent;//isIE()?:oCurrentNode.parentNode;
                  }
              if (pNode == document.body ){
                 if (_isIE){
                 if (document.documentElement.scrollTop)
                  iTop+=document.documentElement.scrollTop;
                 if (document.documentElement.scrollLeft)
                  iLeft+=document.documentElement.scrollLeft;
                  }
                  else
                       if (!_isFF){
                             iLeft+=document.body.offsetLeft;
                           iTop+=document.body.offsetTop;
                  }
                 }

   return new Array(iLeft,iTop);
     
}

/**
*  @desc:  set sensitive range for calendar
*  @param: fromDate - {Date} lower band of the range 
*  @param: toDate - {Date} upper band of the range
*  @type: public
*  @topic: 4
*/
dhtmlxCalendarObject.prototype.setSensitive = function(fromDate,toDate){
  if (fromDate)
    if (fromDate instanceof Date) {
      this.sensitiveFrom = this.cutTime(fromDate);
    } else {
      this.sensitiveFrom = fromDate.toString ().split (',');
    }
  if (toDate) this.sensitiveTo = this.cutTime(toDate);
  if (this.isAutoDraw) this.draw();
}

/**
*  @desc: set holidays dates
*  @type: public
*  @topic: 4
*/
dhtmlxCalendarObject.prototype.setHolidays = function(dates){
  this.holidays = dates.toString().split(",");
  if (this.isAutoDraw) this.draw();
}

/**
*  @desc: set on month change handler 
*  @type: public
*  @topic: 5
*/
dhtmlxCalendarObject.prototype.onChangeMonth = function (func) {
    this.attachEvent ("onChangeMonth",func);
}

/**
* @desc: set insensitive dates
* @type: public
* @topic: 4
*/
dhtmlxCalendarObject.prototype.setInsensitiveDates = function (dates) {
  this.insensitiveDates = dates.toString().split(",");
  if (this.isAutoDraw) this.draw();
}

/**
* @desc: enable timePicker
* @type: private
* @topic: 4
*/
dhtmlxCalendarObject.prototype.enableTime = function (mode) {
  if (this.time = mode) {
    this.tp = new dhtmlXTimePicker (); 
        this.tp.setPosition (getAbsoluteLeft (this.parent) + 30, getAbsoluteTop (this.parent) + 160);   
    
    for (m in dhtmlXTimePicker.prototype)
      (function (m) { 
        if (!dhtmlxCalendarObject.prototype [m])
          dhtmlxCalendarObject.prototype [m] = function (){return this.tp[m].apply(this.tp, arguments)}
      })(m);
  } else {
    this.tp.entBox.parentNode.removeChild (this.tp.entBox);
    this.tp = null;
  }
  this.setSkin(this.skinName);
}

/**
* @desc: set header text
* @type: public
* @param: text
* @topic: 4
*/
dhtmlxCalendarObject.prototype.setHeaderText = function (text) {
  this.options.headerText = text;
  if (this.headerLabel) {
    this.headerLabel.childNodes[0].nodeValue = text;
    this.headerLabel.setAttribute('title', text);
  }
}

/**
* @desc: disable iframe which used to fix ie bug with overlapping
* @type: public
* @param: mode 
* @topic: 4
*/
dhtmlxCalendarObject.prototype.disableIESelectFix = function (mode) {
  this.useIframe = !mode;
  if (this.ifr != undefined) 
  {
    this.ifr.parentNode.removeChild(this.ifr);
    this.ifr = null;
  }
}
