//////////////////////////////////////////////
// Generic function script
// This file contains some generic functions
// used throughout the site.
// Also defines some constants used throughout
// the site also
// Ali Russell 2004
//
//////////////////////////////////////////////


//browser sniffer
var browserDetails=new Array(4);
var osDetails=new Array(2);
browserDetails=getBrowser();
osDetails=getOS();


//////////////////////
//END ENUMERATIONS
//////////////////////


//Extra encode function, that replaces some characters not replaced by escape();
function URLEncode(sStr) {
    return escape(sStr).replace(/\+/g, '%2B').replace(/\"/g,'%22').replace(/\'/g, '%27').replace(/\//g,'%2F');
  }
  
//Decode a string encoded with a bove method.
function URLDecode(sStr) {
    return unescape(sStr).replace('%2B', '+').replace('%22', '"').replace('%27', '\'').replace('%2F','/');
  }  

//Get window height, browser independent
function getWindowHeight() {
	if (window.self && self.innerHeight) 
	{
		return self.innerHeight;
	}
	if (document.documentElement && document.documentElement.clientHeight) 
	{
		return document.documentElement.clientHeight;
	}
	return 0;
}

//Get window width, browser independent
function getWindowWidth() {
	if (window.self && self.innerWidth) 
	{
		return self.innerWidth;
	}
	if (document.documentElement && document.documentElement.clientWidth) 
	{
		return document.documentElement.clientWidth;
	}
	return 0;
}



//function to find the x position in pixels of any object on the page.
function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += (obj.offsetLeft + obj.scrollLeft);
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

//function to find the y position in pixels of any object on the page.
function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{	
			curtop += (obj.offsetTop - obj.scrollTop);
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}



//function to return if true if a number is even, false if odd
function isEven(x) { return (x%2)?false:true; }

//Is a node a parent of another node.
function isParentOf(p, o, notSelf)
{
	if(notSelf && o == p) return false;
	while(o)
		if(o != p)	o = o.parentNode;
		else		return true;
	return false;
}


// Function to sleep for a number of milliseconds.
// This is mainly used for debugging.
function Sleep(intNumMS)
{
 // Checks for a valid number
 if(!isNaN(intNumMS))
 {
  // Uses JS built-in date object
  var datNow = new Date();
  var intNumMSNow = datNow.getTime();
  var intNumMSThen = (intNumMSNow + intNumMS);
  var i=0;

  // Does something useless until the time is right
  while(new Date().getTime() <= intNumMSThen)
  {i++;}
 } return;
}


//Method to set a cookie with the passed values on the client
//computer.
function setCookie(name, value, nDays, path, domain, secure) {
	var expires=new Date();
	expires.setDate(expires.getDate()+nDays);

	
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}


//Method to get a cookie with the passed name.
function getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}


//Method to blend an RGB colour with white based on
//an alpha value.  This simulates alpha transparency
//without having to use the new CSS styles, which
//make a whole object and its childeren transparent.
//Method written by A.Russell (11/04)
function alphaColour(r, g, b, a) {

	if (a>1) {
		return new Array(r, g, b);
	}

	var newR = Math.round((255 * (1-a)) + (r * a));
	var newG = Math.round((255 * (1-a)) + (g * a));
	var newB = Math.round((255 * (1-a)) + (b * a));

	return new Array(newR, newG, newB);

}

//NOT SURE WHAT THIS FUNCTION IS FOR, ~THINK ITS SAME AS Obj2Str essentially, for debugging
function dbg(o,delim, recurse){ 
	delim = delim || "\n";
	recurse = recurse || false;
	var t='';
	var ot;
	for(x in o){
		try{
			ox = (recurse) ? ((typeof(o[x])=='object') ? "{ "+dbg(o[x])+"}" : o[x]) : o[x];
			if(typeof(ox) != 'function')
				t+= x+"="+ox+delim;
			else
				t+= "["+x+"]"+delim;
		}catch(e){}
	}
	
	return t;
}

//Get a CSS rule from a stylesheet
function findCSSRule(id, returnIndex) {

	id = id.toLowerCase();
	// TODO: handle multiple stylesheets
	if(!this.rules)
	{
		this.rules = [];
		if(document.styleSheets[0].cssRules)
			for(var i = 0; i < document.styleSheets.length; i++)
				this.rules.push(document.styleSheets[i].cssRules);
		else
			for(var i = 0; i < document.styleSheets.length; i++)
				this.rules.push(document.styleSheets[i].rules);
	}
			
	if(!this.cache)
		this.cache = {};
	else if(this.cache[id])
		return returnIndex ? this.cache[id] : this.rules[this.cache[id][0]][this.cache[id][1]];
	
	
	for(var i = 0; i < this.rules.length; i++) {
		for(var j = 0; j < this.rules[i].length; j++) {
			if(this.rules[i][j].selectorText.toLowerCase().indexOf(id) != -1) {
				this.cache[id] = [i,j];
				return returnIndex ? [i,j] : this.rules[i][j];
			}
		}
	}
	
	return returnIndex ? -1 : null;
}

//Binary Search function
function binSearch(x, array)
{
	var low = 0;
	var high = array.length - 1;
	var mid;
	
	while (low <= high) {
		mid = Math.floor((low + high)/2);
		
		if (x < array[mid])			high = mid - 1;
		else if (x > array[mid])	low = mid + 1;
		else						return mid;
	}
	return -1;
}

//Fuzzy binary search
function binFuzzyCallSearch(x, array, lessThan)
{
	if(!lessThan) return -1;
	
	var low = 0;
	var high = array.length - 1;
	var mid;
	while (low <= high) {
		mid = Math.floor((low + high)/2);
		
		if(lessThan(x,array[mid]))			high = mid - 1;
		else if (lessThan(array[mid], x))	low = mid + 1;
		else								return mid;
	}
	return mid;
}

//Get a specific style property
function getStyle(x,styleProp)
{
	if (x.currentStyle)
		var y = x.currentStyle[styleProp];
	else if (document.defaultView.getComputedStyle)
	{
		try{
			var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
		}catch(e){
			//Fixes a problem with Safari
		}
	}
	return y;
}

//Same as isEven... why is there 2 of these?
function isOdd(num)
{
	var lowNum = Math.floor(num/2);
	var highNum = Math.ceil(num/2);
	return ((highNum-lowNum) == 1);
}

//converts an object/array into a JSON string representation
function Ob2Str(object)
{
	if (!object)
		return "";
	var isArray = false;
	if (typeof(object.length)=="number")
		isArray=true;
		
	var returnStr = "";
	
	if (isArray)
	{
		returnStr += "[";
	}
	else
	{
		returnStr += "{";
	}
	
	var firstItem = true;
		
	for (x in object)
	{
		
		
		if (typeof(object[x])=="object")
		{
			if (!firstItem)
			{
				returnStr += ",";
			}			
			if (!isArray)
			{
				returnStr += x + ": ";
			}			
			firstItem = false;
			returnStr += Ob2Str(object[x]);
		}
		else if ((typeof(object[x].length)=="number") && (typeof(object[x])!="string") && (typeof(object[x])!="function"))
		{
			if (!firstItem)
			{
				returnStr += ",";
			}		
			if (!isArray)
			{
				returnStr += x + ": ";
			}				
			firstItem = false;
			returnStr += Ob2Str(object[x]);
		}
		else if (typeof(object[x])!="function")
		{
			if (!firstItem)
			{
				returnStr += ",";
			}			
			if (!isArray)
			{
				returnStr += x + ": ";
			}				
			firstItem = false;
			returnStr += "'" + object[x].replace(/\'/g, '&acute;') + "'";			
		}
		
		
	}
	
	if (returnStr[returnStr.length-1]==",")
	{
		returnStr = returnStr.substring(0,returnStr.length-1);
	}
	
	if (isArray)
	{
		returnStr += "]";
	}
	else
	{
		returnStr += "}";
	}	
	
	return returnStr;
}


/*
 * DATE FUNCTIONALITY
 * May be depricated!
 */
window.mSpaceShortMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
window.mSpaceLongMonthNames = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

function DatesIntersect(date1Start, date1End, date2Start, date2End)
{
	
	if ((date1Start>date2Start) && (date1Start<date2End))
	{
		return true;
	}
	else if ((date1End>date2Start) && (date1End<date2End))
	{
		return true;
	}
	else if ((date2Start>date1Start) && (date2Start<date1End))
	{
		return true;
	}	
	else if ((date2End>date1Start) && (date2End<date1End))
	{
		return true;
	}	
	
	return false;
}

//Duplicate an array into a new object.
function CloneArray(array)
{
	var newarr = new Array();
	for (var i=0;i<array.length;i++)
	{
		newarr.push(array[i]);
	}
	return newarr;
}

//function to return 0 if number is less
//than 0, as ie throws a fit when applying
//styles with a negative number
function IEINT(i)
{
	if (isNaN(i) || (i<0))
		return 0;
	return i;
}
