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)
      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("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Pa¼", "Lis", "Gru");
  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 = "NPW¦CPS";
  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());
  
  return cal;
  
  function nonDayBox(contents)
  {
    var box = document.createElement("div");
    if (contents != null)
    {
      box.className = "header";
      box.appendChild(document.createTextNode(contents));
    }
    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 inputTypeDateInit()
{
  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;
}

