function getElement (elId) {
	if (typeof elId != "string") return elId;
	return	document.all ? document.all[elId] :
			document.getElementById ? document.getElementById(elId) :
			null;
}
var $ = getElement;

/**
*	getElementsByTag
*	gets all the elements with the given tag name, within the specified element.
*	the second parameter is optional. leave it blank to get all tags.
*	ie: getElementsByTag("div", myElement) returns an array of all the <div>s within the myElement element.
*		getElementsByTag("div")			   returns an array of all the <div>s within the whole document.
*/
function getElementsByTag(tag, el) {
	if (el == undefined) el = document;
	return document.all ? el.all.tags(tag) :
		   document.getElementsByTagName ? el.getElementsByTagName(tag) :
		   null;
}
var $$ = getElementsByTag;

function getElementsByTagAndClass(tag, clsName, el) {
	var tags = $$(tag, el);
	var ret = [];
	for (var i = 0; i < tags.length; i++) {
		var classes = tags[i].className.split(/\s+/);
		if (indexOf(clsName, classes) != -1) {
			ret.push(tags[i]);
		}
	}
	return ret;
}
var $$$ = getElementsByTagAndClass;

/**
*	hide()
*	Hides a HTML element
*		- pass it an element to hide, or the string identifier of an element
*	eg: <div id="myElement">..</div>
*		hide("myElement");
*
*/
function hide (el) {
	$(el).style.display = "none";
}
/**
*	see hide()
*/
function show (el) {
	$(el).style.display = "";
}

function setVis(what, showHide) {
	if (showHide)	show(what);
	else 			hide(what);
}
function toggleVis(el) {
	el = $(el);
	if (el.style.display == "none") {
		show(el);
		return true;			// we just showed one
	} else {
		hide(el);
		return false;			// we just hid one
	}
}

function showElementCentred(el) {

	el = getElement(el);
	el.style.visibility = "hidden";	// so we can get an accurate reading of its width/height
	show(el);

	var winSize = getWindowSize();
	var scrollOffset = getScrollXY();
	el.style.position = 'absolute';
	el.style.left = ((winSize.w - el.offsetWidth) / 2 + scrollOffset.x) + "px";
	el.style.top = ((winSize.h - el.offsetHeight) / 2 + scrollOffset.y) + "px";

	el.style.visibility = '';
}

/**
*	stolen from http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
*/
function getScrollXY() {
	var scrOfX = 0, scrOfY = 0;
	if (typeof(window.pageYOffset) == 'number') {
		//Netscape compliant
		scrOfY = window.pageYOffset;
		scrOfX = window.pageXOffset;
	} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
		//DOM compliant
		scrOfY = document.body.scrollTop;
		scrOfX = document.body.scrollLeft;
	} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
		//IE6 standards compliant mode
		scrOfY = document.documentElement.scrollTop;
		scrOfX = document.documentElement.scrollLeft;
	}
	return { 'x' : scrOfX, 'y' : scrOfY };
}

/**
*	stolen from http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
*/
function getWindowSize() {
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return {'w' : myWidth, 'h' : myHeight};
}
//
//	pass it a HTML element and it returns an object with 2 properties, x and y, which represent the x and y position of the element.
//
function getPos(el) {
	// yay readability
	for (var lx=0, ly=0;
	     el != null;
		 lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);
	return {x: lx,y: ly};
}

/**
 *	Convert a number into a hex string formatted ready for use in CSS
 *	toHexString(255) 		== "#0000ff"
 *  toHexString(1715004)	== "#1a2b3c"
 *	toHexString(0xff00ff)	== "#ff00ff"
 *
 *	Number can be in any base
 *	toHexString(8615) == toHexString(0x21A7) == toHexString(020647) == "#0021a7"
 *
 *	Forces numbers to be in the range 0x0 to 0xffffff
 *	toHexString(-1)			== "#000000"
 *	toHexString(16777216)	== "#ffffff"
 *
 *	@param	num		Number		A number
 *	@return			String		A hexadecimal representation of that number.
 */
function toHexString(num) {
	var hexString = Math.max(0, Math.min(0xffffff, num)).toString(16);
	while (hexString.length < 6) {
		hexString = "0" + hexString;
	}
	return "#" + hexString;
}

/**
 *	Converts a HTML hex string into a decimal
 *	fromHexString("#0000FF") == 255
 *	fromHexString("#1A2B3C") == 1715004
 *
 *	@param	hexString	String	A hexadecimal representation of a number, optionally prefixed with a #
 *	@return				Number	the decimal representation of that number
 */
function fromHexString(hexString) {
	while (hexString.length && (hexString[0] == "#" || hexString[0] == "0")) {
		hexString = hexString.substr(1);
	}
	return parseInt(hexString, 16);
}


///////////////////////
// COOKIES!
// http://www.quirksmode.org/js/cookies.html#script
function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}

function dump(obj) {

	var out = [];
	for (var i in obj) {
		out.push(i + ": " + obj[i]);
	}
	out.sort();
	var el = $('dumpZone');
	if (!el) {

		var d = document;
		var el = d.createElement('pre');
			el.id = 'dumpZone';
			el.style.position = 'absolute';
			el.style.right = '5px';
			el.style.top = '5px';
			el.style.float = 'right';
			el.style.fontSize = '10px';
			el.style.backgroundColor = 'white';
		d.body.appendChild(el);
	}
	el.innerHTML = 'DUMP\n==============<br /><br />'
				 + out.join("<br />");
}

/**
 *	Adds a classname to the token list, keeping it unique
 *	addClassName("abc", "") == "abc"
 *	addClassName("def", "abc") == "abc def"
 *	addClassName("ghi", "abc def") == "abc def ghi"
 *	addClassName("abc", "abc") = "abc"
 *	Some actual usage:
 *	el.className = addClassName("active", el.className);
 *
 *	@param		newClass	string	A token to add to the list
 *	@param		oldClass	string	A token list
 *	@return					string	A token list with newClass included at most once.
 *	@date		2007-07-31
 */
function addClassName(newClass, oldClass) {
	var tokens = oldClass.split(/\s+/);
	if (indexOf(newClass, tokens) == -1) {
		tokens.push(newClass);
	}
	return tokens.join(" ");
}

/**
 *	Ensures that a token isn't in a list, such as an individual class name.
 *	removeClassName("abc", "abc") = ""
 *	removeClassName("abc", "abc def") = "def"
 *	removeClassName("abc", "def") = "def"
 *
 *	@param		cls			string	The string to remove from the token list
 *	@param		oldClass	string	A token list, separated by spaces
 *	@return					string	The token list without cls
 *	@date		2007-07-31
 */
function removeClassName(cls, oldClass) {
	var tokens = oldClass.split(/\s+/);
	var i = indexOf(cls, tokens);
	if (i != -1) {
		tokens.splice(i, 1);
	}
	return tokens.join(" ");
}

/**
 *	Does the same thing as Array.indexOf()
 *	It's been rewritten because of guess who not having something as bloody
 *	simple and fundamental as an array search function built in?
 *
 *	@param		needle		mixed	The item you're searching for in the array
 *	@param		haystack	Array	The array to search through
 *	@return					int		The index of needle in haystack, or -1 if not found
 *	@date		2007-07-31
 */
function indexOf(needle, haystack) {
	for (var i = 0; i < haystack.length; i++) {
		if (haystack[i] == needle) {
			return i;
		}
	}
	return -1;
}

/**
 *	A function to emulate PHP's intval
 *	Returns the integer value of a string. Returns 0 if it can't convert to a number
 *	@param	numStr		mixed		A representation of a number
 *	@return				int			The integer value of the passed value, or 0.
 *	@date	2007-08-10
 */
function intval(numStr) {
	var ret = parseInt(numStr);
	if (isNaN(ret)) ret = 0;
	return ret;
}

/**
 *	A function to emulate PHP's floatval
 *	Returns the integer value of a string. Returns 0 if it can't convert to a number
 *	@param	numStr		mixed		A representation of a number
 *	@return				float		The float value of the passed value, or 0.0
 *	@date	2007-08-10
 */
function floatval(numStr) {
	var ret = parseFloat(numStr);
	if (isNaN(ret)) ret = 0.0;
	return ret;
}

function getRadioValue(el) {
	for (var i = 0; i < el.length; i++) {
		if (el[i].checked) {
			return el[i].value;
		}
	}
	return; // result will be undefined
}
function getCheckValue(el) {
	var vals = [];
	for (var i = 0; i < el.length; i++) {
		if (el[i].checked) {
			vals.push(el[i].value);
		}
	}
	return vals;
}