/*
 *	$Id: common.js 1 2006-12-16 10:21:16Z james $
 *	$Name$
 *
 *	This fle provides a number of useful global functions for use in any of the templates.
 */

// Global Vars
var undefined;

//-------------------------------
// BOOL in_array( needle, haystack )
//--
// MIXED needle		= Value to search for in the haystack array
// ARRAY haystack	= Array in which to search
//--
// Searches for an occurance of needle inside the haystack array and returns the result
//-------------------------------
function in_array(needle, haystack) {

	// Vars
	if(haystack==null) return;
	var result = false;

	// Search
	for(var i=0; i<haystack.length; i++) {
		if(haystack[i]==needle) result = true;
	}

	// Result
	return result;
}

//-------------------------------
// HTMLElement getHTMLElement( id, [doc] )
//--
// STRING id		= ID of the element to get
// HTMLDocument doc	= Document in which to search for the element. Leave blank to search in current document.
//--
// Returns the object identified by the ID tag
//-------------------------------
function getHTMLElement(id, doc) {

	// Vars
	if(doc==null) doc = document;

	// Determine how to get element
	if(doc.getElementById || doc.getElementsByName) {
		var e = doc.getElementById(id);
		if(e==null && doc.getElementsByName) {
			e = doc.getElementsByName(id);
			if(e.length<=0) {
				e = null;
			}
			else {
				e = e[0];
			}
		}
		return e;
	}
	else if(doc.all) {
		return doc.all[id];
	}
	else if(doc.layers) {
		return doc.layers[id];
	}
	else {
		return null;
	}
}

//-------------------------------
// VOID toggleElementDisplay( id )
//--
// STRING id	= ID of the element
//--
// Show/Hide the specified element
//-------------------------------
function toggleElementDisplay(id) {

	// Vars
	var e = getHTMLElement(id);

	// Toggle display
	e.style.display = (e.style.display=='' || e.style.display=='block') ? 'none' : 'block';
}

//-------------------------------
// STRING escapeFormValue( v )
//--
// STRING v	= String to escape
//--
// Replaces characters that shouldn't appear in the value="" attribute of a form element.
//-------------------------------
function escapeFormValue(v) {
	v = v.toString().replace(/&/g, '&amp;');	// Important that this comes before '&quot;' or any other strings that use '&' legitimatly
	v = v.toString().replace(/"/g, '&quot;');
	return v;
}

//-------------------------------
// VOID orderTableRows( tbodyID, columnNum, dir )
//--
// STRING tbodyID	= ID of the table body to be sorted
// INT columnNum	= The coumn to be ordered
// INT colType		= Type of column contents (I=integer, D*=date with * as the separator,A=alphanumeric)
//--
// Sorts the rows in the specified table body.
// If you want to sort a cell using a value other than the one actually displayed, then
// add a 'sortValue' attribute in the <td> tag which should contain the actual value you want to sort with.
//-------------------------------
var TABLE_ROW_ORDER_DIR = new Object();		// Stores the current direction of the ordering imposed on a table
function orderTableRows(tbodyID, columnNum, colType) {

	// Vars
	var tbody = getHTMLElement(tbodyID);
	if(tbody==null) return;
	if(colType==null) colType = 'A';
	var dir = 1;

	// Toggle/store direction
	if(TABLE_ROW_ORDER_DIR[tbodyID]==null) {
		TABLE_ROW_ORDER_DIR[tbodyID] = new Object();
	}
	if(TABLE_ROW_ORDER_DIR[tbodyID][columnNum]!=null) {
		dir = (TABLE_ROW_ORDER_DIR[tbodyID][columnNum]+1)%2;
	}
	TABLE_ROW_ORDER_DIR[tbodyID][columnNum] = dir;

	// Sort rows
	var len = tbody.rows.length;
	for(var i=0; i<len; i++) {
		var swapID = null;
		for(var j=0; j<len; j++) {

			// Skip same column test
			//if(j==i) continue;

			// Get column contents and format according to colType
			var cellI = tbody.rows[i].cells[columnNum];
			var cellJ = tbody.rows[j].cells[columnNum];
			var contentI = cellI.innerText ? cellI.innerText : stripHTMLTags(cellI.innerHTML);
			var contentJ = cellJ.innerText ? cellJ.innerText : stripHTMLTags(cellJ.innerHTML);
			var colI = cellI.getAttribute('sortValue')!=null ? cellI.getAttribute('sortValue') : contentI.toLowerCase();
			var colJ = cellJ.getAttribute('sortValue')!=null ? cellJ.getAttribute('sortValue') : contentJ.toLowerCase();
			if(colType=='I') {
				colI = parseInt(colI.replace(/[A-za-z\s]/g, ''));
				colJ = parseInt(colJ.replace(/[A-za-z\s]/g, ''));
			}
			else if(colType.charAt(0)=='D') {
				var parts = {I:colI.split(colType.charAt(1)), J:colJ.split(colType.charAt(1))};
				var total = {I:0, J:0};
				var mults = [12, 1, 365];
				for(var a=0; a<parts.I.length; a++) {
					total.I += parseInt(parts.I[a]) * mults[a];
					total.J += parseInt(parts.J[a]) * mults[a];
				}
				colI = total.I;
				colJ = total.J;
			}

			// Perform test
			var test = dir==1 ? colI>colJ : colI<colJ;
			if(test) {
				swapTableRows(tbody.rows[i], tbody.rows[j]);
				j--;
			}
		}
	}
}

function swapTableRows(rowA, rowB) {

	// Get contents and 'sortValue' attribute (if it exists) of all cells of rowA
	var content = new Array();
	var sortValue = new Array();
	for(var i=0; i<rowA.cells.length; i++) {
		content[i] = rowA.cells[i].innerHTML;
		sortValue[i] = rowA.cells[i].getAttribute('sortValue');
	}

	// Copy all rowB cells into rowA
	for(var i=0; i<rowB.cells.length; i++) {
		rowA.cells[i].innerHTML = rowB.cells[i].innerHTML;
		rowA.cells[i].setAttribute('sortValue', rowB.cells[i].getAttribute('sortValue'));
	}

	// Copy all saved content into rowB
	for(var i=0; i<rowA.cells.length; i++) {
		rowB.cells[i].innerHTML = content[i];
		rowB.cells[i].setAttribute('sortValue', sortValue[i]);
	}
}

function stripHTMLTags(string) {
	var temp = "";
	var regExp = /<\S[^>]*>/g;
	return string.replace(regExp, "");
}

function openPopupWindow(url, width, height, features, win_name) {

	// Vars
	if(features==null) features = new Array('resizable', 'scrollbars=yes');
	if(win_name==null) var win_name = 'WIN_'+Math.round(Math.random()*100000);
	if(width!=null) features.push('width='+(parseInt(width)+20));
	if(height!=null) features.push('height='+(parseInt(height)+10));

	// Calculate center if a width/height are provided
	if(width!=null) {
		var x = (screen.availWidth - width)/2;
		features.push('left='+x+'px');
	}
	if(height!=null) {
		var x = (screen.availHeight - height)/2;
		features.push('top='+x+'px');
	}

	// Open window
	var win = window.open(url, win_name, features.join(','));
	win.focus();

	// Return a reference to this window
	return win;
}

function extractChildNodeByName(node, name) {
	var result = null;
	var nodes = node.childNodes;
	for(var i=0; i<nodes.length; i++) {
		if(nodes[i].name==name) result = nodes[i];
	}
	return result;
}

//-------------------------------
// INT findPosX( obj )
// INT findPosY( obj )
//--
// HTMLElement obj	= Object whose position we want to find
//--
// Finds the X and Y position of the specified element.
// HACK:
// 	This function looks for the custom offset variables "EXNT_findPosX_offset" and "EXNT_findPosY_offset"
//	which you an use to manually adjust the returned values to fit with your template.
//-------------------------------
var EXNT_findPosX_offset = 0;
var EXNT_findPosY_offset = 0;
function findPosX(obj) {
	var curleft = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curleft += obj.offsetLeft;
			/*if(obj.offsetParent.currentStyle) {
				var S = obj.offsetParent.currentStyle;
				var marginLeft = parseInt('0'+S['marginLeft'], 10);
				curleft -= marginLeft;
			}*/
			obj = obj.offsetParent;
		}
	}
	else if (obj.x) curleft += obj.x;
	curleft += EXNT_findPosX_offset;
	return curleft;
}

function findPosY(obj) {
	var curtop = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curtop += obj.offsetTop;
			/*if(obj.offsetParent.currentStyle) {
				var S = obj.offsetParent.currentStyle;
				var marginTop = parseInt('0'+S['marginTop'], 10);
				curtop -= marginTop;
			}*/
			obj = obj.offsetParent;
		}
	}
	else if (obj.y) {
		curtop += obj.y;
	}
	curtop += EXNT_findPosY_offset;
	return curtop;
}

function getMousePos(e) {
	var posx = 0;
	var posy = 0;
	if (!e) var e = window.event;
	if (e.pageX || e.pageY)
	{
		posx = e.pageX;
		posy = e.pageY;
	}
	else if (e.clientX || e.clientY)
	{
		posx = e.clientX + document.body.scrollLeft;
		posy = e.clientY + document.body.scrollTop;
	}
	return {x:posx, y:posy};
}

function setCookie(name, value, expires, path, domain, secure) {
	var c = name + "=" + escape(value) +
		((expires) ? "; expires=" + expires.toGMTString() : "") +
		((path) ? "; path=" + path : "") +
		((domain) ? "; domain=" + domain : "") +
		((secure) ? "; secure" : "");
	document.cookie = c;
}

function getCookie(name) {
	var cookies = new Object();
	var data = document.cookie.split(";");
	for(var i=0; i<data.length; i++) {
		var kv = data[i].split("=");
		cookies[kv[0].replace(/^\s/, '')] = kv[1];
	}
	return cookies[name];
}

function uniqid() {

	// Vars
	var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
	var len = 12;

	// Generate
	// Make sure the first charater is an alphabetic char because this code may be used for naming files.
	var id = chars.charAt(Math.floor(Math.random()*52));
	while(id.length<len) {
		id += chars.charAt(Math.floor(Math.random()*chars.length));
	}

	// Result
	return id;
}

//-------------------------------
// object cloneObject( obj )
//--
// OBJECT obj	= Object to be cloned
//--
// Creates a clone of the specified simple object.
//-------------------------------
function cloneObject(obj) {

	// Vars
	var isArray = obj!=null && obj.pop;
	var objC = isArray ? [] : {};

	// Clone it
	if(isArray) {
		for(var i=0; i<obj.length; i++) {
			objC[i] = (typeof(obj[i])=='object') ? cloneObject(obj[i]) : obj[i];
		}
	}
	else {
		for(var i in obj) {
			objC[i] = (typeof(obj[i])=='object') ? cloneObject(obj[i]) : obj[i];
		}
	}

	// Result
	return objC;
}

/********** AJAX STUFF **************************************************************/

function ajax_ORSC() {
	this.setVar = function(vName, vValue) {
		this[vName] = vValue;
	}
}

//--
// void ajax_doGET( reqObj, reqUrl, orsc )
//--
// Initiates an Ajax GET call to the specified script
//--
function ajax_doGET(reqObj, reqUrl, orsc) {

	// Send request
	reqObj.onreadystatechange = orsc.onreadystatechange!=null ? orsc.onreadystatechange : orsc;
	reqObj.open("GET", reqUrl, true);
	reqObj.send(null);
}

//--
// void ajax_doPOST( reqObj, reqUrl, orsc, params )
//--
// Initiates an Ajax POST call to the specified script
//--
function ajax_doPOST(reqObj, reqUrl, orsc, params) {

	// Build parameters string
	var paramsStr = '';
	for(var i in params) {
		paramsStr += i+'='+encodeURIComponent(params[i])+'&';	// ecnodeURI doesn't encode '&', so need encodeURIComponent
	}

	// Send request
	reqObj.onreadystatechange = orsc;
	reqObj.open("POST", reqUrl, true);
	reqObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	reqObj.setRequestHeader("Content-length", paramsStr.length);
	reqObj.setRequestHeader("Connection", "close");
	reqObj.send(paramsStr);
}

//--
// object ajax_createResultObject( xml )
//--
// XMLDocument xml	= The XML document (returned by the server) that is to be parsed into a simple object
//--
// Parse the given XML document tree into a simple object.
//--
function ajax_createResultObject(xml) {

	// Vars
	var resultObj = new Object();

	// Parse child nodes
	for(var c=0; c<xml.childNodes.length; c++) {
		var node = xml.childNodes[c];
		var nType = node.nodeType;
		var nName = node.nodeName;

		// Parse child nodes
		if(nType==1) {
			if(resultObj[nName]==null) {

				// Build child node-set
				resultObj[nName] = ajax_createResultObject(node);

				// Add attributes to result object
				if(typeof resultObj[nName]=='object' && node.attributes!=null) {
					for(var a=0; a<node.attributes.length; a++) {
						resultObj[nName][node.attributes[a].name] = node.attributes[a].value;
					}
				}
			}
			else {
				// Convert the node to an array
				if(typeof resultObj[nName]!='object' || resultObj[nName].length==null) resultObj[nName] = [resultObj[nName]];

				// Build the child node-set
				var childObj = ajax_createResultObject(node);

				// Add attributes to result object
				if(typeof childObj=='object' && node.attributes!=null) {
					for(var a=0; a<node.attributes.length; a++) {
						childObj[node.attributes[a].name] = node.attributes[a].value;
					}
				}

				// Add the child node-set as a new array element
				resultObj[nName].push(childObj);
			}
		}

		// Parse node value
		if(nType==3) {
			if(resultObj['#text']==null) resultObj['#text'] = '';
			resultObj['#text'] += node.nodeValue;
		}

		// Parse CDATA section
		if(nType==4) {
			if(resultObj['#text']==null) resultObj['#text'] = '';
			resultObj['#text'] += node.nodeValue;
		}
	}

	// If ONLY a '#text' node is present in the result, then we can assume that
	// it's a text-node, so can collapse the object into a scalar value
	if(resultObj['#text']!=null) {
		var scalar = resultObj['#text'];
		delete(resultObj['#text']);
		var count = 0;
		for(var i in resultObj) count++;
		if(count==0) resultObj = scalar;
	}
	else if(xml.childNodes.length==0 && xml.nodeValue==null && xml.attributes.length==0) {
		resultObj = '';
	}

	// Result
	return resultObj;
}
	

//-------------------------------
// XMLHttpRequest getXMLHttpRequest()
//--
// Generates a XMLHttpRequest object and returns it.
//-------------------------------
function getXMLHttpRequest() {
	var req = false;
	if(window.XMLHttpRequest) {
		try {
			req = new XMLHttpRequest();
		}
		catch(e) {
			req = false;
		}
	}
	else if(window.ActiveXObject) {
	       	try {
			req = new ActiveXObject("Msxml2.XMLHTTP");
	      	}
		catch(e) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
	        	}
			catch(e) {
				req = false;
			}
		}
	}
	return req;
}
