/* 
 * util.js javascript : general purpose functions
 *
 * when       who             what
 * -----------------------------------------------------------------------------------------------------
 * 15/10/04   Y Paschalidis   Copied from CSOFServe util.js
 */ 

  //Popups being displayed
  var popupDivs = new Array();
  var popupDivShims = new Array();
   
 /*
  * Get an element by its id
  */
  function getElement(elName) 
  {
    var elRef;
    
    if (document.all) 
      elRef = document.all(elName);
    else if (document.getElementById)
      elRef = document.getElementById(elName);
    else if (document.layers)
      elRef = document.layers[elName];
      
    return elRef;
  }

 /*
  * Set the cursor for an element
  */
  function setCursor(elRef, newStyle) 
  {
    // First check the reference for the element (get from event if undefined)
    if (elRef == undefined) 
    {
		if (!window.event) 
			event = arguments.callee.caller.arguments[0];
		
		var el = event.srcElement || event.currentTarget || event.target;
    }
    else 
		var el = elRef;
    
    // Next validate the new cursor sytle
	var cursorStyle = (newStyle == undefined) ? 'auto' : newStyle;
    
    if (newStyle == 'pointer' && document.all) 
		cursorStyle = 'hand';
    
    // Now change the cursor (based on element 'style' support)
	if (el.style) 
		el.style.cursor = cursorStyle;
}
 
 /*
  * Function to calculate position of an element
  */
  function getOffset(el, which) 
  {
    // Default offset to 200px
    var amount = 200;
    
	// window.find introduced in Mozilla 0.9 - 1 "ish". So Netscape 6 doesn't know about it.
    if (document.all || window.find) 
    {
		amount = el["offset"+which]; 
      
		if (which == "Top") 
			amount += el.offsetHeight;
      
		el = el.offsetParent;
      
		while (el != null) 
		{
			amount += el["offset"+which];
			el = el.offsetParent;
		}
    }
    else 
    {
		if (which == "Top") 
			amount = el.offsetTop;
		else if (which == "Left") 
        	amount = el.offsetLeft;
    }
    
	return amount;
}

 /*
  * Write out the contents of the tooltip
  */
  function writeContents(el, tip) 
  {
    if (document.all || document.getElementById) 
    {
      el.innerHTML = tip;
    }
    else 
    {
      // In NS, insert a table to work around
      // stylesheet rendering bug.
      // NS fails to apply style sheets when writing
      // contents into a positioned element.
      el.document.open();
      el.document.write("<TABLE WIDTH=200 STYLE='border: 2pt black solid; '><TR><TD WIDTH=100% BGCOLOR=#ffff99><FONT COLOR=#000000 SIZE=-1>");
      el.document.write(tip);
      el.document.write("</FONT></TD></TR></TABLE>");
      el.document.close();
    }
  }

 /*
  * Set the position of an element
  */
function setPosition(src, el) 
{
	if (document.all || document.getElementById) 
	{
		var top = getOffset(src, "Top");
		var bottomlimit = (document.all) ? document.body.clientHeight - 60 : window.innerHeight - 60;
      
		if (top < bottomlimit) 
			top = top + 15;
		else 
        	top = top - 50;
      
		el.style.top = top + "px";
		var left = getOffset(src, "Left");
		var rightlimit = (document.all) ? document.body.clientWidth - 185 : window.innerWidth - 185;
      
		if (left < rightlimit) 
			left = left + 30;
		else 
			left = left - 150;
      
		el.style.left = left + "px";
    }
    else 
    {
		if (src.y < 500) 
			el.top = src.y + 28;
		else 
		{
			if (src.y == undefined) 
				el.top = 200;
			else 
				el.top = src.y - 50;
		}
      
		if (src.x < 500) 
        	el.left = src.x + 13;
		else 
		{
			if (src.x < 500) 
				el.left = src.x + 13;
        	else 
	        {
				if (src.x == undefined) 
					el.left = 200;
				else 
					el.left = src.x - 137;
	        }
		}
	}
}
  
  
  
  //Gets the div shim for the given div, used by popupDiv for ie5.5+ only
  function getDivShim(div)
  {
     for (i=0 ; i<popupDivs.length ; i++)
     {
         if (popupDivs[i]==div)
         	return popupDivShims[i];        	
     }
     
	 if (div.insertAdjacentHTML)
	 {
	     var id = "divShim"+popupDivs.length;
	    
		 div.insertAdjacentHTML("afterEnd", 
			 "<iframe id=\""+id+"\" src=\"javascript:false;\" scrolling=\"no\" frameborder=\"0\"" +
			 "style=\"position:absolute; top:0px; left:0px; display:none;\"></iframe>"
		 );
		
		 popupDivs[popupDivs.length] = div;
		 popupDivShims[popupDivShims.length] = getElement(id);	
		
		 return popupDivShims[popupDivShims.length-1];
	 }
	
	 return null;
  }
  
  //show or hide a div "popup"
  function popupDiv(div, show)
  {
     if (show)
     {     
		div.style.visibility = "visible";
		div.style.display = "block";
		
		//in ie5.5 and later, we can insert an iframe under the div to get around
		//the problem of select lists ignoring the z-index attribute
	    if (window.createPopup)
	    {
	    	var divShim = getDivShim(div);
	    	
			if (divShim!=null)			
			{
				divShim.style.width = div.offsetWidth;
				divShim.style.height = div.offsetHeight;
				divShim.style.top = div.offsetTop;
				divShim.style.left = div.offsetLeft;
				divShim.style.zIndex = div.style.zIndex - 1;
				divShim.style.display = "block";				
			}			
	    }
	 }
	 else
	 {
		if (window.createPopup)
		{
			var divShim = getDivShim(div);
			
		    if (divShim!=null)
			   divShim.style.display = "none";
		}
		
		div.style.visibility = "hidden";
		div.style.display = "none";		
	 }
  }
  
  function centerDiv(div)
  {
    var left = (window.pageXOffset)?(window.pageXOffset):(document.documentElement)?document.documentElement.scrollLeft:document.body.scrollLeft;
    var top = (window.pageYOffset)?(window.pageYOffset):(document.documentElement)?document.documentElement.scrollTop:document.body.scrollTop;  
    
	//Center the div on the screen
	if (window.innerHeight) 
	{
		// NS/Moz
		div.style.top = top+(window.innerHeight - div.offsetHeight) / 2 + "px";
		div.style.left = left+(window.innerWidth - div.offsetWidth) / 2 + "px";
	}	
	else if (document.body.offsetHeight)
	{
		// IE
		div.style.top = top+(document.body.offsetHeight - div.offsetHeight) / 2 + "px";
		div.style.left = top+(document.body.offsetWidth - div.offsetWidth) / 2 + "px";
	}
  }
 
 /*
  * Display the contents of a tooltip and hide any selectboxes in its way
  */
  function displayTooltip(src, tip)
  {
    var el1 = getElement('tipBox');
	el1.zIndex = 20;
    setPosition(src, el1);
    writeContents(el1, tip);
    
    popupDiv(el1, true);	
  }
  

 /*
  * Hide the contents of a tooltip
  */
  function hideTooltip() 
  {  
    popupDiv(getElement("tipBox"),false);
  }

 /*
  * Open window for reference
  */
  function openwin(url) {
    var win;
    if (document.all) {
      win = window.open(url, 'ReferenceWindow', 'width=670, height=400, left=300, top=200, resizable=yes, scrollbars=yes, toolbar=yes, menubar=yes');
    }
    else {
      win = window.open(url, "ReferenceWindow", "width=670,height=400,resizable=1,scrollbars=1,toolbar=1,menubar=1,alwaysRaised=1,screenx=300,screeny=200");
    }
  }

 /*
  * Do page load routine
  */
  function doLoad() 
  {
    logout = false;
    
    // Set-up Holiday arrays
    satWarning = new Array(false, false);
    sunWarning = new Array(false, false);
    satIdx=0;
    sunIdx=0;
    pubHolWarning = new Array(false, false);
    pholIdx=0;
    
    // Auto scroll to an anchor
    target = getElement("scrollTarget")
    if (target!=null && typeof(target)!="undefined")
    {
      scrollToAnchor(target.value);
    }
  }


  function scrollToAnchor(anchorname) 
  {
    if (anchorname == '')
    {
      return;
    }
    var o = getElement(anchorname);
    var yPosition = getPageOffsetTop(o);
    window.scroll(0,yPosition);
  }

  // Function to get position of an object
  function getPageOffsetTop (el) 
  {
    if (el == undefined)
    {
      return 0;
    }
    var ot=el.offsetTop;
    while((el=el.offsetParent) != null) { ot += el.offsetTop; }
    return ot;
  }

 /*
  * Respond to click on a section
  */
  function doSection(secNum) {
    var secRef = getElement(secNum);
    var imSec = getElement(secNum + "-im");
    if (secRef.style.display == "none" ) {
      secRef.style.display = "";
      imSec.src = "images/arrows/expanded.gif" ;
    }
    else {
      secRef.style.display = "none";
      imSec.src = "images/arrows/collapsed.gif" ;
    }
  }

 /*
  * Load help
  */
  function loadHelp() {
    var pageURL = getElement("helpFile").value;
    var strWrite = "help/Help.htm?#" + pageURL.substring(pageURL.indexOf("help/")+5);
    return openwin(strWrite);
  }


 /*
  * Right align a field
  */
  function rightAlign(field, maxLength) {
    var padding = maxLength - field.value.length;
    for (i = 0; i < padding; i++) {
      field.value = " " + field.value;
    }
    return true;
  }
  
  
  function leftAlign(field, maxLength) {
    var padding = maxLength - field.value.length;
    for (i = 0; i < padding; i++) {
      field.value = field.value + " ";
    }
    return true;
  }

 /*
  * Removes leading and trailing whitespaces from the passed string.
  */
  function trim(str) {
    if (str == "") {
        return str;
    }
    return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
  }

 /*
  * Retrieves a radio button value
  */
function getSelValue(elName) {
	var elResult = '';
	for (var i = 0; i < elName.length; i++) {
		if (elName[i].checked) {
			elResult = elName[i].value; 
			break; 
		}
	}
	return elResult;
}

/** Retrieves the selected option's value from a select box/list */
function getSelectedValue(select)
{
	for (i=0 ; i<select.options.length ; i++)
	{
		if (select.options[i].selected)
			return select.options[i].value;
	}
	
	return "";
}

 /*
  * Disables a button that has been clicked, where you still want the name/value pair sent to the server.
  * (Disabled buttons aren't sent by default)
  */
function disableClickedButton(buttonName) 
{
     if (getElement(buttonName))
     {
	     var button = getElement(buttonName);
	     var hidden = document.createElement("INPUT");
	     var parent = button.parentNode;
	
	     hidden.type = "HIDDEN";
	     hidden.value = button.value;
	     hidden.name = button.name;
	     hidden.id = button.id;
	     
	     button.disabled=true;
	     parent.appendChild(hidden);
	 }
}

 /*
  * Sets the focus to the named field (if present)
  */
function focusField(fieldName) 
{
	if (getElement(fieldName))
		getElement(fieldName).focus();
}

/** Breaks up the given string of tokens into an array, using the given delimiter */

function tokenize(inString, delimiter)
{
	var result = new Array();
   
	for (index = inString.indexOf(delimiter) ; index>=0 ; index = inString.indexOf(delimiter))
	{
		result[result.length] = inString.substring(0,index);      	
      	inString = inString.substring(index+1);
	}
   
	if (inString.length>0)
		result[result.length] = inString;
		
	return result;
}

//Enables/disables a set of fields in one go
function setEnabled(fieldNames, enabled)
{
   for (i=0 ; i<fieldNames.length ; i++)
   {
   	  if (getElement(fieldNames[i]))
   	     getElement(fieldNames[i]).disabled = !enabled;
   }
}

// Moves selected items from one select box to another
function moveSelections(from, to)
{
	if (getElement(from) && getElement(to))
	{
		from = getElement(from);
		to = getElement(to);		
		
	    // Rows are moved in reverse order
	    for (i=from.options.length-1 ; i>=0 ; i--)
	    {
	        if (from.options[i].selected)
	        {
	            to.options[to.length] = new Option(from.options[i].text, from.options[i].value);
	            from.options[i] = null;
	        }
	    }

	    sortList(to);
	}
}

//Clears the items out of the given selection list
function clearList(selectionList)
{
	while (selectionList.options.length>0)
		selectionList.options[selectionList.options.length-1] = null;
}

//sorts the options in a select list, using a stupid bubblesort
function sortList(selectionList)
{
    var temp;
    
    for (i=0; i < selectionList.length - 1; i++)
    {
        for (j=i+1 ; j<selectionList.length ; j++)
        {
            if (selectionList[i].text > selectionList[j].text)
            {
                // Swap rows
                temp=selectionList[i].value;
                selectionList[i].value=selectionList[j].value;
                selectionList[j].value=temp;
                
                temp=selectionList[i].text;
                selectionList[i].text=selectionList[j].text;
                selectionList[j].text=temp;
            }
        }
    }
}

// Adds a hidden field to the form with the given name and value
function addField(form, name, value)
{
	var hidden = document.createElement("INPUT");	
	hidden.type = "HIDDEN";
	hidden.name = name;
	hidden.value = value;
	form.appendChild(hidden);
}
    
function getXMLDocument(location) {

//	var doc = new ActiveXObject("Microsoft.XMLDOM");
    if (document.implementation && document.implementation.createDocument) {
        var doc = document.implementation.createDocument("", "", null);
    }
    else if (window.ActiveXObject) {
        var doc = new ActiveXObject("Microsoft.XMLDOM");
    }
	doc.async = false;
	doc.load(location) ;
 	if (window.ActiveXObject && doc.parseError.errorCode != 0) {
//		alert("error loading :"+location+"\nreason:"+doc.parseError.reason) ;
 		doc = null ;  
 		return null ;
 	}
	return doc ;
}

//Toggles visibility of a div (or other element)
function toggleDiv(divName)
{
	var div = getElement(divName);
	var icon = getElement(divName+".icon");
		
	if (div.style.visibility!="hidden")
	{
		div.style.visibility = "hidden";
		div.style.display = "none";			
		
		if (icon!=null)
			icon.src = "images/open.gif";
	}
	else
	{
		div.style.visibility = "visible";

		if (div.tagName=="DIV")		
			div.style.display = "block";
		else
			div.style.display = "";
			
		if (icon!=null)
			icon.src = "images/close.gif";			
	}
}

//Toggles visibility of a div (or other element)
function ensureVisible(divName)
{
	var div = getElement(divName);
	var icon = getElement(divName+".icon");

	if (div.style.visibility=="hidden")
	{
		div.style.visibility = "visible";

		if (div.tagName=="DIV")		
			div.style.display = "block";
		else
			div.style.display = "";
			
		if (icon!=null)
			icon.src = "images/close.gif";			
	}
}

function createXMLDocument(xmlString) {

//	var doc = new ActiveXObject("Microsoft.XMLDOM");
    if (document.implementation && document.implementation.createDocument) {
        var doc = document.implementation.createDocument("", "", null);
    }
    else if (window.ActiveXObject) {
        var doc = new ActiveXObject("Microsoft.XMLDOM");
    }
	doc.async = false;
	doc.loadXML(xmlString) ;
	if (window.ActiveXObject && doc.parseError.errorCode != 0) {
		alert("error creating :"+xmlString+"\nreason:"+doc.parseError.reason) ;
		doc = null ;  
		return null ;
	}
	return doc ;
}

//date functions

/** Return the number of days in the given month (0=january) */
function daysInMonth(month,year) 
{
  if (month == 1 && year%4 == 0)
	return 29;
	
  return [31,28,31,30,31,30,31,31,30,31,30,31][month];
}

/** Return the full name for the given month of the year (January=1, December=12) */
function getMonthName(month) 
{
    return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][month - 1];
}

/** Return the short name for the given month of the year (Jan=1, Dec=12) */
function getShortMonthName(month) 
{
	return getMonthName(month).substring(0,3);
}

/** Return the abbreviated name for the given day of the week (sun=1, sat=7) */
function getDayName(dow) 
{
    return ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][dow-1];
}

/** Return a date "days" days after the given date */
function addDays(days, date)
{
	var day = date.getDate();
	var month = date.getMonth();
	var year = date.getFullYear();
	
	day += days;

	//adding days
	while (day>daysInMonth(month, year))
	{
		day -= daysInMonth(month, year);
		month++;
		
		if (month>11)
		{
			month=0;
			year++;
		}
	}

	//subtracting days
	while (day<1)
	{
		month--;
		if (month<0)
		{
			month=11;
			year--;
		}

		day += daysInMonth(month, year);
	}
	
	date.setFullYear(year);
	date.setMonth(month);
	date.setDate(day);
}

/** Returns a date "months" months after the given date */
function addMonths(months, date)
{
	var year = date.getFullYear();
	var month = date.getMonth();
	
	month += months;
	
	//adding months
	while (month>11)
	{
		year++;
		month-=12;
	}
	
	//subtracting months
	while (month<0)
	{
		year--;
		month+=12;
	}
	
	//Make sure day is still within month
	date.setFullYear(year);
	date.setMonth(month);
	date.setDate(Math.min(date.getDate(), daysInMonth(date.getMonth(), date.getFullYear())));
}

function parseDate(dateString)
{
	var ddmmyyyy = dateString.replace(/ /,"").split('/');	
	return new Date(parseInt(ddmmyyyy[2]), parseInt(ddmmyyyy[1].replace(/^0/,""))-1, parseInt(ddmmyyyy[0].replace(/^0/,"")));
}

function toDateString(date)
{
	var d = date.getDate();
	var m = date.getMonth()+1;
	var y = date.getFullYear();
	
	return (d<10 ? "0" : "") + d + '/' + (m<10 ? "0" : "") + m + '/' + y;
}

/** Return number of days between the two given date objects */
function daysBetween(date1, date2) 
{
	//want times set to midday
	date1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate(), 12,0,0,0);
	date2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), 12,0,0,0);

	var t1 = date1.getTime();
	var t2 = date2.getTime();
	var dt = t2 - t1;

	if (dt > 0) 
		dt += 12 * 60 * 60 * 1000;
		
	if (dt < 0) 
		dt -= 12 * 60 * 60 * 1000;

	return Math.floor(dt / (24 * 60 * 60 * 1000));
}

/** Returns true if the key pressed for the given event is numeric (ie. 0-9) */
function isNumericKey(e)
{
	var keycode;
	
	if (window.event)
	   keycode = window.event.keyCode;
	else if (e)
	   keycode = e.which;
	else
	   return true; //not supported, let them type anything
	
	return keycode<32 || (keycode>=48 && keycode<=57); //>='0' && <='9'
}

// Form validation functions
 
function getFieldValue(field)
{
	if (field==null)
		return null;
		
	if (field.value)
		return field.value;
		
	if (field.selected)
		return field.selected ? "Y" : "N";
		
	if (field.selectedIndex)
		return field.options[field.selectedIndex].value;
		
	return null;
}

  function radioValue(radioButton)
  {
    for (x = 0; x <= radioButton.length; x++)
    {
        if (radioButton[x].checked == true) return radioButton[x].value; 
    } 
    // if it didn't find anything, return the .value  (behaviour of single radio btn)
    return radioButton.value;
  }

function checkMandatory(fieldId, fieldDescription)
{
	var field = getElement(fieldId);
	
	if (field!=null)
	{	
		var value = getFieldValue(field);
		
		if (value==null || value.length==0)
		{
			alert("A value is required for "+fieldDescription);
			field.focus();
			return false;
		}
	}
	
	return true;
}

function checkDate(fieldId, mandatory, fieldDescription)
{
	if (mandatory && !checkMandatory(fieldId, fieldDescription))
		return false;
		
	var field = getElement(fieldId);
	
	if (field!=null)
	{	
		var value = getFieldValue(field);
		
		if (value!=null && value.length>0)
		{ 
			if (!/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}$/.test(value))
			{
				alert("The value for "+fieldDescription+" must be a date in dd/mm/yyyy format");
				field.focus();
				return false;
			}
			
			//parse the date and check day & month
			value = value.split("/");
			
			//trim leading zeroes
			for (var i=0 ; i<3 ; i++)
			{
				while (value[i].length>1 && value[i].charAt(0)=='0')
					value[i] = value[i].substring(1);
			}
			
			var day = parseInt(value[0]);
			var month = parseInt(value[1]);
			var year = parseInt(value[2]);
			
			if (day<1 || day>daysInMonth(month-1,year) || month<1 || month>12 || year<1900)
			{
				alert("The date given for "+fieldDescription+" is invalid");
				field.focus();
				return false;
			}
		}
	}
	
	return true;
}

function checkInteger(fieldId, mandatory, min, max, fieldDescription)
{
	if (mandatory && !checkMandatory(fieldId, fieldDescription))
		return false;
		
	var field = getElement(fieldId);
	
	if (field!=null)
	{	
		var value = getFieldValue(field);
		
		if (value!=null && value.length>0)
		{
			if (!/^[0-9]*$/.test(value))
			{
				alert("The value for "+fieldDescription+" must be an integer");
				field.focus();
				return false;
			}
			
			value = parseInt(value);
			
			if (value<min || value>max)
			{
				alert("The value for "+fieldDescription+" must be between "+min+" and "+max);
				field.focus();
				return false;
			}
		}
	}
	
	return true;
}

function checkFloat(fieldId, mandatory, min, max, fieldDescription)
{
	if (mandatory && !checkMandatory(fieldId, fieldDescription))
		return false;
		
	var field = getElement(fieldId);
	
	if (field!=null)
	{	
		var value = getFieldValue(field);
		
		if (value!=null && value.length>0)
		{
			if (!/^[0-9]*\.*[0-9]*$/.test(value))
			{
				alert("The value for "+fieldDescription+" must be a number");
				field.focus();
				return false;
			}
			
			value = parseFloat(value);
			
			if (value<min || value>max)
			{
				alert("The value for "+fieldDescription+" must be between "+min+" and "+max);
				field.focus();
				return false;
			}
		}
	}
	
	return true;
}

function checkField(fieldId, mandatory, maxLength, fieldDescription)
{
	if (mandatory && !checkMandatory(fieldId, fieldDescription))
		return false;
		
	var field = getElement(fieldId);
	
	if (field!=null)
	{	
		var value = getFieldValue(field);
		
		if (value!=null && value.length>maxLength)
		{
			alert("The value for "+fieldDescription+" must be "+maxLength+" or fewer characters in length");
			field.focus();
			return false;
		}
	}
	
	return true;
}

function writeError(str)
{
  var dbgObj = document.getElementById("jsdebug");
  if (dbgObj) dbgObj.innerHTML = (str + "<br/>\n" + dbgObj.innerHTML);
}

/** Check if the user really wants to logout. */ 
function verifyLogout()
{
	return confirm("WARNING: you are about to be logged out of the system. All un-saved work will be lost. Ok to continue?");
}
 