//
// jsCal. 2004-05-11
//
// Copyright 2004, Ted Lin
//
// This script is distributed under the GNU Lesser General Public License.
// Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
//

// Completely DOM Calendar generation
//
// call by:
//   openCalendarObjectCallback(origin, callbackfunction, date)
//     opens a calendar based on the origin element position
//     and calls the callback function with the date
//
//   openCalendarObjectInputId(origin, elementidstr, date)
//     opens a calendar based on the origin element position
//     and returns the date in the INPUT element using the id string

var caldiv;

var updateWhat;
var updateValue;

function jsCal_selectCalendarDate()
{
  // make sure it's a valid element to get day from
  if (!this || this.tagName != 'TD' || !this.value)
  {
    return;
  }

  // figure out what to do with the values
  switch(updateWhat)
  {
  case 'callback':
    {
      updateValue(this.value);
    }
    break;

  case 'element':
    {
      var elem = document.getElementById(updateValue);
      if (elem && elem.tagName == 'INPUT')
      {
        elem.value = this.value;
      }
    }
    break;

  default:
    break;
  }

  caldiv.style.display = 'none';
}

function jsCal_changeCalendar()
{
  if (!caldiv)
  {
    return;
  }

  var year = document.getElementById('jsCal_calendarYear');
  var month = document.getElementById('jsCal_calendarMonth');
  var caltbl = document.getElementById('jsCal_calendarTable');

  if (!caltbl || !year || !month || isNaN(year.value) || isNaN(month.value))
  {
    return;
  }

  // locate the tbody
  var tblbdy = caltbl.getElementsByTagName('tbody').item(0);
  if (!tblbdy)
  {
    return;
  }

  // clear everything in the calendar
  while (tblbdy.firstChild)
  {
    tblbdy.removeChild(tblbdy.firstChild);
  }

  // today
  var today = new Date();

  // beginning of month
  var theday = new Date(year.value+'/'+month.value+'/01');

  // end of month
  var endday = new Date(theday);
  endday.setMonth(endday.getMonth()+1);
  endday.setDate(endday.getDate()-1);

  // find first sunday
  while (theday.getDay() != 0)
  {
    theday.setDate(theday.getDate()-1);
  }

  // date comparison function
  function compareDates(a, b)
  {
    if (a.getFullYear() < b.getFullYear())
    {
      return -1;
    }
    if (a.getFullYear() > b.getFullYear())
    {
      return +1;
    }
    if (a.getMonth() < b.getMonth())
    {
      return -1;
    }
    if (a.getMonth() > b.getMonth())
    {
      return +1;
    }
    if (a.getDate() < b.getDate())
    {
      return -1;
    }
    if (a.getDate() > b.getDate())
    {
      return +1;
    }

    return 0;
  }

  // loop over week (7 days) until we're past the end of the month
  while (compareDates(theday,endday) <= 0)
  {
    // create row
    var tblrow = document.createElement('tr');
    
    for (i = 0; i < 7; i++)
    {
      var tblcell = document.createElement('td');
      
      tblcell.style.textAlign = 'center';
      tblcell.style.fontSize = '10pt';
      tblcell.style.fontWeight = 'bold';
      tblcell.style.cursor = 'pointer';

      function pad2(i)
      {
        if (i < 10)
        {
          i = '0' + i;
        }
        return i;
      }
      
      tblcell.value = theday.getFullYear()
                      +'/'+pad2(theday.getMonth()+1)
                      +'/'+pad2(theday.getDate());

      tblcell.onclick = jsCal_selectCalendarDate;
      tblcell.onmouseover = function()
        {
          this.style.backgroundColorOld = this.style.backgroundColor;
          this.style.backgroundColor = '#bbe';
        }
      tblcell.onmouseout = function()
        {
          this.style.backgroundColor = this.style.backgroundColorOld;
        }

      if (theday.getMonth() == month.value-1)
      {
        tblcell.style.backgroundColor = '#ddd';
        tblcell.style.color = '#000';
      }
      else
      {
        tblcell.style.backgroundColor = '#bbb';
        tblcell.style.color = '#777';
      }
      
      if (today.getFullYear() == theday.getFullYear() &&
          today.getMonth() == theday.getMonth() &&
          today.getDate() == theday.getDate())
      {
        tblcell.style.backgroundColor = '#dea';
        tblcell.style.color = '#000';
      }
      
      var tn = document.createTextNode(theday.getDate());
      tblcell.appendChild(tn);

      tblrow.appendChild(tblcell);
      
      theday.setDate(theday.getDate()+1);
    }

    tblbdy.appendChild(tblrow);
  }
}

function jsCal_closeCalendar()
{
  if (!caldiv)
  {
    return;
  }

  if (caldiv.closetimer)
  {
    clearTimeout(caldiv.closetimer);
    caldiv.closetimer = undefined;
  }

  caldiv.style.display = 'none';
}

function openCalendarObjectCallback(origin, callbackFn, date)
{
  // set up callback
  updateWhat = 'callback';
  updateValue = callbackFn;

  jsCal_openCalendar(origin, date);

  return;
}

function openCalendarObjectInputId(origin, elementID, date)
{
  // set up form id
  updateWhat = 'element';
  updateValue = elementID;

  // check date
  if (!date)
  {
    var elem = document.getElementById(updateValue);
    if (elem && elem.tagName == 'INPUT' && elem.value)
    {
      date = elem.value;
    }
  }

  // open the calendar
  jsCal_openCalendar(origin, date);
}

function jsCal_openCalendar(origin, date)
{
  var today = new Date();
  if (date)
  {
    var dar = new Date(date);
    if (dar == 'Invalid Date')
    {
      date = date.replace(/-/g, '/');
      dar = new Date(date);
    }
    if (dar != 'Invalid Date')
    {
      today = dar;
    }
  }

  // create calendar?
  if (!caldiv)
  {
    var e;
    
    // create the element
    {
      caldiv = document.createElement('div');
      
      caldiv.style.position = 'absolute';
      caldiv.style.width = '200px';
      caldiv.style.padding = '2px 4px';
      caldiv.style.border = '1px solid black';
      caldiv.style.color = '#000';
      caldiv.style.backgroundColor = '#eee';
      caldiv.style.display = 'none';

      caldiv.onmouseout = function()
        {
          caldiv.closetimer = setTimeout(jsCal_closeCalendar, 1500);
        }
      caldiv.onmouseover = function()
        {
          clearTimeout(caldiv.closetimer);
          caldiv.closetimer = undefined;
        }
    }

    // create close button
    {
      var image = document.createElement('img');
      
      image.style.position = 'absolute';
      image.style.right = '0px';
      image.style.top = '0px';
      image.style.cursor = 'pointer';

      image.onclick = jsCal_closeCalendar;

      image.src = 'images/close.gif';

      caldiv.appendChild(image);
    }
    
    // create header bar
    {
      var hdrdiv = document.createElement('div');

      hdrdiv.style.borderBottom = '1px solid #999';
      
      // create year selectbox
      {
        var yearbox = document.createElement('select');
        
        yearbox.id = 'jsCal_calendarYear';
        yearbox.onchange = jsCal_changeCalendar;
          
        yearbox.style.marginRight = '4px';
        
        for (i = today.getFullYear()-2; i <= today.getFullYear()+4; i++)
        {
          e = document.createElement('option');

          e.value = i;
          
          if (i == today.getFullYear())
          {
            e.selected = true;
          }
          var tn = document.createTextNode(i);
          e.appendChild(tn);
          
          yearbox.appendChild(e);
        }

        hdrdiv.appendChild(yearbox);
      }

      // create monthbox
      {
        var months = Array('January', 'February', 'March', 'April',
                           'May', 'June', 'July', 'August',
                           'September', 'October', 'November',
                           'December');
        
        var monthbox = document.createElement('select');

        monthbox.id = 'jsCal_calendarMonth';
        monthbox.onchange = jsCal_changeCalendar;

        for (i = 0; i < 12; i++)
        {
          e = document.createElement('option');

          e.value = (i+1);
          
          if (i == today.getMonth())
          {
            e.selected = true;
          }
          var tn = document.createTextNode(months[i]);
          e.appendChild(tn);
          
          monthbox.appendChild(e);
        }

        hdrdiv.appendChild(monthbox);
      }
      
      caldiv.appendChild(hdrdiv);
    }

    // create the table
    {
      var tbl = document.createElement('table');

      tbl.style.fontFamily = 'arial, helvetica, sans-serif';
      tbl.style.width = '100%';

      tbl.id = 'jsCal_calendarTable';

      // create header
      {
        var days = Array('S', 'M', 'T', 'W', 'R', 'F', 'S');
        
        var tblheader = document.createElement('thead');

        tblheader.style.fontSize = '8pt';

        // create row
        {
          var tblrow = document.createElement('tr');

          // add cells
          for (i = 0; i < 7; i++)
          {
            var tblcell = document.createElement('th');
            tblcell.style.fontWeight = 'normal';

            var tn = document.createTextNode(days[i]);
            tblcell.appendChild(tn);
            
            tblrow.appendChild(tblcell);
          }
          
          tblheader.appendChild(tblrow);
        }
        
        tbl.appendChild(tblheader);
      }

      // create body
      {
        var tblbody = document.createElement('tbody');

        // empty, as filled in a little later
        
        tbl.appendChild(tblbody);
      }
      
      caldiv.appendChild(tbl);
    }

    // tack it onto the document
    {
      var mainbody = document.getElementsByTagName('body').item(0);
      
      mainbody.appendChild(caldiv);
    }
  }
  else
  {
    // make sure it's hidden
    caldiv.style.display = 'none';

    // set calendar year to this year
    {
      e = document.getElementById('jsCal_calendarYear');

      i = 0;
      while (i < e.length)
      {
        if (e.options[i].value == today.getFullYear())
        {
          e.selectedIndex = i;
          break;
        }
        i++;
      }
    }

    // set calendar month to this month
    {
      e = document.getElementById('jsCal_calendarMonth');

      e.selectedIndex = today.getMonth();
    }

  }

  // fill in the calendar
  jsCal_changeCalendar();


  // get positioning
  {
    var top = '10px';
    var left = '10px';

    if (origin)
    {
      var theTop = 0;
      var theLeft = 0;
      
      while (origin)
      {
        theTop += origin.offsetTop;
        theLeft += origin.offsetLeft;
        origin = origin.offsetParent;
      }
      
      top = (theTop)+'px';
      left = (theLeft)+'px';
    }

    // position and show the div
    caldiv.style.top = top;
    caldiv.style.left = left;
    caldiv.style.display = 'block';
  }
}
