
if (!document.getElementsByClassName) {
	document.getElementsByClassName = function( cls) {
		var ret = [];
		var elem = this.getElementsByTagName("*");
		var len = elem.length
		for (var i = 0; (i < len); ++i) {
			if (elem[i].className.match( new RegExp("\\b" + cls + "\\b") )) {
				ret.push(elem[i]);
			}
		}
		return ret;
	};
}

function $()
{
	var
		ret = [],
		len = arguments.length;
	for (var i = 0; (i < len); i++) {
		var element = arguments[i];
		if (typeof element === "string") {
			element = document.getElementById(element);
		}
		if (arguments.length === 1) {
			return element;
		}
		ret.push(element);
	}
	return ret;
}

function $c(cls)
{
	return document.getElementsByClassName( cls );
}

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

if (!document.getElementsByTagAndClassName) {
	document.getElementsByTagAndClassName = function(tagName, className) {
		tagName = (tagName || "*");
		var children = document.getElementsByTagName(tagName) || document.all;
		if (className === null) {
			return children;
		}
		var
			ret = [],
			len = children.length;
		for (var i = 0; (i < len); ++i) {
			var
				child = children[i],
				classNames = child.className.split(" "),
				zen = classNames.length;
			for (var j = 0; (j < zen); ++j) {
				if (classNames[j] === className) {
					ret.push(child);
					break;
				}
			}
		}

		return ret;
	};
}

function extend(subClass, superClass)
{
	var func = function() {};
	func.prototype = superClass.prototype;
	subClass.prototype = new func();
	subClass.prototype.constructor = subClass;
}

String.prototype.trim = function() {
	return this.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
};

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

Array.prototype.unique = function() {
	var
		distinct = [],
		maximum = (this.length - 1);
	for (var i = 0, k = 0; (i <= maximum); i++) {
		var len = distinct.length
		// j should increment all the way up to l
		for (var j = 0; (this[i] !== distinct[j]) && (j < len); j++ );
		// if it hasn't, this one's a duplicate
		if (j === len) {
			distinct[k++] = this[i];
		}
	}
	return distinct;
};

Array.prototype.last = function() {
	return this[this.length - 1];
};

function in_array(needle, haystack, strict)
{
	for (var key in haystack) {
		if ((!strict && haystack[key] == needle) || (!!strict && haystack[key] === needle)) {
			return true;
		}
	}
	return false;
}

function array_key_exists(needle, haystack, strict)
{
	for (var key in haystack) {
		if ((!strict && key == needle) || (!!strict && key === needle)) {
			return true;
		}
	}
	return false;
}

function hideSelectOptions( className, exceptions)
{
	var
		selects = document.getElementsByClassName(className),
		exceptions = exceptions || [],
		len = selects.length;
	for (var i = 0; (i < len); ++i) {
		var
			options = selects[i].getElementsByTagName("option"),
			zen = options.length;
		for (var j = 0; (j < zen); ++ j) {
			with (options[j]) {
				if (!value) { // ignore header options
					continue;
				}
				className = "hidden";
				if (in_array( getAttribute("table_name"), exceptions, true )) {
					className = null;
				}
			}
		}
	}
}

if (!window.addClassName) {
	addClassName = function(el, cls) {
		if (hasClassName(el, cls )) {
			return;
		}
		if (el.className === "") {
			el.className = cls;
		} else {
			el.className += (" " + cls);
		}
	};
}

if (!window.removeClassName) {
	removeClassName = function(el, cls) {
		if (!hasClassName(el, cls)) {
			return;
		}
		var
			classNames = el.className.split(" "),
			len = classNames.length;
		for (var i = 0; (i < len); ++i) {
			if (classNames[i] === "" || classNames[i] === cls || classNames[i].match( new RegExp("\\b" + cls + "\\b") )) {
				delete classNames[i];
			}
		}
		el.className = classNames.join(" ");
	};
}

if (!window.hasClassName) {
	hasClassName = function(el, cls) {
		return el.className.match( new RegExp("\\b" + cls + "\\b") );
	};
}

if (!window.toggleClassName) {
	toggleClassName = function(el, cls) {
		if (hasClassName(el, cls)) {
			removeClassName(el, cls);
		} else {
			addClassName(el, cls);
		}
	};
}

function XBrowserAddEvent(target, event, handler){
	if (target.addEventListener) {
		target.addEventListener(event, handler, false);
	} else if (target.attachEvent) {
		target.attachEvent("on" + event, handler);
	} else {
		target["on" + event] = handler;
	}
}

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != "function") {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		};
	}
}

function setOpacity( el, op)
{
	if (op === 100) { /* IE support */
		with (el.style) {
			opacity = "";
			MozOpacity = "";
			filter = "";
		}
	} else {
		with (el.style) {
			opacity = (op / 100);
			MozOpacity = (op / 100);
			filter = "alpha(opacity=" + op + ")";
		}
	}
}

function fadeElement( el, out, phase, increments)
{
	var speed = (phase / increments) * 1000;
	var timer = 0;
	if (!!out) {
		for (var i = 99; (i >= 0); --i) {
			setTimeout( 'setOpacity( $("' + el.id + '"), ' + i + ')', (timer * speed) );
			++timer;
		}
		setTimeout( '$("' + el.id + '").style.display = "none"', (timer * speed) );
	} else {
		if (el.style.display === "none") {
			el.style.display = "";
		}
		for (var i = 0; (i <= 100); ++i) {
			setTimeout( 'setOpacity( $("' + el.id + '"), ' + i + ')', (timer * speed) );
			++timer;
		}
	}
}

function ElementDimensions(elem)
{
	if (!elem) {
		return {};
	}

	if (elem.clientWidth == 0 || elem.clientHeight == 0) {
		var
			old_display = elem.style.display,
			old_visibility = elem.style.visibility;
		with (elem.style) {
			visibility = "hidden";
			display = "block";
		}
	}
	
	this.inner = { // content and padding; gives 0 for inline elements (you can use scrollWidth/Height if it's inline)
		width: elem.clientWidth,
		height: elem.clientHeight
	};
	this.outer = { // everything (content, padding, scrollbar, border)
		width: elem.offsetWidth,
		height: elem.offsetHeight
	};
	this.scroll = { // width & height of entire content field (including padding), visible or not
		// incorrect in Opera; it doesn't include the padding
		width: elem.scrollWidth,
		// if there are no scrollbars, IE gives the actual height of the content instead of the height of the element
		height: (elem.scrollHeight < elem.clientHeight)? elem.clientHeight : elem.scrollHeight,
		//scroll position of content & padding
		left: elem.scrollLeft,
		top: elem.scrollTop
	};
	
	if (typeof old_display === "string" && typeof old_visibility === "string") {
		with (elem.style) {
			display = old_display;
			visibility = old_visibility;
		}
	}

	//position of element from the top-left corner of the document
	var temp = elem;
	this.left = this.top = 0;
	while (temp.offsetParent) {
		this.left += temp.offsetLeft;
		this.top += temp.offsetTop;
		temp = temp.offsetParent;
	}
}

function fireClick(el)
{
	if (!el) {
		return false;
	}
	if (document.all) {
		el.click();
	} else {
		var e = document.createEvent("MouseEvents");
		e.initMouseEvent("click", true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
		el.dispatchEvent(e);
	}
}
