/*
Page Created :	?
By:				Pete and Trev
Description:	javascript library

WARNING:  THERE IS A HARDCODED PATH. In IIMS this is ../common/    in myHR this is ../AJAX/

Page History
----------	---		--------------	---------------------------------------------------------
Date		Who		Reference		Description
---------	---		--------------	---------------------------------------------------------
10/12/2009  seq						Changes copied over from hydra to IIMS.

*/

// JavaScript Document

/*
*	Feel free to improve these functions as needed. Just be
*	careful not to damage or remove any of their existing
*	functionality.
*/

/*
											--- Library ---
----------------------------------------------------------------------------------------------------------------
	Search												Description
----------------------------------------------------------------------------------------------------------------
+++ errorHandler									 ::: Simple Javascript generic error handler
+++ isCompatable									 ::: 
+++ $													 ::: document.getElementById('') replacement
+++ addEvent										 ::: Add JS event to object
+++ removeEvent									 ::: Remove JS event to object
+++ getTarget										 ::: Capture page event
+++ getEventObject								 ::: Capture client event
+++ getEventKey									 ::: Capture key event
+++ getPointerPosition							 ::: Return pointer X:Y
+++ Camelize										 ::: For turning css style names into JS names
+++ setStyleById/setSytle						 ::: Update styles for single object
+++ setStylesByClassName						 ::: Update styles for groups by class
+++ setStylesByTagName							 ::: Update styles for groups by tag
+++ removeChildren								 ::: Remove all child nodes from object
+++ insertAfter									 ::: Insert object after passed object
+++ toggleDisplay									 ::: Toggle object display: none/block etc
+++ findPosX										 ::: Find object X position on screen
+++ findPosY										 ::: Find object Y position on screen
+++ collision Detection							 ::: Test if objects overlap
+++ getElementsByClassName						 ::: Return array of objects by class
+++ getElementsByTagName						 ::: Return array of objects by tag
+++ getFormElements								 ::: Return array of form elements by type
+++ left												 ::: String left
+++ right											 ::: String right
+++ convert Hours To Mins						 ::: Converts string time to int mins
+++ convert Mins To Hours						 ::: Convert int mins to string time
+++ Round to decimal places					 ::: Round number to specified decimal places
+++ Create date from string					 ::: Create JS date from dd/mm/yyyy string
+++ Table Add Row									 ::: Add row to table
+++ Table Remove Row								 ::: Remove row from table
+++ Table Update Cell							 ::: Update table cell
+++ Order Select list							 ::: Order single or all select lists
+++ Check radio sets								 ::: Test for selected radio button
+++ Toggle Yes/No radio sets					 ::: Toggle all Yes/No radio boxes
+++ HTTP Object detect							 ::: Creates xml object for Ajax calls
+++ Check all Dates								 ::: Checks all dates in parent are dd/mm/yyyy by prefix
+++ buildCal										 ::: add calendar functionality to any date fields with attribute "dateType" 
+++ date Field Tab								 ::: add autotabbing to multiple date fields
+++ getDateParts									 ::: Use this to get a javascript date from three date fields
+++ sortTable										 ::: Add sorting to tables
+++ $_GET											 ::: Request Querystring for JS
+++ returnStdDate 								 ::: Returns standard date from JS date
+++ dateAdd 										 ::: Date add function for standard string dates

										 --- Prototypes ---
----------------------------------------------------------------------------------------------------------------
+++ Ajax Class										 ::: Ajax class object contructor
+++ Prototype Left								 ::: string.left(n) returns left n from string
+++ Prototype Right								 ::: string.right(n) returns right n from string
+++ String reverse								 ::: Reverse string
+++ In Array										 ::: Checks array for searched value
+++ GoTo Array										 ::: Return array position for searched value
----------------------------------------------------------------------------------------------------------------
*/

// +++ $ - document.getElementById('')
	function $(){
		var elements = new Array();
		
		// Find all the elems supplied as args
		for(var i=0; i<arguments.length; i++){
			var element = arguments[i];
			
			// If string
			if(typeof element == 'string') element = document.getElementById(element);
			
			// If only 1 arg
			if(arguments.length == 1) return element;
			
			// Else add to array
			elements.push(element);
		}
			
		return elements;
	};
	

(function(){
	if(!window.sds) {window['sds'] = {}}
	
	// DOM constants
	window['sds']['node'] = {
		ELEMENT_NODE						:1,
		ATTRIBUTE_NODE						:2,
		TEXT_NODE							:3,
		CDATA_SECTION_NODE				:4,
		ENTITY_REFERENCE_NODE			:5,
		ENTITY_NODE							:6,
		PROCESSING_INSTRUCTION_NODE	:7,
		COMMENT_NODE						:8,
		DOCUMENT_NODE						:9,
		DOCUMENT_TYPE_NODE				:10,
		DOCUMENT_FRAGMENT_NODE			:11,
		NOTATION_NODE						:12
	};
	
// +++ errorHandler
	/*******************************************************************\
	| Use try{}catch(error){} in your code for the local error handler. |
	| Anything not handled will pass to the global handler and should   |
	| not cause a page error.                                           |
	\*******************************************************************/
	function errorHandler(err){
		if(arguments.length == 3){
			var handler = 'Global';
			var msg = arguments[0];
			var url = document.URL.split('?')[0];
			var line = 'At line: ' + arguments[2];
		}else{
			var handler = 'Local';
			var msg = err.description;
			var url = document.URL.split('?')[0];
			var line = 'Within try/catch block';
		}
		err = null;
		
		// Global throws a browser error if JS error is outside of a function
		// in page global. Wrap your JS in try/catch if you want to see 
		// friendly js error messages!
		if(handler != 'Global'){ 
			alert('Javascript '+handler+' Error Handler Caught an error:'
					+'<br />'+ msg
					+'<br />On page: '+ url.substr(url.lastIndexOf("/")+1,url.length)
					+'<br />'+ line,'Javascript Error!','Continue','left');
		}else{
			alert('Javascript '+handler+' Error Handler Caught an error:'
					+'\n\n'+ msg
					+'\n\nOn page: '+ url.substr(url.lastIndexOf("/")+1,url.length)
					+'\n\n'+ line);
		}
		
		// Turn off browser error message
		return true;
	};
	window['window']['errorHandler'] = errorHandler;
	window['window']['eh'] = errorHandler;
	window.onerror = eh;


// +++ isCompatable
	function isCompatable(other){
		if(other === false
		   || !Array.prototype.push
		   || !Object.hasOwnProperty
		   || !document.createElement
		   || !document.getElementsByTagName
		  ) {
			return false;
		}
		return true;
	};
	window['sds']['isCompatable'] = isCompatable;
	
// +++ $ - document.getElementById('')
	function $(){
		var elements = new Array();
		
		// Find all the elems supplied as args
		for(var i=0; i<arguments.length; i++){
			var element = arguments[i];
			
			// If string
			if(typeof element == 'string') element = document.getElementById(element);
			
			// If only 1 arg
			if(arguments.length == 1) return element;
			
			// Else add to array
			elements.push(element);
		}
			
		return elements;
	};
	window['sds']['$'] = $
	
// +++ addEvent
	function addEvent(obj,type,fn){
		if(!(obj)) return false;
		if (obj.addEventListener) {
			obj.addEventListener( type, fn, false );
			EventCache.add(obj, type, fn);
		}
		else if (obj.attachEvent) {
			obj["e"+type+fn] = fn;
			obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
			obj.attachEvent( "on"+type, obj[type+fn] );
			EventCache.add(obj, type, fn);
		}
		else {
			obj["on"+type] = obj["e"+type+fn];
		}
	};
	
	var EventCache = function(){
		var listEvents = [];
		return {
			listEvents : listEvents,
			add : function(node, sEventName, fHandler){
				listEvents.push(arguments);
			},
			flush : function(){
				var i, item;
				for(i = listEvents.length - 1; i >= 0; i = i - 1){
					item = listEvents[i];
					if(item[0].removeEventListener){
						item[0].removeEventListener(item[1], item[2], item[3]);
					};
					if(item[1].substring(0, 2) != "on"){
						item[1] = "on" + item[1];
					};
					if(item[0].detachEvent){
						item[0].detachEvent(item[1], item[2]);
					};
					item[0][item[1]] = null;
				};
			}
		};
	}();
	addEvent(window,'unload',EventCache.flush);
	window['sds']['addEvent'] = addEvent;
	
// +++ removeEvent
	function removeEvent(node, type, listener){
		if(!(node = $(node))) { return false; }
		
		try{
			if(node.removeEventListener){
				node.removeEventListener(type, listener, false);
				return true;
			}else if(node.detachEvent){
				node.detachEvent('on'+type, node[type+listener]);
				node[type+listener] = null;
				return true;
			}
		}catch(e){errorHandler(e)}
		return false;
	};
	window['sds']['removeEvent'] = removeEvent;
	
	function insertAfter(node, referenceNode){
		if(!(node = $(node))) return false;
		if(!(referenceNode = $(referenceNode))) return false;
		return referenceNode.parentNode.insertBefore(node,referenceNode.nextSibling);
	};
	window['sds']['insertAfter'] = insertAfter;
	
// +++ getTarget
	function getTarget(eventObject){
		
		eventObject = eventObject || getEventObject(eventObject);
		
		var target = eventObject.target || eventObject.srcElement;
		
		if(target.nodeType == sds.node.TEXT_NODE){
			target = node.parentNode;
		}
		
		return target;
	};
	window['sds']['getTarget'] = getTarget;
	
// +++ getEventObject
	function getEventObject(thisEvent){
		return thisEvent || window.event;
	};
	window['sds']['getEventObject'] = getEventObject;
	
// +++ getEventKey
	function getEventKey(arrKey){
		key = window.event;

		if(typeof(key.keyCode) == 'number'){ //DOM
			key.code = key.keyCode;
		}else if(typeof(key.which) == 'number'){ //NS 4 compatible
			key.code = key.which;
		}else if(typeof(key.charCode) == 'number'){ //also NS 6+, Mozilla 0.9+
			key.code = key.charCode;
		}else{
			//Fail
			return false;
		}

		key.actual = String.fromCharCode(key.code);
		
		if(arrKey){
			if(arrKey.indexOf(key.actual) != -1 || arrKey.indexOf(key.code) != -1){
				key.check = true;
			}else{
				key.check = false;
			}
		}
		
		return key;
	};
	window['sds']['getEventKey'] = getEventKey;
	
// +++ getPointerPosition
	function getMouseXY(eventObject){
		eventObject = eventObject || getEventObject(eventObject);
		
		var x = eventObject.pagex || (eventObject.clientX +
									  (document.documentElement.scrollLeft
									  || document.body.scrollLeft));

		var y = eventObject.pagex || (eventObject.clientY +
									  (document.documentElement.scrollTop
									  || document.body.scrollTop));
		return {'x':x,'y':y};
	};
	window['sds']['getMouseXY'] = getMouseXY;
	
// +++ Camelize
	function camelize(s){
		return s.replace(/-(\w)/g, function (strMatch, p1){ return p1.toUpperCase(); });
	};
	window['sds']['camelize'] = camelize;
	
// +++ setStyleById
	function setStyleById(element, styles){
		if(!(element = $(element))) return false;
		
		for(property in styles){
			if(!styles.hasOwnProperty(property)) continue;
			
			if(element.style.property){
				element.style.setProperty(camelize(property,'-'),styles[property],null);
			}else{
				element.style[camelize(property)] = styles[property];
			}
		}
		return true;
	};
	window['sds']['setStyle'] = setStyleById;
	window['sds']['setStyleById'] = setStyleById;
	
// +++ setStylesByClassName
	function setStylesByClassName(parent, tag, className, styles){
		if(!(parent = $(parent))) return false;
		
		var elements = getElementsByClassName(className, tag, parent);
		for(var e=0; e<elements.length; e++){
			setStyleById(elements[e], styles);
		}
		return true;
	};
	window['sds']['setStylesByClassName'] = setStylesByClassName;
	
// +++ setStylesByTagName
	function setStylesByTagName(tagname, styles, parent){
		parent = $(parent) || document;
		
		var elements = parent.getElementsByTagName(tagname);
		for(var e=0; e<elements.length; e++){
			setStyleById(elements[e], styles);
		}
	};
	window['sds']['setStylesByTagName'] = setStylesByTagName;
	
// +++ removeChildren
	function removeChildren(parent){
		if(!(parent = $(parent))) { return false; }
		
		while (parent.firstChild){
			parent.firstChild.parentNode.removeChild(parent.firstChild);
		}
		return parent;
	}
	window['sds']['removeChildren'] = removeChildren;

// +++ insertAfter
	function insertAfter(node, referenceNode){
		if(!(node = $(node))) return false;
		if(!(referenceNode = $(referenceNode))) return false;
		return referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling);
	};
	window['sds']['insertAfter'] = insertAfter;
	
// +++ toggleDisplay
	function toggleDisplay(node, value){
		if(!(node = $(node))) { return false; }
		if(node.style.display != 'none'){
			node.style.display = 'none';
		}else{
			node.style.display = value || '';
		}
		return true;
	};

// +++ findPosX
	function findPosX(obj){
		if(!(obj = $(obj))) { return false; }
		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;
	};
	window['sds']['findPosX'] = findPosX;

// +++ findPosY
	function findPosY(obj){
		if(!(obj = $(obj))) { return false; }
		var curtop = 0;
		if(obj.offsetParent){
			while(1){
				curtop += obj.offsetTop;
				if(!obj.offsetParent) break;
				obj = obj.offsetParent;
			}
		}else if(obj.y){
			curtop += obj.y;
		}
		return curtop;
	};
	window['sds']['findPosY'] = findPosY;
	
// +++ collision Detection
	function colDetect(obj1,obj2){
	
		if(!(obj1 = $(obj1))) { return false; }
		if(!(obj2 = $(obj2))) { return false; }

		var a = new Object();
		var b = new Object();
		
		a.x1 = findPosX(obj1);
		a.x2 = findPosX(obj1) + obj1.offsetWidth;
		a.y1 = findPosY(obj1);
		a.y2 = findPosY(obj1) + obj1.offsetHeight;

		b.x1 = findPosX(obj2);
		b.x2 = findPosX(obj2) + obj2.offsetWidth;
		b.y1 = findPosY(obj2);
		b.y2 = findPosY(obj2) + obj2.offsetHeight;
		
		// Check for complete overlap
		if((b.x1 < a.x1) &&
		   (b.x2 > a.x2) &&
		   (b.y1 < a.y1) &&
		   (b.y2 > a.y2)) return true;
		
		// Check for overlap on X plain
		if(	( 
			( (b.x1 <= a.x1) && (b.x2 >= a.x2) ) ||
			( (b.x1 >= a.x1) && (b.x2 <= a.x2) ) ||
			( (b.x1 <= a.x1) && ((b.x2 > a.x1) && (b.x2 < a.x2)) ) ||
			( ((b.x1 > a.x1) && (b.x1 < a.x2)) && (b.x2 >= a.x2) )
			) 
			&&
			(
			( (b.y1 < a.y1) && ((b.y2 > a.y1) && (b.y2 < a.y2)) ) || 
			( ((b.y1 > a.y1) && (b.y1 < a.y2)) && (b.y2 > a.y2) )
			)
			) return true;

		// Check for overlap on Y plain
		if(	( 
			( (b.y1 <= a.y1) && (b.y2 >= a.y2) ) ||
			( (b.y1 >= a.y1) && (b.y2 <= a.y2) ) ||
			( (b.y1 <= a.y1) && ((b.y2 > a.y1) && (b.y2 < a.y2)) ) ||
			( ((b.y1 > a.y1) && (b.y1 < a.y2)) && (b.y2 >= a.y2) )
			) 
			&&
			(
			( (b.x1 < a.x1) && ((b.x2 > a.x1) && (b.x2 < a.x2)) ) || 
			( ((b.x1 > a.x1) && (b.x1 < a.x2)) && (b.x2 > a.x2) )
			)
			) return true;

	return false;
	};
	window['sds']['colDetect'] = colDetect;

// +++ getElementsByClassName
	function getElementsByClassName(className,tag,parent){
		parent = parent || document;
		if(!(parent = $(parent))) {return false;}
		
		var allTags = (tag == "*" && parent.all) ? parent.all : parent.getElementsByTagName(tag);
		var matchingElements = new Array();
		
		className = className.replace(/\-/g, "\\-");
		var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
		
		var element;
		for(var i=0; i<allTags.length; i++){
			element = allTags[i];
			if(regex.test(element.className)){
				matchingElements.push(element);
			}
		}
		return matchingElements;
	};
	window['sds']['getElementsByClassName'] = getElementsByClassName;

// +++ getElementsByTagName
	function getElementsByTagName(tag,prefix,parent){
		parent = parent || document;
		if(!(parent = $(parent))) {return false;}
		
		var allTags = (tag == '*' && parent.all) ? parent.all : parent.getElementsByTagName(tag);
		var matchingElements = new Array();
		
		var element;
		for(var i=0; i<allTags.length; i++){
			element = allTags[i];
			if(prefix && element.name){
				if(element.name.left(prefix.length) == prefix)
					matchingElements.push(element);
			}
		}
		return matchingElements;
	};
	window['sds']['getElementsByTagName'] = getElementsByTagName;

// +++ getFormElements
	function getFormElements(type,prefix,parent){
		parent = parent || document;
		if(!(parent = $(parent))) {return false;}
		
		var allTags = (type == '*' && parent.all) ? parent.all : parent.getElementsByTagName('input');
		var matchingElements = new Array();
		
		var element;
		for(var i=0; i<allTags.length; i++){
			element = allTags[i];
			if(element.type.toUpperCase() == type.toUpperCase()){
				if(prefix && element.name){
					if(element.name.left(prefix.length) == prefix)
						matchingElements.push(element);
				}else{
					matchingElements.push(element);
				}
			}
		}
		return matchingElements;
	};
	window['sds']['getFormElements'] = getFormElements;

// +++ left
	function left(str,n){
		if(n <= 0){
			return "";
		}else if(n > String(str).length){
			return str;
		}else{
			return String(str).substring(0,n);
		}
	};
	window['sds']['left'] = left;

// +++ right
	function right(str,n){
		if(n <= 0){
			return "";
		}else if(n > String(str).length){
			return str;
		}else{
			var iLen = String(str).length;
			return String(str).substring(iLen,iLen-n);
		}
	};
	window['sds']['right'] = right;

// +++ convert Hours To Mins
	function convertHoursToMins(str){
		if($(str)) if($(str).value) str = $(str).value;
		if(str == null || str == '') return 0;
		str = str.replace(/\./,':');
		if(str.indexOf(':') != -1){
			var part = str.split(/:/);
			var h = Number(part[0])*60;
			var m = Number(part[1]);
		}else{
			var h = 0;
			var m = Number(str);
		}
		if(m > 59 || m < 0) return false;
		return (h+m);
	};
	window['sds']['convertHoursToMins'] = convertHoursToMins;

// +++ convert Mins To Hours
	function convertMinsToHours(int){
/*		($(int)) ? int = Number($(int).value) : Number(int);
		alert(int);
		if(!int) return '00:00';
*/		int = Number(int);
		var m = int%60;
		var h = (int-m)/60;
		if(m < 10) m = '0' + m;
		if(h < 10) h = '0' + h;
		if(isNaN(h) || isNaN(m)) return('00:00');
		return (h +':'+ m);
	};
	window['sds']['convertMinsToHours'] = convertMinsToHours;

// +++ Round to decimal places
	function decRound(num,dp){
		if(!Number(num)) return false;
		
		return (Math.round(num*Math.pow(10,dp))/Math.pow(10,dp));
	};
	window['sds']['decRound'] = decRound;

// +++ Create date from string
	function createDate(strDate){
		var cSep = '';
		
		for(var a=0; a<strDate.length; a++){
			if(f2(strDate.charAt(a))) return false;
			
			if(!f1(strDate.charAt(a))){
				cSep = strDate.charAt(a);
				break;
			}
		}
		
		part = strDate.split(cSep);

		var thisYear = part[2];
		var thisMonth = part[1];
		var thisDay = part[0];

		return (new Date(thisYear,thisMonth-1,thisDay));

		function f1(c){return ((c >= "0") && (c <= "9"))}
		function f2(c){return (((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")))}
	};
	window['sds']['createDate'] = createDate;
	
	
	// +++ Get date parts    --use this for getting three field dates formatted into javascript date
	function getDateParts(element){
		var theYear = element.value;
		do{
			element = element.previousSibling;
		}while(element.nodeType != 1);
		var theMonth = element.value;
		do{
			element = element.previousSibling;
		}while(element.nodeType != 1);
		var theDay = element.value;
		
		var theReturnDate = createDate(theDay+'-'+theMonth+'-'+theYear);
		return theReturnDate;
	}
	
	window['sds']['getDateParts'] = getDateParts;

// +++ Table Add Row
	function tableAddRow(parent,cols,pos){
		if(!(parent = $(parent))) return false;
		tb = parent.getElementsByTagName('tbody')[0];
		
		var tr = parent.getElementsByTagName('tr');
		if(tr.length == 0){
			var newRow = document.createElement('tr');
			tb.appendChild(newRow);
			for(var c=0; c<cols; c++){
				newRow.appendChild(document.createElement('td'));
			}
		}else{
			var newRow = tr[tr.length-1].cloneNode(true);
			if(Number(pos)){
				insertAfter(newRow,tr[pos-1]);
			}else{
				insertAfter(newRow,tr[tr.length-1]);
			}
		}

		var td = newRow.getElementsByTagName('td');
		for(var a=0; a<td.length; a++){
			td[a].innerHTML = '';
		}
	};
	window['sds']['tableAddRow'] = tableAddRow;
/*	Usage:
	Adds a new row to the specified table by copying the last existing row and 
	clearing the innerHTML.
	If there are no rows a new row is created using the cols parameter.
	If pos is passed create the new row at that position - pushes other rows down.
	A pos of 0 (zero) will create a row at the end of the table not at the start.
*/

// +++ Table Remove Row
	function tableRemoveRow(parent,r){
		if(!(parent = $(parent))) return false;
		tb = parent.getElementsByTagName('tbody')[0];
		
		if(!(r)) r = tb.getElementsByTagName('tr').length-1;
		if(!(tb.childNodes[r])) return false;
		row = tb.childNodes[r];
		tb.removeChild(row);
	};
	window['sds']['tableRemoveRow'] = tableRemoveRow;
/*	Usage:
	Removes specified row from the specified table.
	If no row number is passed the last row is removed.
	Rows start from zero.
*/

// +++ Table Update Cell
	function tableUpdateCell(parent,r,c,data){
		if(!(parent = $(parent))) return false;
		
		if(!(parent.getElementsByTagName('tr')[r])) return false;
		var row = parent.getElementsByTagName('tr')[r];
		if(!(row.childNodes[c])) return false;
		row.childNodes[c].innerHTML = data;
	};
	window['sds']['tableUpdateCell'] = tableUpdateCell;
/*	Usage:
	Replaces cell innerHTML in specified table with passed data.
	Row and Cell (r & c) arrays start from zero.
*/


// +++ Order Select list
	function orderSelect(obj){
		if(!$(obj)){ //Get all lists
			var sel = document.getElementsByTagName('select');
			for(var x=0; x<sel.length; x++){
				orderOptions(sel[x]);
			}
		}else{
			orderOptions(obj);
		}
	
		function orderOptions(menu, byValue){
			if(typeof menu == "string"){menu=$(menu);};
			if(!menu){return false;};
			byValue=(byValue)?'value':'text';
			var L=menu.options.length-1
			for(var i=L; i>=0; i--){
				var indexOfMinimum=i;
				for(var i2=i-1; i2>=0; i2--){
					if(menu.options[i2][byValue].toLowerCase() < menu.options[indexOfMinimum][byValue].toLowerCase()){
						indexOfMinimum=i2;
					};
				}
				menu.insertBefore(menu.removeChild(menu.options[indexOfMinimum]),menu.options[L]);
			}
			return true;
		};
	};
	window['sds']['orderSelect'] = orderSelect;

// +++ Check radio sets
	function radioCheck(prefix,parent){
		if(!prefix) return;
		parent = parent || document;

		var jsRad = parent.getElementsByTagName('input');

		for (var a=0; a<jsRad.length; a++){
			if(jsRad[a].type == 'radio' && left(jsRad[a].name,prefix.length) == prefix){
				if(jsRad[a].checked) 
					return jsRad[a].value;
			}
		}
		
		return false;
	};
	window['sds']['radioCheck'] = radioCheck;

// +++ Toggle Yes/No radio sets
	function radioToggle(prefix,master){
		if(!(master = $(master))) master = getTarget(getEventObject());
		var chks = document.getElementsByTagName("input");
		for (i=0; i<chks.length; i++){
			if(left(chks[i].name,prefix.length) == prefix){
				chks[i].checked = false;
				if(master.checked == true){
					if(chks[i].value == 'Y' || chks[i].value =='y' || chks[i].value =='1')
						chks[i].checked = true;
				}else{
					if(chks[i].value == 'N' || chks[i].value =='n' || chks[i].value =='0') 
						chks[i].checked = true;
				}
			}
		}
	};
	window['sds']['radioToggle'] = radioToggle;

// +++ HTTP Object detect
	function getHTTPObject() {
		var xmlhttp = false;
	
		if (window.XMLHttpRequest) {
			xmlhttp = new XMLHttpRequest();
			}else if (window.ActiveXObject) {
				try {
					xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch(e){
					try {
						xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
					}
					catch(e){
						xmlhttp = false;
					}
				}
			}
		return xmlhttp;
	};
	window['sds']['getHTTPObject'] = getHTTPObject;
	
// +++ Check all Dates
	function chkAllDates(dateFieldName,exceptions,parent){

		// ++ Check for delimeter
		function checkDelim (c){
			return (((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) || ((c >= "0") && (c <= "9")))
		};
		
		// ++ Check if valid date
		function isValidDate(DateDay,DateMonth,DateYear){
			if((DateDay.length == 0) && (DateMonth.length == 0) && (DateYear.length == 0)) return false;
			if(isNaN(DateDay) || isNaN(DateMonth) || isNaN(DateYear)) return false;
			if(DateYear.length != 4) return false;
			if(DateYear > 2999 || DateYear < 1810) return false;
			if(!parseInt(DateMonth,10) || !parseInt(DateMonth,10) || !parseInt(DateDay,10) || !parseInt(DateDay,10) || !parseInt(DateYear,10)) return false;	
			if(DateMonth < 1 || DateMonth > 12 || DateDay < 1 || DateDay > 31 || DateYear < 0) return false;
			if(DateMonth==4 || DateMonth==6 || DateMonth==9 || DateMonth==11) {
				if(parseInt(DateDay)==31) return false;
			}
			
			if(DateMonth==2) {
				if((parseInt(DateYear) % 4)!=0) {
					if(parseInt(DateDay)>28) return false;
				} else if((parseInt(DateYear) % 400)==0) {
					if(parseInt(DateDay)>29) return false;
				} else if((parseInt(DateYear) % 100)==0) {
					if(parseInt(DateDay)>28) return false;
				} else {
					if(parseInt(DateDay)>29) return false;
				}
			}
			return true;
		};


		// ++ Parse and handle date object
		function valiDate(obj,delim){
			if(obj.tempValue.length > 0){
				var dateParts = obj.tempValue.split(delim);
			
				var thisYear = dateParts[2];
				var thisMonth = dateParts[1];
				var thisDay = dateParts[0];
	
				if(thisDay.length == 1) thisDay = '0' + thisDay;
				if(thisMonth.length == 1) thisMonth = '0' + thisMonth;
	
				if(!isValidDate(thisDay,thisMonth,thisYear)){
					alert("Please enter your dates as: dd/mm/yyyy");
					obj.focus();
					obj.select();
					return false;
				}else{
					// <% ' We don't care what symbol the user parses their dates with but the system might ' %> \\
					// <% ' For this reason we rebuild the entered date and make absolutly sure it's usable ' %> \\
					if(obj.splt == '3'){

						obj.value = thisDay;
						
						do{
							elem = elem.nextSibling;
						}while(elem.nodeType != 1);
						elem.value = thisMonth;

						do{
							elem = elem.nextSibling;
						}while(elem.nodeType != 1);
						elem.value = thisYear;

					}else{
						obj.value = thisDay +'/'+ thisMonth +'/'+ thisYear;
					}
				}
			}else{
				if(!exceptions){
					alert("Please enter dates in all date fields");
					obj.focus();
					obj.select();
					return false;
				}
			}
		};

		// ++ Start
		parent = parent || document;
		if(!(parent = $(parent))) {return false;}
	
		var jsDates = parent.getElementsByTagName('input');
		for (var i=0; i<jsDates.length; i++){
			var obj = jsDates[i];
			if((left(obj.name,dateFieldName.length) == dateFieldName 
				|| left(obj.id,dateFieldName.length) == dateFieldName)
				&& obj.dateType != null){
				
				switch(obj.dateType){
					
					case 'single':
	
						for (x=0; x<obj.value.length; x++){   
							var delim = obj.value.charAt(x);
							if (!checkDelim(delim)){
								break;
							}
						}
						
						obj.splt = '1';
						obj.tempValue = obj.value;
						if(valiDate(obj,delim) == false) return false;
						break;
						
					case 'multi':
						var elem = obj;
	
						var field = new Array;
						field[0] = elem;
						for(var a=1; a<3; a++){
							do{
								elem = elem.previousSibling;
								field[a] = elem;
							}while(elem.nodeType != 1);
						}
						
						obj = elem;
						obj.tempValue = (field[2].value +'-'+ field[1].value +'-'+ field[0].value);
						obj.splt = '3';
						
						if(valiDate(obj,'-') == false) return false;
						break;
						
				}
			}
		}
	};
	window['sds']['chkAllDates'] = chkAllDates;

// +++ Validate 24hr time
	function validateTime24(obj){
		
		if(obj.value.length < 3) obj.value += ':00';
		
		if(obj.value.indexOf('.')){
			obj.value = obj.value.replace(/\./,':');
		}else if(obj.value.indexOf('-')){
			obj.value = obj.value.replace(/-/,':');
		}else if(obj.value.indexOf(',')){
			obj.value = obj.value.replace(/,/,':');
		}else if(obj.value.indexOf(';')){
			obj.value = obj.value.replace(/;/,':');
		}else if(obj.value.indexOf('-')){
			obj.value = obj.value.replace(/-/,':');
		}
		
		var iS = 0;
		for(var a=0; a<obj.value.length; a++){
			if(obj.value.charAt(a) == ':') iS++;
		}
		
		if(iS > 1){
			alert('Please enter your times as a 24 hour hh:mm value ie. 9:25 or 13:00');
			obj.focus;
			obj.select();
			return false;
		}
		
		if(obj.value.indexOf(':') == -1 && obj.value.length == 4){
			obj.value = obj.value.left(2) + ':' + obj.value.right(2);
		}

		var part = obj.value.split(/:/);
		var h = Number(part[0]);
		var m = Number(part[1]);
		
		if(!(h+1) || !(m+1)){
			alert('Please enter your times as a 24 hour hh:mm value ie. 9:25 or 13:00');
			obj.focus;
			obj.select();
			return false;
		}
		
		if((h > 23 || h < 0) || (m > 59 || m < 0)){
			alert('Time out of range');
			obj.focus;
			obj.select();
			return false;
		}
		
		if(h < 10) h = '0' + h;
		if(m < 10) m = '0' + m;
		
		obj.value = h +':'+ m;

		return true;
	};
	window['sds']['validateTime24'] = validateTime24;
	
// +++ buildCal
	//+++++++++++++++Build calendar functionality for all date fields on a page
	// To use this function simply add dateType="single" for single datefields or dateType="multi" for 3 field dates, to the date field (add to the year field for 3 part dates)
	// NB The calendar scripts are required for this to work. 
	function buildCal(){
		var dateArray = [];
		dateArray = getFormElements('text','','');
		// Clear any previous calendars -- Essential when called to create an ajax'd calendar
		for(var a=0; a<dateArray.length; a++) 
			if($('start_button'+a)) $('start_button'+a).parentNode.removeChild($('start_button'+a));
		for(var i=0; i<dateArray.length; i++) {
			if (dateArray[i].getAttribute("dateType") != null && dateArray[i].getAttribute("showCal") != "false"){
				dateArray[i].setAttribute('size','8');
				dateArray[i].setAttribute('maxLength','10');
				var theImage = document.createElement("img");
				var pServer = document.URL.split('\/')[2];
				var pSite = document.URL.split('\/')[3];
				var cPath = ('http://'+pServer+'/'+pSite+'/');
				theImage.setAttribute("src", cPath+"common/calendar/images/calendar5.gif");
				theImage.setAttribute("id", "start_button"+i);
				theImage.setAttribute('title','Calendar');
				theImage.setAttribute('alt','Calendar');
				setStyleById(theImage,{
										'margin-left':'3px',
										'cursor':'pointer'
										});
				insertAfter(theImage,dateArray[i]);
				numFields = dateArray[i].getAttribute("dateType");
				initCal(dateArray[i].name,i,numFields);
			}
		}
	
		function initCal(theField,theRef,type){
			Calendar.setup({
				inputField	:''+theField,           // ID of the input field
				ifFormat	:"%d/%m/20%y",          // the date format
				button		:"start_button"+theRef,
				numFields	:type,
				onUpdate	:updateCalFields
			});
		};
		
	
	
	  function updateCalFields(cal) {
			var date = cal.date;
			if (cal.params.numFields == "multi"){
				var txtYear = cal.params.inputField;
				var p = txtYear.parentNode;
				var txt = getFormElements('text','txt',p);
				if(txt.length <1){
					alert('Date fields not found.\nPlease check type="text" and name="txt*******"');
					return false;
				}
				txt[0].value = date.print("%d");
				txt[1].value = date.print("%m");
				txt[2].value = date.getYear();
				txt[2].focus();
			}

			// Trigger a change event on the year field
			if(window.ActiveXObject){ // If Explorer
				var event = document.createEventObject();
				try{ 
					cal.params.inputField.fireEvent('onChange',event);
				}catch(e){}
			}else{ // Other browsers
				var event = document.createEventObject('HTMLEvents');
				event.initEvent('onChange','true','true');
			}	
		};
	};
	window['sds']['buildCal'] = buildCal;
	


//+++++++++++++++ Add autotabbing between datefields
	function dateFieldTab(){
		var dateArray = getFormElements('text','','');
		for(var i=0; i<dateArray.length; i++) {
			if (dateArray[i].getAttribute("dateType") != null){
				numFields = dateArray[i].getAttribute("dateType");
				if (numFields == "multi"){
					var txtYear = dateArray[i];
					var p = txtYear.parentNode;
					var txt = getFormElements('text','txt',p);
					addEvent(txt[0], 'keyup', autoTab);
					addEvent(txt[1], 'keyup', autoTab);
					function autoTab() {
						if (this.value.length == 2){
							var elem = this
							do{
								elem = elem.nextSibling;
							}
							while (elem.nodeType != 1);
							elem.focus();
						}
					}
				}
			}
		}
	};
	window['sds']['dateFieldTab'] = dateFieldTab;
	

// +++ DisplayTableRows
	function DisplayTableRows(objClass){
		if (!document.getElementsByTagName) return false;
		// Set tblClass for backward compatibility if class not passed
		if(!objClass) objClass = 'displaytable';
		var tables = document.getElementsByTagName("table");
		for (var i=0; i<tables.length; i++){
			if (tables[i].className == objClass) {
				var odd = true;
				var rows = tables[i].getElementsByTagName("tr");
				for (var j=0; j<rows.length; j++){
					if (odd == true){
						rows[j].className = "odd";
						//rows[j].style.backgroundColor = "#D6D6D6";
						odd = false;
					} else{
						rows[j].className = "even";
						odd = true;
					}
				}
			}
		}
	};
	window['sds']['DisplayTableRows'] = DisplayTableRows;


// +++ sortTable
	function sortTable(tblName){
		/*
		Call:	sortTable('myTableName'); to sort an individual table.
		OR:  	sortTable(); to sort all tables on the page.
		*/
		
		var image_path = "../imgs/";
		var image_up = "arrow-up.gif";
		var image_down = "arrow-down.gif";
		var image_none = "arrow-none.gif";
		var europeandate = true;
		var alternate_row_colors = true;
		var SORT_COLUMN_INDEX;
		var thead = false;
		
		function ts_makeSortable(t) {
			if (t.rows && t.rows.length > 0) {
				if (t.tHead && t.tHead.rows.length > 0) {
					var firstRow = t.tHead.rows[t.tHead.rows.length-1];
					thead = true;
				} else {
					var firstRow = t.rows[0];
				}
			}
			if (!firstRow) return;
			
			// We have a first row: assume it's the header, and make its contents clickable links
			for (var i=0;i<firstRow.cells.length;i++) {
				var cell = firstRow.cells[i];
				var txt = ts_getInnerText(cell);
				if (cell.className != "unsortable" && cell.className.indexOf("unsortable") == -1) {
					cell.innerHTML = '';
					var anc = cell.appendChild(document.createElement('a'));
					anc.href='#';
					anc.i = i;
					anc.className = 'NPSCentered';
					anc.innerHTML = txt
									+'<span class="sortarrow">&nbsp;&nbsp;<img border="none" '
									+'src="'+ image_path + image_none + '" alt="Click to sort"/></span>';
					
					addEvent(anc,'click',ts_resortTable);
				}
			}
			if (alternate_row_colors) {
				alternate(t);
			}
		}
		
		function ts_getInnerText(el) {
			if (typeof el == "string") return el;
			if (typeof el == "undefined") { return el };
			if (el.innerText) return el.innerText;	//Not needed but it is faster
			var str = "";
			
			var cs = el.childNodes;
			var l = cs.length;
			for (var i = 0; i < l; i++) {
				switch (cs[i].nodeType) {
					case 1: //ELEMENT_NODE
						str += ts_getInnerText(cs[i]);
						break;
					case 3:	//TEXT_NODE
						str += cs[i].nodeValue;
						break;
				}
			}
			return str;
		}
		
		function ts_resortTable() {
			var span;
			var lnk = this;
			var clid = this.i;
			for (var ci=0;ci<lnk.childNodes.length;ci++) {
				if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
			}
			var spantext = ts_getInnerText(span);
			var td = lnk.parentNode;
			var column = clid || td.cellIndex;
			var t = getParent(td,'TABLE');
			// Work out a type for the column
			if (t.rows.length <= 1) return;
			var itm = "";
			var i = 0;
			while (itm == "" && i < t.tBodies[0].rows.length) {
				var itm = ts_getInnerText(t.tBodies[0].rows[i].cells[column]);
				itm = trim(itm);
				if (itm.substr(0,4) == "<!--" || itm.length == 0) {
					itm = "";
				}
				i++;
			}
			if (itm == "") return; 
			sortfn = ts_sort_caseinsensitive;
			if (itm.match(/^\d\d[\/\.-][a-zA-z][a-zA-Z][a-zA-Z][\/\.-]\d\d\d\d$/)) sortfn = ts_sort_date;
			if (itm.match(/^\d\d[\/\.-]\d\d[\/\.-]\d\d\d{2}?$/)) sortfn = ts_sort_date;
			if (itm.match(/^-?[£$€Û¢´]\d/)) sortfn = ts_sort_numeric;
			if (itm.match(/^-?(\d+[,\.]?)+(E[-+][\d]+)?%?$/)) sortfn = ts_sort_numeric;
			SORT_COLUMN_INDEX = column;
			var firstRow = new Array();
			var newRows = new Array();
			for (k=0;k<t.tBodies.length;k++) {
				for (i=0;i<t.tBodies[k].rows[0].length;i++) { 
					firstRow[i] = t.tBodies[k].rows[0][i]; 
				}
			}
			for (k=0;k<t.tBodies.length;k++) {
				if (!thead) {
					// Skip the first row
					for (j=1;j<t.tBodies[k].rows.length;j++) { 
						newRows[j-1] = t.tBodies[k].rows[j];
					}
				} else {
					// Do NOT skip the first row
					for (j=0;j<t.tBodies[k].rows.length;j++) { 
						newRows[j] = t.tBodies[k].rows[j];
					}
				}
			}
			newRows.sort(sortfn);
			if (span.getAttribute("sortdir") == 'down') {
					ARROW = '&nbsp;&nbsp;<img border="none" src="'+ image_path + image_down + '" alt="Click to sort Asc"/>';
					newRows.reverse();
					span.setAttribute('sortdir','up');
			} else {
					ARROW = '&nbsp;&nbsp;<img border="none" src="'+ image_path + image_up + '" alt="Click to sort Desc"/>';
					span.setAttribute('sortdir','down');
			} 
			// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
			// don't do sortbottom rows
			for (i=0; i<newRows.length; i++) { 
				if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
					t.tBodies[0].appendChild(newRows[i]);
				}
			}
			// do sortbottom rows only
			for (i=0; i<newRows.length; i++) {
				if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) 
					t.tBodies[0].appendChild(newRows[i]);
			}
			// Delete any other arrows there may be showing
			var allspans = document.getElementsByTagName("span");
			for (var ci=0;ci<allspans.length;ci++) {
				if (allspans[ci].className == 'sortarrow') {
					if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
						allspans[ci].innerHTML = '&nbsp;&nbsp;<img border="none" src="'+ image_path + image_none + '" alt="&darr;"/>';
					}
				}
			}		
			span.innerHTML = ARROW;
			alternate(t);
		}
		
		function getParent(el, pTagName) {
			if (el == null) {
				return null;
			} else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) {
				return el;
			} else {
				return getParent(el.parentNode, pTagName);
			}
		}
		
		function sort_date(date) {	
			// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
			dt = "00000000";
			if (date.length == 11) {
				mtstr = date.substr(3,3);
				mtstr = mtstr.toLowerCase();
				switch(mtstr) {
					case "jan": var mt = "01"; break;
					case "feb": var mt = "02"; break;
					case "mar": var mt = "03"; break;
					case "apr": var mt = "04"; break;
					case "may": var mt = "05"; break;
					case "jun": var mt = "06"; break;
					case "jul": var mt = "07"; break;
					case "aug": var mt = "08"; break;
					case "sep": var mt = "09"; break;
					case "oct": var mt = "10"; break;
					case "nov": var mt = "11"; break;
					case "dec": var mt = "12"; break;
					// default: var mt = "00";
				}
				dt = date.substr(7,4)+mt+date.substr(0,2);
				return dt;
			} else if (date.length == 10) {
				if (europeandate == false) {
					dt = date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
					return dt;
				} else {
					dt = date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
					return dt;
				}
			} else if (date.length == 8) {
				yr = date.substr(6,2);
				if (parseInt(yr) < 50) { 
					yr = '20'+yr; 
				} else { 
					yr = '19'+yr; 
				}
				if (europeandate == true) {
					dt = yr+date.substr(3,2)+date.substr(0,2);
					return dt;
				} else {
					dt = yr+date.substr(0,2)+date.substr(3,2);
					return dt;
				}
			}
			return dt;
		}
		
		function ts_sort_date(a,b) {
			dt1 = sort_date(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
			dt2 = sort_date(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
			
			if (dt1==dt2) {
				return 0;
			}
			if (dt1<dt2) { 
				return -1;
			}
			return 1;
		}
		
		function ts_sort_numeric(a,b) {
			var aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
			aa = clean_num(aa);
			var bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
			bb = clean_num(bb);
			return compare_numeric(aa,bb);
		}
		
		function compare_numeric(a,b) {
			var a = parseFloat(a);
			a = (isNaN(a) ? 0 : a);
			var b = parseFloat(b);
			b = (isNaN(b) ? 0 : b);
			return a - b;
		}
		
		function ts_sort_caseinsensitive(a,b) {
			aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
			bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
			if (aa==bb) {
				return 0;
			}
			if (aa<bb) {
				return -1;
			}
			return 1;
		}
		
		function ts_sort_default(a,b) {
			aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
			bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
			if (aa==bb) {
				return 0;
			}
			if (aa<bb) {
				return -1;
			}
			return 1;
		}
		
		function clean_num(str) {
			str = str.replace(new RegExp(/[^-?0-9.]/g),"");
			return str;
		}
		
		function trim(s) {
			return s.replace(/^\s+|\s+$/g, "");
		}
		
		function alternate(table) {
			// Take object table and get all it's tbodies.
			var tableBodies = table.getElementsByTagName("tbody");
			// Loop through these tbodies
			for (var i = 0; i < tableBodies.length; i++) {
				// Take the tbody, and get all it's rows
				var tableRows = tableBodies[i].getElementsByTagName("tr");
				// Loop through these rows
				// Start at 1 because we want to leave the heading row untouched
				for (var j = 0; j < tableRows.length; j++) {
					// Check if j is even, and apply classes for both possible results
					if ( (j % 2) == 0  ) {
						if ( !(tableRows[j].className.indexOf('odd') == -1) ) {
							tableRows[j].className = tableRows[j].className.replace('odd', 'even');
						} else {
							if ( tableRows[j].className.indexOf('even') == -1 ) {
								tableRows[j].className += " even";
							}
						}
					} else {
						if ( !(tableRows[j].className.indexOf('even') == -1) ) {
							tableRows[j].className = tableRows[j].className.replace('even', 'odd');
						} else {
							if ( tableRows[j].className.indexOf('odd') == -1 ) {
								tableRows[j].className += " odd";
							}
						}
					} 
				}
			}
		}
		
		// Find all tables with class sortable and make them sortable
		if(!tblName) var blAll = true;
		if (!document.getElementsByTagName) return;
		tbls = document.getElementsByTagName("table");
		for (ti=0;ti<tbls.length;ti++) {
			thisTbl = tbls[ti];
			if(blAll){
				ts_makeSortable(thisTbl);
			}else{
				if(thisTbl.name == tblName){
					ts_makeSortable(thisTbl);
				}
			}
		}
	};
	window['sds']['sortTable'] = sortTable;
//+++++++

// +++ $_GET - JS Request QueryString
	// Call with URL object you want to retrieve
	function $_GET(s){
		var url = document.URL;
		var p1 = url.indexOf(s);
		if(p1===-1) return;
		var val = url.substring(p1);
		(val.indexOf('&') !== -1)?p2=val.indexOf('&'):p2=val.length;
		return val.substring(val.indexOf('=')+1);
	};
	window['sds']['$_GET'] = $_GET;
	window['window']['$_GET'] = $_GET;

// +++ returnStdDate
	function returnStdDate(sDate){
		return sDate.print("%d") +'/'+ sDate.print("%m") +'/'+ sDate.getYear();
	};
	window['sds']['returnStdDate'] = returnStdDate;

// +++ dateAdd
	function dateAdd(sDate,interval,incriment){
		var thisDate = createDate(sDate);
		thisDate.dateAdd(interval,incriment);
		return returnStdDate(thisDate);
	};
	window['sds']['dateAdd'] = dateAdd;

// +++ Custom JS Alert box
	// css MUST support this function!
	function customAlert(sText,sTitle,sButton,sAlign){
		function removeCustomAlert() {
			window.onscroll=function(){}
			document.getElementsByTagName("body")[0].removeChild(document.getElementById("modalContainer"));
			document.getElementsByTagName("body")[0].removeChild(document.getElementById("transFrame"));
			document.getElementsByTagName("body")[0].removeChild(document.getElementById("transDiv"));
		};
		
		d = document;
		var txt = sText;
		if(sTitle){
			var ALERT_TITLE = sTitle;
		}else{
			var ALERT_TITLE = 'Alert!';
		}
		if(sTitle){
			var ALERT_BUTTON_TEXT = sButton;
		}else{
			var ALERT_BUTTON_TEXT = 'OK';
		}
		if(sAlign){
			var TEXT_ALIGN = sAlign;
		}else{
			var TEXT_ALIGN = 'center';
		}
		if(d.getElementById('modalContainer')) return false;
		mObj = d.getElementsByTagName("body")[0].appendChild(d.createElement("div"));
		mObj.id = "modalContainer";
		mObj.style.height = d.documentElement.scrollHeight + "px";

		mObjif = d.getElementsByTagName("body")[0].appendChild(d.createElement("iframe"));
		mObjif.id = 'transFrame';
		mObjif.style.height = d.documentElement.scrollHeight + "px";

		mObjtd = d.getElementsByTagName("body")[0].appendChild(d.createElement("div"));
		mObjtd.id = "transDiv";
		mObjtd.style.height = d.documentElement.scrollHeight + "px";

		alertObj = mObj.appendChild(d.createElement('div'));
		alertObj.id = 'alertBox';
		if(d.all && !window.opera) alertObj.style.top = d.documentElement.scrollTop + 'px';
		alertObj.style.left = (d.documentElement.scrollWidth - alertObj.offsetWidth)/2 + 'px';
		alertObj.align = 'center';
		alertObj.style.position = 'absolute';
	
		h1 = alertObj.appendChild(d.createElement('h1'));
		h1.appendChild(d.createTextNode(ALERT_TITLE));
	
		msg = alertObj.appendChild(d.createElement('div'));
		msg.appendChild(d.createElement('br'));
		var msgTxtHolder = d.createElement('div');
		msgTxtHolder.innerHTML = txt
		msg.appendChild(msgTxtHolder);
		sds.setStyle(msg,{'font-size':'0.8em'});
		sds.setStyle(msgTxtHolder,{'align':TEXT_ALIGN});
		msg.appendChild(d.createElement('br'));
	
		btn = alertObj.appendChild(d.createElement('button'));
		btn.id = 'closeBtn';
		btn.value = ALERT_BUTTON_TEXT;
		btn.className = 'button';
		btn.style.cursor = 'pointer';
		btn.focus();
		addEvent(btn,'click',removeCustomAlert);
		//window.onscroll=function(){window.scroll(0,0)}  // <- This works but it's jerky  :(
	};
	window['sds']['customAlert'] = customAlert;
	window['window']['customAlert'] = customAlert;


// +++ Cookie Functions +++ \\
// +++ getCookie
	function getCookie( name ) {
		var start = document.cookie.indexOf( name + "=" );
		var len = start + name.length + 1;
		if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
			return null;
		}
		if ( start == -1 ) return null;
		var end = document.cookie.indexOf( ";", len );
		if ( end == -1 ) end = document.cookie.length;
		return unescape( document.cookie.substring( len, end ) );
	};
	window['sds']['getCookie'] = getCookie;
		
// +++ setCookie
	function setCookie( name, value, expires, path, domain, secure ) {
		var today = new Date();
		today.setTime( today.getTime() );
		if ( expires ) {
			expires = expires * 1000 * 60 * 60 * 24;
		}
		var expires_date = new Date( today.getTime() + (expires) );
		document.cookie = name+"="+escape( value ) +
			( ( expires ) ? ";expires="+expires_date.toGMTString() : "" ) + //expires.toGMTString()
			( ( path ) ? ";path=" + path : "" ) +
			( ( domain ) ? ";domain=" + domain : "" ) +
			( ( secure ) ? ";secure" : "" );
	};
	window['sds']['setCookie'] = setCookie;
		
// +++ deleteCookie
	function deleteCookie( name, path, domain ) {
		if ( getCookie( name ) ) document.cookie = name + "=" +
				( ( path ) ? ";path=" + path : "") +
				( ( domain ) ? ";domain=" + domain : "" ) +
				";expires=Thu, 01-Jan-1970 00:00:01 GMT";
	};
	window['sds']['deleteCookie'] = deleteCookie;

	
// +++ Ajax Class Start
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\\
	function ajaxObject(page,query,method,proc,div,func,message){
		if(arguments.length){
			var values = new Array();
			for(var x=7; x<arguments.length; x++){
				// If this arg is an array break it down into our values
				if(arguments[x].isArray()){
					for(var y=0;y<arguments[x].length;y++){
						values.push(arguments[x][y]);
					}
				}else{
					// Push next value to array
					values.push(arguments[x]);
				}
			}
			this.init(page,query,method,proc,div,func,message,values);
		}
	};
	window['sds']['ajaxObject'] = ajaxObject;
	window['window']['ajaxObject'] = ajaxObject;
	
	// --- Ajax Class - Implimentation function
	ajaxObject.prototype.init = function(a,b,c,d,e,f,g,values){
		this.page 		= a;
		this.query 		= b;
		this.method 	= (c)?(c.toUpperCase() == 'POST')?'POST':'GET':'GET'; // Old skool nested ifs! :)
		this.proc		= (d)?(d.toUpperCase() == 'TRUE')?true:false:false;
		this.div			= e;
		this.func		= f;
		this.message	= g;
		this.values		= values;
		
		this.http		= this.getHTTPObject(); 	// HTTP object for the actual call
		this.params		= this.buildParamString();	// Builds a string of named pairs for call
		this.state		= this.http.readyState;		// HTTP state (0-4)
		this.response	= this.submitAjax();			// The response from the call as a string
	};
	
	// --- Ajax Class - Return HTTP request state (0-4)
	ajaxObject.prototype.returnState = function(){
		return this.http.readyState;
	};
	
	// --- Ajax Class - Sniff and return appropriate HTTP object
	ajaxObject.prototype.getHTTPObject = function() {
		var xmlhttp = false;
	
		// Sniff sniff
		if (window.XMLHttpRequest) {
			xmlhttp = new XMLHttpRequest();
			}else if (window.ActiveXObject) {
				try {
					xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch(e){
					try {
						xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
					}
					catch(e){
						xmlhttp = false;
					}
				}
			}
		return xmlhttp;
	};
	
	// --- Ajax Class - Turn the arguments array into a passable parameter string
	ajaxObject.prototype.buildParamString = function(){
		var theParameters = '';
		var fields = document.all;
		var valuesArray = this.values;
		for (var i = 0; i < valuesArray.length; i++){
			var j = i+1;
			var thisVal = valuesArray[i];
			if(thisVal != null){
				if(thisVal.left(4) == "frm_" || thisVal.left(4) == "FRM_"){
					var iLen = thisVal.length - 4;
					for(var a=0;a<fields.length;a++){
						if(fields[a].name == thisVal.right(iLen)){
							window["param"+j] = "value"+j+"=" + escape(fields[a].value);
							a = fields.length;
						}
					}
				}else{
					window["param"+j] = "value"+j+"=" + escape(thisVal);
				}
			}
			theParameters += "&" + window["param"+j];
		}
		return theParameters;
	};
	
	// --- Ajax Class - Generate the correct URL for the Ajax page to be called
	ajaxObject.prototype.returnURL = function(){
		if (this.page.substring(0,1) == '~'){
			url = this.page.substr(1,this.page.length);
		}
		else{
			var slashPos = "";
			var url = '';
			slashPos = this.page.lastIndexOf("/")
			
			if(slashPos != -1){		
				url = this.page.substr(0,slashPos+1) + "../ajax/" + this.page.substr(slashPos+1,this.page.length)
			} else {
				url =  "../ajax/" +this.page; 	
			}
		}
		return url;
	};
	

	// --- Ajax Class - Submit Ajax call to the Ajax page
	ajaxObject.prototype.submitAjax = function(){
		var obj = this;
		var http = obj.http;
		var url = this.returnURL();
	
		var strSub = '';
		if (this.method.toUpperCase() == "POST"){
			http.open("POST", url, this.proc);
			http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			if(this.proc == true) http.onreadystatechange = obj.handleObjectHttpResponse();
			strSub = "method=post&query=" + this.query + this.params
								  + "&" + "&fix=" 
								  + Date() + Math.floor(Math.random()*999999);
			http.send(strSub);
		}else{
			strSub = url + "?method=get&query=" + this.query + this.params 
					  + "&" + "&fix=" + Date() + Math.floor(Math.random()*999999);
			http.open("GET", strSub, this.proc);
			if(this.proc == true) http.onreadystatechange = 
				function(){if(http.readyState == 4){
					obj.response = http.responseText;
					if(obj.div != ''){
						if($(obj.div)){ 
							$(obj.div).innerHTML = obj.response;
							obj.DisplayTableRows();
						}
					}
				}
			}
			http.send(null);
		}
		
		// Handler for SJAX
		if(http && this.proc != true){
			if(http.readyState == 4){
				if(obj.div != ''){
					if($(obj.div)){
						$(obj.div).innerHTML = http.responseText;
						obj.DisplayTableRows();
					}
				}
				return http.responseText;
			}
		}else{
			return '';
		}
	};
	
	// --- Ajax Class - Return the result as returned from the Ajax page
	ajaxObject.prototype.returnResult = function(){
		return this.response;
	};
	
	// --- Ajax Class - Return the result as an array
	ajaxObject.prototype.returnArray = function(c){
		function f1(c){return ((c >= "0") && (c <= "9"))}
		function f2(c){return (((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")))}
	
		function setC(str){
			for(var a=0; a<str.length; a++){
				if(f2(str.charAt(a))) return false;
				
				if(!f1(str.charAt(a))){
					return str.charAt(a);
					break;
				}
			}
		}
	
		if(!c) c = setC(this.response)||',';
		
		return this.response.split(c);
	};
	
	// --- Ajax Class - DisplayTableRows as a prototype
	ajaxObject.prototype.DisplayTableRows = function(objClass){
		if (!document.getElementsByTagName) return false;
		// Set tblClass for backward compatibility if class not passed
		if(!objClass) objClass = 'displaytable';
		var tables = document.getElementsByTagName("table");
		for (var i=0; i<tables.length; i++){
			if (tables[i].className == objClass) {
				var odd = true;
				var rows = tables[i].getElementsByTagName("tr");
				for (var j=0; j<rows.length; j++){
					if (odd == true){
						rows[j].className = "odd";
						//rows[j].style.backgroundColor = "#D6D6D6";
						odd = false;
					} else{
						rows[j].className = "even";
						odd = true;
					}
				}
			}
		}
	};

	// --- Ajax Class - Output prototype for dev use
	ajaxObject.prototype.toString = function(){
		return '-- Ajax Object: -- \n'
					+ 'Page: ' + this.page + '\n' 
					+ 'Query: ' + this.query + '\n' 
					+ 'Method: ' + this.method + '\n' 
					+ 'Div: ' + this.div + '\n' 
					+ 'Func: ' + this.func + '\n' 
					+ 'Message: ' + this.message + '\n' 
					+ 'Values: ' + this.returnValues() + '\n' 
					+ 'ParamStr: ' + this.params + '\n' 
					+ 'Response: ' + this.response + '\n';
	};
	
	// --- Ajax Class - Returns passed vars as a string for dev use
	ajaxObject.prototype.returnValues = function(){
		var s = '';
		for(var x=0; x<this.values.length; x++){
			s += '|'+ this.values[x] +'|';
		}
		return s.replace(/\|\|/gi,'|');
	};
	
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\\
// +++ Ajax Class End
	
	



//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\\
})();




// +++ Prototypes

// +++ Prototype Left
String.prototype.left = function(n){
	if(n <= 0){
		return "";
	}else if(n > this.length){
		return this;
	}else{
		return this.substring(0,n);
	}
}

// +++ Prototype Right
String.prototype.right = function(n){
		if(n <= 0){
			return "";
		}else if(n > this.length){
			return this;
		}else{
			var iLen = this.length;
			return this.substring(iLen,iLen-n);
		}
	};


// +++ dateAdd
Date.prototype.dateAdd = function(strInterval, intIncrement){
	if(strInterval != "M"
		&& strInterval != "D"
		&& strInterval != "Y"
		&& strInterval != "h"
		&& strInterval != "m"
		&& strInterval != "uM"
		&& strInterval != "uD"
		&& strInterval != "uY"
		&& strInterval != "uh"
		&& strInterval != "um"
		&& strInterval != "us"){
		throw("Dev Error!\ndateAdd: First parameter must be M, D, Y, h, m, uM, uD, uY, uh, um or us");
	}

	if(typeof(intIncrement) != "number"){
		throw("Dev Error!\ndateAdd: Second parameter must be a number");
	}

	switch(strInterval){
		case "M":
		this.setMonth(parseInt(this.getMonth()) + parseInt(intIncrement));
		break;

		case "D":
		this.setDate(parseInt(this.getDate()) + parseInt(intIncrement));
		break;

		case "Y":
		this.setYear(parseInt(this.getYear()) + parseInt(intIncrement));
		break;

		case "h":
		this.setHours(parseInt(this.getHours()) + parseInt(intIncrement));
		break;

		case "m":
		this.setMinutes(parseInt(this.getMinutes()) + parseInt(intIncrement));
		break;

		case "s":
		this.setSeconds(parseInt(this.getSeconds()) + parseInt(intIncrement));
		break;

		case "uM":
		this.setUTCMonth(parseInt(this.getUTCMonth()) + parseInt(intIncrement));
		break;

		case "uD":
		this.setUTCDate(parseInt(this.getUTCDate()) + parseInt(intIncrement));
		break;

		case "uY":
		this.setUTCFullYear(parseInt(this.getUTCFullYear()) + parseInt(intIncrement));
		break;

		case "uh":
		this.setUTCHours(parseInt(this.getUTCHours()) + parseInt(intIncrement));
		break;

		case "um":
		this.setUTCMinutes(parseInt(this.getUTCMinutes()) + parseInt(intIncrement));
		break;

		case "us":
		this.setUTCSeconds(parseInt(this.getUTCSeconds()) + parseInt(intIncrement));
		break;
	}
	return this;
}

// +++ String reverse
String.prototype.reverse = function(){
	parts = this.split('');
	parts = parts.reverse();
	string = parts.join('');
	
	return string;
}

// +++ In Array
Array.prototype.inArray = function(value){
	for (var i=0; i < this.length; i++){
		if (this[i] === value){
			return true;
		}
	}
	return false;
};

// +++ GoTo Array
Array.prototype.goToArray = function(value){
	for (var i=0; i < this.length; i++){
		if (this[i] === value){
			return i;
		}
	}
	return false;
};

Object.prototype.isArray = function(){
	return this.constructor == Array;
};






