var datePickerDivId = 'datepicker';
var iFrameDivId = 'datepickeriframe';
var dayArrayShort = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
var dayArrayMed = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
var dayArrayLong = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
var monthArrayShort = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
var monthArrayLong = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
var dateSeparator = '/';
var dateFormat = 'short';

function displayDatePicker(dateFieldId, dtFormat) {
  var targetDateField = document.getElementById(dateFieldId);
  var x = targetDateField.offsetLeft;
  var y = targetDateField.offsetTop + targetDateField.offsetHeight;
 
  // Get offset for nested elements
  var parent = targetDateField;
  while(parent.offsetParent) {
	parent = parent.offsetParent;
	x += parent.offsetLeft;
	y += parent.offsetTop;
  }

  // Update the date format if necessary
  if(dtFormat)
	dateFormat = dtFormat;
 
  drawDatePicker(targetDateField, x, y + 3);
}

function drawDatePicker(targetDateField, x, y) {
  var dt = getFieldDate(targetDateField.value);
 
  // Create datePickerDiv if it doesn't exist
  if(!document.getElementById(datePickerDivId)) {
	var newNode = document.createElement('div');
	newNode.setAttribute('id', datePickerDivId);
	newNode.setAttribute('class', 'dpDiv');
	//newNode.setAttribute('style', 'visibility:hidden');
	document.body.appendChild(newNode);
  }
 
  // Move datePickerDiv to the proper x,y coordinate and toggle the visiblity
  var pickerDiv = document.getElementById(datePickerDivId);
  pickerDiv.style.position = 'absolute';
  pickerDiv.style.left = x + 'px';
  pickerDiv.style.top = y + 'px';
  //pickerDiv.style.visibility = pickerDiv.style.visibility == 'visible' ? 'hidden' : 'visible';
  pickerDiv.style.display = pickerDiv.style.display == 'block' ? 'none' : 'block';
  pickerDiv.style.zIndex = 100000;

  // Draw the datepicker table
  refreshDatePicker('day', targetDateField.id, dt.getFullYear(), dt.getMonth(), dt.getDate());
}

function refreshDatePicker(view, dateFieldId, year, month, day) {
  var thisDay = new Date();             
  if(month >= 0 && year > 0)
	thisDay = new Date(year, month, 1);
  else if(year > 0)
    thisDay = new Date(year, 0, 1);
  else {
	day = thisDay.getDate();
	thisDay.setDate(1);
  }
  
  // This is a way of differentiating between the currently
  // selected year (view='year') and a calculated span (view='yearspan').
  // Only highlight the year, if it is the currently selected year.
  var showHighlight = true;
  if(view == 'yearspan') {
    showHighlight = false;
    view = 'year';
  }
 
  // Initialize variables used to build html for calendar
  var crlf = '\r\n';
  var cols = view == 'day' ? 7 : 3;
  var TABLE = '<table cols="' + cols + '" class="dpTable">' + crlf;
  var xTABLE = '</table>' + crlf;
  var TR = '<tr class="dpTR">';
  var TR_alt = '<tr class="dpAltTR">';
  var TR_title = '<tr class="dpTitleTR">';
  var TR_header = '<tr class="dpHeaderTR">';
  var xTR = '</tr>' + crlf;
  var TD = '<td class="dpTD" onMouseOut="this.className=\'dpTD\';" onMouseOver="this.className=\'dpTDHover\';" ';    // leave this tag open, because we'll be adding an onClick event
  var TD_blank = '<td class="dpBlankTD">&nbsp;</td>';
  var TD_title = '<td colspan="' + (cols - 2) + '" class="dpTitleTD">';
  var TD_buttons = '<td class="dpButtonTD">';
  var TD_days = '<td class="dpDayTD">';
  var TD_spacer = '<td colspan="3" class="dpSpacerTD">&nbsp;</td>';
  var TD_selected = '<td class="dpDayHighlightTD" onMouseOut="this.className=\'dpDayHighlightTD\';" onMouseOver="this.className=\'dpTDHover\';" ';    // leave this tag open, because we'll be adding an onClick event
  var xTD = '</td>' + crlf;
  var DIV_title = '<div class="dpTitleText">';
  var DIV_selected = '<div class="dpDayHighlight">';
  var xDIV = '</div>';
 
  // Start building html for calendar
  var html = TABLE;
 
  // Title bar
  html += TR_title;
  html += TD_buttons + getNavCode(dateFieldId, thisDay, -1, view) + xTD;
  html += TD_title + DIV_title + getTitleCode(dateFieldId, thisDay, view) + xDIV + xTD;
  html += TD_buttons + getNavCode(dateFieldId, thisDay, 1, view) + xTD;
  html += xTR;

  // Header bar
  html += TR_header;
  if(view == 'day') // Weekdays
      for(i = 0; i < dayArrayShort.length; i++)
	    html += TD_days + dayArrayShort[i] + xTD;
  else if(view == 'month' || view == 'year') // Spacer
    html += TD_spacer;
  html += xTR;

  // Calendar grid
  html += view == 'day' ? TR : TR_alt;
  switch(view) {
    case 'day':
      // Leading blanks
      for(i = 0; i < thisDay.getDay(); i++)
	    html += TD_blank;
 
      // Days of the month
      do {
	    dayNum = thisDay.getDate();
	    TD_onclick = ' onclick="updateDateField(\'' + dateFieldId + '\', \'' + getDateString(thisDay) + '\');">';
	    if(dayNum == day)
	      html += TD_selected + TD_onclick + DIV_selected + dayNum + xDIV + xTD;
	    else
	      html += TD + TD_onclick + dayNum + xTD;
    	
	    // if this is Saturday, start a new row
	    if(thisDay.getDay() == 6)
	      html += xTR + TR;
    	
	    // increment the day
	    thisDay.setDate(thisDay.getDate() + 1);
      } while(thisDay.getDate() > 1)
 
      // Trailing blanks
      if(thisDay.getDay() > 0)
	    for(i = 6; i > thisDay.getDay(); i--)
	      html += TD_blank;
      break;
    case 'month':
      for(var i=0; i<monthArrayLong.length; i++) {
        TD_onclick = ' onclick="refreshDatePicker(\'day\', \'' + dateFieldId + '\', \'' + year + '\', \'' + i + '\');">';
        if(i == month)
            html += TD_selected + TD_onclick + DIV_selected + monthArrayLong[i] + xDIV + xTD;
	    else
            html += TD + TD_onclick + monthArrayLong[i] + xTD;
        
        // if this is third column, start a new row
        if((i+1) % 3 == 0)
            html += xTR + TR_alt;
      }
      break;
    case 'year':
        var thisYear = thisDay.getFullYear();
        for(var i=thisYear-4; i<thisYear+8; i++) {
            TD_onclick = ' onclick="refreshDatePicker(\'month\', \'' + dateFieldId + '\', \'' + i + '\');">';
            if(i == thisYear && showHighlight)
                html += TD_selected + TD_onclick + DIV_selected + i + xDIV + xTD;
	        else
                html += TD + TD_onclick + i + xTD;

            // if this is third column, start a new row
            if((i-(thisYear-4)+1) % 3 == 0)
                html += xTR + TR_alt;
        }
        break;
  }
  html += xTR;
  html += xTABLE;
  document.getElementById(datePickerDivId).innerHTML = html;
  adjustiFrame();
}

function getTitleCode(dateFieldId, dateVal, view) {
    if(view == 'day')
        return '<a class="dpTitleText" href="javascript:refreshDatePicker(\'month\', \'' + dateFieldId + '\', ' + dateVal.getFullYear() + ', ' + dateVal.getMonth() + ');">' + monthArrayLong[dateVal.getMonth()] + ' ' + dateVal.getFullYear() + '</a>';
    else if(view == 'month')
        return '<a class="dpTitleText" href="javascript:refreshDatePicker(\'year\', \'' + dateFieldId + '\', ' + dateVal.getFullYear() + ', ' + dateVal.getMonth() + ');">' + dateVal.getFullYear() + '</a>';
    else if(view == 'year')
        return (dateVal.getFullYear() - 4) + ' - ' + (dateVal.getFullYear() + 7);
}

function getNavCode(dateFieldId, dateVal, adjust, view) {
    if(view == 'day') {
        var newMonth = (dateVal.getMonth () + adjust) % 12;
        var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12);
        if(newMonth < 0) {
            newMonth += 12;
            newYear += -1;
        }
        return '<a class="dpTitleNav" href="javascript:refreshDatePicker(\'day\', \'' + dateFieldId + '\', ' + newYear + ', ' + newMonth + ');">' + monthArrayShort[newMonth] + '</a>';
    }
    else if(view == 'month') {
        var newYear = dateVal.getFullYear() + adjust;
        return '<a class="dpTitleNav" href="javascript:refreshDatePicker(\'month\', \'' + dateFieldId + '\', ' + newYear + ');">' + newYear + '</a>';
    }
    else if(view == 'year') {
        var newYear = dateVal.getFullYear() + (adjust * 12);
        var label = (newYear - 4) + ' - ' + (newYear + 7);
        return '<a class="dpTitleNav" href="javascript:refreshDatePicker(\'yearspan\', \'' + dateFieldId + '\', ' + newYear + ');">' + label + '</a>';
    }
}

function getDateString(dateVal) {
  var dayString = '00' + dateVal.getDate();
  var monthString = '00' + (dateVal.getMonth()+1);
  dayString = dayString.substring(dayString.length - 2);
  monthString = monthString.substring(monthString.length - 2);
  var dateString = monthString + dateSeparator + dayString + dateSeparator + dateVal.getFullYear();
  if(dateFormat == 'long')
	  dateString += ' 12:00:00 AM';
  return dateString;
}

function getFieldDate(dateString) {
  var dateVal;        
  try {
	var dArray = splitDateString(dateString);
	if(dArray) {
	  var d = parseInt(dArray[1], 10);
	  var m = parseInt(dArray[0], 10) - 1;
	  var y = parseInt(dArray[2], 10);
	  dateVal = new Date(y, m, d);
	}
	else if(dateString)
	  dateVal = new Date(dateString);
	else
	  dateVal = new Date();
  } catch(e) {
	dateVal = new Date();
  }             
  return dateVal;
}

function splitDateString(dateString) {
  var dArray;
  if(dateString.indexOf('/') >= 0)
	dArray = dateString.split('/');
  else if(dateString.indexOf('.') >= 0)
	dArray = dateString.split('.');
  else if(dateString.indexOf('-') >= 0)
	dArray = dateString.split('-');
  else if(dateString.indexOf('\\') >= 0)
	dArray = dateString.split('\\');
  else
	dArray = false;             
  return dArray;
}

function updateDateField(dateFieldId, dateString) {
  var targetDateField = document.getElementById(dateFieldId);
  if(targetDateField && dateString)
	targetDateField.value = dateString;
  var pickerDiv = document.getElementById(datePickerDivId);
  //pickerDiv.style.visibility = 'hidden';
  pickerDiv.style.display = 'none';             
  adjustiFrame();
  targetDateField.focus();
  // after the datepicker has closed, optionally run a user-defined function called
  // datePickerClosed, passing the field that was just updated as a parameter
  // (note that this will only run if the user actually selected a date from the datepicker)
  if(dateString && typeof(datePickerClosed) == 'function')
	datePickerClosed(targetDateField);
}

function adjustiFrame() {
  if(navigator.userAgent.toLowerCase().indexOf('opera') != -1)
	return;
  try {
    var pickerDiv = document.getElementById(datePickerDivId);
    var iFrameDiv = document.getElementById(iFrameDivId);
	if(!iFrameDiv) {
	  // don't use innerHTML to update the body, because it can cause global variables
	  // that are currently pointing to objects on the page to have bad references
	  //document.body.innerHTML += '<iframe id="' + iFrameDivId + '" src="javascript:false;" scrolling="no" frameborder="0">';
	  var newNode = document.createElement('iFrame');
	  newNode.setAttribute('id', iFrameDivId);
	  newNode.setAttribute('src', 'javascript:false;');
	  newNode.setAttribute('scrolling', 'no');
	  newNode.setAttribute('frameborder', '0');
	  newNode.setAttribute('style', 'display:none');
	  document.body.appendChild(newNode);
	  iFrameDiv = document.getElementById(iFrameDivId);
	}
    iFrameDiv.style.position = 'absolute';
    iFrameDiv.style.width = pickerDiv.offsetWidth + 'px';
    iFrameDiv.style.height = pickerDiv.offsetHeight + 'px';
    iFrameDiv.style.top = pickerDiv.style.top;
    iFrameDiv.style.left = pickerDiv.style.left;
    iFrameDiv.style.zIndex = pickerDiv.style.zIndex - 1;
    //iFrameDiv.style.visibility = pickerDiv.style.visibility;
    iFrameDiv.style.display = pickerDiv.style.display;
  }
  catch(e) {
  }
}

function hideDatePicker(e) {
	if(!e) e = event;
	var pickerDiv = document.getElementById(datePickerDivId);
	var elem = e.srcElement || e.target;
	if(elem.className.indexOf('dp') != 0 && pickerDiv) {
		//pickerDiv.style.visibility = 'hidden';
		pickerDiv.style.display = 'none';
		adjustiFrame();
	}
}

// Attach event to hide datepicker when focus is lost
if (document.addEventListener)
    document.addEventListener("click", hideDatePicker, false);
else
    document.attachEvent("onclick", hideDatePicker);