var ElementWrapper = function (e) {
	this.e = e;
};
ElementWrapper.prototype = {
	getElement: function () {
		return this.e;
	},
	isShown: function () {
		return this.e.style.display != "none";
	},
	show: function () {
		this.e.style.display = "";
		return this;
	},
	hide: function () {
		this.e.style.display = "none";
		return this;
	},
	toggle: function () {
		return this.isShown() ? this.hide(): this.show();
	},
	append: function () {
		for (var i = 0; i < arguments.length; i++) {
			var c = arguments[i];
			if (c == null) continue;
			if (typeof(c) == "object") {
				if (c instanceof ElementWrapper) {
					this.e.appendChild(c.e);
				} else if (c.tagName) {
					this.e.appendChild(c);
				} else if (c instanceof Array) {
					for (var j = 0; j < c.length; j++) {
						this.append(c[j]);
					}
				} else if (c.constructor == Object) {
					this.set(c);
				}
			} else {
				this.e.appendChild(document.createTextNode(c));
			}
		}
		return this;
	},
	appendNext: function () {
		var arg = (arguments.length == 1 ? arguments[0] : Array.prototype.slice.call(arguments));
		if (this.e.nextSibling) {
			this.parent()._insertBefore(this.next(), arg);
		} else {
			this.parent().append(arg);
		}
		return this;
	},
	appendPrev: function () {
		var arg = (arguments.length == 1 ? arguments[0] : Array.prototype.slice.call(arguments));
		this.parent()._insertBefore(this, arg);
		return this;
	},
	_insertBefore: function () {
		var ref = arguments[0];
		for (var i = 1; i < arguments.length; i++) {
			var c = arguments[i];
			if (c == null) continue;
			if (typeof(c) == "object") {
				if (c instanceof ElementWrapper) {
					this.e.insertBefore(c.e, ref.e);
				} else if (c.tagName) {
					this.e.insertBefore(c, ref.e);
				} else if (c instanceof Array) {
					for (var j = 0; j < c.length; j++) {
						this._insertBefore(arguments[0], c[j]);
					}
				}
			} else {
				this.e.insertBefore(document.createTextNode(c));
			}
		}
		return this;
	},
	clear: function () {
		var children = this.e.childNodes;
		for (var i = children.length - 1; i >= 0; i--) {
			this.e.removeChild(children[i]);
		}
		return this;
	},
	replace: function () {
		return this.clear().append.apply(this, arguments);
	},
	remove: function () {
		return this.e.parentNode.removeChild(this.e);
	},
	setClass: function (className) {
		this.e.className = className;
		return this;
	},
	addClass: function (className) {
		if (className == "") {
			return this;
		}
		var cn = this.e.className;
		if (cn == "") {
			this.e.className = className;
			return this;
		}
		var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)")
		if (cn == className || cn.match(pattern)) {
			return this;
		}
		this.e.className = cn + " " + className;
		return this;
	},
	removeClass: function (className) {
		if (className == "") {
			return this;
		}
		var cn = this.trim(this.e.className);
		if (cn == "") {
			return this;
		}
		if (cn == className) {
			this.e.className = "";
			return this;
		}
		var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
		if (cn.match(pattern)) {
			this.e.className = this.trim(cn.replace(pattern, " "));
			return this;
		}
		return this;
	},
	set: function (attr, value) {
		if (typeof(attr) == "object") {
			for (var i in attr) {
				if (i == "class") {
					this.e.className = attr[i];
				} else {
					this.e.setAttribute(i, attr[i]);
				}
			}
		} else {
			this.e.setAttribute(attr, value);
		}
		return this;
	},
	get: function (attr) {
		return this.e.getAttribute(attr);
	},
	parent: function () {
		var p = this.e.parentNode;
		return p ? new ElementWrapper(p): null;
	},
	removeFirst: function () {
		this.e.removeChild(this.e.firstChild);
		return this;
	},
	removeLast: function () {
		var children = this.e.childNodes;
		this.e.removeChild(children[children.length - 1]);
		return this;
	},
	first: function () {
		var c = this.e.firstChild;
		return c ? new ElementWrapper(c): null;
	},
	last: function () {
		var c = this.e.childNodes;
		return c ? new ElementWrapper(c[c.length - 1]): null;
	},
	next: function () {
		var s = this.e.nextSibling;
		return s ? new ElementWrapper(s): null;
	},
	prev: function () {
		var s = this.e.previousSibling;
		return s ? new ElementWrapper(s): null;
	},
	children: function () {
		var array = [];
		for (c = this.first(); c; c = c.next()) {
			array[array.length] = c;
		}
		return array;
	},
	addListener: function(type, fn) {
		var ee = this;
		if (this.e.addEventListener) {
			var f = function (e) {
				return fn.call(ee.e, ee, e);
			};
			this.e.addEventListener(type, f, false);
		} else if (this.e.attachEvent) {
			var f = function () {
				return fn.call(ee.e, ee, window.event);
			};
			this.e.attachEvent('on' + type, f);
		} else {
			this.e['on'+type] = function (e) {
				return fn.call(ee.e, ee, e ? e: window.event);
			};
		}
		return this;
	},
	getStyle: function (attr) {
		return this.e.style[attr];
	},
	setStyle: function (attr, value) {
		if (typeof(attr) == "object") {
			for (var i in attr) this.e.style[i] = attr[i];
		} else {
			this.e.style[attr] = value;
		}
		return this;
	},
	setSize: function (a1, a2) {
		var w, h;
		if (typeof(a1) == "object") {
			w = a1.width;
			h = a1.height;
		} else {
			w = a1; h = a2;
		}
		if (w != undefined && h != undefined) {
			this.e.style.width = w + "px";
			this.e.style.height = h + "px";
		}
		return this;
	},
	getSize: function () {
		return { width: this.e.offsetWidth, height: this.e.offsetHeight };
	},
	setRect: function (a1, a2, a3, a4) {
		var x, y, w, h;
		if (typeof(a1) == "object") {
			x = a1.x != null ? a1.x : a1.left;
			y = a1.y != null ? a1.y : a1.top;
			if (a1.width) {
				w = a1.width;
				h = a1.height;
			} else if (typeof(a2) == "object") {
				w = a2.width;
				h = a2.height;
			}
		} else {
			x = a1; y = a2; w = a3; h = a4;
		}
		if (x != undefined && y != undefined && w != undefined && h != undefined) {
			this.e.style.left = x + "px";
			this.e.style.top = y + "px";
			this.e.style.width = w + "px";
			this.e.style.height = h + "px";
		}
		return this;
	},
	getRect: function () {
		return { x: this.e.offsetLeft, y: this.e.offsetTop, width: this.e.offsetWidth, height: this.e.offsetHeight };
	},
	setPosition: function (a1, a2) {
		var x, y;
		if (typeof(a1) == "object") {
			x = a1.x != null ? a1.x : a1.left;
			y = a1.y != null ? a1.y : a1.top;
		} else {
			x = a1; y = a2;
		}
		if (x != undefined && y != undefined) {
			this.e.style.left = x + "px";
			this.e.style.top = y + "px";
		}
		return this;
	},
	getPosition: function () {
		return { x: this.e.offsetLeft, y: this.e.offsetTop };
	},
	getPagePosition: function () {
		var x = 0;
		var y = 0;
		var e = this.e;
		while (e) {
			if (e.offsetLeft) x += e.offsetLeft;
			if (e.offsetTop) y += e.offsetTop;
			e = (e.offsetParent ? e.offsetParent: null);
		}
		return { x: x, y: y };
	},
	text: function () {
		var s = "";
		var children = this.e.childNodes;
		for (var i = 0; i < children.length; i++) {
			var child = children[i];
			if (child.nodeType == 3) {
				s += child.nodeValue;
			}
		}
		return s;
	},
	trim: function (str) {
		return str.replace(new RegExp("^\\s+|\\s+$", "g"), "");
	}
};
ElementWrapper._create = function (tagName, children) {
	var e = new ElementWrapper(document.createElement(tagName));
	if (children) {
		for (var i = 0; i < children.length; i++) {
			e.append(children[i]);
		}
	}
	return e;
}
eval(
	function () {
		var tags = [
			"A", "ABBR", "ACRONYM", "ADDRESS", "B", "BASE", "BDO", "BIG", "BLOCKQUOTE", "BR",
			"BUTTON", "CAPTION", "CITE", "CODE", "COL", "COLGROUP", "DD", "DEL", "DFN", "DIV",
			"DL", "DT", "EM", "FIELDSET", "FORM", "FRAME", "FRAMESET", "H1", "H2", "H3",
			"H4", "H5", "H6", "HR", "I", "IFRAME", "IMG", "INPUT", "INS", "KBD",
			"LABEL", "LEGEND", "LI", "LINK", "MAP", "OBJECT", "OL", "OPTGROUP", "OPTION", "P",
			"PARAM", "PRE", "Q", "SAMP", "SELECT", "SMALL", "SPAN", "STRONG", "SUB", "SUP",
			"TABLE", "TBODY", "TD", "TEXTAREA", "TFOOT", "TH", "THEAD", "TR", "TT", "UL",
			"VAR"
		];
		var s = "";
		for (var i = 0; i < tags.length; i++) {
			var tag = tags[i];
			s += "function " + tag + "() { return ElementWrapper._create(\"" + tag + "\", arguments); }";
		}
		return s;
	}()
);
var E = function (e) {
	if (typeof(e) == "string") {
		return new ElementWrapper(document.getElementById(e));
	} else if (e instanceof ElementWrapper) {
		return e;
	} else if (e.tagName) {
		return new ElementWrapper(e);
	}
};
var HTML = function (html) {
	var div = DIV();
	div.e.innerHTML = html;
	var children = div.children();
	if (children.length == 0) {
		return null;
	} else if (children.length == 1) {
		return children[0];
	} else {
		return children;
	}
};
var BODY = function () { return new ElementWrapper(document.getElementsByTagName("body")[0]); }
Coords = {
	getScrollOffset: function () {
		var de = document.documentElement;
		return { x: de.scrollLeft, y: de.scrollTop};
	},
	add: function (p1, p2) {
		var p = p1;
		if (p1.x != null) {
			if (p2.x != null) {
				p = { x: p1.x + p2.x, y: p1.y + p2.y };
			} else if (p2.width != null) {
				p = { x: p1.x + p2.width, y: p1.y + p2.height };
			}
		} else if (p1.width != null) {
			if (p2.width != null) {
				p = { width: p1.width + p2.width, y: p1.height + p2.height };
			}
		}
		return p;
	},
	sub: function (p1, p2) {
		if (p1.x != null) {
			if (p2.x != null) {
				return { width: p1.x - p2.x, height: p1.y - p2.y };
			} else if (p2.width != null) {
				return { x: p1.x - p2.width, y: p1.y - p2.height };
			}
		} else if (p1.width != null) {
			if (p2.width != null) {
				return { width: p1.width - p2.width, y: p1.height - p2.height };
			}
		}
		return p1;
	},
	getMousePosition: function (e) {
		if (e.pageX == null) {
			return this.add(this.getScrollOffset(), { x: e.x, y: e.y });
		} else {
			return { x: e.pageX, y: e.pageY };
		}
	},
	getLayerPosition: function (evt, elem) {
		var el = evt.srcElement || evt.target;
		var x = 0, y = 0;
		while (el && el != elem) {
			x += el.offsetLeft;
			y += el.offsetTop;
			el = el.parentNode;
		}
		return { x: x + (evt.offsetX != null ? evt.offsetX : evt.layerX), y: y + (evt.offsetY != null ? wvt.offsetY : evt.layerY) };
	},
	getDisplayRect: function () {
		var b1 = document.documentElement;
		var b2 = document.body;
		return {
			x: b1.scrollLeft,
			y: b1.scrollTop,
			width: (window.opera ? b2.clientWidth : b1.clientWidth),
			height: (window.opera ? b2.clientHeight : b1.clientHeight)
		};
	},
	getDocumentRect: function () {
		var b = document.documentElement;
		return { x: 0, y: 0, width: b.scrollWidth, height: b.scrollHeight };
	}
};
var Util = {
	iterate: function (array, func) {
		if (!array || array.length == 0) {
			return null;
		}
		var result = [];
		for (var i = 0; i < array.length; i++) {
			result[i] = func(array[i]);
		}
		return result;
	},
	addListener : function(e, type, fn) {
		if (e.addEventListener) {
			e.addEventListener(type, fn, false);
		} else if (e.attachEvent) {
			var f = function () { return fn.call(e, window.event); };
			e.attachEvent('on' + type, f);
		} else {
			e['on'+type] = function (e) { return fn.call(e, e ? e : window.event); };
		}
	},
	getElementsByClassName : function (tagName, className) {
		if (className == undefined) {
			className = tagName;
			tagName = "*";
		}
		var selects = document.getElementsByTagName(tagName);
		var elems = [];
		var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
		for (var i = 0; i < selects.length; i++) {
			var e = selects[i];
			var cn = e.className;
			if (cn.length == 0) continue;
			if (cn == className || cn.match(pattern)) {
				elems.push(e);
			}
		}
		return elems;
	}
}
