//
// Some Regular Expressions for checking form data
// Use them in this way:
// if (expression.exec(value) == null) {
//   value is bad, process error here
// }
// else {
//   value is good, continue
// }
//

var reNumeric = /^[-0-9]+$/;
var reMoney = /^\d+(\.\d{1,2}){0,1}$/;
var reAlphaNumeric = /^[-a-zA-Z0-9\u0410-\u044f\u00c0-\u00ff]+$/;
var rePhone = /^[-\[\]\.\(\) a-zA-Z0-9]+$/;
var reCleanText = /^[-_\.a-zA-Z0-9\u0410-\u044f\u00c0-\u00ff]+([\s]*?[-_\.a-zA-Z0-9\u0410-\u044f\u00c0-\u00ff]+)*$/;
var reText = /^[-_\+=\.\,\/!@#\$%&*\(\)a-zA-Z0-9\u0410-\u044f\u00c0-\u00ff]+([\s]*?[-_\+=\.\,\/!@#\$%&*\(\)a-zA-Z0-9\u0410-\u044f\u00c0-\u00ff]+)*$/;
var reAnyText = /^\S+(\s*?\S+)*$/;
var reEmail = /^\w+[\w\-\.]*@\w+[\w\-\.]*\.\w{2,4}(,\w+[\w\-\.]*@\w+[\w\-\.]*\.\w{2,4})*$/;
var reStrict = /^[a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9]+)$/;
var reUserStrict = /^[a-zA-Z0-9]+([-_\. ]?[a-zA-Z0-9]+)$/;
var reUserLogin = /^[a-zA-Z0-9]+([a-zA-Z0-9\-_\.]+)$/;
var reTime = /^([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?$/;
var reDate = /^(\d+)-(\d+)-(\d+)$/;

var oTarget;

//
// Creates new window from form
// Parameters:
// Form - form to submit
// IsResizable - boolean
// IsBig - boolean, if true open window bigger than standart window
// Effect:
// Opens a window with name "Additional". Sets target of form to that windows and submits
// form.
//
function FormWindow(Form, IsResizable, IsBig) {
  if (window.event) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }

  var width = Math.ceil(screen.width/2);
  var height = Math.ceil(screen.height*0.6);
	if (IsBig)	{
		height += 100;
		width += 200;
	}
  if (width < 600) { width = 600; }
  if (height < 400) { height = 400; }
  var left;
  var top = Math.ceil(screen.height*0.1);
	if (IsBig) {
		left = Math.ceil(Math.abs(screen.width - width)/2);
	} else {
		left = Math.ceil(screen.width/4);
	}
  if (oTarget) {
    oTarget.close();
  }
	params = "height="+height+",width="+width+",scrollbars=1,left="+left+",top="+top;
	if (IsResizable) {
		params += ",resizable";
	}
  var time = (new Date()).getTime();
  oTarget = window.open("", "Additional" + time, params);
  oTarget.focus();
  Form.target = "Additional" + time;
  Form.submit();
};

//
// Creates new full-screen window from form
// Parameters:
// Form - form to submit
// Effect:
// Opens a full-screen window with name "FullAdditional". Sets target of form to that windows and
// submits form.
//
function FullFormWindow(Form) {
  if (window.event) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  var left = Math.ceil(screen.width/4);
  var top = Math.ceil(screen.height*0.1);
  var height = Math.ceil(screen.availHeight*0.99);
  var width = Math.ceil(screen.availWidth*0.99);
  var top = 0;
  var left = 0;
  if (oTarget) {
    oTarget.close();
  }
  var time = (new Date()).getTime();
  oTarget = window.open("", "FullAdditional" + time, "height="+height+",width="+width+",left="+left+",top="+top+",scrollbars=1,location=0,menubar=0,status=0,toolbar=0,resizable=1");
  oTarget.focus();
  Form.target = "FullAdditional" + time;
  Form.submit();
};

//
// Creates new window from link
// Parameters:
// Link - link to show in window
// IsResizable - boolean
// IsBig - boolean, if true open window bigger than standart window
// w - width of window. If ommitted, then width is calculated automatically
// h - height of window. If ommitted, then height is calculated automatically
// parameters - string of additional parameters
// noWindowMessage - message, which will be shown for user if popup blockers are "On"
// Effect:
// Opens a window with name "Additional" and shows needed link in it.
//
function LinkWindow(Link, IsResizable, IsBig, w, h, parameters, noWindowMessage) {
  if (window.event) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
	var width, height;
	try {
		width = Math.ceil(screen.width/2);
		height = Math.ceil(screen.height*0.6);
	}
	catch (error) {
		width = 600;
		height = 400;
	}
	if (IsBig)	{
		height += 60;
		width += 200;
	}
  if (width < 600) { width = 600; }
  if (height < 400) { height = 400; }
	if (w) {
		width = w;
	}
	if (h) {
		height = h;
	}
	var left, top;
	try {
		left = Math.ceil(Math.abs(screen.width - width)/2);
		if (height < 400) {
			top = Math.ceil(Math.abs(screen.height - height)/2);
		}
		else {
			top = Math.ceil(screen.height*0.1);
		}
	}
	catch (error) {
		left = 100;
		top = 100;
	}
  if (oTarget) {
    oTarget.close();
  }

	params = "height="+height+",width="+width+",scrollbars=1,left="+left+",top="+top;
	if (IsResizable) {
		params += ",resizable";
	}
	if (parameters) {
		params += parameters;
	}
	var time = (new Date()).getTime();
  oTarget = window.open(Link, "Additional" + time, params);
	if (oTarget == null) {
		if (noWindowMessage) {
			alert(noWindowMessage);
		}
	} else {
  	oTarget.focus();
	}
  return false;
};

//
// Creates new full-screen window from link
// Parameters:
// Link - to show in window
// Effect:
// Opens a full-screen window with name "FullAdditional" and shows needed link in it.
//
function FullLinkWindow(Link) {
  if (window.event) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }
  var height = Math.ceil(screen.availHeight*0.99);
  var width = Math.ceil(screen.availWidth*0.99);
  var top = 0;
  var left = 0;
  if (oTarget) {
    oTarget.close();
  }
  var time = (new Date()).getTime();
  oTarget = window.open(Link, "FullAdditional" + time, "height="+height+",width="+width+",left="+left+",top="+top+",scrollbars=1,location=0,menubar=0,status=0,toolbar=0,resizable=1");
  oTarget.focus();
  return false;
}

//
// Sets region list by country
// Parameters:
// Form - the form where country and region selects are located
// Effect:
// Modifies <select> named "RegionID" in the form. <select> will have regions
// for country which is selected in <select> with name "CountryID". Or, it will
// be disabled if no regions are available for selected country.
// List of all regions is stored in regiondb array and is initialized by PHP code.
//
function SetRegions(Form) {
  var Country = Form.elements["CountryID"];
  var Region = Form.elements["RegionID"];
  var i;
  // empty previous settings
  // get chosen value to act as index to regiondb hash table
  var choice = Country.options[Country.selectedIndex].value;
  var db = regiondb[choice];
  // insert default first item
  Region.disabled = false;
  Region.options.length = 0;
  if (db) {
    Region.options.length = db.length + 1;
    Region.options[0].value = "";
    Region.options[0].text = "-- " + getTranslation("choose-region") + " --";
    // loop through array of the hash table entry, and populate options
    for (i = 0; i < db.length; i++) {
      Region.options[i + 1].value = db[i].value;
      Region.options[i + 1].text = db[i].text;
    }
  } else {
    Region.options.length = 1;
    Region.options[0].value = "";
    Region.options[0].text = "-- " + getTranslation("choose-region") + " --";
    Region.disabled = true;
  }
};

//
// Returns selected value
// Parameters:
// Elm - <select> element
// Returns:
// Value attribute of selected <option>
//
function SelectedValue(Elm) {
  if (typeof(Elm) != "undefined") {
    if (Elm.selectedIndex < 0) {
      return null;
    } else {
      return Elm.options[Elm.selectedIndex].value;
    }
  }
  return null;
};

//
// Sets value of select
// Parameters:
// select - <select> element
// value - value to set
// Effect:
// value property of select is updated.
//
function selectValue(select, value) {
  var i;
  value = "" + value;
  select.value = value;
  if (select.value != value) {
    select.selectedIndex = -1;
    for (i = 0; i < select.options.length; i++) {
      if (select.options[i].value == value) {
        select.selectedIndex = i;
        break;
      }
    }
  }
}

//
// Returns selected text
// Parameters:
// Elm - <select> element
// Returns:
// Text of selected <option>
//
function SelectedText(Elm) {
  if (typeof(Elm) != "undefined") {
    if (Elm.selectedIndex < 0) {
      return null;
    } else {
      return Elm.options[Elm.selectedIndex].text;
    }
  }
  return null;
};

//
// Selects group of checkboxes
// Parameters:
// elm - what element is a "template" for selecting
// Number - index of element with name equal elm.name, that will be a "template" for selecting
// Name - name of element to select
// Effect:
// Selects group of checkboxes. It works in the following way:
// 1) Number'th (starting from 0) form element with name matching elm.name is found.
// 2) Status (checked/unchecked) of that element is saved.
// 3) For all elements that go in the form after found element and before next element with the same
// name - do the folowing: if it's name is equal to Name, then set it's status (checked/unchecked)
// to the same value which was in "template" element.
//
function SelectAll(elm, Number, Name) {
  var i, j = 0, sts;
  var elements = elm.form.elements;
  for (i = 0; i < elements.length; i++) {
    if (elements[i].name == elm.name) {
      if (j == Number) {
        sts = elements[i].checked;
        break;
      }
      j++;
    }
  }
  for (i++; i < elements.length; i++) {
    if (elements[i].name == Name) {
      elements[i].checked = sts;
      continue;
    }
    if (elements[i].name == elm.name) {
      break;
    }
  }
  return;
};

//
// Tests if value is found in array
// Parameters:
// value - value to find
// array - where to find
// Returns:
// If any element of array equals to value, then true is returned. Otherwise, false
// is returned.
//
function in_array(value, array) {
  var result = false;
  var n = array.length;
  var i;

  for (i = 0; i < n; i++) {
    if (array[i] == value) {
      result = true;
      break;
    }
  }

  return result;
};

//
// Updates days <select> for a group of <select>s
// Parameters:
// YearElement - year <select>
// MonthElement - month <select>
// DayElement - day <select>
// Effect:
// Function checks what month and year is selected now and updates day <select> to contain required
// number of days.
//
function UpdateDays(YearElement, MonthElement, DayElement) {
  var TestDate = new Date(SelectedValue(YearElement), SelectedValue(MonthElement) - 1, 31);
  var days = TestDate.getMonth() == SelectedValue(MonthElement) - 1 ? 31 : 31 - TestDate.getDate();

  while (DayElement.options.length > days) {
    DayElement.options[DayElement.options.length-1] = null;
  }
  while (DayElement.options.length < days) {
    DayElement.options[DayElement.options.length] =
        new Option(DayElement.options.length + 1, DayElement.options.length + 1);
  }
};

//
// Calculates sum of array elements
// Parameters:
// array - array
// Returns:
// Sum of all values in array.
//
function array_sum(array) {
  var i, result = 0;
  for (i = 0; i < array.length; i++) {
    result += 1 * array[i];
  }
  return result;
}

//
// Compares two dates
// Parameters:
// date1 - first date to compare
// date2 - second date to compare
// Returns:
// 0 if date1 and date2 are equal. Number less then 0 if date1 is less then date2. Number more then 0
// if date1 is more then date2.
//
function compareDates(date1, date2) {
  var time1 = getDateTimestamp(date1);
  var time2 = getDateTimestamp(date2);
  return time1 - time2;
}

//
// Checks that date is between two other dates.
// Parameters:
// date - date that should be tested for being between two other dates, MySQL format (YYYY-MM-DD)
// start - start date, MySQL format (YYYY-MM-DD)
// end - end date, MySQL format (YYYY-MM-DD)
// Returns:
// true if date is between start and end.
//
function dateBetween(date, start, end) {
  return compareDates(date, start) >= 0 && compareDates(date, end) <= 0;
}

//
// Tests if two date periods intersect.
// Parameters:
// start1 - start of first dates period
// end1 - end of first dates period
// start2 - start of second dates period
// end2 - end of second dates period
// Returns:
// true if periods defined by start1, end1 and start2, end2 intersect.
//
function datesIntersect(start1, end1, start2, end2) {
  return dateBetween(start1, start2, end2) || dateBetween(start2, start1, end1);
}

//
// Returns timestamp for date
// Parameters:
// date - date to use, MySQL format (YYYY-MM-DD)
// Returns:
// timestamp for given date. If given date is not in MySQL format, then current date is used.
//
function getDateTimestamp(date) {
  var parts = reDate.exec(date);
  var time;
  if (parts == null) {
    time = new Date();
  }
  else {
    time = new Date(parts[1], parts[2] - 1, parts[3]);
  }
  return Math.floor(time.getTime() / 1000);
}

//
// Compares two times
// Parameters:
// time1 - first time to compare
// time2 - second time to compare
// Returns:
// 0 if time1 and time2 are equal. Number less then 0 if time1 is less them time2. Number more then 0
// if time1 is more then time2.
//
function compareTimes(time1, time2) {
  var parts1, parts2;

  parts1 = time1.split(":");
  if (parts1.length < 2) {
    return 0;
  }

  parts2 = time2.split(":");
  if (parts2.length < 2) {
    return 0;
  }

  return (parts1[0] - parts2[0]) * 3600 +
      (parts1[1] - parts2[1]) * 60 +
      (parts1[2] == null ? 0 : parts1[2]) * 1 - (parts2[2] == null ? 0 : parts2[2]) * 1;
}

//
// Tests if time is between two other times
// Parameters:
// time - time to test
// start - start time of period
// end - end time of period
// wrap - if start & end should be considered as start & end of shift
// Returns:
// true if time is between start and end. If wrap is true, then start and end are considered as
// start and end of shift.
//
function timeBetween(time, start, end, wrap) {
  var difference;
  if (wrap) {
    difference = compareTimes(start, end);
    if (difference == 0) {
      return true;
    }
    if (difference > 0) {
      return compareTimes(time, start) >= 0 || compareTimes(time, end) <= 0;
    }
  }
  return compareTimes(time, start) >= 0 && compareTimes(time, end) <= 0;
}

//
// Returns difference between two dates/times
// Parameters:
// date1 - first date and time (YYYY-MM-DD HH:MM:SS)
// date2 - second date and time (YYYY-MM-DD HH:MM:SS)
// Returns:
// Difference (in seconds) between first and second date/time.
//
function timeDifference(date1, date2) {
	var re = /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/;
	var parts = re.exec(date1);
	var d1 = new Date(parts[1], parseInt(parts[2], 10) - 1, parts[3], parts[4], parts[5], parts[6]);
	parts = re.exec(date2);
	var d2 = new Date(parts[1], parseInt(parts[2], 10) - 1, parts[3], parts[4], parts[5], parts[6]);
	return (d1.getTime() - d2.getTime())/1000;
}

//
// Adds days to date/time
// Parameters:
// date - date and time (YYYY-MM-DD HH:MM:SS)
// days - number of days to add
// Returns:
// Adds days to date and returns the result in YYYY-MM-DD HH:MM:SS format.
//
function addDays(date, days) {
	var re = /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/;
	var parts = re.exec(date);
	var d = new Date(parts[1], parseInt(parts[2], 10) - 1, parts[3], parts[4], parts[5], parts[6]);
	d.setTime(d.getTime()+24*3600*1000);
	var result = d.getFullYear()+"-";
	var add = ""+(d.getMonth()+1);
	if (add.length < 2) {
		add = "0"+add;
	}
	result += add+"-";
	add = ""+d.getDate();
	if (add.length < 2) {
		add = "0"+add;
	}
	result += add+" ";
	add = ""+d.getHours();
	if (add.length < 2) {
		add = "0"+add;
	}
	result += add+":";
	add = ""+d.getMinutes();
	if (add.length < 2) {
		add = "0"+add;
	}
	result += add+":";
	add = ""+d.getSeconds();
	if (add.length < 2) {
		add = "0"+add;
	}
	return result+add;
}

//
// Tests if time period should be converted to two time periods
// Parameters:
// operationBegin - operation begin
// operationEnd - operation end
// start - start time of period
// end - end time of period
// Returns:
// true is time period represented by start and end should be converted to two time periods for
// given operationBegin and operationEnd.
//
function timeTwoPeriods(operationBegin, operationEnd, start, end) {
  if (start == "no" || end == "no" || end == "" || start == "") {
    return false;
  }
  if (compareTimes(operationBegin, operationEnd) != 0) {
    return false;
  }
  var opEndTime, opStartTime, endTime, startTime;
  opStartTime = getTimestamp(operationBegin);
  opEndTime = getTimestamp(operationEnd, operationBegin);
  endTime = getTimestamp(end, start);
  startTime = getTimestamp(start);
  while (startTime < opStartTime) {
    startTime += 24 * 60 * 60;
  }
  while (endTime <= startTime) {
    endTime += 24 * 60 * 60;
  }
  return endTime > opEndTime;
}

//
// Tests if two times intersect
// Parameters:
// start1 - start of first period
// end1 - end of first period
// start2 - start of second period
// end2 - end of second period
// Returns:
// true if time periods defined by start1 and end1 and start2 and end2 intersect. false otherwise.
//
function timeIntersect(start1, end1, start2, end2) {
	var s1, e1, s2, e2;
	s1 = getTimestamp(start1);
	e1 = getTimestamp(end1);
	while (e1 <= s1) {
		e1 += 24*3600;
	}
	s2 = getTimestamp(start2);
	e2 = getTimestamp(end2);
	while (e2 <= s2) {
		e2 += 24*3600;
	}
	return s2 < e1 && s1 < e2;
}

//
// Checks or unchecks checkboxes
// Parameters:
// check - true or false - if they should be checked or unchecked
// form - form where checkboxes should be checked/unchecked
// name - name of checkboxes
// Effect:
// If check is true, then checks checkboxes, otherwise unchecks them. Checkboxes are looked for in
// form. They should have name name.
//
function checkAll(check, form, name) {
  var i;
  for (i = 0; i < form.elements.length; i++) {
    if (form.elements[i].name == name) {
      form.elements[i].checked = check;
    }
  }
}

//
// Checks or unchecks first checkbox
// Parameters:
// form - form where checkbox should be checked or unchecked
// name - name of checkboxes
// Effect:
// form is scanned for checkboxes with name name. If second and all other checkboxes are checked, then
// checks first checkbox. Otherwise, uncheck it.
//
function checkFirst(form, name) {
  var i, count, status;

  count = 0;
  status = true;
  for (i = 0; i < form.elements.length; i++) {
    if (form.elements[i].name == name) {
      if (count == 0) {
        count++;
      }
      else if (!form.elements[i].checked){
        status = false;
        break;
      }
    }
  }
  for (i = 0; i < form.elements.length; i++) {
    if (form.elements[i].name == name) {
      form.elements[i].checked = status;
      break;
    }
  }
}

//
// Tests if at least one checkbox is checked
// Parameters:
// form - form where checkboxes should exist
// name - name of checkboxes
// Returns:
// true if at least one checkbox in form with name name is checked. false otherwise.
//
function isOneChecked(form, name) {
  var i;
  for (i = 0; i < form.elements.length; i++) {
    if (form.elements[i].name == name && form.elements[i].checked) {
      return true;
    }
  }
  return false;
}

//
// Returns hour part of time
// Parameters:
// time - time in MySQL format (HH:MM:SS)
// Returns:
// hour part of time without leading 0.
//
function getHours(time) {
  var parts;
  parts = reTime.exec(time);
  return parts == null ? null : parseInt(parts[1], 10);
}

//
// Returns next hour
// Parameters:
// hour - hour
// Returns:
// If hour+1 is less then 24, then returns it. Otherwise, returns 0
//
function nextHour(hour) {
  return hour + 1 > 23 ? 0 : hour + 1;
}

//
// Returns next day of week
// Parameters:
// day - day
// Returns:
// If day+1 is less then 7, then returns it. Otherwise, returns 0
//
function nextDay(day) {
  return parseInt(day, 10) + 1 > 6 ? 0 : parseInt(day, 10) + 1;
}

//
// Sets hours and minutes <select>s to specified time
// Parameters:
// time - time in MySQL format (HH:MM:SS)
// hours - <select> with hours
// minutes - <select> with minutes
// last - if true, then last matching value is selected
// Effect:
// time is parsed and corresponding hours and minutes are selected.
//
function setSelectsTime(time, hours, minutes, last) {
  var oldIndex;
  if (time == "" || time == "no") {
    oldIndex = hours.selectedIndex;
    selectValue(hours, time);
    if (hours.selectedIndex < 0) {
      hours.selectedIndex = oldIndex;
    }
    else {
      minutes.disabled = true;
    }
    return;
  }

  var parts = reTime.exec(time);
  if (parts != null) {
    if (last) {
      var i, value;
      value = parseInt(parts[1], 10);
      for (i = hours.options.length - 1; i >= 0; i--) {
        if (parseInt(hours.options[i].value, 10) == value) {
          hours.selectedIndex = i;
          break;
        }
      }
    }
    else {
      oldIndex = hours.selectedIndex;
      selectValue(hours, parts[1]);
      if (hours.selectedIndex < 0) {
        selectValue(hours, parts[1].length == 1 ? "0" + parts[1] : parseInt(parts[1], 10));
      }
      if (hours.selectedIndex < 0) {
        hours.selectedIndex = oldIndex;
      }
    }
    selectValue(minutes, parts[2]);
    if (minutes.selectedIndex < 0) {
      minutes.selectedIndex = 0;
    }
  }
}

//
// Converts time to seconds
// Parameters:
// time - time in MySQL format (HH:MM:SS)
// second parameter (optional) - minimum allowed time in MySQL format (HH:MM:SS)
// Returns:
// Number of seconds passed from 00:00:00. If second parameters is supplied, then function adds 24
// hours while returned time is less then or equal to second parameter.
//
function getTimestamp(time) {
  var parts;

  parts = ("" + time).split(":");
  if (parts.length < 2) {
    return 0;
  }

  time = parseInt(parts[0], 10) * 3600 + parseInt(parts[1], 10) * 60 +
      (parts.length < 3 || parts[2] == "" ? 0 : parseInt(parts[2], 10));
  if (arguments.length < 2) {
    return time;
  }

  var second;
  second = getTimestamp(arguments[1]);
  while (time <= second) {
    time += 24 * 60 * 60;
  }
  return time;
}

//
// Converts timestamp to MySQL format
// Parameters:
// timestamp - number of seconds
// seconds - whether or not seconds should be included in result
// Returns:
// If seconds is true, then time is returned in this format: HH:MM:SS
// Otherwise, time is returned in this format: HH:MM
//
function getTime(timestamp, seconds) {
  timestamp %= 24 * 60 * 60;
  var minutes = "" + Math.floor((timestamp % 3600)/60);
  if (minutes.length == 1) {
    minutes = "0" + minutes;
  }
  var result = Math.floor(timestamp / 3600) + ":" + minutes;
  if (seconds) {
    result += ":" + (timestamp % 60);
  }
  return result;
}

//
// Converts time to HH:MM format
// Parameters:
// time - time in MySQL format (HH:MM:SS)
// Returns:
// time converted to HH:MM format.
//
function getHMTime(time) {
  var re = /^(\d+:\d+):\d+$/;
  var reResult = re.exec(time);
  if (reResult == null) {
    return time;
  }
  return reResult[1];
}

//
// Sets start year, month & day if needed
// Parameters:
// endYear - <select> object that contains end year
// endMonth - <select> object that contains end month
// endDay - <select> object that contains end day
// startYear - <select> object that contains start year
// startMonth - <select> object that contains start month
// startDay - <select> object that contains start day
// Effect:
// If date represented by startYear, startMonth and startDay is more then date represented by
// endYear, endMonth and endDay, then startYear, startMonth and startDay are set to values of
// endYear, endMonth and endDay.
//
function setStartDate(endYear, endMonth, endDay, startYear, startMonth, startDay) {
	if (endYear.value != "1000" && startYear.value == "1000") {
		startYear.selectedIndex = startYear.options.length - 1;
	}
  if (endYear.selectedIndex > startYear.selectedIndex) {
    return;
  }
  if (endYear.selectedIndex == startYear.selectedIndex) {
    if (endMonth.selectedIndex > startMonth.selectedIndex) {
      return;
    }
    if (endMonth.selectedIndex == startMonth.selectedIndex) {
      if (endDay.selectedIndex >= startDay.selectedIndex) {
        return;
      }
    }
  }
  startYear.selectedIndex = endYear.selectedIndex;
  startMonth.selectedIndex = endMonth.selectedIndex;
  startDay.selectedIndex = endDay.selectedIndex;
}

//
// Sets end year, month & day if needed
// Parameters:
// startYear - <select> object that contains start year
// startMonth - <select> object that contains start month
// startDay - <select> object that contains start day
// endYear - <select> object that contains end year
// endMonth - <select> object that contains end month
// endDay - <select> object that contains end day
// Effect:
// If date represented by endYear, endMonth and endDay is less then date represented by startYear,
// startMonth and startDay, then endYear, endMonth and endDay are set to values of startYear,
// startMonth and startDay.
//
function setEndDate(startYear, startMonth, startDay, endYear, endMonth, endDay) {
	if (startYear.value == "1000") {
		selectValue(endYear, "1000");
	}
  if (startYear.selectedIndex < endYear.selectedIndex) {
    return;
  }
  if (startYear.selectedIndex == endYear.selectedIndex) {
    if (startMonth.selectedIndex < endMonth.selectedIndex) {
      return;
    }
    if (startMonth.selectedIndex == endMonth.selectedIndex) {
      if (startDay.selectedIndex <= endDay.selectedIndex) {
        return;
      }
    }
  }
  endYear.selectedIndex = startYear.selectedIndex;
  endMonth.selectedIndex = startMonth.selectedIndex;
  endDay.selectedIndex = startDay.selectedIndex;
}

//
// Sets start hours & minutes if needed
// Parameters:
// endHours - Select object that contains end hours
// endMinutes - Select object that contains end minutes
// startHours - Select object that contains start hours
// startMinutes - Select object that contains start minutes
// Effect:
// If time represented by startHours and startMinutes is more then time represented by
// endHours and endMinutes, then startHours and startMinutes are set to values of endHours and
// endMinutes.
//
function setStartHours(endHours, endMinutes, startHours, startMinutes) {
  if (endHours.value == "" || endHours.value == "no" || startHours.value == "no" ||
			startHours.value == "") {
    return;
  }
  if (startHours.selectedIndex > endHours.selectedIndex) {
    startHours.selectedIndex = endHours.selectedIndex;
  }
  if (startHours.selectedIndex == endHours.selectedIndex &&
      startMinutes.selectedIndex > endMinutes.selectedIndex) {
    startMinutes.selectedIndex = endMinutes.selectedIndex;
  }
}

//
// Sets end hours & minutes if needed
// Parameters:
// startHours - Select object that contains start hours
// startMinutes - Select object that contains start minutes
// endHours - Select object that contains end hours
// endMinutes - Select object that contains end minutes
// Effect:
// If time represented by endHours and endMinutes is less then time represented by
// startHours and startMinutes, then endHours and endMinutes are set to values of startHours and
// startMinutes.
//
function setEndHours(startHours, startMinutes, endHours, endMinutes) {
  if (endHours.value == "" || endHours.value == "no" || startHours.value == "no" ||
			startHours.value == "") {
    return;
  }
  if (endHours.selectedIndex < startHours.selectedIndex) {
    endHours.selectedIndex = startHours.selectedIndex;
  }
  if (endHours.selectedIndex == startHours.selectedIndex &&
      endMinutes.selectedIndex < startMinutes.selectedIndex) {
    endMinutes.selectedIndex = startMinutes.selectedIndex;
  }
}

//
// Colors used to colorify hours options
// Different options
//
var amFgColor = null, amBgColor = null, pmFgColor = null, pmBgColor = null;
var timeFormat = "S", startingDay = 1, needClose = false;

//
// Sets time format
// Parameters:
// format - time format to set
// Effect:
// Global variable which stores time format is set. That variable is used by other functions to
// display HTML elements.
//
function setTimeFormat(format) {
  timeFormat = format;
}

//
// Sets needClose flag
// Parameters:
// need - value of flag
// Effect:
// Global variable which stores needClose flag is set. That variable is used by other functions
// to display HTML elements.
//
function setNeedClose(need) {
  needClose = need;
}

//
// Sets starting day of week
// Parameters:
// day - day to set
// Effect:
// Global variable which stores starting day of week is set. That variable is used by other functions
// to display HTML elements.
//
function setStartingDay(day) {
  startingDay = day;
}

//
// Returns formatted hours
// Parameters:
// hour - hour to format
// Returns:
// Hour in format defined by timeFormat variable
//
function getFormattedHour(hour) {
  if (timeFormat == "M") {
    return hour;
  }
  var ap;
  if (hour < 12) {
    ap = getTranslation("am");
  }
  else {
    ap = getTranslation("pm");
    hour -= 12;
  }
  return (hour == 0 ? "12" : hour) + ap;
}

//
// Returns formatted time
// Parameters:
// time - time to format, in MySQL format (HH:MM:SS)
// start - if this is start time
// showMins - show with mins, if mins == 0
// Returns:
// Time in format defined by timeFormat variable
//
function getFormattedTime(time, start, showMins) {
  if (time == "") {
    return getTranslation(start ? "time-open-small" : "time-close-small");
  }
  if (time == "no") {
    return "";
  }
  var parts = time.split(":");
  if (parts != null && parts.length >= 2) {
    var hours = parseInt(parts[0], 10);
    var minutes = parseInt(parts[1], 10);
    if (timeFormat == "M") {
      return hours + ":" + (minutes >= 10 ? minutes : "0" + minutes);
    }
    else {
      var ap;
      if (hours < 12) {
        ap = getTranslation("am");
      } else {
        ap = getTranslation("pm");
        hours -= 12;
      }
      if (hours == 0) {
        hours = 12;
      }
      if (minutes == 0) {
		if (showMins) {
			return hours + ":00" + ap;
		}
		else {
        	return hours + ap;
		}
      }
      return hours + ":" + (minutes >= 10 ? minutes : "0" + minutes) + ap;
    }
  }
  else {
    return null;
  }
}

//
// Sets foreground and background colors.
// Parameters:
// fgColor - foreground color
// bgColor - background color
// Effect:
// Global variables which store colors for AM hours are set. Those variables are used by other
// functions to display HTML elements with needed colors.
//
function setAMColor(fgColor, bgColor) {
  amFgColor = fgColor;
  amBgColor = bgColor;
}

//
// Sets foreground and background colors.
// Parameters:
// fgColor - foreground color
// bgColor - background color
// Effect:
// Global variables which store colors for PM hours are set. Those variables are used by other
// functions to display HTML elements with needed colors.
//
function setPMColor(fgColor, bgColor) {
  pmFgColor = fgColor;
  pmBgColor = bgColor;
}

//
// Sets foreground and background colors of hours select
// Parameters:
// select - <select> object that contains list of hours
// Effect:
// Colors of <option> elements is set according to values previously set up by
// setAMColor/setPMColor/setTimeFormat
//
function setHoursColor(select) {
  if (timeFormat == "M") {
    return;
  }

  var i, value, hour, style, fg, bg;

  for (i = 0; i < select.options.length; i++) {
    value = select.options[i].value;
    if (reNumeric.exec(value) == null) {
      continue;
    }
    hour = parseInt(value, 10);
    style = select.options[i].style;
    if (hour < 12) {
      fg = amFgColor;
      bg = amBgColor;
    }
    else {
      fg = pmFgColor;
      bg = pmBgColor;
    }
    if (fg) {
      style.color = fg;
    }
    if (bg) {
      style.backgroundColor = bg;
    }
  }
}

//
// Fills hours select
// Parameters:
// hours - <select> object
// start - start time, MySQL format (HH:MM:SS)
// end - end time, MySQL format (HH:MM:SS)
// close - if Close option should be added
// shifts - array of shifts, in format HH:MM:SS-HH:MM:SS
// colors - array of colors, in format #RRGGBB
// Effect:
// <select> is filled with options for all hours between start and end
//
function fillHoursSelect(hours, start, end, close, shifts, colors) {
  var last = getHours(end);
  var current = getHours(start);
  var option;
	var ovalue;

  do {
		ovalue = getFormattedHour(current);
		if (ovalue == "12am") {
			ovalue = "12am "+getTranslation("Midnight");
		}
		if (ovalue == "12pm") {
			ovalue = "12pm "+getTranslation("Noon");
		}
    hours.options[hours.options.length] = new Option(ovalue, current);
    current = nextHour(current);
  } while (current != last);
	ovalue = getFormattedHour(last);
	if (ovalue == "12am") {
		ovalue = "12am "+getTranslation("Midnight");
	}
	if (ovalue == "12pm") {
		ovalue = "12pm "+getTranslation("Noon");
	}
  hours.options[hours.options.length] = new Option(ovalue, last);
  hours.options[hours.options.length] = new Option(getTranslation("time-no"), "no");
  if (needClose) {
    hours.options[hours.options.length] =
				new Option(getTranslation(close ? "time-close" : "time-open"), "");
  }
  if (shifts) {
    var reShift = /^(\d+:\d+(:\d+)?)-(\d+:\d+(:\d+)?)$/;
    var i, parts;
    for (i = 0; i < shifts.length; i++) {
      parts = reShift.exec(shifts[i]);
      if (parts != null) {
        option = new Option(getFormattedTime(parts[1], true) + "-" +
						getFormattedTime(parts[3], false), shifts[i]);
        if (colors && colors[i]) {
          option.style.backgroundColor = colors[i];
        }
        hours.options[hours.options.length] = option;
      }
    }
  }
  setHoursColor(hours);
}

//
// Fills minutes select
// Parameters:
// minutes - <select> object
// Effect:
// <select> is filled with options for all minutes
//
function fillMinutesSelect(minutes, scheduling) {
  if (scheduling == 5) {
    minutes.options[minutes.options.length] = new Option("00", "00");
    minutes.options[minutes.options.length] = new Option("05", "05");
    minutes.options[minutes.options.length] = new Option("10", "10");
    minutes.options[minutes.options.length] = new Option("15", "15");
    minutes.options[minutes.options.length] = new Option("20", "20");
    minutes.options[minutes.options.length] = new Option("25", "25");
    minutes.options[minutes.options.length] = new Option("30", "30");
    minutes.options[minutes.options.length] = new Option("35", "35");
    minutes.options[minutes.options.length] = new Option("40", "40");
    minutes.options[minutes.options.length] = new Option("45", "45");
    minutes.options[minutes.options.length] = new Option("50", "50");
    minutes.options[minutes.options.length] = new Option("55", "55");
  } else {
    minutes.options[minutes.options.length] = new Option("00", "00");
    minutes.options[minutes.options.length] = new Option("15", "15");
    minutes.options[minutes.options.length] = new Option("30", "30");
    minutes.options[minutes.options.length] = new Option("45", "45");
  }
}

//
// Fills days select
// Parameters:
// days - <select> object
// Effect:
// <select> is filled with options for all days
//
function fillDaysSelect(days) {
  var names = [getTranslation("sunday"), getTranslation("monday"), getTranslation("tuesday"),
      getTranslation("wednesday"), getTranslation("thursday"), getTranslation("friday"),
      getTranslation("saturday")];
  var current = startingDay;
  do {
    days.options[days.options.length] = new Option(names[current], current);
    current = nextDay(current);
  } while(current != startingDay);
}

//
// Hides calendar windows
// Effect:
// Hides calendar windows
//
function hideCalendar() {
	var element;
	if (element = window.popCalSchedule) {
		if (element.style.display) {
			element.style.display = "none";
		}
		if (element.style.visibility) {
			element.style.visibility = "hidden";
		}
	} else if (element = document.getElementById("popCalSchedule")) {
		if (element.style.display && element.style.display != "none") {
			element.style.display = "none";
		}
		if (element.style.visibility) {
			element.style.visibility = "hidden";
		}
	}
	if (element = window.popCal) {
		if (element.style.display) {
			element.style.display = "none";
		}
		if (element.style.visibility) {
			element.style.visibility = "hidden";
		}
	} else if (element = document.getElementById("popCal")) {
		if (element.style.display && element.style.display != "none") {
			element.style.display = "none";
		}
		if (element.style.visibility) {
			element.style.visibility = "hidden";
		}
	}
}

//
// Variables to support "dialogs"
//
var dialogParameters, dialogWindow;

//
// Shows "dialog"
// Parameters:
// page - URL of page to show
// parameters - parameters that should be used by opened window
// features - features that should be used by opened window, format like in showModalDialog method
// Effect:
// New window is opened and page is loaded into it.
//
function compatShowDialog(page, parameters, features) {
  dialogParameters = parameters;
  var allFeatures = new Array();
  var re, reResult;
  re = /dialogHeight\s*:\s*(\d+)/;
  if (reResult = re.exec(features)) {
    allFeatures[allFeatures.length] = "height=" + reResult[1];
  }
  re = /dialogWidth\s*:\s*(\d+)/;
  if (reResult = re.exec(features)) {
    allFeatures[allFeatures.length] = "width=" + reResult[1];
  }
  re = /resizable\s*:\s*(yes|on|1)/i;
  if (reResult = re.exec(features)) {
    allFeatures[allFeatures.length] = "resizable=yes";
  } else {
    allFeatures[allFeatures.length] = "resizable=no";
  }
  re = /status\s*:\s*(yes|on|1)/i;
  if (reResult = re.exec(features)) {
    allFeatures[allFeatures.length] = "status=yes";
  } else {
    allFeatures[allFeatures.length] = "status=no";
  }
  re = /scroll\s*:\s*(no|off|0)/i;
  if (reResult = re.exec(features)) {
    allFeatures[allFeatures.length] = "scrollbars=no";
  } else {
    allFeatures[allFeatures.length] = "scrollbars=yes";
  }
  if (dialogWindow) {
    dialogWindow.close();
  }
  var time = (new Date()).getTime();
  dialogWindow = window.open(page, "DialogWindow" + time, allFeatures.join(","));
}

//
// Called when loading of page is completed
// Effect:
// Element with loadingDiv id is hidden, mainDiv id is displayed
//
function pageLoaded() {
	document.getElementById("loadingDiv").style.display = "none";
	document.getElementById("mainDiv").style.display = "block";
}

//
// "MAIN"
//
if (navigator.appName != "Microsoft Internet Explorer") {
  window.showModalDialog = compatShowDialog;
  window.showModelessDialog = compatShowDialog;
  if (window.opener && window.opener.dialogParameters) {
    window.dialogArguments = window.opener.dialogParameters;
  }
}

//
// Converts timestamp to MySQL format
// Parameters:
// timestamp - number of seconds
// Returns:
// date is returned in this format: YYYY-MM-DD
//
function getCurDate(timestamp) {
  var date = new Date(timestamp*1000);
	var result = date.getFullYear() +"-"+
		(date.getMonth() < 9 ? "0" : "") +
		(date.getMonth()+1) + "-" +
		(date.getDate() < 10 ? "0" : "") +
		date.getDate();
	return result;
}

//
// Converts timestamp to MySQL format
// Parameters:
// timestamp - number of seconds
// seconds - whether or not seconds should be included in result
// Returns:
// If seconds is true, then time is returned in this format: HH:MM:SS
// Otherwise, time is returned in this format: HH:MM
//
function getCurTime(timestamp, seconds) {
  var date = new Date(timestamp*1000);
	var result = (date.getHours() < 10 ? "0" : "") +
		date.getHours() +":"+
		(date.getMinutes() < 10 ? "0" : "") + date.getMinutes() +
		(seconds ? (":" + (date.getSeconds() < 10 ? "0" : "") + date.getSeconds()) : "");
	return result;
}

//
// removes left and right spaces from string
// Parameters:
// str - some string
// Returns:
// string without left and right spaces
//
function trim(str)
{
	str = str.replace(/^(\s)*/, "");
	str = str.replace(/(\s)*$/, "");
	return str;
}

//
// opens training wizard window
// Parameters:
// url - url to open (page 'pop_wizard.php' with parameter PageName)
// Returns:
// window object reference, if popup is open, null otherwize
//
function OpenWizardWindow(url) {
	if (!url) {
		url = 'pop_wizard.php';
	}
	return LinkWindow(url, true, true, 800, 600, ',titlebar=0,status=0,toolbar=0,menubar=0,location=0', getTranslation('turn-off-popup-blockers'));
}

