/**
 * @(#)$Id: calendar.js,v 1.12 2011/08/09 08:25:38 sergiot-cocha Exp $
 *
 * Calendar extension to prototype / script.aculo.us
 *
 * (C)opyright OpenJaw Technologies Ltd. 2009
 *
 * script.aculo.us is freely distributable under the terms of an MIT-style license.
 * For details, see the script.aculo.us web site: http://script.aculo.us/
 *
 * Sample use:
 *    <span>
 *     <input type="text" value="" id="cal-test"/>
 *     <input type="hidden" value="2009-01-01" id="cal-value"/>
 *   </span>
 *
 *   <script type="text/javascript" language="javascript">
 *     function myCallback(calendar) {
 *       var date = calendar.getDate();
 *       var formatted = calendar.formatOTADate(date);
 *       alert(formatted);
 *     }
 *     new OpenJaw.Calendar('cal-test', 'cal-value', { onChoose: myCallback });
 *   </script>
 *
 *
 *
 * Rendered by: xsl/OpenJaw/Calendar.xsl
 */

OpenJaw.Calendar = Class.create();

OpenJaw.Calendar.Frame = null;
OpenJaw.Calendar.Container = null;
OpenJaw.Calendar.Calendar1 = null;
OpenJaw.Calendar.Calendar2 = null;
OpenJaw.Calendar.Calendar3 = null;
OpenJaw.Calendar.Calendar4 = null;
OpenJaw.Calendar.AnyRow = null;
OpenJaw.Calendar.AnyBtn = null;
OpenJaw.Calendar.ClockRow = null;
OpenJaw.Calendar.ClockField = null;
OpenJaw.Calendar.PrevMonth = null;
OpenJaw.Calendar.ThisMonth1 = null;
OpenJaw.Calendar.ThisMonth2 = null;
OpenJaw.Calendar.ThisMonth3 = null;
OpenJaw.Calendar.ThisMonth4 = null;
OpenJaw.Calendar.NextMonth = null;
OpenJaw.Calendar.PrevMonthImg = null;
OpenJaw.Calendar.NextMonthImg = null;
OpenJaw.Calendar.Grid1 = null;
OpenJaw.Calendar.Grid2 = null;
OpenJaw.Calendar.Grid3 = null;
OpenJaw.Calendar.Grid4 = null;
OpenJaw.Calendar.Months = 1;



OpenJaw.Calendar.Format = '%d %m %Y';

Object.extend(Object.extend(OpenJaw.Calendar.prototype, OpenJaw.Dialog.prototype), {

  // The field that is visible to the user.
  // The format of the displayed date is that of the 'format' property.
  input_field: null,
  input_field_style: null,
  // The hidden field that holds the date in OTA format.
  value_field: null,
  // Keeps record of the last used date when a field is disabled.
  stored_value: '',		  

  // The currently selected date.
  date: null,
  
  // The number of days in the future to be enabled
  dateRange:null,
  
  // The furthest date to be enabled, calculated based on furthestDate
  furthestDate:null,
  
  // The currently visible month.
  month: null,
  // Stores state of the calendar dialog
  visible: false,
  // Calendars that must have a date after this calendar.
  following: null,
  // Reference to clock that is paired with this calendar
  clock: null,
  // Reference to simple clock, displayed in calendar popup div.
  simpleClock: null,

  anybutton: null,

  /**
   * Constructs a new calendar picker dialog.
   * @param input_field The date-field that is visible to the user.
   * @param value_field The hidden date-field that holds the date value (OTA-format)
   * @option months Array of month strings (for visible input field).
   * @option format Format for date shown in visible input field.
   * @option showPastDates Allow past dates to be selected (true/false)?
   * @option onChoose Function called when a date is selected. A reference to
   *     an object of this class is the only parameter (see getDate()).
   * @option dateRange The number of days in the future that the calendar should be displayed for
   * @anyOn (true/false) Show "match any" button in calendar popup.
   * @simpleClock (true/false) Show clock input in calendar popup.
   */
  initialize: function(input_field, value_field, options) {
	

    // Initialise some global element references.
    if (OpenJaw.Calendar.Frame == null)
      OpenJaw.Calendar.Frame = $('calendar-container-iframe');
    if (OpenJaw.Calendar.Container == null)
      OpenJaw.Calendar.Container = $('calendar-container');
    if (OpenJaw.Calendar.Calendar1 == null) {
      OpenJaw.Calendar.Calendar1 = $('calendar-1');
      OpenJaw.Calendar.Calendar2 = $('calendar-2');
      OpenJaw.Calendar.Calendar3 = $('calendar-3');
      OpenJaw.Calendar.Calendar4 = $('calendar-4');
    }
    if (OpenJaw.Calendar.AnyRow == null)
      OpenJaw.Calendar.AnyRow = $('calendar-anyrow');
    if (OpenJaw.Calendar.AnyBtn == null)
      OpenJaw.Calendar.AnyBtn = $('calendar-anybutton');
    if (OpenJaw.Calendar.ClockRow == null)
      OpenJaw.Calendar.ClockRow = $('calendar-clockrow');
    if (OpenJaw.Calendar.ClockField == null)
      OpenJaw.Calendar.ClockField = $('calendar-clock');
    if (OpenJaw.Calendar.PrevMonth == null)
      OpenJaw.Calendar.PrevMonth = $('calendar-prev-month');
    if (OpenJaw.Calendar.ThisMonth1 == null) {
      OpenJaw.Calendar.ThisMonth1 = $('calendar-this-month-1');
      OpenJaw.Calendar.ThisMonth2 = $('calendar-this-month-2');
      OpenJaw.Calendar.ThisMonth3 = $('calendar-this-month-3');
      OpenJaw.Calendar.ThisMonth4 = $('calendar-this-month-4');
    }
    if (OpenJaw.Calendar.NextMonth == null)
      OpenJaw.Calendar.NextMonth = $('calendar-next-month');
    if (OpenJaw.Calendar.PrevMonthImg == null)
      OpenJaw.Calendar.PrevMonthImg =  $('calendar-prev-month-img');
    if (OpenJaw.Calendar.NextMonthImg == null)
      OpenJaw.Calendar.NextMonthImg = $('calendar-next-month-img');
    if (OpenJaw.Calendar.Grid1 == null) {
      OpenJaw.Calendar.Grid1 = $('calendar-grid-1');
      OpenJaw.Calendar.Grid2 = $('calendar-grid-2');
      OpenJaw.Calendar.Grid3 = $('calendar-grid-3');
      OpenJaw.Calendar.Grid4 = $('calendar-grid-4');
    }

    // Input field that displays the date.
    // Clicks on this field will open the calendar.
    this.input_field = $(input_field);
    // Hidden field with the date in OTA-format.
    this.value_field = $(value_field);
    this.value_field.objRef = this;

    if (this.input_field == null) throw('Calendar input field "'+input_field+'" does not exist!');

    if (this.value_field == null) throw('Calendar value field "'+value_field+'" does not exist!');

    this.input_field_style = this.input_field.style.color;

    // Parse other init options.
    this.setOptions(options);
    // For now we'll assume that the calendar is enabled.
    this.any = false;

    // This array will hold a list of calendars whose dates must be
    // equal to or after this calendar's selected date.
    this.following = new Array();
 
    // Get the selected date from the options if not set.
    if ((this.options.date != null) && (this.options.date.length >= 10)) {
      this.date = this.parseOTADate(this.options.date);
      this.value_field.value = this.options.date;
    }
    // Otherwise get it from the value field.
    else if (this.value_field.value.length >= 10) {
      this.date = this.parseOTADate(this.value_field.value);
    }
    
    this.date.setTime(this.date.getTime() + (12 * 60 * 60 * 1000)); // Add 12 hours
    
    //  Disable dates beyond a certain range
    // Get the furthest allowable date from the options if not set.
    if ((this.options.dateRange != null) ) {
      this.furthestDate = this.addCalendarDays(new Date,this.options.dateRange);
    }
    
    // Or if that isn't set either use today's date.
    else {
      this.any = true;
      this.date = new Date();
      this.value_field.value = this.formatOTADate(this.date);
    }
	
    // Display date value in visible input field.
    this.input_field.value = this.formatDate(this.date);

    this.container = this.input_field;

    // Create onClick and onKeyPress hooks for the visible input field.
    this.input_field.onclick = function() { this.show() }.bind(this);
    this.input_field.onkeypress = function() { this.show() }.bind(this);

    // If the calendar can be enabled/disabled by clicks on images, divs
    // or something else we'll create hooks for the any on/off gizmos.
    if (this.options.anyOn == true) {
      // Enable or disable the calendar depending on the date that was
      // passed to us from the caller
      if (this.any == true) {
	this.disable(true);
      }
      else {
	this.enable(true);
      }
    }
    // If no any on/off controls are used the calendar must be enabled.
    else {
      this.any = false;
    }

    if (this.options.simpleClock == true) {
      var opts = { };
      opts.onChoose = function() {
	this.chooseClock(this);
      }.bind(this);
      this.simpleClock = new OpenJaw.SimpleClock(OpenJaw.Calendar.ClockField, opts);
    }
  },

  dispose: function() {
    if (this.simpleClock != null) {
      this.simpleClock.dispose();
    }
  },

  onKeyPress: function(event) {
    var e = Event.element(event);
    if (e == OpenJaw.Calendar.Container) {
      if (this.options.onKeyPress != null)
	this.options.onKeyPress(event, this);
    }
  },

  onBlur: function(event) {
    if (this.simpleClock != null) {
      var date = this.value_field.value;
      date = date.substring(0, 10);
      this.value_field.value = date + 'T' + this.simpleClock.getTime();
    }

    // Check if we have dependent calendars to update
    this.checkDependantCalendars();

    // Call the user-defined callback.
    if (this.options.onChoose != null) {
      this.options.onChoose(this);
    }

    // Close the calendar
    this.close();
  },

  /**
   * Parses options passed to the constructor.
   */
  setOptions: function(options) {
    this.options = {
      monthsShort:   OpenJaw.Calendar.MonthsShort, 
      monthsLong:    OpenJaw.Calendar.MonthsLong, 
      format:        OpenJaw.Calendar.Format,
      date:          null,
      anyOn:         false,
      allowPastDates: false,
      onChoose: null,
      dateRange: null
    }
    Object.extend(this.options, options || {});
  },

  setClock: function(clock) {
    this.clock = clock;
    if (this.any == true) {
      this.clock.disable();
    }
    else {
      this.clock.enable();
      var date = this.formatOTADate(this.date);
      var time = this.clock.getTime();
      this.value_field.value = date + 'T' + time;
    }
  },

  getClock: function() {
    return this.clock;
  },

  disable: function(init) {
    this.close();
    this.any = true;
    this.input_field.style.color = '#b0b0b0';

    if (this.clock != null || this.simpleClock != null) {
      this.stored_value = this.value_field.value.substring(0, 10);
    }
    else {
      this.stored_value = this.value_field.value;
    }
    this.value_field.value = '';

    if (this.clock != null) this.clock.disable();

    this.value_field.value = '';

    // Call the user-defined callback.
    if (init != true && this.options.onChoose != null) {
      this.options.onChoose(this);
    }
  },

  enable: function(init) {
    this.close();
    this.any = false;
    this.input_field.style.color = this.input_field_style;

    if (init != true) {
      if (this.simpleClock != null) {
	this.value_field.value = this.stored_value + 'T' + this.simpleClock.getTime();
      }
      else if (this.clock != null) {
	this.value_field.value = this.stored_value + 'T' + this.clock.getTime();
      }
      else {
	this.value_field.value = this.stored_value;
      }
    }

    if (this.clock != null) this.clock.enable();
    // Call the user-defined callback.
    if (init != true && this.options.onChoose != null) {
      this.options.onChoose(this);
    }
  },

  /**
   * Returns the date currently selected by this calendar.
   */
  getDate: function() {
    if (this.any)
      return null;
    else
      return this.date;
  },

  setOTADate: function(ota) {
    if ((ota == null) || (ota.length < 8)) {
      this.setDate(new Date());
      if (this.clock != null) {
	this.clock.setTime('00:00');
	this.clock.refresh();
      }
      else if (this.simpleClock != null) {
	this.simpleClock.setTime('00:00');
      }
    }
    else {
      this.date = this.parseOTADate(ota);
      // If the date is non-blank we have to make sure the visible
      // input field is enabled.
      this.enable();
      this.value_field.value = ota;
      // Check if we have dependent calendars to update
      this.checkDependantCalendars();
      // Update the displayed date in the visible input field.
      this.refresh();
      // Update attached clock
      if (this.clock != null) {
	this.clock.setTime(ota.substring(11));
	this.clock.refresh();
      }
      else if (this.simpleClock != null) {
	this.simpleClock.setTime(ota.substring(11));
      }
    }
  },

  getOTADate: function() {
    return this.value_field.value;
  },

  /**
   * Sets the calendars date without changing the controls.
   */
  setDateValue: function(date) {
    this.value_field.value = date;

    if ((date == null) || (date == '')) {
      this.date = new Date();
    }
    else {
      this.date = this.parseOTADate(date);
    }

    if (this.clock != null) {
      if ((date != null) && (date.length > 10)) {
	this.clock.setTime(date.substring(11));
      }
      else {
	this.clock.setTime('00:00');
      }
    }
    else if (this.simpleClock != null) {
      if ((date != null) && (date.length > 10)) {
	this.simpleClock.setTime(date.substring(11));
      }
      else {
	this.simpleClock.setTime('00:00');
      }
    }
  },

  /**
   * Updates this calendar's currently selected date.
   */
  setDate: function(date) {
    if (date == null) {
      // If date is blank we'll disable the visible input field.
      // This function will also clear the hidden input field.
      // We'll leave current text in visible input field.
      this.disable();
    }
    else {
      this.date = date;
      // If the date is non-blank we have to make sure the visible
      // input field is enabled.
      this.enable();
      if (this.clock != null) {
	var date = this.formatOTADate(this.date);
	var time = this.clock.getTime();
	this.value_field.value = date + 'T' + time;
      }
      else if (this.simpleClock != null) {
	var date = this.formatOTADate(this.date);
	var time = this.simpleClock.getTime();
	this.value_field.value = date + 'T' + time;
      }
      else {
	this.value_field.value = this.formatOTADate(this.date);
      }
      // Check if we have dependent calendars to update
      this.checkDependantCalendars();
      // Update the displayed date in the visible input field.
      this.refresh();
      // Update attached clock
      if (this.clock != null) this.clock.refresh();
    }
  },

  setTime: function() {
    if (this.clock != null) {
      var date = this.value_field.value.substring(0, 10);
      var time = this.clock.getTime();
      this.value_field.value = date + 'T' + time;
    }
    else if (this.simpleClock != null) {
      var date = this.value_field.value.substring(0, 10);
      var time = this.simpleClock.getTime();
      this.value_field.value = date + 'T' + time;
    }
  },

  refresh: function() {
    // Update the displayed date in the visible input field.
    this.input_field.value = this.formatDate(this.date);
  },

  /**
   * Adds another calendar to a list of calendars whose date values
   * must be later in time than this calendar's.
   */
  mustBeBefore: function(other) {
    this.following[this.following.length] = other;
  },

  /**
   * Runs through all calendars set by the mustBeBefore() function and
   * updates their dates if they are not after this calendar's.
   */
  checkDependantCalendars: function() {
    // Not much we can do if our own date is not set.
    if (this.any == true) return;
    if (this.date == null) return;

    // Iterate through all dependent calendars.
    for (var i=0; i<this.following.length; i++) {
      var cal = this.following[i];
      if (cal.date == null) return;

      // If our date is not before the other calendar's we'll have to update it.
      if (this.isSameOrBefore(this.date, cal.date) == false) {
	cal.setDate(this.date);
      }
    }
  },

  grep: function(code,list) {
    var result = [];
    for (var i = 0; i < list.length; i++) {
      if (code(list[i])) {
	result.push(list[i]);
      }
    }
    return result;
  },
  
  formatDate: function(date) {
    var result = '' + this.options.format;
    result = result.replace( /%Y/, date.getFullYear());
    result = result.replace( /%m/, this.options.monthsShort[date.getMonth()]);
    result = result.replace( /%d/, date.getDate());
    if (this.options.simpleClock == true) {
      result += ' ';
      if (this.simpleClock == null) {
	result += '00:00';
      }
      else {
	result += this.simpleClock.getTime();
      }
    }
    return result;
  },
 
  parseOTADate: function(ota) {
    if (ota.length < 10) return null;
    var year = ota.substring(0, 4);
    var month = ota.substring(5, 7);
    var day = ota.substring(8, 10);
    return new Date(year, month - 1, day);
  },

  formatOTADate: function(date) {
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();

    var buf = new StringBuffer();
    buf.append(year);
    buf.append('-');
    if (month < 10) buf.append('0');
    buf.append(month);
    buf.append('-');
    if (day < 10) buf.append('0');
    buf.append(day);
    return buf.toString();
  },

  getCalendarCells: function(id) {
    var div = OpenJaw.Calendar.Grid1;
    if (id == 2)
      div = OpenJaw.Calendar.Grid2;
    else if (id == 3)
      div = OpenJaw.Calendar.Grid3;
    else if (id == 4)
      div = OpenJaw.Calendar.Grid4;
    return this.grep( function(i) { return i.className == 'cell' || i.className == 'cell cell-top' || i.className == 'cell cell-left' || i.className == 'cell cell-top cell-left' }, div.getElementsByTagName('span'));
  },
     
  addCalendarDays: function(date, delta) {
    // Get the calendar date 24h before the current date.
    var result = new Date();
    result.setTime(date.getTime() + delta*(24 * 60 * 60 *1000) );
    if (result.getDate() == date.getDate()) {
      // Special case if date had more than 24 hours to it (DST!)
      result.setTime(result.getTime() + (delta > 0 ? 1 : -1 ) *60 * 60 * 1000);
    }
         
    // Clamp the time to the original time:
    result.setHours(date.getHours());
    
    return result;
  },
     
  getDateBefore: function (date) {
    return this.addCalendarDays(date, -1);
  },

  getDateAfter: function(date) {
    return this.addCalendarDays(date, 1);
  },

  getFirstOfMonth: function(date) {
	var result = new Date(date.getFullYear(), date.getMonth(), 1);
	result.setTime(result.getTime() + (12 * 60 * 60 * 1000)); // Add 12 hours
	return result;
  },

  getPrevMonth: function(date) {
    return this.getDateBefore(this.getFirstOfMonth(date));
  },

  getNextMonth: function(date) {
    return this.addCalendarDays(this.getFirstOfMonth(date), 32);
  },

  isSameDate: function(d1,d2) {
    return d1.getDate() == d2.getDate() && d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()
  },

  isBefore: function(d1,d2) { 
  
    if (d1.getFullYear() < d2.getFullYear()) return true;
    if ((d1.getFullYear() == d2.getFullYear()) &&  (d1.getMonth() < d2.getMonth())) return true;
    if ((d1.getFullYear() == d2.getFullYear()) && (d1.getMonth() == d2.getMonth()) && (d1.getDate() < d2.getDate())) return true;
    return false;
  },

  isAfter: function(d1,d2) { 
    if (d1.getFullYear() < d2.getFullYear()) return false;
    if ((d1.getFullYear() == d2.getFullYear()) &&  (d1.getMonth() < d2.getMonth())) return false;
    if ((d1.getFullYear() == d2.getFullYear()) && (d1.getMonth() == d2.getMonth()) && (d1.getDate() < d2.getDate()))return false;
    return true;
  },
    
    isAfterYearMonth: function(d1,d2) { 
    if (d1.getFullYear() < d2.getFullYear()) return false;
    if ((d1.getFullYear() == d2.getFullYear()) &&  (d1.getMonth() < d2.getMonth())) return false;
    return true;
  },

  isSameOrBefore: function(d1, d2) { 
    if (d1.getFullYear() < d2.getFullYear()) return true;
    if ((d1.getFullYear() == d2.getFullYear()) &&  (d1.getMonth() < d2.getMonth())) return true;
    if ((d1.getFullYear() == d2.getFullYear()) && (d1.getMonth() == d2.getMonth()) && (d1.getDate() <= d2.getDate())) return true;
    return false;
  },

  /**
   * Displays a given month in the calendar dialog.
   */
  showMonth: function(month) {
    var m = month;
    for (var i=1; i<=OpenJaw.Calendar.Months; i++) {
      this.showGridMonth(m, i);
      m = this.getNextMonth(m);
    }
    this.month = month;
    this.checkPrevMonth();
    this.checkNextMonth();
  },

  showGridMonth: function(month, index) {
    var first = this.getFirstOfMonth(month);
    var today = new Date;

    // Find the beginning of the calendar.
    var monthdiv = OpenJaw.Calendar.ThisMonth1;
    if (index == 2)
      monthdiv = OpenJaw.Calendar.ThisMonth2;
    else if (index == 3)
      monthdiv = OpenJaw.Calendar.ThisMonth3;
    else if (index == 4)
      monthdiv = OpenJaw.Calendar.ThisMonth4;
    
    // Write out the current month and year.
    monthdiv.innerHTML = this.options.monthsLong[month.getMonth()] + ' ' + month.getFullYear();
         
    // Fill in the day in the upper left corner.
    var curr = this.getDateBefore(first);
    while (curr.getDay() != 1) {
      curr = this.getDateBefore(curr);
    }

    var cells = this.getCalendarCells(index);
    for (var offset = 0; offset < cells.length; offset++) {
      var link = true;
      var span_class = 'calendar-day-normal';

      
      if (this.isSameDate(curr, today)) {
		span_class = 'calendar-day-today';
	}

      if (this.options.allowPastDates == false) {
        if (this.isBefore(curr, today)) {
	  if (curr.getMonth() == month.getMonth()) { 
	    span_class = 'calendar-day-before'; 
          } 
          link = false; 
        }
      }
	  
	  if ((this.isBefore(curr, this.addCalendarDays(today, 2))) && (channel=='B2C'))
	  {	 	  	
		span_class = 'calendar-day-after';
		link = false;
	  }
	  else if ((this.isBefore(curr, this.addCalendarDays(today, 2))) && ((channel=='B2B')&&(document.getElementById("radio_charter")==null)))
	  {	  	
	  	span_class = 'calendar-day-after';
		link = false;
	  }
	  else if ((this.isBefore(curr, this.addCalendarDays(today, 1))) && ((channel=='B2B')&&(document.getElementById("radio_charter").checked==true)))
	  {		
		span_class = 'calendar-day-after';
		link = false;
	  }
	  else if ((this.isBefore(curr, this.addCalendarDays(today, 2))) && ((channel=='B2B')&&(document.getElementById("radio_charter").checked==false)))
	  {	  	
	  	span_class = 'calendar-day-after';
		link = false;
	  }
	  
	  if (curr.getMonth() != month.getMonth()) { span_class = 'calendar-day-other' };
	  
      //  Check if this date is too far in the future
    if (this.furthestDate != null) {
        if (this.isAfter(curr, this.furthestDate)) {
	  if (curr.getMonth() == month.getMonth()) { 
	    span_class = 'calendar-day-after'; 
         } 
          link = false; 
        }
      }

      if (this.isSameDate(curr, this.date)) {
	span_class = 'calendar-day-selected';
      }
	  
         
      // Create the DIV element for the day.
      var div = document.createElement('div');
      div.className = 'box ' + span_class;
      div.innerHTML = curr.getDate();
      div.objRef = curr;

      // Insert the DIV element.
      cells[offset].innerHTML = '';
      cells[offset].appendChild(div);

      // Add the onClick event if the day can be selected.
      if (link) {
        var buf = new StringBuffer();
	buf.append("div.onclick = function() { this.selectDate('");
	buf.append(curr.getFullYear());
	buf.append("','");
	buf.append(curr.getMonth());
	buf.append("','");
	buf.append(curr.getDate());
	buf.append("'); }.bind(this);");
	eval(buf.toString());
      }
      
      curr = this.getDateAfter(curr);
    }
  },

  showPrevMonth: function() {
    OpenJaw.Calendar.PrevMonthImg.style.display = 'inline';
  },

  hidePrevMonth: function() {
    OpenJaw.Calendar.PrevMonthImg.style.display = 'none';
  },

  clickPrevMonth: function() { 
    if (this.checkPrevMonth()) {
      this.showMonth(this.getPrevMonth(this.month)); 
    }
  },

  checkPrevMonth: function() { 
    if (this.options.allowPastDates) {
      this.showPrevMonth();
      return true;
    }

    var today = new Date;
    if ((this.month.getFullYear() == today.getFullYear()) && (this.month.getMonth() <= today.getMonth())) {
      this.hidePrevMonth();
      return false;
    }
    else {
      this.showPrevMonth();
      return true;
    }
  },
     

  showNextMonth: function() {
    OpenJaw.Calendar.NextMonthImg.style.display = 'inline';
  },

  hideNextMonth: function() {
    OpenJaw.Calendar.NextMonthImg.style.display = 'none';
  },

  clickNextMonth: function() {
    this.showPrevMonth();
    this.showMonth(this.getNextMonth(this.month));
  },
  
  //  Don't display arrow to the next month if it is beyond the date range to be displayed
  checkNextMonth: function() { 

    //  Note: this assumes that 2 months are displayed in the calendar.  If more/less, then this code needs to be updated to add that number to the current month
    if (this.isAfterYearMonth(this.furthestDate, this.getNextMonth(this.getNextMonth(this.month)))) {
      this.showNextMonth();
      return true;
    }
    else {
      this.hideNextMonth();
      return false;
    }
  },

  /**
   * This function is called when this calendar is the active one and
   * when the user has picked a new date.
   */
  selectDate: function(year, month, day) {

    // Store the selected date.
    this.date = new Date(year, month, day,12,0,0);

    // Store the value in the hidden field.
    if (this.clock != null) {
      var date = this.formatOTADate(this.date);
      var time = this.clock.getTime();
      this.value_field.value = date + 'T' + time;
    }
    else if (this.simpleClock != null) {
      var date = this.formatOTADate(this.date);
      var time = this.simpleClock.getTime();
      this.value_field.value = date + 'T' + time;
    }
    else {
      this.value_field.value = this.formatOTADate(this.date);
    }
    //this.date.setTime(this.date.getTime() + (12 * 60 * 60 * 1000))
    this.input_field.value = this.formatDate(this.date);

    // Check if we have dependent calendars to update
    this.checkDependantCalendars();

    // Close the calendar
    this.close();

    // Ensure that the calendar and any associated clock are
    // both enabled.
    this.enable(true);

    if (this.options.onChoose != null)
      this.options.onChoose(this);
  },

  chooseClock: function(a, b) {
    var date = this.value_field.value;
    date = date.substring(0, 10);
    this.value_field.value = date + 'T' + this.simpleClock.getTime();

    // Check if we have dependent calendars to update
    this.checkDependantCalendars();

    // Call the user-defined callback.
    if (this.options.onChoose != null) {
      this.options.onChoose(this);
    }

    // Close the calendar
    this.close();
  },

  selectAny: function() {
    this.disable(false);

    // Check if we have dependent calendars to update
    this.checkDependantCalendars();

    // Call the user-defined callback.
    if (this.options.onChoose != null) {
      this.options.onChoose(this);
    }

    // Close the calendar
    this.close();
  },

  /**
   * Displays the calendar widget.
   */
  show: function() {
    if (this.visible) {
      this.close();
      if (this.options.onChoose != null)
	this.options.onChoose(this);
      return;
    }

    var height = 0;

    if (this.options.anyOn == true) {
      if (this.options.simpleClock == true) {
	// Display any-button and clock row
	OpenJaw.Calendar.Frame.style.height = '228px';
	OpenJaw.Calendar.Container.style.height = '226px';
	OpenJaw.Calendar.ClockRow.style.display = '';
	OpenJaw.Calendar.AnyRow.style.display = '';
	height = 228;
      }
      else {
	// Display any-button only.
	OpenJaw.Calendar.Frame.style.height = '210px';
	OpenJaw.Calendar.Container.style.height = '208px';
	OpenJaw.Calendar.ClockRow.style.display = 'none';
	OpenJaw.Calendar.AnyRow.style.display = '';
	height = 210;
      }
    }
    // If no any on/off controls are used the calendar must be enabled.
    else {
      if (this.options.simpleClock == true) {
	// Display clock row only.
	OpenJaw.Calendar.Frame.style.height = '210px';
	OpenJaw.Calendar.Container.style.height = '208px';
	OpenJaw.Calendar.ClockRow.style.display = '';
	OpenJaw.Calendar.AnyRow.style.display = 'none';
	height = 210;
      }
      else {
	// Display no calendar controls.
	OpenJaw.Calendar.Frame.style.height = '186px';
	OpenJaw.Calendar.Container.style.height = '184px';
	OpenJaw.Calendar.ClockRow.style.display = 'none';
	OpenJaw.Calendar.AnyRow.style.display = 'none';
	height = 186;
      }
    }

    var width = 0;
    if (OpenJaw.Calendar.Months == 1) {
      width = 183;
    }
    else if (OpenJaw.Calendar.Months == 2) {
      width =  358;
    }
    else if (OpenJaw.Calendar.Months == 3) {
      width =  533;
    }
    else if (OpenJaw.Calendar.Months == 4) {
      width =  708;
    }

    // Bind the on-click events of the calendar navigation to this calendar instance.
    OpenJaw.Calendar.PrevMonth.onclick = function() { this.clickPrevMonth() }.bind(this);
    OpenJaw.Calendar.NextMonth.onclick = function() { this.clickNextMonth() }.bind(this);
    OpenJaw.Calendar.AnyBtn.onclick = function() { this.selectAny() }.bind(this);
    OpenJaw.Calendar.Container.onkeydown = function(event) { this.onKeyPress(event) }.bind(this);

    // Now connect the current edit to the div:
    this.showMonth(this.date);

    // Find calendar dialog
    var calendar = OpenJaw.Calendar.Container;
        
    // Find lower edge of visible date input field.
    pos = this.getAbsolutePosition(this.input_field);
    if (this.input_field.offsetHeight) {
      pos.y += this.input_field.offsetHeight;
    }
    else {
      pos.y += this.input_field.clientHeight;
    }

    var maxy = document.body.clientHeight - height - 10;
    var maxx = document.body.clientWidth - width - 10;
    if (pos.x > maxx) pos.x = maxx;
    if (pos.y > maxy) pos.y = maxy;

    // Put calendar dialog in position.
    if (document.all) {
      // IE
      calendar.style.posTop = (pos.y + 2) ;
      calendar.style.posLeft = pos.x;
      calendar.style.display = 'block';
                
      var iframe = OpenJaw.Calendar.Frame;
      iframe.style.posTop = calendar.style.posTop;
      iframe.style.posLeft = calendar.style.posLeft;
      iframe.style.display = 'block';
    }
    else {
      // Mozilla
      calendar.style.position = 'absolute';
      calendar.style.top = (pos.y + 2) + 'px';
      calendar.style.left = pos.x + 'px';
      calendar.style.display = 'block';
    }

    this.visible = true;

    OpenJaw.Calendar.Container.focus();
  },

  close: function() {
    OpenJaw.Calendar.Container.style.display = 'none';
    OpenJaw.Calendar.Frame.style.display = 'none';
    OpenJaw.Calendar.Container.onkeydown = null;

    this.visible = false;
  },

  getClass: function() {
    return 'Calendar';
  }

});

