// basic common functions involving js constructs and DOM

/*
 * addDOMLoadEvent by Jesse Skinner
 * See http://www.thefutureoftheweb.com/blog/adddomloadevent
 */

function addDOMLoadEvent(func) {
	if (!window.__load_events) {
		var init = function () {
			// quit if this function has already been called
			if (arguments.callee.done) return;
			
			// flag this function so we don't do the same thing twice
			arguments.callee.done = true;
			
			// kill the timer
			if (window.__load_timer) {
				clearInterval(window.__load_timer);
				window.__load_timer = null;
			}
			
			// execute each function in the stack in the order they were added
			for (var i=0;i < window.__load_events.length;i++) {
				window.__load_events[i]();
			}
			window.__load_events = null;
		};
		
		// for Mozilla/Opera9
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", init, false);
		}
		
		// for Internet Explorer
		/*@cc_on @*/
		/*@if (@_win32)
		
		document.write("<scr"+"ipt id=__ie_onload defer src=//0><\/scr"+"ipt>");
		var script = document.getElementById("__ie_onload");
		script.onreadystatechange = function() {
			if (this.readyState == "complete") {
				init(); // call the onload handler
			}
		};
		
		/*@end @*/
		
		// for Safari
		if (/WebKit/i.test(navigator.userAgent)) { // sniff
			window.__load_timer = setInterval(function() {
				if (/loaded|complete/.test(document.readyState)) {
					init(); // call the onload handler
				}
			}, 10);
		}
		
		// for other browsers
		window.onload = init;
		
		// create event function stack
		window.__load_events = [];
	}
	
	// add function to event stack
	window.__load_events.push(func);
}


function addEvent(elm, evType, fn, useCapture) {
	if (elm.addEventListener) {
		elm.addEventListener(evType, fn, useCapture);
		return true;
	}
	else if (elm.attachEvent) {
		var r = elm.attachEvent('on' + evType, fn);
		return r;
	}
	else {
		elm['on' + evType] = fn;
	}
}

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	}
	else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function addUnloadEvent(func) {
	var oldonunload = window.onunload;
	if (typeof window.onunload != 'function') {
		window.onunload = func;
	}
	else {
		window.onunload = function() {
			oldonunload();
			func();
		}
	}
}

function addMouseHandler(type, func, rootWnd) {
	var rootWindow = rootWnd || window;
	
	if (type != 'onmousedown' &&
	    type != 'onmousemove' &&
	    type != 'onmouseup')
	{
		return;
	}
	
	if (typeof document[type] != 'function') {
		rootWindow.document[type] = func;
	}
	else {
		var oldhandler = document[type];
		rootWindow.document[type] = function() {
			oldhandler(e);
			func(e);
		}
	}
}

function swapMouseHandler(type, func, rootWnd) {
	var rootWindow = rootWnd || window;
	
	if (type != 'onmousedown' &&
	    type != 'onmousemove' &&
	    type != 'onmouseup')
	{
		return;
	}
	
	var oldhandler = document[type];
	rootWindow.document[type] = func;
	return oldhandler;
}

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;
}

function getElementByName(childName, parent, tag)
{
	tag = tag || '*';
	var elems = parent.getElementsByTagName(tag);
	for ( var cls, i = 0; i < elems.length; i++ )
	{
		var elem = elems[i];
		if ( elem.getAttribute('name') == childName )
		{
			return elem;
		}
	}
}

function getElementsByName(childName, parent, tag)
{
	tag = tag || '*';
	var retval = [];
	var elems = parent.getElementsByTagName(tag);
	for ( var cls, i = 0; i < elems.length; i++ )
	{
		var elem = elems[i];
		if ( elem.getAttribute('name') == childName )
		{
			retval.push(elem);
		}
	}
	
	return retval;
}

function toggle(obj) {
	var el;
	if (typeof obj == 'string')
		el = document.getElementById(obj);
	else
		el = obj;
	if ( el.style.display != 'none' ) {
		el.style.display = 'none';
	}
	else {
		el.style.display = '';
	}
}


function insertAfter(parent, node, referenceNode) {
	parent.insertBefore(node, referenceNode.nextSibling);
}

// array operation
function array_search(needle, haystack) {
	if (!haystack)
	{
		return false;
	}
	
	for (var i = 0; i < haystack.length; i++)
	{
		if (haystack[i] == needle)
			return i;
	}
	return false;
}

// from quirksmode
function getCookie( 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 setCookie( name, value, expires, path, domain, secure ) {
	var today = new Date();
	today.setTime( today.getTime() );
	if ( expires ) {
		expires = expires * 1000 * 60 * 60 * 24;
	}
	var expires_date = new Date( today.getTime() + (expires) );
	document.cookie = name+'='+escape( value ) +
		( ( expires ) ? ';expires='+expires_date.toGMTString() : '' ) +
		( ( path ) ? ';path=' + path : '' ) +
		( ( domain ) ? ';domain=' + domain : '' ) +
		( ( secure ) ? ';secure' : '' );
}

function deleteCookie( name, path, domain ) {
	if ( getCookie( name ) ) document.cookie = name + '=' +
			( ( path ) ? ';path=' + path : '') +
			( ( domain ) ? ';domain=' + domain : '' ) +
			';expires=Thu, 01-Jan-1970 00:00:01 GMT';
}

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;
}

// element css class manipulation

function hasClass(ele,cls) {
	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
	if (hasClass(ele,cls)) {
    	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
		ele.className=ele.className.replace(reg,' ');
	}
}

// advanced common functions involving styling or positioning

// www.oreillynet.com/pub/a/javascript/excerpt/JSDHTMLCkbk_chap5/index5.html
// uses elem.currentStyle for IE, getComputedStyle for Standard
function getElementStyle(elem, IEStyleProp, CSSStyleProp) {
	if (elem.currentStyle) {
		return elem.currentStyle[IEStyleProp];
	} else if (document.defaultView && 
	           document.defaultView.getComputedStyle) {
		var compStyle = document.defaultView.getComputedStyle(elem, "");
		return compStyle.getPropertyValue(CSSStyleProp);
	}
	return "";
}

// http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
function getScrollPos() {
	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 [ scrOfX, scrOfY ];
}

function getElementPos(container) {
	var offsetX = 0;
	var offsetY = 0;
	if (container.getBoundingClientRect)
	{
		var rect = container.getBoundingClientRect();
		offsetX = rect.left;
		offsetY = rect.top;
		var z = getScrollPos();
		offsetX += z[0]
		offsetY += z[1];
	}
	else
	{
		var parentElem = container;
		while (parentElem && 
		       parentElem != document.body && 
		       parentElem != document.documentElement) {
			offsetX += parentElem.offsetLeft;
			offsetY += parentElem.offsetTop;
			parentElem = parentElem.offsetParent;
		}
	}
	return [offsetX, offsetY];
}

function getWindowDims(wnd) {
	wnd = wnd || window;
	return [ getWindowWidth(wnd), getWindowHeight(wnd) ];
}

function getWindowWidth(wnd) {
	wnd = wnd || window;
	
	if (wnd.innerWidth && wnd.innerWidth != 0)
		return wnd.innerWidth;
	if (wnd.document.documentElement.clientWidth && 
	    wnd.document.documentElement.clientWidth != 0)
		return wnd.document.documentElement.clientWidth;
	if (wnd.document.body.clientWidth && wnd.document.body.clientWidth != 0)
		return wnd.document.body.clientWidth;
	return 0;
}

function getWindowHeight(wnd) {
	wnd = wnd || window;
	
	if (wnd.innerHeight && wnd.innerHeight != 0)
		return wnd.innerHeight;
	if (wnd.document.documentElement.clientHeight && 
	    wnd.document.documentElement.clientHeight != 0)
		return wnd.document.documentElement.clientHeight;
	if (wnd.document.body.clientHeight && wnd.document.body.clientHeight != 0)
		return wnd.document.body.clientHeight;
	return 0;
}

function getElementDims(target) {
	return [ getElementWidth(target), getElementHeight(target) ];
}

function getElementHeight(target) {
	if (target.clientHeight) return target.clientHeight;
	else if (target.innerHeight) return target.innerHeight;
	else if (target.offsetHeight) return target.offsetHeight;
	else return 0;
}

function getElementWidth(target) {
	if (target.clientWidth) return target.clientWidth;
	else if (target.innerWidth) return target.innerWidth;
	else if (target.offsetWidth) return target.offsetWidth;
	else return 0;
}

