/*
 * UDCalendarView
 *
 * Javascript calendar view creation and management.  Links to webevent calendars
 * by default.
 *
 * Copyright (c) 2008
 * Jeffrey T Frey
 * Network & Systems Services, University of Delaware
 *
 * $Id: UDCalendarView.js,v 1.1 2008/10/10 15:40:07 frey Exp $
 *
 */

/*!
  @class UDTabGroup
  
  A Javascript "class" that creates and manages a calendar view which displays a
  month at a time and features month-based navigation controls.  The panes of days
  of the month link to the WebEvent calendaring system by default.  The CSS is
  written in such a way that the calendar scales appropriately to whatever font
  size the user has chosen in his/her browser.
  
  Adding a calendar is very easy.  In your HTML you must create an empty container
  into which the class will introduce the calendar's HTML structure.  This typically
  means using a <div> with a unique id attribute:
  
    <div id="myCalendarDiv"></div>
    
  You then create the calendar using Javascript a'la
  
    myCalendarObj = new UDCalendarView(
                            document.getElementById("myCalendarDiv"),
                            "1021",
                            "Academic Calendar"
                          );

  The first argument is the actual container element into which the calendar should be inserted.  The calendar is inserted by appending document objects to the container -- so the calendar will appear _after_ whatever else is inside that container already.
  
  The second argument is the WebEvent calender identifier to which you wish the calendar days to be linked.  The third argument is optional: pass a textual description of the WebEvent calendar you are linking to.  If the third argument is provided you will see a tooltip displayed when the user hovers the mouse over the calendar view.
*/
function UDCalendarView(
  insertIntoElement,
  webeventCalId,
  webeventCalName
)
{
  return this.init(insertIntoElement, webeventCalId, webeventCalName);
}

UDCalendarView.prototype = {

  init:function(
    insertIntoElement,
    webeventCalId,
    webeventCalName
  )
  {
    var self = this;
    
    this._showMonth = new Date();
    this._webeventCalId = webeventCalId;
    
    this._dayNames = new Array( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" );
    this._monNames = new Array( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" );
    
    /* Create the calendar wrapper: */
    this._calendarDiv = document.createElement("div");
    this._calendarDiv.className = "UDCalendarView";
    if ( webeventCalName && webeventCalName.length ) {
      this._calendarDiv.setAttribute("title", webeventCalName);
    }
    insertIntoElement.appendChild(this._calendarDiv);
    
    /* Create the title: */
    this._titleDiv = document.createElement("div");
    this._titleDiv.className = "UDCalendarViewTitle";
    this._calendarDiv.appendChild(this._titleDiv);
    
    /* Create the toolbar: */
    this._toolbarDiv = document.createElement("div");
    this._toolbarDiv.className = "UDCalendarViewToolbar";
    this._calendarDiv.appendChild(this._toolbarDiv);
    
      /* Add the toolbar buttons: */
      button = document.createElement("div");
      button.innerHTML = "«";
      button.className = "UDCalendarViewButton UDCalendarViewFlushLeft";
      button.onclick = function() { self.goToPrevYear(); }
      this._toolbarDiv.appendChild(button);
      
      button = document.createElement("div");
      button.innerHTML = "‹";
      button.className = "UDCalendarViewButton UDCalendarViewFlushLeft";
      button.onclick = function() { self.goToPrevMonth(); }
      this._toolbarDiv.appendChild(button);
      
      button = document.createElement("div");
      button.innerHTML = "Today";
      button.className = "UDCalendarViewButton UDCalendarViewButtonToday";
      button.onclick = function() { self.goToToday(); }
      this._toolbarDiv.appendChild(button);
      
      button = document.createElement("div");
      button.innerHTML = "»";
      button.className = "UDCalendarViewButton UDCalendarViewFlushRight";
      button.onclick = function() { self.goToNextYear(); }
      this._toolbarDiv.appendChild(button);
      
      button = document.createElement("div");
      button.innerHTML = "›";
      button.className = "UDCalendarViewButton UDCalendarViewFlushRight";
      button.onclick = function() { self.goToNextMonth(); }
      this._toolbarDiv.appendChild(button);
    
    /* Add the column headers: */
    this._colHeadersDiv = document.createElement("div");
    this._colHeadersDiv.className = "UDCalendarViewColHeaders";
    this._calendarDiv.appendChild(this._colHeadersDiv);
    
      /* Add the names of the days: */
      for ( i = 0 ; i < 7 ; i++ ) {
        pane = document.createElement("div");
        pane.innerHTML = this._dayNames[i];
        this._colHeadersDiv.appendChild(pane);
      }
    
    /* Add the week area: */
    this._weeksDiv = document.createElement("div");
    this._calendarDiv.appendChild(this._weeksDiv);
    
    /* Force a redraw of the week view: */
    this.__refreshView();
  },
  
  /*!
    @function setDateForView
    
    Manually set the date you wish to be displayed on the calendar.  Of course,
    whatever Date object you pass, only the month and year are truly important.
    
    Refreshes the display state of the calendar as well.
  */
  setDateForView:function(
    aDate
  )
  {
    /* Make our own copy of the date, don't just use the one that was
       passed to us: */
    this._showMonth = new Date();
    this._showMonth.setTime( aDate.getTime() );
    this.__refreshView();
  },
  
  /*!
    @function goToPrevYear
    
    Move the displayed calendar back one year to the month.
    
    Refreshes the display state of the calendar as well.
  */
  goToPrevYear:function()
  {
    this._showMonth.setDate(1);
    this._showMonth.setFullYear( this._showMonth.getFullYear() - 1 );
    this.__refreshView();
  },

  /*!
    @function goToPrevMonth
    
    Move the displayed calendar back one month.
    
    Refreshes the display state of the calendar as well.
  */
  goToPrevMonth:function()
  {
    this._showMonth.setDate(1);
    this._showMonth.setMonth( this._showMonth.getMonth() - 1 );
    this.__refreshView();
  },

  /*!
    @function goToToday
    
    Move the displayed calendar to the month and year containing today's
    date.
    
    Refreshes the display state of the calendar as well.
  */
  goToToday:function()
  {
    this._showMonth.setDate(1);
    this._showMonth = new Date();
    this.__refreshView();
  },

  /*!
    @function goToNextMonth
    
    Move the displayed calendar forward one month.
    
    Refreshes the display state of the calendar as well.
  */
  goToNextMonth:function()
  {
    this._showMonth.setDate(1);
    this._showMonth.setMonth( this._showMonth.getMonth() + 1 );
    this.__refreshView();
  },
  
  /*!
    @function goToNextYear
    
    Move the displayed calendar forward one year to the month.
    
    Refreshes the display state of the calendar as well.
  */
  goToNextYear:function()
  {
    this._showMonth.setDate(1);
    this._showMonth.setFullYear( this._showMonth.getFullYear() + 1 );
    this.__refreshView();
  },
  
  /*!
    @function respondToClick
    
    Event handler which will be called when the user clicks on an active
    day pane in the calender.  This implementation navigates to the chosen
    WebEvent calendar.
    
    The single parameter coming in to the function is a reference to the
    <div> which was clicked.
    
    Override this function if you wish to change the behavior of the
    class.
  */
  respondToClick:function(
    clickedPane
  )
  {
    var url = "http://www.udel.edu/webevent/" + this._webeventCalId + "/" + this._showMonth.getFullYear();
    
    /* Add the month: */
    var mon = this._showMonth.getMonth() + 1;
    url += ( mon < 10 ? "0" + mon : mon );
    
    /* Add the day-of-month component: */
    var day = parseInt(clickedPane.innerHTML);
    url += ( day < 10 ? "0" + day : day );
    
    window.location = url;
  },
  
  /*
   * Private functions:
   */
  __refreshView:function()
  {
    var self = this;
    
    /* Make sure we have a copy of today's day number if the year and month
       match the current: */
    var   now = new Date();
    var   todaysDayNum = 0;
    
    if ( (now.getMonth() == this._showMonth.getMonth()) && (now.getFullYear() == this._showMonth.getFullYear()) ) {
      todaysDayNum = now.getDate();
    }
    
    /* Set the title: */
    this._titleDiv.innerHTML = this._monNames[ this._showMonth.getMonth() ] + " " + this._showMonth.getFullYear();
    
    /* Write the array of weeks: */
    this._weeksDiv.innerHTML = "";
    
    /* Which day does the month start on? */
    firstBlock = (this._showMonth.getDay() - ( this._showMonth.getDate() % 7 ) + 8) % 7;
    
      var day,week,i,dayNum = 1,lastDayNum = 31;
      
      /* Figure out the last day of the month: */
      day = new Date();
      day.setTime(this._showMonth.getTime());
      day.setDate(lastDayNum);
      while ( day.getMonth() != this._showMonth.getMonth() ) {
        day = new Date();
        day.setTime(this._showMonth.getTime());
        day.setDate(--lastDayNum);
      }
      
      /* First week: */
      week = document.createElement("div");
      week.className = "UDCalendarViewWeek";
      i = 0;
      while ( i < firstBlock ) {
        day = document.createElement("div");
        week.appendChild(day);
        i++;
      }
      while ( i < 7 ) {
        day = document.createElement("div");
        day.className = ( dayNum == todaysDayNum ? "UDCalendarViewDayPane UDCalendarViewDayPaneToday" : "UDCalendarViewDayPane" );
        day.innerHTML = dayNum++;
        day.onclick = function() { self.respondToClick(this); }
        i++;
        week.appendChild(day);
      }
      this._weeksDiv.appendChild(week);
    
      /* Remaining weeks: */
      while ( dayNum <= lastDayNum ) {
        week = document.createElement("div");
        week.className = "UDCalendarViewWeek";
        i = 0;
        while ( (i < 7) && (dayNum <= lastDayNum) ) {
          day = document.createElement("div");
          day.className = ( dayNum == todaysDayNum ? "UDCalendarViewDayPane UDCalendarViewDayPaneToday" : "UDCalendarViewDayPane" );
          day.innerHTML = dayNum++;
          day.onclick = function() { self.respondToClick(this); }
          i++;
          week.appendChild(day);
        }
        while ( i < 7 ) {
          day = document.createElement("div");
          dayNum++;
          i++;
          week.appendChild(day);
        }
        this._weeksDiv.appendChild(week);
      }
  }

}
