// DateList.js
// -------------------------------------------------------------------------- \\

// DateList Constructor
// -------------------------------------------------------------------------- \\
/*
    Class: DateList
    This class is used to simplify the creation of date list components.
    
    <img:../DateList/DateList.gif>
    
    It can be linked with a <Calendar> component to create a complete DateList+Calendar.
    
    !(*)! Required attributes which must be initialized in the onload function.
    
    
    There are three ways to use this component:
      - One Way Trip.
      - Round Trip.
      - Multi Destination.
      
    Examples:
      - <popup:../DateList/test1.html(name:One Way Trip)(options:location=no, width=600, height=480, menubar=no, status=no, menubar=no)>
      - <popup:../DateList/test2.html(name:Round Trip)(options:location=no, width=600, height=480, menubar=no, status=no, menubar=no)>
      - <popup:../DateList/testMulti.html(name:Multi Destination)(options:location=no, width=600, height=480, menubar=no, status=no, menubar=no)>
*/
function DateList () {
  // ATTRIBUTES
    /*    
       group: ATTRIBUTES
       
       subgroup: One Trip, Round Trip and Multi destination
       Attributes used for one trip, round trip and multi destination.  


       var: startAvailDate
       !(*)! Contains a code given by the toolkit to set the first day allowed to be selected.
       - *Type*: String - date code from toolkit.
       - *Default*: null (Required or <startDate>)
       
       *Example*: M12 means 12 months after current date/Time, H-5 means 5 hours before current date/Time
    */
  this.startAvailDate;   
    /*
       var: endAvailDate
       !(*)! Contains a code given by the toolkit to set the last day allowed to be selected.
       - *Type*: String - date code from toolkit.
       - *Default*: null (Required or <endDate>)
            
       *Example*: M12 means 12 months after current date/Time, H-5 means 5 hours before current date/Time
    */
  this.endAvailDate;
    /*
       var: startDate
       !(*)! Date component containing the first date allowed to be selected.
       - *Type*: Date
       - *Default*: null (Required or <startAvailDate>)
    */
    this.startDate;
    /*
       var: endDate
       !(*)! Date component containing the last date allowed to be selected.
       - *Type*: Date
       - *Default*: null (Required or <endAvailDate>)
    */
    this.endDate;     // Date component containing the last date allowed to be selected   
    /*
       var: grpStart
       !(*)! Table of the 4 departure elements containing the month dropdown, day dropdown, day label, time dropdown.
       - *Type*: Array of elementId
       - *Default*: null (Required) *The time dropdown is not mandatory*
       
       *Example*:  month dropdown (ex : Juin 2005, Juil 2005 ...), day dropdown (ex : 1,2,3,4,5,...), day label (Monday, Tuesday ...), time dropdown (ANY, 00h00, 01h00, ...).
    */
    this.grpStart;          
    /*
       var: monthsNames
       Contains the labels of the months.
       - *Type*: Array of String
       - *Default value*: ["January","February","March","April","May","June","July","August","September","October","November","December"]
    */ 
    this.monthsNames = ["January","February","March","April","May","June","July","August","September","October","November","December"];
    /*
       var: daysNames
       Contains the labels of the days.
       - *Type*: Array of String
       - *Default value*: ["S","M","T","W","T","F","S"]
    */ 
    this.daysNames = ["S","M","T","W","T","F","S"];
    //   nbDays
    //   Contains the number of days for each month of the year.
    this.nbDays = [31,28,31,30,31,30,31,31,30,31,30,31];
    /*
       var: currentDate
       The current day displayed in the first start date list.
       - *Type*: Date
       - *Default*: The current date of the client.
    */
    this.currentDate = new Date();
    /*
       var: classDisabled
       The CSS class used to disable the not allowed days in dropdown lists.
       - *Type*: String
       - *Default*: "dateListsDisabled".
    */
    this.classDisabled = "dateListsDisabled";
    /*
       subgroup: Round Trip (Only)
       
       var: grpEnd
       !(*)! Table of the 4 arrival elements containing the month dropdown, day dropdown, day label, time dropdown.
       - *Type*: Array of elementId
       - *Default*: null (Required) *The time dropdown is not mandatory*
       
       *Example*:  month dropdown (ex : Juin 2005, Juil 2005 ...), day dropdown (ex : 1,2,3,4,5,...), day label (Monday, Tuesday ...), time dropdown (ANY, 00h00, 01h00, ...).
    */
    this.grpEnd;
    /*
       subgroup: Round Trip and Multi Destination
       
       var: betweenDays
       Set the number of days between the departure date and the return date for round trip or between
       the departure dates for multi destination.
       - *Type*: Integer
       - *Default*: 7
       
    */    
    this.betweenDays = 7;
    /*
       var: returnDateModify
       boolean containing the fact that user have modify or not the arrival date
       0 means that no modification have been done, 1 means that user modify it
       - *Type*: Integer
       - *Default*: 0     
       
       *Tip*: Set the returnDateModify to 1 in the onload function to set the arrival date independant from the departure.
    */   
    this.returnDateModify = 0;    
    /*
       subgroup: Multi destination (Only)
       
       var: nextDateList
       !(*)! Set the next dateList (next destination).
       - *Type*: dateList
       - *Default*: null (Required except for the last one).
    */    
    this.nextDateList = null;
    /*
       var: hasBeenModifiedByUser
       Tell if the dateList has been modified so that when modify the precedent dateList,
       it wont modify the current dateList to precedent + betweenDays.
       - *Type*: boolean
       - *Default*: false.
       
       *Tip*: Set all the dateList to true in the onload function to set them all independant each other.
    */    
    this.hasBeenModifiedByUser = false;
    
    // Values of ComboBox
    this.monthsId = new Array;        // For each month, contains a string discribing the YearMonth (example : 200506 for Juily 2005)
    this.monthsLabel= new Array;      // For each month, contains the label used in the month dropdown list
    this.startDayOfMonth= new Array;  // For each month, contains the first avail day (depending on the start avail date)
    this.endDayOfMonth= new Array;    // For each month, contains the last avail day (depending on the end avail date)
    this.nbMonths;                    // Number of months displayed in month dropdown lists (= size of monthsID, monthsLabel ... lists)
    // To calculate day
    this.refMondayDate;     // Javascript have sometimes problem to caculate days of week (problems with time with computer locale).
                            // this variable is a Date/Time components corresponding to a MONDAY (it is set to the 1 janvier 1980)

    // Management of problem on Opera
    if (navigator.userAgent.toLowerCase().indexOf('opera') != -1) {
      this.navigatorOpera=true;
    } else {
      this.navigatorOpera=false;
    }

  // METHODS
    /*
     group: METHODS 
     
     !IMPORTANT!: The Methods names are like DateList_xxx but needs to be called like this.xxx. 
    */
    this.getIntervalAvailabilityDate = DateList_getIntervalAvailabilityDate;
    this.getDateTimeComposed = DateList_getDateTimeComposed;
    this.getDateTimeComposedString = DateList_getDateTimeComposedString;
    this.setDateComposedString = DateList_setDateComposedString;
    this.setDateTimeComposedString = DateList_setDateTimeComposedString;
    this.setDateDecComposedString = DateList_setDateDecComposedString;
    this.getMaxDays = DateList_getMaxDays;
    this.getNameDay = DateList_getNameDay;
    this.addMonth = DateList_addMonth;
    this.addYear = DateList_addYear;
    this.setStartingInfos = DateList_setStartingInfos;
    this.setEndingInfos = DateList_setEndingInfos;
    this.initMonthsDaysTables = DateList_initMonthsDaysTables;
    this.initListMonths = DateList_initListMonths;
    this.getYear = DateList_getYear;
    this.getMonth = DateList_getMonth;
    this.updateDays = DateList_updateDays;
    this.initDate = DateList_initDate;
    this.checkDay = DateList_checkDay;
    this.setReturnDate = DateList_setReturnDate;
    this.updateReturnDate = DateList_updateReturnDate;
    this.initDateLists = DateList_initDateLists;
    // Methods used for multidestination
    this.onkeypress = DateList_onkeypress;
    this.nextAddBetweenDays = DateList_nextAddBetweenDays;
    this.onChange = DateList_onChange;
}
    /*
       subgroup: Initialization

       method: initDateLists
       
       this function initialise all components (month, day, day of week, hours) and select the first day of the departure group.
       
       See in the examples how and where to use it in the code. The function must be called after having initialized the required attributes depending on the case.

       Parameters:
       
               none.
       
       Return:
       
               none.
    */
function DateList_initDateLists() {
  // Initialize good date for reference
    var refDat = new Date(1980,0,1,0,0,0);
    refDat.setHours(0);
    refDat.setMinutes(0);
    refDat.setSeconds(0);
    this.refMondayDate = refDat.getTime();
  // Initialize strat and end available date
    if (! this.startDate) {
      this.setStartingInfos();
    }
    if (! this.endDate) {
      this.setEndingInfos();
    }
  // Reajust currentDate
    this.currentDate.setHours(0);
    this.currentDate.setMinutes(0);
    this.currentDate.setSeconds(0);
  this.initMonthsDaysTables();
  this.initListMonths(this.grpStart[0]);
  if (this.grpEnd) {
    this.initListMonths(this.grpEnd[0]);
  }
  this.initDate();
  this.checkDay(this.grpStart[1]);
  if(this.nextDateList != null) {
	  this.nextAddBetweenDays();
	}
}

    /*
       subgroup: Events in HTML components
    
       method: updateDays
       
       Launched when user change the month of a group, this function change the content
       of the day dropdown list to correspond with the choosen month.
       
       See in the examples how and where to use it in the code.

       Parameters:
       
               cmp - month select element. (grpStart[0] or grpEnd[0])
       
       Return:
       
               none.
    */
function DateList_updateDays(cmp) {
  // Searching for good components
    if (cmp.id == this.grpStart[0].id) {
      cmpMonth = this.grpStart[0];
      cmpDay = this.grpStart[1];
    } else {
      cmpMonth = this.grpEnd[0];
      cmpDay = this.grpEnd[1];
    }
  // Keeping current selected day
    var selectedDay=cmpDay.selectedIndex;
    if (selectedDay<0) {
      selectedDay=0;
    }
  // Deletion of elements after
    while(cmpDay.options.length>0) {
      cmpDay.options[0]=null;
    } 
  // Calculating selected month
    var selectedMonth=cmpMonth.selectedIndex;
  var index=0;
  if (selectedMonth == 0) {   // Adding not allowed elements before
      for(var i=1;i<this.startDayOfMonth[selectedMonth];i++) {
        cmpDay.options[index] = new Option(i, i);
        if (this.navigatorOpera) {
          cmpDay.options[index].disabled=true;
        } else {
          cmpDay.options[index].className=this.classDisabled;
        }
        index++;
      }
  }
  // Adding allowed elements
    for(var i=this.startDayOfMonth[selectedMonth];i<this.endDayOfMonth[selectedMonth]+1;i++) {
      cmpDay.options[index] = new Option(i, i);
        if (this.navigatorOpera) {
          cmpDay.options[index].disabled=false;
        } else {
          cmpDay.options[index].className="";
        }
      index++;
    }
  if (selectedMonth == this.nbMonths-1) {   // Adding not allowed elements
      for(var i=this.endDayOfMonth[selectedMonth]+1;i<=this.getMaxDays(this.getMonth(this.monthsId[selectedMonth]),this.getYear(this.monthsId[selectedMonth]));i++) {
        cmpDay.options[index] = new Option(i, i);
        if (this.navigatorOpera) {
          cmpDay.options[index].disabled=true;
        } else {
          cmpDay.options[index].className=this.classDisabled;
        }
        index++;
      }
  }
  cmpDay.disabled=false;
  var lenCmpDay=cmpDay.options.length;
  // Forcing selected day to old one
    // Deleting all selection (Opera problem)
    for(var j=0;j<lenCmpDay;j++) {
      cmpDay.options[j].selected=false;
    }
    if (selectedDay<lenCmpDay) {
      // Opera doesn't realise that list has been changed !!!!!!
      // Select good day while not selected
        while(cmpDay.selectedIndex!=selectedDay) {
          cmpDay.options[selectedDay].selected = true;
        }
    } else {
      // Opera doesn't realise that list has been changed !!!!!!
      // Select good day while not selected
        while(cmpDay.selectedIndex!=lenCmpDay-1) {
          cmpDay.options[lenCmpDay-1].selected = true;
        }
    }
    
  this.checkDay(cmpDay);
}

    /*
       method: checkDay
       
       This function check the day selected in the day dropdown list and force the selection of the nearest allowed day.
       It updates the day of week label in case of modification
       
       See in the examples how and where to use it in the code.

       Parameters:
       
               cmpDay - day select element. (grpStart[1] or grpEnd[1])
       
       Return:
       
               none.
    */
function DateList_checkDay(cmpDay) {  
  if ((this.navigatorOpera && cmpDay.options[cmpDay.selectedIndex].disabled == true) || (!this.navigatorOpera && cmpDay.options[cmpDay.selectedIndex].className == this.classDisabled)) {   // Day not allowed
    var isInDisableTop;
    // Test at the top if there is disable class
    if ((this.navigatorOpera && cmpDay.options[0].disabled == false) || (!this.navigatorOpera && cmpDay.options[0].className != this.classDisabled)) {
      // First element of list is not disabled => disable are at the bottom
      isInDisableTop = false;
    } else {
      // First element of list is disabled => disable are at the top
      if ((this.navigatorOpera && cmpDay.options[cmpDay.options.length-1].disabled == false) || (!this.navigatorOpera && cmpDay.options[cmpDay.options.length-1].className != this.classDisabled)) {
        // Last element of list is not disabled => disable are at the top
        isInDisableTop = true;
      } else {
        // Last element of list is disabled => disable are at the bottom
        // Special case of only one month is displayed
	      var dec=0;
	      while(dec != cmpDay.selectedIndex && ((this.navigatorOpera && cmpDay.options[dec].disabled == true) || (!this.navigatorOpera && cmpDay.options[dec].className == this.classDisabled))) {
	        dec++;
	      }
        isInDisableTop = (dec == cmpDay.selectedIndex);
      }
    }
    if (isInDisableTop) {     // User selects a date too late
      // Find first allowed date after selection
      var dec=0;
      while((this.navigatorOpera && cmpDay.options[dec].disabled == true) || (!this.navigatorOpera && cmpDay.options[dec].className == this.classDisabled)) {
        dec++;
      }
      cmpDay.options[dec].selected = true;
    } else {      // User selects a date too early
      // Find last allowed date before selection
      var dec=cmpDay.options.length-1;
      while((this.navigatorOpera && cmpDay.options[dec].disabled == true) || (!this.navigatorOpera && cmpDay.options[dec].className == this.classDisabled)) {
        dec--;
      }
      cmpDay.options[dec].selected = true;
    }
  }
  // Change label of day
  if (cmpDay.id == this.grpStart[1].id) {
    this.grpStart[2].innerHTML=this.getNameDay(this.getDateTimeComposed(this.grpStart));
    this.updateReturnDate();
  } else {
    this.grpEnd[2].innerHTML=this.getNameDay(this.getDateTimeComposed(this.grpEnd));
  }
  
  if(this.nextDateList != null) {
    this.nextAddBetweenDays();
  }
}

var cmpOnKeyPress;
var dateListOnKeyPress;
    /*
       method: onkeypress
       
       this function refreshes the day label correctly when changing the month and day select using the keyboard.
       Used only for non IE to refresh the day Name correctly.
       
       See in the examples how and where to use it in the code.

       Parameters:
       
               cmp - month or day select element.
               event - just put event like in the examples.
       
       Return:
       
               none.
    */
function DateList_onkeypress(cmp,event) {
  cmpOnKeyPress = cmp;
  dateListOnKeyPress = this;
  this.hasBeenModifiedByUser = true;
  if((this.grpStart && cmp.id == this.grpStart[0].id) || (this.grpEnd && cmp.id == this.grpEnd[0].id))
    setTimeout('dateListOnKeyPress.updateDays(cmpOnKeyPress)', 0);
  if((this.grpStart && cmp.id == this.grpStart[1].id) || (this.grpEnd && cmp.id == this.grpEnd[1].id))    
      setTimeout('dateListOnKeyPress.checkDay(cmpOnKeyPress)', 0);
  if(dateListOnKeyPress.nextDateList != null) {
    setTimeout('dateListOnKeyPress.nextAddBetweenDays()',0);
  }
}

    /*
       method: onChange
       
       !(Multi destination only)! this function set the hasBeenModifiedByUser param to true and dispatch to update_days() or check_days()
       depending on the component cmp passed in parameter.
       
       Only used for multi destination. See in the examples how and where to use it in the code.

       Parameters:
       
               cmp - month or day select element.
       
       Return:
       
               none.
    */
function DateList_onChange(cmp)
{
  if(this.nextDateList != null) {
    this.nextAddBetweenDays();
  }
  
  switch (cmp.id) {
    case this.grpStart[0].id:
    this.updateDays(cmp);    
     break;
     case this.grpStart[1].id:
    this.checkDay(cmp);
    break;
  }
  
  this.hasBeenModifiedByUser = true;
}

    /*
       subgroup: Getter
    */
    
// getIntervalAvailabilityDate used only by the Calendar component
// Get the interval of availability date. Format : "20041015|20071016"
function DateList_getIntervalAvailabilityDate() {
  var intevalAvailability="";
  intevalAvailability+=this.startDate.getTime();
  intevalAvailability+="|";
  intevalAvailability+=this.endDate.getTime();
  return intevalAvailability;
}

   /*
       method: getDateTimeComposed
       
       Get the date described by the group of element in parameter (grpStart or grpEnd).

       Parameters:
       
               lstCmp - grpStart or grpEnd (see <grpStart> or <grpEnd>).
        
       Return:
       
               Date component containing the date described by the group of element.
    */
function DateList_getDateTimeComposed(lstCmp) {
  var retDatYear=this.getYear(this.monthsId[lstCmp[0].selectedIndex]);
  var retDatMonth=this.getMonth(this.monthsId[lstCmp[0].selectedIndex]);
  var retDatDate=1+lstCmp[1].selectedIndex;
  var retDatHours=0;
  if (lstCmp[3]) {
    if (lstCmp[3].tagName.toLowerCase()=="select") {
      if (lstCmp[3].selectedIndex != 0) {
        retDatHours=lstCmp[3].selectedIndex-1;
      }
    } else {
      var timeToAdd=lstCmp[3].value;
      if (timeToAdd != "ANY" && timeToAdd.length == 4) {
        retDatHours=parseInt(timeToAdd.substr(0,2),10);
      }
    }
  }
  var retDat = new Date(retDatYear,retDatMonth,retDatDate,retDatHours,0,0);
  return retDat;
}

   /*
       method: getDateTimeComposedString
       
       Get a String containing the date described by the group of element (grpStart or grpEnd)

       Parameters:
       
               lstCmp - grpStart or grpEnd (see <grpStart> or <grpEnd>).
               
       Return: 
               
               String containing the date described.
       
       Example:
              
               200510051500 for the 05 october 2005 at time 15H00
    */
function DateList_getDateTimeComposedString(lstCmp) {
  var retDatString = "";
  retDatString += this.getYear(this.monthsId[lstCmp[0].selectedIndex]);
  var month = 1+this.getMonth(this.monthsId[lstCmp[0].selectedIndex]);
  if (month<10) {
    retDatString += "0" + month;
  } else {
    retDatString += month;
  }
  var day = 1+lstCmp[1].selectedIndex;
  if (day<10) {
    retDatString += "0" + day;
  } else {
    retDatString += day;
  }
  // Get time of components group
  var timeToAdd = "0000";
  if (lstCmp[3]) {
    if (lstCmp[3].tagName.toLowerCase()=="select") {
      timeToAdd=lstCmp[3].options[lstCmp[3].selectedIndex].value;
    } else {
      timeToAdd=lstCmp[3].value;
    }
    if (timeToAdd == "ANY") {
      timeToAdd = "0000"
    }
  }
  retDatString += timeToAdd;
  return retDatString;
}


// getMaxDays
// Get the number of day containing in this month/year.
function DateList_getMaxDays(numMonth,numYear) {
  if (numMonth != 1) {  // Standard months
    return this.nbDays[numMonth];
  } else {  // February
    if (numYear == 4*Math.round(numYear/4)) {
      return 29;
    } else {
      return 28;
    }
  }
}


// getNameDay
// Get the day of the week for the javascript Date component passed.
function DateList_getNameDay(dat) {
  var datYear=dat.getYear();
  if (datYear < 1000) {
    datYear+=1900;
  }
  var nbDaysPassed=0;
  for(var i=1980;i<datYear;i++) {
    if (i == 4*Math.round(i/4)) {
      nbDaysPassed+=366;
    } else {
      nbDaysPassed+=365;
    }
  }
  for(var i=0;i<dat.getMonth();i++) {
    nbDaysPassed+=this.getMaxDays(i,datYear);
  }
  nbDaysPassed+=1+dat.getDate();
  return this.daysNames[nbDaysPassed % 7];
}


// getYear     
// Get the year describes in the string passed.
function DateList_getYear(YearMonth) {
  return parseInt(YearMonth.substr(0,4),10);
}


// getMonth
// Get the month describes in the string passed.
function DateList_getMonth(YearMonth) {
  return parseInt(YearMonth.substr(4),10);
}

   /*
       subgroup: Setter   
   
       method: setDateComposedString
       
       Set a group of components with the date passed in parameter.

       Parameters:
       
               lstCmp - grpStart or grpEnd (see <grpStart> or <grpEnd>).
               dat - String describing the date to set (Example : 20051005 for the 05 october 2005)
       
       Return:
       
               none.
       
       !IMPORTANT!:
       
               only the date components are updated (month drop down, day dop down, day of week label) but the time is not modified (use <setDateTimeComposedString> to do that)
    */
function DateList_setDateComposedString(lstCmp,dat) {
  if (dat.length<8) {
    return;
  }
  for(var i=0;i<this.nbMonths;i++) {
    if (this.monthsId[i]==parseInt(dat.substr(0,6),10)) {
      lstCmp[0].options[i].selected = true;
    }
  }
  this.updateDays(lstCmp[0]);
  lstCmp[1].options[parseInt(dat.substr(6,2),10)-1].selected = true;
  if (lstCmp==this.grpEnd) {
    this.returnDateModify=1;
  }
  this.updateDays(lstCmp[0]);
  this.updateReturnDate();
}

   /*
       method: setDateDecComposedString
       
       Set a group of components with the date passed in parameter.
       
       Difference with <setDateComposedString> is that the month number in the parameter is the month wanted less one (10 for november).

       Parameters:
       
               lstCmp - grpStart or grpEnd (see <grpStart> or <grpEnd>).
               dat - String describing the date to set (Example : 20051005 for the 05 november 2005)
       
       Return:
       
               none.
       
       !IMPORTANT!:
       
               only the date components are updated (month drop down, day dop down, day of week label) but the time is not modified (use <setDateTimeComposedString> to do that)
    */
function DateList_setDateDecComposedString(lstCmp,dat) {
  if (dat.length<8) {
    return;
  }
  for(var i=0;i<this.nbMonths;i++) {
    if (this.monthsId[i]==parseInt(dat.substr(0,6),10)-1) {
      lstCmp[0].options[i].selected = true;
    }
  }
  this.updateDays(lstCmp[0]);
  lstCmp[1].options[parseInt(dat.substr(6,2),10)-1].selected = true;
  if (lstCmp==this.grpEnd) {
    this.returnDateModify=1;
  }
  this.updateDays(lstCmp[0]);
  this.updateReturnDate();
}

   /*
       method: setDateTimeComposedString
       
       Set a group of components with the date passed in parameter.

       Parameters:
       
               lstCmp - grpStart or grpEnd (see <grpStart> or <grpEnd>).
               dat - String describing the date to set (Example : 200510051500 for the 05 october 2005 at time 15H00)
               anyTime - String "TRUE" to select Any time, "" to select the time in dat parameter, "!" not to change the time.
       
       Return:
       
               none.       
    */
function DateList_setDateTimeComposedString(lstCmp,dat,anyTime) {
  if (dat.length<12) {
    if (lstCmp==this.grpStart) {
      // Set current date with the startAvailDate
      lstCmp[0].options[0].selected = true;
      this.updateDays(lstCmp[0]);
      lstCmp[1].options[0].selected = true;
      this.checkDay(lstCmp[1]);
      this.updateReturnDate();
    }
    return;
  }
  for(var i=0;i<this.nbMonths;i++) {
    if (this.monthsId[i]==parseInt(dat.substr(0,6),10)-1) {
      lstCmp[0].options[i].selected = true;
    }
  }
  this.updateDays(lstCmp[0]);
  lstCmp[1].options[parseInt(dat.substr(6,2),10)-1].selected = true;

  if (lstCmp[3]) {
    if (anyTime != "!") {
      if (anyTime == "TRUE" || anyTime == "ANY") {
        if (lstCmp[3].tagName.toLowerCase()=="select") {
        for(var i=0;i<lstCmp[3].options.length;i++) {
          if (lstCmp[3].options[i].value=="ANY") {
            lstCmp[3].options[i].selected = true;
            }
        }
        } else {
          lstCmp[3].value="ANY";
        }
    } else if (anyTime == "MORNING" || anyTime == "AFTERNOON" || anyTime == "EVENING") {
        if (lstCmp[3].tagName.toLowerCase()=="select") {
        for(var i=0;i<lstCmp[3].options.length;i++) {
          if (lstCmp[3].options[i].value==anyTime) {
            lstCmp[3].options[i].selected = true;
            }
        }
        } else {
          lstCmp[3].value=anyTime;
        }
    } else {
        if (lstCmp[3].tagName.toLowerCase()=="select") {
          var timeCast = parseInt(dat.substr(8,2),10);
          timeCast *= 100;
          for(var i=0;i<lstCmp[3].options.length;i++) {
            if (lstCmp[3].options[i].value==timeCast) {
              lstCmp[3].options[i].selected = true;
            }
          }
        } else {
          lstCmp[3].value=dat.substr(8,4);
        }
    }
    }
  }
  if (lstCmp==this.grpEnd) {
    this.returnDateModify=1;
  }
  this.updateDays(lstCmp[0]);
  this.updateReturnDate();
}


// setReturnDate used by DateList_updateReturnDate
// Force the arrival group with the Date passed in parameter.
function DateList_setReturnDate(newDat) {
  var newDay = newDat.getDate();
  var newMonth = newDat.getMonth();
  var newYear = newDat.getYear();
  if (newYear < 1000) {
    newYear+=1900;
  }
  // Select good month
  var searchedMonth = "";
  searchedMonth += newYear;
  if (newMonth<10) {
    searchedMonth += "0";
  }
  searchedMonth += newMonth;
  var foundSelection = 0;
  for(var i=0;i<this.grpEnd[0].options.length;i++) {
    if(this.monthsId[i] == searchedMonth) {
      this.grpEnd[0].options[i].selected = true;
      foundSelection = 1;
    } else {
      this.grpEnd[0].options[i].selected = false;
    }
  }
  if (foundSelection == 0) {  // Select last allowed day of last month
    this.grpEnd[0].options[this.grpEnd[0].options.length-1].selected = true;
    this.updateDays(this.grpEnd[0]);
    this.grpEnd[1].options[this.grpEnd[1].options.length-1].selected = true;
  } else {  // Select good day
    this.updateDays(this.grpEnd[0]);
    this.grpEnd[1].options[newDay-1].selected = true;
  }
  this.checkDay(this.grpEnd[1]);
}

    
// addMonth
// Get a new Date component corresponding to the Date passed in parameter adding nbMonth month(s).
function DateList_addMonth(initDat,nbMonth) {
  var resDat=new Date(initDat);
  if (nbMonth>0) {
    for(var i=0;i<nbMonth;i++) {
      resDat.setMonth(resDat.getMonth()+1);
    }
  } else if (nbMonth < 0) {
    for(var i=nbMonth;i<0;i++) {
      resDat.setMonth(resDat.getMonth()-1);
    }
  }
  if (resDat.getDate() != initDat.getDate()) {
    resDat.setMonth(resDat.getMonth()-1);
    var resDatYear=resDat.getYear();
    if (resDatYear < 1000) {
      resDatYear+=1900;
    }
    resDat.setDate(this.getMaxDays(resDat.getMonth(),resDatYear));
  }
  return resDat;
}


// addYear
// Get a new Date component corresponding to the Date passed in parameter adding nbYear year(s).
function DateList_addYear(initDat,nbYear) {
  var resDat=new Date(initDat);
  var initDatYear=initDat.getYear();
  if (initDatYear < 1000) {
    initDatYear+=1900;
  }
  resDat.setYear(initDatYear+nbYear);
  if (resDat.getDate() != initDat.getDate()) {
    resDat.setMonth(resDat.getMonth()-1);
    var resDatYear=resDat.getYear();
    if (resDatYear < 1000) {
      resDatYear+=1900;
    }
    resDat.setDate(this.getMaxDays(resDat.getMonth(),resDatYear));
  }
  return resDat;
}

// setStartingInfos : only used by initDateLists.
// With the currentDate and the startAvailDate setted before (initialisation),
// this function intanciate the startDate with a javascript Date component
// containing the first avail date allowed
function DateList_setStartingInfos() {
  var curDat = new Date(this.currentDate);
  var cDatV = (new Date(this.currentDate)).getTime();
  // Starting Date
    if (this.startAvailDate.length > 0) {
      var v=parseInt(this.startAvailDate.substr(1),10);
      switch (this.startAvailDate.substr(0,1))
      {
        case "N":
          this.startDate = new Date(cDatV+60000*v);
          break;
        case "H":
          this.startDate = new Date(cDatV+3600000*v);
          break;
        case "D":
          this.startDate = new Date(cDatV+86400000*v);
          break;
        case "W":
          this.startDate = new Date(cDatV+604800000*v);
          break;
        case "M":
          this.startDate = this.addMonth(curDat,v);
          break;
        case "Y":
          this.startDate = this.addYear(curDat,v);
          break;
      } 
    } else {
      this.startDate = new Date(curDat);
    }
}

// setEndingInfos : only used by initDateLists.
// With the currentDate and the endAvailDate setted before (initialisation),
// this function intanciate the endDate with a javascript Date component
// containing the last avail date allowed
function DateList_setEndingInfos() {
  var curDat = new Date(this.currentDate);
  var cDatV = (new Date(this.currentDate)).getTime();
  // Ending Date
    if (this.endAvailDate.length > 0) {
      var v=parseInt(this.endAvailDate.substr(1),10);
      switch (this.endAvailDate.substr(0,1))
      {
        case "N":
          this.endDate = new Date(cDatV+60000*v);
          break;
        case "H":
          this.endDate = new Date(cDatV+3600000*v);
          break;
        case "D":
          this.endDate = new Date(cDatV+86400000*v);
          break;
        case "W":
          this.endDate = new Date(cDatV+604800000*v);
          break;
        case "M":
          this.endDate = this.addMonth(curDat,v);
          break;
        case "Y":
          this.endDate = this.addYear(curDat,v);
          break;
      } 
    } else {
      this.endDate = new Date(curDat);
    }
}

// initMonthsDaysTables : only used by initDateLists. 
// Initialise the table of months and day that user can found in the dropdown lists
function DateList_initMonthsDaysTables() {
  this.nbMonths=0;
  var curDat=new Date(this.startDate);
  while(curDat.getTime() <= this.endDate.getTime() || curDat.getMonth() == this.endDate.getMonth()) {
    var year = curDat.getYear();
    if (year < 1000) {
      year+=1900;
    }
    // Months combobox
    this.monthsId[this.nbMonths]="";
    this.monthsId[this.nbMonths]+=year;
    if (curDat.getMonth()<10) {
      this.monthsId[this.nbMonths]+="0";
    }
    this.monthsId[this.nbMonths]+=curDat.getMonth();
    this.monthsLabel[this.nbMonths]="";
    this.monthsLabel[this.nbMonths]+=this.monthsNames[curDat.getMonth()];
    this.monthsLabel[this.nbMonths]+=year;
    // Days combobox
    this.startDayOfMonth[this.nbMonths]=1;
    this.endDayOfMonth[this.nbMonths]=this.getMaxDays(curDat.getMonth(),year);
    this.nbMonths++;    // Next month
    curDat = this.addMonth(this.startDate,this.nbMonths);
  }
  // Initialization of special months
  this.startDayOfMonth[0]=this.startDate.getDate();
  this.endDayOfMonth[this.nbMonths-1]=this.endDate.getDate();
}

// initListMonths : only used by initDateLists. 
function DateList_initListMonths(cmpMonth) {
  for(var i=0;i<this.nbMonths;i++) {
    cmpMonth.options[i] = new Option(this.monthsLabel[i], this.monthsId[i]);
  }
}

// initDate : only used by initDateLists. 
// Fill the groups defined with months and days allowed.
function DateList_initDate() {
  var curDat = new Date(this.currentDate);
  var curDay = curDat.getDate();
  var curMonth = curDat.getMonth();
  var curYear = curDat.getYear();
  if (curYear < 1000) {
    curYear+=1900;
  }
  // Select good month
  var searchedMonth = "";
  searchedMonth += curYear;
  if (curMonth<10) {
    searchedMonth += "0";
  }
  searchedMonth += curMonth;
  var monthFound = false;
  for(var i=0;i<this.grpStart[0].options.length;i++) {
    if(this.monthsId[i] == searchedMonth) {
      this.grpStart[0].options[i].selected = true;
      this.grpStart[0].selectedIndex = i;
      monthFound = true;
    } else {
      this.grpStart[0].options[i].selected = false;
    }
  }
  if (!monthFound) {
    // The current month has not been found, we have to select first of the list
    this.grpStart[0].options[0].selected = true;
    this.grpStart[0].selectedIndex = 0;
  }
  // Select good day
    this.updateDays(this.grpStart[0]);
    this.grpStart[1].options[0].selected = true;
}

// updateReturnDate : only used by others methods.
// Launched by the HTML page, this function forces the arrival group to be setted betweenDays days after the departure date
// the interval is not forced in case returnDateModify == 1 (consequence of user changes the arrival date)
function DateList_updateReturnDate() {
  if (this.returnDateModify == 0 && this.grpEnd) {
    var outboundDate=this.getDateTimeComposed(this.grpStart);
    var returnDate=new Date(outboundDate);
    returnDate.setDate(outboundDate.getDate()+this.betweenDays);
    this.setReturnDate(returnDate);
  }
}

// nextAddBetweenDays : used only by onchange and updateDays methods for multi destination.
// This function add the between days to the next DateList.
var tableAddDone = Array(); // This array optimize the changes by doing each nextAddBetweenDays one time.
function DateList_nextAddBetweenDays(eAnyTime) {
    if(tableAddDone[this.grpStart[0].id] == null) {
      tableAddDone[this.grpStart[0].id] = true;
    }

    if(tableAddDone[this.grpStart[0].id] == false && !this.nextDateList.hasBeenModifiedByUser) {
        var expr = "this.nextDateList.setDateTimeComposedString(this.nextDateList.grpStart,\"";
        eval("var prevDate = this.getDateTimeComposed(this.grpStart);");
        var prevDateTime = prevDate.getTime();   // Time of prevDate (milliseconds since 1970)
        prevDate.setTime(prevDateTime+(7 * 24 * 60 * 60 * 1000));   // 7 days in milliseconds
        // Convert date to String
        var prevDateString = "";
          var prevDateYear = prevDate.getYear();
          var prevDateMonth = prevDate.getMonth() + 1;
          var prevDateDay = prevDate.getDate();
          var prevDateHours = prevDate.getHours();
          var prevDateMinutes = prevDate.getMinutes();
          var prevDateSeconds = prevDate.getSeconds();
          if (prevDateYear < 1000) prevDateYear+=1900;
          prevDateString += prevDateYear;
          if (prevDateMonth<10) prevDateString += "0";
          prevDateString += prevDateMonth;
          if (prevDateDay<10) prevDateString += "0";
          prevDateString += prevDateDay;
          if (prevDateHours<10) prevDateString += "0";
          prevDateString += prevDateHours;
          if (prevDateMinutes<10) prevDateString += "0";
          prevDateString += prevDateMinutes;
          if (prevDateSeconds<10) prevDateString += "0";
          prevDateString += prevDateSeconds;
        expr += prevDateString;
        expr += "\",eAnyTime);";
        tableAddDone[this.grpStart[0].id] = true;
        eval(expr);
     }
     else {
     tableAddDone[this.grpStart[0].id] = false;
     }     
}
