/* 
 * > Receiver - html element receiving the date value.
 * > Trigger  - html element that shows CAL component.
 * 
 * > Date rollover on month change is as implemented by JavaScript.
 * 
 * > As month value is zero based in JavaScript, it has to be increased 
 *   for 1 every time it is displayed and decreased for 1 for calculation. 
 *   Spots in the code that this is done are marked by the comment.
 */
 

/* receiver, html element to receive the date */
var receiverRef;

/* date delimiter */
var delimiterRef;

/* flag that indicates that mouse is down */
var active = false;

/* time to sleep before date values start scrolling when mouse is down */
var sleep = 150;

/* counter used to set variable scroll speed */
var count = 0;
 
/*
 * Create calendar component.
 *
 * Date td elements have to be initialized.
 * Have to escape ' inside document.write().
 */
function create_calendar(){
  
  document.write('<div id="calendar-div">');
  document.write('<table id="calendar-table" cellspacing="1">');
  document.write(' <tr>');
  document.write('  <td class="task" rowspan="3">Date:</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveYear(\'+\');"  onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">+</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveMonth(\'+\');" onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">+</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveDay(\'+\');"   onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">+</td>');
  document.write('  <td class="task" rowspan="6">');
  document.write('	<a class="taskLink" href="javascript:calOk();">Ok</a><br>');
  document.write('	<a class="taskLink" href="javascript:calCancel();">Cancel</a><br>');
  document.write('	<a class="taskLink" href="javascript:calClear();">Clear</a><br>');
  document.write('	<a class="taskLink" href="javascript:calToday();">Today</a><br>');
  document.write('  </td>');
  document.write(' </tr>');
  document.write(' <tr>');
  document.write('  <td class="date">0</td>');
  document.write('  <td class="date">0</td>');
  document.write('  <td class="date">0</td>');
  document.write(' </tr>');
  document.write(' <tr>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveYear(\'-\');"  onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">-</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveMonth(\'-\');" onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">-</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveDay(\'-\');"   onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">-</td>');
  document.write(' </tr>');
  document.write(' <tr>');
  document.write('  <td class="task" rowspan="3">Time:</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveHour(\'+\');"   onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">+</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveMinute(\'+\');" onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">+</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveSecond(\'+\');" onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">+</td>');
  document.write(' </tr>');
  document.write(' <tr>');
  document.write('  <td class="time">0</td>');
  document.write('  <td class="time">0</td>');
  document.write('  <td class="time">0</td>');
  document.write(' </tr>');
  document.write(' <tr>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveHour(\'-\');"   onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">-</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveMinute(\'-\');" onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">-</td>');
  document.write('  <td class="buttonOut" onMouseDown="javascript:this.className=\'buttonIn\';calSetActive(true);calMoveSecond(\'-\');" onMouseUp="javascript:this.className=\'buttonOut\';calSetActive(false);" onMouseOut="javascript:this.className=\'buttonOut\';calSetActive(false);">-</td>');
  document.write(' </tr>');
  document.write('</table>');
  document.write('</div>  ');
}

/*
 * Set mouse down flag. 
 */ 
function calSetActive(value){
   active = value;
}

/*
 * Show CAL component.
 *
 * note:
 * Style property is only for inline style elements, 
 * those that are defined in style element attribute.
 */ 
function calShow(receiver, trigger, delimiter){
  
  var divRef = document.getElementById("calendar-div");
  var triggerRef = document.getElementById(trigger);

  // set component position over the trigger element
  divRef.style.top = findOffsetTop(triggerRef);
  divRef.style.left = findOffsetLeft(triggerRef);
  
  // make it visible
  divRef.style.visibility = "visible";
    
  // set receiver reference, required for ok and cancel events
  //receiverRef = document.getElementById(receiver);
  receiverRef = eval( 'document.mainform.'+receiver );

  // initialize component
  // if no value -> today, otherwise parse existing value 
  // from the receiver based on yyyy-mm-dd format
  if (receiverRef.value == ""){  
    calToday();
  }else{
    var date = new String(receiverRef.value);
    calSetYear(date.substring(0,4));
    calSetMonth(date.substring(5,7)); // no need to increase month for display
    calSetDay(date.substring(8,10));
    calSetHour(date.substring(11,13));
    calSetMinute(date.substring(14,16));
    calSetSecond(date.substring(17,19));
  }
  
  // set delimiter reference
  delimiterRef = delimiter;
}

/*
 * Ok click, update receiver element with picked date and hide CAL component.
 */ 
function calOk(){
  document.getElementById("calendar-div").style.visibility = "hidden";
  receiverRef.value = calGetYear() + delimiterRef + calGetMonth() + delimiterRef + calGetDay() + ' ' + 
                      calGetHour() + ':' + calGetMinute() + ':' + calGetSecond();
}

/*
 * Cancel click, hide CAL component.
 */ 
function calCancel(){
  document.getElementById("calendar-div").style.visibility = "hidden";
}

/*
 * Clear click, clear the receiver and hide CAL component.
 */ 
function calClear(){
  document.getElementById("calendar-div").style.visibility = "hidden";
  receiverRef.value = "";
}

/*
 * Set CAL date values to today.
 */ 
function calToday(){
  var today = new Date();
  calSetYear(today.getFullYear());
  calSetMonth(today.getMonth() + 1); // increase month for display
  calSetDay(today.getDate());
  calSetHour(today.getHours());
  calSetMinute(today.getMinutes()); 
  calSetSecond(today.getSeconds());
}

/*
 * Move year value.
 * If direction is + than year is increased.
 * If direction is - than year is decreased.
 */ 
function calMoveYear(direction){
  
  if(active) {
  
    // calc new year value
    var newYear;
    if (direction == "+"){
      newYear = eval(calGetYear()) + 1;
    }else if (direction == "-"){
      newYear = eval(calGetYear()) - 1;
    }else{
      alert("Invalid argument for calMoveYear().");
    }
  
    // create new date  
    var newDate = new Date(newYear, calGetMonth() - 1, calGetDay()); // decrease month for calculation
  
    // update the component
    calSetYear(newDate.getFullYear());
    calSetMonth(newDate.getMonth() + 1); // increase month for display
    calSetDay(newDate.getDate());
 
    // calculate sleep period for variable scroll speed.
    var currentSpeed;
    if (count < 3){
      currentSpeed = sleep;
    } else if (count >= 3 && count < 10) {
      currentSpeed = 0.7 * sleep;
    } else if (count >= 10){
      currentSpeed = 0.4 * sleep;
    }
    count = count + 1;    

    // recursive timer call, scrolls year when mouse is down   
    setTimeout("calMoveYear('" + direction + "')",currentSpeed); 
    
  } else {
    // mouse not active (mouse up)
    count = 0;
  }    
  
}

/*
 * Move month value.
 * If direction is + than year is increased.
 * If direction is - than year is decreased.
 */ 
function calMoveMonth(direction){
  
  if(active) {
  
    // calc new month value
    var newMonth;
    if (direction == "+"){
      newMonth = eval(calGetMonth()) + 1;
    }else if (direction == "-"){
      newMonth = eval(calGetMonth()) - 1;
    }else{
      alert("Invalid argument for calMoveMonth().");
    }
  
    // create new date  
    var newDate = new Date(calGetYear(), newMonth - 1, calGetDay()); // decrease month for calculation
  
    // update the component
    calSetYear(newDate.getFullYear());
    calSetMonth(newDate.getMonth() + 1); // increase month for display
    calSetDay(newDate.getDate());
   
    // calculate sleep period for variable scroll speed.
    var currentSpeed;
    if (count < 3){
      currentSpeed = sleep;
    } else if (count >= 3 && count < 10) {
      currentSpeed = 0.7 * sleep;
    } else if (count >= 10){
      currentSpeed = 0.4 * sleep;
    }
    count = count + 1;    

    // recursive timer call, scrolls month when mouse is down   
    setTimeout("calMoveMonth('" + direction + "')",currentSpeed); 
    
  } else {
    // mouse not active (mouse up)
    count = 0;
  }    
}

/*
 * Move day value.
 * If direction is + than year is increased.
 * If direction is - than year is decreased.
 */ 
function calMoveDay(direction){
  
  if(active) {

    // calc new day value
    var newDay;
    if (direction == "+"){
      newDay = eval(calGetDay()) + 1;
    }else if (direction == "-"){
      newDay = eval(calGetDay()) - 1;
    }else{
      alert("Invalid argument for calMoveDay().");
    }
  
    // create new date  
    var newDate = new Date(calGetYear(), calGetMonth() - 1, newDay); // decrease month for calculation
  
    // update the component
    calSetYear(newDate.getFullYear());
    calSetMonth(newDate.getMonth() + 1); // increase month for display
    calSetDay(newDate.getDate());
  
 
    // calculate sleep period for variable scroll speed.
    var currentSpeed;
    if (count < 3){
      currentSpeed = sleep;
    } else if (count >= 3 && count < 10) {
      currentSpeed = 0.7 * sleep;
    } else if (count >= 10){
      currentSpeed = 0.4 * sleep;
    }
    count = count + 1;    

    // recursive timer call, scrolls day when mouse is down    
    setTimeout("calMoveDay('" + direction + "')",currentSpeed); 
  
  
  } else {
    // mouse not active (mouse up)
    count = 0;
  }  
}

/*
 * Move hour value.
 * If direction is + than hour is increased.
 * If direction is - than hour is decreased.
 */ 
function calMoveHour(direction){
  
  if(active) {
  
    // calc new hour value
    var newHour;
    if (direction == "+"){
      newHour = eval(calGetHour()) + 1;
    }else if (direction == "-"){
      newHour = eval(calGetHour()) - 1;
    }else{
      alert("Invalid argument for calMoveHour().");
    }
     
    // create new date, date is hardcoded - only time matters
    var newTime = new Date(2000, 1, 1, newHour, calGetMinute(), calGetSecond());
  
    // update the component
    calSetHour(newTime.getHours());
    calSetMinute(newTime.getMinutes());
    calSetSecond(newTime.getSeconds());
 
    // calculate sleep period for variable scroll speed.
    var currentSpeed;
    if (count < 3){
      currentSpeed = sleep;
    } else if (count >= 3 && count < 10) {
      currentSpeed = 0.7 * sleep;
    } else if (count >= 10){
      currentSpeed = 0.4 * sleep;
    }
    count = count + 1;    

    // recursive timer call, scrolls year when mouse is down   
    setTimeout("calMoveHour('" + direction + "')",currentSpeed); 
    
  } else {
    // mouse not active (mouse up)
    count = 0;
  }    
  
}

/*
 * Move minute value.
 * If direction is + than year is increased.
 * If direction is - than year is decreased.
 */ 
function calMoveMinute(direction){
  
  if(active) {
  
    // calc new month value
    var newMinute;
    if (direction == "+"){
      newMinute = eval(calGetMinute()) + 1;
    }else if (direction == "-"){
      newMinute = eval(calGetMinute()) - 1;
    }else{
      alert("Invalid argument for calMoveMinute().");
    }
  
    // create new date, date is hardcoded - only time matters
    var newTime = new Date(2000, 1, 1, calGetHour(), newMinute, calGetSecond());
  
    // update the component
    calSetHour(newTime.getHours());
    calSetMinute(newTime.getMinutes());
    calSetSecond(newTime.getSeconds());
   
    // calculate sleep period for variable scroll speed.
    var currentSpeed;
    if (count < 3){
      currentSpeed = sleep;
    } else if (count >= 3 && count < 10) {
      currentSpeed = 0.7 * sleep;
    } else if (count >= 10){
      currentSpeed = 0.4 * sleep;
    }
    count = count + 1;    

    // recursive timer call, scrolls month when mouse is down   
    setTimeout("calMoveMinute('" + direction + "')",currentSpeed); 
    
  } else {
    // mouse not active (mouse up)
    count = 0;
  }    
}

/*
 * Move second value.
 * If direction is + than year is increased.
 * If direction is - than year is decreased.
 */ 
function calMoveSecond(direction){
  
  if(active) {

    // calc new day value
    var newSecond;
    if (direction == "+"){
      newSecond = eval(calGetSecond()) + 1;
    }else if (direction == "-"){
      newSecond = eval(calGetSecond()) - 1;
    }else{
      alert("Invalid argument for calMoveSecond().");
    }
  
    // create new date, date is hardcoded - only time matters
    var newTime = new Date(2000, 1, 1, calGetHour(), calGetMinute(), newSecond);
  
    // update the component
    calSetHour(newTime.getHours());
    calSetMinute(newTime.getMinutes());
    calSetSecond(newTime.getSeconds());
 
    // calculate sleep period for variable scroll speed.
    var currentSpeed;
    if (count < 3){
      currentSpeed = sleep;
    } else if (count >= 3 && count < 10) {
      currentSpeed = 0.7 * sleep;
    } else if (count >= 10){
      currentSpeed = 0.4 * sleep;
    }
    count = count + 1;    

    // recursive timer call, scrolls day when mouse is down    
    setTimeout("calMoveSecond('" + direction + "')",currentSpeed); 
  
  } else {
    // mouse not active (mouse up)
    count = 0;
  }  
}

/*
 * Get year value.
 */ 
function calGetYear(){
  var table = document.getElementById("calendar-table");
  var row = table.rows[1];
  var cell = row.cells[0];
  return cell.firstChild.nodeValue;
}

/*
 * Set year value.
 */ 
function calSetYear(year){
  var table = document.getElementById("calendar-table");
  var row = table.rows[1];
  var cell = row.cells[0];
  cell.firstChild.nodeValue = padZeroLeftPad(year, 4);
}

/*
 * Get month value.
 */ 
function calGetMonth(){
  var table = document.getElementById("calendar-table");
  var row = table.rows[1];
  var cell = row.cells[1];
  return cell.firstChild.nodeValue;
}

/*
 * Set month value.
 */ 
function calSetMonth(month){
  var table = document.getElementById("calendar-table");
  var row = table.rows[1];
  var cell = row.cells[1];
  cell.firstChild.nodeValue = padZeroLeftPad(month, 2);
}

/*
 * Get day value.
 */ 
function calGetDay(){
  var table = document.getElementById("calendar-table");
  var row = table.rows[1];
  var cell = row.cells[2];
  return cell.firstChild.nodeValue;
}

/*
 * Set day value.
 */ 
function calSetDay(day){
  var table = document.getElementById("calendar-table");
  var row = table.rows[1];
  var cell = row.cells[2];
  cell.firstChild.nodeValue = padZeroLeftPad(day, 2);
}

/*
 * Get hour value.
 */ 
function calGetHour(){
  var table = document.getElementById("calendar-table");
  var row = table.rows[4];
  var cell = row.cells[0];
  return cell.firstChild.nodeValue;
}

/*
 * Set year value.
 */ 
function calSetHour(hour){
  var table = document.getElementById("calendar-table");
  var row = table.rows[4];
  var cell = row.cells[0];
  cell.firstChild.nodeValue = padZeroLeftPad(hour, 2);
}

/*
 * Get minute value.
 */ 
function calGetMinute(){
  var table = document.getElementById("calendar-table");
  var row = table.rows[4];
  var cell = row.cells[1];
  return cell.firstChild.nodeValue;
}

/*
 * Set minute value.
 */ 
function calSetMinute(minute){
  var table = document.getElementById("calendar-table");
  var row = table.rows[4];
  var cell = row.cells[1];
  cell.firstChild.nodeValue = padZeroLeftPad(minute, 2);
}

/*
 * Get second value.
 */ 
function calGetSecond(){
  var table = document.getElementById("calendar-table");
  var row = table.rows[4];
  var cell = row.cells[2];
  return cell.firstChild.nodeValue;
}

/*
 * Set second value.
 */ 
function calSetSecond(second){
  var table = document.getElementById("calendar-table");
  var row = table.rows[4];
  var cell = row.cells[2];
  cell.firstChild.nodeValue = padZeroLeftPad(second, 2);
}

/*
 * Leftpad the value with zeros.
 */ 
function padZeroLeftPad(value, length) {
  
  // build the zeros string
  var zeros = new String();
  for (i=0; i<length; i++) {
    zeros = zeros + "0";
  }

  // prepend zeros to the value
  var longValue = zeros + value;

  // return the last length characters
  return longValue.substring(longValue.length - length, longValue.length);
}


/*
 * Find total left offset.
 */ 
function findOffsetLeft(obj){
  var curleft = 0;
  if (obj.offsetParent){
    while (obj.offsetParent){
      curleft += obj.offsetLeft
        obj = obj.offsetParent;
    }
  }else if (obj.x){
    curleft += obj.x;
  }
  
  return curleft;
}

/*
 * Find total top offset.
 */ 
function findOffsetTop(obj){
  var curtop = 0;
  if (obj.offsetParent)	{
    while (obj.offsetParent){
      curtop += obj.offsetTop
      obj = obj.offsetParent;
    }
  }else if (obj.y){
    curtop += obj.y;
  }
		
  return curtop;
}
