/////////////////////////////////////////////////
/// library of common, DOM enhancing methods ///
///////////////////////////////////////////////

// getElementsByClass()
// @author Dustin Diaz
// fetches elements by their classname

function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

// toggle()
// @author Dustin Diaz
// toggles visibility of an object on and off

function toggle(obj) {
	var el = document.getElementById(obj);
	if ( el.style.display != 'none' ) {
		el.style.display = 'none';
	}
	else {
		el.style.display = '';
	}

}

// insertAfter()
// @author Jeremy Keith
// does exactly the opposite of insertBefore()

function insertAfter(parent, node, referenceNode) {
	parent.insertBefore(node, referenceNode.nextSibling);
}

// $()
// @author Dustin Diaz
// shortcut for getElementById(), with the additional functionality of selecting multiple elements

function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);
		if (arguments.length == 1)
			return element;
		elements.push(element);
	}
	return elements;
}

// addClass()
// @author James Edwards and Cameron Adams
// adds class to an element

function addClass (target, classValue) {
	var pattern = new RegExp("(^| )" + classValue + "( |$)");
	
	if (!pattern.test(target.className)) {
		if (target.className == "") {
			target.className = classValue;
		} else {
			target.className += " " + classValue;
		}
	}
	
	return true;
}

// removeClass()
// @author James Edwards and Cameron Adams
// removes class from an element

function removeClass (target, classValue) {
	var removedClass = target.className;
	var pattern = new RegExp("(^| )" + classValue + "( |$)");
	
	removedClass = removedClass.replace(pattern, "$1");
	removedClass = removedClass.replace(/ $/,"");
	
	target.className = removedClass;
	
	return true;
}

// style ()
// @author Harmen Janssen
// gets the computed style for the current element in a cross-browser fashion

function style (el, prop) {
	var s = null;
	if (typeof el.currentStyle != 'undefined') {
		s = el.currentStyle;
	} else {
		s = document.defaultView.getComputedStyle (el, null);
	}
	
	return s[prop];
}

///////////////////////////////
/// event handling methods ///
/////////////////////////////

// addEvent()
// @author Scott Andrew
// cross-browser event handling for IE5+, NS6+ and Mozilla/Gecko

function addEvent(obj, evType, fn, useCapture){
	if(obj.addEventListener){
		obj.addEventListener(evType, fn, useCapture);
		return true;
	}else if(obj.attachEvent){
		var r = obj.attachEvent('on' + evType, fn);
		return r;
	}else{
		obj['on' +  evType] = fn;
	}
}

// getEventTarget()
// @author Peter-Paul Koch
// returns the element which caused this function to be called

function getEventTarget(e) {
	var targ;
	if (!e) {
		e = window.event;
	}
	if (e.target) {
		targ = e.target;
	} else if (e.srcElement) {
		targ = e.srcElement;
	}
	if (targ.nodeType == 3) { // defeat Safari bug
		targ = targ.parentNode;
	}

	return targ;
}

/////////////////////////////////////////////////
/// 	methods enhancing the Array object	 ///
///////////////////////////////////////////////

// Array.push(), Array.splice()
// @author James Edwards and Cameron Adams
// equivalent of the native push() and splice() methods, rewritten for support in IE 5.0

Array.prototype.push = function () {
	for (var i = 0; i < arguments.length; i++) {
		this[this.length] = arguments[i];
	}
	return arguments[i - 1];
};

Array.prototype.splice = function (a,b) {
	var tmp = [];
	for (var i = a + b; i < this.length; i++) {
		tmp[tmp.length] = this[i];
	}
	
	var rem = [];
	for (i = a; i < a + b; i++) {
		rem[rem.length] = this[i];
	}
	
	this.length = a;
	
	for (i = 2; i < arguments.length; i++) {
		this[this.length] = arguments[i];
	}
	
	for (i = 0; i < tmp.length; i++) {
		this[this.length] = tmp[i];
	}
	
	return rem;
}

// Array.inArray()
// @author EmbiMEDIA
// Javascript equivalent of the common PHP method

Array.prototype.inArray = function (value) {
	var i;
	for (i=0; i < this.length; i++) {
		if (this[i] === value) {
			return true;
		}
	}
	return false;
};

////////////////////////////////////////////////////////////
/// often used regular expressions made into functions	///
//////////////////////////////////////////////////////////

// @author Harmen Janssen

// isNumeric()
// checks if string contains only digits

function isNumeric (s) {
	var p = /^-?\d+(\.\d+)?$/;
	return p.test(s);
}

// isAlpha()
// checks if string contains only alphabetical characters ( or an empty space )

function isAlpha (s) {
	var p = /^[a-zA-Z ]+$/;
	return p.test(s);
}

// isMail()
// checks if string is an email address

function isMail (s) {
	var p = /^[\w\.\-]+@([\w\-]+\.)+[a-zA-Z]+$/;
	return p.test(s);
}

// isZip()
// checks if string is a Dutch zip code

function isZip (s) {
	var p = /^[0-9]{4}[ ]?[a-zA-Z]{2}$/;
	return p.test(s);
}

// isEmpty()
// checks if string is empty ( ignoring extra whitespace like tabs or spaces )

function isEmpty (s) {
	var p = /^\s$/;
	return p.test(s) || s == '';
}

////////////////////////////////////////
/// various mathematical functions	///
//////////////////////////////////////

// @author James Edwards and Cameron Adams

// round a number to x decimal places
function roundTo (base, precision) {
	var m = Math.pow(10, precision);
	var a = Math.round(base * m) / m;
	return a;
}

// give a random integer between min and max
function randomBetween (min, max) {
	return min + Math.floor(Math.random() * (max - min + 1));
}

// round a number to x decimal places and convert to string
// useful for converting currencies 
// [makes use of roundTo()]
function formatTo (base, precision) {
	var a = roundTo(base, precision);
	var s = a.toString();
	
	var decimalIndex = s.indexOf(".");
	if (precision > 0 && decimalIndex < 0) {
		decimalIndex = s.length;
		s += ".";
	}
	while (decimalIndex + precision + 1 > s.length) {
		s += "0";
	}
	return s;
}

// find the appropriate ordinal for a given number
// used with English ordinals
function getOrdinal (n) {
	var ord = 'th';
	
	if (n % 10 == 1 && n % 100 != 11) {
		ord = 'st';
	} else if (n % 10 == 2 && n % 100 != 12) {
		ord = 'nd';
	} else if (n % 10 == 3 && n % 100 != 13) {
		ord = 'rd';
	}
	
	return ord;
}

////////////////////////////////////////
/// various String functions		///
//////////////////////////////////////

// @author liorean

// trim whitespace of both the right and left sides of a string
String.prototype.trim = function () {
    return this.replace(/^\s*|\s*$/g,'');
}

// trim whitespace of the left side of a string
String.prototype.ltrim = function () {
    return this.replace(/^\s*/g,'');
}

// trim whitespace of the right side of a string
String.prototype.rtrim = function () {
    return this.replace(/\s*$/g,'');
}