/**
 *	Utils
 *	-------------------------
 *	(c) Lost Boys - http://www.lostboys.nl
 */

// IE Anti-background flicker
/*@cc_on
try { document.execCommand('BackgroundImageCache', false, true); } catch (e) {}
@*/

/**
 *	Class extender
 *	-------------------------
 *	NewClass = Class.extend(Base[, constructor[, prototype]]);
 *	Class.implement(NewClass, prototype);
 */

var Class = {
	extend:function(Base, constructor, prototype) {
		var Extended = function() {
			Base.apply(this, arguments);
			if(constructor) constructor.apply(this, arguments);
		}

		this.implement(Extended, Base.prototype);
		if(prototype) this.implement(Extended, prototype);
		Extended.prototype.constructor = Extended;
		return Extended;
	},

	implement:function(Class, protoface) {
		for(var i in protoface) {
			Class.prototype[i] = protoface[i];
		}
	}
}
	var AbstractFunction = function() {
		throw Error('Abstract function not implemented');
	}

/**
 *	ClassName
 *	--------------------------
 *	provides node.className functionality
 */

var ClassName = {
	add:function(node, name) {
		if(!this.contains(node, name))
			node.className += node.className? (' ' + name) : name;
	},

	remove:function(node, name) {
		if(node.className)
			node.className = node.className.replace(new RegExp('(^|\\s)'+name+'(\\s|$)','g'), ' ');
	},

	contains:function(node, name) {
		return new RegExp('(^|\\s)'+name+'(\\s|$)').test(node.className);
	},

	swap:function(node, old, name) {
		node.className = this.contains(node, old)?
			node.className.replace(new RegExp('(^|\\s)'+old+'(\\s|$)','g'), '$1'+name+'$2') :
			node.className.replace(new RegExp('(^|\\s)'+name+'(\\s|$)','g'), '$1'+old+'$2');
	},

	replace:function(node, old, name) {
		if(this.contains(node, old)) {
			this.remove(node, old);
			this.add(node, name);
		}
	},

	toggle:function(node, name) {
		if(!this.contains(node, name)) {
			this.add(node, name);
		} else {
			this.remove(node, name);
		}
	}
}

/**
 *	DomContent Load handler
 *	--------------------------
 *	calls functions when DOM is loaded, before window.onload
 *	DOMContent.addListener(functionPointer)
 */

var DOMContent = {
	init:function() {
		this.handlers = [];
		if(document.addEventListener)
			document.addEventListener('DOMContentLoaded', function(){ DOMContent.handleOnload();}, false);
		
		/*@cc_on document.write('<script defer src="//:" onreadystatechange="if(this.readyState==\'complete\') DOMContent.handleOnload();"><\/script>'); @*/
		var safari = /WebKit|Khtml/i.test(navigator.userAgent);
		var o = window.opera, opera8 = (o && parseInt(o.version()) < 9);
		if(safari || opera8) this.pollState();
	},

	pollState:function() {
		if(/loaded|complete/.test(document.readyState)) DOMContent.handleOnload();
		else setTimeout(arguments.callee, 50);
	},

	handleOnload:function() {
		for(var f,i=0; f=this.handlers[i]; i++)
			try { if(!f.executed){ f.executed = true; f(); }} catch (e){}
	},

	addListener:function(handler) {
		this.add(handler); // deprecated
	},

	onload:function(handler) {
		if(!this.handlers) this.init();
		this.handlers[this.handlers.length] = handler;
	}
}

/**
 *	Various utils
 *	--------------------------
 */

var Utils = {
	select:function(selector) { 
		return cssQuery(selector); 
	},

	getParent:function(startNode, parentType) {
		var node = startNode.parentNode;
		var nodeReg = new RegExp('^'+parentType+'$', 'i');
		while(node) {
			if(nodeReg.test(node.nodeName)) return node;
			node = node.parentNode;
		}	return null;
	},

	calculateLeft:function(node, target) {
		var left = 0;
		while(node && (!target || node != target)) {
			left += node.offsetLeft;
			node = node.offsetParent;
		}	return left;
	},

	calculateTop:function(node, target) {
		var top = 0;
		while(node && (!target || node != target)) {
			top += node.offsetTop;
			node = node.offsetParent;
		}	return top;
	},

	setCookie:function(name, value, expires) {
		var date = new Date();
		date.setTime(date.getTime() + (this.expires*24*3600*1000));
		document.cookie = name + "=" + escape(value) + (expires? "; expires=" + date : "");
	},

	getCookie:function(name) {
		try {
			var reg = new RegExp(name + '=([^;$]+)','i');
			return reg.exec(document.cookie)[1];
		} catch (e) {
			return null;
		}
	},

	padString:function(i,l,s) {
		return (i.length<l)?new RegExp('.{'+l+'}$').exec((1<<l).toString(2).replace(/0/g,s||0)+i)[0]:i;
	},

	RGBToHex:function(r,g,b) {
		return (r<16?'#0':'#')+((r<<16)+(g<<8)+b).toString(16);
	}
}

/**
 *	Array extentions
 *	--------------------------
 */

Array.prototype.parseNodes = function(nodeList) {
	for(var i=0; i<nodeList.length; i++) {
		this.push(nodeList[i]);
	}	
	return this;
}

if(!Array.prototype.forEach) {
	Array.prototype.forEach = function(handler, scope) {
		var l = this.length;
		for(var i=0; i<l; i++) {
			handler.call(scope || window, this[i], i, this);
		}
	}
}

if(!Array.prototype.filter) {
	Array.prototype.filter = function(handler, scope) {
		var value, result = [], l = this.length;
		for(var i=0; i<l; i++) {
			value = this[i];
			if(handler.call(scope || window, value, i, this)) {
				result.push(value);
			}
		}
		return result;
	}
}