function _type(v){
	// v = value
	var t = typeof v;
	if(t == "object"){
		if(v){
			if(typeof v.splice == "function"){
				t = "array";
			}
		} else {
			t = "null";
		}
	}
	return t;
}

function _nodelist(a){
	// a = array
	var n = [];
	for(var j=0; j<a.length; j++){
		n[j] = a[j];
	}
	return n;
}

function _isallws(n){
	// n = node
	return !(/[^\t\n\r ]/.test(n.data));
}

function _isignorable(n){
	// n = node
	return ( n.nodeType == 8) || ( (n.nodeType == 3) && _isallws(n) );
}

/* ---------------------------------------------------------------------------------------------------------------------- */

Array.prototype.each = function(f){
	// f=function
	for(var j=0; j<this.length; j++){
		f(this[j]);
	}
}

Number.prototype.times = function(f){
	// f = function
	for(var j=0; j<this; j++){
		f(j);
	}
}

String.prototype.inArray = function(a){
	// a = array
	for(var j=0; j<a.length; j++){
		if(a[j] == this) return true;
	}
	return false;
}

/* ---------------------------------------------------------------------------------------------------------------------- */

var $DOM = {
	append: function(o, p){ // o = object, p = parent
		p = (p) ? p : document.body;
		if(_type(o) != "array"){
			p.appendChild(o);
		} else {
			for(var j=0; j<o.length; j++){
				p.appendChild(o[j]);
			}
		}
		return o;
	},
	
	childNodes: function(p){ // p = parent
		var e = p.childNodes;
		if(!e) return e;
		var n = [];
		for(var j=0; j<e.length; j++){
			if(_isignorable(e[j])) continue;
			n[n.length] = e[j];
		}
		return n;
	},
	
	className: function(c, t, p){ // c = classname, t = tag, p = parent
		t = (t) ? t : "*";
		p = (p) ? p : document;
		var n_l = p.getElementsByTagName(t);
		var n = [];
		for(var j=0; j<n_l.length; j++){
			if((" "+n_l[j].className+" ").indexOf(" "+c+" ") == -1) continue;
			n[n.length] = n_l[j];
		}
		if(n.length === 0) n = null;
		return n;
	},
	
	create: function (e, t, a){ // e = element tag, t = text, a = attributes
		var n;
		n = document.createElement(e);
		if(t){
			var n_t = document.createTextNode(t);
			n.appendChild(n_t);
		}
		if(a){
			for(var j in a){
				if(j == "class"){
					n.className = a[j];
				} else {
					n.setAttribute(j, a[j]);
				}
			}
		}
		return n;
	},
	
	elements: function(t, p){ // t = tag, p = parent
		var n = null;
		var p = (p) ? p : document;
		if(_type(t) != "array"){
			n = _nodelist(p.getElementsByTagName(t));
		} else {
			n = [];
			var n_l;
			var j;
			for(j=0; j<t.length; j++){
				n_l = _nodelist(p.getElementsByTagName(t[j]));
				n = n.concat(n_l);
			}
			for(j=0; j<n.length; j++){
				n[j].append = function(o){
					$append(this, o);
				}
			}
		}
		return n;
	},
	
	firstChild: function(p){ // p = parent
		var n = p.firstChild;
		while(n) {
			if (!_isignorable(n)) return n;
			n = n.nextSibling;
		}
		return null;
	},
	
	id: function (){ // i = id
		var n = null;
		if(arguments.length > 0) n = [];
		for(var j=0; j<arguments.length; j++){
			n[n.length] = document.getElementById(arguments[j]);
		}
		if(n.length === 1) n = n[0];
		return n;
	},

	lastChild: function(p){ // p = parent
		var n = p.lastChild;
		while(n) {
			if (!_isignorable(n)) return n;
			n = n.previousSibling;
		}
		return null;
	},
	
	nest: function(){
		var a = arguments;
		for(var j=a.length-1; j>=0; j--){
			if(a[j-1]){
				if(_type(a[j]) != "array"){
					a[j-1].appendChild(a[j]);
				} else {
					for(var k=0; k<a[j].length; k++){
						a[j-1].appendChild(a[j][k]);
					}
				}
			}
		}
	},
	
	nextSibling: function(s){ // s = sibling
		while ((s = s.nextSibling)) {
			if (!_isignorable(s)) return s;
		}
		return null;
	},
	
	parent: function(o, s){ // o = object, s = steps
		var n = o;
		s = (s) ? s : 1;
		for(var j=0; j<s; j++){
			n = n.parentNode;
		}
		return n;
	},
	
	previousSibling: function(s){ // s = sibling
		while ((s = s.previousSibling)) {
			if (!_isignorable(s)) return s;
		}
		return null;
	},
	
	remove: function(o){ // o = object(s)
		if(_type(o) != "array"){
			o.parentNode.removeChild(o);
		} else {
			for(var j=0; j<o.length; j++){
				o[j].parentNode.removeChild(o[j]);
			}
		}
		return o;
	},
	
	style: function(o, s){ // o = object, s = style
		for(var j in s){
			o.style[j] = s[j];
		}
	}
};

var $EVENT = {
	add: function(o, e, f){ // o =object, e = event, f = function
		if(o.addEventListener){
			o.addEventListener(e, f, false);
		} else {
			o.attachEvent("on"+e, f);
		}
	},
	
	currentTarget: function(e){ // e = event object
		return (e.currentTarget || e.fromElement);
	},
	
	object: function(e){ // e = event object
		return (e || window.event);
	},
	
	preventDefault: function(e){ // e = event object
		if(e.preventDefault){
			e.preventDefault();
		} else {
			e.returnValue = false;
		}
	},
	
	stopPropagation: function(e){ // e = event object
		if(e.stopPropagation){
			e.stopPropagation;
		} else {
			e.cancelBubble = true;
		}
	},
	
	target: function(e){ // e = event object
		return (e.target || e.srcElement);
	},
	
	relatedTarget: function(e){
		return (e.relatedTarget || e.toElement);
	},
	
	window: function(f){ // f = function
		var o = window.onload;
		if(_type(window.onload) != "function"){
			window.onload = f;
		} else {
			window.onload = function(){
				if(o){
					o();
				}
				f();
			}
		}	
	}
};

var $XMLHTTP = {
	objects : [
		function(){ return new XMLHttpRequest(); },
		function(){ return new ActiveXObject("Msxml2.XMLHTTP"); },
		function(){ return new ActiveXObject("Msxml3.XMLHTTP"); },
		function(){ return new ActiveXObject("Microsoft.XMLHTTP"); }
	],
	
	create : function(){
		var XMLHttp = false;
		for( var j=0; j<this.objects.length; j++){
			try {
				XMLHttp = this.objects[j]();
			}
			catch(e){
				continue;
			}
			break;
		}
		return XMLHttp;	
	},
	
	request: function(u, p){ // u = url, p = post data
		var x = this.create();
		if(!x) return;
		var m = (p) ? "POST" : "GET";
		x.open(m, u, true);
		x.setRequestHeader("User-Agent", "XMLHTTP");
		if(p) x.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		if(x.overrideMimeType) x.overrideMimeType('text/xml');
		x.send(p);
		return x;
	},
	
	onload: function(r, c){ // r = request, c = callback
		r.onreadystatechange = function(){
			if(r.readyState == 4) {
				if(r.status == 200 || r.status == 304){
					c();
					return true;
				} else {
					alert("HTTP error: "+r.status);
					return false;
				}
			}
		}
	}
};

/*$EVENT.window(function(){
	var n;
	var b = ["333","777","AAA","EEE"];
	(4).times(function(i){
		n = $DOM.create("div","Teste box");
		n.style.backgroundColor = "#"+b[i];
		n.style.color = "#"+b[4-1-i];
		$DOM.append(n);
	});
	
	$DOM.previousSibling($DOM.lastChild(document.body)).style.backgroundColor = "#A45";
	
	var p  = $DOM.create("p", "Her er en p, og et link: ", {id: "id_test", "class": "id_test1"});
	var a  = $DOM.create("a", "Klik her", {href: "http://google.dk"});
	var b  = $DOM.create("b", "|| Noget fed tekst");
	var i  = $DOM.create("i", "|| Noget kursiv og fed tekst", {"class": "id_test1"});
	$DOM.nest(p, a, b, i);
	$DOM.append(p);
	
	var p	 = $DOM.create("p");
	var a	 = $DOM.create("a", "Manu", {"href":"#"});
	var span = $DOM.create("span", "Slet");
	$DOM.nest(p, span, a);
	$DOM.append(p);
	
	$DOM.style(p, {backgroundColor: "#A84", padding: "10px"});
	
	var x = $XMLHTTP.request("index.php");
	$XMLHTTP.onload(x, function(){
		alert(x.responseText);
	});
});*/