/* This script and many more are available free online at
The JavaScript Source :: http://javascript.internet.com
Created by: Michael O'Connell :: http://wunder-ful.com */

/**
* Invocation represents a function call in a specific object context with a list of parameters
* This is a very powerful object that allows code to be executed in it's intended context
* from any other context (context = the 'this' for that function).
* There is a perfomance hit to use this (takes about 5x more time)
* WARNING in IE if you try to use invoke on an object that is in a window that is no longer loaded it will throw "can't execute code in freed script"
* @constructor
* @param targetObj object to invoke a method on (functions not on an object are attached to the window object)
* @param functionName string containing the name of the function to invoke on targetObj
* @param arguments an Array of arguments to invoke the function with (optional)
* @author Mike O'Connell
*/
function Invocation(targetObj, functionName, arguments) {
  this.targetObj = targetObj;
  this.functionName = functionName;
  this.arguments = arguments;
}

/**
* Actually invoke the function call defined by this instance of Invocation.
* If the object doesn't exist, or the function does not exist it will not try to execute
* @param arguments an Array of arguments to invoke the function with (will be appended to the end of the predefined argument Array)
* @return The return value of the function invoked.
*/
Invocation.prototype.invoke = function(arguments) {
  if(this.targetObj && typeof this.targetObj[this.functionName] == "function") {
    var args = this.arguments;
    if(!args)
      args = new Array();
    if(arguments)
      args = args.concat(arguments);
    return this.targetObj[this.functionName].apply(this.targetObj, args);
  }
}

/**
* @return the sum of all the offsetTop values from this element to the body
*/
function getTotalOffsetTop(element) {
  var offset = 0;
  for(var i = element; i && i.tagName != "BODY"; i = i.offsetParent)
    offset+=i.offsetTop;
  return offset;
}

/**
* @return the sum of all the offsetLeft values from this element to the body
*/
function getTotalOffsetLeft(element) {
  var offset = 0;
  for(var i = element; i && i.tagName != "BODY"; i = i.offsetParent)
    offset+=i.offsetLeft;
  return offset;
}

/**
* Positions a absolutely positioned element over the anchor.  It will detect body clipping
* and move the right side of the element to the right of the anchor.  The element cannot
* have 
* @param element the element to position
* @param anchor the anchor to position element over
* @param positionVertical position on "top" or "bottom" edge of the anchor
* @param positionHorizontal position on "left" or "right" edge of the anchor
*/
function positionAtAnchor(element, anchor, positionVertical, positionHorizontal) {
  var left = getTotalOffsetLeft(anchor);
  
  if(positionHorizontal == "right")
    left = left + anchor.offsetWidth + 1;

  //horizontal clip
  if(left + element.offsetWidth > document.body.scrollWidth && left - element.offsetWidth > 0) {
    left = left - element.offsetWidth;
    if(positionHorizontal == "right")
      left = left - anchor.offsetWidth;
    else
      left = left + anchor.offsetWidth + 1;
  }

  var top = getTotalOffsetTop(anchor);
  if(positionVertical == "bottom")
    top = top + anchor.offsetHeight + 1;

  if (!isNaN(top)) {
    element.style.top = top - element.offsetHeight - 1 + "px";
    element.style.left = left+"px";
  }
}


// ===========================

//map of dynaCalendars by name
var dynaCalendars = {};

/**
* Opens / closes the dynacalendar at the specified anchor
* @param name The unique name for the calendar to open.
* @param anchor A element to open the calendar under
**/
function openDynaCalendar(name, anchor) {
  var anchor = document.getElementById(name);
  var calendar = dynaCalendars[name];
  if(!calendar.isOpen)
    calendar.open(anchor);
  else
    calendar.close();
}

/**
* Constructor for the DynaCalendar
* @param name A unique name for this calendar
* @param invocation The function to pass the date when a date is selected. 
* @param year Year to start calendar.
* @param month Month to start calendar.
* @param day Day to start calendar.
* @see Invocation
**/
function DynaCalendar(name, invocation, year, month, day) {
  //populate day of week and month name constants if not previously created...
  if(!DynaCalendar.MONTHS) {
    var MONTHS_EN = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
    var MONTHS_BG = new Array("Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември");
    var DOW_EN = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
    var DOW_BG = new Array("Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб");

    var tmpDate = new Date(2000, 0, 1);
    var dateStr = tmpDate.toLocaleString();

    if (dateStr.search("Януари") > 0) {
      DynaCalendar.MONTHS = MONTHS_BG;
      DynaCalendar.DOW = DOW_BG;
    }
    else {
      DynaCalendar.MONTHS = MONTHS_EN;
      DynaCalendar.DOW = DOW_EN;
    }
  }

  if(year && month && day)
    this.date = new Date(year, month, day);
  else
    this.date = new Date();
  
  this.invocation = invocation;
  this.name = name;
  this.isOpen = false;
  this.rendered = false;
  this.bodyRendern = false;
          
  dynaCalendars[name] = this;
}

/**
* Displays the dynacalendar at the specified anchor.
* @param anchor A element to open the calendar under
*/
DynaCalendar.prototype.open = function(anchor) {
  if(!this.rendered)
    this.render();
  if(!this.bodyRendern)
    this.renderBody();
  this.calendarDiv.style.display = "block";
  positionAtAnchor(this.calendarDiv, anchor, "top", "left");
  this.isOpen = true;
}

/**
* Closes the dynaCalendar
*/
DynaCalendar.prototype.close = function() {
  this.calendarDiv.style.display = "none";
  this.isOpen = false;
}

/**
* Fills the calendarDiv with actual date spans
**/
DynaCalendar.prototype.render = function() {
  var calendarDiv = document.createElement("DIV");
  var calendarTable = document.createElement("TABLE");
  var calendarHead = document.createElement("THEAD");
  var calendarHeadTR = document.createElement("TR");
  var calendarHeadWeekTR = document.createElement("TR");
  var calendarBY = document.createElement("TH");
  var calendarBM = document.createElement("TH");
  var calendarTitle = document.createElement("TH");
  var calendarFM = document.createElement("TH");
  var calendarFY = document.createElement("TH");
  var calendarBody = document.createElement("TBODY");

  calendarDiv.className = "dynaCalendarDiv";
  calendarTable.className = "dynaCalendarTable";
  calendarTitle.colSpan = 3;
  
  calendarBY.className = "BF";
  calendarBM.className = "BF";
  calendarFM.className = "BF";
  calendarFY.className = "BF";
  calendarBY.innerHTML = "&lt;&lt;";
  calendarBM.innerHTML = "&lt;";
  calendarFM.innerHTML = ">";
  calendarFY.innerHTML = ">>";
  calendarBY.onclick = dynaCalendarBackYearOnClick;
  calendarBM.onclick = dynaCalendarBackMonthOnClick;
  calendarFM.onclick = dynaCalendarForwardMonthOnClick;
  calendarFY.onclick = dynaCalendarForwardYearOnClick;

  calendarDiv.dynaCalendar = this;
  calendarHead.dynaCalendar = this;
  calendarBody.dynaCalendar = this;
  calendarBY.dynaCalendar = this;
  calendarBM.dynaCalendar = this;
  calendarTitle.dynaCalendar = this;
  calendarFM.dynaCalendar = this;
  calendarFY.dynaCalendar = this;
  
  this.calendarTitle = calendarTitle;
  this.calendarBody = calendarBody;
  this.calendarDiv = calendarDiv;
  
  //populate week header
  for(var i = 0; i < 7; i++) {
    var dowTH = document.createElement("TH");
    dowTH.innerHTML = DynaCalendar.DOW[i];
    calendarHeadWeekTR.appendChild(dowTH);
  }
  calendarHeadTR.appendChild(calendarBY);
  calendarHeadTR.appendChild(calendarBM);
  calendarHeadTR.appendChild(calendarTitle);
  calendarHeadTR.appendChild(calendarFM);
  calendarHeadTR.appendChild(calendarFY);
  calendarHead.appendChild(calendarHeadTR);
  calendarHead.appendChild(calendarHeadWeekTR);
  calendarTable.appendChild(calendarHead);
  calendarTable.appendChild(calendarBody);
  calendarDiv.appendChild(calendarTable);
  document.body.appendChild(calendarDiv);

  this.rendered = true;
}

/**
* Renders the actual month.
**/
DynaCalendar.prototype.renderBody = function() {
  //title 
  var title = DynaCalendar.MONTHS[this.date.getMonth()]+ " " + this.date.getFullYear();
  this.calendarTitle.innerHTML = title;
  
  //clear table body
  while(this.calendarBody.hasChildNodes())
    this.calendarBody.removeChild(this.calendarBody.lastChild);
  
  //generate new table body
  var tmpDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1);

  var row = document.createElement("TR");
  this.calendarBody.appendChild(row);
  
  //blanks
  for(var i = 0; i < tmpDate.getDay(); i++) {
    var td = document.createElement("TD");
    row.appendChild(td);
  }
  
  while(tmpDate.getMonth() == this.date.getMonth()) {
    var td = document.createElement("TD");
    var date = tmpDate.getDate();
    if(date == this.date.getDate())
      td.className = "daySelected";
    else
      td.className = "day";
    
    td.innerHTML = date;
    td.dynaCalendar = this;
    td.onclick = dynaCalendarSelectDayOnClick;
    row.appendChild(td);
    
    if(tmpDate.getDay() == 6) {
      row = document.createElement("TR");
      this.calendarBody.appendChild(row);
    }
    
    tmpDate.setDate(date + 1);
  }
  
  //blanks 
  for(var i = tmpDate.getDay(); i < 7; i++) {
    var td = document.createElement("TD");
    row.appendChild(td);
  }
          
  this.bodyRendern = true;
}

/**
* Set the day of the month
* @param date The date of the month to set the calandar to.
**/
DynaCalendar.prototype.setDate = function(date) {
  this.date.setDate(date);
  this.bodyRendern = false;
}

/**
* Moves back a year
**/
DynaCalendar.prototype.backYear = function() {
  this.setDate(1);
  this.date.setFullYear(this.date.getFullYear() - 1);
  this.renderBody();
}

/**
* Moves back a month
**/
DynaCalendar.prototype.backMonth = function() {
  this.setDate(1);
  this.date.setMonth(this.date.getMonth() - 1);
  this.renderBody();
}

/**
* Moves forward a month
**/
DynaCalendar.prototype.forwardMonth = function() {
  this.setDate(1);
  this.date.setMonth(this.date.getMonth() + 1);
  this.renderBody();
}

/**
* Moves forward a year
**/
DynaCalendar.prototype.forwardYear = function() {
  this.setDate(1);
  this.date.setFullYear(this.date.getFullYear() + 1);
  this.renderBody();
}

// Event handlers -------------------------------------------------------------
/**
* onclick to select a day
*/
function dynaCalendarSelectDayOnClick(event) {
  //IE
  if(window.event) {
    var srcElement = window.event.srcElement;
  }
  //MOZ
  else {
    var srcElement = event.currentTarget;
  }
  
  var calendar = srcElement.dynaCalendar;
  calendar.setDate(srcElement.innerHTML);
  if(calendar.invocation)
    calendar.invocation.invoke([calendar.date]);

  var now = new Date();
  var newDate = new Date($("#pkp_date").val()+' 23:59');
  if(newDate < now)
  {
	$("#pkp_date").val('');
  	alert('Invalid date!');
  };
  $("#pkp_date").focus();
  $("#pkp_hour").focus();
  
  srcElement.dynaCalendar.close();

  return false;
}

/**
* onclick to go back one year
*/
function dynaCalendarBackYearOnClick(event) {
  //IE
  if(window.event) {
    var srcElement = window.event.srcElement;
  }
  //MOZ
  else {
    var srcElement = event.currentTarget;
  }

  srcElement.dynaCalendar.backYear();
  return false;
}

/**
* onclick to go back one month
*/
function dynaCalendarBackMonthOnClick(event) {
  //IE
  if(window.event) {
    var srcElement = window.event.srcElement;
  }
  //MOZ
  else {
    var srcElement = event.currentTarget;
  }

  srcElement.dynaCalendar.backMonth();
  return false;
}

/**
* onclick to go forward one month
*/
function dynaCalendarForwardMonthOnClick(event) {
  //IE
  if(window.event) {
    var srcElement = window.event.srcElement;
  }
  //MOZ
  else {
    var srcElement = event.currentTarget;
  }

  srcElement.dynaCalendar.forwardMonth();
  return false;
}

/**
* onclick to go forward one year
*/
function dynaCalendarForwardYearOnClick(event) {
  //IE
  if(window.event) {
    var srcElement = window.event.srcElement;
  }
  //MOZ
  else {
    var srcElement = event.currentTarget;
  }

  srcElement.dynaCalendar.forwardYear();
  return false;
}

// ===================================

function setup_cal() {
  var cal = new DynaCalendar("pkp_date",new Invocation(this,"change_pkp"));
  var cal = new DynaCalendar("ret_pkp_date",new Invocation(this,"change_ret"));
}

function change_pkp(date) {
  document.getElementById("pkp_date").value = (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear();
}

function change_ret(date) {
  document.getElementById("ret_pkp_date").value = (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear();
}

// =================================

//window.onload = setup_cal();





