/*	Prototype JavaScript framework, version 1.5.0_rc0
 *	(c) 2005 Sam Stephenson <sam@conio.net>
 *
 *	Prototype is freely distributable under the terms of an MIT-style license.
 *	For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
	Version: '1.5.0_rc0',
	ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

	emptyFunction: function() {},
	K: function(x) {return x}
}

var Class = {
	create: function() {
		return function() {
			this.initialize.apply(this, arguments);
		}
	}
}

var Abstract = new Object();

Object.extend = function(destination, source) {
	for (var property in source) {
		destination[property] = source[property];
	}
	return destination;
}

Object.inspect = function(object) {
	try {
		if (object == undefined) return 'undefined';
		if (object == null) return 'null';
		return object.inspect ? object.inspect() : object.toString();
	} catch (e) {
		if (e instanceof RangeError) return '...';
		throw e;
	}
}

Function.prototype.bind = function() {
	var __method = this, args = $A(arguments), object = args.shift();
	return function() {
		return __method.apply(object, args.concat($A(arguments)));
	}
}

Function.prototype.bindAsEventListener = function(object) {
	var __method = this;
	return function(event) {
		return __method.call(object, event || window.event);
	}
}

Object.extend(Number.prototype, {
	toColorPart: function() {
		var digits = this.toString(16);
		if (this < 16) return '0' + digits;
		return digits;
	},

	succ: function() {
		return this + 1;
	},

	times: function(iterator) {
		$R(0, this, true).each(iterator);
		return this;
	}
});

var Try = {
	these: function() {
		var returnValue;

		for (var i = 0; i < arguments.length; i++) {
			var lambda = arguments[i];
			try {
				returnValue = lambda();
				break;
			} catch (e) {}
		}

		return returnValue;
	}
}

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

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
	initialize: function(callback, frequency) {
		this.callback = callback;
		this.frequency = frequency;
		this.currentlyExecuting = false;

		this.registerCallback();
	},

	registerCallback: function() {
		setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
	},

	onTimerEvent: function() {
		if (!this.currentlyExecuting) {
			try {
				this.currentlyExecuting = true;
				this.callback();
			} finally {
				this.currentlyExecuting = false;
			}
		}
	}
}
Object.extend(String.prototype, {
	gsub: function(pattern, replacement) {
		var result = '', source = this, match;
		replacement = arguments.callee.prepareReplacement(replacement);

		while (source.length > 0) {
			if (match = source.match(pattern)) {
				result += source.slice(0, match.index);
				result += (replacement(match) || '').toString();
				source	= source.slice(match.index + match[0].length);
			} else {
				result += source, source = '';
			}
		}
		return result;
	},

	sub: function(pattern, replacement, count) {
		replacement = this.gsub.prepareReplacement(replacement);
		count = count === undefined ? 1 : count;

		return this.gsub(pattern, function(match) {
			if (--count < 0) return match[0];
			return replacement(match);
		});
	},

	scan: function(pattern, iterator) {
		this.gsub(pattern, iterator);
		return this;
	},

	truncate: function(length, truncation) {
		length = length || 30;
		truncation = truncation === undefined ? '...' : truncation;
		return this.length > length ?
			this.slice(0, length - truncation.length) + truncation : this;
	},

	strip: function() {
		return this.replace(/^\s+/, '').replace(/\s+$/, '');
	},

	stripTags: function() {
		return this.replace(/<\/?[^>]+>/gi, '');
	},

	stripScripts: function() {
		return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
	},

	extractScripts: function() {
		var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
		var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
		return (this.match(matchAll) || []).map(function(scriptTag) {
			return (scriptTag.match(matchOne) || ['', ''])[1];
		});
	},

	evalScripts: function() {
		return this.extractScripts().map(function(script) { return eval(script) });
	},

	escapeHTML: function() {
		var div = document.createElement('div');
		var text = document.createTextNode(this);
		div.appendChild(text);
		return div.innerHTML;
	},

	unescapeHTML: function() {
		var div = document.createElement('div');
		div.innerHTML = this.stripTags();
		return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
	},

	toQueryParams: function() {
		var pairs = this.match(/^\??(.*)$/)[1].split('&');
		return pairs.inject({}, function(params, pairString) {
			var pair = pairString.split('=');
			params[pair[0]] = pair[1];
			return params;
		});
	},

	toArray: function() {
		return this.split('');
	},

	camelize: function() {
		var oStringList = this.split('-');
		if (oStringList.length == 1) return oStringList[0];

		var camelizedString = this.indexOf('-') == 0
			? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
			: oStringList[0];

		for (var i = 1, len = oStringList.length; i < len; i++) {
			var s = oStringList[i];
			camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
		}

		return camelizedString;
	},

	inspect: function() {
		return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
	}
});

String.prototype.gsub.prepareReplacement = function(replacement) {
	if (typeof replacement == 'function') return replacement;
	var template = new Template(replacement);
	return function(match) { return template.evaluate(match) };
}

String.prototype.parseQuery = String.prototype.toQueryParams;

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
	initialize: function(template, pattern) {
		this.template = template.toString();
		this.pattern	= pattern || Template.Pattern;
	},

	evaluate: function(object) {
		return this.template.gsub(this.pattern, function(match) {
			var before = match[1];
			if (before == '\\') return match[2];
			return before + (object[match[3]] || '').toString();
		});
	}
}

var $break		= new Object();
var $continue = new Object();

var Enumerable = {
	each: function(iterator) {
		var index = 0;
		try {
			this._each(function(value) {
				try {
					iterator(value, index++);
				} catch (e) {
					if (e != $continue) throw e;
				}
			});
		} catch (e) {
			if (e != $break) throw e;
		}
	},

	all: function(iterator) {
		var result = true;
		this.each(function(value, index) {
			result = result && !!(iterator || Prototype.K)(value, index);
			if (!result) throw $break;
		});
		return result;
	},

	any: function(iterator) {
		var result = true;
		this.each(function(value, index) {
			if (result = !!(iterator || Prototype.K)(value, index))
				throw $break;
		});
		return result;
	},

	collect: function(iterator) {
		var results = [];
		this.each(function(value, index) {
			results.push(iterator(value, index));
		});
		return results;
	},

	detect: function (iterator) {
		var result;
		this.each(function(value, index) {
			if (iterator(value, index)) {
				result = value;
				throw $break;
			}
		});
		return result;
	},

	findAll: function(iterator) {
		var results = [];
		this.each(function(value, index) {
			if (iterator(value, index))
				results.push(value);
		});
		return results;
	},

	grep: function(pattern, iterator) {
		var results = [];
		this.each(function(value, index) {
			var stringValue = value.toString();
			if (stringValue.match(pattern))
				results.push((iterator || Prototype.K)(value, index));
		})
		return results;
	},

	include: function(object) {
		var found = false;
		this.each(function(value) {
			if (value == object) {
				found = true;
				throw $break;
			}
		});
		return found;
	},

	inject: function(memo, iterator) {
		this.each(function(value, index) {
			memo = iterator(memo, value, index);
		});
		return memo;
	},

	invoke: function(method) {
		var args = $A(arguments).slice(1);
		return this.collect(function(value) {
			return value[method].apply(value, args);
		});
	},

	max: function(iterator) {
		var result;
		this.each(function(value, index) {
			value = (iterator || Prototype.K)(value, index);
			if (result == undefined || value >= result)
				result = value;
		});
		return result;
	},

	min: function(iterator) {
		var result;
		this.each(function(value, index) {
			value = (iterator || Prototype.K)(value, index);
			if (result == undefined || value < result)
				result = value;
		});
		return result;
	},

	partition: function(iterator) {
		var trues = [], falses = [];
		this.each(function(value, index) {
			((iterator || Prototype.K)(value, index) ?
				trues : falses).push(value);
		});
		return [trues, falses];
	},

	pluck: function(property) {
		var results = [];
		this.each(function(value, index) {
			results.push(value[property]);
		});
		return results;
	},

	reject: function(iterator) {
		var results = [];
		this.each(function(value, index) {
			if (!iterator(value, index))
				results.push(value);
		});
		return results;
	},

	sortBy: function(iterator) {
		return this.collect(function(value, index) {
			return {value: value, criteria: iterator(value, index)};
		}).sort(function(left, right) {
			var a = left.criteria, b = right.criteria;
			return a < b ? -1 : a > b ? 1 : 0;
		}).pluck('value');
	},

	toArray: function() {
		return this.collect(Prototype.K);
	},

	zip: function() {
		var iterator = Prototype.K, args = $A(arguments);
		if (typeof args.last() == 'function')
			iterator = args.pop();

		var collections = [this].concat(args).map($A);
		return this.map(function(value, index) {
			return iterator(collections.pluck(index));
		});
	},

	inspect: function() {
		return '#<Enumerable:' + this.toArray().inspect() + '>';
	}
}

Object.extend(Enumerable, {
	map:		 Enumerable.collect,
	find:		Enumerable.detect,
	select:	Enumerable.findAll,
	member:	Enumerable.include,
	entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
	if (!iterable) return [];
	if (iterable.toArray) {
		return iterable.toArray();
	} else {
		var results = [];
		for (var i = 0; i < iterable.length; i++)
			results.push(iterable[i]);
		return results;
	}
}

Object.extend(Array.prototype, Enumerable);

if (!Array.prototype._reverse)
	Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
	_each: function(iterator) {
		for (var i = 0; i < this.length; i++)
			iterator(this[i]);
	},

	clear: function() {
		this.length = 0;
		return this;
	},

	first: function() {
		return this[0];
	},

	last: function() {
		return this[this.length - 1];
	},

	compact: function() {
		return this.select(function(value) {
			return value != undefined || value != null;
		});
	},

	flatten: function() {
		return this.inject([], function(array, value) {
			return array.concat(value && value.constructor == Array ?
				value.flatten() : [value]);
		});
	},

	without: function() {
		var values = $A(arguments);
		return this.select(function(value) {
			return !values.include(value);
		});
	},

	indexOf: function(object) {
		for (var i = 0; i < this.length; i++)
			if (this[i] == object) return i;
		return -1;
	},

	reverse: function(inline) {
		return (inline !== false ? this : this.toArray())._reverse();
	},

	inspect: function() {
		return '[' + this.map(Object.inspect).join(', ') + ']';
	}
});
var Hash = {
	_each: function(iterator) {
		for (var key in this) {
			var value = this[key];
			if (typeof value == 'function') continue;

			var pair = [key, value];
			pair.key = key;
			pair.value = value;
			iterator(pair);
		}
	},

	keys: function() {
		return this.pluck('key');
	},

	values: function() {
		return this.pluck('value');
	},

	merge: function(hash) {
		return $H(hash).inject($H(this), function(mergedHash, pair) {
			mergedHash[pair.key] = pair.value;
			return mergedHash;
		});
	},

	toQueryString: function() {
		return this.map(function(pair) {
			return pair.map(encodeURIComponent).join('=');
		}).join('&');
	},

	inspect: function() {
		return '#<Hash:{' + this.map(function(pair) {
			return pair.map(Object.inspect).join(': ');
		}).join(', ') + '}>';
	}
}

function $H(object) {
	var hash = Object.extend({}, object || {});
	Object.extend(hash, Enumerable);
	Object.extend(hash, Hash);
	return hash;
}
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
	initialize: function(start, end, exclusive) {
		this.start = start;
		this.end = end;
		this.exclusive = exclusive;
	},

	_each: function(iterator) {
		var value = this.start;
		do {
			iterator(value);
			value = value.succ();
		} while (this.include(value));
	},

	include: function(value) {
		if (value < this.start)
			return false;
		if (this.exclusive)
			return value < this.end;
		return value <= this.end;
	}
});

var $R = function(start, end, exclusive) {
	return new ObjectRange(start, end, exclusive);
}

var Ajax = {
	getTransport: function() {
		return Try.these(
			function() {return new XMLHttpRequest()},
			function() {return new ActiveXObject('Msxml2.XMLHTTP')},
			function() {return new ActiveXObject('Microsoft.XMLHTTP')}
		) || false;
	},

	activeRequestCount: 0
}

Ajax.Responders = {
	responders: [],

	_each: function(iterator) {
		this.responders._each(iterator);
	},

	register: function(responderToAdd) {
		if (!this.include(responderToAdd))
			this.responders.push(responderToAdd);
	},

	unregister: function(responderToRemove) {
		this.responders = this.responders.without(responderToRemove);
	},

	dispatch: function(callback, request, transport, json) {
		this.each(function(responder) {
			if (responder[callback] && typeof responder[callback] == 'function') {
				try {
					responder[callback].apply(responder, [request, transport, json]);
				} catch (e) {}
			}
		});
	}
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
	onCreate: function() {
		Ajax.activeRequestCount++;
	},

	onComplete: function() {
		Ajax.activeRequestCount--;
	}
});

Ajax.Base = function() {};
Ajax.Base.prototype = {
	setOptions: function(options) {
		this.options = {
			method:			 'post',
			asynchronous: true,
			contentType:	'application/x-www-form-urlencoded',
			parameters:	 ''
		}
		Object.extend(this.options, options || {});
	},

	responseIsSuccess: function() {
		return this.transport.status == undefined
				|| this.transport.status == 0
				|| (this.transport.status >= 200 && this.transport.status < 300);
	},

	responseIsFailure: function() {
		return !this.responseIsSuccess();
	}
}

Ajax.Request = Class.create();
Ajax.Request.Events =
	['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
	initialize: function(url, options) {
		this.transport = Ajax.getTransport();
		this.setOptions(options);
		this.request(url);
	},

	request: function(url) {
		var parameters = this.options.parameters || '';
		if (parameters.length > 0) parameters += '&_=';

		try {
			this.url = url;
			if (this.options.method == 'get' && parameters.length > 0)
				this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

			Ajax.Responders.dispatch('onCreate', this, this.transport);

			this.transport.open(this.options.method, this.url,
				this.options.asynchronous);

			if (this.options.asynchronous) {
				this.transport.onreadystatechange = this.onStateChange.bind(this);
				setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
			}

			this.setRequestHeaders();

			var body = this.options.postBody ? this.options.postBody : parameters;
			this.transport.send(this.options.method == 'post' ? body : null);

		} catch (e) {
			this.dispatchException(e);
		}
	},

	setRequestHeaders: function() {
		var requestHeaders =
			['X-Requested-With', 'XMLHttpRequest',
			 'X-Prototype-Version', Prototype.Version,
			 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];

		if (this.options.method == 'post') {
			requestHeaders.push('Content-type', this.options.contentType);

			/* Force "Connection: close" for Mozilla browsers to work around
			 * a bug where XMLHttpReqeuest sends an incorrect Content-length
			 * header. See Mozilla Bugzilla #246651.
			 */
			if (this.transport.overrideMimeType)
				requestHeaders.push('Connection', 'close');
		}

		if (this.options.requestHeaders)
			requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

		for (var i = 0; i < requestHeaders.length; i += 2)
			this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
	},

	onStateChange: function() {
		var readyState = this.transport.readyState;
		if (readyState != 1)
			this.respondToReadyState(this.transport.readyState);
	},

	header: function(name) {
		try {
			return this.transport.getResponseHeader(name);
		} catch (e) {}
	},

	evalJSON: function() {
		try {
			return eval('(' + this.header('X-JSON') + ')');
		} catch (e) {}
	},

	evalResponse: function() {
		try {
			return eval(this.transport.responseText);
		} catch (e) {
			this.dispatchException(e);
		}
	},

	respondToReadyState: function(readyState) {
		var event = Ajax.Request.Events[readyState];
		var transport = this.transport, json = this.evalJSON();

		if (event == 'Complete') {
			try {
				(this.options['on' + this.transport.status]
				 || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
				 || Prototype.emptyFunction)(transport, json);
			} catch (e) {
				this.dispatchException(e);
			}

			if ((this.header('Content-type') || '').match(/^text\/javascript/i))
				this.evalResponse();
		}

		try {
			(this.options['on' + event] || Prototype.emptyFunction)(transport, json);
			Ajax.Responders.dispatch('on' + event, this, transport, json);
		} catch (e) {
			this.dispatchException(e);
		}

		/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
		if (event == 'Complete')
			this.transport.onreadystatechange = Prototype.emptyFunction;
	},

	dispatchException: function(exception) {
		(this.options.onException || Prototype.emptyFunction)(this, exception);
		Ajax.Responders.dispatch('onException', this, exception);
	}
});

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
	initialize: function(container, url, options) {
		this.containers = {
			success: container.success ? $(container.success) : $(container),
			failure: container.failure ? $(container.failure) :
				(container.success ? null : $(container))
		}

		this.transport = Ajax.getTransport();
		this.setOptions(options);

		var onComplete = this.options.onComplete || Prototype.emptyFunction;
		this.options.onComplete = (function(transport, object) {
			this.updateContent();
			onComplete(transport, object);
		}).bind(this);

		this.request(url);
	},

	updateContent: function() {
		var receiver = this.responseIsSuccess() ?
			this.containers.success : this.containers.failure;
		var response = this.transport.responseText;

		if (!this.options.evalScripts)
			response = response.stripScripts();

		if (receiver) {
			if (this.options.insertion) {
				new this.options.insertion(receiver, response);
			} else {
				Element.update(receiver, response);
			}
		}

		if (this.responseIsSuccess()) {
			if (this.onComplete)
				setTimeout(this.onComplete.bind(this), 10);
		}
	}
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
	initialize: function(container, url, options) {
		this.setOptions(options);
		this.onComplete = this.options.onComplete;

		this.frequency = (this.options.frequency || 2);
		this.decay = (this.options.decay || 1);

		this.updater = {};
		this.container = container;
		this.url = url;

		this.start();
	},

	start: function() {
		this.options.onComplete = this.updateComplete.bind(this);
		this.onTimerEvent();
	},

	stop: function() {
		this.updater.onComplete = undefined;
		clearTimeout(this.timer);
		(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
	},

	updateComplete: function(request) {
		if (this.options.decay) {
			this.decay = (request.responseText == this.lastText ?
				this.decay * this.options.decay : 1);

			this.lastText = request.responseText;
		}
		this.timer = setTimeout(this.onTimerEvent.bind(this),
			this.decay * this.frequency * 1000);
	},

	onTimerEvent: function() {
		this.updater = new Ajax.Updater(this.container, this.url, this.options);
	}
});
function $() {
	var results = [], element;
	for (var i = 0; i < arguments.length; i++) {
		element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);
		results.push(Element.extend(element));
	}
	return results.length < 2 ? results[0] : results;
}

document.getElementsByClassName = function(className, parentElement) {
	var children = ($(parentElement) || document.body).getElementsByTagName('*');
	return $A(children).inject([], function(elements, child) {
		if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
			elements.push(Element.extend(child));
		return elements;
	});
}

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

if (!window.Element)
	var Element = new Object();

Element.extend = function(element) {
	if (!element) return;
	if (_nativeExtensions) return element;

	if (!element._extended && element.tagName && element != window) {
		var methods = Element.Methods, cache = Element.extend.cache;
		for (property in methods) {
			var value = methods[property];
			if (typeof value == 'function')
				element[property] = cache.findOrStore(value);
		}
	}

	element._extended = true;
	return element;
}

Element.extend.cache = {
	findOrStore: function(value) {
		return this[value] = this[value] || function() {
			return value.apply(null, [this].concat($A(arguments)));
		}
	}
}

Element.Methods = {
	visible: function(element) {
		return $(element).style.display != 'none';
	},

	toggle: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = $(arguments[i]);
			Element[Element.visible(element) ? 'hide' : 'show'](element);
		}
	},

	hide: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = $(arguments[i]);
			element.style.display = 'none';
		}
	},

	show: function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = $(arguments[i]);
			element.style.display = '';
		}
	},

	remove: function(element) {
		element = $(element);
		element.parentNode.removeChild(element);
	},

	update: function(element, html) {
		$(element).innerHTML = html.stripScripts();
		setTimeout(function() {html.evalScripts()}, 10);
	},

	replace: function(element, html) {
		element = $(element);
		if (element.outerHTML) {
			element.outerHTML = html.stripScripts();
		} else {
			var range = element.ownerDocument.createRange();
			range.selectNodeContents(element);
			element.parentNode.replaceChild(
				range.createContextualFragment(html.stripScripts()), element);
		}
		setTimeout(function() {html.evalScripts()}, 10);
	},

	getHeight: function(element) {
		element = $(element);
		return element.offsetHeight;
	},

	classNames: function(element) {
		return new Element.ClassNames(element);
	},

	hasClassName: function(element, className) {
		if (!(element = $(element))) return;
		return Element.classNames(element).include(className);
	},

	addClassName: function(element, className) {
		if (!(element = $(element))) return;
		return Element.classNames(element).add(className);
	},

	removeClassName: function(element, className) {
		if (!(element = $(element))) return;
		return Element.classNames(element).remove(className);
	},

	// removes whitespace-only text node children
	cleanWhitespace: function(element) {
		element = $(element);
		for (var i = 0; i < element.childNodes.length; i++) {
			var node = element.childNodes[i];
			if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
				Element.remove(node);
		}
	},

	empty: function(element) {
		return $(element).innerHTML.match(/^\s*$/);
	},

	childOf: function(element, ancestor) {
		element = $(element), ancestor = $(ancestor);
		while (element = element.parentNode)
			if (element == ancestor) return true;
		return false;
	},

	scrollTo: function(element) {
		element = $(element);
		var x = element.x ? element.x : element.offsetLeft,
				y = element.y ? element.y : element.offsetTop;
		window.scrollTo(x, y);
	},

	getStyle: function(element, style) {
		element = $(element);
		var value = element.style[style.camelize()];
		if (!value) {
			if (document.defaultView && document.defaultView.getComputedStyle) {
				var css = document.defaultView.getComputedStyle(element, null);
				value = css ? css.getPropertyValue(style) : null;
			} else if (element.currentStyle) {
				value = element.currentStyle[style.camelize()];
			}
		}

		if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
			if (Element.getStyle(element, 'position') == 'static') value = 'auto';

		return value == 'auto' ? null : value;
	},

	setStyle: function(element, style) {
		element = $(element);
		for (var name in style)
			element.style[name.camelize()] = style[name];
	},

	getDimensions: function(element) {
		element = $(element);
		if (Element.getStyle(element, 'display') != 'none')
			return {width: element.offsetWidth, height: element.offsetHeight};

		// All *Width and *Height properties give 0 on elements with display none,
		// so enable the element temporarily
		var els = element.style;
		var originalVisibility = els.visibility;
		var originalPosition = els.position;
		els.visibility = 'hidden';
		els.position = 'absolute';
		els.display = '';
		var originalWidth = element.clientWidth;
		var originalHeight = element.clientHeight;
		els.display = 'none';
		els.position = originalPosition;
		els.visibility = originalVisibility;
		return {width: originalWidth, height: originalHeight};
	},

	makePositioned: function(element) {
		element = $(element);
		var pos = Element.getStyle(element, 'position');
		if (pos == 'static' || !pos) {
			element._madePositioned = true;
			element.style.position