var
  cMinDate = new Date(Number(new Date())-86400000),
  cMaxDate = new Date(Number(new Date())+86400000*365);

function Calendar(aName,aDiv,aYear,aMonth,aDay,aValidate,aPatched)
{
  var lAttr,lDate;
  this.name        = aName;
  this.div         = aDiv;
  this.year        = aYear;
  this.month       = aMonth;
  this.day         = aDay;
  this.onValidate  = aValidate;
  this.patched     = aPatched;
  this.min         = cMinDate;
  lAttr = _$($(aDiv),"min");
  if(lAttr!=null && lAttr.length>0)
  {
    lDate = eval(lAttr);
    if(typeof(lDate)=="object") { this.min = lDate; }
  }
  this.max         = cMaxDate;
  lAttr = _$($(aDiv),"max");
  if(lAttr!=null && lAttr.length>0)
  {
    lDate = eval(lAttr);
    if(typeof(lDate)=="object") { this.max = lDate; }
  }
  this.build();
} 

Calendar.prototype.click = function(aDay)
{ var
    lDay   = aDay;
    lMonth = this.month*1 + 1;
  
  if (this.onValidate && this.onValidate(new Date(this.year,this.month,aDay)))
  {
    this.day   = aDay;
    if (String(lDay).length==1)   { lDay = '0'+lDay; }
    if (String(lMonth).length==1) { lMonth = '0'+lMonth; }
    this.update(this.year,this.month,this.day);
  }
}

Calendar.prototype.changed = function()
{
  var lDate;
  
  if(this.patched)
  {
    lDate = new Date($(this.name+'_year').value,$(this.name+'_month').value,this.day);
    if(lDate>=this.min && lDate<=this.max)
    {
      if (this.onValidate && this.onValidate(lDate))
	  {
        this.year  = $(this.name+'_year').value;
        this.month = $(this.name+'_month').value;
        this.update(this.year,this.month,this.day);
      }
      
    }
    else { this.update(this.year,this.month,this.day); }
  }
  else
  {
    this.year  = $(this.name+'_year').value;
    this.month = $(this.name+'_month').value;
    this.update(this.year,this.month,this.day);
  }

}

Calendar.prototype.arrayToSelect = function(aArray,aElement,aUseIndex)
{
  var
    lCount,
    lSelect = $(aElement),
    lOption;
    
  lSelect.options.length = 0;  
  for (lCount=0;lCount<aArray.length;lCount++)
  {
    lOption = new Option(aArray[lCount],aUseIndex?lCount:aArray[lCount],false,false);
    lSelect.options[lSelect.options.length]=lOption;
  }
}

Calendar.prototype.build = function()
{
  var
    lDiv = $(this.div),
    lHTML='';

  lHTML += '<center><table cellspacing="0" cellpadding="0"><tr><td>';
  lHTML += '<table cellspacing="0" cellpadding="0"><tr>';
  lHTML += '<td><select id="'+this.name+'_month" onChange="'+this.name+'.changed()" class="CalMonth"></select></td>';
  lHTML += '<td>&nbsp;</td>';
  lHTML += '<td><select id="'+this.name+'_year" onChange="'+this.name+'.changed()" class="CalYear"></select></td>';
  lHTML += '</tr></table>';
  lHTML += '</td></tr><tr><td><div id="'+this.name+'_calendar"></div></td></tr></table></center>';

  lDiv.innerHTML = lHTML;
  this.arrayToSelect(_$(lDiv,'months').split(','),this.name+'_month',true);
  if (this.min.getFullYear()!=this.max.getFullYear())
  { this.arrayToSelect([this.min.getFullYear(), this.max.getFullYear()], this.name+'_year', false); }
  else
  { this.arrayToSelect([this.min.getFullYear()], this.name+'_year', false); }
  $(this.name+'_month').value = this.month;
  $(this.name+'_year').value = this.year;
  this.update(this.year,this.month,this.day);
}

Calendar.prototype.update = function(aYear,aMonth,aDay)
{
  var
    lElement = $(this.name+'_calendar'),
    lDate = new Date(aYear,aMonth,1),
    lDays = _$($(this.div),'weekdays').split(','), 
    lHTML='',
    lCount;

  this.year  = aYear;
  this.month = aMonth;
  this.day   = aDay;
  $(this.name+'_month').value = this.month;
  $(this.name+'_year').value = this.year;
  lHTML += '<center><table cellspacing="0" cellpadding="0" class="Cal"><tr>';
  for (lCount=0;lCount<lDays.length;lCount++) { lHTML += '<td class="CalDow">'+lDays[lCount]+'</td>'; }
  lHTML += '</tr><tr>';
  for (lCount=0;lCount<lDate.getDay();lCount++) { lHTML += '<td class="CalSpacer">&nbsp;</td>'; }
  while (lDate.getMonth()==aMonth)
  {
    if (lDate<this.min || lDate>this.max)
    { lHTML += '<td class="CalVoid">'+lDate.getDate()+'</td>'; }
	else { lHTML += '<td align="center" class="'+(this.day==lDate.getDate()?'CalToday"':'d"')+'><a href="javascript:'+this.name+'.click('+lDate.getDate()+')"'+' class="CalDay">'+lDate.getDate()+'</a></td>'; }
    if (lDate.getDay()==6) { lHTML += '</tr><tr>'; }
    lDate.setDate(lDate.getDate()+1);
  }
  if (lDate.getDay()!=0)
  { for (lCount=lDate.getDay();lCount<=6;lCount++) { lHTML += '<td class="CalSpacer">&nbsp;</td>'; } }
  lHTML += '</tr></table></center>';  

  lElement.innerHTML = lHTML;
}

Calendar.prototype.toDate = function()
{
    var lYear,lMonth,lDay;
    lYear = String(this.year);
    lMonth = String(parseInt(this.month,10)+1);
    if(lMonth.length==1) { lMonth = "0"+lMonth; }
    lDay = String(this.day);
    if(lDay.length==1) { lDay = "0"+lDay; }
    return lYear+lMonth+lDay;
}

// -----------------------------

var _track = new Object();
  function getMonth(d)
  {
        if(d.parentElement!=null && d.parentElement.tagName.toUpperCase()=='TR')
        {
          if(d.parentElement.parentElement!=null && d.parentElement.parentElement.tagName.toUpperCase()=='TBODY')
          {
              if(d.parentElement.parentElement.parentElement!=null && d.parentElement.parentElement.parentElement.tagName.toUpperCase()=='TABLE')
              { return _$(d.parentElement.parentElement.parentElement,"ym"); }
          }
      }
      return null;
  }

  function dayClick(e)
  {
      var lO=_$esrc(e),lYM,lI,lD;

      lI=false;
      if(lO.tagName.toUpperCase()=="TD")
      {
          lYM = getMonth(lO);
          if(lYM!=null)
          {
              switch(lO.className)
              {
                  case 'h':
                      lO.className='r';
                      break;
                  case 'r':
                      lO.className='';
                      break;
                  case '':
                      lO.className='h';
                      break;
                  default:
                      lI=true;
                      break
              }
              if(!lI)
              {
                lD = lO.innerText;
                if(lD.length==1) { lD='0'+lD; }
                _track[lYM+lD]=lO.className;
              }
          }
      }
  }

  function calendarDump()
  {
      var lB='',lO;

      for(lO in _track)
      {
        lB += lO + '=' + _track[lO] + '<br/>';
      }
      
      _out.innerHTML=lB;
  }