	//////////////////////////////////////////////////////////////////////////////////////////////////////////
	// RS. 
	// AJAX Interaction function, which separates object creation, request, and callback.
	// This function allows passing of parameters to whatever is specified as the callback() function.
	// Requirements:
	// - url: the URL of the asp page that loads the data in the background
	// - callback: the function to call when the AJAX load is complete
	// - destinationobject: the object to pass to the callback function, which is to receive the data
	// - param1: an additional parameter that will be passed to the callback function. This could carry
	// anything you like. For select boxes, it carries a possible preselect value.
	// - It is also required that the destinationobject has a corresponding <DIV> tag with an
	// ID value of "<destinationobjectname>AJAXloading". This is for the display of an animated
	// .GIF beside the destinationobject.
	//////////////////////////////////////////////////////////////////////////////////////////////////////////
	function AJAXInteraction(url, callback, destinationobject, param1) {
		var MyAJAXdiv;
		var MySelectBox;

		if (document.getElementById(destinationobject + 'AJAXloading')) { 
			MyAJAXdiv = document.getElementById(destinationobject + 'AJAXloading');
		}
		if (document.getElementById(destinationobject)) { 
			MySelectBox = document.getElementById(destinationobject);
		}

		var http_request = init();
		http_request.onreadystatechange = processRequest;

		function init() {
		  if (window.XMLHttpRequest) {
			return new XMLHttpRequest();
		  } else if (window.ActiveXObject) {
			return new ActiveXObject("Microsoft.XMLHTTP");
		  }
		}
		
		//The function needs to check for the state of the request. If the state has the value of 4, that means that the full 
		//server response is received and it's OK for you to continue processing it.
		//The full list of the readyState values is as follows:
		//* 0 (uninitialized)
		//* 1 (loading)
		//* 2 (loaded)
		//* 3 (interactive)
		//* 4 (complete) 
		// Not all of these readyState values behave as expected in different browser. In fact, only 0 and 4 are truly reliable. - RS.

		function processRequest () {
			if (http_request.readyState == 4) {
				if (http_request.status == 200) {

					if (MyAJAXdiv) {
						MyAJAXdiv.innerHTML = "";
					}
					if (MySelectBox) {
						MySelectBox.disabled=false;
					}

					if (callback) callback(http_request.responseText, destinationobject, param1);

					//http_request.abort(); //Prevents known minor memory leak in IE, but crashes Safari.
				}
			}
			else {
				if (MyAJAXdiv) {
					MyAJAXdiv.innerHTML = "<img src='/_shared/_images/load.gif' border='0'>";
				}

				if (MySelectBox) {
					MySelectBox.disabled=true;
				}
			}
		}

		this.doGet = function() {
		  http_request.open('GET', url, true);
		  http_request.send(null);
		}
		
		this.doPost = function(body) {
		  http_request.open("POST", url, true);
		  http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		  http_request.send(body);
		}	
	}
 

	//////////////////////////////////////////////////////////////////////////////////////////////////////////
	// RS. 
	// Global AJAX Request handler. Use this function to set up a call to retrieve data via AJAX.
	//////////////////////////////////////////////////////////////////////////////////////////////////////////
	function AJAXRequest(url, outputfunction, destinationobject, param1) {
		var ai = new AJAXInteraction(url, eval(outputfunction), destinationobject, param1);
		ai.doGet();	 
		ai = null;
	}


	//////////////////////////////////////////////////////////////////////////////////////////////////////////
	// RS. 
	// Global LoadSelectBox handler. Use this function to load up any SelectBox via AJAX.
	// Requirements:
	// - destinationobject - the select box to receive the JSON data.
	// - preselect - the index of the select box item to be preselected, if any.
	// - Data being returned must be JSON format.
	// - The existence of a <DIV> tag on the calling page, with an ID of "<destinationobject ID>AJAXloading"
	//////////////////////////////////////////////////////////////////////////////////////////////////////////
	function LoadSelectBox(JSONData, destinationobject, preselect) {
				
		var SelectBoxName = destinationobject;  //First value is always the name of the object being populated (REQUIRED)
		var SelectBoxSelectItemID = preselect; //Second value is always the ID value of the item that is to be preselected (OPTIONAL)
		var MySelectBox;
		var MyAJAXdiv;
		var nPreselectIndex;

		if (document.getElementById(SelectBoxName + 'AJAXloading')) { 
			MyAJAXdiv = document.getElementById(SelectBoxName + 'AJAXloading');
		}

		if (document.getElementById(SelectBoxName)) { 
			MySelectBox = document.getElementById(SelectBoxName);
		}
		
		var myJSONtext = JSONData;
		var objData = JSON.parse(myJSONtext);
		
		if (MySelectBox) {
			MySelectBox.options.length= 0;
			// Old method of populating select boxes that while not using DOM, works on all browsers, except Opera 5.02. Works fine on later Operas.
			myOption = new Option("[Select]", "", true, true); //Text, Value, Selected, Default Selected. The last two appear to be dead ducks in most browsers.
			MySelectBox.options[MySelectBox.options.length] = myOption;

		}
		
		nPreselectIndex = -1;
		if (objData) {
			for(i=0;i<objData.items.length;i++) {
				// Old method of populating select boxes that while not using DOM, works on all browsers, except Opera 5.02. Works fine on later Operas.
				if (objData.items[i].id==SelectBoxSelectItemID){
					//alert(SelectBoxSelectItemID);
					myOption = new Option(objData.items[i].name, objData.items[i].id, false, false); //Text, Value, Selected, Default Selected. The last two appear to be dead ducks in most browsers.
					myOption.selected = true; //Preselect this item on the fly. Works on most browsers

					//Some browsers require the setting of a flag, in order to force the preselect of a chosen option, after the whole <Select> has finished building.
					//One example is Opera. 
					nPreselectIndex = i + 1; // i + 1 because we already added an option called [select]
				}
				else {
					myOption = new Option(objData.items[i].name, objData.items[i].id, false, false); //Text, Value, Selected, Default Selected. The last two appear to be dead ducks in most browsers.
				}
				MySelectBox.options[MySelectBox.options.length] = myOption;
				MySelectBox.select

			}

			//Force a preselect here, after building the select box. Required on browsers like Opera which won't preselect elements on the fly.
			if (nPreselectIndex > -1) {
				MySelectBox.options[nPreselectIndex].selected = true; //This forces a preselect if necessary.
			}
		}
		
		myOption = null;
		MySelectBox = null;
		MyAJAXdiv = null;
		objData = null;
	}	



// This function is used to write out Quicktime embedded movie tags, as a way to get around Microsoft's "EOLAS" patch, in 
// which ActiveX objects like Quicktime or Flash are prevented from playing seamlessly by a prompt asking the user to "click to activate" them.
function InsertQuicktimeMovie(movie)
{
	document.write('<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="320" height="285" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0">\n');
	document.write('<param name="src" value="' + movie + '"/>\n');
	document.write('<param name="autoplay" value="true" />');
	document.write('<param name="controller" value="true" />');
	document.write('<embed src="' + movie + '" width="320" height="285" pluginspage=http://www.apple.com/quicktime/download/  autoplay="true" bgcolor="black" ></embed>');
	document.write('</object>\n');
}




	function SubmitForm(which_form, field_str)
	{
		// CHECK FOR OPTIONAL ACTION OVERIDE
		my_arr = field_str.split("~#~")
		if (my_arr.length == 2){
			which_form.action = my_arr[0];
			field_str = my_arr[1];
		} else {
			field_str = my_arr[0];
		}

		field_arr = field_str.split("|");

		with (window.document) {
			for ( i=0; i < which_form.elements.length; i++ ) {
				current_name = which_form.elements[i].name;

				for (j=0; j < field_arr.length; j++){
					data_arr = field_arr[j].split("~=~");
					if (current_name == data_arr[0]) {

						UpdateFieldValue(which_form.elements[i], data_arr[1]);
						break;
					}
				}
			}
		}

		which_form.submit()
	}






	function findPosX(obj) {
		var curleft = 0;
		if (obj.offsetParent) {
			while (1) {
				curleft+=obj.offsetLeft;
				if (!obj.offsetParent) {
					break;
				}
				obj=obj.offsetParent;
			}
		} else if (obj.x) {
			curleft+=obj.x;
		}
		return curleft;
	}



	function ValueCheck(StrValue,CheckValue, strMsg) {
		if (fCheck) {
			if (Trim(StrValue) == CheckValue) { 
				alert(strMsg);
				fCheck = false;
			}
		}
	}

	function ValidateChars( StrValue , AllowChars , strMsg ) {

		if (fCheck) {  

			StrValue = StrValue.toUpperCase()

			for ( var i = 0 ; i < StrValue.length ; i++ ){
				fCheck = false;
				for ( var n = 0 ; n < AllowChars.length ; n++ ){
					if ( AllowChars.substring(n, n + 1) == StrValue.substring(i, i + 1) ) {
						fCheck = true;
						break;
					}
				}
				if ( !fCheck ) {
					alert(strMsg);
					return;
				}
			}
		}
	}


	function IntCheck( IntValue, strMsg ) {
		var AllowChars = "0123456789";
		ValidateChars( IntValue , AllowChars , strMsg );
	}


	function LengthCheck(StrValue, FieldName, MaxLength) {
		if (fCheck) {   
			if (StrValue.length > MaxLength) {   
				var substr = StrValue.substring(StrValue.length,MaxLength);
				alert("you have exceeded the " + MaxLength + " character limit for the " + FieldName + " field\nthe following text will need to be removed:\n\n" + substr);
				fCheck = false;
			}
		}
	}


	function MinLength(StrValue, MinLength, strMsg) {
		if (fCheck) {   
			if (StrValue.length < MinLength) {
				alert(strMsg);
				fCheck = false;
			}
		}
	}


	function SelectCheck(OptionValue,CheckValue, strMsg) {
		if (fCheck) { 
			if (OptionValue == CheckValue) { 	
				alert(strMsg);
				fCheck = false;
			}
		}
	}

	function BoundsCheck(FieldValue, strMsg, minimum, maximum) {
		if (fCheck) {
			if ( (FieldValue < minimum) || (FieldValue > maximum) ) {
				alert(strMsg);
				fCheck = false;
			}
		}
	}

	function UpdateFieldValue(which_element, final_value){
		with (window.document) {
			which_element.value = final_value
			//alert(which_element.name + " = " + which_element.value)
		}
	}


	function AtLeastOneSelected(which_form, element_name, check_mode, alert_message){
		if (fCheck) {
			fCheck = false;
			with (window.document) {
				for ( i=0; i < which_form.elements.length; i++ ) {
					current_name = which_form.elements[i].name
					if (current_name.substring(0,element_name.length) == element_name) {
						if ((check_mode == "checkbox" && which_form.elements[i].checked == true) || (check_mode == "text_field" && which_form.elements[i].value != "")) {
							fCheck = true;
							break;
						}
					}
				}
			}
			if (fCheck == false){
				alert(alert_message);
			}
		}
	}


	function CheckRanking(which_form, field_name, exclusion_str) {

		loop_count = 0
		fCheck = true

		with (window.document) {
			this_value = which_form.elements.length;
			final_array = new Array();

			for ( i=0; i < this_value; i++ ) {
				item_name = which_form.elements[i].name;

				if (item_name == field_name) {

					for(var m = 0; m < which_form.elements[i].options.length; m++){
						if(which_form.elements[i].options[m].selected){
							item_value = which_form.elements[i].options[m].value

							//	alert("item_value = " + item_value);
						}
					}

					tempstr = item_value;
					finalstr = tempstr.split("_");

					if (finalstr[1] != exclusion_str) {

						final_array[loop_count] = finalstr[1];
    
						for ( n=0; n < loop_count; n++) {
							if (fCheck){
	
								if (final_array[n] == finalstr[1]) {
									fCheck = false;
									alert("there is more than one item ranked in position " + finalstr[1] + "\nplease make sure that all rankings are unique and try again");
									//	alert("failed test\n" + final_array[n] + " = " + finalstr[1]);
								}
								//else {
									//	alert("passed test\n" + final_array[n] + " != " + finalstr[1]);
								//}
							}
						}
						loop_count++;

					} // finalstr[1] is not equal to the exclusion_str value [999]
				}
			}
		}
		if (fCheck) {
			which_form.submit()
		}
	}



	function FixedLengthNumber(intValue,fixedLength,element_name) {
		if (fCheck) { 
			var StrMsg = "";

			if ( intValue.length != fixedLength) {  
				StrMsg = "\n" + element_name + " must be " + fixedLength + " digits long, The number you provided was " + intValue.length + " digits long";
			}

			if ( isNaN(intValue) ) { 
				StrMsg = StrMsg + "\n" + element_name + " may only contain numbers, please remove any punctuation or letters";
			}

			if (StrMsg.length > 0) {
					alert(StrMsg);
					fCheck = false;
			}
		}
	}


	function EmailCheck( StrValue, isRequired ) {

        if (fCheck) {   

			StrValue = Trim(StrValue);
			if ( (isRequired == 0) && (StrValue.length == 0) ) {
				return;
			}

			var disallowStr = ",!#$%^<>&*;:~` '\"\\|/"
			var error_prefix = "The email address entered was not valid: \n"

			for ( var i = 0 ; i < StrValue.length ; i++ ){
				for ( var n = 0 ; n < disallowStr.length ; n++ ){
					if ( disallowStr.substring(n, n + 1) == StrValue.substring(i, i + 1) ) {
						alert(error_prefix + "An illegal character [ " + disallowStr.substring(n, n + 1) + " ] was found");
						fCheck = false;
						return
					}
				}
			}

            var myArr = StrValue.split("@");

            if ( myArr.length != 2 ) {
                alert(error_prefix + "There must be a single '@' symbol");
                fCheck = false;
				return;
            }

            if ( myArr[0].length == 0 ) {
                alert(error_prefix + "No user has been specified");
                fCheck = false;
				return;
            }

            if ( myArr[1].length == 0 ) {
                alert(error_prefix + "No domain has been specified");
                fCheck = false;
				return;
            }

            var dotArr = myArr[1].split(".")

            if ( dotArr.length < 2 ) {
                alert(error_prefix + "Please provide a suffix for this domain \( ie: .com, .org or country code\) ");
                fCheck = false;
				return;
            }

			for (i=0; i<dotArr.length; i++) {
				if ( dotArr[i].length < 1 ) {
					alert(error_prefix + "Each element in the domain must be at least one character long \( ie: @a.b.com\)");
					fCheck = false;
					return;
				}
			}

		}
	}



	function Validate_date(date_field)
	{
		if (fCheck){

			var my_arr 		= date_field.split("/");
			var format_msg 	= "\n\ndates must be in the format DD/MM/YYYY"

			if (my_arr.length != 3){
				if (my_arr.length == 1){
					alert("the date string provided did not contain any slashes [/] which are used to seperate day/month/year values\nthe date was unable to be validated");
				} else {
					alert("the date string provided contained " + (my_arr.length - 1) + " slashes [/] instead of 2\nthe date was unable to be validated");
				}
				fCheck = false;
				return;
			} 

			// CONFIRM THAT PROVIDED VALUES ARE ALL INTEGERS
			for(var m = 0; m < my_arr.length; m++){
				if (isNaN(my_arr[m])){
					alert("the date string must contain only numbers, please change '" + my_arr[m] + "'");
					fCheck = false;
					return;
				}
			}

			// initialise
			this_day	= my_arr[0];
			this_month	= my_arr[1];
			this_year	= my_arr[2];

			month_str 	= "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC"
			month_arr 	= month_str.split(",")

			if (this_year.length != 4){
				alert("please enter a four digit year" + format_msg);
				fCheck = false;
				return;
			}

			if (this_month > 12 || this_month < 1){
				alert("there can only be 12 months in a year, please use a number from 1 - 12" + format_msg);
				fCheck = false;
				return;
			}

			if (this_day < 1){
				alert("the day value must be a number greater than 0" + format_msg);
				fCheck = false;
				return;
			}

			if (this_month == 2){
				if (this_year % 4 == 0 && (this_year % 100 != 0 || this_year % 400 == 0)){
					if (this_day > 29){
						alert("there can only be 29 days in " + month_arr[this_month-1] + " on a leap year");
						fCheck = false;
						return;
					}
				} else {
					if (this_day > 28){
						alert("there can only be 28 days in " + month_arr[this_month-1]);
						fCheck = false;
						return;
					}
				}	
			}

			if ( ( (this_month == 4) || (this_month == 6) || (this_month == 9) || (this_month == 11) ) && (this_day > 30) ) {
				alert("there can only be 30 days in " + month_arr[this_month-1]);
				fCheck = false;
				return;
			}

			if (this_day > 31){
				alert("there can not be more that 31 days in " + month_arr[this_month-1]);
				fCheck = false;
				return;
			}		
		}

	}

	function Validate_datediff(start_date_name, start_date_value, end_date_name, end_date_value, error_msg){

		if (fCheck) {

			Validate_date(start_date_value);
			Validate_date(end_date_value);

			var start_arr 		= start_date_value.split("/");
			var end_arr 		= end_date_value.split("/");

			// initialise
			var is_error = 1
			var error_str = ""

			start_day		= parseInt(start_arr[0],10);
			start_month		= parseInt(start_arr[1],10);
			start_year		= parseInt(start_arr[2],10);

			end_day			= parseInt(end_arr[0],10);
			end_month		= parseInt(end_arr[1],10);
			end_year		= parseInt(end_arr[2],10);

			if (start_year > end_year){
				error_str = "year"
			} else {
				if ((start_month > end_month) && (start_year == end_year)){
					error_str = "month"
				} else {
					if ((start_day > end_day) && (start_month == end_month) && (start_year == end_year)){
						error_str = "day"
					} else {
						is_error = 0
					}
				}
			}
			if (is_error == 1){
				alert(error_msg + start_date_name + " (" + start_date_value + ") occurs after " + end_date_name + " (" + end_date_value + ")");
				//alert(error_msg + "The selected " + start_date_name + " (" + start_date_value + ") occurs after " + end_date_name + " (" + end_date_value + ")");
				fCheck = false;
				return;
			}	
		}
	}


	function LTrim(str){

		var whitespace = new String(" \t\n\r");
		var s = new String(str);

		if (whitespace.indexOf(s.charAt(0)) != -1) {
			var j=1, i = s.length;
			while (j < i && whitespace.indexOf(s.charAt(j)) != -1) {
				j++;
			}
			s = s.substring(j, i);
		}
		return s;
	}


	function RTrim(str){

		var whitespace = new String(" \t\n\r");
		var s = new String(str);

		if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {
			var i = s.length - 2;       // Get length of string -2 . Because we have already checked the character at s.length - 1
			while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1){
				i--;
			}
			s = s.substring(0, i+1);
		}
		return s;
	}


	function Trim(str){
		  return RTrim(LTrim(str));
	}

	//asks user to confirm a selection
	function fnConfirmSelection(oForm, sMsg) 
	{
		if(confirm(sMsg))
		{
			return true;
		}
		else
			return false;
	}
