  CalendarWidget = function (boxName, funcRef) {
//  boxName, funcRef, cellClass, selectedCellClass
  var params = new Array();
  for (var i = 2; i < arguments.length; i += 2) {
    params[arguments[i]] = arguments[i+1];
  }
  this._box_name = boxName;
  this._function = funcRef;
  this._box = document.getElementById(this._box_name);
  this._now = params['startDate'] || new Date();
  this._curdate = this._now;
  this._selecteddate;
  this._selectedcell;
  this._nextdate;
  this._selectedclass = params['selectedCellClass'] || '';
  this._normalclass = params['cellClass'] || '';
  CalendarWidget.prototype._instance_hash[this._box_name] = this;
  Date.prototype._espressoDays = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
  Date.prototype._espressoMonths = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
  Date.prototype.toEspressoString = function () {
    try {
      return this._espressoDays[this.getDay()] +'&nbsp;'+
        this.getDate() +'&nbsp;'+
        this._espressoMonths[this.getMonth()] +'&nbsp;'+
        this.getFullYear();
    }
    catch (error) {
      alert('Error in Date.prototype.toEspressoString: ' + error);
    }
  };
 };
 
 CalendarWidget.prototype['_instance_hash'] = {}; 
 CalendarWidget.prototype['get_instance'] = function (boxName) {
  return CalendarWidget.prototype._instance_hash[boxName];
 }
 
 CalendarWidget.prototype['render'] = function () {
  this._box.innerHTML = this.get_box_html();
  var monthSelect = document.getElementById(this.get_month_select_name());
  monthSelect.selectedIndex = this._now.getMonth();
  this.render_days(this._now);
 }
CalendarWidget.prototype['render_days'] = function (renderDate) {
  
  var startOfMonth = new Date(renderDate.getFullYear(), renderDate.getMonth(), 1);
  var offset = (startOfMonth.getDay()) * 86400 * 1000;
  startDate = new Date(startOfMonth.getTime() - offset);
  var count = 0;
  for (var y=1; y <= 6; y++) {
    for (var x=0; x <= 6; x++) {
      var cell = document.getElementById(this._box_name +'.row'+ y +'_cell'+x);
      var offset = count * 86400 * 1000;
      var thisDay = new Date(startDate.getTime() + offset);
      if (thisDay.getMonth() == renderDate.getMonth()) {
        if (thisDay.getDate() == this._now.getDate() && thisDay.getMonth() == this._now.getMonth() && thisDay.getFullYear() == this._now.getFullYear())
        {
          cell.innerHTML = '<a href="javascript:CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').selectDate(new Date('+ thisDay.getTime() +'), \''+ this._box_name +'.row'+ y +'_cell'+ x +'\');"><b>'+ thisDay.getDate() +'</b></a>';
        }
        else {
          cell.innerHTML = '<a href="javascript:CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').selectDate(new Date('+ thisDay.getTime() +'), \''+ this._box_name +'.row'+ y +'_cell'+ x +'\');">'+ thisDay.getDate() +'</a>';
        }
        
        if (this._selecteddate && thisDay.getDate() == this._selecteddate.getDate() && thisDay.getMonth() == this._selecteddate.getMonth() && thisDay.getFullYear() == this._selecteddate.getFullYear()) {
          cell.className = this._selectedclass;
        }
        else {
          cell.className = this._normalclass;
        }
      }
      else {
        cell.innerHTML = thisDay.getDate();
          cell.className = '';
      }
      count++;
    }
  }
}
CalendarWidget.prototype['selectDate'] = function (selectedDate, cellName) {
  this._selecteddate = selectedDate;
  var selectedCell = document.getElementById(cellName);
  selectedCell.className = this._selectedclass;
  if (this._selectedcell) this._selectedcell.className = this._normalclass;
  this._selectedcell = selectedCell;
  this._function(selectedDate);
}

CalendarWidget.prototype['changeYear'] = function (offset) {
  this._curdate = new Date(this._curdate.getFullYear() + offset, this._curdate.getMonth(), this._curdate.getDate());
  document.getElementById(this.get_year_name()).innerHTML = this._curdate.getFullYear();
  this.render_days(this._curdate);
}
CalendarWidget.prototype['changeMonth'] = function (month) {
  this._curdate = new Date(this._curdate.getFullYear(), month, this._curdate.getDate());
  this.render_days(this._curdate);
}
CalendarWidget.prototype['shiftMonth'] = function (offset) {
  var monthSelect = document.getElementById(this.get_month_select_name());
  var month = monthSelect.selectedIndex + offset;
  if (month >= 0 && month <= 11) {
    monthSelect.selectedIndex = month;
    this.changeMonth(month);
  }
}
 
CalendarWidget.prototype['get_box_html'] = function () {
  return '<table border="0" class="borderlight" bgcolor="#f1f1f1">'
  +'  <tbody>'
  +'    <tr>'
  +'      <td>'
  +'<table border="0">'
  +'  <tbody>'
  +'    <tr>'
  +'      <td><a href="javascript:CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').changeYear(-1);">&laquo;</a></td>'
  +'      <td><a href="javascript:CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').shiftMonth(-1);">&lt;</a></td>'
  +'      <td>'
  +'        <select onchange="CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').changeMonth(this.selectedIndex);" id="'+ this.get_month_select_name() +'" class="form">'
  +'          <option value="0">January</option>'
  +'          <option value="1">February</option>'
  +'          <option value="2">March</option>'
  +'          <option value="3">April</option>'
  +'          <option value="4">May</option>'
  +'          <option value="5">June</option>'
  +'          <option value="6">July</option>'
  +'          <option value="7">August</option>'
  +'          <option value="8">September</option>'
  +'          <option value="9">October</option>'
  +'          <option value="10">November</option>'
  +'          <option value="11">December</option>'
  +'        </select>'
  +'      </td>'
  +'      <td id="'+ this.get_year_name() +'">'+ this._now.getFullYear() +'</td>'
  +'      <td><a href="javascript:CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').shiftMonth(1);">&gt;</a></td>'
  +'      <td><a href="javascript:CalendarWidget.prototype.get_instance(\''+ this._box_name +'\').changeYear(1);">&raquo;</a></td>'
  +'    </tr>'
  +'  </tbody>'
  +'</table>'
  +'      </td>'
  +'    </tr>'
  +'    <tr>'
  +'      <td align="center">'
  +'<table border="0" class="borderlight" bgcolor="#FFFFFF">'
  +'  <tbody>'
  +'    <tr>'
  +'      <td>Sun</td>'
  +'      <td>Mon</td>'
  +'      <td>Tue</td>'
  +'      <td>Wed</td>'
  +'      <td>Thu</td>'
  +'      <td>Fri</td>'
  +'      <td>Sat</td>'
  +'    </tr>'
  
  +'    <tr>'
  +'      <td id="'+ this._box_name +'.row1_cell0"></td>'
  +'      <td id="'+ this._box_name +'.row1_cell1"></td>'
  +'      <td id="'+ this._box_name +'.row1_cell2"></td>'
  +'      <td id="'+ this._box_name +'.row1_cell3"></td>'
  +'      <td id="'+ this._box_name +'.row1_cell4"></td>'
  +'      <td id="'+ this._box_name +'.row1_cell5"></td>'
  +'      <td id="'+ this._box_name +'.row1_cell6"></td>'
  +'    </tr>'
  +'    <tr>'
  +'      <td id="'+ this._box_name +'.row2_cell0"></td>'
  +'      <td id="'+ this._box_name +'.row2_cell1"></td>'
  +'      <td id="'+ this._box_name +'.row2_cell2"></td>'
  +'      <td id="'+ this._box_name +'.row2_cell3"></td>'
  +'      <td id="'+ this._box_name +'.row2_cell4"></td>'
  +'      <td id="'+ this._box_name +'.row2_cell5"></td>'
  +'      <td id="'+ this._box_name +'.row2_cell6"></td>'
  +'    </tr>'
  +'    <tr>'
  +'      <td id="'+ this._box_name +'.row3_cell0"></td>'
  +'      <td id="'+ this._box_name +'.row3_cell1"></td>'
  +'      <td id="'+ this._box_name +'.row3_cell2"></td>'
  +'      <td id="'+ this._box_name +'.row3_cell3"></td>'
  +'      <td id="'+ this._box_name +'.row3_cell4"></td>'
  +'      <td id="'+ this._box_name +'.row3_cell5"></td>'
  +'      <td id="'+ this._box_name +'.row3_cell6"></td>'
  +'    </tr>'
  +'    <tr>'
  +'      <td id="'+ this._box_name +'.row4_cell0"></td>'
  +'      <td id="'+ this._box_name +'.row4_cell1"></td>'
  +'      <td id="'+ this._box_name +'.row4_cell2"></td>'
  +'      <td id="'+ this._box_name +'.row4_cell3"></td>'
  +'      <td id="'+ this._box_name +'.row4_cell4"></td>'
  +'      <td id="'+ this._box_name +'.row4_cell5"></td>'
  +'      <td id="'+ this._box_name +'.row4_cell6"></td>'
  +'    </tr>'
  +'    <tr>'
  +'      <td id="'+ this._box_name +'.row5_cell0"></td>'
  +'      <td id="'+ this._box_name +'.row5_cell1"></td>'
  +'      <td id="'+ this._box_name +'.row5_cell2"></td>'
  +'      <td id="'+ this._box_name +'.row5_cell3"></td>'
  +'      <td id="'+ this._box_name +'.row5_cell4"></td>'
  +'      <td id="'+ this._box_name +'.row5_cell5"></td>'
  +'      <td id="'+ this._box_name +'.row5_cell6"></td>'
  +'    </tr>'
  +'    <tr>'
  +'      <td id="'+ this._box_name +'.row6_cell0"></td>'
  +'      <td id="'+ this._box_name +'.row6_cell1"></td>'
  +'      <td id="'+ this._box_name +'.row6_cell2"></td>'
  +'      <td id="'+ this._box_name +'.row6_cell3"></td>'
  +'      <td id="'+ this._box_name +'.row6_cell4"></td>'
  +'      <td id="'+ this._box_name +'.row6_cell5"></td>'
  +'      <td id="'+ this._box_name +'.row6_cell6"></td>'
  +'    </tr>'
  +'  </tbody>'
  +'</table>'
  +'      </td>'
  +'    </tr>'
  +'  </tbody>'
  +'</table>'
 }
 
 CalendarWidget.prototype['get_month_select_name'] = function () {
  return 'CalendarWidget.month.'+ this._box_name;
 }
 CalendarWidget.prototype['get_year_name'] = function () {
  return 'CalendarWidget.year.'+ this._box_name;
 }

 CalendarWidget.prototype['refresh'] = function (date) {
   this._curdate = date;
   this._now = this._curdate;
   document.getElementById(this.get_year_name()).innerHTML = this._curdate.getFullYear();
   var monthSelect = document.getElementById(this.get_month_select_name());
   monthSelect.selectedIndex = this._curdate.getMonth();
   this.render_days(this._curdate);
   return this._curdate;
 }


