function sortBy(formName, columnName, sortDirection)
{
   // We have to find the form like this because the syntax
   // document.forms[formName] does not appear to work.

   allForms = document.getElementsByTagName("FORM");

   for (i = 0; i < allForms.length; i++)
   {
      if (allForms[i].name == formName)
         form = allForms[i];
   }

   form.HTMLifierSortField.value = columnName;
   form.HTMLifierSortDirection.value = sortDirection;
   form.submit();
}

// Menus are the popup windows used in some of the reports to allow
// more than one action to be taken when clicking an item description etc
function showMenu(menuID)
{
   if (document.selectedMenu)
      document.selectedMenu.style.visibility = 'hidden';

   document.selectedMenu = document.getElementById(menuID);

   if (document.selectedMenu)
      document.selectedMenu.style.visibility = 'visible';
}

function hideMenu()
{
   if (document.selectedMenu)
      document.selectedMenu.style.visibility = 'hidden';

   document.selectedMenu = null;
}

function setLocation(page, target)
{
   if (target)
      window.parent[target].document.location.href = page;
   else
      document.location.href = page;
}


function closePopups()
{
   if (document.popups)
   {
      for (popup in document.popups)
         document.popups[popup].close();
   }

   hideMenu();
}
//if(document.body)
//    document.body.onclick = new Function("event", "closePopups()");

function registerPopup(popup)
{
   closePopups();

   if (!isset(document.popups))
      document.popups = new Object();

   document.popups[popup.getName()] = popup;
}

function deregisterPopup(popup)
{
   if (isset(document.popups) && isset(document.popups[popup.getName()]))
      delete(document.popups[popup.getName()]);
}

//Returns the source element for the event. This is needed because
//srcElement is used in IE5 but currentTarget in Mozilla

function getSource(event)
{
   if (event.currentTarget)
      return event.currentTarget;
   else
      return event.srcElement;
}

function hoverButton(event)
{
   getSource(event).className = 'button-hover';
}

function normalButton(event)
{
   getSource(event).className = 'button-normal';
}

function pressButton(event)
{
   getSource(event).className = 'button-pressed';
}

function releaseButton(event)
{
   button = getSource(event);

   if (event.offsetX < button.width && event.offsetX >= 0 &&
         event.offsetY < button.height && event.offsetY >= 0)
      button.className = 'button-hover';
}

function toggleSideMenu()
{
   if (parent.document.sideMenuHidden)
   {
      document.getElementById("ToggleSideMenu").innerHTML = "Hide&nbsp;menu";
      parent.document.body.cols = "130, *";
   }
   else
   {
      document.getElementById("ToggleSideMenu").innerHTML = "Show&nbsp;menu";
      parent.document.body.cols = "0, *";
   }

   parent.document.sideMenuHidden = !parent.document.sideMenuHidden;
}

function hideSideMenu()
{
   if (!parent.document.sideMenuHidden)
   {
      document.getElementById("ToggleSideMenu").innerHTML = "Show&nbsp;menu";
      parent.document.body.cols = "0, *";
      parent.document.sideMenuHidden = !parent.document.sideMenuHidden;
   }
}

function loadPageInMainFrame(href)
{
   var count = 0;
   var topParent = parent;

   while (!(count > 10 || topParent.document.getElementById("MAIN")))
   {
      topParent = topParent.parent;
      count++;
   }

   var mainFrame = topParent.document.getElementById("MAIN");

   if (mainFrame)
      mainFrame.src = href;
   else
      alert("Error: Unable to find main frame");
}

function toggleCommsWindow()
{
   var commsFrameset = parent.document.getElementById("commsFrameset");

   if (parent.document.commsWindowShown == true)
      commsFrameset.rows = "0, *";
   else
      commsFrameset.rows = "20%, *";

   parent.document.commsWindowShown = !parent.document.commsWindowShown;
}

function fsub() {
	document.MForm.submit();

}


// From www.quirksmode.org/dom/getstyles.html
// Returns the current style property for that element
// Modified so it can be given direct HTML elements

function getStyle (id, property)
{
   if (typeof(id) == 'string')
      var element = document.getElementById(id);
   else
      var element = id;

   if (window.getComputedStyle)
      return window.getComputedStyle(element, null).getPropertyValue(property);
   else if (element.currentStyle)
      return eval('element.currentStyle.' + property);
}

function getPosition(id)
{
   if (typeof(id) == 'string')
      var element = document.getElementById(id);
   else
      var element = id;

   var elementPosY = 0;
   var elementPosX = 0;

   while (element)
   {
      elementPosX += parseInt(element.offsetLeft);
      elementPosY += parseInt(element.offsetTop);

      if (navigator.appVersion.indexOf("MSIE") != -1)
      {
         var borderStyle = getStyle(element, 'borderWidth');
         var borderLeft = /^[^ ]*/.exec(borderStyle);


         var intBorderLeft = parseInt(borderLeft);
         if (!isNaN(intBorderLeft))
            elementPosX += intBorderLeft;

         var borderTop = /^[^ ]* ([^ ]*)/.exec(borderStyle);

         if (isset(borderTop))
            var intBorderTop = parseInt(borderTop[0]);

       /*  if (!isNaN(intBorderTop))
            elementPosY += intBorderTop;
         else if (!isNaN(intBorderLeft))
            elementPosY += intBorderLeft;*/
      }

      element = element.offsetParent;
   }

   var result = {x: elementPosX, y: elementPosY};

   return result;
}

function setScrollPos(id, scrollPos)
{
   element = document.getElementById(id);
   element.scrollTop = scrollPos;
}

function printPage()
{
	document.forms["dateForm"].printPage.value = "Yes";
	document.forms["dateForm"].target = "_blank";
	document.forms["dateForm"].submit();
	document.forms["dateForm"].printPage.value = "No";
	document.forms["dateForm"].target = "";

}

function dumpPage()
{
	document.forms["dateForm"].dumpPage.value = "Yes";
	document.forms["dateForm"].target = "_blank";
	document.forms["dateForm"].submit();
	document.forms["dateForm"].dumpPage.value = "No";
	document.forms["dateForm"].target = "";

}

function Today() {
	var dd = new Date();
	return((dd.getMonth()+1) + "/" + dd.getDate() + "/" + dd.getFullYear());
}


function mouseMoved(event)
{
   if (!window.draggedPopup)
      return;

   if (!isset(event))
   {
      if (window.event)
         event = window.event;
      else
         return;
   }

   newX = window.draggedPopup.origPos.x + event.screenX - window.draggedPopup.mouseStart.x;
   newY = window.draggedPopup.origPos.y + event.screenY - window.draggedPopup.mouseStart.y;

   if (navigator.product == 'Gecko')
      window.setTimeout('window.draggedPopup.popup.move(' + newX + ', ' + newY + ');', 1);
   else
      window.draggedPopup.popup.move(newX, newY);
}

if(document.body)
   document.body.onmousemove = new Function("event", "mouseMoved(event)");


function startDrag(event, popup)
{
   if (!isset(event))
   {
      if (window.event)
         event = window.event;
      else
         return;
   }

   window.draggedPopup = {popup: popup,
                          mouseStart: {x: event.screenX, y: event.screenY},
                          origPos: popup.getCurrentPosition()};
}

function stopDrag()
{
   window.draggedPopup = null;
}

if(document.body)
   document.body.onmouseup = new Function("event", "stopDrag()");


////// USERINPUTEXCEPTION //////

function UserInputException(message)
{
   this.message = message;
}

function UserInputException_getMessage()
{
   return this.message;
}

UserInputException.prototype.getMessage = UserInputException_getMessage;

function implode(glue, array)
{
   var result = '';
   var first = true;

   for (var i = 0; i < array.length; i++)
   {
      if (!first)
         result += glue;

      result += array[i];
      first = false;
   }

   return result;
}

function isset(object)
{
   return (typeof(object) != 'undefined' && object != null);
}

function padNumber(number, digits)
{
   count = digits - 1;
   tempNumber = number;
   string = number;

   while (tempNumber >= 10 && count > 0)
   {
      tempNumber /= 10;
      count--;
   }

   for ( ; count > 0 ; count--)
      string = "0" + string;

   return string;
}

function round (number, decimalPlaces)
{
   return Math.round(Math.pow(10, decimalPlaces) * number)
         / Math.pow(10, decimalPlaces);
}

function Date_format(format)
{
   var string = "";
   var lastCharWasSlash = false;
   var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday",
         "Thursday", "Friday", "Saturday"];
   var monthNames = ["January", "February", "March", "April", "May", "June",
         "July", "August", "September", "October", "November", "December"];

   for (var i = 0; i < format.length; i++)
   {
      var character = format.charAt(i);

      if (lastCharWasSlash)
      {
         string = string + character;
         lastCharWasSlash = false;
      }
      else if (character == '\\') //'
         lastCharWasSlash = true;
      else if (character == "a" && this.getHours() <= 11)
         string = string + "am";
      else if (character == "a" && this.getHours() > 11)
         string = string + "pm";
      else if (character == "A" && this.getHours() <= 11)
         string = string + "AM";
      else if (character == "A" && this.getHours() > 11)
         string = string + "PM";
      else if (character == "d")
         string = string + padNumber(this.getDate(), 2);
      else if (character == "D")
         string = string + dayNames[this.getDay()].substr(0, 3);
      else if (character == "F")
         string = string + monthNames[this.getMonth()];
      else if (character == "g")
      {
         hours = this.getHours() % 12;

         if (hours == 0)
            string = string + "12";
         else
            string = string + hours;
      }
      else if (character == "G")
         string = string + this.getHours();
      else if (character == "h")
      {
         hours = this.getHours() % 12;

         if (hours == 0)
            string = string + "12";
         else
            string = string + padNumber(hours, 2);
      }
      else if (character == "H")
         string = string + padNumber(this.getHours(), 2);
      else if (character == "i")
         string = string + padNumber(this.getMinutes(), 2);
      else if (character == "j")
         string = string + this.getDate();
      else if (character == "l")
         string = string + dayNames[this.getDay()];
      else if (character == "m")
         string = string + padNumber(this.getMonth() + 1, 2);
      else if (character == "M")
         string = string + monthNames[this.getMonth()].substr(0, 3);
      else if (character == "n")
         string = string + (this.getMonth() + 1);
      else if (character == "O" || character == "T")
      {
         offset = Math.abs(this.getTimezoneOffset());
         hours = Math.floor(offset / 60);
         mins = offset - hours * 60;

         if (this.getTimezoneOffset() >= 0)
            string = string + "-";
         else
            string = string + "+";

         string = string + padNumber(hours, 2) + padNumber(mins, 2);
      }
      else if (character == "r")
         string = string + this.toLocaleString();
      else if (character == "s")
         string = string + padNumber(this.getSeconds(), 2);
      else if (character == "S")
      {
         dayNum = this.getDate();

         if (dayNum == 1 || dayNum == 21 || dayNum == 31)
            string = string + "st";
         else if (dayNum == 2 || dayNum == 22)
            string = string + "nd";
         else if (dayNum == 3 || dayNum == 23)
            string = string + "rd";
         else
            string = string + "th";
      }
      else if (character == "T")
         ; // This info not available from browser, so act as if 'O' was used instead.
      else if (character == "U")
         string = string + this.valueOf();
      else if (character == "w")
         string = string + this.getDay();
//      else if (character == "W")  -- Not currently supported
      else if (character == "Y")
         string = string + this.getFullYear();
      else if (character == "y")
         string = string + padNumber(this.getFullYear() % 100, 2);
//      else if (character == "z")   -- Not currently supported
      else if (character == "Z")
         string = string + (this.getTimezoneOffset() * -60);
      else
         string = string + character;
   }

   return string;
}



function Date_getDaysInMonth()
{
   // Number of days in each month
   monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

   // Check if it's a leap year
   var year = this.getFullYear();
   if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
      monthDays[1]++;

   return monthDays[this.getMonth()];
}

Date.prototype.getDaysInMonth = Date_getDaysInMonth;
Date.prototype.format = Date_format;



////// HTMLCALENDAR //////

function createCalendar(textfieldID, startDate, endDate, xPos, yPos, dateFormat, onchange, onclose)
{
   if (!isset(window.calendars))
      window.calendars = new Object();

   window.calendars[textfieldID] = new HTMLCalendar(textfieldID, startDate, endDate, xPos, yPos, dateFormat, onchange, onclose);
}

function HTMLCalendar(textfieldID, startDate, endDate, initialX, initialY, dateFormat, onchange, onclose)
{
   this.name = textfieldID;
   this.textfieldID = textfieldID;
   this.initialX = initialX;
   this.initialY = initialY;
   this.onchange = onchange;
   this.onclose = onclose;

   if (startDate)
   {
      try
      {
         this.startDate = convertToDate(startDate);
         this.startDate.setHours(0);
         this.startDate.setMinutes(0);
         this.startDate.setSeconds(0);
         this.startDate.setMilliseconds(0);
      }
      catch (e)
      {
         alert('Start date for calendar "' + this.name + '" is invalid');
      }
   }

   if (endDate)
   {
      try
      {
         this.endDate = convertToDate(endDate);
         this.endDate.setHours(0);
         this.endDate.setMinutes(0);
         this.endDate.setSeconds(0);
         this.endDate.setMilliseconds(0);
      }
      catch (e)
      {
         alert('End date for calendar "' + this.name + '" is invalid');
      }
   }

   if (dateFormat)
      this.dateFormat = dateFormat;
   else
      this.dateFormat = 'd M Y';

   this.visible = false;
}

function HTMLCalendar_open()
{
   if (this.visible)
      return;

   registerPopup(this);


   this.visible = true;

   var textfield = document.getElementById(this.textfieldID);

   if (!textfield)
      return;

   // Find where the textfield is
   var element = textfield;
   var textfieldPosX = 0;
   var textfieldPosY = 0;
   var initialX = this.initialX;
   var initialY = this.initialY;
   var startDate = this.startDate;
   var endDate = this.endDate;

   this.lastValidDateString = textfield.value;

   while (element)
   {
      textfieldPosX += element.offsetLeft;
      textfieldPosY += element.offsetTop;

      element = element.offsetParent;
   }

   if (textfield && initialX == null)
      initialX = textfieldPosX;
   if (textfield && initialY == null)
      initialY = textfieldPosY + textfield.offsetHeight + 10;

   var divTag = document.createElement('DIV');
   divTag.id = "HTMLCalendar_" + this.name + "_html";
   divTag.style.position = 'absolute';
   divTag.style.top = initialY;
   divTag.style.left = initialX;
   document.body.appendChild(divTag);
   document.selectedMenu = divTag;


   this.updateUI(true);
}

function HTMLCalendar_getName()
{
   return this.name;
}

function HTMLCalendar_getCurrentPosition()
{
   var divTag = document.getElementById('HTMLCalendar_' + this.name + '_html');

   return {x: parseInt(divTag.style.left), y: parseInt(divTag.style.top)};
}


function HTMLCalendar_move(x, y)
{
   if (arguments.length == 1)
   {
      y = x.y;
      x = x.x;
   }

   var divTag = document.getElementById('HTMLCalendar_' + this.name + '_html');

   divTag.style.top = y;
   divTag.style.left = x;
}

function HTMLCalendar_updateUI(showSelectedMonth)
{
   if (showSelectedMonth)
      this.displayedMonth = this.readDate();

   if (!isset(this.displayedMonth))
      this.displayedMonth = new Date();

   var html = "<table class='calendar' cellpadding='0' cellspacing='0' onmousedown='window.ignoreBlur = true;' onclick='event.cancelBubble=true'>";
   html += "<tr><td colspan='7'><table cellspacing='0' ><tr class='calendarButtons'>";

   // We don't have to worry about the actual day for this bit because if they're in the same month the displayedMonth
   // will just be reasserted
   if (this.startDate)
   {
      if (this.displayedMonth.valueOf() < this.startDate.valueOf())
         this.displayedMonth = new Date(this.startDate.valueOf());
   }

   if (this.endDate)
   {
      if (this.displayedMonth.valueOf() > this.endDate.valueOf())
         this.displayedMonth = new Date(this.endDate.valueOf());
   }

   this.displayedMonth.setDate(1);
   // Work out whether the next/previous month/year buttons should be enabled

   if (this.displayedMonth.getMonth() == 0)
      var previousMonthDate = new Date(this.displayedMonth.getFullYear() - 1, 11, 1);
   else
      var previousMonthDate = new Date(this.displayedMonth.getFullYear(), this.displayedMonth.getMonth() - 1, 1);

   previousMonthDate.setDate(previousMonthDate.getDaysInMonth());

   if (this.displayedMonth.getMonth() == 11)
      var nextMonthDate = new Date(this.displayedMonth.getFullYear() + 1, 0, 1);
   else
      var nextMonthDate = new Date(this.displayedMonth.getFullYear(), this.displayedMonth.getMonth() + 1, 1);

   var previousYearDate = new Date(this.displayedMonth.getFullYear() - 1, this.displayedMonth.getMonth(), 1);
   previousYearDate.setDate(previousYearDate.getDaysInMonth());

   var nextYearDate = new Date(this.displayedMonth.getFullYear() + 1, this.displayedMonth.getMonth(), 1);

   if (this.canShowMonth(previousYearDate))
      html += '<td class="calendarArrow"><a href="#" onclick="window.calendars[&quot;' + this.name + '&quot;].showDate(' + previousYearDate.valueOf() + '); return false">&lt;&lt;</a></td>';
   else
      html += '<td class="calendarArrow">&lt;&lt;</td>';

   if (this.canShowMonth(previousMonthDate))
      html += '<td class="calendarArrow"><a href="#" onclick="window.calendars[&quot;' + this.name + '&quot;].showDate(' + previousMonthDate.valueOf() + '); return false">&lt;</a></td>';
   else
      html += '<td class="calendarArrow">&lt;</td>';

   html += '<td class="calendarTitle" onmousedown="startDrag(event, window.calendars[&quot;' + this.name + '&quot;])">';

   html += this.getMonthName(this.displayedMonth.getMonth()) + "&nbsp;" + (this.displayedMonth.getFullYear()) + '</td>';

   if (this.canShowMonth(nextMonthDate))
      html += '<td class="calendarArrow"><a href="#" onclick="window.calendars[&quot;' + this.name + '&quot;].showDate(' + nextMonthDate.valueOf() + '); return false">&gt;</a></td>';
   else
      html += '<td class="calendarArrow">&gt;</td>';

   if (this.canShowMonth(nextYearDate))
      html += '<td class="calendarArrow"><a href="#" onclick="window.calendars[&quot;' + this.name + '&quot;].showDate(' + nextYearDate.valueOf() + '); return false">&gt;&gt;</a></td>';
   else
      html += '<td class="calendarArrow">&gt;&gt;</td>';

   html += '</tr></table>';

   var dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

   html += '<tr class="dayNames">';

   currDay = window.START_OF_WEEK;
   for (var count = 0; count < dayNames.length; count++)
   {
      if (isWeekend(currDay))
         html += '<td class="shaded">';
      else
         html += '<td>';

      html += dayNames[currDay] + '</td>';

      currDay++;
      if (currDay == 7)
         currDay = 0;
   }

   html += '</tr>';

   var lastDayOfMonth = this.displayedMonth.getDaysInMonth();
   var currDay = 0;
   var tempDate = new Date(this.displayedMonth.getFullYear(), this.displayedMonth.getMonth(), 1);


   var currDate = 1 - (tempDate.getDay() - window.START_OF_WEEK);
   if (currDate > 1)
      currDate -= 7;

   var timestamp = tempDate.valueOf();
   var selectedDate = this.readDate();

   var today = new Date();

   if (isset(selectedDate))
      var showingSelectedMonth = selectedDate.getMonth() == this.displayedMonth.getMonth() && selectedDate.getFullYear() == this.displayedMonth.getFullYear();
   else
      var showingSelectedMonth = false;

   var showingThisMonth = today.getMonth() == this.displayedMonth.getMonth() && today.getFullYear() == this.displayedMonth.getFullYear();

   html += '<tr class="days">';

   while (currDate <= lastDayOfMonth)
   {
      var cellClass;

      if (isWeekend((currDay + window.START_OF_WEEK) % 7))
         html += '<td class="shaded"';
      else
         html += '<td';

      var id = '';

      if (showingSelectedMonth && selectedDate.getDate() == currDate)
         id += 'selected';

      if (showingThisMonth && today.getDate() == currDate)
         id += 'today';

      if (id.length > 0)
         html += ' id="' + id + '"';

      html += '>';

      if (currDate < 1)
         html += '&nbsp;';
      else
      {
         dayString = currDate;

         html += '<div';

			var tempDate = new Date(timestamp);
			tempDate.setHours(0);

         if (this.isInRange(tempDate))
				html += '><a href="#" onclick="window.calendars[&quot;' + this.getName() + '&quot;].selectDate(' + timestamp + '); return false">' + dayString + "</a></div>";
			else
            html += ' class="unavailable">' + dayString + '</div>';



         timestamp += 24 * 60 * 60 * 1000;
      }

      html += '</td>';

      currDay++;
      currDate++;

      if (currDay == 7 && currDate <= lastDayOfMonth)
      {
         currDay = 0;
         html += '</tr><tr class="days">';
      }

   }

   while (currDay < 7)
   {
      if (isWeekend((currDay + window.START_OF_WEEK) % 7))
         html += '<td class="shaded">&nbsp;</td>';
      else
         html += '<td>&nbsp;</td>';

      currDay++;
   }

   html += '</tr>';
   html += '<tr><td colspan="7" height="2px"></td></tr>'
   html += '<tr class="calendarButtons">';
   html += '<td colspan="2">';

   if (this.isInRange(new Date()))
   {
      todaysDate = new Date();
      todaysDate.setHours(0);
      todaysDate.setMinutes(0);
      todaysDate.setSeconds(0);
      todaysDate.setMilliseconds(0);
      html += '<a style="text-decoration: none" href="#" onclick="window.calendars[&quot;' + this.name + '&quot;].selectDate(' + todaysDate.valueOf() + '); return false">';
      html += 'Today</a>';
   }
   else
      html += 'Today';

   html +  '</td>';
   html += '<td colspan="5">';
   html += '<a style="text-decoration: none" href="#" onclick="window.calendars[&quot;' + this.name + '&quot;].toggleMonthList(); return false">Select Month...</a></td>';
   html += '</tr>';
   if (this.showMonthList)
      html += '<tr id="' + this.name + '_monthList">';
   else
      html += '<tr id="' + this.name + '_monthList" style="display: none">';

   html += '<td colspan="7">';

   var tempDate = new Date(this.displayedMonth.valueOf());

   html += '<table class="monthList">';
   for (var row = 0; row < 4; row++)
   {
      html += '<tr>';

      for (var column = 0; column < 3; column++)
      {
         html += '<td>';
         var monthNum = row * 3 + column;
         var monthName = this.getMonthName(monthNum);

         tempDate.setMonth(monthNum);
         if (this.canShowMonth(tempDate))
         {
            html += '<a href="#" onclick="calendars[&quot;' + this.name + '&quot;].showDate(' + tempDate.valueOf() + '); return false">';
            html += monthName;
            html += '</a>';
         }
         else
            html += monthName;

         html += '</td>';
      }

      html += '</tr>';
   }
   html += '</table>';
   html += '</td>';
   html += '</tr>';
   html += '</table>';

   var outerDiv = document.getElementById('HTMLCalendar_' + this.name + "_html");
   outerDiv.innerHTML = html;
}

function HTMLCalendar_toggleMonthList()
{
   this.showMonthList = !this.showMonthList;

   if (this.showMonthList)
      document.getElementById(this.name + "_monthList").style.display = "";
   else
      document.getElementById(this.name + "_monthList").style.display = "none";
}


function HTMLCalendar_getMonthName(month)
{
   monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

   return monthNames[month];
}

function HTMLCalendar_isInRange(date)
{
   var tempDate = new Date(date.valueOf());

   tempDate.setHours(0);
   tempDate.setMinutes(0);
   tempDate.setSeconds(0);
   tempDate.setMilliseconds(0);

   if (isset(this.startDate) && this.startDate.valueOf() > tempDate.valueOf())
      return false;
   else if (isset(this.endDate) && this.endDate.valueOf() < tempDate.valueOf())
      return false;
   else
      return true;
}

function HTMLCalendar_canShowMonth(date)
{
   var tempDate = new Date(date.valueOf());

   tempDate.setDate(1);
   if (isset(this.endDate) && this.endDate.valueOf() < tempDate.valueOf())
      return false;

   tempDate.setDate(tempDate.getDaysInMonth())
   if (isset(this.startDate) && this.startDate.valueOf() > tempDate.valueOf())
      return false;

   return true;
}

function HTMLCalendar_showDate(timestamp)
{
   displayDate = new Date(timestamp);

   this.displayedMonth = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1);

   this.updateUI();
}

function HTMLCalendar_selectEnteredDate()
{
   var textfield = document.getElementById(this.textfieldID);

   return this.selectDate(textfield.value);
}


function HTMLCalendar_selectDate(dateString)
{
   textfieldID = this.textfieldID;

   try
   {
      var textfield = document.getElementById(textfieldID);

      date = convertToDate(dateString, true);
		if (date.getHours() == 23)
			date = new Date(date.valueOf() + 1000 * 3600);

      if (!this.isInRange(date))
      {
         if (isset(startDate))
            var startDateString = startDate.format(this.dateFormat);
         if (isset(endDate))
            var endDateString = endDate.format(this.dateFormat);

         if (isset(startDate) && isset(endDate))
            throw new UserInputException('Date must be between ' + startDateString + ' and ' + endDateString);
         else if (isset(startDate))
            throw new UserInputException('Date cannot be before ' + startDateString);
         else if (isset(endDate))
            throw new UserInputException('Date cannot be after ' + endDateString);
      }

      var stringDate = date.format(this.dateFormat);
      textfield.value = stringDate;
      this.close();

      if (this.onchange && this.lastValidDateString != stringDate)
         eval(this.onchange);

      textfield.lastValidDateString = stringDate;
      return true;
   }
   catch (e)
   {
      if (e.getMessage)
      {
         alert(e.getMessage());
         textfield.value = this.lastValidDateString;
         return false;
      }
      else
         throw e;
   }
}



function HTMLCalendar_close()
{
   if (!this.visible)
      return;

   if (this.onclose)
      eval(this.onclose);

   this.visible = false;
   var outerElement = document.getElementById('HTMLCalendar_' + this.name + '_html');

   outerElement.parentNode.removeChild(outerElement);
   deregisterPopup(this);
   document.getElementById(this.textfieldID).calendar = null;
}


function HTMLCalendar_readDate(textfieldID)
{
   textfield = document.getElementById(this.textfieldID);

   try
   {
      return convertToDate(textfield.value);
   }
   catch (e)
   {
      return null;
   }
}

HTMLCalendar.prototype.getName = HTMLCalendar_getName;
HTMLCalendar.prototype.open = HTMLCalendar_open;
HTMLCalendar.prototype.updateUI = HTMLCalendar_updateUI;
HTMLCalendar.prototype.getMonthName = HTMLCalendar_getMonthName;
HTMLCalendar.prototype.showDate = HTMLCalendar_showDate;
HTMLCalendar.prototype.close = HTMLCalendar_close;
HTMLCalendar.prototype.selectDate = HTMLCalendar_selectDate;
HTMLCalendar.prototype.selectEnteredDate = HTMLCalendar_selectEnteredDate;
HTMLCalendar.prototype.getCurrentPosition = HTMLCalendar_getCurrentPosition;
HTMLCalendar.prototype.move = HTMLCalendar_move;
HTMLCalendar.prototype.readDate = HTMLCalendar_readDate;
HTMLCalendar.prototype.canShowMonth = HTMLCalendar_canShowMonth;
HTMLCalendar.prototype.isInRange = HTMLCalendar_isInRange;
HTMLCalendar.prototype.toggleMonthList = HTMLCalendar_toggleMonthList;

function isWeekend(dayNum)
{
   for (var i = 0; i < window.WEEKEND_DAYS.length; i++)
   {
      if (window.WEEKEND_DAYS[i] == dayNum)
         return true;
   }

   return false;
}

function convertToDate(dateString, preserveTime)
{
   //See if it's in Today+900 format...

   var relativeDateArray = /^\s*Today([+-])(\d*)\s*$/i.exec(dateString);

   if (isset(relativeDateArray))
   {
      date = new Date();
      date.setHours(0);
      date.setMinutes(0);
      date.setSeconds(0);
      date.setMilliseconds(0);

      var timestamp = date.valueOf();

      if (relativeDateArray[1] == '+')
         timestamp += parseInt(relativeDateArray[2]) * 1000 * 60 * 60 * 24;
      else
         timestamp -= parseInt(relativeDateArray[2]) * 1000 * 60 * 60 * 24;

      return new Date(timestamp);
   }


   if (typeof(dateString) == 'string')
   {
      // Remove the 'rd' from 3rd etc because Date.parse() doesn't like those
      dateString = dateString.replace(/(\d| )(st|nd|rd|th)/i, "$1");

      //Convert the date into US format for the browser's locale-dead parser
      dateString = dateString.replace(/(\d*)\/(\d*)/, "$2/$1");
   }

   date = new Date(dateString);

   // If it didn't work, try adding the year to the date
   if (isNaN(date))
      date = new Date(dateString + " " + new Date().getFullYear());

   // Adding the year didn't help
   if (isNaN(date))
      throw new UserInputException("Please enter a valid date");

   if (date.getFullYear() < 1930 && typeof(dateString) == 'string' && dateString.search(date.getFullYear()) == -1)
      date.setFullYear(date.getFullYear() + 100);

   if (preserveTime)
      ;
   else
   {
      date.setHours(0);
      date.setMinutes(0);
      date.setSeconds(0);
      date.setMilliseconds(0);
   }

   return date;
}

function serialiseObject(object)
{
   var output = '~{';
   var first = true;

   var keyList = new Object();

   if (typeof(object) == 'Array')
   {
      for (var i = 0; i < object.length; i++)
         keyList[i] = i;
   }
   else
      keyList = object;


   for (var key in keyList)
   {
      // If this is not the first key, put a marker after the last value
      if (first)
         first = false;
      else
         output += "~|";

      output += key.replace(/~/g, "~~");

      // If the value is an object itself, recurse to serialise it
      if (typeof(object[key]) == 'object')
         output += serialiseObject(object[key]);
      else
      {
         output += "~=";

         if (typeof(object[key]) == 'string')
            output += object[key].replace(/~/g, "~~");
         else
            output += object[key];
      }
   }

   output += "~}";

   return output;
}

////// HTMLCOMBOBOX //////

function createComboBox(ID, initialValue, itemList, eventListeners, style, dontAddToDocument)
{
   if (!isset(itemList[initialValue]))
   {
      // Just get the first element
      for (firstValue in itemList)
      {
         initialValue = firstValue;
         break;
      }

      // If it's STILL not set (ie the list is empty)
      if (!isset(itemList[initialValue]))
         initialValue = '&nbsp;';
   }


   var html = "<table class='HTMLComboBox' id='HTMLComboBox_" + ID + "_outer' border='0' cellspacing='0' onclick='event.cancelBubble=true'";
   if (style)
   {
      html += " style='";

      if (style.noborder)
         html += "border: none; ";
      if (style.fullwidth)
         html += "width: 100%; ";
      if (style.fullheight)
         html += "height: 100%; ";

      html += "'";
   }

   html += ">";
   html += "<tr><td ";
   if (style && style.disabled)
      html += "class='value_disabled'";
   else
      html += "class='value'";

   html += "' id='HTMLComboBox_" + ID + "_value'  onclick='window.comboBoxes[&quot;" + ID + "&quot;].clicked(event)'>";
   html += itemList[initialValue];
   html += "</td>";
   html += "<td class='arrow' onclick='window.comboBoxes[&quot;" + ID + "&quot;].clicked(event)'>";
   html += "<img src='images/dropdown-arrow.gif' width='9' height='6' />";
   html += "</td>";
   html += "</tr></table>";

   // Check to see if this element exists somewhere else in the document, if it doesn't create it
   // This check is for the HTMLifier table builder where the hidden field may have been inserted elsewhere
   if (!isset(document.getElementById(ID)))
      html += "<input type='hidden' id='" + ID + "' name='" + ID + "' value='" + initialValue + "'>";
   else
      document.getElementById(ID).value = initialValue;

   var outerDiv = document.createElement('DIV');
   outerDiv.style.width = '100%';
   outerDiv.innerHTML = html;

   if (!isset(dontAddToDocument))
      document.write(html);

   if (!isset(window.comboBoxes))
      window.comboBoxes = new Object();

   window.comboBoxes[ID] = new HTMLComboBox(ID, initialValue, itemList, eventListeners, style);

   return outerDiv;
}


function HTMLComboBox(ID, initialValue, itemList, eventListeners, style)
{
   this.name = ID;
   this.value = initialValue;
   this.style = style;
   if (style && style.disabled)
      this.enabled = false;
   else
      this.enabled = true;
   this.currentSelection = initialValue;
   this.setItemList(itemList);
   this.eventListeners = eventListeners;
}

function HTMLComboBox_getName()
{
   return this.name;
}

function HTMLComboBox_clicked(event)
{
   if (this.eventListeners && this.eventListeners.onclick)
      eval(this.eventListeners.onclick);

   if (this.isOpen)
      this.close();
   else
      this.open();
}

function HTMLComboBox_isEnabled()
{
   return this.enabled;
}

function HTMLComboBox_setEnabled(enabled)
{
   this.enabled = enabled;

   var HTMLvalue = document.getElementById("HTMLComboBox_" + this.name + "_value");

   if (HTMLvalue)
   {
      if (enabled)
         HTMLvalue.className = 'value';
      else
         HTMLvalue.className = 'value_disabled';
   }
}

function HTMLComboBox_open()
{
   if (!this.isEnabled() || this.isOpen)
      return;
   else
      this.isOpen = true;

   var outer = document.getElementById("HTMLComboBox_" + this.name + "_outer");
   var outerPosition = getPosition(outer);

   //var formElement = document.getElementById(this.name);
   this.mouseOverItem(this.value);

   var dropDown = this.createDropDown();


   if (navigator.appVersion.indexOf("MSIE") != -1)
   {
      dropDown.style.top = outerPosition.y + outer.offsetHeight + 2;
      dropDown.style.left = outerPosition.x - 2;
      dropDown.style.width = outer.offsetWidth;
   }
   else
   {
      dropDown.style.top = outerPosition.y + outer.offsetHeight;
      dropDown.style.left = outerPosition.x;
      dropDown.style.width = outer.offsetWidth - 4; // 4 adjusts for the 2px borders on each side
   }

   dropDown.style.zIndex = 100;

   document.body.appendChild(dropDown);

   // IE 5.0 doesn't set scroll properly if scrollTop is set immediately
   window.setTimeout('setScrollPos("HTMLComboBox_' + this.name + '_dropDown", ' + dropDown.scrollPos + ')', 1);

   registerPopup(this);

   if (isset(this.eventListeners.onopen))
   	eval(this.eventListeners.onopen);
}

function HTMLComboBox_getValue()
{
   return this.value;
    /*var formElement = document.getElementById(this.name);
    return formElement.value;*/
}


function HTMLComboBox_setValue(value)
{
   //var HTMLvalue = document.getElementById("HTMLComboBox_" + this.name + "_value");

   if (!isset(this.itemList))
      html = '&nbsp;';
   else if (!isset(this.itemList[value]))
   {
      // Just get the first element
      for (firstValue in this.itemList)
      {
         value = firstValue;
         break;
      }

      // If it's STILL not set (ie the list is empty)
      if (!isset(this.itemList[value]))
         html = '&nbsp;';
      else
         html = this.itemList[value];
   }
   else
      html = this.itemList[value];

   this.value = value;

   var formElement = document.getElementById(this.name);
   if (formElement)
      formElement.value = value;

   var HTMLvalue = document.getElementById("HTMLComboBox_" + this.name + "_value");
   if (HTMLvalue)
   {
      while (HTMLvalue.firstChild)
         HTMLvalue.removeChild(HTMLvalue.firstChild);

     newText = document.createTextNode(html);
     HTMLvalue.appendChild(newText);
   }

   this.mouseOverItem(this.value);
}


function HTMLComboBox_setItemList(itemList)
{
   this.itemList = itemList;

   this.createDropDown();

   // Update the list in case the current selected item is no longer in the list
   this.setValue(this.getValue());
}

function HTMLComboBox_createDropDown()
{
   var outer = document.getElementById("HTMLComboBox_" + this.name + "_outer");

   if (!isset(outer))
      return;

   var dropDown = document.createElement('DIV');
   dropDown.className = 'HTMLComboBoxDropDown';
   dropDown.id = "HTMLComboBox_" + this.name + "_dropDown";


   var itemCount = 0;
   var selectedPosition = 0;

   for (currItem in this.itemList)
   {
      var div = document.createElement('DIV');
      div.id = 'HTMLComboBox_' + this.name + "_item_" + currItem;
      div.style.width = '100%';
      if (currItem == this.currentSelection)
      {
         selectedPosition = itemCount;
         div.className = 'selected';
      }

      div.onmouseover = new Function("event", 'window.comboBoxes["' + this.name + '"].mouseOverItem("' + currItem + '")');
      div.onclick = new Function("event", 'window.comboBoxes["' + this.name + '"].selectItem("' + currItem + '")');

      div.innerHTML = this.itemList[currItem].replace(/ /g, "&nbsp;");

      dropDown.appendChild(div);
      itemCount++;
   }

   //ieHack is needed so IE calculates the width of the dropdown correctly.

   var ieHack = document.createElement('DIV');
   ieHack.style.width = 1;
   ieHack.appendChild(dropDown);
   document.body.appendChild(ieHack);

   if (!isset(this.style) || !isset(this.style.fullwidth))
      outer.style.width = dropDown.offsetWidth + 30;

   if (itemCount > window.DEFAULT_DROPDOWN_SIZE)
   {
       var itemHeight = parseInt(dropDown.offsetHeight) / itemCount;
       dropDown.style.height = itemHeight * window.DEFAULT_DROPDOWN_SIZE;
       dropDown.style.overflow = 'auto';

       // Stored in scrollPos because scrollTop gets overwritten. We copy scrollPos
       // into scrollTop just after we add it to the page in open()
       dropDown.scrollPos = itemHeight * selectedPosition;
   }
   else
      dropDown.scrollPos = 0;

   ieHack.removeChild(dropDown);
   document.body.removeChild(ieHack);

   return dropDown;
}

function HTMLComboBox_mouseOverItem(itemNum)
{
   var selectedItem = document.getElementById("HTMLComboBox_" + this.name + "_item_" + itemNum);
   if (selectedItem)
      selectedItem.className = 'selected';

   if (isset(this.currentSelection) && this.currentSelection != itemNum)
   {
      var lastSelectedItem = document.getElementById("HTMLComboBox_" + this.name + "_item_" + this.currentSelection);
      if (lastSelectedItem)
         lastSelectedItem.className = '';
   }

   this.currentSelection = itemNum;
}

function HTMLComboBox_selectItem(itemNum)
{
   if (itemNum == this.getValue())
      return;

   this.setValue(itemNum);

   if (this.eventListeners && this.eventListeners.onchange)
      eval(this.eventListeners.onchange);

   this.close();
}

function HTMLComboBox_close()
{
   this.isOpen = false;

   var dropDown = document.getElementById('HTMLComboBox_' + this.name + "_dropDown");

   if (isset(dropDown))
      document.body.removeChild(dropDown);

   deregisterPopup(this);
	if (isset(this.eventListeners.onclose))
   	eval(this.eventListeners.onclose);
}

HTMLComboBox.prototype.getName = HTMLComboBox_getName;
HTMLComboBox.prototype.isEnabled = HTMLComboBox_isEnabled;
HTMLComboBox.prototype.setEnabled = HTMLComboBox_setEnabled;
HTMLComboBox.prototype.clicked = HTMLComboBox_clicked;
HTMLComboBox.prototype.open = HTMLComboBox_open;
HTMLComboBox.prototype.setItemList = HTMLComboBox_setItemList;
HTMLComboBox.prototype.setValue = HTMLComboBox_setValue;
HTMLComboBox.prototype.getValue = HTMLComboBox_getValue;
HTMLComboBox.prototype.createDropDown = HTMLComboBox_createDropDown;
HTMLComboBox.prototype.close = HTMLComboBox_close;
HTMLComboBox.prototype.mouseOverItem = HTMLComboBox_mouseOverItem;
HTMLComboBox.prototype.selectItem = HTMLComboBox_selectItem;


