function isLeapYear(year)
{
   return(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0));
}

function daysInMonth(month, year)
{
   // month: 1 -> 12

   var daysInMonth = 31;

   if(month == 2)
      daysInMonth = (isLeapYear(year) ? 29 : 28);

   else if(month == 4 || month == 6 || month == 9 || month == 11)
      daysInMonth = 30;

   return(daysInMonth);
}

function getCalendar(month, year)
{
   var data = {
      display  : month + " / " + year,
      entries  : [],
      lastMonth: month - 1,
      lastYear : year,
      nextMonth: month + 1,
      nextYear : year
   };

   if(data.lastMonth < 1)
   {
      data.lastMonth = 12;
      data.lastYear--;
   }

   if(data.nextMonth > 12)
   {
      data.nextMonth = 1;
      data.nextYear++;
   }

   // Months are 0-11 in the Date object rather than 1-12

   var d = new Date();

   d.setDate(1);
   d.setMonth(month - 1);
   d.setFullYear(year);

   // Find the most recent sunday on or before the
   // first of this month

   var t            = d.getTime();
   var millisPerDay = 1000 * 60 * 60 * 24;

   while(true)
   {
      var dayOfWeek = d.getDay();

      if(dayOfWeek == 0)
         break;

      t -= millisPerDay;
      d.setTime(t);
   }

   var beginDay   = d.getDate();
   var beginMonth = d.getMonth() + 1;
   var beginYear  = d.getFullYear();

   while(true)
   {
      var row = [];

      for(var i = 0; i < 7; i ++)
      {
         row[i] = { day: beginDay, month: beginMonth, year: beginYear };
         var dm = daysInMonth(beginMonth, beginYear);

         if(++beginDay > dm)
         {
            beginDay = 1;

            if(++beginMonth > 12)
            {
               beginMonth = 1;
               beginYear++;
            }
         }
      }

      data.entries[data.entries.length] = row;

      if(beginMonth > month || beginYear > year)
         break;
   }

   return(data);
}

function drawCalendar(divName, month, year)
{
   var d = document.getElementById(divName);

   if(!d)
   {
      alert("div: '" + divName + "' not found");
      return(false);
   }

   var obj = getCalendar(month, year);

   var previous =
      '<a href="javascript:drawCalendar(\'' +
         divName + '\', ' + obj.lastMonth + ', ' + obj.lastYear +
      ')">&lt;&lt;</a>';

   var next =
      '<a href="javascript:drawCalendar(\'' +
         divName + '\', ' + obj.nextMonth + ', ' + obj.nextYear +
      ')">&gt;&gt;</a>';

   var html =
      '<table border="0">' +
      ' <tr>' +
      '  <td>' + previous + '</td>' +
      '  <td align="center">' + obj.display + '</td>' +
      '  <td>' + next + '</td>' +
      ' </tr>' +
      ' <tr>' +
      '  <td colspan="3">' +
      '   <table border="0">' +
      '    <tr>' +
      '     <th>Su</th>' +
      '     <th>Mo</th>' +
      '     <th>Tu</th>' +
      '     <th>We</th>' +
      '     <th>Th</th>' +
      '     <th>Fr</th>' +
      '     <th>Sa</th>' +
      '    </tr>';

   for(var i = 0; i < obj.entries.length; i ++)
   {
      var row = "<tr>";

      for(var j = 0; j < obj.entries[i].length; j ++)
      {
         var e = obj.entries[i][j];
         var s = (e.month == month && e.year == year ? e.day : "&nbsp");

         row += "<td>" + s + "</td>";
      }

      row  += "</tr>";
      html += row;
   }

   html += "   </table>";
   html += "  </td>";
   html += " </td>";
   html += "</table>";
   html += "<table>";
   html += "<tr>";
   html += "<td>";
/*   html += "this is a test";
   html += "</td>";
   html += "</tr>";
   html += "</table>"; */

   d.innerHTML = html;
}

function doCalendar(divName)
{
   var d = new Date();
   drawCalendar(divName, d.getMonth() + 1, d.getFullYear());
}
