function parseDate(dateString)
{
  var retVal = null;
  if (typeof(dateString) ==  "string")
  {
    var tArray = dateString.split("-");
    if (tArray.length == 3)
    {
      retVal = new Date(tArray[0], tArray[1] - 1, tArray[2]);
      if (tArray[0] >= 0 && tArray[0] < 100)
        retVal.setFullYear(tArray[0]);
    }
    else if (tArray.length == 4)
      retVal = new Date(-tArray[1], tArray[2] - 1, tArray[3]);
    else if (tArray.length == 2 && dateString.length == 9)
      retVal = new Date(dateString.substr(0, 5), dateString.substr(5, 2) - 1, dateString.substr(7, 2));
    else if (tArray.length == 1 && dateString.length == 8)
    {
      var year = dateString.substr(0, 4);
      retVal = new Date(year, dateString.substr(4, 2) - 1, dateString.substr(6, 2));
      if (year >= 0 && year < 100)
        retVal.setFullYear(year);
    } 
  }
  return retVal;
}

function DateValidityState()
{
  this.typeMismatch = false;
  this.stepMismatch = false;
  this.rangeUnderflow = false;
  this.rangeOverflow = false;
  this.tooLong = false;
  this.patternMismatch = false;
  this.valueMissing = false;
  this.customError = false;
  this.valid = true;
  
  this.update = function()
  {
    this.valid = !(this.typeMismatch || this.rangeUnderflow || this.rangeOverflow || this.tooLong || this.patternMismatch || this.valueMissing || this.customError);
  }
}

function inputTypeDate(target)
{
  //Copy values from attributes, or if the
  //attributes aren't present, set the defaults.
  var originalDate = parseDate(target.value);
  var now = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
  if (originalDate)
    now = new Date(originalDate.getTime());
  now.setDate(1);
  
  var max = parseDate(target.max); 
  var min = parseDate(target.min);
  var step = target.step;
    
  
  //Get the original calendar, and insert it into
  //the document.
  var cal = new Calendar(now, originalDate, returnValue, max, min, step);
  var containerSpan = document.createElement("span");
  containerSpan.className = "calendar-container";
  containerSpan.appendChild(cal);
  target.parentNode.replaceChild(containerSpan, target);
  containerSpan.appendChild(target);
  if (document.addEventListener)
    document.addEventListener("click", clearHandlers, false);
  else if (document.attachEvent)
    document.attachEvent("onclick",  clearHandlers);
  
  cal.style.top = target.offsetTop + "px";
  cal.style.left = target.offsetLeft + "px";
  
  function returnValue(value)
  {
    var oldValue = target.value;
    if (value != null)
    {
      target.value = value;
    }
    clearHandlers();
    
    var prefHandler = target.oninput;
    var handler = target.getAttribute("oninput");
    if (prefHandler)
    {
      var hEvt = null
      if (document.createEvent)
      {
        hEvt = document.createEvent("HTMLEvents");
        hEvt.initEvent("input", true, false);
      }
      else if (document.createEventObject)
      {
        hEvt = new Object();
        hEvt.type = "input";
        hEvt.srcElement = target;
      }
      prefHandler(hEvt);
    }
    else if (handler)
      eval(handler);
    
    if (document.createEvent)
    {
      var inpEvt = document.createEvent("HTMLEvents");
      inpEvt.initEvent("input", true, false);
      target.dispatchEvent(inpEvt);
      
      if (oldValue == "")
      {
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent("change", true, false);
        target.dispatchEvent(evt);
      }
    }
    else if (document.createEventObject)
    {
      var evt = document.createEventObject();
      evt.type = "change";
      evt.srcElement = target;
      target.fireEvent("onchange", evt);
    }
  }
  
  function clearHandlers(event)
  {
    if (containerSpan && containerSpan.parentNode && containerSpan.parentNode.className.indexOf("calendar-container") == -1)
    {
      containerSpan.parentNode.replaceChild(target, containerSpan);
    }
    if (document.detachEvent)
    {
      window.event.cancelBubble = true;
      document.detachEvent("onclick", clearHandlers);
    }
    if (document.removeEventListener)
    {
      if (event)
        event.cancelBubble = true;
      document.removeEventListener("click", clearHandlers, false);
    }
  }
}
function Calendar(now, originalDate, returnValue, max, min, step)
{
  var cal = document.createElement("div");
  cal.className = "calendar";
  var calClickCatch = function(event) { event.cancelBubble = true; };
  if (cal.addEventListener)
    cal.addEventListener("click", calClickCatch, false);
  else if (cal.attachEvent)
    cal.attachEvent("onclick", calClickCatch);
  
  var prevYear = document.createElement("div");
  cal.appendChild(prevYear);
  prevYear.className = "previous-year";
  var prevYearDate = subtractOneYearFromDate(now);
  if (prevYearDate >= min)
  {
    prevYear.appendChild(document.createTextNode("<<"));
    var prevYearClick = function(event) {
      var nCal = new Calendar(prevYearDate, originalDate, returnValue, max, min, step);
      nCal.style.top = cal.style.top;
      nCal.style.left = cal.style.left;
      cal.parentNode.replaceChild(nCal, cal);
      event.cancelBubble = true;
    };
    if (prevYear.addEventListener)
      prevYear.addEventListener("click", prevYearClick, false);
    else if (prevYear.attachEvent)
      prevYear.attachEvent("onclick", prevYearClick);
  }
  else
    prevYear.appendChild(document.createTextNode(" "));
  
  var prevMonth = document.createElement("div");
  cal.appendChild(prevMonth);
  prevMonth.className = "previous-month";
  var prevMonthDate = subtractOneMonthFromDate(now);
  if (prevMonthDate >= min)
  {
    prevMonth.appendChild(document.createTextNode("<"));
    var prevMonthClick = function(event) {
      var nCal = new Calendar(prevMonthDate, originalDate, returnValue, max, min, step);
      nCal.style.top = cal.style.top;
      nCal.style.left = cal.style.left;
      cal.parentNode.replaceChild(nCal, cal);
      event.cancelBubble = true;
    };
    if (prevMonth.addEventListener)
      prevMonth.addEventListener("click", prevMonthClick, false);
    else if (prevMonth.attachEvent)
      prevMonth.attachEvent("onclick", prevMonthClick);
  }
  else
    prevMonth.appendChild(document.createTextNode(" "));
  
  var monthNames = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
  var monthDiv = document.createElement("div");
  cal.appendChild(monthDiv);
  monthDiv.className = "month";
  monthDiv.appendChild(document.createTextNode(monthNames[now.getMonth()]));
  monthDiv.appendChild(document.createTextNode(" "));
  monthDiv.appendChild(document.createTextNode(now.getFullYear()));
  
  var nextMonth = document.createElement("div");
  cal.appendChild(nextMonth);
  nextMonth.className = "next-month";
  var nextMonthDate = addOneMonthToDate(now);
  if (nextMonthDate <= max)
  {
    nextMonth.appendChild(document.createTextNode(">"));
    var nextMonthClick = function(event) {
      var nCal = new Calendar(nextMonthDate, originalDate, returnValue, max, min, step);
      nCal.style.top = cal.style.top;
      nCal.style.left = cal.style.left;
      cal.parentNode.replaceChild(nCal, cal);
      event.cancelBubble = true;
    };
    if (nextMonth.addEventListener)
      nextMonth.addEventListener("click", nextMonthClick, false);
    else if (nextMonth.attachEvent)
      nextMonth.attachEvent("onclick", nextMonthClick);
  }
  else
    nextMonth.appendChild(document.createTextNode(" "));
  
  var nextYear = document.createElement("div");
  cal.appendChild(nextYear);
  nextYear.className = "next-year";
  var nextYearDate = addOneYearToDate(now);
  if (nextYearDate <= max)
  {
    nextYear.appendChild(document.createTextNode(">>"));
    var nextYearClick = function(event) {
      var nCal = new Calendar(nextYearDate, originalDate, returnValue, max, min, step);
      nCal.style.top = cal.style.top;
      nCal.style.left = cal.style.left;
      cal.parentNode.replaceChild(nCal, cal);
      event.cancelBubble = true;
    };
    if (nextYear.addEventListener)
      nextYear.addEventListener("click", nextYearClick, false);
    else if (nextYear.attachEvent)
      nextYear.attachEvent("onclick", nextYearClick);
  }
  else
    nextYear.appendChild(document.createTextNode(" "));
  
  var dayLetters = "SMTWTFS";
  for (var i = 0; i < dayLetters.length; i++)
    cal.appendChild(nonDayBox(dayLetters.charAt(i)));
  
  //Sets up the date body of the Calendar
  var tempDate = new Date(now.getTime());
  tempDate.setDate(1);
  var month = tempDate.getMonth();
  for (var j = tempDate.getDay(); j > 0; j--)
    cal.appendChild(nonDayBox());
  while (tempDate.getMonth() == month)
  {
    var littleDate = new Date(tempDate.getTime());
    cal.appendChild(dayBox(littleDate));
    tempDate.setDate(tempDate.getDate() + 1);
  }
  
  if (tempDate.getDay() != 0)
    for (var k = tempDate.getDay(); k < 7; k++)
      cal.appendChild(nonDayBox());
  
  cal.appendChild(todayBox());
  cal.appendChild(noDayBox());
  
  
  
  return cal;

  function noDayBox()
  {// Allows you to select no value
	
	var boxClick = function(event) {returnValue("");};
	var box = nonDayBox("None", boxClick);
	box.className = "extraopt";
	return box;
  }
  
  function todayBox()
  {// Allows you to select no value
	
	var boxClick = function(event) {
		var today = new Date();
		 var nMonth = (today.getMonth() + 1).toString();
		if (nMonth.length != 2)
		  nMonth = "0" + nMonth;
		var nDate = today.getDate().toString();
		if (nDate.length != 2)
		  nDate = "0" + nDate;
		returnValue(today.getFullYear() + "-" + nMonth + "-" + nDate);
	};
	var box = nonDayBox("Today", boxClick);
	box.className = "extraopt";
	return box;
  }
 
  function nonDayBox(contents, boxClick)
  {
    var box = document.createElement("div");
    if (contents != null)
    {
      box.className = "header";
      box.appendChild(document.createTextNode(contents));
      if(boxClick != null)
      {
	if (box.addEventListener)
		box.addEventListener("click", boxClick, false);
	else if (box.attachEvent)
		box.attachEvent("onclick", boxClick);
      }
    }
    else
    {
      box.className = "blank-day";
      box.appendChild(document.createTextNode(" "));
    }
    return box;
  }
  
  function dayBox(boxDate)
  {
    var unselectable = false;
    if (boxDate < min || boxDate > max)
      unselectable = true;
    
    var lowBar = new Date(0);
    if (min.getTime() != -1e15)
      lowBar = new Date(min.getTime());
    
    var offset = Math.ceil((boxDate.getTime() - lowBar.getTime()) / 86400000);
    if (offset % new Number(step) != 0)
      unselectable = true;

    var box = document.createElement("div");
    box.className = "day";
    var today = new Date();
    if (originalDate != null && originalDate.getTime() == boxDate.getTime())
      box.className += " current";
    
    if (today.getTime() == boxDate.getTime())
      box.className += " today";
    
    if (boxDate.getDay() == 0 || boxDate.getDay() == 6)
      box.className += " weekend";
    else
      box.className += " weekday";
    
    if (unselectable)
      box.className += " unselectable";
    
    box.appendChild(document.createTextNode(boxDate.getDate()));
    if (!unselectable)
    {
      var boxClick = function(event) {
        now.setDate(boxDate.getDate());
        var nMonth = (now.getMonth() + 1).toString();
        if (nMonth.length != 2)
          nMonth = "0" + nMonth;
        var nDate = now.getDate().toString();
        if (nDate.length != 2)
          nDate = "0" + nDate;
        returnValue(now.getFullYear() + "-" + nMonth + "-" + nDate);
      };
      if (box.addEventListener)
        box.addEventListener("click", boxClick, false);
      else if (box.attachEvent)
        box.attachEvent("onclick", boxClick);
    }
    
    return box;
  }
}

function browserSupportsInputTypeDate()
{
	var i = document.createElement("input");
	//Next, set the type attribute on the dummy <input> element to the input type you want to detect.
	i.setAttribute("type", "date");
	//If your browser supports that particular input type, the type property will retain the value you set. If your browser doesn’t support that particular input type, it will ignore the value you set and the type property will still be "text".
	return i.type !== "text";
}

function inputTypeDateInit()
{
  if(browserSupportsInputTypeDate()) return;
  var inputs = document.getElementsByTagName("input");
  for (var i = 0; i < inputs.length; i++)
  {
    var ctl = inputs[i];
    if (ctl.getAttribute("type") == "date" && (!ctl.attached || ctl.attached == null) && !ctl.disabled && !ctl.readonly)
    {
      ctl.onfocus = function() { inputTypeDate(this); };
      ctl.readonly = true;
      ctl.attached = true;
      
      var required = false;
      if (ctl.getAttribute("required") == "required")
        required = true;
      ctl.required = required;
      ctl.validity = new DateValidityState();
      if (ctl.getAttribute("name") != null && (ctl.form || ctl.getAttribute("form")))
        ctl.willValidate = true;
      else
        ctl.willValidate = false;
      
      var min = ctl.getAttribute("min");
      if (parseDate(min))
        ctl.min = min;
      else
        ctl.min = "-33000-01-01";
      
      var max = ctl.getAttribute("max");
      if (parseDate(max))
        ctl.max = max;
      else
        ctl.max = "33000-01-01";
        
      var step = ctl.getAttribute("step");
      var nStep = Number(step);
      if (!step || isNaN(step))
        ctl.step = 1;
      else
        ctl.step = step;
       
      
      ctl.checkValidity = function() {
       ctl.validity.valueMissing = (required && ctl.value == "");
       ctl.validity.update();
        
        if (!ctl.validity.valid)
        {
          if (document.createEvent)
          {
            var evt = document.createEvent("HTMLEvents");
            evt.initEvent("invalid", true, true);
            ctl.dispatchEvent(evt);
            
            var prefHandler = ctl.oninvalid;
            var handler = ctl.getAttribute("oninvalid");
            if (prefHandler instanceof Function)
              prefHandler(evt);
            else if (handler)
              eval(handler);
          }
          else if (document.createEventObject)
          {
            var prefHandler = ctl.oninvalid;
            var handler = ctl.getAttribute("oninvalid");
            if (prefHandler instanceof Function)
            {
              var evt = new Object();
              evt.type = "invalid";
              evt.srcElement = ctl;
              prefHandler(evt);
            }
            else if (handler)
            {
              eval(handler);
            } 
          }
        }
        
        return ctl.validity.valid;
      }
      
      if (ctl.getAttribute("autofocus") == "autofocus")
      {
        ctl.autofocus = true;
        ctl.focus();
      }
      else
        ctl.autofocus = false;
        
    }
  }
  
  window.setTimeout(inputTypeDateInit, 200);
}

if (window.addEventListener)
  window.addEventListener("load", inputTypeDateInit, false);
else
  window.attachEvent("onload", inputTypeDateInit);

function addOneYearToDate(now)
{
  var year = now.getFullYear();
  var month = now.getMonth();
  var nDate = addOneMonthToDate(now);
  
  while (year == nDate.getFullYear() || month != nDate.getMonth())
    nDate = addOneMonthToDate(nDate);
  return nDate;
}

function addOneMonthToDate(now)
{
  var nDate = new Date(now.getTime());
  var month = nDate.getMonth();
  while (nDate.getMonth() == month)
    nDate.setDate(nDate.getDate() + 1);
  
  return nDate;
}

function subtractOneMonthFromDate(now)
{
  var nDate = new Date(now.getTime());
  nDate.setDate(-1);
  
  return nDate;
}

function subtractOneYearFromDate(now)
{
  var year = now.getFullYear();
  var month = now.getMonth();
  var nDate = subtractOneMonthFromDate(now);
  
  while (year == nDate.getFullYear() || month != nDate.getMonth())
    nDate = subtractOneMonthFromDate(nDate);
  return nDate;
}

