/* Fix ie6 background image caching
-------------------------------------------------------------------------*/
try {
  document.execCommand('BackgroundImageCache', false, true);
} catch(e) {}

/* Shortcut functions
-------------------------------------------------------------------------*/
function $id(id) {
	return document.getElementById(id);
}

function $class(name,parent,tag) {
	var se = [];
	var p = typeof(parent) != "undefined" ? parent : document;
	var t = typeof(tag) != "undefined" ? tag : "*";
	var elements = $tag(t,p);
	for (var i=elements.length-1;i>=0;i--) {
		if (Element.Class.Contains(elements[i],name)) {
			se.push(elements[i]);
		}
	}
	return se;
}

function $tag(name,parent) {
	return (typeof(parent) != "undefined") ? parent.getElementsByTagName(name) : document.getElementsByTagName(name);
}

function $parent(tag,obj) {
	if (obj.parentNode) {
		while(obj = obj.parentNode) {
			if (tag == obj.nodeName.toLowerCase()) {
				return obj;
			}
		}
	}
	return null;
}


/* Element related 
-------------------------------------------------------------------------*/
Element = {
	Remove:function(obj) {
		if(obj.parentNode) {			
			obj.parentNode.removeChild(obj);
		}
	},
	
	RemoveChildNodes:function(obj) {
		var cn = obj.childNodes;		
		for (var i=cn.length-1;i>=0;i--) {
			cn[i].parentNode.removeChild(cn[i]);
		}
	},
	
	Class:{
		Add:function(obj,name) {
			if (!Element.Class.Contains(obj,name)) {
				obj.className += " " + name; }
		},
		
		Contains:function(obj,name) {
			return (obj.className.indexOf(name)!=-1);
		},
		
		Remove:function(obj,name) {
			if (Element.Class.Contains(obj,name)) {
				obj.className = obj.className.replace(name,"");
			}
		}
	},
	
	// returns the position of the element
	GetPosition:function(obj) {
		var pos = {x:0,y:0};
		if (obj.offsetParent) {
			pos.x = obj.offsetLeft;
			pos.y = obj.offsetTop;
			while(obj = obj.offsetParent) {
				pos.x += obj.offsetLeft;
				pos.y += obj.offsetTop;
			}
		}
		return pos;
	}
}


/* Event related 
-------------------------------------------------------------------------*/
var $OBSERVERS = [];

Event = {
	// returns the correct event
	Get:function(e) {
		return e || window.event;
	},
	
	// stop the event propagation from event e
	Stop:function(e) {
		var e = Event.Get(e);
			e.cancelBubble = true;
		if (e.preventDefault) {e.preventDefault();}
		if (e.stopPropagation) {e.stopPropagation();}
	},
	
	// returns the element that fired the event e
	GetElement:function(e) {
		var e = Event.Get(e);
		var obj = !e.target ? e.srcElement : e.target;		
		return obj;
	},
	
	// attaches an event listener to an element obj
	Observe:function(obj,name,func,capture) {
		if (obj == window && name == "load") {
			this._onContent(func);
			return;
		}
		
		var capture = typeof(capture)=="undefined" ? false : capture;
		var success = false;
		if (obj.addEventListener) {
			obj.addEventListener(name,func,capture); 
			success = true;
		}
		if (obj.attachEvent) {
			obj.attachEvent("on" + name,func); 
			success = true;
		}
		if (success) {
			// add object to observers array
			if (!$OBSERVERS[obj]) {
				$OBSERVERS[obj] = [];
			}
			// add event to observers arr
			$OBSERVERS[obj].push({Name:name,Function:func,Capture:capture});			
			return true;
		}
		return false;
	},
	
	// removes an event listener from element obj and removes it from the observer list
	Remove:function(obj,name,func,capture) {
		if (typeof(name)=="undefined" && typeof(func) == "undefined" && typeof(capture) == "undefined") {
			Event.RemoveBoundTo(obj);
		}
		else {
			Event._removeFromObject(obj,name,func,capture);
			Event._removeFromList(obj,name,func,capture);
		}
	},
	
	// removes all event listeners
	RemoveAll:function() {
		for (var obj in $OBSERVERS) {
			this.RemoveBoundTo(obj);
		}
	},
	
	// removes all event listeners bound to the supplied element
	RemoveBoundTo:function(obj) {
		for (var i=$OBSERVERS[obj].length-1;i>=0;i--) {
			var e = $OBSERVERS[obj][i];
			this._removeFromObject(obj,e.Name,e.Function,e.Capture);
		}
		
		delete $OBSERVERS[obj];		
	},

	// mouse related
	Mouse:{
		GetPosition:function(e) {
			var e = Event.Get(e);
			var pos = {x:0,y:0};
			
			if (e.pageX || e.pageY)	{
				pos.x = e.pageX;
				pos.y = e.pageY;
			}
			else if (e.clientX || e.clientY) {
				pos.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
				pos.y = e.clientY + document.body.scrollTop	+ document.documentElement.scrollTop;
			}
			return pos;
		}
	},
	
	// removes the event from the object
	_removeFromObject:function(obj,name,func,capture) {
		var capture = typeof(capture)=="undefined" ? false : capture;
		if (obj.removeEventListener) {
			obj.removeEventListener(name,func,capture); 
			return true; 
		}
		if (obj.detachEvent) {
			return (obj.detachEvent("on" + name,func));
		}
		return false;
	},
	
	// removes an event from the event list
	_removeFromList:function(obj,name,func,capture) {
		var capture = typeof(capture)=="undefined" ? false : capture;		
		for (var i=0;i<$OBSERVERS[obj].length;i++) {
			var e = $OBSERVERS[obj][i];
			if (e.Name == name && e.Function == func && e.Capture == capture) {
				$OBSERVERS[obj].splice(i,1);
			}
		}
		if ($OBSERVERS[obj].length==0) { 
			delete $OBSERVERS[obj];
		}
	},
	
	// takes care of the window onload problem, see http://webreflection.blogspot.com/2006/11/my-domcontentloaded-final-solution.html
	_onContent:function(func) {
		var a,b=navigator.userAgent,d=document,w=window,
		c="__onContent__",e="addEventListener",o="opera",r="readyState",
		s="<scr".concat("ipt defer src='//:' on",r,"change='if(this.",r,"==\"complete\"){this.parentNode.removeChild(this);",c,"()}'></scr","ipt>");
		w[c]=(function(o){return function(){w[c]=function(){};for(a=arguments.callee;!a.done;a.done=1)func(o?o():o)}})(w[c]);
		if(d[e])d[e]("DOMContentLoaded",w[c],false);
		if(/WebKit|Khtml/i.test(b)||(w[o]&&parseInt(w[o].version())<9))
		(function(){/loaded|complete/.test(d[r])?w[c]():setTimeout(arguments.callee,1)})();
		else if(/MSIE/i.test(b))d.write(s);
	}
}


/* Bind function from prototype library
-------------------------------------------------------------------------*/
Function.prototype.bind = function(obj) {
	var m = this;
	f = function() {
		return m.apply(obj, arguments);
	};
	return f;
}