function bind(object, fnc) {
	var args = [];
	for (var i=2; i<arguments.length; ++i) {
		args.push(arguments[i]);
	}
	return function() {
		var args2 = [];
		for (var i = 0; i < arguments.length; i++) {
			args2.push(arguments[i]);
		}
		return fnc.apply(object, args.concat(args2));
	}
}

function bindAsEventListener(object, fnc) {
	return function(event) {
		return fnc.apply(object, [event || window.event]);
	}
}

function inArray(a, value) {
	var i;
	for (i=0; i < a.length; i++) {
		if (a[i] === value) {
			return true;
		}
	}
	return false;
}

function $() {
	var elements = [];
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof(element) == 'string') {
			var element = document.getElementById(element);
		}
		if (arguments.length == 1) {
			return element;
		}
		elements.push(element);
	}
	return elements;
}

function allChildNodes(elm) {
	var result = [];
	for (var i = 0, c = elm.childNodes; i < c.length; ++i) {
		result.push(c[i]);
		if (c[i].childNodes && c[i].childNodes.length > 0) {
			for (var child in allChildNodes(c[i])) {
				result.push(child);
			}
		}
	}
	return result;
}

function popwin(anchor, height, width) {
	if (typeof(height) == "undefined") {
		height = 346;
	}
	if (typeof(width) == "undefined") {
		width = 489;
	}
	var d = window.open(anchor.href, "puppy", "toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width="+width+",height="+height);
	d.focus();
	return false;
}

function getAjax(url, callback) {
	var httpRequest = false;

	if (window.XMLHttpRequest) {
		httpRequest = new XMLHttpRequest();
//		if (httpRequest.overrideMimeType) httpRequest.overrideMimeType('text/xml');
		if (httpRequest.overrideMimeType) httpRequest.overrideMimeType('text/html');
	} else if (window.ActiveXObject) {
		try {
			httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
		}
	}

	if (!httpRequest) return false;

	httpRequest.onreadystatechange = function() {
		if (httpRequest.readyState == 4) {
			if (httpRequest.status == 200) {
				eval(callback);
			} else {
				alert('Error: ' + httpRequest.status);
			}
		}
	}
	httpRequest.open('GET', url, true);
	httpRequest.send(null);
}

function updateFromCookie(id, cookie, defaultvalue) {
	value = unescape(readCookie(cookie)).replace("+", " ");
	if (value=='') value = defaultvalue;
	document.getElementById(id).innerHTML = value;
}

function readCookie(cookie) {
	var cookieEQ = cookie + "=";
	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(cookieEQ)==0) {
			return c.substring(cookieEQ.length, c.length);
		}
	}
	return "";
}

/**
  * @package Position
  *
  * Contains various crossbrowser adapters and low-level utilities
  */
if (typeof(Position) == "undefined") {
	Position = {};
}

/** This function will return an Object with x and y properties of the element */
Position.getPosition = function(elm) {
	var offset = Position.cumulativeOffset(elm);
	return { x : offset[0], y : offset[1] }
};

Position.cumulativeOffset = function(element) {
	var valueT = 0, valueL = 0;
	do {
		valueT += element.offsetTop  || 0;
		valueL += element.offsetLeft || 0;
		element = element.offsetParent;
	} while (element);
	return [valueL, valueT];
};

/** Surprisingly it returns the x,y position of the mouse */

Position.getMousePosition = function(e) {
	if (!e) var e = window.event;
	if (e.pageX || e.pageY) {
		return {
			x : e.pageX,
			y : e.pageY
		}
	} else if (e.clientX || e.clientY) {
		return {
			x : e.clientX + Math.max(document.body.scrollLeft, document.documentElement.scrollLeft),
			y : e.clientY + Math.max(document.body.scrollTop, document.documentElement.scrollTop)
		}
	}
	return {
		x : 0,
		y : 0
	}
};

/**
  * The inner dimensions of the window or frame.
  * Straight out of : http://www.quirksmode.org/viewport/compatibility.html
  */
Position.getScreenDimensions = function() {
	var x,y;
	if (self.innerHeight) {
		// all except Explorer
		x = self.innerWidth;
		y = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) {
		// Explorer 6 Strict Mode
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	}
	else if (document.body) {
		// other Explorers
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	return {
		width : x,
		height : y
	}
}

/**
  * The inner dimensions of the document.
  * Straight out of : http://www.quirksmode.org/viewport/compatibility.html
  */
Position.getPageDimensions = function() {
	var x,y;
	var test1 = document.body.scrollHeight;
	var test2 = document.body.offsetHeight
	if (test1 > test2) {
		// all but Explorer Mac
		x = document.body.scrollWidth;
		y = document.body.scrollHeight;
	} else {
		// Explorer Mac;
		//would also work in Explorer 6 Strict, Mozilla and Safari
		x = document.body.offsetWidth;
		y = document.body.offsetHeight;
	}
	return {
		width : x,
		height : y
	}
}

/**
  * This function will return an Object with width and height properties of the element.
  * Messaurements does NOT include borders and padding. (content-box)
  */
Position.getDimensions = function(elm) {
	var bp = Position.getBorderPadding(elm);
	return {
		width  : elm.offsetWidth - (bp.borderWidth + bp.paddingWidth),
		height : elm.offsetHeight - (bp.borderHeight + bp.paddingHeight)
	}
};

/**
  * Returns the actual border and padding of an element.
  * @param elm HTMLElement
  */
Position.getBorderPadding = function(elm) {
	var cs = Position.getCurrentSize(elm);
	if (elm.currentStyle) {
		var thin = 2;
		var medium = 4;
		var thick = 6;
	} else {
		var thin = 1;
		var medium = 3;
		var thick = 5;
	}
	// this isn't entirely precise, since the actual pixel-sizes may differ from browser to browser.
	// they are however the defaults for internet explorer 6sp2 and firefox 1.0, windows xp
	var tmpFunc = function(val) {
		val = parseInt(val);
		if (isNaN(val)) {
			switch (val) {
			case "thin" : return thin;
			case "medium" : return medium;
			case "thick" : return thick;
			}
			return 1;
		} else {
			return val;
		}
	};

	return {
		borderWidth  : tmpFunc(cs.borderLeftWidth) + tmpFunc(cs.borderRightWidth),
		borderHeight : tmpFunc(cs.borderTopWidth) + tmpFunc(cs.borderBottomWidth),
		paddingWidth : tmpFunc(cs.paddingLeft) + tmpFunc(cs.paddingRight),
		paddingHeight: tmpFunc(cs.paddingTop) + tmpFunc(cs.paddingBottom)
	}
};

Position.getCurrentSize = function(elm) {
	if (elm == null) throw new Error("Argument is not an HTMLElement");
	if (elm.currentStyle) {
		return elm.currentStyle;
	} else {
		var cs = document.defaultView.getComputedStyle(elm,'');
		return {
			paddingLeft  : cs.getPropertyValue('padding-left'),
			paddingRight : cs.getPropertyValue('padding-right'),
			borderLeftWidth : cs.getPropertyValue('border-left-width'),
			borderRightWidth: cs.getPropertyValue('border-right-width'),
			marginLeft  : cs.getPropertyValue('margin-left'),
			marginRight : cs.getPropertyValue('margin-right'),

			paddingTop  : cs.getPropertyValue('padding-top'),
			paddingBottom : cs.getPropertyValue('padding-bottom'),
			borderTopWidth : cs.getPropertyValue('border-top-width'),
			borderBottomWidth: cs.getPropertyValue('border-bottom-width'),
			marginTop  : cs.getPropertyValue('margin-top'),
			marginBottom : cs.getPropertyValue('margin-bottom')
		}
	}
};