function $(id) {
	if (document.getElementById) return document.getElementById(id);
	else return document.all[id];
}

var XML = new Object();
XML.value = function(node) {
	if (node && node.childNodes[0]) {
		var value = node.childNodes[0].nodeValue;
		return value ? value : '';
	}
	return null;
}
XML.tags = function(node, tag) {
	return node.getElementsByTagName(tag);
}
XML.tag = function(node, tag) {
	return node.getElementsByTagName(tag)[0];
}

var DOM = new Object();
DOM._ = function(tag) {
	return document.createElement(tag);
}
DOM.text = function(text, maxlen) {
	if (maxlen > 3 && text.length > maxlen) {
		return document.createTextNode(text.substring(0, maxlen-3) + '...');
	}
	return document.createTextNode(text ? text : '');
}
DOM.clearNode = function(node) {
	if (node) while (node.childNodes.length) node.removeChild(node.childNodes[0]);
}
DOM.appendClass = function(e, c) {
	if (e && e.className) e.className += ' ' + c;
	else e.className = c;
}
DOM.removeClass = function(e, c) {
	if (e && e.className && c) {
		if (e.className == c) e.className = '';
		else {
			var pos = e.className.indexOf(c + ' ');
			if (pos == 0) e.className = e.className.substring(c.length + 1);
			else {
				pos = e.className.lastIndexOf(' ' + c);
				if (pos == e.className.length - c.length - 1) e.className = e.className.substring(0, pos);
				else e.className.replace(' ' + c + ' ', ' ');
			}
		}
	}
}
DOM.getEventTarget = function(evt) {
	var t;
	if (!evt) var evt = window.event;
	if (evt.target) t = evt.target;
	else if (evt.srcElement) t = evt.srcElement;
	if (t.nodeType == 3) t = t.parentNode;
	return t;
}
DOM.mousePos = function(evt, offset) {
	if (!evt) var evt = window.event;
	var mouseX = (offset ? offset.X : 0);
	var mouseY = (offset ? offset.Y : 0);
	if (evt.pageX || evt.pageY) {
		mouseX += evt.pageX;
		mouseY += evt.pageY;
	} else if (evt.clientX || evt.clientY) {
		mouseX += evt.clientX;
		mouseY += evt.clientY;
		if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
			mouseX += document.body.scrollLeft;
			mouseY += document.body.scrollTop;
		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
			mouseX += document.documentElement.scrollLeft;
			mouseY += document.documentElement.scrollTop;
		}
	}
	return {X:mouseX,Y:mouseY}
}
DOM.show = function(e, pos) {
	if (e && e.style) {
		e.style.display = 'block';
		if (pos) {
			e.style.left = pos.X + 'px';
			e.style.top = pos.Y + 'px';
		}
	}
}
DOM.hide = function(e) {
	if (e && e.style) e.style.display = 'none';
}
DOM.reveal = function(e, pos) {
	if (e && e.style) {
		e.style.visibility = 'visible';
		if (pos) {
			e.style.left = pos.X;
			e.style.top = pos.Y;
		}
	}
}
DOM.cloak = function(e) {
	if (e && e.style) e.style.visibility = 'hidden';
}

var QueryString = new Object();
QueryString.parse = function() {
	var query = document.location.search.substring(1);
	var parms = query.split('&');
	for (var i = 0; i < parms.length; i++) {
		var pos = parms[i].indexOf('=');
		if (pos > 0) QueryString[parms[i].substring(0, pos)] = parms[i].substring(pos+1);
	}
}
QueryString.parse();

var XMLRequest = new Object();
XMLRequest.send = function(url, callback) {
	var xmlreq = false;
	if (window.XMLHttpRequest) xmlreq = new XMLHttpRequest();
	else if (window.ActiveXObject) xmlreq = new ActiveXObject('Msxml2.XMLHTTP');
	else xmlreq = new ActiveXObject('Microsoft.XMLHTTP');

	xmlreq.onreadystatechange = function() {
		if (xmlreq.readyState == 4) {
			if (xmlreq.status == 200) {callback(xmlreq);}
			else if (xmlreq.status == 403) {alert('not logged in');}
			else {alert('Error: ' + xmlreq.statusText + ' (' + xmlreq.status + ')\nResponse:\n' + xmlreq.responseText);}
		}
	}
	xmlreq.open("GET", url, true);
	xmlreq.send(null);
	return xmlreq;
}
