//<script>
/*
 * Ext JS Library 2.2
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

// Achtung !!! (beim Upgrade)
// Diese Zeile zur Prüfung nicht überbügeln und dann BlankImageUrl wieder setzen:
//		BLANK_IMAGE_URL: "res.ashx?res=SharedResources.ExtJs2.images.default.s.gif",
if (typeof Ext != 'undefined') alert("Achtung Ext Version " + Ext.version + " ist bereits eingebunden und es wird nun noch (mal) Ext 2.2 daruebergeladen.");



Ext = {
	version: "2.2"
};
window["undefined"] = window["undefined"];
Ext.apply = function(C, D, B) {
	if (B) {
		Ext.apply(C, B)
	}
	if (C && D && typeof D == "object") {
		for (var A in D) {
			C[A] = D[A]
		}
	}
	return C
}; (function() {
	var idSeed = 0;
	var ua = navigator.userAgent.toLowerCase();
	var isStrict = document.compatMode == "CSS1Compat",
	isOpera = ua.indexOf("opera") > -1,
	isSafari = (/webkit|khtml/).test(ua),
	isSafari3 = isSafari && ua.indexOf("webkit/5") != -1,
	isIE = !isOpera && ua.indexOf("msie") > -1,
	isIE7 = !isOpera && ua.indexOf("msie 7") > -1,
	isGecko = !isSafari && ua.indexOf("gecko") > -1,
	isGecko3 = !isSafari && ua.indexOf("rv:1.9") > -1,
	isBorderBox = isIE && !isStrict,
	isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
	isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
	isAir = (ua.indexOf("adobeair") != -1),
	isLinux = (ua.indexOf("linux") != -1),
	isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
	if (isIE && !isIE7) {
		try {
			document.execCommand("BackgroundImageCache", false, true)
		} catch(e) {}
	}
	Ext.apply(Ext, {
		isStrict: isStrict,
		isSecure: isSecure,
		isReady: false,
		enableGarbageCollector: true,
		enableListenerCollection: false,
		SSL_SECURE_URL: "javascript:false",
		BLANK_IMAGE_URL: "res.ashx?res=SharedResources.ExtJs2.images.default.s.gif",
		emptyFn: function() {},
		applyIf: function(o, c) {
			if (o && c) {
				for (var p in c) {
					if (typeof o[p] == "undefined") {
						o[p] = c[p]
					}
				}
			}
			return o
		},
		addBehaviors: function(o) {
			if (!Ext.isReady) {
				Ext.onReady(function() {
					Ext.addBehaviors(o)
				});
				return
			}
			var cache = {};
			for (var b in o) {
				var parts = b.split("@");
				if (parts[1]) {
					var s = parts[0];
					if (!cache[s]) {
						cache[s] = Ext.select(s)
					}
					cache[s].on(parts[1], o[b])
				}
			}
			cache = null
		},
		id: function(el, prefix) {
			prefix = prefix || "ext-gen";
			el = Ext.getDom(el);
			var id = prefix + (++idSeed);
			return el ? (el.id ? el.id: (el.id = id)) : id
		},
		extend: function() {
			var io = function(o) {
				for (var m in o) {
					this[m] = o[m]
				}
			};
			var oc = Object.prototype.constructor;
			return function(sb, sp, overrides) {
				if (typeof sp == "object") {
					overrides = sp;
					sp = sb;
					sb = overrides.constructor != oc ? overrides.constructor: function() {
						sp.apply(this, arguments)
					}
				}
				var F = function() {},
				sbp,
				spp = sp.prototype;
				F.prototype = spp;
				sbp = sb.prototype = new F();
				sbp.constructor = sb;
				sb.superclass = spp;
				if (spp.constructor == oc) {
					spp.constructor = sp
				}
				sb.override = function(o) {
					Ext.override(sb, o)
				};
				sbp.override = io;
				Ext.override(sb, overrides);
				sb.extend = function(o) {
					Ext.extend(sb, o)
				};
				return sb
			}
		} (),
		override: function(origclass, overrides) {
			if (overrides) {
				var p = origclass.prototype;
				for (var method in overrides) {
					p[method] = overrides[method]
				}
			}
		},
		namespace: function() {
			var a = arguments,
			o = null,
			i,
			j,
			d,
			rt;
			for (i = 0; i < a.length; ++i) {
				d = a[i].split(".");
				rt = d[0];
				eval("if (typeof " + rt + " == \"undefined\"){" + rt + " = {};} o = " + rt + ";");
				for (j = 1; j < d.length; ++j) {
					o[d[j]] = o[d[j]] || {};
					o = o[d[j]]
				}
			}
		},
		urlEncode: function(o) {
			if (!o) {
				return ""
			}
			var buf = [];
			for (var key in o) {
				var ov = o[key],
				k = encodeURIComponent(key);
				var type = typeof ov;
				if (type == "undefined") {
					buf.push(k, "=&")
				} else {
					if (type != "function" && type != "object") {
						buf.push(k, "=", encodeURIComponent(ov), "&")
					} else {
						if (Ext.isArray(ov)) {
							if (ov.length) {
								for (var i = 0, len = ov.length; i < len; i++) {
									buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? "": ov[i]), "&")
								}
							} else {
								buf.push(k, "=&")
							}
						}
					}
				}
			}
			buf.pop();
			return buf.join("")
		},
		urlDecode: function(string, overwrite) {
			if (!string || !string.length) {
				return {}
			}
			var obj = {};
			var pairs = string.split("&");
			var pair,
			name,
			value;
			for (var i = 0, len = pairs.length; i < len; i++) {
				pair = pairs[i].split("=");
				name = decodeURIComponent(pair[0]);
				value = decodeURIComponent(pair[1]);
				if (overwrite !== true) {
					if (typeof obj[name] == "undefined") {
						obj[name] = value
					} else {
						if (typeof obj[name] == "string") {
							obj[name] = [obj[name]];
							obj[name].push(value)
						} else {
							obj[name].push(value)
						}
					}
				} else {
					obj[name] = value
				}
			}
			return obj
		},
		each: function(array, fn, scope) {
			if (typeof array.length == "undefined" || typeof array == "string") {
				array = [array]
			}
			for (var i = 0, len = array.length; i < len; i++) {
				if (fn.call(scope || array[i], array[i], i, array) === false) {
					return i
				}
			}
		},
		combine: function() {
			var as = arguments,
			l = as.length,
			r = [];
			for (var i = 0; i < l; i++) {
				var a = as[i];
				if (Ext.isArray(a)) {
					r = r.concat(a)
				} else {
					if (a.length !== undefined && !a.substr) {
						r = r.concat(Array.prototype.slice.call(a, 0))
					} else {
						r.push(a)
					}
				}
			}
			return r
		},
		escapeRe: function(s) {
			return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1")
		},
		callback: function(cb, scope, args, delay) {
			if (typeof cb == "function") {
				if (delay) {
					cb.defer(delay, scope, args || [])
				} else {
					cb.apply(scope, args || [])
				}
			}
		},
		getDom: function(el) {
			if (!el || !document) {
				return null
			}
			return el.dom ? el.dom: (typeof el == "string" ? document.getElementById(el) : el)
		},
		getDoc: function() {
			return Ext.get(document)
		},
		getBody: function() {
			return Ext.get(document.body || document.documentElement)
		},
		getCmp: function(id) {
			return Ext.ComponentMgr.get(id)
		},
		num: function(v, defaultValue) {
			if (typeof v != "number") {
				return defaultValue
			}
			return v
		},
		destroy: function() {
			for (var i = 0, a = arguments, len = a.length; i < len; i++) {
				var as = a[i];
				if (as) {
					if (typeof as.destroy == "function") {
						as.destroy()
					} else {
						if (as.dom) {
							as.removeAllListeners();
							as.remove()
						}
					}
				}
			}
		},
		removeNode: isIE ?
		function() {
			var d;
			return function(n) {
				if (n && n.tagName != "BODY") {
					d = d || document.createElement("div");
					d.appendChild(n);
					d.innerHTML = ""
				}
			}
		} () : function(n) {
			if (n && n.parentNode && n.tagName != "BODY") {
				n.parentNode.removeChild(n)
			}
		},
		type: function(o) {
			if (o === undefined || o === null) {
				return false
			}
			if (o.htmlElement) {
				return "element"
			}
			var t = typeof o;
			if (t == "object" && o.nodeName) {
				switch (o.nodeType) {
				case 1:
					return "element";
				case 3:
					return (/\S/).test(o.nodeValue) ? "textnode": "whitespace"
				}
			}
			if (t == "object" || t == "function") {
				switch (o.constructor) {
				case Array:
					return "array";
				case RegExp:
					return "regexp"
				}
				if (typeof o.length == "number" && typeof o.item == "function") {
					return "nodelist"
				}
			}
			return t
		},
		isEmpty: function(v, allowBlank) {
			return v === null || v === undefined || (!allowBlank ? v === "": false)
		},
		value: function(v, defaultValue, allowBlank) {
			return Ext.isEmpty(v, allowBlank) ? defaultValue: v
		},
		isArray: function(v) {
			return v && typeof v.length == "number" && typeof v.splice == "function"
		},
		isDate: function(v) {
			return v && typeof v.getFullYear == "function"
		},
		isOpera: isOpera,
		isSafari: isSafari,
		isSafari3: isSafari3,
		isSafari2: isSafari && !isSafari3,
		isIE: isIE,
		isIE6: isIE && !isIE7,
		isIE7: isIE7,
		isGecko: isGecko,
		isGecko2: isGecko && !isGecko3,
		isGecko3: isGecko3,
		isBorderBox: isBorderBox,
		isLinux: isLinux,
		isWindows: isWindows,
		isMac: isMac,
		isAir: isAir,
		useShims: ((isIE && !isIE7) || (isMac && isGecko && !isGecko3))
	});
	Ext.ns = Ext.namespace
})();
Ext.ns("Ext", "Ext.util", "Ext.grid", "Ext.dd", "Ext.tree", "Ext.data", "Ext.form", "Ext.menu", "Ext.state", "Ext.lib", "Ext.layout", "Ext.app", "Ext.ux");
Ext.apply(Function.prototype, {
	createCallback: function() {
		var A = arguments;
		var B = this;
		return function() {
			return B.apply(window, A)
		}
	},
	createDelegate: function(C, B, A) {
		var D = this;
		return function() {
			var F = B || arguments;
			if (A === true) {
				F = Array.prototype.slice.call(arguments, 0);
				F = F.concat(B)
			} else {
				if (typeof A == "number") {
					F = Array.prototype.slice.call(arguments, 0);
					var E = [A, 0].concat(B);
					Array.prototype.splice.apply(F, E)
				}
			}
			return D.apply(C || window, F)
		}
	},
	defer: function(C, E, B, A) {
		var D = this.createDelegate(E, B, A);
		if (C) {
			return setTimeout(D, C)
		}
		D();
		return 0
	},
	createSequence: function(B, A) {
		if (typeof B != "function") {
			return this
		}
		var C = this;
		return function() {
			var D = C.apply(this || window, arguments);
			B.apply(A || this || window, arguments);
			return D
		}
	},
	createInterceptor: function(B, A) {
		if (typeof B != "function") {
			return this
		}
		var C = this;
		return function() {
			B.target = this;
			B.method = C;
			if (B.apply(A || this || window, arguments) === false) {
				return
			}
			return C.apply(this || window, arguments)
		}
	}
});
Ext.applyIf(String, {
	escape: function(A) {
		return A.replace(/('|\\)/g, "\\$1")
	},
	leftPad: function(D, B, C) {
		var A = new String(D);
		if (!C) {
			C = " "
		}
		while (A.length < B) {
			A = C + A
		}
		return A.toString()
	},
	format: function(B) {
		var A = Array.prototype.slice.call(arguments, 1);
		return B.replace(/\{(\d+)\}/g,
		function(C, D) {
			return A[D]
		})
	}
});
String.prototype.toggle = function(B, A) {
	return this == B ? A: B
};
String.prototype.trim = function() {
	var A = /^\s+|\s+$/g;
	return function() {
		return this.replace(A, "")
	}
} ();
Ext.applyIf(Number.prototype, {
	constrain: function(B, A) {
		return Math.min(Math.max(this, B), A)
	}
});
Ext.applyIf(Array.prototype, {
	indexOf: function(C) {
		for (var B = 0, A = this.length; B < A; B++) {
			if (this[B] == C) {
				return B
			}
		}
		return - 1
	},
	remove: function(B) {
		var A = this.indexOf(B);
		if (A != -1) {
			this.splice(A, 1)
		}
		return this
	}
});
Date.prototype.getElapsed = function(A) {
	return Math.abs((A || new Date()).getTime() - this.getTime())
}; (function() {
	var B;
	Ext.lib.Dom = {
		getViewWidth: function(E) {
			return E ? this.getDocumentWidth() : this.getViewportWidth()
		},
		getViewHeight: function(E) {
			return E ? this.getDocumentHeight() : this.getViewportHeight()
		},
		getDocumentHeight: function() {
			var E = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight: document.documentElement.scrollHeight;
			return Math.max(E, this.getViewportHeight())
		},
		getDocumentWidth: function() {
			var E = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth: document.documentElement.scrollWidth;
			return Math.max(E, this.getViewportWidth())
		},
		getViewportHeight: function() {
			if (Ext.isIE) {
				return Ext.isStrict ? document.documentElement.clientHeight: document.body.clientHeight
			} else {
				return self.innerHeight
			}
		},
		getViewportWidth: function() {
			if (Ext.isIE) {
				return Ext.isStrict ? document.documentElement.clientWidth: document.body.clientWidth
			} else {
				return self.innerWidth
			}
		},
		isAncestor: function(F, G) {
			F = Ext.getDom(F);
			G = Ext.getDom(G);
			if (!F || !G) {
				return false
			}
			if (F.contains && !Ext.isSafari) {
				return F.contains(G)
			} else {
				if (F.compareDocumentPosition) {
					return !! (F.compareDocumentPosition(G) & 16)
				} else {
					var E = G.parentNode;
					while (E) {
						if (E == F) {
							return true
						} else {
							if (!E.tagName || E.tagName.toUpperCase() == "HTML") {
								return false
							}
						}
						E = E.parentNode
					}
					return false
				}
			}
		},
		getRegion: function(E) {
			return Ext.lib.Region.getRegion(E)
		},
		getY: function(E) {
			return this.getXY(E)[1]
		},
		getX: function(E) {
			return this.getXY(E)[0]
		},
		getXY: function(G) {
			var F,
			K,
			M,
			N,
			J = (document.body || document.documentElement);
			G = Ext.getDom(G);
			if (G == J) {
				return [0, 0]
			}
			if (G.getBoundingClientRect) {
				M = G.getBoundingClientRect();
				N = C(document).getScroll();
				return [M.left + N.left, M.top + N.top]
			}
			var O = 0,
			L = 0;
			F = G;
			var E = C(G).getStyle("position") == "absolute";
			while (F) {
				O += F.offsetLeft;
				L += F.offsetTop;
				if (!E && C(F).getStyle("position") == "absolute") {
					E = true
				}
				if (Ext.isGecko) {
					K = C(F);
					var P = parseInt(K.getStyle("borderTopWidth"), 10) || 0;
					var H = parseInt(K.getStyle("borderLeftWidth"), 10) || 0;
					O += H;
					L += P;
					if (F != G && K.getStyle("overflow") != "visible") {
						O += H;
						L += P
					}
				}
				F = F.offsetParent
			}
			if (Ext.isSafari && E) {
				O -= J.offsetLeft;
				L -= J.offsetTop
			}
			if (Ext.isGecko && !E) {
				var I = C(J);
				O += parseInt(I.getStyle("borderLeftWidth"), 10) || 0;
				L += parseInt(I.getStyle("borderTopWidth"), 10) || 0
			}
			F = G.parentNode;
			while (F && F != J) {
				if (!Ext.isOpera || (F.tagName != "TR" && C(F).getStyle("display") != "inline")) {
					O -= F.scrollLeft;
					L -= F.scrollTop
				}
				F = F.parentNode
			}
			return [O, L]
		},
		setXY: function(E, F) {
			E = Ext.fly(E, "_setXY");
			E.position();
			var G = E.translatePoints(F);
			if (F[0] !== false) {
				E.dom.style.left = G.left + "px"
			}
			if (F[1] !== false) {
				E.dom.style.top = G.top + "px"
			}
		},
		setX: function(F, E) {
			this.setXY(F, [E, false])
		},
		setY: function(E, F) {
			this.setXY(E, [false, F])
		}
	};
	Ext.lib.Event = function() {
		var F = false;
		var G = [];
		var K = [];
		var I = 0;
		var H = [];
		var E = 0;
		var J = null;
		return {
			POLL_RETRYS: 200,
			POLL_INTERVAL: 20,
			EL: 0,
			TYPE: 1,
			FN: 2,
			WFN: 3,
			OBJ: 3,
			ADJ_SCOPE: 4,
			_interval: null,
			startInterval: function() {
				if (!this._interval) {
					var L = this;
					var M = function() {
						L._tryPreloadAttach()
					};
					this._interval = setInterval(M, this.POLL_INTERVAL)
				}
			},
			onAvailable: function(N, L, O, M) {
				H.push({
					id: N,
					fn: L,
					obj: O,
					override: M,
					checkReady: false
				});
				I = this.POLL_RETRYS;
				this.startInterval()
			},
			addListener: function(Q, M, P) {
				Q = Ext.getDom(Q);
				if (!Q || !P) {
					return false
				}
				if ("unload" == M) {
					K[K.length] = [Q, M, P];
					return true
				}
				var O = function(R) {
					return typeof Ext != "undefined" ? P(Ext.lib.Event.getEvent(R)) : false
				};
				var L = [Q, M, P, O];
				var N = G.length;
				G[N] = L;
				this.doAdd(Q, M, O, false);
				return true
			},
			removeListener: function(S, O, R) {
				var Q,
				N;
				S = Ext.getDom(S);
				if (!R) {
					return this.purgeElement(S, false, O)
				}
				if ("unload" == O) {
					for (Q = 0, N = K.length; Q < N; Q++) {
						var M = K[Q];
						if (M && M[0] == S && M[1] == O && M[2] == R) {
							K.splice(Q, 1);
							return true
						}
					}
					return false
				}
				var L = null;
				var P = arguments[3];
				if ("undefined" == typeof P) {
					P = this._getCacheIndex(S, O, R)
				}
				if (P >= 0) {
					L = G[P]
				}
				if (!S || !L) {
					return false
				}
				this.doRemove(S, O, L[this.WFN], false);
				delete G[P][this.WFN];
				delete G[P][this.FN];
				G.splice(P, 1);
				return true
			},
			getTarget: function(N, M) {
				N = N.browserEvent || N;
				var L = N.target || N.srcElement;
				return this.resolveTextNode(L)
			},
			resolveTextNode: function(L) {
				if (Ext.isSafari && L && 3 == L.nodeType) {
					return L.parentNode
				} else {
					return L
				}
			},
			getPageX: function(M) {
				M = M.browserEvent || M;
				var L = M.pageX;
				if (!L && 0 !== L) {
					L = M.clientX || 0;
					if (Ext.isIE) {
						L += this.getScroll()[1]
					}
				}
				return L
			},
			getPageY: function(L) {
				L = L.browserEvent || L;
				var M = L.pageY;
				if (!M && 0 !== M) {
					M = L.clientY || 0;
					if (Ext.isIE) {
						M += this.getScroll()[0]
					}
				}
				return M
			},
			getXY: function(L) {
				L = L.browserEvent || L;
				return [this.getPageX(L), this.getPageY(L)]
			},
			getRelatedTarget: function(M) {
				M = M.browserEvent || M;
				var L = M.relatedTarget;
				if (!L) {
					if (M.type == "mouseout") {
						L = M.toElement
					} else {
						if (M.type == "mouseover") {
							L = M.fromElement
						}
					}
				}
				return this.resolveTextNode(L)
			},
			getTime: function(N) {
				N = N.browserEvent || N;
				if (!N.time) {
					var M = new Date().getTime();
					try {
						N.time = M
					} catch(L) {
						this.lastError = L;
						return M
					}
				}
				return N.time
			},
			stopEvent: function(L) {
				this.stopPropagation(L);
				this.preventDefault(L)
			},
			stopPropagation: function(L) {
				L = L.browserEvent || L;
				if (L.stopPropagation) {
					L.stopPropagation()
				} else {
					L.cancelBubble = true
				}
			},
			preventDefault: function(L) {
				L = L.browserEvent || L;
				if (L.preventDefault) {
					L.preventDefault()
				} else {
					L.returnValue = false
				}
			},
			getEvent: function(M) {
				var L = M || window.event;
				if (!L) {
					var N = this.getEvent.caller;
					while (N) {
						L = N.arguments[0];
						if (L && Event == L.constructor) {
							break
						}
						N = N.caller
					}
				}
				return L
			},
			getCharCode: function(L) {
				L = L.browserEvent || L;
				return L.charCode || L.keyCode || 0
			},
			_getCacheIndex: function(Q, N, P) {
				for (var O = 0, M = G.length; O < M; ++O) {
					var L = G[O];
					if (L && L[this.FN] == P && L[this.EL] == Q && L[this.TYPE] == N) {
						return O
					}
				}
				return - 1
			},
			elCache: {},
			getEl: function(L) {
				return document.getElementById(L)
			},
			clearCache: function() {},
			_load: function(M) {
				F = true;
				var L = Ext.lib.Event;
				if (Ext.isIE) {
					L.doRemove(window, "load", L._load)
				}
			},
			_tryPreloadAttach: function() {
				if (this.locked) {
					return false
				}
				this.locked = true;
				var R = !F;
				if (!R) {
					R = (I > 0)
				}
				var Q = [];
				for (var M = 0, L = H.length; M < L; ++M) {
					var P = H[M];
					if (P) {
						var O = this.getEl(P.id);
						if (O) {
							if (!P.checkReady || F || O.nextSibling || (document && document.body)) {
								var N = O;
								if (P.override) {
									if (P.override === true) {
										N = P.obj
									} else {
										N = P.override
									}
								}
								P.fn.call(N, P.obj);
								H[M] = null
							}
						} else {
							Q.push(P)
						}
					}
				}
				I = (Q.length === 0) ? 0: I - 1;
				if (R) {
					this.startInterval()
				} else {
					clearInterval(this._interval);
					this._interval = null
				}
				this.locked = false;
				return true
			},
			purgeElement: function(P, Q, N) {
				var R = this.getListeners(P, N);
				if (R) {
					for (var O = 0, L = R.length; O < L; ++O) {
						var M = R[O];
						this.removeListener(P, M.type, M.fn)
					}
				}
				if (Q && P && P.childNodes) {
					for (O = 0, L = P.childNodes.length; O < L; ++O) {
						this.purgeElement(P.childNodes[O], Q, N)
					}
				}
			},
			getListeners: function(M, R) {
				var P = [],
				L;
				if (!R) {
					L = [G, K]
				} else {
					if (R == "unload") {
						L = [K]
					} else {
						L = [G]
					}
				}
				for (var O = 0; O < L.length; ++O) {
					var T = L[O];
					if (T && T.length > 0) {
						for (var Q = 0, S = T.length; Q < S; ++Q) {
							var N = T[Q];
							if (N && N[this.EL] === M && (!R || R === N[this.TYPE])) {
								P.push({
									type: N[this.TYPE],
									fn: N[this.FN],
									obj: N[this.OBJ],
									adjust: N[this.ADJ_SCOPE],
									index: Q
								})
							}
						}
					}
				}
				return (P.length) ? P: null
			},
			_unload: function(S) {
				var R = Ext.lib.Event,
				P,
				O,
				M,
				L,
				N;
				for (P = 0, L = K.length; P < L; ++P) {
					M = K[P];
					if (M) {
						var Q = window;
						if (M[R.ADJ_SCOPE]) {
							if (M[R.ADJ_SCOPE] === true) {
								Q = M[R.OBJ]
							} else {
								Q = M[R.ADJ_SCOPE]
							}
						}
						M[R.FN].call(Q, R.getEvent(S), M[R.OBJ]);
						K[P] = null;
						M = null;
						Q = null
					}
				}
				K = null;
				if (G && G.length > 0) {
					O = G.length;
					while (O) {
						N = O - 1;
						M = G[N];
						if (M) {
							R.removeListener(M[R.EL], M[R.TYPE], M[R.FN], N)
						}
						O = O - 1
					}
					M = null;
					R.clearCache()
				}
				R.doRemove(window, "unload", R._unload)
			},
			getScroll: function() {
				var L = document.documentElement,
				M = document.body;
				if (L && (L.scrollTop || L.scrollLeft)) {
					return [L.scrollTop, L.scrollLeft]
				} else {
					if (M) {
						return [M.scrollTop, M.scrollLeft]
					} else {
						return [0, 0]
					}
				}
			},
			doAdd: function() {
				if (window.addEventListener) {
					return function(O, M, N, L) {
						O.addEventListener(M, N, (L))
					}
				} else {
					if (window.attachEvent) {
						return function(O, M, N, L) {
							O.attachEvent("on" + M, N)
						}
					} else {
						return function() {}
					}
				}
			} (),
			doRemove: function() {
				if (window.removeEventListener) {
					return function(O, M, N, L) {
						O.removeEventListener(M, N, (L))
					}
				} else {
					if (window.detachEvent) {
						return function(N, L, M) {
							N.detachEvent("on" + L, M)
						}
					} else {
						return function() {}
					}
				}
			} ()
		}
	} ();
	var D = Ext.lib.Event;
	D.on = D.addListener;
	D.un = D.removeListener;
	if (document && document.body) {
		D._load()
	} else {
		D.doAdd(window, "load", D._load)
	}
	D.doAdd(window, "unload", D._unload);
	D._tryPreloadAttach();
	Ext.lib.Ajax = {
		request: function(K, I, E, J, F) {
			if (F) {
				var G = F.headers;
				if (G) {
					for (var H in G) {
						if (G.hasOwnProperty(H)) {
							this.initHeader(H, G[H], false)
						}
					}
				}
				if (F.xmlData) {
					if (!G || !G["Content-Type"]) {
						this.initHeader("Content-Type", "text/xml", false)
					}
					K = (K ? K: (F.method ? F.method: "POST"));
					J = F.xmlData
				} else {
					if (F.jsonData) {
						if (!G || !G["Content-Type"]) {
							this.initHeader("Content-Type", "application/json", false)
						}
						K = (K ? K: (F.method ? F.method: "POST"));
						J = typeof F.jsonData == "object" ? Ext.encode(F.jsonData) : F.jsonData
					}
				}
			}
			return this.asyncRequest(K, I, E, J)
		},
		serializeForm: function(F) {
			if (typeof F == "string") {
				F = (document.getElementById(F) || document.forms[F])
			}
			var G,
			E,
			H,
			J,
			K = "",
			M = false;
			for (var L = 0; L < F.elements.length; L++) {
				G = F.elements[L];
				J = F.elements[L].disabled;
				E = F.elements[L].name;
				H = F.elements[L].value;
				if (!J && E) {
					switch (G.type) {
					case "select-one":
					case "select-multiple":
						for (var I = 0; I < G.options.length; I++) {
							if (G.options[I].selected) {
								if (Ext.isIE) {
									K += encodeURIComponent(E) + "=" + encodeURIComponent(G.options[I].attributes["value"].specified ? G.options[I].value: G.options[I].text) + "&"
								} else {
									K += encodeURIComponent(E) + "=" + encodeURIComponent(G.options[I].hasAttribute("value") ? G.options[I].value: G.options[I].text) + "&"
								}
							}
						}
						break;
					case "radio":
					case "checkbox":
						if (G.checked) {
							K += encodeURIComponent(E) + "=" + encodeURIComponent(H) + "&"
						}
						break;
					case "file":
					case undefined:
					case "reset":
					case "button":
						break;
					case "submit":
						if (M == false) {
							K += encodeURIComponent(E) + "=" + encodeURIComponent(H) + "&";
							M = true
						}
						break;
					default:
						K += encodeURIComponent(E) + "=" + encodeURIComponent(H) + "&";
						break
					}
				}
			}
			K = K.substr(0, K.length - 1);
			return K
		},
		headers: {},
		hasHeaders: false,
		useDefaultHeader: true,
		defaultPostHeader: "application/x-www-form-urlencoded; charset=UTF-8",
		useDefaultXhrHeader: true,
		defaultXhrHeader: "XMLHttpRequest",
		hasDefaultHeaders: true,
		defaultHeaders: {},
		poll: {},
		timeout: {},
		pollInterval: 50,
		transactionId: 0,
		setProgId: function(E) {
			this.activeX.unshift(E)
		},
		setDefaultPostHeader: function(E) {
			this.useDefaultHeader = E
		},
		setDefaultXhrHeader: function(E) {
			this.useDefaultXhrHeader = E
		},
		setPollingInterval: function(E) {
			if (typeof E == "number" && isFinite(E)) {
				this.pollInterval = E
			}
		},
		createXhrObject: function(I) {
			var H,
			E;
			try {
				E = new XMLHttpRequest();
				H = {
					conn: E,
					tId: I
				}
			} catch(G) {
				for (var F = 0; F < this.activeX.length; ++F) {
					try {
						E = new ActiveXObject(this.activeX[F]);
						H = {
							conn: E,
							tId: I
						};
						break
					} catch(G) {}
				}
			} finally {
				return H
			}
		},
		getConnectionObject: function() {
			var F;
			var G = this.transactionId;
			try {
				F = this.createXhrObject(G);
				if (F) {
					this.transactionId++
				}
			} catch(E) {} finally {
				return F
			}
		},
		asyncRequest: function(I, F, H, E) {
			var G = this.getConnectionObject();
			if (!G) {
				return null
			} else {
				G.conn.open(I, F, true);
				if (this.useDefaultXhrHeader) {
					if (!this.defaultHeaders["X-Requested-With"]) {
						this.initHeader("X-Requested-With", this.defaultXhrHeader, true)
					}
				}
				if (E && this.useDefaultHeader && (!this.hasHeaders || !this.headers["Content-Type"])) {
					this.initHeader("Content-Type", this.defaultPostHeader)
				}
				if (this.hasDefaultHeaders || this.hasHeaders) {
					this.setHeader(G)
				}
				this.handleReadyState(G, H);
				G.conn.send(E || null);
				return G
			}
		},
		handleReadyState: function(F, G) {
			var E = this;
			if (G && G.timeout) {
				this.timeout[F.tId] = window.setTimeout(function() {
					E.abort(F, G, true)
				},
				G.timeout)
			}
			this.poll[F.tId] = window.setInterval(function() {
				if (F.conn && F.conn.readyState == 4) {
					window.clearInterval(E.poll[F.tId]);
					delete E.poll[F.tId];
					if (G && G.timeout) {
						window.clearTimeout(E.timeout[F.tId]);
						delete E.timeout[F.tId]
					}
					E.handleTransactionResponse(F, G)
				}
			},
			this.pollInterval)
		},
		handleTransactionResponse: function(I, J, E) {
			if (!J) {
				this.releaseObject(I);
				return
			}
			var G,
			F;
			try {
				if (I.conn.status !== undefined && I.conn.status != 0) {
					G = I.conn.status
				} else {
					G = 13030
				}
			} catch(H) {
				G = 13030
			}
			if (G >= 200 && G < 300) {
				F = this.createResponseObject(I, J.argument);
				if (J.success) {
					if (!J.scope) {
						J.success(F)
					} else {
						J.success.apply(J.scope, [F])
					}
				}
			} else {
				switch (G) {
				case 12002:
				case 12029:
				case 12030:
				case 12031:
				case 12152:
				case 13030:
					F = this.createExceptionObject(I.tId, J.argument, (E ? E: false));
					if (J.failure) {
						if (!J.scope) {
							J.failure(F)
						} else {
							J.failure.apply(J.scope, [F])
						}
					}
					break;
				default:
					F = this.createResponseObject(I, J.argument);
					if (J.failure) {
						if (!J.scope) {
							J.failure(F)
						} else {
							J.failure.apply(J.scope, [F])
						}
					}
				}
			}
			this.releaseObject(I);
			F = null
		},
		createResponseObject: function(E, K) {
			var H = {};
			var M = {};
			try {
				var G = E.conn.getAllResponseHeaders();
				var J = G.split("\n");
				for (var I = 0; I < J.length; I++) {
					var F = J[I].indexOf(":");
					if (F != -1) {
						M[J[I].substring(0, F)] = J[I].substring(F + 2)
					}
				}
			} catch(L) {}
			H.tId = E.tId;
			H.status = E.conn.status;
			H.statusText = E.conn.statusText;
			H.getResponseHeader = M;
			H.getAllResponseHeaders = G;
			H.responseText = E.conn.responseText;
			H.responseXML = E.conn.responseXML;
			if (typeof K !== undefined) {
				H.argument = K
			}
			return H
		},
		createExceptionObject: function(L, H, E) {
			var J = 0;
			var K = "communication failure";
			var G = -1;
			var F = "transaction aborted";
			var I = {};
			I.tId = L;
			if (E) {
				I.status = G;
				I.statusText = F
			} else {
				I.status = J;
				I.statusText = K
			}
			if (H) {
				I.argument = H
			}
			return I
		},
		initHeader: function(E, H, G) {
			var F = (G) ? this.defaultHeaders: this.headers;
			if (F[E] === undefined) {
				F[E] = H
			} else {
				F[E] = H + "," + F[E]
			}
			if (G) {
				this.hasDefaultHeaders = true
			} else {
				this.hasHeaders = true
			}
		},
		setHeader: function(E) {
			if (this.hasDefaultHeaders) {
				for (var F in this.defaultHeaders) {
					if (this.defaultHeaders.hasOwnProperty(F)) {
						E.conn.setRequestHeader(F, this.defaultHeaders[F])
					}
				}
			}
			if (this.hasHeaders) {
				for (var F in this.headers) {
					if (this.headers.hasOwnProperty(F)) {
						E.conn.setRequestHeader(F, this.headers[F])
					}
				}
				this.headers = {};
				this.hasHeaders = false
			}
		},
		resetDefaultHeaders: function() {
			delete this.defaultHeaders;
			this.defaultHeaders = {};
			this.hasDefaultHeaders = false
		},
		abort: function(F, G, E) {
			if (this.isCallInProgress(F)) {
				F.conn.abort();
				window.clearInterval(this.poll[F.tId]);
				delete this.poll[F.tId];
				if (E) {
					delete this.timeout[F.tId]
				}
				this.handleTransactionResponse(F, G, true);
				return true
			} else {
				return false
			}
		},
		isCallInProgress: function(E) {
			if (E.conn) {
				return E.conn.readyState != 4 && E.conn.readyState != 0
			} else {
				return false
			}
		},
		releaseObject: function(E) {
			E.conn = null;
			E = null
		},
		activeX: ["MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]
	};
	Ext.lib.Region = function(G, H, E, F) {
		this.top = G;
		this[1] = G;
		this.right = H;
		this.bottom = E;
		this.left = F;
		this[0] = F
	};
	Ext.lib.Region.prototype = {
		contains: function(E) {
			return (E.left >= this.left && E.right <= this.right && E.top >= this.top && E.bottom <= this.bottom)
		},
		getArea: function() {
			return ((this.bottom - this.top) * (this.right - this.left))
		},
		intersect: function(I) {
			var G = Math.max(this.top, I.top);
			var H = Math.min(this.right, I.right);
			var E = Math.min(this.bottom, I.bottom);
			var F = Math.max(this.left, I.left);
			if (E >= G && H >= F) {
				return new Ext.lib.Region(G, H, E, F)
			} else {
				return null
			}
		},
		union: function(I) {
			var G = Math.min(this.top, I.top);
			var H = Math.max(this.right, I.right);
			var E = Math.max(this.bottom, I.bottom);
			var F = Math.min(this.left, I.left);
			return new Ext.lib.Region(G, H, E, F)
		},
		constrainTo: function(E) {
			this.top = this.top.constrain(E.top, E.bottom);
			this.bottom = this.bottom.constrain(E.top, E.bottom);
			this.left = this.left.constrain(E.left, E.right);
			this.right = this.right.constrain(E.left, E.right);
			return this
		},
		adjust: function(G, F, E, H) {
			this.top += G;
			this.left += F;
			this.right += H;
			this.bottom += E;
			return this
		}
	};
	Ext.lib.Region.getRegion = function(H) {
		var J = Ext.lib.Dom.getXY(H);
		var G = J[1];
		var I = J[0] + H.offsetWidth;
		var E = J[1] + H.offsetHeight;
		var F = J[0];
		return new Ext.lib.Region(G, I, E, F)
	};
	Ext.lib.Point = function(E, F) {
		if (Ext.isArray(E)) {
			F = E[1];
			E = E[0]
		}
		this.x = this.right = this.left = this[0] = E;
		this.y = this.top = this.bottom = this[1] = F
	};
	Ext.lib.Point.prototype = new Ext.lib.Region();
	Ext.lib.Anim = {
		scroll: function(H, F, I, J, E, G) {
			return this.run(H, F, I, J, E, G, Ext.lib.Scroll)
		},
		motion: function(H, F, I, J, E, G) {
			return this.run(H, F, I, J, E, G, Ext.lib.Motion)
		},
		color: function(H, F, I, J, E, G) {
			return this.run(H, F, I, J, E, G, Ext.lib.ColorAnim)
		},
		run: function(I, F, K, L, E, H, G) {
			G = G || Ext.lib.AnimBase;
			if (typeof L == "string") {
				L = Ext.lib.Easing[L]
			}
			var J = new G(I, F, K, L);
			J.animateX(function() {
				Ext.callback(E, H)
			});
			return J
		}
	};
	function C(E) {
		if (!B) {
			B = new Ext.Element.Flyweight()
		}
		B.dom = E;
		return B
	}
	if (Ext.isIE) {
		function A() {
			var E = Function.prototype;
			delete E.createSequence;
			delete E.defer;
			delete E.createDelegate;
			delete E.createCallback;
			delete E.createInterceptor;
			window.detachEvent("onunload", A)
		}
		window.attachEvent("onunload", A)
	}
	Ext.lib.AnimBase = function(F, E, G, H) {
		if (F) {
			this.init(F, E, G, H)
		}
	};
	Ext.lib.AnimBase.prototype = {
		toString: function() {
			var E = this.getEl();
			var F = E.id || E.tagName;
			return ("Anim " + F)
		},
		patterns: {
			noNegatives: /width|height|opacity|padding/i,
			offsetAttribute: /^((width|height)|(top|left))$/,
			defaultUnit: /width|height|top$|bottom$|left$|right$/i,
			offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
		},
		doMethod: function(E, G, F) {
			return this.method(this.currentFrame, G, F - G, this.totalFrames)
		},
		setAttribute: function(E, G, F) {
			if (this.patterns.noNegatives.test(E)) {
				G = (G > 0) ? G: 0
			}
			Ext.fly(this.getEl(), "_anim").setStyle(E, G + F)
		},
		getAttribute: function(E) {
			var G = this.getEl();
			var I = C(G).getStyle(E);
			if (I !== "auto" && !this.patterns.offsetUnit.test(I)) {
				return parseFloat(I)
			}
			var F = this.patterns.offsetAttribute.exec(E) || [];
			var J = !!(F[3]);
			var H = !!(F[2]);
			if (H || (C(G).getStyle("position") == "absolute" && J)) {
				I = G["offset" + F[0].charAt(0).toUpperCase() + F[0].substr(1)]
			} else {
				I = 0
			}
			return I
		},
		getDefaultUnit: function(E) {
			if (this.patterns.defaultUnit.test(E)) {
				return "px"
			}
			return ""
		},
		animateX: function(G, E) {
			var F = function() {
				this.onComplete.removeListener(F);
				if (typeof G == "function") {
					G.call(E || this, this)
				}
			};
			this.onComplete.addListener(F, this);
			this.animate()
		},
		setRuntimeAttribute: function(F) {
			var K;
			var G;
			var H = this.attributes;
			this.runtimeAttributes[F] = {};
			var J = function(L) {
				return (typeof L !== "undefined")
			};
			if (!J(H[F]["to"]) && !J(H[F]["by"])) {
				return false
			}
			K = (J(H[F]["from"])) ? H[F]["from"] : this.getAttribute(F);
			if (J(H[F]["to"])) {
				G = H[F]["to"]
			} else {
				if (J(H[F]["by"])) {
					if (K.constructor == Array) {
						G = [];
						for (var I = 0, E = K.length; I < E; ++I) {
							G[I] = K[I] + H[F]["by"][I]
						}
					} else {
						G = K + H[F]["by"]
					}
				}
			}
			this.runtimeAttributes[F].start = K;
			this.runtimeAttributes[F].end = G;
			this.runtimeAttributes[F].unit = (J(H[F].unit)) ? H[F]["unit"] : this.getDefaultUnit(F)
		},
		init: function(G, L, K, E) {
			var F = false;
			var H = null;
			var J = 0;
			G = Ext.getDom(G);
			this.attributes = L || {};
			this.duration = K || 1;
			this.method = E || Ext.lib.Easing.easeNone;
			this.useSeconds = true;
			this.currentFrame = 0;
			this.totalFrames = Ext.lib.AnimMgr.fps;
			this.getEl = function() {
				return G
			};
			this.isAnimated = function() {
				return F
			};
			this.getStartTime = function() {
				return H
			};
			this.runtimeAttributes = {};
			this.animate = function() {
				if (this.isAnimated()) {
					return false
				}
				this.currentFrame = 0;
				this.totalFrames = (this.useSeconds) ? Math.ceil(Ext.lib.AnimMgr.fps * this.duration) : this.duration;
				Ext.lib.AnimMgr.registerElement(this)
			};
			this.stop = function(O) {
				if (O) {
					this.currentFrame = this.totalFrames;
					this._onTween.fire()
				}
				Ext.lib.AnimMgr.stop(this)
			};
			var N = function() {
				this.onStart.fire();
				this.runtimeAttributes = {};
				for (var O in this.attributes) {
					this.setRuntimeAttribute(O)
				}
				F = true;
				J = 0;
				H = new Date()
			};
			var M = function() {
				var Q = {
					duration: new Date() - this.getStartTime(),
					currentFrame: this.currentFrame
				};
				Q.toString = function() {
					return ("duration: " + Q.duration + ", currentFrame: " + Q.currentFrame)
				};
				this.onTween.fire(Q);
				var P = this.runtimeAttributes;
				for (var O in P) {
					this.setAttribute(O, this.doMethod(O, P[O].start, P[O].end), P[O].unit)
				}
				J += 1
			};
			var I = function() {
				var O = (new Date() - H) / 1000;
				var P = {
					duration: O,
					frames: J,
					fps: J / O
				};
				P.toString = function() {
					return ("duration: " + P.duration + ", frames: " + P.frames + ", fps: " + P.fps)
				};
				F = false;
				J = 0;
				this.onComplete.fire(P)
			};
			this._onStart = new Ext.util.Event(this);
			this.onStart = new Ext.util.Event(this);
			this.onTween = new Ext.util.Event(this);
			this._onTween = new Ext.util.Event(this);
			this.onComplete = new Ext.util.Event(this);
			this._onComplete = new Ext.util.Event(this);
			this._onStart.addListener(N);
			this._onTween.addListener(M);
			this._onComplete.addListener(I)
		}
	};
	Ext.lib.AnimMgr = new
	function() {
		var G = null;
		var F = [];
		var E = 0;
		this.fps = 1000;
		this.delay = 1;
		this.registerElement = function(J) {
			F[F.length] = J;
			E += 1;
			J._onStart.fire();
			this.start()
		};
		this.unRegister = function(K, J) {
			K._onComplete.fire();
			J = J || I(K);
			if (J != -1) {
				F.splice(J, 1)
			}
			E -= 1;
			if (E <= 0) {
				this.stop()
			}
		};
		this.start = function() {
			if (G === null) {
				G = setInterval(this.run, this.delay)
			}
		};
		this.stop = function(L) {
			if (!L) {
				clearInterval(G);
				for (var K = 0, J = F.length; K < J; ++K) {
					if (F[0].isAnimated()) {
						this.unRegister(F[0], 0)
					}
				}
				F = [];
				G = null;
				E = 0
			} else {
				this.unRegister(L)
			}
		};
		this.run = function() {
			for (var L = 0, J = F.length; L < J; ++L) {
				var K = F[L];
				if (!K || !K.isAnimated()) {
					continue
				}
				if (K.currentFrame < K.totalFrames || K.totalFrames === null) {
					K.currentFrame += 1;
					if (K.useSeconds) {
						H(K)
					}
					K._onTween.fire()
				} else {
					Ext.lib.AnimMgr.stop(K, L)
				}
			}
		};
		var I = function(L) {
			for (var K = 0, J = F.length; K < J; ++K) {
				if (F[K] == L) {
					return K
				}
			}
			return - 1
		};
		var H = function(K) {
			var N = K.totalFrames;
			var M = K.currentFrame;
			var L = (K.currentFrame * K.duration * 1000 / K.totalFrames);
			var J = (new Date() - K.getStartTime());
			var O = 0;
			if (J < K.duration * 1000) {
				O = Math.round((J / L - 1) * K.currentFrame)
			} else {
				O = N - (M + 1)
			}
			if (O > 0 && isFinite(O)) {
				if (K.currentFrame + O >= N) {
					O = N - (M + 1)
				}
				K.currentFrame += O
			}
		}
	};
	Ext.lib.Bezier = new
	function() {
		this.getPosition = function(I, H) {
			var J = I.length;
			var G = [];
			for (var F = 0; F < J; ++F) {
				G[F] = [I[F][0], I[F][1]]
			}
			for (var E = 1; E < J; ++E) {
				for (F = 0; F < J - E; ++F) {
					G[F][0] = (1 - H) * G[F][0] + H * G[parseInt(F + 1, 10)][0];
					G[F][1] = (1 - H) * G[F][1] + H * G[parseInt(F + 1, 10)][1]
				}
			}
			return [G[0][0], G[0][1]]
		}
	}; (function() {
		Ext.lib.ColorAnim = function(I, H, J, K) {
			Ext.lib.ColorAnim.superclass.constructor.call(this, I, H, J, K)
		};
		Ext.extend(Ext.lib.ColorAnim, Ext.lib.AnimBase);
		var F = Ext.lib;
		var G = F.ColorAnim.superclass;
		var E = F.ColorAnim.prototype;
		E.toString = function() {
			var H = this.getEl();
			var I = H.id || H.tagName;
			return ("ColorAnim " + I)
		};
		E.patterns.color = /color$/i;
		E.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
		E.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
		E.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
		E.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
		E.parseColor = function(H) {
			if (H.length == 3) {
				return H
			}
			var I = this.patterns.hex.exec(H);
			if (I && I.length == 4) {
				return [parseInt(I[1], 16), parseInt(I[2], 16), parseInt(I[3], 16)]
			}
			I = this.patterns.rgb.exec(H);
			if (I && I.length == 4) {
				return [parseInt(I[1], 10), parseInt(I[2], 10), parseInt(I[3], 10)]
			}
			I = this.patterns.hex3.exec(H);
			if (I && I.length == 4) {
				return [parseInt(I[1] + I[1], 16), parseInt(I[2] + I[2], 16), parseInt(I[3] + I[3], 16)]
			}
			return null
		};
		E.getAttribute = function(H) {
			var J = this.getEl();
			if (this.patterns.color.test(H)) {
				var K = C(J).getStyle(H);
				if (this.patterns.transparent.test(K)) {
					var I = J.parentNode;
					K = C(I).getStyle(H);
					while (I && this.patterns.transparent.test(K)) {
						I = I.parentNode;
						K = C(I).getStyle(H);
						if (I.tagName.toUpperCase() == "HTML") {
							K = "#fff"
						}
					}
				}
			} else {
				K = G.getAttribute.call(this, H)
			}
			return K
		};
		E.doMethod = function(I, M, J) {
			var L;
			if (this.patterns.color.test(I)) {
				L = [];
				for (var K = 0, H = M.length; K < H; ++K) {
					L[K] = G.doMethod.call(this, I, M[K], J[K])
				}
				L = "rgb(" + Math.floor(L[0]) + "," + Math.floor(L[1]) + "," + Math.floor(L[2]) + ")"
			} else {
				L = G.doMethod.call(this, I, M, J)
			}
			return L
		};
		E.setRuntimeAttribute = function(I) {
			G.setRuntimeAttribute.call(this, I);
			if (this.patterns.color.test(I)) {
				var K = this.attributes;
				var M = this.parseColor(this.runtimeAttributes[I].start);
				var J = this.parseColor(this.runtimeAttributes[I].end);
				if (typeof K[I]["to"] === "undefined" && typeof K[I]["by"] !== "undefined") {
					J = this.parseColor(K[I].by);
					for (var L = 0, H = M.length; L < H; ++L) {
						J[L] = M[L] + J[L]
					}
				}
				this.runtimeAttributes[I].start = M;
				this.runtimeAttributes[I].end = J
			}
		}
	})();
	Ext.lib.Easing = {
		easeNone: function(F, E, H, G) {
			return H * F / G + E
		},
		easeIn: function(F, E, H, G) {
			return H * (F /= G) * F + E
		},
		easeOut: function(F, E, H, G) {
			return - H * (F /= G) * (F - 2) + E
		},
		easeBoth: function(F, E, H, G) {
			if ((F /= G / 2) < 1) {
				return H / 2 * F * F + E
			}
			return - H / 2 * ((--F) * (F - 2) - 1) + E
		},
		easeInStrong: function(F, E, H, G) {
			return H * (F /= G) * F * F * F + E
		},
		easeOutStrong: function(F, E, H, G) {
			return - H * ((F = F / G - 1) * F * F * F - 1) + E
		},
		easeBothStrong: function(F, E, H, G) {
			if ((F /= G / 2) < 1) {
				return H / 2 * F * F * F * F + E
			}
			return - H / 2 * ((F -= 2) * F * F * F - 2) + E
		},
		elasticIn: function(G, E, K, J, F, I) {
			if (G == 0) {
				return E
			}
			if ((G /= J) == 1) {
				return E + K
			}
			if (!I) {
				I = J * 0.3
			}
			if (!F || F < Math.abs(K)) {
				F = K;
				var H = I / 4
			} else {
				var H = I / (2 * Math.PI) * Math.asin(K / F)
			}
			return - (F * Math.pow(2, 10 * (G -= 1)) * Math.sin((G * J - H) * (2 * Math.PI) / I)) + E
		},
		elasticOut: function(G, E, K, J, F, I) {
			if (G == 0) {
				return E
			}
			if ((G /= J) == 1) {
				return E + K
			}
			if (!I) {
				I = J * 0.3
			}
			if (!F || F < Math.abs(K)) {
				F = K;
				var H = I / 4
			} else {
				var H = I / (2 * Math.PI) * Math.asin(K / F)
			}
			return F * Math.pow(2, -10 * G) * Math.sin((G * J - H) * (2 * Math.PI) / I) + K + E
		},
		elasticBoth: function(G, E, K, J, F, I) {
			if (G == 0) {
				return E
			}
			if ((G /= J / 2) == 2) {
				return E + K
			}
			if (!I) {
				I = J * (0.3 * 1.5)
			}
			if (!F || F < Math.abs(K)) {
				F = K;
				var H = I / 4
			} else {
				var H = I / (2 * Math.PI) * Math.asin(K / F)
			}
			if (G < 1) {
				return - 0.5 * (F * Math.pow(2, 10 * (G -= 1)) * Math.sin((G * J - H) * (2 * Math.PI) / I)) + E
			}
			return F * Math.pow(2, -10 * (G -= 1)) * Math.sin((G * J - H) * (2 * Math.PI) / I) * 0.5 + K + E
		},
		backIn: function(F, E, I, H, G) {
			if (typeof G == "undefined") {
				G = 1.70158
			}
			return I * (F /= H) * F * ((G + 1) * F - G) + E
		},
		backOut: function(F, E, I, H, G) {
			if (typeof G == "undefined") {
				G = 1.70158
			}
			return I * ((F = F / H - 1) * F * ((G + 1) * F + G) + 1) + E
		},
		backBoth: function(F, E, I, H, G) {
			if (typeof G == "undefined") {
				G = 1.70158
			}
			if ((F /= H / 2) < 1) {
				return I / 2 * (F * F * (((G *= (1.525)) + 1) * F - G)) + E
			}
			return I / 2 * ((F -= 2) * F * (((G *= (1.525)) + 1) * F + G) + 2) + E
		},
		bounceIn: function(F, E, H, G) {
			return H - Ext.lib.Easing.bounceOut(G - F, 0, H, G) + E
		},
		bounceOut: function(F, E, H, G) {
			if ((F /= G) < (1 / 2.75)) {
				return H * (7.5625 * F * F) + E
			} else {
				if (F < (2 / 2.75)) {
					return H * (7.5625 * (F -= (1.5 / 2.75)) * F + 0.75) + E
				} else {
					if (F < (2.5 / 2.75)) {
						return H * (7.5625 * (F -= (2.25 / 2.75)) * F + 0.9375) + E
					}
				}
			}
			return H * (7.5625 * (F -= (2.625 / 2.75)) * F + 0.984375) + E
		},
		bounceBoth: function(F, E, H, G) {
			if (F < G / 2) {
				return Ext.lib.Easing.bounceIn(F * 2, 0, H, G) * 0.5 + E
			}
			return Ext.lib.Easing.bounceOut(F * 2 - G, 0, H, G) * 0.5 + H * 0.5 + E
		}
	}; (function() {
		Ext.lib.Motion = function(K, J, L, M) {
			if (K) {
				Ext.lib.Motion.superclass.constructor.call(this, K, J, L, M)
			}
		};
		Ext.extend(Ext.lib.Motion, Ext.lib.ColorAnim);
		var H = Ext.lib;
		var I = H.Motion.superclass;
		var F = H.Motion.prototype;
		F.toString = function() {
			var J = this.getEl();
			var K = J.id || J.tagName;
			return ("Motion " + K)
		};
		F.patterns.points = /^points$/i;
		F.setAttribute = function(J, L, K) {
			if (this.patterns.points.test(J)) {
				K = K || "px";
				I.setAttribute.call(this, "left", L[0], K);
				I.setAttribute.call(this, "top", L[1], K)
			} else {
				I.setAttribute.call(this, J, L, K)
			}
		};
		F.getAttribute = function(J) {
			if (this.patterns.points.test(J)) {
				var K = [I.getAttribute.call(this, "left"), I.getAttribute.call(this, "top")]
			} else {
				K = I.getAttribute.call(this, J)
			}
			return K
		};
		F.doMethod = function(J, N, K) {
			var M = null;
			if (this.patterns.points.test(J)) {
				var L = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
				M = H.Bezier.getPosition(this.runtimeAttributes[J], L)
			} else {
				M = I.doMethod.call(this, J, N, K)
			}
			return M
		};
		F.setRuntimeAttribute = function(S) {
			if (this.patterns.points.test(S)) {
				var K = this.getEl();
				var M = this.attributes;
				var J;
				var O = M["points"]["control"] || [];
				var L;
				var P,
				R;
				if (O.length > 0 && !Ext.isArray(O[0])) {
					O = [O]
				} else {
					var N = [];
					for (P = 0, R = O.length; P < R; ++P) {
						N[P] = O[P]
					}
					O = N
				}
				Ext.fly(K, "_anim").position();
				if (G(M["points"]["from"])) {
					Ext.lib.Dom.setXY(K, M["points"]["from"])
				} else {
					Ext.lib.Dom.setXY(K, Ext.lib.Dom.getXY(K))
				}
				J = this.getAttribute("points");
				if (G(M["points"]["to"])) {
					L = E.call(this, M["points"]["to"], J);
					var Q = Ext.lib.Dom.getXY(this.getEl());
					for (P = 0, R = O.length; P < R; ++P) {
						O[P] = E.call(this, O[P], J)
					}
				} else {
					if (G(M["points"]["by"])) {
						L = [J[0] + M["points"]["by"][0], J[1] + M["points"]["by"][1]];
						for (P = 0, R = O.length; P < R; ++P) {
							O[P] = [J[0] + O[P][0], J[1] + O[P][1]]
						}
					}
				}
				this.runtimeAttributes[S] = [J];
				if (O.length > 0) {
					this.runtimeAttributes[S] = this.runtimeAttributes[S].concat(O)
				}
				this.runtimeAttributes[S][this.runtimeAttributes[S].length] = L
			} else {
				I.setRuntimeAttribute.call(this, S)
			}
		};
		var E = function(J, L) {
			var K = Ext.lib.Dom.getXY(this.getEl());
			J = [J[0] - K[0] + L[0], J[1] - K[1] + L[1]];
			return J
		};
		var G = function(J) {
			return (typeof J !== "undefined")
		}
	})(); (function() {
		Ext.lib.Scroll = function(I, H, J, K) {
			if (I) {
				Ext.lib.Scroll.superclass.constructor.call(this, I, H, J, K)
			}
		};
		Ext.extend(Ext.lib.Scroll, Ext.lib.ColorAnim);
		var F = Ext.lib;
		var G = F.Scroll.superclass;
		var E = F.Scroll.prototype;
		E.toString = function() {
			var H = this.getEl();
			var I = H.id || H.tagName;
			return ("Scroll " + I)
		};
		E.doMethod = function(H, K, I) {
			var J = null;
			if (H == "scroll") {
				J = [this.method(this.currentFrame, K[0], I[0] - K[0], this.totalFrames), this.method(this.currentFrame, K[1], I[1] - K[1], this.totalFrames)]
			} else {
				J = G.doMethod.call(this, H, K, I)
			}
			return J
		};
		E.getAttribute = function(H) {
			var J = null;
			var I = this.getEl();
			if (H == "scroll") {
				J = [I.scrollLeft, I.scrollTop]
			} else {
				J = G.getAttribute.call(this, H)
			}
			return J
		};
		E.setAttribute = function(H, K, J) {
			var I = this.getEl();
			if (H == "scroll") {
				I.scrollLeft = K[0];
				I.scrollTop = K[1]
			} else {
				G.setAttribute.call(this, H, K, J)
			}
		}
	})()
})();/*
 * Ext JS Library 2.2
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.DomHelper = function() {
	var tempTableEl = null;
	var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
	var tableRe = /^table|tbody|tr|td$/i;

	var createHtml = function(o) {
		if (typeof o == 'string') {
			return o;
		}
		var b = "";
		if (Ext.isArray(o)) {
			for (var i = 0, l = o.length; i < l; i++) {
				b += createHtml(o[i]);
			}
			return b;
		}
		if (!o.tag) {
			o.tag = "div";
		}
		b += "<" + o.tag;
		for (var attr in o) {
			if (attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
			if (attr == "style") {
				var s = o["style"];
				if (typeof s == "function") {
					s = s.call();
				}
				if (typeof s == "string") {
					b += ' style="' + s + '"';
				} else if (typeof s == "object") {
					b += ' style="';
					for (var key in s) {
						if (typeof s[key] != "function") {
							b += key + ":" + s[key] + ";";
						}
					}
					b += '"';
				}
			} else {
				if (attr == "cls") {
					b += ' class="' + o["cls"] + '"';
				} else if (attr == "htmlFor") {
					b += ' for="' + o["htmlFor"] + '"';
				} else {
					b += " " + attr + '="' + o[attr] + '"';
				}
			}
		}
		if (emptyTags.test(o.tag)) {
			b += "/>";
		} else {
			b += ">";
			var cn = o.children || o.cn;
			if (cn) {
				b += createHtml(cn);
			} else if (o.html) {
				b += o.html;
			}
			b += "</" + o.tag + ">";
		}
		return b;
	};

	var createDom = function(o, parentNode) {
		var el;
		if (Ext.isArray(o)) {
			el = document.createDocumentFragment();
			for (var i = 0, l = o.length; i < l; i++) {
				createDom(o[i], el);
			}
		} else if (typeof o == "string") {
			el = document.createTextNode(o);
		} else {
			el = document.createElement(o.tag || 'div');
			var useSet = !!el.setAttribute;
			for (var attr in o) {
				if (attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;
				if (attr == "cls") {
					el.className = o["cls"];
				} else {
					if (useSet) el.setAttribute(attr, o[attr]);
					else el[attr] = o[attr];
				}
			}
			Ext.DomHelper.applyStyles(el, o.style);
			var cn = o.children || o.cn;
			if (cn) {
				createDom(cn, el);
			} else if (o.html) {
				el.innerHTML = o.html;
			}
		}
		if (parentNode) {
			parentNode.appendChild(el);
		}
		return el;
	};

	var ieTable = function(depth, s, h, e) {
		tempTableEl.innerHTML = [s, h, e].join('');
		var i = -1,
		el = tempTableEl;
		while (++i < depth) {
			el = el.firstChild;
		}
		return el;
	};

	var ts = '<table>',
	te = '</table>',
	tbs = ts + '<tbody>',
	tbe = '</tbody>' + te,
	trs = tbs + '<tr>',
	tre = '</tr>' + tbe;

	var insertIntoTable = function(tag, where, el, html) {
		if (!tempTableEl) {
			tempTableEl = document.createElement('div');
		}
		var node;
		var before = null;
		if (tag == 'td') {
			if (where == 'afterbegin' || where == 'beforeend') {
				return;
			}
			if (where == 'beforebegin') {
				before = el;
				el = el.parentNode;
			} else {
				before = el.nextSibling;
				el = el.parentNode;
			}
			node = ieTable(4, trs, html, tre);
		} else if (tag == 'tr') {
			if (where == 'beforebegin') {
				before = el;
				el = el.parentNode;
				node = ieTable(3, tbs, html, tbe);
			} else if (where == 'afterend') {
				before = el.nextSibling;
				el = el.parentNode;
				node = ieTable(3, tbs, html, tbe);
			} else {
				if (where == 'afterbegin') {
					before = el.firstChild;
				}
				node = ieTable(4, trs, html, tre);
			}
		} else if (tag == 'tbody') {
			if (where == 'beforebegin') {
				before = el;
				el = el.parentNode;
				node = ieTable(2, ts, html, te);
			} else if (where == 'afterend') {
				before = el.nextSibling;
				el = el.parentNode;
				node = ieTable(2, ts, html, te);
			} else {
				if (where == 'afterbegin') {
					before = el.firstChild;
				}
				node = ieTable(3, tbs, html, tbe);
			}
		} else {
			if (where == 'beforebegin' || where == 'afterend') {
				return;
			}
			if (where == 'afterbegin') {
				before = el.firstChild;
			}
			node = ieTable(2, ts, html, te);
		}
		el.insertBefore(node, before);
		return node;
	};

	return {

		useDom: false,

		markup: function(o) {
			return createHtml(o);
		},

		applyStyles: function(el, styles) {
			if (styles) {
				el = Ext.fly(el);
				if (typeof styles == "string") {
					var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
					var matches;
					while ((matches = re.exec(styles)) != null) {
						el.setStyle(matches[1], matches[2]);
					}
				} else if (typeof styles == "object") {
					for (var style in styles) {
						el.setStyle(style, styles[style]);
					}
				} else if (typeof styles == "function") {
					Ext.DomHelper.applyStyles(el, styles.call());
				}
			}
		},

		insertHtml: function(where, el, html) {
			where = where.toLowerCase();
			if (el.insertAdjacentHTML) {
				if (tableRe.test(el.tagName)) {
					var rs;
					if (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)) {
						return rs;
					}
				}
				switch (where) {
				case "beforebegin":
					el.insertAdjacentHTML('BeforeBegin', html);
					return el.previousSibling;
				case "afterbegin":
					el.insertAdjacentHTML('AfterBegin', html);
					return el.firstChild;
				case "beforeend":
					el.insertAdjacentHTML('BeforeEnd', html);
					return el.lastChild;
				case "afterend":
					el.insertAdjacentHTML('AfterEnd', html);
					return el.nextSibling;
				}
				throw 'Illegal insertion point -> "' + where + '"';
			}
			var range = el.ownerDocument.createRange();
			var frag;
			switch (where) {
			case "beforebegin":
				range.setStartBefore(el);
				frag = range.createContextualFragment(html);
				el.parentNode.insertBefore(frag, el);
				return el.previousSibling;
			case "afterbegin":
				if (el.firstChild) {
					range.setStartBefore(el.firstChild);
					frag = range.createContextualFragment(html);
					el.insertBefore(frag, el.firstChild);
					return el.firstChild;
				} else {
					el.innerHTML = html;
					return el.firstChild;
				}
			case "beforeend":
				if (el.lastChild) {
					range.setStartAfter(el.lastChild);
					frag = range.createContextualFragment(html);
					el.appendChild(frag);
					return el.lastChild;
				} else {
					el.innerHTML = html;
					return el.lastChild;
				}
			case "afterend":
				range.setStartAfter(el);
				frag = range.createContextualFragment(html);
				el.parentNode.insertBefore(frag, el.nextSibling);
				return el.nextSibling;
			}
			throw 'Illegal insertion point -> "' + where + '"';
		},

		insertBefore: function(el, o, returnElement) {
			return this.doInsert(el, o, returnElement, "beforeBegin");
		},

		insertAfter: function(el, o, returnElement) {
			return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
		},

		insertFirst: function(el, o, returnElement) {
			return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");
		},

		doInsert: function(el, o, returnElement, pos, sibling) {
			el = Ext.getDom(el);
			var newNode;
			if (this.useDom) {
				newNode = createDom(o, null); (sibling === "firstChild" ? el: el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);
			} else {
				var html = createHtml(o);
				newNode = this.insertHtml(pos, el, html);
			}
			return returnElement ? Ext.get(newNode, true) : newNode;
		},

		append: function(el, o, returnElement) {
			el = Ext.getDom(el);
			var newNode;
			if (this.useDom) {
				newNode = createDom(o, null);
				el.appendChild(newNode);
			} else {
				var html = createHtml(o);
				newNode = this.insertHtml("beforeEnd", el, html);
			}
			return returnElement ? Ext.get(newNode, true) : newNode;
		},

		overwrite: function(el, o, returnElement) {
			el = Ext.getDom(el);
			el.innerHTML = createHtml(o);
			return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
		},

		createTemplate: function(o) {
			var html = createHtml(o);
			return new Ext.Template(html);
		}
	};
} ();

Ext.Template = function(html) {
	var a = arguments;
	if (Ext.isArray(html)) {
		html = html.join("");
	} else if (a.length > 1) {
		var buf = [];
		for (var i = 0, len = a.length; i < len; i++) {
			if (typeof a[i] == 'object') {
				Ext.apply(this, a[i]);
			} else {
				buf[buf.length] = a[i];
			}
		}
		html = buf.join('');
	}

	this.html = html;
	if (this.compiled) {
		this.compile();
	}
};
Ext.Template.prototype = {

	applyTemplate: function(values) {
		if (this.compiled) {
			return this.compiled(values);
		}
		var useF = this.disableFormats !== true;
		var fm = Ext.util.Format,
		tpl = this;
		var fn = function(m, name, format, args) {
			if (format && useF) {
				if (format.substr(0, 5) == "this.") {
					return tpl.call(format.substr(5), values[name], values);
				} else {
					if (args) {
						var re = /^\s*['"](.*)["']\s*$/;
						args = args.split(',');
						for (var i = 0, len = args.length; i < len; i++) {
							args[i] = args[i].replace(re, "$1");
						}
						args = [values[name]].concat(args);
					} else {
						args = [values[name]];
					}
					return fm[format].apply(fm, args);
				}
			} else {
				return values[name] !== undefined ? values[name] : "";
			}
		};
		return this.html.replace(this.re, fn);
	},

	set: function(html, compile) {
		this.html = html;
		this.compiled = null;
		if (compile) {
			this.compile();
		}
		return this;
	},

	disableFormats: false,

	re: /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,

	compile: function() {
		var fm = Ext.util.Format;
		var useF = this.disableFormats !== true;
		var sep = Ext.isGecko ? "+": ",";
		var fn = function(m, name, format, args) {
			if (format && useF) {
				args = args ? ',' + args: "";
				if (format.substr(0, 5) != "this.") {
					format = "fm." + format + '(';
				} else {
					format = 'this.call("' + format.substr(5) + '", ';
					args = ", values";
				}
			} else {
				args = '';
				format = "(values['" + name + "'] == undefined ? '' : ";
			}
			return "'" + sep + format + "values['" + name + "']" + args + ")" + sep + "'";
		};
		var body;
		if (Ext.isGecko) {
			body = "this.compiled = function(values){ return '" + this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) + "';};";
		} else {
			body = ["this.compiled = function(values){ return ['"];
			body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
			body.push("'].join('');};");
			body = body.join('');
		}
		eval(body);
		return this;
	},

	call: function(fnName, value, allValues) {
		return this[fnName](value, allValues);
	},

	insertFirst: function(el, values, returnElement) {
		return this.doInsert('afterBegin', el, values, returnElement);
	},

	insertBefore: function(el, values, returnElement) {
		return this.doInsert('beforeBegin', el, values, returnElement);
	},

	insertAfter: function(el, values, returnElement) {
		return this.doInsert('afterEnd', el, values, returnElement);
	},

	append: function(el, values, returnElement) {
		return this.doInsert('beforeEnd', el, values, returnElement);
	},

	doInsert: function(where, el, values, returnEl) {
		el = Ext.getDom(el);
		var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
		return returnEl ? Ext.get(newNode, true) : newNode;
	},

	overwrite: function(el, values, returnElement) {
		el = Ext.getDom(el);
		el.innerHTML = this.applyTemplate(values);
		return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
	}
};

Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;

Ext.DomHelper.Template = Ext.Template;

Ext.Template.from = function(el, config) {
	el = Ext.getDom(el);
	return new Ext.Template(el.value || el.innerHTML, config || '');
};

Ext.DomQuery = function() {
	var cache = {},
	simpleCache = {},
	valueCache = {};
	var nonSpace = /\S/;
	var trimRe = /^\s+|\s+$/g;
	var tplRe = /\{(\d+)\}/g;
	var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
	var tagTokenRe = /^(#)?([\w-\*]+)/;
	var nthRe = /(\d*)n\+?(\d*)/,
	nthRe2 = /\D/;

	function child(p, index) {
		var i = 0;
		var n = p.firstChild;
		while (n) {
			if (n.nodeType == 1) {
				if (++i == index) {
					return n;
				}
			}
			n = n.nextSibling;
		}
		return null;
	};

	function next(n) {
		while ((n = n.nextSibling) && n.nodeType != 1);
		return n;
	};

	function prev(n) {
		while ((n = n.previousSibling) && n.nodeType != 1);
		return n;
	};

	function children(d) {
		var n = d.firstChild,
		ni = -1;
		while (n) {
			var nx = n.nextSibling;
			if (n.nodeType == 3 && !nonSpace.test(n.nodeValue)) {
				d.removeChild(n);
			} else {
				n.nodeIndex = ++ni;
			}
			n = nx;
		}
		return this;
	};

	function byClassName(c, a, v) {
		if (!v) {
			return c;
		}
		var r = [],
		ri = -1,
		cn;
		for (var i = 0, ci; ci = c[i]; i++) {
			if ((' ' + ci.className + ' ').indexOf(v) != -1) {
				r[++ri] = ci;
			}
		}
		return r;
	};

	function attrValue(n, attr) {
		if (!n.tagName && typeof n.length != "undefined") {
			n = n[0];
		}
		if (!n) {
			return null;
		}
		if (attr == "for") {
			return n.htmlFor;
		}
		if (attr == "class" || attr == "className") {
			return n.className;
		}
		return n.getAttribute(attr) || n[attr];

	};

	function getNodes(ns, mode, tagName) {
		var result = [],
		ri = -1,
		cs;
		if (!ns) {
			return result;
		}
		tagName = tagName || "*";
		if (typeof ns.getElementsByTagName != "undefined") {
			ns = [ns];
		}
		if (!mode) {
			for (var i = 0, ni; ni = ns[i]; i++) {
				cs = ni.getElementsByTagName(tagName);
				for (var j = 0, ci; ci = cs[j]; j++) {
					result[++ri] = ci;
				}
			}
		} else if (mode == "/" || mode == ">") {
			var utag = tagName.toUpperCase();
			for (var i = 0, ni, cn; ni = ns[i]; i++) {
				cn = ni.children || ni.childNodes;
				for (var j = 0, cj; cj = cn[j]; j++) {
					if (cj.nodeName == utag || cj.nodeName == tagName || tagName == '*') {
						result[++ri] = cj;
					}
				}
			}
		} else if (mode == "+") {
			var utag = tagName.toUpperCase();
			for (var i = 0, n; n = ns[i]; i++) {
				while ((n = n.nextSibling) && n.nodeType != 1);
				if (n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')) {
					result[++ri] = n;
				}
			}
		} else if (mode == "~") {
			for (var i = 0, n; n = ns[i]; i++) {
				while ((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase() != tagName)));
				if (n) {
					result[++ri] = n;
				}
			}
		}
		return result;
	};

	function concat(a, b) {
		if (b.slice) {
			return a.concat(b);
		}
		for (var i = 0, l = b.length; i < l; i++) {
			a[a.length] = b[i];
		}
		return a;
	}

	function byTag(cs, tagName) {
		if (cs.tagName || cs == document) {
			cs = [cs];
		}
		if (!tagName) {
			return cs;
		}
		var r = [],
		ri = -1;
		tagName = tagName.toLowerCase();
		for (var i = 0, ci; ci = cs[i]; i++) {
			if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName) {
				r[++ri] = ci;
			}
		}
		return r;
	};

	function byId(cs, attr, id) {
		if (cs.tagName || cs == document) {
			cs = [cs];
		}
		if (!id) {
			return cs;
		}
		var r = [],
		ri = -1;
		for (var i = 0, ci; ci = cs[i]; i++) {
			if (ci && ci.id == id) {
				r[++ri] = ci;
				return r;
			}
		}
		return r;
	};

	function byAttribute(cs, attr, value, op, custom) {
		var r = [],
		ri = -1,
		st = custom == "{";
		var f = Ext.DomQuery.operators[op];
		for (var i = 0, ci; ci = cs[i]; i++) {
			var a;
			if (st) {
				a = Ext.DomQuery.getStyle(ci, attr);
			} else if (attr == "class" || attr == "className") {
				a = ci.className;
			} else if (attr == "for") {
				a = ci.htmlFor;
			} else if (attr == "href") {
				a = ci.getAttribute("href", 2);
			} else {
				a = ci.getAttribute(attr);
			}
			if ((f && f(a, value)) || (!f && a)) {
				r[++ri] = ci;
			}
		}
		return r;
	};

	function byPseudo(cs, name, value) {
		return Ext.DomQuery.pseudos[name](cs, value);
	};

	var isIE = window.ActiveXObject ? true: false;

	eval("var batch = 30803;");

	var key = 30803;

	function nodupIEXml(cs) {
		var d = ++key;
		cs[0].setAttribute("_nodup", d);
		var r = [cs[0]];
		for (var i = 1, len = cs.length; i < len; i++) {
			var c = cs[i];
			if (!c.getAttribute("_nodup") != d) {
				c.setAttribute("_nodup", d);
				r[r.length] = c;
			}
		}
		for (var i = 0, len = cs.length; i < len; i++) {
			cs[i].removeAttribute("_nodup");
		}
		return r;
	}

	function nodup(cs) {
		if (!cs) {
			return [];
		}
		var len = cs.length,
		c,
		i,
		r = cs,
		cj,
		ri = -1;
		if (!len || typeof cs.nodeType != "undefined" || len == 1) {
			return cs;
		}
		if (isIE && typeof cs[0].selectSingleNode != "undefined") {
			return nodupIEXml(cs);
		}
		var d = ++key;
		cs[0]._nodup = d;
		for (i = 1; c = cs[i]; i++) {
			if (c._nodup != d) {
				c._nodup = d;
			} else {
				r = [];
				for (var j = 0; j < i; j++) {
					r[++ri] = cs[j];
				}
				for (j = i + 1; cj = cs[j]; j++) {
					if (cj._nodup != d) {
						cj._nodup = d;
						r[++ri] = cj;
					}
				}
				return r;
			}
		}
		return r;
	}

	function quickDiffIEXml(c1, c2) {
		var d = ++key;
		for (var i = 0, len = c1.length; i < len; i++) {
			c1[i].setAttribute("_qdiff", d);
		}
		var r = [];
		for (var i = 0, len = c2.length; i < len; i++) {
			if (c2[i].getAttribute("_qdiff") != d) {
				r[r.length] = c2[i];
			}
		}
		for (var i = 0, len = c1.length; i < len; i++) {
			c1[i].removeAttribute("_qdiff");
		}
		return r;
	}

	function quickDiff(c1, c2) {
		var len1 = c1.length;
		if (!len1) {
			return c2;
		}
		if (isIE && c1[0].selectSingleNode) {
			return quickDiffIEXml(c1, c2);
		}
		var d = ++key;
		for (var i = 0; i < len1; i++) {
			c1[i]._qdiff = d;
		}
		var r = [];
		for (var i = 0, len = c2.length; i < len; i++) {
			if (c2[i]._qdiff != d) {
				r[r.length] = c2[i];
			}
		}
		return r;
	}

	function quickId(ns, mode, root, id) {
		if (ns == root) {
			var d = root.ownerDocument || root;
			return d.getElementById(id);
		}
		ns = getNodes(ns, mode, "*");
		return byId(ns, null, id);
	}

	return {
		getStyle: function(el, name) {
			return Ext.fly(el).getStyle(name);
		},

		compile: function(path, type) {
			type = type || "select";

			var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
			var q = path,
			mode,
			lq;
			var tk = Ext.DomQuery.matchers;
			var tklen = tk.length;
			var mm;

			var lmode = q.match(modeRe);
			if (lmode && lmode[1]) {
				fn[fn.length] = 'mode="' + lmode[1].replace(trimRe, "") + '";';
				q = q.replace(lmode[1], "");
			}

			while (path.substr(0, 1) == "/") {
				path = path.substr(1);
			}

			while (q && lq != q) {
				lq = q;
				var tm = q.match(tagTokenRe);
				if (type == "select") {
					if (tm) {
						if (tm[1] == "#") {
							fn[fn.length] = 'n = quickId(n, mode, root, "' + tm[2] + '");';
						} else {
							fn[fn.length] = 'n = getNodes(n, mode, "' + tm[2] + '");';
						}
						q = q.replace(tm[0], "");
					} else if (q.substr(0, 1) != '@') {
						fn[fn.length] = 'n = getNodes(n, mode, "*");';
					}
				} else {
					if (tm) {
						if (tm[1] == "#") {
							fn[fn.length] = 'n = byId(n, null, "' + tm[2] + '");';
						} else {
							fn[fn.length] = 'n = byTag(n, "' + tm[2] + '");';
						}
						q = q.replace(tm[0], "");
					}
				}
				while (! (mm = q.match(modeRe))) {
					var matched = false;
					for (var j = 0; j < tklen; j++) {
						var t = tk[j];
						var m = q.match(t.re);
						if (m) {
							fn[fn.length] = t.select.replace(tplRe,
							function(x, i) {
								return m[i];
							});
							q = q.replace(m[0], "");
							matched = true;
							break;
						}
					}

					if (!matched) {
						throw 'Error parsing selector, parsing failed at "' + q + '"';
					}
				}
				if (mm[1]) {
					fn[fn.length] = 'mode="' + mm[1].replace(trimRe, "") + '";';
					q = q.replace(mm[1], "");
				}
			}
			fn[fn.length] = "return nodup(n);\n}";
			eval(fn.join(""));
			return f;
		},

		select: function(path, root, type) {
			if (!root || root == document) {
				root = document;
			}
			if (typeof root == "string") {
				root = document.getElementById(root);
			}
			var paths = path.split(",");
			var results = [];
			for (var i = 0, len = paths.length; i < len; i++) {
				var p = paths[i].replace(trimRe, "");
				if (!cache[p]) {
					cache[p] = Ext.DomQuery.compile(p);
					if (!cache[p]) {
						throw p + " is not a valid selector";
					}
				}
				var result = cache[p](root);
				if (result && result != document) {
					results = results.concat(result);
				}
			}
			if (paths.length > 1) {
				return nodup(results);
			}
			return results;
		},

		selectNode: function(path, root) {
			return Ext.DomQuery.select(path, root)[0];
		},

		selectValue: function(path, root, defaultValue) {
			path = path.replace(trimRe, "");
			if (!valueCache[path]) {
				valueCache[path] = Ext.DomQuery.compile(path, "select");
			}
			var n = valueCache[path](root);
			n = n[0] ? n[0] : n;
			var v = (n && n.firstChild ? n.firstChild.nodeValue: null);
			return ((v === null || v === undefined || v === '') ? defaultValue: v);
		},

		selectNumber: function(path, root, defaultValue) {
			var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
			return parseFloat(v);
		},

		is: function(el, ss) {
			if (typeof el == "string") {
				el = document.getElementById(el);
			}
			var isArray = Ext.isArray(el);
			var result = Ext.DomQuery.filter(isArray ? el: [el], ss);
			return isArray ? (result.length == el.length) : (result.length > 0);
		},

		filter: function(els, ss, nonMatches) {
			ss = ss.replace(trimRe, "");
			if (!simpleCache[ss]) {
				simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
			}
			var result = simpleCache[ss](els);
			return nonMatches ? quickDiff(result, els) : result;
		},

		matchers: [{
			re: /^\.([\w-]+)/,
			select: 'n = byClassName(n, null, " {1} ");'
		},
		{
			re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
			select: 'n = byPseudo(n, "{1}", "{2}");'
		},
		{
			re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
			select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
		},
		{
			re: /^#([\w-]+)/,
			select: 'n = byId(n, null, "{1}");'
		},
		{
			re: /^@([\w-]+)/,
			select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
		}],

		operators: {
			"=": function(a, v) {
				return a == v;
			},
			"!=": function(a, v) {
				return a != v;
			},
			"^=": function(a, v) {
				return a && a.substr(0, v.length) == v;
			},
			"$=": function(a, v) {
				return a && a.substr(a.length - v.length) == v;
			},
			"*=": function(a, v) {
				return a && a.indexOf(v) !== -1;
			},
			"%=": function(a, v) {
				return (a % v) == 0;
			},
			"|=": function(a, v) {
				return a && (a == v || a.substr(0, v.length + 1) == v + '-');
			},
			"~=": function(a, v) {
				return a && (' ' + a + ' ').indexOf(' ' + v + ' ') != -1;
			}
		},

		pseudos: {
			"first-child": function(c) {
				var r = [],
				ri = -1,
				n;
				for (var i = 0, ci; ci = n = c[i]; i++) {
					while ((n = n.previousSibling) && n.nodeType != 1);
					if (!n) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"last-child": function(c) {
				var r = [],
				ri = -1,
				n;
				for (var i = 0, ci; ci = n = c[i]; i++) {
					while ((n = n.nextSibling) && n.nodeType != 1);
					if (!n) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"nth-child": function(c, a) {
				var r = [],
				ri = -1;
				var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
				var f = (m[1] || 1) - 0,
				l = m[2] - 0;
				for (var i = 0, n; n = c[i]; i++) {
					var pn = n.parentNode;
					if (batch != pn._batch) {
						var j = 0;
						for (var cn = pn.firstChild; cn; cn = cn.nextSibling) {
							if (cn.nodeType == 1) {
								cn.nodeIndex = ++j;
							}
						}
						pn._batch = batch;
					}
					if (f == 1) {
						if (l == 0 || n.nodeIndex == l) {
							r[++ri] = n;
						}
					} else if ((n.nodeIndex + l) % f == 0) {
						r[++ri] = n;
					}
				}

				return r;
			},

			"only-child": function(c) {
				var r = [],
				ri = -1;;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (!prev(ci) && !next(ci)) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"empty": function(c) {
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					var cns = ci.childNodes,
					j = 0,
					cn,
					empty = true;
					while (cn = cns[j]) {++j;
						if (cn.nodeType == 1 || cn.nodeType == 3) {
							empty = false;
							break;
						}
					}
					if (empty) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"contains": function(c, v) {
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if ((ci.textContent || ci.innerText || '').indexOf(v) != -1) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"nodeValue": function(c, v) {
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (ci.firstChild && ci.firstChild.nodeValue == v) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"checked": function(c) {
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (ci.checked == true) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"not": function(c, ss) {
				return Ext.DomQuery.filter(c, ss, true);
			},

			"any": function(c, selectors) {
				var ss = selectors.split('|');
				var r = [],
				ri = -1,
				s;
				for (var i = 0, ci; ci = c[i]; i++) {
					for (var j = 0; s = ss[j]; j++) {
						if (Ext.DomQuery.is(ci, s)) {
							r[++ri] = ci;
							break;
						}
					}
				}
				return r;
			},

			"odd": function(c) {
				return this["nth-child"](c, "odd");
			},

			"even": function(c) {
				return this["nth-child"](c, "even");
			},

			"nth": function(c, a) {
				return c[a - 1] || [];
			},

			"first": function(c) {
				return c[0] || [];
			},

			"last": function(c) {
				return c[c.length - 1] || [];
			},

			"has": function(c, ss) {
				var s = Ext.DomQuery.select;
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (s(ss, ci).length > 0) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"next": function(c, ss) {
				var is = Ext.DomQuery.is;
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					var n = next(ci);
					if (n && is(n, ss)) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"prev": function(c, ss) {
				var is = Ext.DomQuery.is;
				var r = [],
				ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					var n = prev(ci);
					if (n && is(n, ss)) {
						r[++ri] = ci;
					}
				}
				return r;
			}
		}
	};
} ();

Ext.query = Ext.DomQuery.select;

Ext.util.Observable = function() {

	if (this.listeners) {
		this.on(this.listeners);
		delete this.listeners;
	}
};
Ext.util.Observable.prototype = {

	fireEvent: function() {
		if (this.eventsSuspended !== true) {
			var ce = this.events[arguments[0].toLowerCase()];
			if (typeof ce == "object") {
				return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
			}
		}
		return true;
	},

	filterOptRe: /^(?:scope|delay|buffer|single)$/,

	addListener: function(eventName, fn, scope, o) {
		if (typeof eventName == "object") {
			o = eventName;
			for (var e in o) {
				if (this.filterOptRe.test(e)) {
					continue;
				}
				if (typeof o[e] == "function") {
					this.addListener(e, o[e], o.scope, o);
				} else {
					this.addListener(e, o[e].fn, o[e].scope, o[e]);
				}
			}
			return;
		}
		o = (!o || typeof o == "boolean") ? {}: o;
		eventName = eventName.toLowerCase();
		var ce = this.events[eventName] || true;
		if (typeof ce == "boolean") {
			ce = new Ext.util.Event(this, eventName);
			this.events[eventName] = ce;
		}
		ce.addListener(fn, scope, o);
	},

	removeListener: function(eventName, fn, scope) {
		var ce = this.events[eventName.toLowerCase()];
		if (typeof ce == "object") {
			ce.removeListener(fn, scope);
		}
	},

	purgeListeners: function() {
		for (var evt in this.events) {
			if (typeof this.events[evt] == "object") {
				this.events[evt].clearListeners();
			}
		}
	},

	relayEvents: function(o, events) {
		var createHandler = function(ename) {
			return function() {
				return this.fireEvent.apply(this, Ext.combine(ename, Array.prototype.slice.call(arguments, 0)));
			};
		};
		for (var i = 0, len = events.length; i < len; i++) {
			var ename = events[i];
			if (!this.events[ename]) {
				this.events[ename] = true;
			};
			o.on(ename, createHandler(ename), this);
		}
	},

	addEvents: function(o) {
		if (!this.events) {
			this.events = {};
		}
		if (typeof o == 'string') {
			for (var i = 0, a = arguments, v; v = a[i]; i++) {
				if (!this.events[a[i]]) {
					this.events[a[i]] = true;
				}
			}
		} else {
			Ext.applyIf(this.events, o);
		}
	},

	hasListener: function(eventName) {
		var e = this.events[eventName];
		return typeof e == "object" && e.listeners.length > 0;
	},

	suspendEvents: function() {
		this.eventsSuspended = true;
	},

	resumeEvents: function() {
		this.eventsSuspended = false;
	},

	getMethodEvent: function(method) {
		if (!this.methodEvents) {
			this.methodEvents = {};
		}
		var e = this.methodEvents[method];
		if (!e) {
			e = {};
			this.methodEvents[method] = e;

			e.originalFn = this[method];
			e.methodName = method;
			e.before = [];
			e.after = [];

			var returnValue,
			v,
			cancel;
			var obj = this;

			var makeCall = function(fn, scope, args) {
				if ((v = fn.apply(scope || obj, args)) !== undefined) {
					if (typeof v === 'object') {
						if (v.returnValue !== undefined) {
							returnValue = v.returnValue;
						} else {
							returnValue = v;
						}
						if (v.cancel === true) {
							cancel = true;
						}
					} else if (v === false) {
						cancel = true;
					} else {
						returnValue = v;
					}
				}
			}

			this[method] = function() {
				returnValue = v = undefined;
				cancel = false;
				var args = Array.prototype.slice.call(arguments, 0);
				for (var i = 0, len = e.before.length; i < len; i++) {
					makeCall(e.before[i].fn, e.before[i].scope, args);
					if (cancel) {
						return returnValue;
					}
				}

				if ((v = e.originalFn.apply(obj, args)) !== undefined) {
					returnValue = v;
				}

				for (var i = 0, len = e.after.length; i < len; i++) {
					makeCall(e.after[i].fn, e.after[i].scope, args);
					if (cancel) {
						return returnValue;
					}
				}
				return returnValue;
			};
		}
		return e;
	},

	beforeMethod: function(method, fn, scope) {
		var e = this.getMethodEvent(method);
		e.before.push({
			fn: fn,
			scope: scope
		});
	},

	afterMethod: function(method, fn, scope) {
		var e = this.getMethodEvent(method);
		e.after.push({
			fn: fn,
			scope: scope
		});
	},

	removeMethodListener: function(method, fn, scope) {
		var e = this.getMethodEvent(method);
		for (var i = 0, len = e.before.length; i < len; i++) {
			if (e.before[i].fn == fn && e.before[i].scope == scope) {
				e.before.splice(i, 1);
				return;
			}
		}
		for (var i = 0, len = e.after.length; i < len; i++) {
			if (e.after[i].fn == fn && e.after[i].scope == scope) {
				e.after.splice(i, 1);
				return;
			}
		}
	}
};

Ext.util.Observable.prototype.on = Ext.util.Observable.prototype.addListener;

Ext.util.Observable.prototype.un = Ext.util.Observable.prototype.removeListener;

Ext.util.Observable.capture = function(o, fn, scope) {
	o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
};

Ext.util.Observable.releaseCapture = function(o) {
	o.fireEvent = Ext.util.Observable.prototype.fireEvent;
};
 (function() {

	var createBuffered = function(h, o, scope) {
		var task = new Ext.util.DelayedTask();
		return function() {
			task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
		};
	};

	var createSingle = function(h, e, fn, scope) {
		return function() {
			e.removeListener(fn, scope);
			return h.apply(scope, arguments);
		};
	};

	var createDelayed = function(h, o, scope) {
		return function() {
			var args = Array.prototype.slice.call(arguments, 0);
			setTimeout(function() {
				h.apply(scope, args);
			},
			o.delay || 10);
		};
	};

	Ext.util.Event = function(obj, name) {
		this.name = name;
		this.obj = obj;
		this.listeners = [];
	};

	Ext.util.Event.prototype = {
		addListener: function(fn, scope, options) {
			scope = scope || this.obj;
			if (!this.isListening(fn, scope)) {
				var l = this.createListener(fn, scope, options);
				if (!this.firing) {
					this.listeners.push(l);
				} else {
					this.listeners = this.listeners.slice(0);
					this.listeners.push(l);
				}
			}
		},

		createListener: function(fn, scope, o) {
			o = o || {};
			scope = scope || this.obj;
			var l = {
				fn: fn,
				scope: scope,
				options: o
			};
			var h = fn;
			if (o.delay) {
				h = createDelayed(h, o, scope);
			}
			if (o.single) {
				h = createSingle(h, this, fn, scope);
			}
			if (o.buffer) {
				h = createBuffered(h, o, scope);
			}
			l.fireFn = h;
			return l;
		},

		findListener: function(fn, scope) {
			scope = scope || this.obj;
			var ls = this.listeners;
			for (var i = 0, len = ls.length; i < len; i++) {
				var l = ls[i];
				if (l.fn == fn && l.scope == scope) {
					return i;
				}
			}
			return - 1;
		},

		isListening: function(fn, scope) {
			return this.findListener(fn, scope) != -1;
		},

		removeListener: function(fn, scope) {
			var index;
			if ((index = this.findListener(fn, scope)) != -1) {
				if (!this.firing) {
					this.listeners.splice(index, 1);
				} else {
					this.listeners = this.listeners.slice(0);
					this.listeners.splice(index, 1);
				}
				return true;
			}
			return false;
		},

		clearListeners: function() {
			this.listeners = [];
		},

		fire: function() {
			var ls = this.listeners,
			scope,
			len = ls.length;
			if (len > 0) {
				this.firing = true;
				var args = Array.prototype.slice.call(arguments, 0);
				for (var i = 0; i < len; i++) {
					var l = ls[i];
					if (l.fireFn.apply(l.scope || this.obj || window, arguments) === false) {
						this.firing = false;
						return false;
					}
				}
				this.firing = false;
			}
			return true;
		}
	};
})();

Ext.EventManager = function() {
	var docReadyEvent,
	docReadyProcId,
	docReadyState = false;
	var resizeEvent,
	resizeTask,
	textEvent,
	textSize;
	var E = Ext.lib.Event;
	var D = Ext.lib.Dom;
	var xname = 'Ex' + 't';

	var elHash = {};

	var addListener = function(el, ename, fn, wrap, scope) {
		var id = Ext.id(el);
		if (!elHash[id]) {
			elHash[id] = {};
		}
		var es = elHash[id];
		if (!es[ename]) {
			es[ename] = [];
		}
		var ls = es[ename];
		ls.push({
			id: id,
			ename: ename,
			fn: fn,
			wrap: wrap,
			scope: scope
		});

		E.on(el, ename, wrap);

		if (ename == "mousewheel" && el.addEventListener) {
			el.addEventListener("DOMMouseScroll", wrap, false);
			E.on(window, 'unload',
			function() {
				el.removeEventListener("DOMMouseScroll", wrap, false);
			});
		}
		if (ename == "mousedown" && el == document) {
			Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
		}
	}

	var removeListener = function(el, ename, fn, scope) {
		el = Ext.getDom(el);
		var id = Ext.id(el),
		es = elHash[id],
		wrap;
		if (es) {
			var ls = es[ename],
			l;
			if (ls) {
				for (var i = 0, len = ls.length; i < len; i++) {
					l = ls[i];
					if (l.fn == fn && (!scope || l.scope == scope)) {
						wrap = l.wrap;
						E.un(el, ename, wrap);
						ls.splice(i, 1);
						break;
					}
				}
			}
		}
		if (ename == "mousewheel" && el.addEventListener && wrap) {
			el.removeEventListener("DOMMouseScroll", wrap, false);
		}
		if (ename == "mousedown" && el == document && wrap) {
			Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
		}
	}

	var removeAll = function(el) {
		el = Ext.getDom(el);
		var id = Ext.id(el),
		es = elHash[id],
		ls;
		if (es) {
			for (var ename in es) {
				if (es.hasOwnProperty(ename)) {
					ls = es[ename];
					for (var i = 0, len = ls.length; i < len; i++) {
						E.un(el, ename, ls[i].wrap);
						ls[i] = null;
					}
				}
				es[ename] = null;
			}
			delete elHash[id];
		}
	}
	
	var fireDocReady = function(){
        if(!docReadyState){
            docReadyState = true;
            Ext.isReady = true;
            if(docReadyProcId){
                clearInterval(docReadyProcId);
            }
            if(Ext.isGecko || Ext.isOpera) {
                document.removeEventListener("DOMContentLoaded", fireDocReady, false);
            }
            if(Ext.isIE){
                var defer = document.getElementById("ie-deferred-loader");
                if(defer){
                    defer.onreadystatechange = null;
                    defer.parentNode.removeChild(defer);
                }
            }
            if(docReadyEvent){
                docReadyEvent.fire();
                docReadyEvent.clearListeners();
            }
        }
    };

    var initDocReady = function(){
        docReadyEvent = new Ext.util.Event();
        if(Ext.isGecko || Ext.isOpera) {
            document.addEventListener("DOMContentLoaded", fireDocReady, false);
        }else if(Ext.isIE){
            document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
            var defer = document.getElementById("ie-deferred-loader");
            defer.onreadystatechange = function(){
                if(this.readyState == "complete"){
                    fireDocReady();
                }
            };
        }else if(Ext.isSafari){
            docReadyProcId = setInterval(function(){
                var rs = document.readyState;
                if(rs == "complete") {
                    fireDocReady();
                 }
            }, 10);
        }
        
        E.on(window, "load", fireDocReady);
    };

	
/*
	var fireDocReady = function() {
		if (!docReadyState) {
			docReadyState = Ext.isReady = true;
			if (Ext.isGecko || Ext.isOpera) {
				document.removeEventListener("DOMContentLoaded", fireDocReady, false);
			}
		}
		if (docReadyProcId) {
			clearInterval(docReadyProcId);
			docReadyProcId = null;
		}
		if (docReadyEvent) {
			docReadyEvent.fire();
			docReadyEvent.clearListeners();
		}
	};

	var initDocReady = function() {
		docReadyEvent = new Ext.util.Event();

		if (Ext.isReady) {
			return;
		}

		E.on(window, 'load', fireDocReady);

		if (Ext.isGecko || Ext.isOpera) {
			document.addEventListener('DOMContentLoaded', fireDocReady, false);
		} else if (Ext.isIE) {
			docReadyProcId = setInterval(function() {
				try {
					Ext.isReady || (document.documentElement.doScroll('left'));
				} catch(e) {
					return;
				}
				fireDocReady();
			},
			5);

			document.onreadystatechange = function() {
				if (document.readyState == 'complete') {
					document.onreadystatechange = null;
					fireDocReady();
				}
			};
		} else if (Ext.isSafari) {
			docReadyProcId = setInterval(function() {
				var rs = document.readyState;
				if (rs == 'complete') {
					fireDocReady();
				}
			},
			10);
		}
	};
*/
	var createBuffered = function(h, o) {
		var task = new Ext.util.DelayedTask(h);
		return function(e) {
			e = new Ext.EventObjectImpl(e);
			task.delay(o.buffer, h, null, [e]);
		};
	};

	var createSingle = function(h, el, ename, fn, scope) {
		return function(e) {
			Ext.EventManager.removeListener(el, ename, fn, scope);
			h(e);
		};
	};

	var createDelayed = function(h, o) {
		return function(e) {
			e = new Ext.EventObjectImpl(e);
			setTimeout(function() {
				h(e);
			},
			o.delay || 10);
		};
	};

	var listen = function(element, ename, opt, fn, scope) {
		var o = (!opt || typeof opt == "boolean") ? {}: opt;
		fn = fn || o.fn;
		scope = scope || o.scope;
		var el = Ext.getDom(element);
		if (!el) {
			throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
		}
		var h = function(e) {
			if (!window[xname]) {
				return;
			}
			e = Ext.EventObject.setEvent(e);
			var t;
			if (o.delegate) {
				t = e.getTarget(o.delegate, el);
				if (!t) {
					return;
				}
			} else {
				t = e.target;
			}
			if (o.stopEvent === true) {
				e.stopEvent();
			}
			if (o.preventDefault === true) {
				e.preventDefault();
			}
			if (o.stopPropagation === true) {
				e.stopPropagation();
			}

			if (o.normalized === false) {
				e = e.browserEvent;
			}

			fn.call(scope || el, e, t, o);
		};
		if (o.delay) {
			h = createDelayed(h, o);
		}
		if (o.single) {
			h = createSingle(h, el, ename, fn, scope);
		}
		if (o.buffer) {
			h = createBuffered(h, o);
		}

		addListener(el, ename, fn, h, scope);
		return h;
	};

	var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
	var pub = {

		addListener: function(element, eventName, fn, scope, options) {
			if (typeof eventName == "object") {
				var o = eventName;
				for (var e in o) {
					if (propRe.test(e)) {
						continue;
					}
					if (typeof o[e] == "function") {
						listen(element, e, o, o[e], o.scope);
					} else {
						listen(element, e, o[e]);
					}
				}
				return;
			}
			return listen(element, eventName, options, fn, scope);
		},

		removeListener: function(element, eventName, fn, scope) {
			return removeListener(element, eventName, fn, scope);
		},

		removeAll: function(element) {
			return removeAll(element);
		},

		onDocumentReady: function(fn, scope, options) {
			if (!docReadyEvent) {
				initDocReady();
			}
			if (docReadyState || Ext.isReady) {
				options || (options = {});
				fn.defer(options.delay || 0, scope);
			} else {
				docReadyEvent.addListener(fn, scope, options);
			}
		},

		onWindowResize: function(fn, scope, options) {
			if (!resizeEvent) {
				resizeEvent = new Ext.util.Event();
				resizeTask = new Ext.util.DelayedTask(function() {
					resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
				});
				E.on(window, "resize", this.fireWindowResize, this);
			}
			resizeEvent.addListener(fn, scope, options);
		},

		fireWindowResize: function() {
			if (resizeEvent) {
				if ((Ext.isIE || Ext.isAir) && resizeTask) {
					resizeTask.delay(50);
				} else {
					resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
				}
			}
		},

		onTextResize: function(fn, scope, options) {
			if (!textEvent) {
				textEvent = new Ext.util.Event();
				var textEl = new Ext.Element(document.createElement('div'));
				textEl.dom.className = 'x-text-resize';
				textEl.dom.innerHTML = 'X';
				textEl.appendTo(document.body);
				textSize = textEl.dom.offsetHeight;
				setInterval(function() {
					if (textEl.dom.offsetHeight != textSize) {
						textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
					}
				},
				this.textResizeInterval);
			}
			textEvent.addListener(fn, scope, options);
		},

		removeResizeListener: function(fn, scope) {
			if (resizeEvent) {
				resizeEvent.removeListener(fn, scope);
			}
		},

		fireResize: function() {
			if (resizeEvent) {
				resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
			}
		},

		ieDeferSrc: false,

		textResizeInterval: 50
	};

	pub.on = pub.addListener;

	pub.un = pub.removeListener;

	pub.stoppedMouseDownEvent = new Ext.util.Event();
	return pub;
} ();

Ext.onReady = Ext.EventManager.onDocumentReady;
 (function() {
	var initExtCss = function() {
		var bd = document.body || document.getElementsByTagName('body')[0];
		if (!bd) {
			return false;
		}
		var cls = [' ', Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6': 'ext-ie7') : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2': 'ext-gecko3') : Ext.isOpera ? "ext-opera": Ext.isSafari ? "ext-safari": ""];

		if (Ext.isMac) {
			cls.push("ext-mac");
		}
		if (Ext.isLinux) {
			cls.push("ext-linux");
		}
		if (Ext.isBorderBox) {
			cls.push('ext-border-box');
		}
		if (Ext.isStrict) {
			var p = bd.parentNode;
			if (p) {
				p.className += ' ext-strict';
			}
		}
		bd.className += cls.join(' ');
		return true;
	}

	if (!initExtCss()) {
		Ext.onReady(initExtCss);
	}
})();

Ext.EventObject = function() {

	var E = Ext.lib.Event;

	var safariKeys = {
		3: 13,
		63234: 37,
		63235: 39,
		63232: 38,
		63233: 40,
		63276: 33,
		63277: 34,
		63272: 46,
		63273: 36,
		63275: 35
	};

	var btnMap = Ext.isIE ? {
		1: 0,
		4: 1,
		2: 2
	}: (Ext.isSafari ? {
		1: 0,
		2: 1,
		3: 2
	}: {
		0: 0,
		1: 1,
		2: 2
	});

	Ext.EventObjectImpl = function(e) {
		if (e) {
			this.setEvent(e.browserEvent || e);
		}
	};

	Ext.EventObjectImpl.prototype = {

		browserEvent: null,

		button: -1,

		shiftKey: false,

		ctrlKey: false,

		altKey: false,

		BACKSPACE: 8,

		TAB: 9,

		NUM_CENTER: 12,

		ENTER: 13,

		RETURN: 13,

		SHIFT: 16,

		CTRL: 17,
		CONTROL: 17,
		ALT: 18,

		PAUSE: 19,

		CAPS_LOCK: 20,

		ESC: 27,

		SPACE: 32,

		PAGE_UP: 33,
		PAGEUP: 33,
		PAGE_DOWN: 34,
		PAGEDOWN: 34,
		END: 35,

		HOME: 36,

		LEFT: 37,

		UP: 38,

		RIGHT: 39,

		DOWN: 40,

		PRINT_SCREEN: 44,

		INSERT: 45,

		DELETE: 46,

		ZERO: 48,

		ONE: 49,

		TWO: 50,

		THREE: 51,

		FOUR: 52,

		FIVE: 53,

		SIX: 54,

		SEVEN: 55,

		EIGHT: 56,

		NINE: 57,

		A: 65,

		B: 66,

		C: 67,

		D: 68,

		E: 69,

		F: 70,

		G: 71,

		H: 72,

		I: 73,

		J: 74,

		K: 75,

		L: 76,

		M: 77,

		N: 78,

		O: 79,

		P: 80,

		Q: 81,

		R: 82,

		S: 83,

		T: 84,

		U: 85,

		V: 86,

		W: 87,

		X: 88,

		Y: 89,

		Z: 90,

		CONTEXT_MENU: 93,

		NUM_ZERO: 96,

		NUM_ONE: 97,

		NUM_TWO: 98,

		NUM_THREE: 99,

		NUM_FOUR: 100,

		NUM_FIVE: 101,

		NUM_SIX: 102,

		NUM_SEVEN: 103,

		NUM_EIGHT: 104,

		NUM_NINE: 105,

		NUM_MULTIPLY: 106,

		NUM_PLUS: 107,

		NUM_MINUS: 109,

		NUM_PERIOD: 110,

		NUM_DIVISION: 111,

		F1: 112,

		F2: 113,

		F3: 114,

		F4: 115,

		F5: 116,

		F6: 117,

		F7: 118,

		F8: 119,

		F9: 120,

		F10: 121,

		F11: 122,

		F12: 123,

		setEvent: function(e) {
			if (e == this || (e && e.browserEvent)) {
				return e;
			}
			this.browserEvent = e;
			if (e) {
				this.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1: -1);
				if (e.type == 'click' && this.button == -1) {
					this.button = 0;
				}
				this.type = e.type;
				this.shiftKey = e.shiftKey;
				this.ctrlKey = e.ctrlKey || e.metaKey;
				this.altKey = e.altKey;
				this.keyCode = e.keyCode;
				this.charCode = e.charCode;
				this.target = E.getTarget(e);
				this.xy = E.getXY(e);
			} else {
				this.button = -1;
				this.shiftKey = false;
				this.ctrlKey = false;
				this.altKey = false;
				this.keyCode = 0;
				this.charCode = 0;
				this.target = null;
				this.xy = [0, 0];
			}
			return this;
		},

		stopEvent: function() {
			if (this.browserEvent) {
				if (this.browserEvent.type == 'mousedown') {
					Ext.EventManager.stoppedMouseDownEvent.fire(this);
				}
				E.stopEvent(this.browserEvent);
			}
		},

		preventDefault: function() {
			if (this.browserEvent) {
				E.preventDefault(this.browserEvent);
			}
		},

		isNavKeyPress: function() {
			var k = this.keyCode;
			k = Ext.isSafari ? (safariKeys[k] || k) : k;
			return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
		},

		isSpecialKey: function() {
			var k = this.keyCode;
			return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 || (k == 16) || (k == 17) || (k >= 18 && k <= 20) || (k >= 33 && k <= 35) || (k >= 36 && k <= 39) || (k >= 44 && k <= 45);
		},

		stopPropagation: function() {
			if (this.browserEvent) {
				if (this.browserEvent.type == 'mousedown') {
					Ext.EventManager.stoppedMouseDownEvent.fire(this);
				}
				E.stopPropagation(this.browserEvent);
			}
		},

		getCharCode: function() {
			return this.charCode || this.keyCode;
		},

		getKey: function() {
			var k = this.keyCode || this.charCode;
			return Ext.isSafari ? (safariKeys[k] || k) : k;
		},

		getPageX: function() {
			return this.xy[0];
		},

		getPageY: function() {
			return this.xy[1];
		},

		getTime: function() {
			if (this.browserEvent) {
				return E.getTime(this.browserEvent);
			}
			return null;
		},

		getXY: function() {
			return this.xy;
		},

		getTarget: function(selector, maxDepth, returnEl) {
			return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
		},

		getRelatedTarget: function() {
			if (this.browserEvent) {
				return E.getRelatedTarget(this.browserEvent);
			}
			return null;
		},

		getWheelDelta: function() {
			var e = this.browserEvent;
			var delta = 0;
			if (e.wheelDelta) {
				delta = e.wheelDelta / 120;
			} else if (e.detail) {
				delta = -e.detail / 3;
			}
			return delta;
		},

		hasModifier: function() {
			return ((this.ctrlKey || this.altKey) || this.shiftKey) ? true: false;
		},

		within: function(el, related) {
			var t = this[related ? "getRelatedTarget": "getTarget"]();
			return t && Ext.fly(el).contains(t);
		},

		getPoint: function() {
			return new Ext.lib.Point(this.xy[0], this.xy[1]);
		}
	};

	return new Ext.EventObjectImpl();
} ();
 (function() {
	var D = Ext.lib.Dom;
	var E = Ext.lib.Event;
	var A = Ext.lib.Anim;

	var propCache = {};
	var camelRe = /(-[a-z])/gi;
	var camelFn = function(m, a) {
		return a.charAt(1).toUpperCase();
	};
	var view = document.defaultView;

	Ext.Element = function(element, forceNew) {
		var dom = typeof element == "string" ? document.getElementById(element) : element;
		if (!dom) {
			return null;
		}
		var id = dom.id;
		if (forceNew !== true && id && Ext.Element.cache[id]) {
			return Ext.Element.cache[id];
		}

		this.dom = dom;

		this.id = id || Ext.id(dom);
	};

	var El = Ext.Element;

	El.prototype = {

		originalDisplay: "",

		visibilityMode: 1,

		defaultUnit: "px",

		setVisibilityMode: function(visMode) {
			this.visibilityMode = visMode;
			return this;
		},

		enableDisplayMode: function(display) {
			this.setVisibilityMode(El.DISPLAY);
			if (typeof display != "undefined") this.originalDisplay = display;
			return this;
		},

		findParent: function(simpleSelector, maxDepth, returnEl) {
			var p = this.dom,
			b = document.body,
			depth = 0,
			dq = Ext.DomQuery,
			stopEl;
			maxDepth = maxDepth || 50;
			if (typeof maxDepth != "number") {
				stopEl = Ext.getDom(maxDepth);
				maxDepth = 10;
			}
			while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
				if (dq.is(p, simpleSelector)) {
					return returnEl ? Ext.get(p) : p;
				}
				depth++;
				p = p.parentNode;
			}
			return null;
		},

		findParentNode: function(simpleSelector, maxDepth, returnEl) {
			var p = Ext.fly(this.dom.parentNode, '_internal');
			return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
		},

		up: function(simpleSelector, maxDepth) {
			return this.findParentNode(simpleSelector, maxDepth, true);
		},

		is: function(simpleSelector) {
			return Ext.DomQuery.is(this.dom, simpleSelector);
		},

		animate: function(args, duration, onComplete, easing, animType) {
			this.anim(args, {
				duration: duration,
				callback: onComplete,
				easing: easing
			},
			animType);
			return this;
		},

		anim: function(args, opt, animType, defaultDur, defaultEase, cb) {
			animType = animType || 'run';
			opt = opt || {};
			var anim = Ext.lib.Anim[animType](this.dom, args, (opt.duration || defaultDur) || .35, (opt.easing || defaultEase) || 'easeOut',
			function() {
				Ext.callback(cb, this);
				Ext.callback(opt.callback, opt.scope || this, [this, opt]);
			},
			this);
			opt.anim = anim;
			return anim;
		},

		preanim: function(a, i) {
			return ! a[i] ? false: (typeof a[i] == "object" ? a[i] : {
				duration: a[i + 1],
				callback: a[i + 2],
				easing: a[i + 3]
			});
		},

		clean: function(forceReclean) {
			if (this.isCleaned && forceReclean !== true) {
				return this;
			}
			var ns = /\S/;
			var d = this.dom,
			n = d.firstChild,
			ni = -1;
			while (n) {
				var nx = n.nextSibling;
				if (n.nodeType == 3 && !ns.test(n.nodeValue)) {
					d.removeChild(n);
				} else {
					n.nodeIndex = ++ni;
				}
				n = nx;
			}
			this.isCleaned = true;
			return this;
		},

		scrollIntoView: function(container, hscroll) {
			var c = Ext.getDom(container) || Ext.getBody().dom;
			var el = this.dom;

			var o = this.getOffsetsTo(c),
			l = o[0] + c.scrollLeft,
			t = o[1] + c.scrollTop,
			b = t + el.offsetHeight,
			r = l + el.offsetWidth;

			var ch = c.clientHeight;
			var ct = parseInt(c.scrollTop, 10);
			var cl = parseInt(c.scrollLeft, 10);
			var cb = ct + ch;
			var cr = cl + c.clientWidth;

			if (el.offsetHeight > ch || t < ct) {
				c.scrollTop = t;
			} else if (b > cb) {
				c.scrollTop = b - ch;
			}
			c.scrollTop = c.scrollTop;
			if (hscroll !== false) {
				if (el.offsetWidth > c.clientWidth || l < cl) {
					c.scrollLeft = l;
				} else if (r > cr) {
					c.scrollLeft = r - c.clientWidth;
				}
				c.scrollLeft = c.scrollLeft;
			}
			return this;
		},

		scrollChildIntoView: function(child, hscroll) {
			Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
		},

		autoHeight: function(animate, duration, onComplete, easing) {
			var oldHeight = this.getHeight();
			this.clip();
			this.setHeight(1);
			setTimeout(function() {
				var height = parseInt(this.dom.scrollHeight, 10);
				if (!animate) {
					this.setHeight(height);
					this.unclip();
					if (typeof onComplete == "function") {
						onComplete();
					}
				} else {
					this.setHeight(oldHeight);
					this.setHeight(height, animate, duration,
					function() {
						this.unclip();
						if (typeof onComplete == "function") onComplete();
					}.createDelegate(this), easing);
				}
			}.createDelegate(this), 0);
			return this;
		},

		contains: function(el) {
			if (!el) {
				return false;
			}
			return D.isAncestor(this.dom, el.dom ? el.dom: el);
		},

		isVisible: function(deep) {
			var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
			if (deep !== true || !vis) {
				return vis;
			}
			var p = this.dom.parentNode;
			while (p && p.tagName.toLowerCase() != "body") {
				if (!Ext.fly(p, '_isVisible').isVisible()) {
					return false;
				}
				p = p.parentNode;
			}
			return true;
		},

		select: function(selector, unique) {
			return El.select(selector, unique, this.dom);
		},

		query: function(selector) {
			return Ext.DomQuery.select(selector, this.dom);
		},

		child: function(selector, returnDom) {
			var n = Ext.DomQuery.selectNode(selector, this.dom);
			return returnDom ? n: Ext.get(n);
		},

		down: function(selector, returnDom) {
			var n = Ext.DomQuery.selectNode(" > " + selector, this.dom);
			return returnDom ? n: Ext.get(n);
		},

		initDD: function(group, config, overrides) {
			var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
			return Ext.apply(dd, overrides);
		},

		initDDProxy: function(group, config, overrides) {
			var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
			return Ext.apply(dd, overrides);
		},

		initDDTarget: function(group, config, overrides) {
			var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
			return Ext.apply(dd, overrides);
		},

		setVisible: function(visible, animate) {
			if (!animate || !A) {
				if (this.visibilityMode == El.DISPLAY) {
					this.setDisplayed(visible);
				} else {
					this.fixDisplay();
					this.dom.style.visibility = visible ? "visible": "hidden";
				}
			} else {
				var dom = this.dom;
				var visMode = this.visibilityMode;
				if (visible) {
					this.setOpacity(.01);
					this.setVisible(true);
				}
				this.anim({
					opacity: {
						to: (visible ? 1: 0)
					}
				},
				this.preanim(arguments, 1), null, .35, 'easeIn',
				function() {
					if (!visible) {
						if (visMode == El.DISPLAY) {
							dom.style.display = "none";
						} else {
							dom.style.visibility = "hidden";
						}
						Ext.get(dom).setOpacity(1);
					}
				});
			}
			return this;
		},

		isDisplayed: function() {
			return this.getStyle("display") != "none";
		},

		toggle: function(animate) {
			this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
			return this;
		},

		setDisplayed: function(value) {
			if (typeof value == "boolean") {
				value = value ? this.originalDisplay: "none";
			}
			this.setStyle("display", value);
			return this;
		},

		focus: function() {
			try {
				this.dom.focus();
			} catch(e) {}
			return this;
		},

		blur: function() {
			try {
				this.dom.blur();
			} catch(e) {}
			return this;
		},

		addClass: function(className) {
			if (Ext.isArray(className)) {
				for (var i = 0, len = className.length; i < len; i++) {
					this.addClass(className[i]);
				}
			} else {
				if (className && !this.hasClass(className)) {
					this.dom.className = this.dom.className + " " + className;
				}
			}
			return this;
		},

		radioClass: function(className) {
			var siblings = this.dom.parentNode.childNodes;
			for (var i = 0; i < siblings.length; i++) {
				var s = siblings[i];
				if (s.nodeType == 1) {
					Ext.get(s).removeClass(className);
				}
			}
			this.addClass(className);
			return this;
		},

		removeClass: function(className) {
			if (!className || !this.dom.className) {
				return this;
			}
			if (Ext.isArray(className)) {
				for (var i = 0, len = className.length; i < len; i++) {
					this.removeClass(className[i]);
				}
			} else {
				if (this.hasClass(className)) {
					var re = this.classReCache[className];
					if (!re) {
						re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
						this.classReCache[className] = re;
					}
					this.dom.className = this.dom.className.replace(re, " ");
				}
			}
			return this;
		},

		classReCache: {},

		toggleClass: function(className) {
			if (this.hasClass(className)) {
				this.removeClass(className);
			} else {
				this.addClass(className);
			}
			return this;
		},

		hasClass: function(className) {
			return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
		},

		replaceClass: function(oldClassName, newClassName) {
			this.removeClass(oldClassName);
			this.addClass(newClassName);
			return this;
		},

		getStyles: function() {
			var a = arguments,
			len = a.length,
			r = {};
			for (var i = 0; i < len; i++) {
				r[a[i]] = this.getStyle(a[i]);
			}
			return r;
		},

		getStyle: function() {
			return view && view.getComputedStyle ?
			function(prop) {
				var el = this.dom,
				v,
				cs,
				camel;
				if (prop == 'float') {
					prop = "cssFloat";
				}
				if (v = el.style[prop]) {
					return v;
				}
				if (cs = view.getComputedStyle(el, "")) {
					if (! (camel = propCache[prop])) {
						camel = propCache[prop] = prop.replace(camelRe, camelFn);
					}
					return cs[camel];
				}
				return null;
			}: function(prop) {
				var el = this.dom,
				v,
				cs,
				camel;
				if (prop == 'opacity') {
					if (typeof el.style.filter == 'string') {
						var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
						if (m) {
							var fv = parseFloat(m[1]);
							if (!isNaN(fv)) {
								return fv ? fv / 100: 0;
							}
						}
					}
					return 1;
				} else if (prop == 'float') {
					prop = "styleFloat";
				}
				if (! (camel = propCache[prop])) {
					camel = propCache[prop] = prop.replace(camelRe, camelFn);
				}
				if (v = el.style[camel]) {
					return v;
				}
				if (cs = el.currentStyle) {
					return cs[camel];
				}
				return null;
			};
		} (),

		setStyle: function(prop, value) {
			if (typeof prop == "string") {
				var camel;
				if (! (camel = propCache[prop])) {
					camel = propCache[prop] = prop.replace(camelRe, camelFn);
				}
				if (camel == 'opacity') {
					this.setOpacity(value);
				} else {
					this.dom.style[camel] = value;
				}
			} else {
				for (var style in prop) {
					if (typeof prop[style] != "function") {
						this.setStyle(style, prop[style]);
					}
				}
			}
			return this;
		},

		applyStyles: function(style) {
			Ext.DomHelper.applyStyles(this.dom, style);
			return this;
		},

		getX: function() {
			return D.getX(this.dom);
		},

		getY: function() {
			return D.getY(this.dom);
		},

		getXY: function() {
			return D.getXY(this.dom);
		},

		getOffsetsTo: function(el) {
			var o = this.getXY();
			var e = Ext.fly(el, '_internal').getXY();
			return [o[0] - e[0], o[1] - e[1]];
		},

		setX: function(x, animate) {
			if (!animate || !A) {
				D.setX(this.dom, x);
			} else {
				this.setXY([x, this.getY()], this.preanim(arguments, 1));
			}
			return this;
		},

		setY: function(y, animate) {
			if (!animate || !A) {
				D.setY(this.dom, y);
			} else {
				this.setXY([this.getX(), y], this.preanim(arguments, 1));
			}
			return this;
		},

		setLeft: function(left) {
			this.setStyle("left", this.addUnits(left));
			return this;
		},

		setTop: function(top) {
			this.setStyle("top", this.addUnits(top));
			return this;
		},

		setRight: function(right) {
			this.setStyle("right", this.addUnits(right));
			return this;
		},

		setBottom: function(bottom) {
			this.setStyle("bottom", this.addUnits(bottom));
			return this;
		},

		setXY: function(pos, animate) {
			if (!animate || !A) {
				D.setXY(this.dom, pos);
			} else {
				this.anim({
					points: {
						to: pos
					}
				},
				this.preanim(arguments, 1), 'motion');
			}
			return this;
		},

		setLocation: function(x, y, animate) {
			this.setXY([x, y], this.preanim(arguments, 2));
			return this;
		},

		moveTo: function(x, y, animate) {
			this.setXY([x, y], this.preanim(arguments, 2));
			return this;
		},

		getRegion: function() {
			return D.getRegion(this.dom);
		},

		getHeight: function(contentHeight) {
			var h = this.dom.offsetHeight || 0;
			h = contentHeight !== true ? h: h - this.getBorderWidth("tb") - this.getPadding("tb");
			return h < 0 ? 0: h;
		},

		getWidth: function(contentWidth) {
			var w = this.dom.offsetWidth || 0;
			w = contentWidth !== true ? w: w - this.getBorderWidth("lr") - this.getPadding("lr");
			return w < 0 ? 0: w;
		},

		getComputedHeight: function() {
			var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
			if (!h) {
				h = parseInt(this.getStyle('height'), 10) || 0;
				if (!this.isBorderBox()) {
					h += this.getFrameWidth('tb');
				}
			}
			return h;
		},

		getComputedWidth: function() {
			var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
			if (!w) {
				w = parseInt(this.getStyle('width'), 10) || 0;
				if (!this.isBorderBox()) {
					w += this.getFrameWidth('lr');
				}
			}
			return w;
		},

		getSize: function(contentSize) {
			return {
				width: this.getWidth(contentSize),
				height: this.getHeight(contentSize)
			};
		},

		getStyleSize: function() {
			var w,
			h,
			d = this.dom,
			s = d.style;
			if (s.width && s.width != 'auto') {
				w = parseInt(s.width, 10);
				if (Ext.isBorderBox) {
					w -= this.getFrameWidth('lr');
				}
			}
			if (s.height && s.height != 'auto') {
				h = parseInt(s.height, 10);
				if (Ext.isBorderBox) {
					h -= this.getFrameWidth('tb');
				}
			}
			return {
				width: w || this.getWidth(true),
				height: h || this.getHeight(true)
			};

		},

		getViewSize: function() {
			var d = this.dom,
			doc = document,
			aw = 0,
			ah = 0;
			if (d == doc || d == doc.body) {
				return {
					width: D.getViewWidth(),
					height: D.getViewHeight()
				};
			} else {
				return {
					width: d.clientWidth,
					height: d.clientHeight
				};
			}
		},

		getValue: function(asNumber) {
			return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
		},

		adjustWidth: function(width) {
			if (typeof width == "number") {
				if (this.autoBoxAdjust && !this.isBorderBox()) {
					width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
				}
				if (width < 0) {
					width = 0;
				}
			}
			return width;
		},

		adjustHeight: function(height) {
			if (typeof height == "number") {
				if (this.autoBoxAdjust && !this.isBorderBox()) {
					height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
				}
				if (height < 0) {
					height = 0;
				}
			}
			return height;
		},

		setWidth: function(width, animate) {
			width = this.adjustWidth(width);
			if (!animate || !A) {
				this.dom.style.width = this.addUnits(width);
			} else {
				this.anim({
					width: {
						to: width
					}
				},
				this.preanim(arguments, 1));
			}
			return this;
		},

		setHeight: function(height, animate) {
			height = this.adjustHeight(height);
			if (!animate || !A) {
				this.dom.style.height = this.addUnits(height);
			} else {
				this.anim({
					height: {
						to: height
					}
				},
				this.preanim(arguments, 1));
			}
			return this;
		},

		setSize: function(width, height, animate) {
			if (typeof width == "object") {
				height = width.height;
				width = width.width;
			}
			width = this.adjustWidth(width);
			height = this.adjustHeight(height);
			if (!animate || !A) {
				this.dom.style.width = this.addUnits(width);
				this.dom.style.height = this.addUnits(height);
			} else {
				this.anim({
					width: {
						to: width
					},
					height: {
						to: height
					}
				},
				this.preanim(arguments, 2));
			}
			return this;
		},

		setBounds: function(x, y, width, height, animate) {
			if (!animate || !A) {
				this.setSize(width, height);
				this.setLocation(x, y);
			} else {
				width = this.adjustWidth(width);
				height = this.adjustHeight(height);
				this.anim({
					points: {
						to: [x, y]
					},
					width: {
						to: width
					},
					height: {
						to: height
					}
				},
				this.preanim(arguments, 4), 'motion');
			}
			return this;
		},

		setRegion: function(region, animate) {
			this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, this.preanim(arguments, 1));
			return this;
		},

		addListener: function(eventName, fn, scope, options) {
			Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
		},

		removeListener: function(eventName, fn, scope) {
			Ext.EventManager.removeListener(this.dom, eventName, fn, scope || this);
			return this;
		},

		removeAllListeners: function() {
			Ext.EventManager.removeAll(this.dom);
			return this;
		},

		relayEvent: function(eventName, observable) {
			this.on(eventName,
			function(e) {
				observable.fireEvent(eventName, e);
			});
		},

		setOpacity: function(opacity, animate) {
			if (!animate || !A) {
				var s = this.dom.style;
				if (Ext.isIE) {
					s.zoom = 1;
					s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi, "") + (opacity == 1 ? "": " alpha(opacity=" + opacity * 100 + ")");
				} else {
					s.opacity = opacity;
				}
			} else {
				this.anim({
					opacity: {
						to: opacity
					}
				},
				this.preanim(arguments, 1), null, .35, 'easeIn');
			}
			return this;
		},

		getLeft: function(local) {
			if (!local) {
				return this.getX();
			} else {
				return parseInt(this.getStyle("left"), 10) || 0;
			}
		},

		getRight: function(local) {
			if (!local) {
				return this.getX() + this.getWidth();
			} else {
				return (this.getLeft(true) + this.getWidth()) || 0;
			}
		},

		getTop: function(local) {
			if (!local) {
				return this.getY();
			} else {
				return parseInt(this.getStyle("top"), 10) || 0;
			}
		},

		getBottom: function(local) {
			if (!local) {
				return this.getY() + this.getHeight();
			} else {
				return (this.getTop(true) + this.getHeight()) || 0;
			}
		},

		position: function(pos, zIndex, x, y) {
			if (!pos) {
				if (this.getStyle('position') == 'static') {
					this.setStyle('position', 'relative');
				}
			} else {
				this.setStyle("position", pos);
			}
			if (zIndex) {
				this.setStyle("z-index", zIndex);
			}
			if (x !== undefined && y !== undefined) {
				this.setXY([x, y]);
			} else if (x !== undefined) {
				this.setX(x);
			} else if (y !== undefined) {
				this.setY(y);
			}
		},

		clearPositioning: function(value) {
			value = value || '';
			this.setStyle({
				"left": value,
				"right": value,
				"top": value,
				"bottom": value,
				"z-index": "",
				"position": "static"
			});
			return this;
		},

		getPositioning: function() {
			var l = this.getStyle("left");
			var t = this.getStyle("top");
			return {
				"position": this.getStyle("position"),
				"left": l,
				"right": l ? "": this.getStyle("right"),
				"top": t,
				"bottom": t ? "": this.getStyle("bottom"),
				"z-index": this.getStyle("z-index")
			};
		},

		getBorderWidth: function(side) {
			return this.addStyles(side, El.borders);
		},

		getPadding: function(side) {
			return this.addStyles(side, El.paddings);
		},

		setPositioning: function(pc) {
			this.applyStyles(pc);
			if (pc.right == "auto") {
				this.dom.style.right = "";
			}
			if (pc.bottom == "auto") {
				this.dom.style.bottom = "";
			}
			return this;
		},

		fixDisplay: function() {
			if (this.getStyle("display") == "none") {
				this.setStyle("visibility", "hidden");
				this.setStyle("display", this.originalDisplay);
				if (this.getStyle("display") == "none") {
					this.setStyle("display", "block");
				}
			}
		},

		setOverflow: function(v) {
			if (v == 'auto' && Ext.isMac && Ext.isGecko2) {
				this.dom.style.overflow = 'hidden'; (function() {
					this.dom.style.overflow = 'auto';
				}).defer(1, this);
			} else {
				this.dom.style.overflow = v;
			}
		},

		setLeftTop: function(left, top) {
			this.dom.style.left = this.addUnits(left);
			this.dom.style.top = this.addUnits(top);
			return this;
		},

		move: function(direction, distance, animate) {
			var xy = this.getXY();
			direction = direction.toLowerCase();
			switch (direction) {
			case "l":
			case "left":
				this.moveTo(xy[0] - distance, xy[1], this.preanim(arguments, 2));
				break;
			case "r":
			case "right":
				this.moveTo(xy[0] + distance, xy[1], this.preanim(arguments, 2));
				break;
			case "t":
			case "top":
			case "up":
				this.moveTo(xy[0], xy[1] - distance, this.preanim(arguments, 2));
				break;
			case "b":
			case "bottom":
			case "down":
				this.moveTo(xy[0], xy[1] + distance, this.preanim(arguments, 2));
				break;
			}
			return this;
		},

		clip: function() {
			if (!this.isClipped) {
				this.isClipped = true;
				this.originalClip = {
					"o": this.getStyle("overflow"),
					"x": this.getStyle("overflow-x"),
					"y": this.getStyle("overflow-y")
				};
				this.setStyle("overflow", "hidden");
				this.setStyle("overflow-x", "hidden");
				this.setStyle("overflow-y", "hidden");
			}
			return this;
		},

		unclip: function() {
			if (this.isClipped) {
				this.isClipped = false;
				var o = this.originalClip;
				if (o.o) {
					this.setStyle("overflow", o.o);
				}
				if (o.x) {
					this.setStyle("overflow-x", o.x);
				}
				if (o.y) {
					this.setStyle("overflow-y", o.y);
				}
			}
			return this;
		},

		getAnchorXY: function(anchor, local, s) {

			var w,
			h,
			vp = false;
			if (!s) {
				var d = this.dom;
				if (d == document.body || d == document) {
					vp = true;
					w = D.getViewWidth();
					h = D.getViewHeight();
				} else {
					w = this.getWidth();
					h = this.getHeight();
				}
			} else {
				w = s.width;
				h = s.height;
			}
			var x = 0,
			y = 0,
			r = Math.round;
			switch ((anchor || "tl").toLowerCase()) {
			case "c":
				x = r(w * .5);
				y = r(h * .5);
				break;
			case "t":
				x = r(w * .5);
				y = 0;
				break;
			case "l":
				x = 0;
				y = r(h * .5);
				break;
			case "r":
				x = w;
				y = r(h * .5);
				break;
			case "b":
				x = r(w * .5);
				y = h;
				break;
			case "tl":
				x = 0;
				y = 0;
				break;
			case "bl":
				x = 0;
				y = h;
				break;
			case "br":
				x = w;
				y = h;
				break;
			case "tr":
				x = w;
				y = 0;
				break;
			}
			if (local === true) {
				return [x, y];
			}
			if (vp) {
				var sc = this.getScroll();
				return [x + sc.left, y + sc.top];
			}
			var o = this.getXY();
			return [x + o[0], y + o[1]];
		},

		getAlignToXY: function(el, p, o) {
			el = Ext.get(el);
			if (!el || !el.dom) {
				throw "Element.alignToXY with an element that doesn't exist";
			}
			var d = this.dom;
			var c = false;
			var p1 = "",
			p2 = "";
			o = o || [0, 0];

			if (!p) {
				p = "tl-bl";
			} else if (p == "?") {
				p = "tl-bl?";
			} else if (p.indexOf("-") == -1) {
				p = "tl-" + p;
			}
			p = p.toLowerCase();
			var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
			if (!m) {
				throw "Element.alignTo with an invalid alignment " + p;
			}
			p1 = m[1];
			p2 = m[2];
			c = !!m[3];

			var a1 = this.getAnchorXY(p1, true);
			var a2 = el.getAnchorXY(p2, false);

			var x = a2[0] - a1[0] + o[0];
			var y = a2[1] - a1[1] + o[1];

			if (c) {
				var w = this.getWidth(),
				h = this.getHeight(),
				r = el.getRegion();
				var dw = D.getViewWidth() - 5,
				dh = D.getViewHeight() - 5;

				var p1y = p1.charAt(0),
				p1x = p1.charAt(p1.length - 1);
				var p2y = p2.charAt(0),
				p2x = p2.charAt(p2.length - 1);
				var swapY = ((p1y == "t" && p2y == "b") || (p1y == "b" && p2y == "t"));
				var swapX = ((p1x == "r" && p2x == "l") || (p1x == "l" && p2x == "r"));

				var doc = document;
				var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0) + 5;
				var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0) + 5;

				if ((x + w) > dw + scrollX) {
					x = swapX ? r.left - w: dw + scrollX - w;
				}
				if (x < scrollX) {
					x = swapX ? r.right: scrollX;
				}
				if ((y + h) > dh + scrollY) {
					y = swapY ? r.top - h: dh + scrollY - h;
				}
				if (y < scrollY) {
					y = swapY ? r.bottom: scrollY;
				}
			}
			return [x, y];
		},

		getConstrainToXY: function() {
			var os = {
				top: 0,
				left: 0,
				bottom: 0,
				right: 0
			};

			return function(el, local, offsets, proposedXY) {
				el = Ext.get(el);
				offsets = offsets ? Ext.applyIf(offsets, os) : os;

				var vw,
				vh,
				vx = 0,
				vy = 0;
				if (el.dom == document.body || el.dom == document) {
					vw = Ext.lib.Dom.getViewWidth();
					vh = Ext.lib.Dom.getViewHeight();
				} else {
					vw = el.dom.clientWidth;
					vh = el.dom.clientHeight;
					if (!local) {
						var vxy = el.getXY();
						vx = vxy[0];
						vy = vxy[1];
					}
				}

				var s = el.getScroll();

				vx += offsets.left + s.left;
				vy += offsets.top + s.top;

				vw -= offsets.right;
				vh -= offsets.bottom;

				var vr = vx + vw;
				var vb = vy + vh;

				var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
				var x = xy[0],
				y = xy[1];
				var w = this.dom.offsetWidth,
				h = this.dom.offsetHeight;

				var moved = false;

				if ((x + w) > vr) {
					x = vr - w;
					moved = true;
				}
				if ((y + h) > vb) {
					y = vb - h;
					moved = true;
				}
				if (x < vx) {
					x = vx;
					moved = true;
				}
				if (y < vy) {
					y = vy;
					moved = true;
				}
				return moved ? [x, y] : false;
			};
		} (),

		adjustForConstraints: function(xy, parent, offsets) {
			return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
		},

		alignTo: function(element, position, offsets, animate) {
			var xy = this.getAlignToXY(element, position, offsets);
			this.setXY(xy, this.preanim(arguments, 3));
			return this;
		},

		anchorTo: function(el, alignment, offsets, animate, monitorScroll, callback) {
			var action = function() {
				this.alignTo(el, alignment, offsets, animate);
				Ext.callback(callback, this);
			};
			Ext.EventManager.onWindowResize(action, this);
			var tm = typeof monitorScroll;
			if (tm != 'undefined') {
				Ext.EventManager.on(window, 'scroll', action, this, {
					buffer: tm == 'number' ? monitorScroll: 50
				});
			}
			action.call(this);
			return this;
		},

		clearOpacity: function() {
			if (window.ActiveXObject) {
				if (typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)) {
					this.dom.style.filter = "";
				}
			} else {
				this.dom.style.opacity = "";
				this.dom.style["-moz-opacity"] = "";
				this.dom.style["-khtml-opacity"] = "";
			}
			return this;
		},

		hide: function(animate) {
			this.setVisible(false, this.preanim(arguments, 0));
			return this;
		},

		show: function(animate) {
			this.setVisible(true, this.preanim(arguments, 0));
			return this;
		},

		addUnits: function(size) {
			return Ext.Element.addUnits(size, this.defaultUnit);
		},

		update: function(html, loadScripts, callback) {
			if (typeof html == "undefined") {
				html = "";
			}
			if (loadScripts !== true) {
				this.dom.innerHTML = html;
				if (typeof callback == "function") {
					callback();
				}
				return this;
			}
			var id = Ext.id();
			var dom = this.dom;

			html += '<span id="' + id + '"></span>';

			E.onAvailable(id,
			function() {
				var hd = document.getElementsByTagName("head")[0];
				var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
				var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
				var typeRe = /\stype=([\'\"])(.*?)\1/i;

				var match;
				while (match = re.exec(html)) {
					var attrs = match[1];
					var srcMatch = attrs ? attrs.match(srcRe) : false;
					if (srcMatch && srcMatch[2]) {
						var s = document.createElement("script");
						s.src = srcMatch[2];
						var typeMatch = attrs.match(typeRe);
						if (typeMatch && typeMatch[2]) {
							s.type = typeMatch[2];
						}
						hd.appendChild(s);
					} else if (match[2] && match[2].length > 0) {
						if (window.execScript) {
							window.execScript(match[2]);
						} else {
							window.eval(match[2]);
						}
					}
				}
				var el = document.getElementById(id);
				if (el) {
					Ext.removeNode(el);
				}
				if (typeof callback == "function") {
					callback();
				}
			});
			dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
			return this;
		},

		load: function() {
			var um = this.getUpdater();
			um.update.apply(um, arguments);
			return this;
		},

		getUpdater: function() {
			if (!this.updateManager) {
				this.updateManager = new Ext.Updater(this);
			}
			return this.updateManager;
		},

		unselectable: function() {
			this.dom.unselectable = "on";
			this.swallowEvent("selectstart", true);
			this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
			this.addClass("x-unselectable");
			return this;
		},

		getCenterXY: function() {
			return this.getAlignToXY(document, 'c-c');
		},

		center: function(centerIn) {
			this.alignTo(centerIn || document, 'c-c');
			return this;
		},

		isBorderBox: function() {
			return noBoxAdjust[this.dom.tagName.toLowerCase()] || Ext.isBorderBox;
		},

		getBox: function(contentBox, local) {
			var xy;
			if (!local) {
				xy = this.getXY();
			} else {
				var left = parseInt(this.getStyle("left"), 10) || 0;
				var top = parseInt(this.getStyle("top"), 10) || 0;
				xy = [left, top];
			}
			var el = this.dom,
			w = el.offsetWidth,
			h = el.offsetHeight,
			bx;
			if (!contentBox) {
				bx = {
					x: xy[0],
					y: xy[1],
					0: xy[0],
					1: xy[1],
					width: w,
					height: h
				};
			} else {
				var l = this.getBorderWidth("l") + this.getPadding("l");
				var r = this.getBorderWidth("r") + this.getPadding("r");
				var t = this.getBorderWidth("t") + this.getPadding("t");
				var b = this.getBorderWidth("b") + this.getPadding("b");
				bx = {
					x: xy[0] + l,
					y: xy[1] + t,
					0: xy[0] + l,
					1: xy[1] + t,
					width: w - (l + r),
					height: h - (t + b)
				};
			}
			bx.right = bx.x + bx.width;
			bx.bottom = bx.y + bx.height;
			return bx;
		},

		getFrameWidth: function(sides, onlyContentBox) {
			return onlyContentBox && Ext.isBorderBox ? 0: (this.getPadding(sides) + this.getBorderWidth(sides));
		},

		setBox: function(box, adjust, animate) {
			var w = box.width,
			h = box.height;
			if ((adjust && !this.autoBoxAdjust) && !this.isBorderBox()) {
				w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
				h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
			}
			this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
			return this;
		},

		repaint: function() {
			var dom = this.dom;
			this.addClass("x-repaint");
			setTimeout(function() {
				Ext.get(dom).removeClass("x-repaint");
			},
			1);
			return this;
		},

		getMargins: function(side) {
			if (!side) {
				return {
					top: parseInt(this.getStyle("margin-top"), 10) || 0,
					left: parseInt(this.getStyle("margin-left"), 10) || 0,
					bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
					right: parseInt(this.getStyle("margin-right"), 10) || 0
				};
			} else {
				return this.addStyles(side, El.margins);
			}
		},

		addStyles: function(sides, styles) {
			var val = 0,
			v,
			w;
			for (var i = 0, len = sides.length; i < len; i++) {
				v = this.getStyle(styles[sides.charAt(i)]);
				if (v) {
					w = parseInt(v, 10);
					if (w) {
						val += (w >= 0 ? w: -1 * w);
					}
				}
			}
			return val;
		},

		createProxy: function(config, renderTo, matchBox) {
			config = typeof config == "object" ? config: {
				tag: "div",
				cls: config
			};

			var proxy;
			if (renderTo) {
				proxy = Ext.DomHelper.append(renderTo, config, true);
			} else {
				proxy = Ext.DomHelper.insertBefore(this.dom, config, true);
			}
			if (matchBox) {
				proxy.setBox(this.getBox());
			}
			return proxy;
		},

		mask: function(msg, msgCls) {
			if (this.getStyle("position") == "static") {
				this.setStyle("position", "relative");
			}
			if (this._maskMsg) {
				this._maskMsg.remove();
			}
			if (this._mask) {
				this._mask.remove();
			}

			this._mask = Ext.DomHelper.append(this.dom, {
				cls: "ext-el-mask"
			},
			true);

			this.addClass("x-masked");
			this._mask.setDisplayed(true);
			if (typeof msg == 'string') {
				this._maskMsg = Ext.DomHelper.append(this.dom, {
					cls: "ext-el-mask-msg",
					cn: {
						tag: 'div'
					}
				},
				true);
				var mm = this._maskMsg;
				mm.dom.className = msgCls ? "ext-el-mask-msg " + msgCls: "ext-el-mask-msg";
				mm.dom.firstChild.innerHTML = msg;
				mm.setDisplayed(true);
				mm.center(this);
			}
			if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && this.getStyle('height') == 'auto') {
				this._mask.setSize(this.dom.clientWidth, this.getHeight());
			}
			return this._mask;
		},

		unmask: function() {
			if (this._mask) {
				if (this._maskMsg) {
					this._maskMsg.remove();
					delete this._maskMsg;
				}
				this._mask.remove();
				delete this._mask;
			}
			this.removeClass("x-masked");
		},

		isMasked: function() {
			return this._mask && this._mask.isVisible();
		},

		createShim: function() {
			var el = document.createElement('iframe');
			el.frameBorder = '0';
			el.className = 'ext-shim';
			if (Ext.isIE && Ext.isSecure) {
				el.src = Ext.SSL_SECURE_URL;
			}
			var shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
			shim.autoBoxAdjust = false;
			return shim;
		},

		remove: function() {
			Ext.removeNode(this.dom);
			delete El.cache[this.dom.id];
		},

		hover: function(overFn, outFn, scope) {
			var preOverFn = function(e) {
				if (!e.within(this, true)) {
					overFn.apply(scope || this, arguments);
				}
			};
			var preOutFn = function(e) {
				if (!e.within(this, true)) {
					outFn.apply(scope || this, arguments);
				}
			};
			this.on("mouseover", preOverFn, this.dom);
			this.on("mouseout", preOutFn, this.dom);
			return this;
		},

		addClassOnOver: function(className) {
			this.hover(function() {
				Ext.fly(this, '_internal').addClass(className);
			},
			function() {
				Ext.fly(this, '_internal').removeClass(className);
			});
			return this;
		},

		addClassOnFocus: function(className) {
			this.on("focus",
			function() {
				Ext.fly(this, '_internal').addClass(className);
			},
			this.dom);
			this.on("blur",
			function() {
				Ext.fly(this, '_internal').removeClass(className);
			},
			this.dom);
			return this;
		},

		addClassOnClick: function(className) {
			var dom = this.dom;
			this.on("mousedown",
			function() {
				Ext.fly(dom, '_internal').addClass(className);
				var d = Ext.getDoc();
				var fn = function() {
					Ext.fly(dom, '_internal').removeClass(className);
					d.removeListener("mouseup", fn);
				};
				d.on("mouseup", fn);
			});
			return this;
		},

		swallowEvent: function(eventName, preventDefault) {
			var fn = function(e) {
				e.stopPropagation();
				if (preventDefault) {
					e.preventDefault();
				}
			};
			if (Ext.isArray(eventName)) {
				for (var i = 0, len = eventName.length; i < len; i++) {
					this.on(eventName[i], fn);
				}
				return this;
			}
			this.on(eventName, fn);
			return this;
		},

		parent: function(selector, returnDom) {
			return this.matchNode('parentNode', 'parentNode', selector, returnDom);
		},

		next: function(selector, returnDom) {
			return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
		},

		prev: function(selector, returnDom) {
			return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
		},

		first: function(selector, returnDom) {
			return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
		},

		last: function(selector, returnDom) {
			return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
		},

		matchNode: function(dir, start, selector, returnDom) {
			var n = this.dom[start];
			while (n) {
				if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) {
					return ! returnDom ? Ext.get(n) : n;
				}
				n = n[dir];
			}
			return null;
		},

		appendChild: function(el) {
			el = Ext.get(el);
			el.appendTo(this);
			return this;
		},

		createChild: function(config, insertBefore, returnDom) {
			config = config || {
				tag: 'div'
			};
			if (insertBefore) {
				return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
			}
			return Ext.DomHelper[!this.dom.firstChild ? 'overwrite': 'append'](this.dom, config, returnDom !== true);
		},

		appendTo: function(el) {
			el = Ext.getDom(el);
			el.appendChild(this.dom);
			return this;
		},

		insertBefore: function(el) {
			el = Ext.getDom(el);
			el.parentNode.insertBefore(this.dom, el);
			return this;
		},

		insertAfter: function(el) {
			el = Ext.getDom(el);
			el.parentNode.insertBefore(this.dom, el.nextSibling);
			return this;
		},

		insertFirst: function(el, returnDom) {
			el = el || {};
			if (typeof el == 'object' && !el.nodeType && !el.dom) {
				return this.createChild(el, this.dom.firstChild, returnDom);
			} else {
				el = Ext.getDom(el);
				this.dom.insertBefore(el, this.dom.firstChild);
				return ! returnDom ? Ext.get(el) : el;
			}
		},

		insertSibling: function(el, where, returnDom) {
			var rt;
			if (Ext.isArray(el)) {
				for (var i = 0, len = el.length; i < len; i++) {
					rt = this.insertSibling(el[i], where, returnDom);
				}
				return rt;
			}
			where = where ? where.toLowerCase() : 'before';
			el = el || {};
			var refNode = where == 'before' ? this.dom: this.dom.nextSibling;

			if (typeof el == 'object' && !el.nodeType && !el.dom) {
				if (where == 'after' && !this.dom.nextSibling) {
					rt = Ext.DomHelper.append(this.dom.parentNode, el, !returnDom);
				} else {
					rt = Ext.DomHelper[where == 'after' ? 'insertAfter': 'insertBefore'](this.dom, el, !returnDom);
				}

			} else {
				rt = this.dom.parentNode.insertBefore(Ext.getDom(el), refNode);
				if (!returnDom) {
					rt = Ext.get(rt);
				}
			}
			return rt;
		},

		wrap: function(config, returnDom) {
			if (!config) {
				config = {
					tag: "div"
				};
			}
			var newEl = Ext.DomHelper.insertBefore(this.dom, config, !returnDom);
			newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
			return newEl;
		},

		replace: function(el) {
			el = Ext.get(el);
			this.insertBefore(el);
			el.remove();
			return this;
		},

		replaceWith: function(el) {
			if (typeof el == 'object' && !el.nodeType && !el.dom) {
				el = this.insertSibling(el, 'before');
			} else {
				el = Ext.getDom(el);
				this.dom.parentNode.insertBefore(el, this.dom);
			}
			El.uncache(this.id);
			this.dom.parentNode.removeChild(this.dom);
			this.dom = el;
			this.id = Ext.id(el);
			El.cache[this.id] = this;
			return this;
		},

		insertHtml: function(where, html, returnEl) {
			var el = Ext.DomHelper.insertHtml(where, this.dom, html);
			return returnEl ? Ext.get(el) : el;
		},

		set: function(o, useSet) {
			var el = this.dom;
			useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true: false) : useSet;
			for (var attr in o) {
				if (attr == "style" || typeof o[attr] == "function") continue;
				if (attr == "cls") {
					el.className = o["cls"];
				} else if (o.hasOwnProperty(attr)) {
					if (useSet) el.setAttribute(attr, o[attr]);
					else el[attr] = o[attr];
				}
			}
			if (o.style) {
				Ext.DomHelper.applyStyles(el, o.style);
			}
			return this;
		},

		addKeyListener: function(key, fn, scope) {
			var config;
			if (typeof key != "object" || Ext.isArray(key)) {
				config = {
					key: key,
					fn: fn,
					scope: scope
				};
			} else {
				config = {
					key: key.key,
					shift: key.shift,
					ctrl: key.ctrl,
					alt: key.alt,
					fn: fn,
					scope: scope
				};
			}
			return new Ext.KeyMap(this, config);
		},

		addKeyMap: function(config) {
			return new Ext.KeyMap(this, config);
		},

		isScrollable: function() {
			var dom = this.dom;
			return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
		},

		scrollTo: function(side, value, animate) {
			var prop = side.toLowerCase() == "left" ? "scrollLeft": "scrollTop";
			if (!animate || !A) {
				this.dom[prop] = value;
			} else {
				var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
				this.anim({
					scroll: {
						"to": to
					}
				},
				this.preanim(arguments, 2), 'scroll');
			}
			return this;
		},

		scroll: function(direction, distance, animate) {
			if (!this.isScrollable()) {
				return;
			}
			var el = this.dom;
			var l = el.scrollLeft,
			t = el.scrollTop;
			var w = el.scrollWidth,
			h = el.scrollHeight;
			var cw = el.clientWidth,
			ch = el.clientHeight;
			direction = direction.toLowerCase();
			var scrolled = false;
			var a = this.preanim(arguments, 2);
			switch (direction) {
			case "l":
			case "left":
				if (w - l > cw) {
					var v = Math.min(l + distance, w - cw);
					this.scrollTo("left", v, a);
					scrolled = true;
				}
				break;
			case "r":
			case "right":
				if (l > 0) {
					var v = Math.max(l - distance, 0);
					this.scrollTo("left", v, a);
					scrolled = true;
				}
				break;
			case "t":
			case "top":
			case "up":
				if (t > 0) {
					var v = Math.max(t - distance, 0);
					this.scrollTo("top", v, a);
					scrolled = true;
				}
				break;
			case "b":
			case "bottom":
			case "down":
				if (h - t > ch) {
					var v = Math.min(t + distance, h - ch);
					this.scrollTo("top", v, a);
					scrolled = true;
				}
				break;
			}
			return scrolled;
		},

		translatePoints: function(x, y) {
			if (typeof x == 'object' || Ext.isArray(x)) {
				y = x[1];
				x = x[0];
			}
			var p = this.getStyle('position');
			var o = this.getXY();

			var l = parseInt(this.getStyle('left'), 10);
			var t = parseInt(this.getStyle('top'), 10);

			if (isNaN(l)) {
				l = (p == "relative") ? 0: this.dom.offsetLeft;
			}
			if (isNaN(t)) {
				t = (p == "relative") ? 0: this.dom.offsetTop;
			}

			return {
				left: (x - o[0] + l),
				top: (y - o[1] + t)
			};
		},

		getScroll: function() {
			var d = this.dom,
			doc = document;
			if (d == doc || d == doc.body) {
				var l,
				t;
				if (Ext.isIE && Ext.isStrict) {
					l = doc.documentElement.scrollLeft || (doc.body.scrollLeft || 0);
					t = doc.documentElement.scrollTop || (doc.body.scrollTop || 0);
				} else {
					l = window.pageXOffset || (doc.body.scrollLeft || 0);
					t = window.pageYOffset || (doc.body.scrollTop || 0);
				}
				return {
					left: l,
					top: t
				};
			} else {
				return {
					left: d.scrollLeft,
					top: d.scrollTop
				};
			}
		},

		getColor: function(attr, defaultValue, prefix) {
			var v = this.getStyle(attr);
			if (!v || v == "transparent" || v == "inherit") {
				return defaultValue;
			}
			var color = typeof prefix == "undefined" ? "#": prefix;
			if (v.substr(0, 4) == "rgb(") {
				var rvs = v.slice(4, v.length - 1).split(",");
				for (var i = 0; i < 3; i++) {
					var h = parseInt(rvs[i]);
					var s = h.toString(16);
					if (h < 16) {
						s = "0" + s;
					}
					color += s;
				}
			} else {
				if (v.substr(0, 1) == "#") {
					if (v.length == 4) {
						for (var i = 1; i < 4; i++) {
							var c = v.charAt(i);
							color += c + c;
						}
					} else if (v.length == 7) {
						color += v.substr(1);
					}
				}
			}
			return (color.length > 5 ? color.toLowerCase() : defaultValue);
		},

		boxWrap: function(cls) {
			cls = cls || 'x-box';
			var el = Ext.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">' + El.boxMarkup + '</div>', cls)));
			el.child('.' + cls + '-mc').dom.appendChild(this.dom);
			return el;
		},

		getAttributeNS: Ext.isIE ?
		function(ns, name) {
			var d = this.dom;
			var type = typeof d[ns + ":" + name];
			if (type != 'undefined' && type != 'unknown') {
				return d[ns + ":" + name];
			}
			return d[name];
		}: function(ns, name) {
			var d = this.dom;
			return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
		},

		getTextWidth: function(text, min, max) {
			return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
		}
	};

	var ep = El.prototype;

	ep.on = ep.addListener;
	ep.mon = ep.addListener;

	ep.getUpdateManager = ep.getUpdater;

	ep.un = ep.removeListener;

	ep.autoBoxAdjust = true;

	El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;

	El.addUnits = function(v, defaultUnit) {
		if (v === "" || v == "auto") {
			return v;
		}
		if (v === undefined) {
			return '';
		}
		if (typeof v == "number" || !El.unitPattern.test(v)) {
			return v + (defaultUnit || 'px');
		}
		return v;
	};

	El.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';

	El.VISIBILITY = 1;

	El.DISPLAY = 2;

	El.borders = {
		l: "border-left-width",
		r: "border-right-width",
		t: "border-top-width",
		b: "border-bottom-width"
	};
	El.paddings = {
		l: "padding-left",
		r: "padding-right",
		t: "padding-top",
		b: "padding-bottom"
	};
	El.margins = {
		l: "margin-left",
		r: "margin-right",
		t: "margin-top",
		b: "margin-bottom"
	};

	El.cache = {};

	var docEl;

	El.get = function(el) {
		var ex,
		elm,
		id;
		if (!el) {
			return null;
		}
		if (typeof el == "string") {
			if (! (elm = document.getElementById(el))) {
				return null;
			}
			if (ex = El.cache[el]) {
				ex.dom = elm;
			} else {
				ex = El.cache[el] = new El(elm);
			}
			return ex;
		} else if (el.tagName) {
			if (! (id = el.id)) {
				id = Ext.id(el);
			}
			if (ex = El.cache[id]) {
				ex.dom = el;
			} else {
				ex = El.cache[id] = new El(el);
			}
			return ex;
		} else if (el instanceof El) {
			if (el != docEl) {
				el.dom = document.getElementById(el.id) || el.dom;
				El.cache[el.id] = el;
			}
			return el;
		} else if (el.isComposite) {
			return el;
		} else if (Ext.isArray(el)) {
			return El.select(el);
		} else if (el == document) {
			if (!docEl) {
				var f = function() {};
				f.prototype = El.prototype;
				docEl = new f();
				docEl.dom = document;
			}
			return docEl;
		}
		return null;
	};

	El.uncache = function(el) {
		for (var i = 0, a = arguments, len = a.length; i < len; i++) {
			if (a[i]) {
				delete El.cache[a[i].id || a[i]];
			}
		}
	};

	El.garbageCollect = function() {
		if (!Ext.enableGarbageCollector) {
			clearInterval(El.collectorThread);
			return;
		}
		for (var eid in El.cache) {
			var el = El.cache[eid],
			d = el.dom;
			if (!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))) {
				delete El.cache[eid];
				if (d && Ext.enableListenerCollection) {
					Ext.EventManager.removeAll(d);
				}
			}
		}
	}
	El.collectorThreadId = setInterval(El.garbageCollect, 30000);

	var flyFn = function() {};
	flyFn.prototype = El.prototype;
	var _cls = new flyFn();

	El.Flyweight = function(dom) {
		this.dom = dom;
	};

	El.Flyweight.prototype = _cls;
	El.Flyweight.prototype.isFlyweight = true;

	El._flyweights = {};

	El.fly = function(el, named) {
		named = named || '_global';
		el = Ext.getDom(el);
		if (!el) {
			return null;
		}
		if (!El._flyweights[named]) {
			El._flyweights[named] = new El.Flyweight();
		}
		El._flyweights[named].dom = el;
		return El._flyweights[named];
	};

	Ext.get = El.get;

	Ext.fly = El.fly;

	var noBoxAdjust = Ext.isStrict ? {
		select: 1
	}: {
		input: 1,
		select: 1,
		textarea: 1
	};
	if (Ext.isIE || Ext.isGecko) {
		noBoxAdjust['button'] = 1;
	}

	Ext.EventManager.on(window, 'unload',
	function() {
		delete El.cache;
		delete El._flyweights;
	});
})();

Ext.enableFx = true;

Ext.Fx = {

	slideIn: function(anchor, o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {

			anchor = anchor || "t";

			this.fixDisplay();

			var r = this.getFxRestore();
			var b = this.getBox();
			this.setSize(b);

			var wrap = this.fxWrap(r.pos, o, "hidden");

			var st = this.dom.style;
			st.visibility = "visible";
			st.position = "absolute";

			var after = function() {
				el.fxUnwrap(wrap, r.pos, o);
				st.width = r.width;
				st.height = r.height;
				el.afterFx(o);
			};
			var a,
			pt = {
				to: [b.x, b.y]
			},
			bw = {
				to: b.width
			},
			bh = {
				to: b.height
			};

			switch (anchor.toLowerCase()) {
			case "t":
				wrap.setSize(b.width, 0);
				st.left = st.bottom = "0";
				a = {
					height: bh
				};
				break;
			case "l":
				wrap.setSize(0, b.height);
				st.right = st.top = "0";
				a = {
					width: bw
				};
				break;
			case "r":
				wrap.setSize(0, b.height);
				wrap.setX(b.right);
				st.left = st.top = "0";
				a = {
					width: bw,
					points: pt
				};
				break;
			case "b":
				wrap.setSize(b.width, 0);
				wrap.setY(b.bottom);
				st.left = st.top = "0";
				a = {
					height: bh,
					points: pt
				};
				break;
			case "tl":
				wrap.setSize(0, 0);
				st.right = st.bottom = "0";
				a = {
					width: bw,
					height: bh
				};
				break;
			case "bl":
				wrap.setSize(0, 0);
				wrap.setY(b.y + b.height);
				st.right = st.top = "0";
				a = {
					width: bw,
					height: bh,
					points: pt
				};
				break;
			case "br":
				wrap.setSize(0, 0);
				wrap.setXY([b.right, b.bottom]);
				st.left = st.top = "0";
				a = {
					width: bw,
					height: bh,
					points: pt
				};
				break;
			case "tr":
				wrap.setSize(0, 0);
				wrap.setX(b.x + b.width);
				st.left = st.bottom = "0";
				a = {
					width: bw,
					height: bh,
					points: pt
				};
				break;
			}
			this.dom.style.visibility = "visible";
			wrap.show();

			arguments.callee.anim = wrap.fxanim(a, o, 'motion', .5, 'easeOut', after);
		});
		return this;
	},

	slideOut: function(anchor, o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {

			anchor = anchor || "t";

			var r = this.getFxRestore();

			var b = this.getBox();
			this.setSize(b);

			var wrap = this.fxWrap(r.pos, o, "visible");

			var st = this.dom.style;
			st.visibility = "visible";
			st.position = "absolute";

			wrap.setSize(b);

			var after = function() {
				if (o.useDisplay) {
					el.setDisplayed(false);
				} else {
					el.hide();
				}

				el.fxUnwrap(wrap, r.pos, o);

				st.width = r.width;
				st.height = r.height;

				el.afterFx(o);
			};

			var a,
			zero = {
				to: 0
			};
			switch (anchor.toLowerCase()) {
			case "t":
				st.left = st.bottom = "0";
				a = {
					height: zero
				};
				break;
			case "l":
				st.right = st.top = "0";
				a = {
					width: zero
				};
				break;
			case "r":
				st.left = st.top = "0";
				a = {
					width: zero,
					points: {
						to: [b.right, b.y]
					}
				};
				break;
			case "b":
				st.left = st.top = "0";
				a = {
					height: zero,
					points: {
						to: [b.x, b.bottom]
					}
				};
				break;
			case "tl":
				st.right = st.bottom = "0";
				a = {
					width: zero,
					height: zero
				};
				break;
			case "bl":
				st.right = st.top = "0";
				a = {
					width: zero,
					height: zero,
					points: {
						to: [b.x, b.bottom]
					}
				};
				break;
			case "br":
				st.left = st.top = "0";
				a = {
					width: zero,
					height: zero,
					points: {
						to: [b.x + b.width, b.bottom]
					}
				};
				break;
			case "tr":
				st.left = st.bottom = "0";
				a = {
					width: zero,
					height: zero,
					points: {
						to: [b.right, b.y]
					}
				};
				break;
			}

			arguments.callee.anim = wrap.fxanim(a, o, 'motion', .5, "easeOut", after);
		});
		return this;
	},

	puff: function(o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {
			this.clearOpacity();
			this.show();

			var r = this.getFxRestore();
			var st = this.dom.style;

			var after = function() {
				if (o.useDisplay) {
					el.setDisplayed(false);
				} else {
					el.hide();
				}

				el.clearOpacity();

				el.setPositioning(r.pos);
				st.width = r.width;
				st.height = r.height;
				st.fontSize = '';
				el.afterFx(o);
			};

			var width = this.getWidth();
			var height = this.getHeight();

			arguments.callee.anim = this.fxanim({
				width: {
					to: this.adjustWidth(width * 2)
				},
				height: {
					to: this.adjustHeight(height * 2)
				},
				points: {
					by: [ - (width * .5), -(height * .5)]
				},
				opacity: {
					to: 0
				},
				fontSize: {
					to: 200,
					unit: "%"
				}
			},
			o, 'motion', .5, "easeOut", after);
		});
		return this;
	},

	switchOff: function(o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {
			this.clearOpacity();
			this.clip();

			var r = this.getFxRestore();
			var st = this.dom.style;

			var after = function() {
				if (o.useDisplay) {
					el.setDisplayed(false);
				} else {
					el.hide();
				}

				el.clearOpacity();
				el.setPositioning(r.pos);
				st.width = r.width;
				st.height = r.height;

				el.afterFx(o);
			};

			this.fxanim({
				opacity: {
					to: 0.3
				}
			},
			null, null, .1, null,
			function() {
				this.clearOpacity(); (function() {
					this.fxanim({
						height: {
							to: 1
						},
						points: {
							by: [0, this.getHeight() * .5]
						}
					},
					o, 'motion', 0.3, 'easeIn', after);
				}).defer(100, this);
			});
		});
		return this;
	},

	highlight: function(color, o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {
			color = color || "ffff9c";
			var attr = o.attr || "backgroundColor";

			this.clearOpacity();
			this.show();

			var origColor = this.getColor(attr);
			var restoreColor = this.dom.style[attr];
			var endColor = (o.endColor || origColor) || "ffffff";

			var after = function() {
				el.dom.style[attr] = restoreColor;
				el.afterFx(o);
			};

			var a = {};
			a[attr] = {
				from: color,
				to: endColor
			};
			arguments.callee.anim = this.fxanim(a, o, 'color', 1, 'easeIn', after);
		});
		return this;
	},

	frame: function(color, count, o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {
			color = color || "#C3DAF9";
			if (color.length == 6) {
				color = "#" + color;
			}
			count = count || 1;
			var duration = o.duration || 1;
			this.show();

			var b = this.getBox();
			var animFn = function() {
				var proxy = Ext.getBody().createChild({
					style: {
						visbility: "hidden",
						position: "absolute",
						"z-index": "35000",
						border: "0px solid " + color
					}
				});
				var scale = Ext.isBorderBox ? 2: 1;
				proxy.animate({
					top: {
						from: b.y,
						to: b.y - 20
					},
					left: {
						from: b.x,
						to: b.x - 20
					},
					borderWidth: {
						from: 0,
						to: 10
					},
					opacity: {
						from: 1,
						to: 0
					},
					height: {
						from: b.height,
						to: (b.height + (20 * scale))
					},
					width: {
						from: b.width,
						to: (b.width + (20 * scale))
					}
				},
				duration,
				function() {
					proxy.remove();
					if (--count > 0) {
						animFn();
					} else {
						el.afterFx(o);
					}
				});
			};
			animFn.call(this);
		});
		return this;
	},

	pause: function(seconds) {
		var el = this.getFxEl();
		var o = {};

		el.queueFx(o,
		function() {
			setTimeout(function() {
				el.afterFx(o);
			},
			seconds * 1000);
		});
		return this;
	},

	fadeIn: function(o) {
		var el = this.getFxEl();
		o = o || {};
		el.queueFx(o,
		function() {
			this.setOpacity(0);
			this.fixDisplay();
			this.dom.style.visibility = 'visible';
			var to = o.endOpacity || 1;
			arguments.callee.anim = this.fxanim({
				opacity: {
					to: to
				}
			},
			o, null, .5, "easeOut",
			function() {
				if (to == 1) {
					this.clearOpacity();
				}
				el.afterFx(o);
			});
		});
		return this;
	},

	fadeOut: function(o) {
		var el = this.getFxEl();
		o = o || {};
		el.queueFx(o,
		function() {
			arguments.callee.anim = this.fxanim({
				opacity: {
					to: o.endOpacity || 0
				}
			},
			o, null, .5, "easeOut",
			function() {
				if (this.visibilityMode == Ext.Element.DISPLAY || o.useDisplay) {
					this.dom.style.display = "none";
				} else {
					this.dom.style.visibility = "hidden";
				}
				this.clearOpacity();
				el.afterFx(o);
			});
		});
		return this;
	},

	scale: function(w, h, o) {
		this.shift(Ext.apply({},
		o, {
			width: w,
			height: h
		}));
		return this;
	},

	shift: function(o) {
		var el = this.getFxEl();
		o = o || {};
		el.queueFx(o,
		function() {
			var a = {},
			w = o.width,
			h = o.height,
			x = o.x,
			y = o.y,
			op = o.opacity;
			if (w !== undefined) {
				a.width = {
					to: this.adjustWidth(w)
				};
			}
			if (h !== undefined) {
				a.height = {
					to: this.adjustHeight(h)
				};
			}
			if (o.left !== undefined) {
				a.left = {
					to: o.left
				};
			}
			if (o.top !== undefined) {
				a.top = {
					to: o.top
				};
			}
			if (o.right !== undefined) {
				a.right = {
					to: o.right
				};
			}
			if (o.bottom !== undefined) {
				a.bottom = {
					to: o.bottom
				};
			}
			if (x !== undefined || y !== undefined) {
				a.points = {
					to: [x !== undefined ? x: this.getX(), y !== undefined ? y: this.getY()]
				};
			}
			if (op !== undefined) {
				a.opacity = {
					to: op
				};
			}
			if (o.xy !== undefined) {
				a.points = {
					to: o.xy
				};
			}
			arguments.callee.anim = this.fxanim(a, o, 'motion', .35, "easeOut",
			function() {
				el.afterFx(o);
			});
		});
		return this;
	},

	ghost: function(anchor, o) {
		var el = this.getFxEl();
		o = o || {};

		el.queueFx(o,
		function() {
			anchor = anchor || "b";

			var r = this.getFxRestore();
			var w = this.getWidth(),
			h = this.getHeight();

			var st = this.dom.style;

			var after = function() {
				if (o.useDisplay) {
					el.setDisplayed(false);
				} else {
					el.hide();
				}

				el.clearOpacity();
				el.setPositioning(r.pos);
				st.width = r.width;
				st.height = r.height;

				el.afterFx(o);
			};

			var a = {
				opacity: {
					to: 0
				},
				points: {}
			},
			pt = a.points;
			switch (anchor.toLowerCase()) {
			case "t":
				pt.by = [0, -h];
				break;
			case "l":
				pt.by = [ - w, 0];
				break;
			case "r":
				pt.by = [w, 0];
				break;
			case "b":
				pt.by = [0, h];
				break;
			case "tl":
				pt.by = [ - w, -h];
				break;
			case "bl":
				pt.by = [ - w, h];
				break;
			case "br":
				pt.by = [w, h];
				break;
			case "tr":
				pt.by = [w, -h];
				break;
			}

			arguments.callee.anim = this.fxanim(a, o, 'motion', .5, "easeOut", after);
		});
		return this;
	},

	syncFx: function() {
		this.fxDefaults = Ext.apply(this.fxDefaults || {},
		{
			block: false,
			concurrent: true,
			stopFx: false
		});
		return this;
	},

	sequenceFx: function() {
		this.fxDefaults = Ext.apply(this.fxDefaults || {},
		{
			block: false,
			concurrent: false,
			stopFx: false
		});
		return this;
	},

	nextFx: function() {
		var ef = this.fxQueue[0];
		if (ef) {
			ef.call(this);
		}
	},

	hasActiveFx: function() {
		return this.fxQueue && this.fxQueue[0];
	},

	stopFx: function() {
		if (this.hasActiveFx()) {
			var cur = this.fxQueue[0];
			if (cur && cur.anim && cur.anim.isAnimated()) {
				this.fxQueue = [cur];
				cur.anim.stop(true);
			}
		}
		return this;
	},

	beforeFx: function(o) {
		if (this.hasActiveFx() && !o.concurrent) {
			if (o.stopFx) {
				this.stopFx();
				return true;
			}
			return false;
		}
		return true;
	},

	hasFxBlock: function() {
		var q = this.fxQueue;
		return q && q[0] && q[0].block;
	},

	queueFx: function(o, fn) {
		if (!this.fxQueue) {
			this.fxQueue = [];
		}
		if (!this.hasFxBlock()) {
			Ext.applyIf(o, this.fxDefaults);
			if (!o.concurrent) {
				var run = this.beforeFx(o);
				fn.block = o.block;
				this.fxQueue.push(fn);
				if (run) {
					this.nextFx();
				}
			} else {
				fn.call(this);
			}
		}
		return this;
	},

	fxWrap: function(pos, o, vis) {
		var wrap;
		if (!o.wrap || !(wrap = Ext.get(o.wrap))) {
			var wrapXY;
			if (o.fixPosition) {
				wrapXY = this.getXY();
			}
			var div = document.createElement("div");
			div.style.visibility = vis;
			wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));
			wrap.setPositioning(pos);
			if (wrap.getStyle("position") == "static") {
				wrap.position("relative");
			}
			this.clearPositioning('auto');
			wrap.clip();
			wrap.dom.appendChild(this.dom);
			if (wrapXY) {
				wrap.setXY(wrapXY);
			}
		}
		return wrap;
	},

	fxUnwrap: function(wrap, pos, o) {
		this.clearPositioning();
		this.setPositioning(pos);
		if (!o.wrap) {
			wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
			wrap.remove();
		}
	},

	getFxRestore: function() {
		var st = this.dom.style;
		return {
			pos: this.getPositioning(),
			width: st.width,
			height: st.height
		};
	},

	afterFx: function(o) {
		if (o.afterStyle) {
			this.applyStyles(o.afterStyle);
		}
		if (o.afterCls) {
			this.addClass(o.afterCls);
		}
		if (o.remove === true) {
			this.remove();
		}
		Ext.callback(o.callback, o.scope, [this]);
		if (!o.concurrent) {
			this.fxQueue.shift();
			this.nextFx();
		}
	},

	getFxEl: function() {
		return Ext.get(this.dom);
	},

	fxanim: function(args, opt, animType, defaultDur, defaultEase, cb) {
		animType = animType || 'run';
		opt = opt || {};
		var anim = Ext.lib.Anim[animType](this.dom, args, (opt.duration || defaultDur) || .35, (opt.easing || defaultEase) || 'easeOut',
		function() {
			Ext.callback(cb, this);
		},
		this);
		opt.anim = anim;
		return anim;
	}
};

Ext.Fx.resize = Ext.Fx.scale;

Ext.apply(Ext.Element.prototype, Ext.Fx);

Ext.CompositeElement = function(els) {
	this.elements = [];
	this.addElements(els);
};
Ext.CompositeElement.prototype = {
	isComposite: true,
	addElements: function(els) {
		if (!els) return this;
		if (typeof els == "string") {
			els = Ext.Element.selectorFunction(els);
		}
		var yels = this.elements;
		var index = yels.length - 1;
		for (var i = 0, len = els.length; i < len; i++) {
			yels[++index] = Ext.get(els[i]);
		}
		return this;
	},

	fill: function(els) {
		this.elements = [];
		this.add(els);
		return this;
	},

	filter: function(selector) {
		var els = [];
		this.each(function(el) {
			if (el.is(selector)) {
				els[els.length] = el.dom;
			}
		});
		this.fill(els);
		return this;
	},

	invoke: function(fn, args) {
		var els = this.elements;
		for (var i = 0, len = els.length; i < len; i++) {
			Ext.Element.prototype[fn].apply(els[i], args);
		}
		return this;
	},

	add: function(els) {
		if (typeof els == "string") {
			this.addElements(Ext.Element.selectorFunction(els));
		} else if (els.length !== undefined) {
			this.addElements(els);
		} else {
			this.addElements([els]);
		}
		return this;
	},

	each: function(fn, scope) {
		var els = this.elements;
		for (var i = 0, len = els.length; i < len; i++) {
			if (fn.call(scope || els[i], els[i], this, i) === false) {
				break;
			}
		}
		return this;
	},

	item: function(index) {
		return this.elements[index] || null;
	},

	first: function() {
		return this.item(0);
	},

	last: function() {
		return this.item(this.elements.length - 1);
	},

	getCount: function() {
		return this.elements.length;
	},

	contains: function(el) {
		return this.indexOf(el) !== -1;
	},

	indexOf: function(el) {
		return this.elements.indexOf(Ext.get(el));
	},

	removeElement: function(el, removeDom) {
		if (Ext.isArray(el)) {
			for (var i = 0, len = el.length; i < len; i++) {
				this.removeElement(el[i]);
			}
			return this;
		}
		var index = typeof el == 'number' ? el: this.indexOf(el);
		if (index !== -1 && this.elements[index]) {
			if (removeDom) {
				var d = this.elements[index];
				if (d.dom) {
					d.remove();
				} else {
					Ext.removeNode(d);
				}
			}
			this.elements.splice(index, 1);
		}
		return this;
	},

	replaceElement: function(el, replacement, domReplace) {
		var index = typeof el == 'number' ? el: this.indexOf(el);
		if (index !== -1) {
			if (domReplace) {
				this.elements[index].replaceWith(replacement);
			} else {
				this.elements.splice(index, 1, Ext.get(replacement))
			}
		}
		return this;
	},

	clear: function() {
		this.elements = [];
	}
}; (function() {
	Ext.CompositeElement.createCall = function(proto, fnName) {
		if (!proto[fnName]) {
			proto[fnName] = function() {
				return this.invoke(fnName, arguments);
			};
		}
	};
	for (var fnName in Ext.Element.prototype) {
		if (typeof Ext.Element.prototype[fnName] == "function") {
			Ext.CompositeElement.createCall(Ext.CompositeElement.prototype, fnName);
		}
	};
})();

Ext.CompositeElementLite = function(els) {
	Ext.CompositeElementLite.superclass.constructor.call(this, els);
	this.el = new Ext.Element.Flyweight();
};
Ext.extend(Ext.CompositeElementLite, Ext.CompositeElement, {
	addElements: function(els) {
		if (els) {
			if (Ext.isArray(els)) {
				this.elements = this.elements.concat(els);
			} else {
				var yels = this.elements;
				var index = yels.length - 1;
				for (var i = 0, len = els.length; i < len; i++) {
					yels[++index] = els[i];
				}
			}
		}
		return this;
	},
	invoke: function(fn, args) {
		var els = this.elements;
		var el = this.el;
		for (var i = 0, len = els.length; i < len; i++) {
			el.dom = els[i];
			Ext.Element.prototype[fn].apply(el, args);
		}
		return this;
	},

	item: function(index) {
		if (!this.elements[index]) {
			return null;
		}
		this.el.dom = this.elements[index];
		return this.el;
	},

	addListener: function(eventName, handler, scope, opt) {
		var els = this.elements;
		for (var i = 0, len = els.length; i < len; i++) {
			Ext.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
		}
		return this;
	},

	each: function(fn, scope) {
		var els = this.elements;
		var el = this.el;
		for (var i = 0, len = els.length; i < len; i++) {
			el.dom = els[i];
			if (fn.call(scope || el, el, this, i) === false) {
				break;
			}
		}
		return this;
	},

	indexOf: function(el) {
		return this.elements.indexOf(Ext.getDom(el));
	},

	replaceElement: function(el, replacement, domReplace) {
		var index = typeof el == 'number' ? el: this.indexOf(el);
		if (index !== -1) {
			replacement = Ext.getDom(replacement);
			if (domReplace) {
				var d = this.elements[index];
				d.parentNode.insertBefore(replacement, d);
				Ext.removeNode(d);
			}
			this.elements.splice(index, 1, replacement);
		}
		return this;
	}
});
Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
if (Ext.DomQuery) {
	Ext.Element.selectorFunction = Ext.DomQuery.select;
}

Ext.Element.select = function(selector, unique, root) {
	var els;
	if (typeof selector == "string") {
		els = Ext.Element.selectorFunction(selector, root);
	} else if (selector.length !== undefined) {
		els = selector;
	} else {
		throw "Invalid selector";
	}
	if (unique === true) {
		return new Ext.CompositeElement(els);
	} else {
		return new Ext.CompositeElementLite(els);
	}
};

Ext.select = Ext.Element.select;

Ext.data.Connection = function(config) {
	Ext.apply(this, config);
	this.addEvents(
	"beforerequest",
	"requestcomplete",
	"requestexception");
	Ext.data.Connection.superclass.constructor.call(this);
};

Ext.extend(Ext.data.Connection, Ext.util.Observable, {

	timeout: 30000,

	autoAbort: false,

	disableCaching: true,

	disableCachingParam: '_dc',

	request: function(o) {
		if (this.fireEvent("beforerequest", this, o) !== false) {
			var p = o.params;

			if (typeof p == "function") {
				p = p.call(o.scope || window, o);
			}
			if (typeof p == "object") {
				p = Ext.urlEncode(p);
			}
			if (this.extraParams) {
				var extras = Ext.urlEncode(this.extraParams);
				p = p ? (p + '&' + extras) : extras;
			}

			var url = o.url || this.url;
			if (typeof url == 'function') {
				url = url.call(o.scope || window, o);
			}

			if (o.form) {
				var form = Ext.getDom(o.form);
				url = url || form.action;

				var enctype = form.getAttribute("enctype");
				if (o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')) {
					return this.doFormUpload(o, p, url);
				}
				var f = Ext.lib.Ajax.serializeForm(form);
				p = p ? (p + '&' + f) : f;
			}

			var hs = o.headers;
			if (this.defaultHeaders) {
				hs = Ext.apply(hs || {},
				this.defaultHeaders);
				if (!o.headers) {
					o.headers = hs;
				}
			}

			var cb = {
				success: this.handleResponse,
				failure: this.handleFailure,
				scope: this,
				argument: {
					options: o
				},
				timeout: o.timeout || this.timeout
			};

			var method = o.method || this.method || ((p || o.xmlData || o.jsonData) ? "POST": "GET");

			if (method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true) {
				var dcp = o.disableCachingParam || this.disableCachingParam;
				url += (url.indexOf('?') != -1 ? '&': '?') + dcp + '=' + (new Date().getTime());
			}

			if (typeof o.autoAbort == 'boolean') {
				if (o.autoAbort) {
					this.abort();
				}
			} else if (this.autoAbort !== false) {
				this.abort();
			}
			if ((method == 'GET' || o.xmlData || o.jsonData) && p) {
				url += (url.indexOf('?') != -1 ? '&': '?') + p;
				p = '';
			}
			this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
			return this.transId;
		} else {
			Ext.callback(o.callback, o.scope, [o, null, null]);
			return null;
		}
	},

	isLoading: function(transId) {
		if (transId) {
			return Ext.lib.Ajax.isCallInProgress(transId);
		} else {
			return this.transId ? true: false;
		}
	},

	abort: function(transId) {
		if (transId || this.isLoading()) {
			Ext.lib.Ajax.abort(transId || this.transId);
		}
	},

	handleResponse: function(response) {
		this.transId = false;
		var options = response.argument.options;
		response.argument = options ? options.argument: null;
		this.fireEvent("requestcomplete", this, response, options);
		Ext.callback(options.success, options.scope, [response, options]);
		Ext.callback(options.callback, options.scope, [options, true, response]);
	},

	handleFailure: function(response, e) {
		this.transId = false;
		var options = response.argument.options;
		response.argument = options ? options.argument: null;
		this.fireEvent("requestexception", this, response, options, e);
		Ext.callback(options.failure, options.scope, [response, options]);
		Ext.callback(options.callback, options.scope, [options, false, response]);
	},

	doFormUpload: function(o, ps, url) {
		var id = Ext.id();
		var frame = document.createElement('iframe');
		frame.id = id;
		frame.name = id;
		frame.className = 'x-hidden';
		if (Ext.isIE) {
			frame.src = Ext.SSL_SECURE_URL;
		}
		document.body.appendChild(frame);

		if (Ext.isIE) {
			document.frames[id].name = id;
		}

		var form = Ext.getDom(o.form);
		form.target = id;
		form.method = 'POST';
		form.enctype = form.encoding = 'multipart/form-data';
		if (url) {
			form.action = url;
		}

		var hiddens,
		hd;
		if (ps) {
			hiddens = [];
			ps = Ext.urlDecode(ps, false);
			for (var k in ps) {
				if (ps.hasOwnProperty(k)) {
					hd = document.createElement('input');
					hd.type = 'hidden';
					hd.name = k;
					hd.value = ps[k];
					form.appendChild(hd);
					hiddens.push(hd);
				}
			}
		}

		function cb() {
			var r = {
				responseText: '',
				responseXML: null
			};

			r.argument = o ? o.argument: null;

			try {
				var doc;
				if (Ext.isIE) {
					doc = frame.contentWindow.document;
				} else {
					doc = (frame.contentDocument || window.frames[id].document);
				}
				if (doc && doc.body) {
					r.responseText = doc.body.innerHTML;
				}
				if (doc && doc.XMLDocument) {
					r.responseXML = doc.XMLDocument;
				} else {
					r.responseXML = doc;
				}
			} catch(e) {}

			Ext.EventManager.removeListener(frame, 'load', cb, this);

			this.fireEvent("requestcomplete", this, r, o);

			Ext.callback(o.success, o.scope, [r, o]);
			Ext.callback(o.callback, o.scope, [o, true, r]);

			setTimeout(function() {
				Ext.removeNode(frame);
			},
			100);
		}

		Ext.EventManager.on(frame, 'load', cb, this);
		form.submit();

		if (hiddens) {
			for (var i = 0, len = hiddens.length; i < len; i++) {
				Ext.removeNode(hiddens[i]);
			}
		}
	}
});

Ext.Ajax = new Ext.data.Connection({

	autoAbort: false,

	serializeForm: function(form) {
		return Ext.lib.Ajax.serializeForm(form);
	}
});

Ext.Updater = Ext.extend(Ext.util.Observable, {
	constructor: function(el, forceNew) {
		el = Ext.get(el);
		if (!forceNew && el.updateManager) {
			return el.updateManager;
		}

		this.el = el;

		this.defaultUrl = null;

		this.addEvents(
		"beforeupdate",
		"update",
		"failure");
		var d = Ext.Updater.defaults;

		this.sslBlankUrl = d.sslBlankUrl;

		this.disableCaching = d.disableCaching;

		this.indicatorText = d.indicatorText;

		this.showLoadIndicator = d.showLoadIndicator;

		this.timeout = d.timeout;

		this.loadScripts = d.loadScripts;

		this.transaction = null;

		this.refreshDelegate = this.refresh.createDelegate(this);

		this.updateDelegate = this.update.createDelegate(this);

		this.formUpdateDelegate = this.formUpdate.createDelegate(this);

		if (!this.renderer) {

			this.renderer = this.getDefaultRenderer();
		}
		Ext.Updater.superclass.constructor.call(this);
	},

	getDefaultRenderer: function() {
		return new Ext.Updater.BasicRenderer();
	},

	getEl: function() {
		return this.el;
	},

	update: function(url, params, callback, discardUrl) {
		if (this.fireEvent("beforeupdate", this.el, url, params) !== false) {
			var cfg,
			callerScope;
			if (typeof url == "object") {
				cfg = url;
				url = cfg.url;
				params = params || cfg.params;
				callback = callback || cfg.callback;
				discardUrl = discardUrl || cfg.discardUrl;
				callerScope = cfg.scope;
				if (typeof cfg.nocache != "undefined") {
					this.disableCaching = cfg.nocache;
				};
				if (typeof cfg.text != "undefined") {
					this.indicatorText = '<div class="loading-indicator">' + cfg.text + "</div>";
				};
				if (typeof cfg.scripts != "undefined") {
					this.loadScripts = cfg.scripts;
				};
				if (typeof cfg.timeout != "undefined") {
					this.timeout = cfg.timeout;
				};
			}
			this.showLoading();

			if (!discardUrl) {
				this.defaultUrl = url;
			}
			if (typeof url == "function") {
				url = url.call(this);
			}

			var o = Ext.apply({},
			{
				url: url,
				params: (typeof params == "function" && callerScope) ? params.createDelegate(callerScope) : params,
				success: this.processSuccess,
				failure: this.processFailure,
				scope: this,
				callback: undefined,
				timeout: (this.timeout * 1000),
				disableCaching: this.disableCaching,
				argument: {
					"options": cfg,
					"url": url,
					"form": null,
					"callback": callback,
					"scope": callerScope || window,
					"params": params
				}
			},
			cfg);

			this.transaction = Ext.Ajax.request(o);
		}
	},

	formUpdate: function(form, url, reset, callback) {
		if (this.fireEvent("beforeupdate", this.el, form, url) !== false) {
			if (typeof url == "function") {
				url = url.call(this);
			}
			form = Ext.getDom(form);
			this.transaction = Ext.Ajax.request({
				form: form,
				url: url,
				success: this.processSuccess,
				failure: this.processFailure,
				scope: this,
				timeout: (this.timeout * 1000),
				argument: {
					"url": url,
					"form": form,
					"callback": callback,
					"reset": reset
				}
			});
			this.showLoading.defer(1, this);
		}
	},

	refresh: function(callback) {
		if (this.defaultUrl == null) {
			return;
		}
		this.update(this.defaultUrl, null, callback, true);
	},

	startAutoRefresh: function(interval, url, params, callback, refreshNow) {
		if (refreshNow) {
			this.update(url || this.defaultUrl, params, callback, true);
		}
		if (this.autoRefreshProcId) {
			clearInterval(this.autoRefreshProcId);
		}
		this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval * 1000);
	},

	stopAutoRefresh: function() {
		if (this.autoRefreshProcId) {
			clearInterval(this.autoRefreshProcId);
			delete this.autoRefreshProcId;
		}
	},

	isAutoRefreshing: function() {
		return this.autoRefreshProcId ? true: false;
	},

	showLoading: function() {
		if (this.showLoadIndicator) {
			this.el.update(this.indicatorText);
		}
	},

	processSuccess: function(response) {
		this.transaction = null;
		if (response.argument.form && response.argument.reset) {
			try {
				response.argument.form.reset();
			} catch(e) {}
		}
		if (this.loadScripts) {
			this.renderer.render(this.el, response, this, this.updateComplete.createDelegate(this, [response]));
		} else {
			this.renderer.render(this.el, response, this);
			this.updateComplete(response);
		}
	},

	updateComplete: function(response) {
		this.fireEvent("update", this.el, response);
		if (typeof response.argument.callback == "function") {
			response.argument.callback.call(response.argument.scope, this.el, true, response, response.argument.options);
		}
	},

	processFailure: function(response) {
		this.transaction = null;
		this.fireEvent("failure", this.el, response);
		if (typeof response.argument.callback == "function") {
			response.argument.callback.call(response.argument.scope, this.el, false, response, response.argument.options);
		}
	},

	setRenderer: function(renderer) {
		this.renderer = renderer;
	},

	getRenderer: function() {
		return this.renderer;
	},

	setDefaultUrl: function(defaultUrl) {
		this.defaultUrl = defaultUrl;
	},

	abort: function() {
		if (this.transaction) {
			Ext.Ajax.abort(this.transaction);
		}
	},

	isUpdating: function() {
		if (this.transaction) {
			return Ext.Ajax.isLoading(this.transaction);
		}
		return false;
	}
});

Ext.Updater.defaults = {

	timeout: 30,

	loadScripts: false,

	sslBlankUrl: (Ext.SSL_SECURE_URL || "javascript:false"),

	disableCaching: false,

	showLoadIndicator: true,

	indicatorText: '<div class="loading-indicator">Loading...</div>'
};

Ext.Updater.updateElement = function(el, url, params, options) {
	var um = Ext.get(el).getUpdater();
	Ext.apply(um, options);
	um.update(url, params, options ? options.callback: null);
};

Ext.Updater.BasicRenderer = function() {};

Ext.Updater.BasicRenderer.prototype = {

	render: function(el, response, updateManager, callback) {
		el.update(response.responseText, updateManager.loadScripts, callback);
	}
};

Ext.UpdateManager = Ext.Updater;
 (function() {
	Date.formatCodeToRegex = function(character, currentGroup) {
		var p = Date.parseCodes[character];

		if (p) {
			p = Ext.type(p) == 'function' ? p() : p;
			Date.parseCodes[character] = p;
		}

		return p ? Ext.applyIf({
			c: p.c ? String.format(p.c, currentGroup || "{0}") : p.c
		},
		p) : {
			g: 0,
			c: null,
			s: Ext.escapeRe(character)
		}
	}

	var $f = Date.formatCodeToRegex;

	Ext.apply(Date, {
		parseFunctions: {
			count: 0
		},
		parseRegexes: [],
		formatFunctions: {
			count: 0
		},
		daysInMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
		y2kYear: 50,

		MILLI: "ms",

		SECOND: "s",

		MINUTE: "mi",

		HOUR: "h",

		DAY: "d",

		MONTH: "mo",

		YEAR: "y",

		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],

		monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],

		monthNumbers: {
			Jan: 0,
			Feb: 1,
			Mar: 2,
			Apr: 3,
			May: 4,
			Jun: 5,
			Jul: 6,
			Aug: 7,
			Sep: 8,
			Oct: 9,
			Nov: 10,
			Dec: 11
		},

		getShortMonthName: function(month) {
			return Date.monthNames[month].substring(0, 3);
		},

		getShortDayName: function(day) {
			return Date.dayNames[day].substring(0, 3);
		},

		getMonthNumber: function(name) {
			return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
		},

		formatCodes: {
			d: "String.leftPad(this.getDate(), 2, '0')",
			D: "Date.getShortDayName(this.getDay())",
			j: "this.getDate()",
			l: "Date.dayNames[this.getDay()]",
			N: "(this.getDay() ? this.getDay() : 7)",
			S: "this.getSuffix()",
			w: "this.getDay()",
			z: "this.getDayOfYear()",
			W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
			F: "Date.monthNames[this.getMonth()]",
			m: "String.leftPad(this.getMonth() + 1, 2, '0')",
			M: "Date.getShortMonthName(this.getMonth())",
			n: "(this.getMonth() + 1)",
			t: "this.getDaysInMonth()",
			L: "(this.isLeapYear() ? 1 : 0)",
			o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
			Y: "this.getFullYear()",
			y: "('' + this.getFullYear()).substring(2, 4)",
			a: "(this.getHours() < 12 ? 'am' : 'pm')",
			A: "(this.getHours() < 12 ? 'AM' : 'PM')",
			g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
			G: "this.getHours()",
			h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
			H: "String.leftPad(this.getHours(), 2, '0')",
			i: "String.leftPad(this.getMinutes(), 2, '0')",
			s: "String.leftPad(this.getSeconds(), 2, '0')",
			u: "String.leftPad(this.getMilliseconds(), 3, '0')",
			O: "this.getGMTOffset()",
			P: "this.getGMTOffset(true)",
			T: "this.getTimezone()",
			Z: "(this.getTimezoneOffset() * -60)",
			c: function() {
				for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
					var e = c.charAt(i);
					code.push(e == "T" ? "'T'": Date.getFormatCode(e));
				}
				return code.join(" + ");
			},

			U: "Math.round(this.getTime() / 1000)"
		},

		parseDate: function(input, format) {
			var p = Date.parseFunctions;
			if (p[format] == null) {
				Date.createParser(format);
			}
			var func = p[format];
			return Date[func](input);
		},

		getFormatCode: function(character) {
			var f = Date.formatCodes[character];

			if (f) {
				f = Ext.type(f) == 'function' ? f() : f;
				Date.formatCodes[character] = f;
			}

			return f || ("'" + String.escape(character) + "'");
		},

		createNewFormat: function(format) {
			var funcName = "format" + Date.formatFunctions.count++;
			Date.formatFunctions[format] = funcName;
			var code = "Date.prototype." + funcName + " = function(){return ";
			var special = false;
			var ch = '';
			for (var i = 0; i < format.length; ++i) {
				ch = format.charAt(i);
				if (!special && ch == "\\") {
					special = true;
				} else if (special) {
					special = false;
					code += "'" + String.escape(ch) + "' + ";
				} else {
					code += Date.getFormatCode(ch) + " + ";
				}
			}
			eval(code.substring(0, code.length - 3) + ";}");
		},

		createParser: function(format) {
			var funcName = "parse" + Date.parseFunctions.count++;
			var regexNum = Date.parseRegexes.length;
			var currentGroup = 1;
			Date.parseFunctions[format] = funcName;

			var code = "Date." + funcName + " = function(input){\n" + "var y, m, d, h = 0, i = 0, s = 0, ms = 0, o, z, u, v;\n" + "input = String(input);\n" + "d = new Date();\n" + "y = d.getFullYear();\n" + "m = d.getMonth();\n" + "d = d.getDate();\n" + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" + "if (results && results.length > 0) {";
			var regex = "";

			var special = false;
			var ch = '';
			for (var i = 0; i < format.length; ++i) {
				ch = format.charAt(i);
				if (!special && ch == "\\") {
					special = true;
				} else if (special) {
					special = false;
					regex += String.escape(ch);
				} else {
					var obj = Date.formatCodeToRegex(ch, currentGroup);
					currentGroup += obj.g;
					regex += obj.s;
					if (obj.g && obj.c) {
						code += obj.c;
					}
				}
			}

			code += "if (u){\n" + "v = new Date(u * 1000);\n" + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0){\n" + "v = new Date(y, m, d, h, i, s, ms);\n" + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0){\n" + "v = new Date(y, m, d, h, i, s);\n" + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0){\n" + "v = new Date(y, m, d, h, i);\n" + "}else if (y >= 0 && m >= 0 && d > 0 && h >= 0){\n" + "v = new Date(y, m, d, h);\n" + "}else if (y >= 0 && m >= 0 && d > 0){\n" + "v = new Date(y, m, d);\n" + "}else if (y >= 0 && m >= 0){\n" + "v = new Date(y, m);\n" + "}else if (y >= 0){\n" + "v = new Date(y);\n" + "}\n}\nreturn (v && (z || o))?" + " (Ext.type(z) == 'number' ? v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - z) :" + " v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn))) : v;\n" + "}";

			Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$", "i");
			eval(code);
		},

		parseCodes: {

			d: {
				g: 1,
				c: "d = parseInt(results[{0}], 10);\n",
				s: "(\\d{2})"
			},
			j: {
				g: 1,
				c: "d = parseInt(results[{0}], 10);\n",
				s: "(\\d{1,2})"
			},
			D: function() {
				for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i);
				return {
					g: 0,
					c: null,
					s: "(?:" + a.join("|") + ")"
				}
			},
			l: function() {
				return {
					g: 0,
					c: null,
					s: "(?:" + Date.dayNames.join("|") + ")"
				}
			},
			N: {
				g: 0,
				c: null,
				s: "[1-7]"
			},
			S: {
				g: 0,
				c: null,
				s: "(?:st|nd|rd|th)"
			},
			w: {
				g: 0,
				c: null,
				s: "[0-6]"
			},
			z: {
				g: 0,
				c: null,
				s: "(?:\\d{1,3}"
			},
			W: {
				g: 0,
				c: null,
				s: "(?:\\d{2})"
			},
			F: function() {
				return {
					g: 1,
					c: "m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n",
					s: "(" + Date.monthNames.join("|") + ")"
				}
			},
			M: function() {
				for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i);
				return Ext.applyIf({
					s: "(" + a.join("|") + ")"
				},
				$f("F"));
			},
			m: {
				g: 1,
				c: "m = parseInt(results[{0}], 10) - 1;\n",
				s: "(\\d{2})"
			},
			n: {
				g: 1,
				c: "m = parseInt(results[{0}], 10) - 1;\n",
				s: "(\\d{1,2})"
			},
			t: {
				g: 0,
				c: null,
				s: "(?:\\d{2})"
			},
			L: {
				g: 0,
				c: null,
				s: "(?:1|0)"
			},
			o: function() {
				return $f("Y");
			},
			Y: {
				g: 1,
				c: "y = parseInt(results[{0}], 10);\n",
				s: "(\\d{4})"
			},
			y: {
				g: 1,
				c: "var ty = parseInt(results[{0}], 10);\n" + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
				s: "(\\d{1,2})"
			},
			a: {
				g: 1,
				c: "if (results[{0}] == 'am') {\n" + "if (h == 12) { h = 0; }\n" + "} else { if (h < 12) { h += 12; }}",
				s: "(am|pm)"
			},
			A: {
				g: 1,
				c: "if (results[{0}] == 'AM') {\n" + "if (h == 12) { h = 0; }\n" + "} else { if (h < 12) { h += 12; }}",
				s: "(AM|PM)"
			},
			g: function() {
				return $f("G");
			},
			G: {
				g: 1,
				c: "h = parseInt(results[{0}], 10);\n",
				s: "(\\d{1,2})"
			},
			h: function() {
				return $f("H");
			},
			H: {
				g: 1,
				c: "h = parseInt(results[{0}], 10);\n",
				s: "(\\d{2})"
			},
			i: {
				g: 1,
				c: "i = parseInt(results[{0}], 10);\n",
				s: "(\\d{2})"
			},
			s: {
				g: 1,
				c: "s = parseInt(results[{0}], 10);\n",
				s: "(\\d{2})"
			},
			u: {
				g: 1,
				c: "ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
				s: "(\\d+)"
			},
			O: {
				g: 1,
				c: ["o = results[{0}];", "var sn = o.substring(0,1);", "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);", "var mn = o.substring(3,5) % 60;", "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),
				s: "([+\-]\\d{4})"
			},
			P: {
				g: 1,
				c: ["o = results[{0}];", "var sn = o.substring(0,1);", "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);", "var mn = o.substring(4,6) % 60;", "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),
				s: "([+\-]\\d{2}:\\d{2})"
			},
			T: {
				g: 0,
				c: null,
				s: "[A-Z]{1,4}"
			},
			Z: {
				g: 1,
				c: "z = results[{0}] * 1;\n" + "z = (-43200 <= z && z <= 50400)? z : null;\n",
				s: "([+\-]?\\d{1,5})"
			},
			c: function() {
				var calc = [];
				var arr = [$f("Y", 1), $f("m", 2), $f("d", 3), $f("h", 4), $f("i", 5), $f("s", 6), {
					c: "ms = (results[7] || '.0').substring(1); ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"
				},
				{
					c: "if(results[9] == 'Z'){\no = 0;\n}else{\n" + $f("P", 9).c + "\n}"
				}];
				for (var i = 0, l = arr.length; i < l; ++i) {
					calc.push(arr[i].c);
				}

				return {
					g: 1,
					c: calc.join(""),
					s: arr[0].s + "-" + arr[1].s + "-" + arr[2].s + "T" + arr[3].s + ":" + arr[4].s + ":" + arr[5].s + "((\.|,)\\d+)?" + "(" + $f("P", null).s + "|Z)"
				}
			},
			U: {
				g: 1,
				c: "u = parseInt(results[{0}], 10);\n",
				s: "(-?\\d+)"
			}
		}
	});

} ());

Ext.override(Date, {
	dateFormat: function(format) {
		if (Date.formatFunctions[format] == null) {
			Date.createNewFormat(format);
		}
		var func = Date.formatFunctions[format];
		return this[func]();
	},

	getTimezone: function() {
		return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
	},

	getGMTOffset: function(colon) {
		return (this.getTimezoneOffset() > 0 ? "-": "+") + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0") + (colon ? ":": "") + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
	},

	getDayOfYear: function() {
		var num = 0;
		Date.daysInMonth[1] = this.isLeapYear() ? 29: 28;
		for (var i = 0; i < this.getMonth(); ++i) {
			num += Date.daysInMonth[i];
		}
		return num + this.getDate() - 1;
	},

	getWeekOfYear: function() {
		var ms1d = 864e5;
		var ms7d = 7 * ms1d;
		var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d;
		var AWN = Math.floor(DC3 / 7);
		var Wyr = new Date(AWN * ms7d).getUTCFullYear();
		return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
	},

	isLeapYear: function() {
		var year = this.getFullYear();
		return !! ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
	},

	getFirstDayOfMonth: function() {
		var day = (this.getDay() - (this.getDate() - 1)) % 7;
		return (day < 0) ? (day + 7) : day;
	},

	getLastDayOfMonth: function() {
		var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
		return (day < 0) ? (day + 7) : day;
	},

	getFirstDateOfMonth: function() {
		return new Date(this.getFullYear(), this.getMonth(), 1);
	},

	getLastDateOfMonth: function() {
		return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
	},

	getDaysInMonth: function() {
		Date.daysInMonth[1] = this.isLeapYear() ? 29: 28;
		return Date.daysInMonth[this.getMonth()];
	},

	getSuffix: function() {
		switch (this.getDate()) {
		case 1:
		case 21:
		case 31:
			return "st";
		case 2:
		case 22:
			return "nd";
		case 3:
		case 23:
			return "rd";
		default:
			return "th";
		}
	},

	clone: function() {
		return new Date(this.getTime());
	},

	clearTime: function(clone) {
		if (clone) {
			return this.clone().clearTime();
		}
		this.setHours(0);
		this.setMinutes(0);
		this.setSeconds(0);
		this.setMilliseconds(0);
		return this;
	},

	add: function(interval, value) {
		var d = this.clone();
		if (!interval || value === 0) return d;

		switch (interval.toLowerCase()) {
		case Date.MILLI:
			d.setMilliseconds(this.getMilliseconds() + value);
			break;
		case Date.SECOND:
			d.setSeconds(this.getSeconds() + value);
			break;
		case Date.MINUTE:
			d.setMinutes(this.getMinutes() + value);
			break;
		case Date.HOUR:
			d.setHours(this.getHours() + value);
			break;
		case Date.DAY:
			d.setDate(this.getDate() + value);
			break;
		case Date.MONTH:
			var day = this.getDate();
			if (day > 28) {
				day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
			}
			d.setDate(day);
			d.setMonth(this.getMonth() + value);
			break;
		case Date.YEAR:
			d.setFullYear(this.getFullYear() + value);
			break;
		}
		return d;
	},

	between: function(start, end) {
		var t = this.getTime();
		return start.getTime() <= t && t <= end.getTime();
	}
});

Date.prototype.format = Date.prototype.dateFormat;

if (Ext.isSafari) {
	Date.brokenSetMonth = Date.prototype.setMonth;
	Date.prototype.setMonth = function(num) {
		if (num <= -1) {
			var n = Math.ceil( - num);
			var back_year = Math.ceil(n / 12);
			var month = (n % 12) ? 12 - n % 12: 0;
			this.setFullYear(this.getFullYear() - back_year);
			return Date.brokenSetMonth.call(this, month);
		} else {
			return Date.brokenSetMonth.apply(this, arguments);
		}
	};
}

Ext.util.DelayedTask = function(fn, scope, args) {
	var id = null,
	d,
	t;

	var call = function() {
		var now = new Date().getTime();
		if (now - t >= d) {
			clearInterval(id);
			id = null;
			fn.apply(scope, args || []);
		}
	};

	this.delay = function(delay, newFn, newScope, newArgs) {
		if (id && delay != d) {
			this.cancel();
		}
		d = delay;
		t = new Date().getTime();
		fn = newFn || fn;
		scope = newScope || scope;
		args = newArgs || args;
		if (!id) {
			id = setInterval(call, d);
		}
	};

	this.cancel = function() {
		if (id) {
			clearInterval(id);
			id = null;
		}
	};
};

Ext.util.TaskRunner = function(interval) {
	interval = interval || 10;
	var tasks = [],
	removeQueue = [];
	var id = 0;
	var running = false;

	var stopThread = function() {
		running = false;
		clearInterval(id);
		id = 0;
	};

	var startThread = function() {
		if (!running) {
			running = true;
			id = setInterval(runTasks, interval);
		}
	};

	var removeTask = function(t) {
		removeQueue.push(t);
		if (t.onStop) {
			t.onStop.apply(t.scope || t);
		}
	};

	var runTasks = function() {
		if (removeQueue.length > 0) {
			for (var i = 0, len = removeQueue.length; i < len; i++) {
				tasks.remove(removeQueue[i]);
			}
			removeQueue = [];
			if (tasks.length < 1) {
				stopThread();
				return;
			}
		}
		var now = new Date().getTime();
		for (var i = 0, len = tasks.length; i < len; ++i) {
			var t = tasks[i];
			var itime = now - t.taskRunTime;
			if (t.interval <= itime) {
				var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
				t.taskRunTime = now;
				if (rt === false || t.taskRunCount === t.repeat) {
					removeTask(t);
					return;
				}
			}
			if (t.duration && t.duration <= (now - t.taskStartTime)) {
				removeTask(t);
			}
		}
	};

	this.start = function(task) {
		tasks.push(task);
		task.taskStartTime = new Date().getTime();
		task.taskRunTime = 0;
		task.taskRunCount = 0;
		startThread();
		return task;
	};

	this.stop = function(task) {
		removeTask(task);
		return task;
	};

	this.stopAll = function() {
		stopThread();
		for (var i = 0, len = tasks.length; i < len; i++) {
			if (tasks[i].onStop) {
				tasks[i].onStop();
			}
		}
		tasks = [];
		removeQueue = [];
	};
};

Ext.TaskMgr = new Ext.util.TaskRunner();

Ext.util.MixedCollection = function(allowFunctions, keyFn) {
	this.items = [];
	this.map = {};
	this.keys = [];
	this.length = 0;
	this.addEvents(
	"clear",
	"add",
	"replace",
	"remove", "sort");
	this.allowFunctions = allowFunctions === true;
	if (keyFn) {
		this.getKey = keyFn;
	}
	Ext.util.MixedCollection.superclass.constructor.call(this);
};

Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
	allowFunctions: false,

	add: function(key, o) {
		if (arguments.length == 1) {
			o = arguments[0];
			key = this.getKey(o);
		}
		if (typeof key == "undefined" || key === null) {
			this.length++;
			this.items.push(o);
			this.keys.push(null);
		} else {
			var old = this.map[key];
			if (old) {
				return this.replace(key, o);
			}
			this.length++;
			this.items.push(o);
			this.map[key] = o;
			this.keys.push(key);
		}
		this.fireEvent("add", this.length - 1, o, key);
		return o;
	},

	getKey: function(o) {
		return o.id;
	},

	replace: function(key, o) {
		if (arguments.length == 1) {
			o = arguments[0];
			key = this.getKey(o);
		}
		var old = this.item(key);
		if (typeof key == "undefined" || key === null || typeof old == "undefined") {
			return this.add(key, o);
		}
		var index = this.indexOfKey(key);
		this.items[index] = o;
		this.map[key] = o;
		this.fireEvent("replace", key, old, o);
		return o;
	},

	addAll: function(objs) {
		if (arguments.length > 1 || Ext.isArray(objs)) {
			var args = arguments.length > 1 ? arguments: objs;
			for (var i = 0, len = args.length; i < len; i++) {
				this.add(args[i]);
			}
		} else {
			for (var key in objs) {
				if (this.allowFunctions || typeof objs[key] != "function") {
					this.add(key, objs[key]);
				}
			}
		}
	},

	each: function(fn, scope) {
		var items = [].concat(this.items);
		for (var i = 0, len = items.length; i < len; i++) {
			if (fn.call(scope || items[i], items[i], i, len) === false) {
				break;
			}
		}
	},

	eachKey: function(fn, scope) {
		for (var i = 0, len = this.keys.length; i < len; i++) {
			fn.call(scope || window, this.keys[i], this.items[i], i, len);
		}
	},

	find: function(fn, scope) {
		for (var i = 0, len = this.items.length; i < len; i++) {
			if (fn.call(scope || window, this.items[i], this.keys[i])) {
				return this.items[i];
			}
		}
		return null;
	},

	insert: function(index, key, o) {
		if (arguments.length == 2) {
			o = arguments[1];
			key = this.getKey(o);
		}
		if (index >= this.length) {
			return this.add(key, o);
		}
		this.length++;
		this.items.splice(index, 0, o);
		if (typeof key != "undefined" && key != null) {
			this.map[key] = o;
		}
		this.keys.splice(index, 0, key);
		this.fireEvent("add", index, o, key);
		return o;
	},

	remove: function(o) {
		return this.removeAt(this.indexOf(o));
	},

	removeAt: function(index) {
		if (index < this.length && index >= 0) {
			this.length--;
			var o = this.items[index];
			this.items.splice(index, 1);
			var key = this.keys[index];
			if (typeof key != "undefined") {
				delete this.map[key];
			}
			this.keys.splice(index, 1);
			this.fireEvent("remove", o, key);
			return o;
		}
		return false;
	},

	removeKey: function(key) {
		return this.removeAt(this.indexOfKey(key));
	},

	getCount: function() {
		return this.length;
	},

	indexOf: function(o) {
		return this.items.indexOf(o);
	},

	indexOfKey: function(key) {
		return this.keys.indexOf(key);
	},

	item: function(key) {
		var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
		return typeof item != 'function' || this.allowFunctions ? item: null;
	},

	itemAt: function(index) {
		return this.items[index];
	},

	key: function(key) {
		return this.map[key];
	},

	contains: function(o) {
		return this.indexOf(o) != -1;
	},

	containsKey: function(key) {
		return typeof this.map[key] != "undefined";
	},

	clear: function() {
		this.length = 0;
		this.items = [];
		this.keys = [];
		this.map = {};
		this.fireEvent("clear");
	},

	first: function() {
		return this.items[0];
	},

	last: function() {
		return this.items[this.length - 1];
	},

	_sort: function(property, dir, fn) {
		var dsc = String(dir).toUpperCase() == "DESC" ? -1: 1;
		fn = fn ||
		function(a, b) {
			return a - b;
		};
		var c = [],
		k = this.keys,
		items = this.items;
		for (var i = 0, len = items.length; i < len; i++) {
			c[c.length] = {
				key: k[i],
				value: items[i],
				index: i
			};
		}
		c.sort(function(a, b) {
			var v = fn(a[property], b[property]) * dsc;
			if (v == 0) {
				v = (a.index < b.index ? -1: 1);
			}
			return v;
		});
		for (var i = 0, len = c.length; i < len; i++) {
			items[i] = c[i].value;
			k[i] = c[i].key;
		}
		this.fireEvent("sort", this);
	},

	sort: function(dir, fn) {
		this._sort("value", dir, fn);
	},

	keySort: function(dir, fn) {
		this._sort("key", dir, fn ||
		function(a, b) {
			return String(a).toUpperCase() - String(b).toUpperCase();
		});
	},

	getRange: function(start, end) {
		var items = this.items;
		if (items.length < 1) {
			return [];
		}
		start = start || 0;
		end = Math.min(typeof end == "undefined" ? this.length - 1: end, this.length - 1);
		var r = [];
		if (start <= end) {
			for (var i = start; i <= end; i++) {
				r[r.length] = items[i];
			}
		} else {
			for (var i = start; i >= end; i--) {
				r[r.length] = items[i];
			}
		}
		return r;
	},

	filter: function(property, value, anyMatch, caseSensitive) {
		if (Ext.isEmpty(value, false)) {
			return this.clone();
		}
		value = this.createValueMatcher(value, anyMatch, caseSensitive);
		return this.filterBy(function(o) {
			return o && value.test(o[property]);
		});
	},

	filterBy: function(fn, scope) {
		var r = new Ext.util.MixedCollection();
		r.getKey = this.getKey;
		var k = this.keys,
		it = this.items;
		for (var i = 0, len = it.length; i < len; i++) {
			if (fn.call(scope || this, it[i], k[i])) {
				r.add(k[i], it[i]);
			}
		}
		return r;
	},

	findIndex: function(property, value, start, anyMatch, caseSensitive) {
		if (Ext.isEmpty(value, false)) {
			return - 1;
		}
		value = this.createValueMatcher(value, anyMatch, caseSensitive);
		return this.findIndexBy(function(o) {
			return o && value.test(o[property]);
		},
		null, start);
	},

	findIndexBy: function(fn, scope, start) {
		var k = this.keys,
		it = this.items;
		for (var i = (start || 0), len = it.length; i < len; i++) {
			if (fn.call(scope || this, it[i], k[i])) {
				return i;
			}
		}
		if (typeof start == 'number' && start > 0) {
			for (var i = 0; i < start; i++) {
				if (fn.call(scope || this, it[i], k[i])) {
					return i;
				}
			}
		}
		return - 1;
	},

	createValueMatcher: function(value, anyMatch, caseSensitive) {
		if (!value.exec) {
			value = String(value);
			value = new RegExp((anyMatch === true ? '': '^') + Ext.escapeRe(value), caseSensitive ? '': 'i');
		}
		return value;
	},

	clone: function() {
		var r = new Ext.util.MixedCollection();
		var k = this.keys,
		it = this.items;
		for (var i = 0, len = it.length; i < len; i++) {
			r.add(k[i], it[i]);
		}
		r.getKey = this.getKey;
		return r;
	}
});

Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;

Ext.util.JSON = new(function() {
	var useHasOwn = !!{}.hasOwnProperty;

	var pad = function(n) {
		return n < 10 ? "0" + n: n;
	};

	var m = {
		"\b": '\\b',
		"\t": '\\t',
		"\n": '\\n',
		"\f": '\\f',
		"\r": '\\r',
		'"': '\\"',
		"\\": '\\\\'
	};

	var encodeString = function(s) {
		if (/["\\\x00-\x1f]/.test(s)) {
			return '"' + s.replace(/([\x00-\x1f\\"])/g,
			function(a, b) {
				var c = m[b];
				if (c) {
					return c;
				}
				c = b.charCodeAt();
				return "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
			}) + '"';
		}
		return '"' + s + '"';
	};

	var encodeArray = function(o) {
		var a = ["["],
		b,
		i,
		l = o.length,
		v;
		for (i = 0; i < l; i += 1) {
			v = o[i];
			switch (typeof v) {
			case "undefined":
			case "function":
			case "unknown":
				break;
			default:
				if (b) {
					a.push(',');
				}
				a.push(v === null ? "null": Ext.util.JSON.encode(v));
				b = true;
			}
		}
		a.push("]");
		return a.join("");
	};

	this.encodeDate = function(o) {
		return '"' + o.getFullYear() + "-" + pad(o.getMonth() + 1) + "-" + pad(o.getDate()) + "T" + pad(o.getHours()) + ":" + pad(o.getMinutes()) + ":" + pad(o.getSeconds()) + '"';
	};

	this.encode = function(o) {
		if (typeof o == "undefined" || o === null) {
			return "null";
		} else if (Ext.isArray(o)) {
			return encodeArray(o);
		} else if (Ext.isDate(o)) {
			return Ext.util.JSON.encodeDate(o);
		} else if (typeof o == "string") {
			return encodeString(o);
		} else if (typeof o == "number") {
			return isFinite(o) ? String(o) : "null";
		} else if (typeof o == "boolean") {
			return String(o);
		} else {
			var a = ["{"],
			b,
			i,
			v;
			for (i in o) {
				if (!useHasOwn || o.hasOwnProperty(i)) {
					v = o[i];
					switch (typeof v) {
					case "undefined":
					case "function":
					case "unknown":
						break;
					default:
						if (b) {
							a.push(',');
						}
						a.push(this.encode(i), ":", v === null ? "null": this.encode(v));
						b = true;
					}
				}
			}
			a.push("}");
			return a.join("");
		}
	};

	this.decode = function(json) {
		return eval("(" + json + ')');
	};
})();

Ext.encode = Ext.util.JSON.encode;

Ext.decode = Ext.util.JSON.decode;

Ext.util.Format = function() {
	var trimRe = /^\s+|\s+$/g;
	return {

		ellipsis: function(value, len) {
			if (value && value.length > len) {
				return value.substr(0, len - 3) + "...";
			}
			return value;
		},

		undef: function(value) {
			return value !== undefined ? value: "";
		},

		defaultValue: function(value, defaultValue) {
			return value !== undefined && value !== '' ? value: defaultValue;
		},

		htmlEncode: function(value) {
			return ! value ? value: String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
		},

		htmlDecode: function(value) {
			return ! value ? value: String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
		},

		trim: function(value) {
			return String(value).replace(trimRe, "");
		},

		substr: function(value, start, length) {
			return String(value).substr(start, length);
		},

		lowercase: function(value) {
			return String(value).toLowerCase();
		},

		uppercase: function(value) {
			return String(value).toUpperCase();
		},

		capitalize: function(value) {
			return ! value ? value: value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
		},

		call: function(value, fn) {
			if (arguments.length > 2) {
				var args = Array.prototype.slice.call(arguments, 2);
				args.unshift(value);
				return eval(fn).apply(window, args);
			} else {
				return eval(fn).call(window, value);
			}
		},

		usMoney: function(v) {
			v = (Math.round((v - 0) * 100)) / 100;
			v = (v == Math.floor(v)) ? v + ".00": ((v * 10 == Math.floor(v * 10)) ? v + "0": v);
			v = String(v);
			var ps = v.split('.');
			var whole = ps[0];
			var sub = ps[1] ? '.' + ps[1] : '.00';
			var r = /(\d+)(\d{3})/;
			while (r.test(whole)) {
				whole = whole.replace(r, '$1' + ',' + '$2');
			}
			v = whole + sub;
			if (v.charAt(0) == '-') {
				return '-$' + v.substr(1);
			}
			return "$" + v;
		},

		date: function(v, format) {
			if (!v) {
				return "";
			}
			if (!Ext.isDate(v)) {
				v = new Date(Date.parse(v));
			}
			return v.dateFormat(format || "m/d/Y");
		},

		dateRenderer: function(format) {
			return function(v) {
				return Ext.util.Format.date(v, format);
			};
		},

		stripTagsRE: /<\/?[^>]+>/gi,

		stripTags: function(v) {
			return ! v ? v: String(v).replace(this.stripTagsRE, "");
		},

		stripScriptsRe: /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,

		stripScripts: function(v) {
			return ! v ? v: String(v).replace(this.stripScriptsRe, "");
		},

		fileSize: function(size) {
			if (size < 1024) {
				return size + " bytes";
			} else if (size < 1048576) {
				return (Math.round(((size * 10) / 1024)) / 10) + " KB";
			} else {
				return (Math.round(((size * 10) / 1048576)) / 10) + " MB";
			}
		},

		math: function() {
			var fns = {};
			return function(v, a) {
				if (!fns[a]) {
					fns[a] = new Function('v', 'return v ' + a + ';');
				}
				return fns[a](v);
			}
		} (),

		nl2br: function(v) {
			return v === undefined || v === null ? '': v.replace(/\n/g, '<br/>');
		}
	};
} ();

Ext.XTemplate = function() {
	Ext.XTemplate.superclass.constructor.apply(this, arguments);
	var s = this.html;

	s = ['<tpl>', s, '</tpl>'].join('');

	var re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;

	var nameRe = /^<tpl\b[^>]*?for="(.*?)"/;
	var ifRe = /^<tpl\b[^>]*?if="(.*?)"/;
	var execRe = /^<tpl\b[^>]*?exec="(.*?)"/;
	var m,
	id = 0;
	var tpls = [];

	while (m = s.match(re)) {
		var m2 = m[0].match(nameRe);
		var m3 = m[0].match(ifRe);
		var m4 = m[0].match(execRe);
		var exp = null,
		fn = null,
		exec = null;
		var name = m2 && m2[1] ? m2[1] : '';
		if (m3) {
			exp = m3 && m3[1] ? m3[1] : null;
			if (exp) {
				fn = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ return ' + (Ext.util.Format.htmlDecode(exp)) + '; }');
			}
		}
		if (m4) {
			exp = m4 && m4[1] ? m4[1] : null;
			if (exp) {
				exec = new Function('values', 'parent', 'xindex', 'xcount', 'with(values){ ' + (Ext.util.Format.htmlDecode(exp)) + '; }');
			}
		}
		if (name) {
			switch (name) {
			case '.':
				name = new Function('values', 'parent', 'with(values){ return values; }');
				break;
			case '..':
				name = new Function('values', 'parent', 'with(values){ return parent; }');
				break;
			default:
				name = new Function('values', 'parent', 'with(values){ return ' + name + '; }');
			}
		}
		tpls.push({
			id: id,
			target: name,
			exec: exec,
			test: fn,
			body: m[1] || ''
		});
		s = s.replace(m[0], '{xtpl' + id + '}'); ++id;
	}
	for (var i = tpls.length - 1; i >= 0; --i) {
		this.compileTpl(tpls[i]);
	}
	this.master = tpls[tpls.length - 1];
	this.tpls = tpls;
};
Ext.extend(Ext.XTemplate, Ext.Template, {
	re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
	codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,

	applySubTemplate: function(id, values, parent, xindex, xcount) {
		var t = this.tpls[id];
		if (t.test && !t.test.call(this, values, parent, xindex, xcount)) {
			return '';
		}
		if (t.exec && t.exec.call(this, values, parent, xindex, xcount)) {
			return '';
		}
		var vs = t.target ? t.target.call(this, values, parent) : values;
		parent = t.target ? values: parent;
		if (t.target && Ext.isArray(vs)) {
			var buf = [];
			for (var i = 0, len = vs.length; i < len; i++) {
				buf[buf.length] = t.compiled.call(this, vs[i], parent, i + 1, len);
			}
			return buf.join('');
		}
		return t.compiled.call(this, vs, parent, xindex, xcount);
	},

	compileTpl: function(tpl) {
		var fm = Ext.util.Format;
		var useF = this.disableFormats !== true;
		var sep = Ext.isGecko ? "+": ",";
		var fn = function(m, name, format, args, math) {
			if (name.substr(0, 4) == 'xtpl') {
				return "'" + sep + 'this.applySubTemplate(' + name.substr(4) + ', values, parent, xindex, xcount)' + sep + "'";
			}
			var v;
			if (name === '.') {
				v = 'values';
			} else if (name === '#') {
				v = 'xindex';
			} else if (name.indexOf('.') != -1) {
				v = name;
			} else {
				v = "values['" + name + "']";
			}
			if (math) {
				v = '(' + v + math + ')';
			}
			if (format && useF) {
				args = args ? ',' + args: "";
				if (format.substr(0, 5) != "this.") {
					format = "fm." + format + '(';
				} else {
					format = 'this.call("' + format.substr(5) + '", ';
					args = ", values";
				}
			} else {
				args = '';
				format = "(" + v + " === undefined ? '' : ";
			}
			return "'" + sep + format + v + args + ")" + sep + "'";
		};
		var codeFn = function(m, code) {
			return "'" + sep + '(' + code + ')' + sep + "'";
		};

		var body;
		if (Ext.isGecko) {
			body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" + tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) + "';};";
		} else {
			body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
			body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
			body.push("'].join('');};");
			body = body.join('');
		}
		eval(body);
		return this;
	},

	applyTemplate: function(values) {
		return this.master.compiled.call(this, values, {},
		1, 1);
	},

	compile: function() {
		return this;
	}

});

Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;

Ext.XTemplate.from = function(el) {
	el = Ext.getDom(el);
	return new Ext.XTemplate(el.value || el.innerHTML);
};

Ext.util.CSS = function() {
	var rules = null;
	var doc = document;

	var camelRe = /(-[a-z])/gi;
	var camelFn = function(m, a) {
		return a.charAt(1).toUpperCase();
	};

	return {

		createStyleSheet: function(cssText, id) {
			var ss;
			var head = doc.getElementsByTagName("head")[0];
			var rules = doc.createElement("style");
			rules.setAttribute("type", "text/css");
			if (id) {
				rules.setAttribute("id", id);
			}
			if (Ext.isIE) {
				head.appendChild(rules);
				ss = rules.styleSheet;
				ss.cssText = cssText;
			} else {
				try {
					rules.appendChild(doc.createTextNode(cssText));
				} catch(e) {
					rules.cssText = cssText;
				}
				head.appendChild(rules);
				ss = rules.styleSheet ? rules.styleSheet: (rules.sheet || doc.styleSheets[doc.styleSheets.length - 1]);
			}
			this.cacheStyleSheet(ss);
			return ss;
		},

		removeStyleSheet: function(id) {
			var existing = doc.getElementById(id);
			if (existing) {
				existing.parentNode.removeChild(existing);
			}
		},

		swapStyleSheet: function(id, url) {
			this.removeStyleSheet(id);
			var ss = doc.createElement("link");
			ss.setAttribute("rel", "stylesheet");
			ss.setAttribute("type", "text/css");
			ss.setAttribute("id", id);
			ss.setAttribute("href", url);
			doc.getElementsByTagName("head")[0].appendChild(ss);
		},

		refreshCache: function() {
			return this.getRules(true);
		},

		cacheStyleSheet: function(ss) {
			if (!rules) {
				rules = {};
			}
			try {
				var ssRules = ss.cssRules || ss.rules;
				for (var j = ssRules.length - 1; j >= 0; --j) {
					rules[ssRules[j].selectorText] = ssRules[j];
				}
			} catch(e) {}
		},

		getRules: function(refreshCache) {
			if (rules == null || refreshCache) {
				rules = {};
				var ds = doc.styleSheets;
				for (var i = 0, len = ds.length; i < len; i++) {
					try {
						this.cacheStyleSheet(ds[i]);
					} catch(e) {}
				}
			}
			return rules;
		},

		getRule: function(selector, refreshCache) {
			var rs = this.getRules(refreshCache);
			if (!Ext.isArray(selector)) {
				return rs[selector];
			}
			for (var i = 0; i < selector.length; i++) {
				if (rs[selector[i]]) {
					return rs[selector[i]];
				}
			}
			return null;
		},

		updateRule: function(selector, property, value) {
			if (!Ext.isArray(selector)) {
				var rule = this.getRule(selector);
				if (rule) {
					rule.style[property.replace(camelRe, camelFn)] = value;
					return true;
				}
			} else {
				for (var i = 0; i < selector.length; i++) {
					if (this.updateRule(selector[i], property, value)) {
						return true;
					}
				}
			}
			return false;
		}
	};
} ();

Ext.util.ClickRepeater = function(el, config) {
	this.el = Ext.get(el);
	this.el.unselectable();

	Ext.apply(this, config);

	this.addEvents(
	"mousedown",
	"click",
	"mouseup");

	this.el.on("mousedown", this.handleMouseDown, this);
	if (this.preventDefault || this.stopDefault) {
		this.el.on("click",
		function(e) {
			if (this.preventDefault) {
				e.preventDefault();
			}
			if (this.stopDefault) {
				e.stopEvent();
			}
		},
		this);
	}

	if (this.handler) {
		this.on("click", this.handler, this.scope || this);
	}

	Ext.util.ClickRepeater.superclass.constructor.call(this);
};

Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
	interval: 20,
	delay: 250,
	preventDefault: true,
	stopDefault: false,
	timer: 0,

	handleMouseDown: function() {
		clearTimeout(this.timer);
		this.el.blur();
		if (this.pressClass) {
			this.el.addClass(this.pressClass);
		}
		this.mousedownTime = new Date();

		Ext.getDoc().on("mouseup", this.handleMouseUp, this);
		this.el.on("mouseout", this.handleMouseOut, this);

		this.fireEvent("mousedown", this);
		this.fireEvent("click", this);

		if (this.accelerate) {
			this.delay = 400;
		}
		this.timer = this.click.defer(this.delay || this.interval, this);
	},

	click: function() {
		this.fireEvent("click", this);
		this.timer = this.click.defer(this.accelerate ? this.easeOutExpo(this.mousedownTime.getElapsed(), 400, -390, 12000) : this.interval, this);
	},

	easeOutExpo: function(t, b, c, d) {
		return (t == d) ? b + c: c * ( - Math.pow(2, -10 * t / d) + 1) + b;
	},

	handleMouseOut: function() {
		clearTimeout(this.timer);
		if (this.pressClass) {
			this.el.removeClass(this.pressClass);
		}
		this.el.on("mouseover", this.handleMouseReturn, this);
	},

	handleMouseReturn: function() {
		this.el.un("mouseover", this.handleMouseReturn, this);
		if (this.pressClass) {
			this.el.addClass(this.pressClass);
		}
		this.click();
	},

	handleMouseUp: function() {
		clearTimeout(this.timer);
		this.el.un("mouseover", this.handleMouseReturn, this);
		this.el.un("mouseout", this.handleMouseOut, this);
		Ext.getDoc().un("mouseup", this.handleMouseUp, this);
		this.el.removeClass(this.pressClass);
		this.fireEvent("mouseup", this);
	}
});

Ext.KeyNav = function(el, config) {
	this.el = Ext.get(el);
	Ext.apply(this, config);
	if (!this.disabled) {
		this.disabled = true;
		this.enable();
	}
};

Ext.KeyNav.prototype = {

	disabled: false,

	defaultEventAction: "stopEvent",

	forceKeyDown: false,

	prepareEvent: function(e) {
		var k = e.getKey();
		var h = this.keyToHandler[k];
		if (Ext.isSafari2 && h && k >= 37 && k <= 40) {
			e.stopEvent();
		}
	},

	relay: function(e) {
		var k = e.getKey();
		var h = this.keyToHandler[k];
		if (h && this[h]) {
			if (this.doRelay(e, this[h], h) !== true) {
				e[this.defaultEventAction]();
			}
		}
	},

	doRelay: function(e, h, hname) {
		return h.call(this.scope || this, e);
	},

	enter: false,
	left: false,
	right: false,
	up: false,
	down: false,
	tab: false,
	esc: false,
	pageUp: false,
	pageDown: false,
	del: false,
	home: false,
	end: false,

	keyToHandler: {
		37: "left",
		39: "right",
		38: "up",
		40: "down",
		33: "pageUp",
		34: "pageDown",
		46: "del",
		36: "home",
		35: "end",
		13: "enter",
		27: "esc",
		9: "tab"
	},

	enable: function() {
		if (this.disabled) {
			if (this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isAir) {
				this.el.on("keydown", this.relay, this);
			} else {
				this.el.on("keydown", this.prepareEvent, this);
				this.el.on("keypress", this.relay, this);
			}
			this.disabled = false;
		}
	},

	disable: function() {
		if (!this.disabled) {
			if (this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isAir) {
				this.el.un("keydown", this.relay);
			} else {
				this.el.un("keydown", this.prepareEvent);
				this.el.un("keypress", this.relay);
			}
			this.disabled = true;
		}
	}
};

Ext.KeyMap = function(el, config, eventName) {
	this.el = Ext.get(el);
	this.eventName = eventName || "keydown";
	this.bindings = [];
	if (config) {
		this.addBinding(config);
	}
	this.enable();
};

Ext.KeyMap.prototype = {

	stopEvent: false,

	addBinding: function(config) {
		if (Ext.isArray(config)) {
			for (var i = 0, len = config.length; i < len; i++) {
				this.addBinding(config[i]);
			}
			return;
		}
		var keyCode = config.key,
		shift = config.shift,
		ctrl = config.ctrl,
		alt = config.alt,
		fn = config.fn || config.handler,
		scope = config.scope;

		if (config.stopEvent) {
			this.stopEvent = config.stopEvent;
		}

		if (typeof keyCode == "string") {
			var ks = [];
			var keyString = keyCode.toUpperCase();
			for (var j = 0, len = keyString.length; j < len; j++) {
				ks.push(keyString.charCodeAt(j));
			}
			keyCode = ks;
		}
		var keyArray = Ext.isArray(keyCode);

		var handler = function(e) {
			if ((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)) {
				var k = e.getKey();
				if (keyArray) {
					for (var i = 0, len = keyCode.length; i < len; i++) {
						if (keyCode[i] == k) {
							if (this.stopEvent) {
								e.stopEvent();
							}
							fn.call(scope || window, k, e);
							return;
						}
					}
				} else {
					if (k == keyCode) {
						if (this.stopEvent) {
							e.stopEvent();
						}
						fn.call(scope || window, k, e);
					}
				}
			}
		};
		this.bindings.push(handler);
	},

	on: function(key, fn, scope) {
		var keyCode,
		shift,
		ctrl,
		alt;
		if (typeof key == "object" && !Ext.isArray(key)) {
			keyCode = key.key;
			shift = key.shift;
			ctrl = key.ctrl;
			alt = key.alt;
		} else {
			keyCode = key;
		}
		this.addBinding({
			key: keyCode,
			shift: shift,
			ctrl: ctrl,
			alt: alt,
			fn: fn,
			scope: scope
		})
	},

	handleKeyDown: function(e) {
		if (this.enabled) {
			var b = this.bindings;
			for (var i = 0, len = b.length; i < len; i++) {
				b[i].call(this, e);
			}
		}
	},

	isEnabled: function() {
		return this.enabled;
	},

	enable: function() {
		if (!this.enabled) {
			this.el.on(this.eventName, this.handleKeyDown, this);
			this.enabled = true;
		}
	},

	disable: function() {
		if (this.enabled) {
			this.el.removeListener(this.eventName, this.handleKeyDown, this);
			this.enabled = false;
		}
	}
};

Ext.util.TextMetrics = function() {
	var shared;
	return {

		measure: function(el, text, fixedWidth) {
			if (!shared) {
				shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
			}
			shared.bind(el);
			shared.setFixedWidth(fixedWidth || 'auto');
			return shared.getSize(text);
		},

		createInstance: function(el, fixedWidth) {
			return Ext.util.TextMetrics.Instance(el, fixedWidth);
		}
	};
} ();

Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth) {
	var ml = new Ext.Element(document.createElement('div'));
	document.body.appendChild(ml.dom);
	ml.position('absolute');
	ml.setLeftTop( - 1000, -1000);
	ml.hide();

	if (fixedWidth) {
		ml.setWidth(fixedWidth);
	}

	var instance = {

		getSize: function(text) {
			ml.update(text);
			var s = ml.getSize();
			ml.update('');
			return s;
		},

		bind: function(el) {
			ml.setStyle(Ext.fly(el).getStyles('font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'));
		},

		setFixedWidth: function(width) {
			ml.setWidth(width);
		},

		getWidth: function(text) {
			ml.dom.style.width = 'auto';
			return this.getSize(text).width;
		},

		getHeight: function(text) {
			return this.getSize(text).height;
		}
	};

	instance.bind(bindTo);

	return instance;
};

Ext.Element.measureText = Ext.util.TextMetrics.measure;
 (function() {

	var Event = Ext.EventManager;
	var Dom = Ext.lib.Dom;

	Ext.dd.DragDrop = function(id, sGroup, config) {
		if (id) {
			this.init(id, sGroup, config);
		}
	};

	Ext.dd.DragDrop.prototype = {

		id: null,

		config: null,

		dragElId: null,

		handleElId: null,

		invalidHandleTypes: null,

		invalidHandleIds: null,

		invalidHandleClasses: null,

		startPageX: 0,

		startPageY: 0,

		groups: null,

		locked: false,

		lock: function() {
			this.locked = true;
		},

		unlock: function() {
			this.locked = false;
		},

		isTarget: true,

		padding: null,

		_domRef: null,

		__ygDragDrop: true,

		constrainX: false,

		constrainY: false,

		minX: 0,

		maxX: 0,

		minY: 0,

		maxY: 0,

		maintainOffset: false,

		xTicks: null,

		yTicks: null,

		primaryButtonOnly: true,

		available: false,

		hasOuterHandles: false,

		b4StartDrag: function(x, y) {},

		startDrag: function(x, y) {},

		b4Drag: function(e) {},

		onDrag: function(e) {},

		onDragEnter: function(e, id) {},

		b4DragOver: function(e) {},

		onDragOver: function(e, id) {},

		b4DragOut: function(e) {},

		onDragOut: function(e, id) {},

		b4DragDrop: function(e) {},

		onDragDrop: function(e, id) {},

		onInvalidDrop: function(e) {},

		b4EndDrag: function(e) {},

		endDrag: function(e) {},

		b4MouseDown: function(e) {},

		onMouseDown: function(e) {},

		onMouseUp: function(e) {},

		onAvailable: function() {},

		defaultPadding: {
			left: 0,
			right: 0,
			top: 0,
			bottom: 0
		},

		constrainTo: function(constrainTo, pad, inContent) {
			if (typeof pad == "number") {
				pad = {
					left: pad,
					right: pad,
					top: pad,
					bottom: pad
				};
			}
			pad = pad || this.defaultPadding;
			var b = Ext.get(this.getEl()).getBox();
			var ce = Ext.get(constrainTo);
			var s = ce.getScroll();
			var c,
			cd = ce.dom;
			if (cd == document.body) {
				c = {
					x: s.left,
					y: s.top,
					width: Ext.lib.Dom.getViewWidth(),
					height: Ext.lib.Dom.getViewHeight()
				};
			} else {
				var xy = ce.getXY();
				c = {
					x: xy[0] + s.left,
					y: xy[1] + s.top,
					width: cd.clientWidth,
					height: cd.clientHeight
				};
			}

			var topSpace = b.y - c.y;
			var leftSpace = b.x - c.x;

			this.resetConstraints();
			this.setXConstraint(leftSpace - (pad.left || 0), c.width - leftSpace - b.width - (pad.right || 0), this.xTickSize);
			this.setYConstraint(topSpace - (pad.top || 0), c.height - topSpace - b.height - (pad.bottom || 0), this.yTickSize);
		},

		getEl: function() {
			if (!this._domRef) {
				this._domRef = Ext.getDom(this.id);
			}

			return this._domRef;
		},

		getDragEl: function() {
			return Ext.getDom(this.dragElId);
		},

		init: function(id, sGroup, config) {
			this.initTarget(id, sGroup, config);
			Event.on(this.id, "mousedown", this.handleMouseDown, this);

		},

		initTarget: function(id, sGroup, config) {

			this.config = config || {};

			this.DDM = Ext.dd.DDM;

			this.groups = {};

			if (typeof id !== "string") {
				id = Ext.id(id);
			}

			this.id = id;

			this.addToGroup((sGroup) ? sGroup: "default");

			this.handleElId = id;

			this.setDragElId(id);

			this.invalidHandleTypes = {
				A: "A"
			};
			this.invalidHandleIds = {};
			this.invalidHandleClasses = [];

			this.applyConfig();

			this.handleOnAvailable();
		},

		applyConfig: function() {

			this.padding = this.config.padding || [0, 0, 0, 0];
			this.isTarget = (this.config.isTarget !== false);
			this.maintainOffset = (this.config.maintainOffset);
			this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);

		},

		handleOnAvailable: function() {
			this.available = true;
			this.resetConstraints();
			this.onAvailable();
		},

		setPadding: function(iTop, iRight, iBot, iLeft) {

			if (!iRight && 0 !== iRight) {
				this.padding = [iTop, iTop, iTop, iTop];
			} else if (!iBot && 0 !== iBot) {
				this.padding = [iTop, iRight, iTop, iRight];
			} else {
				this.padding = [iTop, iRight, iBot, iLeft];
			}
		},

		setInitPosition: function(diffX, diffY) {
			var el = this.getEl();

			if (!this.DDM.verifyEl(el)) {
				return;
			}

			var dx = diffX || 0;
			var dy = diffY || 0;

			var p = Dom.getXY(el);

			this.initPageX = p[0] - dx;
			this.initPageY = p[1] - dy;

			this.lastPageX = p[0];
			this.lastPageY = p[1];

			this.setStartPosition(p);
		},

		setStartPosition: function(pos) {
			var p = pos || Dom.getXY(this.getEl());
			this.deltaSetXY = null;

			this.startPageX = p[0];
			this.startPageY = p[1];
		},

		addToGroup: function(sGroup) {
			this.groups[sGroup] = true;
			this.DDM.regDragDrop(this, sGroup);
		},

		removeFromGroup: function(sGroup) {
			if (this.groups[sGroup]) {
				delete this.groups[sGroup];
			}

			this.DDM.removeDDFromGroup(this, sGroup);
		},

		setDragElId: function(id) {
			this.dragElId = id;
		},

		setHandleElId: function(id) {
			if (typeof id !== "string") {
				id = Ext.id(id);
			}
			this.handleElId = id;
			this.DDM.regHandle(this.id, id);
		},

		setOuterHandleElId: function(id) {
			if (typeof id !== "string") {
				id = Ext.id(id);
			}
			Event.on(id, "mousedown", this.handleMouseDown, this);
			this.setHandleElId(id);

			this.hasOuterHandles = true;
		},

		unreg: function() {
			Event.un(this.id, "mousedown", this.handleMouseDown);
			this._domRef = null;
			this.DDM._remove(this);
		},

		destroy: function() {
			this.unreg();
		},

		isLocked: function() {
			return (this.DDM.isLocked() || this.locked);
		},

		handleMouseDown: function(e, oDD) {
			if (this.primaryButtonOnly && e.button != 0) {
				return;
			}

			if (this.isLocked()) {
				return;
			}

			this.DDM.refreshCache(this.groups);

			var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
			if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this)) {} else {
				if (this.clickValidator(e)) {

					this.setStartPosition();

					this.b4MouseDown(e);
					this.onMouseDown(e);

					this.DDM.handleMouseDown(e, this);

					this.DDM.stopEvent(e);
				} else {
					}
			}
		},

		clickValidator: function(e) {
			var target = e.getTarget();
			return (this.isValidHandleChild(target) && (this.id == this.handleElId || this.DDM.handleWasClicked(target, this.id)));
		},

		addInvalidHandleType: function(tagName) {
			var type = tagName.toUpperCase();
			this.invalidHandleTypes[type] = type;
		},

		addInvalidHandleId: function(id) {
			if (typeof id !== "string") {
				id = Ext.id(id);
			}
			this.invalidHandleIds[id] = id;
		},

		addInvalidHandleClass: function(cssClass) {
			this.invalidHandleClasses.push(cssClass);
		},

		removeInvalidHandleType: function(tagName) {
			var type = tagName.toUpperCase();

			delete this.invalidHandleTypes[type];
		},

		removeInvalidHandleId: function(id) {
			if (typeof id !== "string") {
				id = Ext.id(id);
			}
			delete this.invalidHandleIds[id];
		},

		removeInvalidHandleClass: function(cssClass) {
			for (var i = 0, len = this.invalidHandleClasses.length; i < len; ++i) {
				if (this.invalidHandleClasses[i] == cssClass) {
					delete this.invalidHandleClasses[i];
				}
			}
		},

		isValidHandleChild: function(node) {

			var valid = true;

			var nodeName;
			try {
				nodeName = node.nodeName.toUpperCase();
			} catch(e) {
				nodeName = node.nodeName;
			}
			valid = valid && !this.invalidHandleTypes[nodeName];
			valid = valid && !this.invalidHandleIds[node.id];

			for (var i = 0, len = this.invalidHandleClasses.length; valid && i < len; ++i) {
				valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
			}

			return valid;

		},

		setXTicks: function(iStartX, iTickSize) {
			this.xTicks = [];
			this.xTickSize = iTickSize;

			var tickMap = {};

			for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
				if (!tickMap[i]) {
					this.xTicks[this.xTicks.length] = i;
					tickMap[i] = true;
				}
			}

			for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
				if (!tickMap[i]) {
					this.xTicks[this.xTicks.length] = i;
					tickMap[i] = true;
				}
			}

			this.xTicks.sort(this.DDM.numericSort);
		},

		setYTicks: function(iStartY, iTickSize) {
			this.yTicks = [];
			this.yTickSize = iTickSize;

			var tickMap = {};

			for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
				if (!tickMap[i]) {
					this.yTicks[this.yTicks.length] = i;
					tickMap[i] = true;
				}
			}

			for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
				if (!tickMap[i]) {
					this.yTicks[this.yTicks.length] = i;
					tickMap[i] = true;
				}
			}

			this.yTicks.sort(this.DDM.numericSort);
		},

		setXConstraint: function(iLeft, iRight, iTickSize) {
			this.leftConstraint = iLeft;
			this.rightConstraint = iRight;

			this.minX = this.initPageX - iLeft;
			this.maxX = this.initPageX + iRight;
			if (iTickSize) {
				this.setXTicks(this.initPageX, iTickSize);
			}

			this.constrainX = true;
		},

		clearConstraints: function() {
			this.constrainX = false;
			this.constrainY = false;
			this.clearTicks();
		},

		clearTicks: function() {
			this.xTicks = null;
			this.yTicks = null;
			this.xTickSize = 0;
			this.yTickSize = 0;
		},

		setYConstraint: function(iUp, iDown, iTickSize) {
			this.topConstraint = iUp;
			this.bottomConstraint = iDown;

			this.minY = this.initPageY - iUp;
			this.maxY = this.initPageY + iDown;
			if (iTickSize) {
				this.setYTicks(this.initPageY, iTickSize);
			}

			this.constrainY = true;

		},

		resetConstraints: function() {

			if (this.initPageX || this.initPageX === 0) {

				var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX: 0;
				var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY: 0;

				this.setInitPosition(dx, dy);

			} else {
				this.setInitPosition();
			}

			if (this.constrainX) {
				this.setXConstraint(this.leftConstraint, this.rightConstraint, this.xTickSize);
			}

			if (this.constrainY) {
				this.setYConstraint(this.topConstraint, this.bottomConstraint, this.yTickSize);
			}
		},

		getTick: function(val, tickArray) {

			if (!tickArray) {

				return val;
			} else if (tickArray[0] >= val) {

				return tickArray[0];
			} else {
				for (var i = 0, len = tickArray.length; i < len; ++i) {
					var next = i + 1;
					if (tickArray[next] && tickArray[next] >= val) {
						var diff1 = val - tickArray[i];
						var diff2 = tickArray[next] - val;
						return (diff2 > diff1) ? tickArray[i] : tickArray[next];
					}
				}

				return tickArray[tickArray.length - 1];
			}
		},

		toString: function() {
			return ("DragDrop " + this.id);
		}

	};

})();

if (!Ext.dd.DragDropMgr) {

	Ext.dd.DragDropMgr = function() {

		var Event = Ext.EventManager;

		return {

			ids: {},

			handleIds: {},

			dragCurrent: null,

			dragOvers: {},

			deltaX: 0,

			deltaY: 0,

			preventDefault: true,

			stopPropagation: true,

			initialized: false,

			locked: false,

			init: function() {
				this.initialized = true;
			},

			POINT: 0,

			INTERSECT: 1,

			mode: 0,

			_execOnAll: function(sMethod, args) {
				for (var i in this.ids) {
					for (var j in this.ids[i]) {
						var oDD = this.ids[i][j];
						if (!this.isTypeOfDD(oDD)) {
							continue;
						}
						oDD[sMethod].apply(oDD, args);
					}
				}
			},

			_onLoad: function() {

				this.init();

				Event.on(document, "mouseup", this.handleMouseUp, this, true);
				Event.on(document, "mousemove", this.handleMouseMove, this, true);
				Event.on(window, "unload", this._onUnload, this, true);
				Event.on(window, "resize", this._onResize, this, true);

			},

			_onResize: function(e) {
				this._execOnAll("resetConstraints", []);
			},

			lock: function() {
				this.locked = true;
			},

			unlock: function() {
				this.locked = false;
			},

			isLocked: function() {
				return this.locked;
			},

			locationCache: {},

			useCache: true,

			clickPixelThresh: 3,

			clickTimeThresh: 350,

			dragThreshMet: false,

			clickTimeout: null,

			startX: 0,

			startY: 0,

			regDragDrop: function(oDD, sGroup) {
				if (!this.initialized) {
					this.init();
				}

				if (!this.ids[sGroup]) {
					this.ids[sGroup] = {};
				}
				this.ids[sGroup][oDD.id] = oDD;
			},

			removeDDFromGroup: function(oDD, sGroup) {
				if (!this.ids[sGroup]) {
					this.ids[sGroup] = {};
				}

				var obj = this.ids[sGroup];
				if (obj && obj[oDD.id]) {
					delete obj[oDD.id];
				}
			},

			_remove: function(oDD) {
				for (var g in oDD.groups) {
					if (g && this.ids[g][oDD.id]) {
						delete this.ids[g][oDD.id];
					}
				}
				delete this.handleIds[oDD.id];
			},

			regHandle: function(sDDId, sHandleId) {
				if (!this.handleIds[sDDId]) {
					this.handleIds[sDDId] = {};
				}
				this.handleIds[sDDId][sHandleId] = sHandleId;
			},

			isDragDrop: function(id) {
				return (this.getDDById(id)) ? true: false;
			},

			getRelated: function(p_oDD, bTargetsOnly) {
				var oDDs = [];
				for (var i in p_oDD.groups) {
					for (j in this.ids[i]) {
						var dd = this.ids[i][j];
						if (!this.isTypeOfDD(dd)) {
							continue;
						}
						if (!bTargetsOnly || dd.isTarget) {
							oDDs[oDDs.length] = dd;
						}
					}
				}

				return oDDs;
			},

			isLegalTarget: function(oDD, oTargetDD) {
				var targets = this.getRelated(oDD, true);
				for (var i = 0, len = targets.length; i < len; ++i) {
					if (targets[i].id == oTargetDD.id) {
						return true;
					}
				}

				return false;
			},

			isTypeOfDD: function(oDD) {
				return (oDD && oDD.__ygDragDrop);
			},

			isHandle: function(sDDId, sHandleId) {
				return (this.handleIds[sDDId] && this.handleIds[sDDId][sHandleId]);
			},

			getDDById: function(id) {
				for (var i in this.ids) {
					if (this.ids[i][id]) {
						return this.ids[i][id];
					}
				}
				return null;
			},

			handleMouseDown: function(e, oDD) {
				if (Ext.QuickTips) {
					Ext.QuickTips.disable();
				}
				this.currentTarget = e.getTarget();

				this.dragCurrent = oDD;

				var el = oDD.getEl();

				this.startX = e.getPageX();
				this.startY = e.getPageY();

				this.deltaX = this.startX - el.offsetLeft;
				this.deltaY = this.startY - el.offsetTop;

				this.dragThreshMet = false;

				this.clickTimeout = setTimeout(function() {
					var DDM = Ext.dd.DDM;
					DDM.startDrag(DDM.startX, DDM.startY);
				},
				this.clickTimeThresh);
			},

			startDrag: function(x, y) {
				clearTimeout(this.clickTimeout);
				if (this.dragCurrent) {
					this.dragCurrent.b4StartDrag(x, y);
					this.dragCurrent.startDrag(x, y);
				}
				this.dragThreshMet = true;
			},

			handleMouseUp: function(e) {

				if (Ext.QuickTips) {
					Ext.QuickTips.enable();
				}
				if (!this.dragCurrent) {
					return;
				}

				clearTimeout(this.clickTimeout);

				if (this.dragThreshMet) {
					this.fireEvents(e, true);
				} else {}

				this.stopDrag(e);

				this.stopEvent(e);
			},

			stopEvent: function(e) {
				if (this.stopPropagation) {
					e.stopPropagation();
				}

				if (this.preventDefault) {
					e.preventDefault();
				}
			},

			stopDrag: function(e) {

				if (this.dragCurrent) {
					if (this.dragThreshMet) {
						this.dragCurrent.b4EndDrag(e);
						this.dragCurrent.endDrag(e);
					}

					this.dragCurrent.onMouseUp(e);
				}

				this.dragCurrent = null;
				this.dragOvers = {};
			},

			handleMouseMove: function(e) {
				if (!this.dragCurrent) {
					return true;
				}

				if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
					this.stopEvent(e);
					return this.handleMouseUp(e);
				}

				if (!this.dragThreshMet) {
					var diffX = Math.abs(this.startX - e.getPageX());
					var diffY = Math.abs(this.startY - e.getPageY());
					if (diffX > this.clickPixelThresh || diffY > this.clickPixelThresh) {
						this.startDrag(this.startX, this.startY);
					}
				}

				if (this.dragThreshMet) {
					this.dragCurrent.b4Drag(e);
					this.dragCurrent.onDrag(e);
					if (!this.dragCurrent.moveOnly) {
						this.fireEvents(e, false);
					}
				}

				this.stopEvent(e);

				return true;
			},

			fireEvents: function(e, isDrop) {
				var dc = this.dragCurrent;

				if (!dc || dc.isLocked()) {
					return;
				}

				var pt = e.getPoint();

				var oldOvers = [];

				var outEvts = [];
				var overEvts = [];
				var dropEvts = [];
				var enterEvts = [];

				for (var i in this.dragOvers) {

					var ddo = this.dragOvers[i];

					if (!this.isTypeOfDD(ddo)) {
						continue;
					}

					if (!this.isOverTarget(pt, ddo, this.mode)) {
						outEvts.push(ddo);
					}

					oldOvers[i] = true;
					delete this.dragOvers[i];
				}

				for (var sGroup in dc.groups) {

					if ("string" != typeof sGroup) {
						continue;
					}

					for (i in this.ids[sGroup]) {
						var oDD = this.ids[sGroup][i];
						if (!this.isTypeOfDD(oDD)) {
							continue;
						}

						if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
							if (this.isOverTarget(pt, oDD, this.mode)) {

								if (isDrop) {
									dropEvts.push(oDD);

								} else {

									if (!oldOvers[oDD.id]) {
										enterEvts.push(oDD);

									} else {
										overEvts.push(oDD);
									}

									this.dragOvers[oDD.id] = oDD;
								}
							}
						}
					}
				}

				if (this.mode) {
					if (outEvts.length) {
						dc.b4DragOut(e, outEvts);
						dc.onDragOut(e, outEvts);
					}

					if (enterEvts.length) {
						dc.onDragEnter(e, enterEvts);
					}

					if (overEvts.length) {
						dc.b4DragOver(e, overEvts);
						dc.onDragOver(e, overEvts);
					}

					if (dropEvts.length) {
						dc.b4DragDrop(e, dropEvts);
						dc.onDragDrop(e, dropEvts);
					}

				} else {

					var len = 0;
					for (i = 0, len = outEvts.length; i < len; ++i) {
						dc.b4DragOut(e, outEvts[i].id);
						dc.onDragOut(e, outEvts[i].id);
					}

					for (i = 0, len = enterEvts.length; i < len; ++i) {

						dc.onDragEnter(e, enterEvts[i].id);
					}

					for (i = 0, len = overEvts.length; i < len; ++i) {
						dc.b4DragOver(e, overEvts[i].id);
						dc.onDragOver(e, overEvts[i].id);
					}

					for (i = 0, len = dropEvts.length; i < len; ++i) {
						dc.b4DragDrop(e, dropEvts[i].id);
						dc.onDragDrop(e, dropEvts[i].id);
					}

				}

				if (isDrop && !dropEvts.length) {
					dc.onInvalidDrop(e);
				}

			},

			getBestMatch: function(dds) {
				var winner = null;

				var len = dds.length;

				if (len == 1) {
					winner = dds[0];
				} else {

					for (var i = 0; i < len; ++i) {
						var dd = dds[i];

						if (dd.cursorIsOver) {
							winner = dd;
							break;

						} else {
							if (!winner || winner.overlap.getArea() < dd.overlap.getArea()) {
								winner = dd;
							}
						}
					}
				}

				return winner;
			},

			refreshCache: function(groups) {
				for (var sGroup in groups) {
					if ("string" != typeof sGroup) {
						continue;
					}
					for (var i in this.ids[sGroup]) {
						var oDD = this.ids[sGroup][i];

						if (this.isTypeOfDD(oDD)) {

							var loc = this.getLocation(oDD);
							if (loc) {
								this.locationCache[oDD.id] = loc;
							} else {
								delete this.locationCache[oDD.id];

							}
						}
					}
				}
			},

			verifyEl: function(el) {
				if (el) {
					var parent;
					if (Ext.isIE) {
						try {
							parent = el.offsetParent;
						} catch(e) {}
					} else {
						parent = el.offsetParent;
					}
					if (parent) {
						return true;
					}
				}

				return false;
			},

			getLocation: function(oDD) {
				if (!this.isTypeOfDD(oDD)) {
					return null;
				}

				var el = oDD.getEl(),
				pos,
				x1,
				x2,
				y1,
				y2,
				t,
				r,
				b,
				l;

				try {
					pos = Ext.lib.Dom.getXY(el);
				} catch(e) {}

				if (!pos) {
					return null;
				}

				x1 = pos[0];
				x2 = x1 + el.offsetWidth;
				y1 = pos[1];
				y2 = y1 + el.offsetHeight;

				t = y1 - oDD.padding[0];
				r = x2 + oDD.padding[1];
				b = y2 + oDD.padding[2];
				l = x1 - oDD.padding[3];

				return new Ext.lib.Region(t, r, b, l);
			},

			isOverTarget: function(pt, oTarget, intersect) {

				var loc = this.locationCache[oTarget.id];
				if (!loc || !this.useCache) {
					loc = this.getLocation(oTarget);
					this.locationCache[oTarget.id] = loc;

				}

				if (!loc) {
					return false;
				}

				oTarget.cursorIsOver = loc.contains(pt);

				var dc = this.dragCurrent;
				if (!dc || !dc.getTargetCoord || (!intersect && !dc.constrainX && !dc.constrainY)) {
					return oTarget.cursorIsOver;
				}

				oTarget.overlap = null;

				var pos = dc.getTargetCoord(pt.x, pt.y);

				var el = dc.getDragEl();
				var curRegion = new Ext.lib.Region(pos.y, pos.x + el.offsetWidth, pos.y + el.offsetHeight, pos.x);

				var overlap = curRegion.intersect(loc);

				if (overlap) {
					oTarget.overlap = overlap;
					return (intersect) ? true: oTarget.cursorIsOver;
				} else {
					return false;
				}
			},

			_onUnload: function(e, me) {
				Ext.dd.DragDropMgr.unregAll();
			},

			unregAll: function() {

				if (this.dragCurrent) {
					this.stopDrag();
					this.dragCurrent = null;
				}

				this._execOnAll("unreg", []);

				for (var i in this.elementCache) {
					delete this.elementCache[i];
				}

				this.elementCache = {};
				this.ids = {};
			},

			elementCache: {},

			getElWrapper: function(id) {
				var oWrapper = this.elementCache[id];
				if (!oWrapper || !oWrapper.el) {
					oWrapper = this.elementCache[id] = new this.ElementWrapper(Ext.getDom(id));
				}
				return oWrapper;
			},

			getElement: function(id) {
				return Ext.getDom(id);
			},

			getCss: function(id) {
				var el = Ext.getDom(id);
				return (el) ? el.style: null;
			},

			ElementWrapper: function(el) {

				this.el = el || null;

				this.id = this.el && el.id;

				this.css = this.el && el.style;
			},

			getPosX: function(el) {
				return Ext.lib.Dom.getX(el);
			},

			getPosY: function(el) {
				return Ext.lib.Dom.getY(el);
			},

			swapNode: function(n1, n2) {
				if (n1.swapNode) {
					n1.swapNode(n2);
				} else {
					var p = n2.parentNode;
					var s = n2.nextSibling;

					if (s == n1) {
						p.insertBefore(n1, n2);
					} else if (n2 == n1.nextSibling) {
						p.insertBefore(n2, n1);
					} else {
						n1.parentNode.replaceChild(n2, n1);
						p.insertBefore(n1, s);
					}
				}
			},

			getScroll: function() {
				var t,
				l,
				dde = document.documentElement,
				db = document.body;
				if (dde && (dde.scrollTop || dde.scrollLeft)) {
					t = dde.scrollTop;
					l = dde.scrollLeft;
				} else if (db) {
					t = db.scrollTop;
					l = db.scrollLeft;
				} else {
					}
				return {
					top: t,
					left: l
				};
			},

			getStyle: function(el, styleProp) {
				return Ext.fly(el).getStyle(styleProp);
			},

			getScrollTop: function() {
				return this.getScroll().top;
			},

			getScrollLeft: function() {
				return this.getScroll().left;
			},

			moveToEl: function(moveEl, targetEl) {
				var aCoord = Ext.lib.Dom.getXY(targetEl);
				Ext.lib.Dom.setXY(moveEl, aCoord);
			},

			numericSort: function(a, b) {
				return (a - b);
			},

			_timeoutCount: 0,

			_addListeners: function() {
				var DDM = Ext.dd.DDM;
				if (Ext.lib.Event && document) {
					DDM._onLoad();
				} else {
					if (DDM._timeoutCount > 2000) {} else {
						setTimeout(DDM._addListeners, 10);
						if (document && document.body) {
							DDM._timeoutCount += 1;
						}
					}
				}
			},

			handleWasClicked: function(node, id) {
				if (this.isHandle(id, node.id)) {
					return true;
				} else {

					var p = node.parentNode;

					while (p) {
						if (this.isHandle(id, p.id)) {
							return true;
						} else {
							p = p.parentNode;
						}
					}
				}

				return false;
			}

		};

	} ();

	Ext.dd.DDM = Ext.dd.DragDropMgr;
	Ext.dd.DDM._addListeners();

}

Ext.dd.DD = function(id, sGroup, config) {
	if (id) {
		this.init(id, sGroup, config);
	}
};

Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {

	scroll: true,

	autoOffset: function(iPageX, iPageY) {
		var x = iPageX - this.startPageX;
		var y = iPageY - this.startPageY;
		this.setDelta(x, y);
	},

	setDelta: function(iDeltaX, iDeltaY) {
		this.deltaX = iDeltaX;
		this.deltaY = iDeltaY;
	},

	setDragElPos: function(iPageX, iPageY) {

		var el = this.getDragEl();
		this.alignElWithMouse(el, iPageX, iPageY);
	},

	alignElWithMouse: function(el, iPageX, iPageY) {
		var oCoord = this.getTargetCoord(iPageX, iPageY);
		var fly = el.dom ? el: Ext.fly(el, '_dd');
		if (!this.deltaSetXY) {
			var aCoord = [oCoord.x, oCoord.y];
			fly.setXY(aCoord);
			var newLeft = fly.getLeft(true);
			var newTop = fly.getTop(true);
			this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
		} else {
			fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
		}

		this.cachePosition(oCoord.x, oCoord.y);
		this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
		return oCoord;
	},

	cachePosition: function(iPageX, iPageY) {
		if (iPageX) {
			this.lastPageX = iPageX;
			this.lastPageY = iPageY;
		} else {
			var aCoord = Ext.lib.Dom.getXY(this.getEl());
			this.lastPageX = aCoord[0];
			this.lastPageY = aCoord[1];
		}
	},

	autoScroll: function(x, y, h, w) {

		if (this.scroll) {

			var clientH = Ext.lib.Dom.getViewHeight();

			var clientW = Ext.lib.Dom.getViewWidth();

			var st = this.DDM.getScrollTop();

			var sl = this.DDM.getScrollLeft();

			var bot = h + y;

			var right = w + x;

			var toBot = (clientH + st - y - this.deltaY);

			var toRight = (clientW + sl - x - this.deltaX);

			var thresh = 40;

			var scrAmt = (document.all) ? 80: 30;

			if (bot > clientH && toBot < thresh) {
				window.scrollTo(sl, st + scrAmt);
			}

			if (y < st && st > 0 && y - st < thresh) {
				window.scrollTo(sl, st - scrAmt);
			}

			if (right > clientW && toRight < thresh) {
				window.scrollTo(sl + scrAmt, st);
			}

			if (x < sl && sl > 0 && x - sl < thresh) {
				window.scrollTo(sl - scrAmt, st);
			}
		}
	},

	getTargetCoord: function(iPageX, iPageY) {

		var x = iPageX - this.deltaX;
		var y = iPageY - this.deltaY;

		if (this.constrainX) {
			if (x < this.minX) {
				x = this.minX;
			}
			if (x > this.maxX) {
				x = this.maxX;
			}
		}

		if (this.constrainY) {
			if (y < this.minY) {
				y = this.minY;
			}
			if (y > this.maxY) {
				y = this.maxY;
			}
		}

		x = this.getTick(x, this.xTicks);
		y = this.getTick(y, this.yTicks);

		return {
			x: x,
			y: y
		};
	},

	applyConfig: function() {
		Ext.dd.DD.superclass.applyConfig.call(this);
		this.scroll = (this.config.scroll !== false);
	},

	b4MouseDown: function(e) {

		this.autoOffset(e.getPageX(), e.getPageY());
	},

	b4Drag: function(e) {
		this.setDragElPos(e.getPageX(), e.getPageY());
	},

	toString: function() {
		return ("DD " + this.id);
	}

});

Ext.dd.DDProxy = function(id, sGroup, config) {
	if (id) {
		this.init(id, sGroup, config);
		this.initFrame();
	}
};

Ext.dd.DDProxy.dragElId = "ygddfdiv";

Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {

	resizeFrame: true,

	centerFrame: false,

	createFrame: function() {
		var self = this;
		var body = document.body;

		if (!body || !body.firstChild) {
			setTimeout(function() {
				self.createFrame();
			},
			50);
			return;
		}

		var div = this.getDragEl();

		if (!div) {
			div = document.createElement("div");
			div.id = this.dragElId;
			var s = div.style;

			s.position = "absolute";
			s.visibility = "hidden";
			s.cursor = "move";
			s.border = "2px solid #aaa";
			s.zIndex = 999;

			body.insertBefore(div, body.firstChild);
		}
	},

	initFrame: function() {
		this.createFrame();
	},

	applyConfig: function() {
		Ext.dd.DDProxy.superclass.applyConfig.call(this);

		this.resizeFrame = (this.config.resizeFrame !== false);
		this.centerFrame = (this.config.centerFrame);
		this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
	},

	showFrame: function(iPageX, iPageY) {
		var el = this.getEl();
		var dragEl = this.getDragEl();
		var s = dragEl.style;

		this._resizeProxy();

		if (this.centerFrame) {
			this.setDelta(Math.round(parseInt(s.width, 10) / 2), Math.round(parseInt(s.height, 10) / 2));
		}

		this.setDragElPos(iPageX, iPageY);

		Ext.fly(dragEl).show();
	},

	_resizeProxy: function() {
		if (this.resizeFrame) {
			var el = this.getEl();
			Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
		}
	},

	b4MouseDown: function(e) {
		var x = e.getPageX();
		var y = e.getPageY();
		this.autoOffset(x, y);
		this.setDragElPos(x, y);
	},

	b4StartDrag: function(x, y) {

		this.showFrame(x, y);
	},

	b4EndDrag: function(e) {
		Ext.fly(this.getDragEl()).hide();
	},

	endDrag: function(e) {

		var lel = this.getEl();
		var del = this.getDragEl();

		del.style.visibility = "";

		this.beforeMove();

		lel.style.visibility = "hidden";
		Ext.dd.DDM.moveToEl(lel, del);
		del.style.visibility = "hidden";
		lel.style.visibility = "";

		this.afterDrag();
	},

	beforeMove: function() {
		},

	afterDrag: function() {
		},

	toString: function() {
		return ("DDProxy " + this.id);
	}

});

Ext.dd.DDTarget = function(id, sGroup, config) {
	if (id) {
		this.initTarget(id, sGroup, config);
	}
};

Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
	toString: function() {
		return ("DDTarget " + this.id);
	}
});

Ext.dd.DragTracker = function(config) {
	Ext.apply(this, config);
	this.addEvents('mousedown', 'mouseup', 'mousemove', 'dragstart', 'dragend', 'drag');

	this.dragRegion = new Ext.lib.Region(0, 0, 0, 0);

	if (this.el) {
		this.initEl(this.el);
	}
}

Ext.extend(Ext.dd.DragTracker, Ext.util.Observable, {
	active: false,
	tolerance: 5,
	autoStart: false,

	initEl: function(el) {
		this.el = Ext.get(el);
		el.on('mousedown', this.onMouseDown, this, this.delegate ? {
			delegate: this.delegate
		}: undefined);
	},

	destroy: function() {
		this.el.un('mousedown', this.onMouseDown, this);
	},

	onMouseDown: function(e, target) {
		if (this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false) {
			this.startXY = this.lastXY = e.getXY();
			this.dragTarget = this.delegate ? target: this.el.dom;
			e.preventDefault();
			var doc = Ext.getDoc();
			doc.on('mouseup', this.onMouseUp, this);
			doc.on('mousemove', this.onMouseMove, this);
			doc.on('selectstart', this.stopSelect, this);
			if (this.autoStart) {
				this.timer = this.triggerStart.defer(this.autoStart === true ? 1000: this.autoStart, this);
			}
		}
	},

	onMouseMove: function(e, target) {
		e.preventDefault();
		var xy = e.getXY(),
		s = this.startXY;
		this.lastXY = xy;
		if (!this.active) {
			if (Math.abs(s[0] - xy[0]) > this.tolerance || Math.abs(s[1] - xy[1]) > this.tolerance) {
				this.triggerStart();
			} else {
				return;
			}
		}
		this.fireEvent('mousemove', this, e);
		this.onDrag(e);
		this.fireEvent('drag', this, e);
	},

	onMouseUp: function(e) {
		var doc = Ext.getDoc();
		doc.un('mousemove', this.onMouseMove, this);
		doc.un('mouseup', this.onMouseUp, this);
		doc.un('selectstart', this.stopSelect, this);
		e.preventDefault();
		this.clearStart();
		this.active = false;
		delete this.elRegion;
		this.fireEvent('mouseup', this, e);
		this.onEnd(e);
		this.fireEvent('dragend', this, e);
	},

	triggerStart: function(isTimer) {
		this.clearStart();
		this.active = true;
		this.onStart(this.startXY);
		this.fireEvent('dragstart', this, this.startXY);
	},

	clearStart: function() {
		if (this.timer) {
			clearTimeout(this.timer);
			delete this.timer;
		}
	},

	stopSelect: function(e) {
		e.stopEvent();
		return false;
	},

	onBeforeStart: function(e) {
		},

	onStart: function(xy) {
		},

	onDrag: function(e) {
		},

	onEnd: function(e) {
		},

	getDragTarget: function() {
		return this.dragTarget;
	},

	getDragCt: function() {
		return this.el;
	},

	getXY: function(constrain) {
		return constrain ? this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
	},

	getOffset: function(constrain) {
		var xy = this.getXY(constrain);
		var s = this.startXY;
		return [s[0] - xy[0], s[1] - xy[1]];
	},

	constrainModes: {
		'point': function(xy) {

			if (!this.elRegion) {
				this.elRegion = this.getDragCt().getRegion();
			}

			var dr = this.dragRegion;

			dr.left = xy[0];
			dr.top = xy[1];
			dr.right = xy[0];
			dr.bottom = xy[1];

			dr.constrainTo(this.elRegion);

			return [dr.left, dr.top];
		}
	}
});

Ext.dd.ScrollManager = function() {
	var ddm = Ext.dd.DragDropMgr;
	var els = {};
	var dragEl = null;
	var proc = {};

	var onStop = function(e) {
		dragEl = null;
		clearProc();
	};

	var triggerRefresh = function() {
		if (ddm.dragCurrent) {
			ddm.refreshCache(ddm.dragCurrent.groups);
		}
	};

	var doScroll = function() {
		if (ddm.dragCurrent) {
			var dds = Ext.dd.ScrollManager;
			var inc = proc.el.ddScrollConfig ? proc.el.ddScrollConfig.increment: dds.increment;
			if (!dds.animate) {
				if (proc.el.scroll(proc.dir, inc)) {
					triggerRefresh();
				}
			} else {
				proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
			}
		}
	};

	var clearProc = function() {
		if (proc.id) {
			clearInterval(proc.id);
		}
		proc.id = 0;
		proc.el = null;
		proc.dir = "";
	};

	var startProc = function(el, dir) {
		clearProc();
		proc.el = el;
		proc.dir = dir;
		var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? el.ddScrollConfig.frequency: Ext.dd.ScrollManager.frequency;
		proc.id = setInterval(doScroll, freq);
	};

	var onFire = function(e, isDrop) {
		if (isDrop || !ddm.dragCurrent) {
			return;
		}
		var dds = Ext.dd.ScrollManager;
		if (!dragEl || dragEl != ddm.dragCurrent) {
			dragEl = ddm.dragCurrent;

			dds.refreshCache();
		}

		var xy = Ext.lib.Event.getXY(e);
		var pt = new Ext.lib.Point(xy[0], xy[1]);
		for (var id in els) {
			var el = els[id],
			r = el._region;
			var c = el.ddScrollConfig ? el.ddScrollConfig: dds;
			if (r && r.contains(pt) && el.isScrollable()) {
				if (r.bottom - pt.y <= c.vthresh) {
					if (proc.el != el) {
						startProc(el, "down");
					}
					return;
				} else if (r.right - pt.x <= c.hthresh) {
					if (proc.el != el) {
						startProc(el, "left");
					}
					return;
				} else if (pt.y - r.top <= c.vthresh) {
					if (proc.el != el) {
						startProc(el, "up");
					}
					return;
				} else if (pt.x - r.left <= c.hthresh) {
					if (proc.el != el) {
						startProc(el, "right");
					}
					return;
				}
			}
		}
		clearProc();
	};

	ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
	ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);

	return {

		register: function(el) {
			if (Ext.isArray(el)) {
				for (var i = 0, len = el.length; i < len; i++) {
					this.register(el[i]);
				}
			} else {
				el = Ext.get(el);
				els[el.id] = el;
			}
		},

		unregister: function(el) {
			if (Ext.isArray(el)) {
				for (var i = 0, len = el.length; i < len; i++) {
					this.unregister(el[i]);
				}
			} else {
				el = Ext.get(el);
				delete els[el.id];
			}
		},

		vthresh: 25,

		hthresh: 25,

		increment: 100,

		frequency: 500,

		animate: true,

		animDuration: .4,

		refreshCache: function() {
			for (var id in els) {
				if (typeof els[id] == 'object') {
					els[id]._region = els[id].getRegion();
				}
			}
		}
	};
} ();

Ext.dd.Registry = function() {
	var elements = {};
	var handles = {};
	var autoIdSeed = 0;

	var getId = function(el, autogen) {
		if (typeof el == "string") {
			return el;
		}
		var id = el.id;
		if (!id && autogen !== false) {
			id = "extdd-" + (++autoIdSeed);
			el.id = id;
		}
		return id;
	};

	return {

		register: function(el, data) {
			data = data || {};
			if (typeof el == "string") {
				el = document.getElementById(el);
			}
			data.ddel = el;
			elements[getId(el)] = data;
			if (data.isHandle !== false) {
				handles[data.ddel.id] = data;
			}
			if (data.handles) {
				var hs = data.handles;
				for (var i = 0, len = hs.length; i < len; i++) {
					handles[getId(hs[i])] = data;
				}
			}
		},

		unregister: function(el) {
			var id = getId(el, false);
			var data = elements[id];
			if (data) {
				delete elements[id];
				if (data.handles) {
					var hs = data.handles;
					for (var i = 0, len = hs.length; i < len; i++) {
						delete handles[getId(hs[i], false)];
					}
				}
			}
		},

		getHandle: function(id) {
			if (typeof id != "string") {
				id = id.id;
			}
			return handles[id];
		},

		getHandleFromEvent: function(e) {
			var t = Ext.lib.Event.getTarget(e);
			return t ? handles[t.id] : null;
		},

		getTarget: function(id) {
			if (typeof id != "string") {
				id = id.id;
			}
			return elements[id];
		},

		getTargetFromEvent: function(e) {
			var t = Ext.lib.Event.getTarget(e);
			return t ? elements[t.id] || handles[t.id] : null;
		}
	};
} ();

Ext.dd.StatusProxy = function(config) {
	Ext.apply(this, config);
	this.id = this.id || Ext.id();
	this.el = new Ext.Layer({
		dh: {
			id: this.id,
			tag: "div",
			cls: "x-dd-drag-proxy " + this.dropNotAllowed,
			children: [{
				tag: "div",
				cls: "x-dd-drop-icon"
			},
			{
				tag: "div",
				cls: "x-dd-drag-ghost"
			}]
		},
		shadow: !config || config.shadow !== false
	});
	this.ghost = Ext.get(this.el.dom.childNodes[1]);
	this.dropStatus = this.dropNotAllowed;
};

Ext.dd.StatusProxy.prototype = {

	dropAllowed: "x-dd-drop-ok",

	dropNotAllowed: "x-dd-drop-nodrop",

	setStatus: function(cssClass) {
		cssClass = cssClass || this.dropNotAllowed;
		if (this.dropStatus != cssClass) {
			this.el.replaceClass(this.dropStatus, cssClass);
			this.dropStatus = cssClass;
		}
	},

	reset: function(clearGhost) {
		this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
		this.dropStatus = this.dropNotAllowed;
		if (clearGhost) {
			this.ghost.update("");
		}
	},

	update: function(html) {
		if (typeof html == "string") {
			this.ghost.update(html);
		} else {
			this.ghost.update("");
			html.style.margin = "0";
			this.ghost.dom.appendChild(html);
		}
		var el = this.ghost.dom.firstChild;
		if (el) {
			Ext.fly(el).setStyle(Ext.isIE ? 'styleFloat': 'cssFloat', 'none');
		}
	},

	getEl: function() {
		return this.el;
	},

	getGhost: function() {
		return this.ghost;
	},

	hide: function(clear) {
		this.el.hide();
		if (clear) {
			this.reset(true);
		}
	},

	stop: function() {
		if (this.anim && this.anim.isAnimated && this.anim.isAnimated()) {
			this.anim.stop();
		}
	},

	show: function() {
		this.el.show();
	},

	sync: function() {
		this.el.sync();
	},

	repair: function(xy, callback, scope) {
		this.callback = callback;
		this.scope = scope;
		if (xy && this.animRepair !== false) {
			this.el.addClass("x-dd-drag-repair");
			this.el.hideUnders(true);
			this.anim = this.el.shift({
				duration: this.repairDuration || .5,
				easing: 'easeOut',
				xy: xy,
				stopFx: true,
				callback: this.afterRepair,
				scope: this
			});
		} else {
			this.afterRepair();
		}
	},

	afterRepair: function() {
		this.hide(true);
		if (typeof this.callback == "function") {
			this.callback.call(this.scope || this);
		}
		this.callback = null;
		this.scope = null;
	}
};

Ext.dd.DragSource = function(el, config) {
	this.el = Ext.get(el);
	if (!this.dragData) {
		this.dragData = {};
	}

	Ext.apply(this, config);

	if (!this.proxy) {
		this.proxy = new Ext.dd.StatusProxy();
	}
	Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, {
		dragElId: this.proxy.id,
		resizeFrame: false,
		isTarget: false,
		scroll: this.scroll === true
	});

	this.dragging = false;
};

Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {

	dropAllowed: "x-dd-drop-ok",

	dropNotAllowed: "x-dd-drop-nodrop",

	getDragData: function(e) {
		return this.dragData;
	},

	onDragEnter: function(e, id) {
		var target = Ext.dd.DragDropMgr.getDDById(id);
		this.cachedTarget = target;
		if (this.beforeDragEnter(target, e, id) !== false) {
			if (target.isNotifyTarget) {
				var status = target.notifyEnter(this, e, this.dragData);
				this.proxy.setStatus(status);
			} else {
				this.proxy.setStatus(this.dropAllowed);
			}

			if (this.afterDragEnter) {

				this.afterDragEnter(target, e, id);
			}
		}
	},

	beforeDragEnter: function(target, e, id) {
		return true;
	},

	alignElWithMouse: function() {
		Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
		this.proxy.sync();
	},

	onDragOver: function(e, id) {
		var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
		if (this.beforeDragOver(target, e, id) !== false) {
			if (target.isNotifyTarget) {
				var status = target.notifyOver(this, e, this.dragData);
				this.proxy.setStatus(status);
			}

			if (this.afterDragOver) {

				this.afterDragOver(target, e, id);
			}
		}
	},

	beforeDragOver: function(target, e, id) {
		return true;
	},

	onDragOut: function(e, id) {
		var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
		if (this.beforeDragOut(target, e, id) !== false) {
			if (target.isNotifyTarget) {
				target.notifyOut(this, e, this.dragData);
			}
			this.proxy.reset();
			if (this.afterDragOut) {

				this.afterDragOut(target, e, id);
			}
		}
		this.cachedTarget = null;
	},

	beforeDragOut: function(target, e, id) {
		return true;
	},

	onDragDrop: function(e, id) {
		var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
		if (this.beforeDragDrop(target, e, id) !== false) {
			if (target.isNotifyTarget) {
				if (target.notifyDrop(this, e, this.dragData)) {
					this.onValidDrop(target, e, id);
				} else {
					this.onInvalidDrop(target, e, id);
				}
			} else {
				this.onValidDrop(target, e, id);
			}

			if (this.afterDragDrop) {

				this.afterDragDrop(target, e, id);
			}
		}
		delete this.cachedTarget;
	},

	beforeDragDrop: function(target, e, id) {
		return true;
	},

	onValidDrop: function(target, e, id) {
		this.hideProxy();
		if (this.afterValidDrop) {

			this.afterValidDrop(target, e, id);
		}
	},

	getRepairXY: function(e, data) {
		return this.el.getXY();
	},

	onInvalidDrop: function(target, e, id) {
		this.beforeInvalidDrop(target, e, id);
		if (this.cachedTarget) {
			if (this.cachedTarget.isNotifyTarget) {
				this.cachedTarget.notifyOut(this, e, this.dragData);
			}
			this.cacheTarget = null;
		}
		this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);

		if (this.afterInvalidDrop) {

			this.afterInvalidDrop(e, id);
		}
	},

	afterRepair: function() {
		if (Ext.enableFx) {
			this.el.highlight(this.hlColor || "c3daf9");
		}
		this.dragging = false;
	},

	beforeInvalidDrop: function(target, e, id) {
		return true;
	},

	handleMouseDown: function(e) {
		if (this.dragging) {
			return;
		}
		var data = this.getDragData(e);
		if (data && this.onBeforeDrag(data, e) !== false) {
			this.dragData = data;
			this.proxy.stop();
			Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
		}
	},

	onBeforeDrag: function(data, e) {
		return true;
	},

	onStartDrag: Ext.emptyFn,

	startDrag: function(x, y) {
		this.proxy.reset();
		this.dragging = true;
		this.proxy.update("");
		this.onInitDrag(x, y);
		this.proxy.show();
	},

	onInitDrag: function(x, y) {
		var clone = this.el.dom.cloneNode(true);
		clone.id = Ext.id();
		this.proxy.update(clone);
		this.onStartDrag(x, y);
		return true;
	},

	getProxy: function() {
		return this.proxy;
	},

	hideProxy: function() {
		this.proxy.hide();
		this.proxy.reset(true);
		this.dragging = false;
	},

	triggerCacheRefresh: function() {
		Ext.dd.DDM.refreshCache(this.groups);
	},

	b4EndDrag: function(e) {},

	endDrag: function(e) {
		this.onEndDrag(this.dragData, e);
	},

	onEndDrag: function(data, e) {},

	autoOffset: function(x, y) {
		this.setDelta( - 12, -20);
	}
});

Ext.dd.DropTarget = function(el, config) {
	this.el = Ext.get(el);

	Ext.apply(this, config);

	if (this.containerScroll) {
		Ext.dd.ScrollManager.register(this.el);
	}

	Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, {
		isTarget: true
	});

};

Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {

	dropAllowed: "x-dd-drop-ok",

	dropNotAllowed: "x-dd-drop-nodrop",

	isTarget: true,

	isNotifyTarget: true,

	notifyEnter: function(dd, e, data) {
		if (this.overClass) {
			this.el.addClass(this.overClass);
		}
		return this.dropAllowed;
	},

	notifyOver: function(dd, e, data) {
		return this.dropAllowed;
	},

	notifyOut: function(dd, e, data) {
		if (this.overClass) {
			this.el.removeClass(this.overClass);
		}
	},

	notifyDrop: function(dd, e, data) {
		return false;
	}
});

Ext.dd.DragZone = function(el, config) {
	Ext.dd.DragZone.superclass.constructor.call(this, el, config);
	if (this.containerScroll) {
		Ext.dd.ScrollManager.register(this.el);
	}
};

Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {

	getDragData: function(e) {
		return Ext.dd.Registry.getHandleFromEvent(e);
	},

	onInitDrag: function(x, y) {
		this.proxy.update(this.dragData.ddel.cloneNode(true));
		this.onStartDrag(x, y);
		return true;
	},

	afterRepair: function() {
		if (Ext.enableFx) {
			Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
		}
		this.dragging = false;
	},

	getRepairXY: function(e) {
		return Ext.Element.fly(this.dragData.ddel).getXY();
	}
});

Ext.dd.DropZone = function(el, config) {
	Ext.dd.DropZone.superclass.constructor.call(this, el, config);
};

Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {

	getTargetFromEvent: function(e) {
		return Ext.dd.Registry.getTargetFromEvent(e);
	},

	onNodeEnter: function(n, dd, e, data) {
		},

	onNodeOver: function(n, dd, e, data) {
		return this.dropAllowed;
	},

	onNodeOut: function(n, dd, e, data) {
		},

	onNodeDrop: function(n, dd, e, data) {
		return false;
	},

	onContainerOver: function(dd, e, data) {
		return this.dropNotAllowed;
	},

	onContainerDrop: function(dd, e, data) {
		return false;
	},

	notifyEnter: function(dd, e, data) {
		return this.dropNotAllowed;
	},

	notifyOver: function(dd, e, data) {
		var n = this.getTargetFromEvent(e);
		if (!n) {
			if (this.lastOverNode) {
				this.onNodeOut(this.lastOverNode, dd, e, data);
				this.lastOverNode = null;
			}
			return this.onContainerOver(dd, e, data);
		}
		if (this.lastOverNode != n) {
			if (this.lastOverNode) {
				this.onNodeOut(this.lastOverNode, dd, e, data);
			}
			this.onNodeEnter(n, dd, e, data);
			this.lastOverNode = n;
		}
		return this.onNodeOver(n, dd, e, data);
	},

	notifyOut: function(dd, e, data) {
		if (this.lastOverNode) {
			this.onNodeOut(this.lastOverNode, dd, e, data);
			this.lastOverNode = null;
		}
	},

	notifyDrop: function(dd, e, data) {
		if (this.lastOverNode) {
			this.onNodeOut(this.lastOverNode, dd, e, data);
			this.lastOverNode = null;
		}
		var n = this.getTargetFromEvent(e);
		return n ? this.onNodeDrop(n, dd, e, data) : this.onContainerDrop(dd, e, data);
	},

	triggerCacheRefresh: function() {
		Ext.dd.DDM.refreshCache(this.groups);
	}
});

Ext.data.SortTypes = {

	none: function(s) {
		return s;
	},

	stripTagsRE: /<\/?[^>]+>/gi,

	asText: function(s) {
		return String(s).replace(this.stripTagsRE, "");
	},

	asUCText: function(s) {
		return String(s).toUpperCase().replace(this.stripTagsRE, "");
	},

	asUCString: function(s) {
		return String(s).toUpperCase();
	},

	asDate: function(s) {
		if (!s) {
			return 0;
		}
		if (Ext.isDate(s)) {
			return s.getTime();
		}
		return Date.parse(String(s));
	},

	asFloat: function(s) {
		var val = parseFloat(String(s).replace(/,/g, ""));
		if (isNaN(val)) val = 0;
		return val;
	},

	asInt: function(s) {
		var val = parseInt(String(s).replace(/,/g, ""));
		if (isNaN(val)) val = 0;
		return val;
	}
};

Ext.data.Record = function(data, id) {
	this.id = (id || id === 0) ? id: ++Ext.data.Record.AUTO_ID;
	this.data = data;
};

Ext.data.Record.create = function(o) {
	var f = Ext.extend(Ext.data.Record, {});
	var p = f.prototype;
	p.fields = new Ext.util.MixedCollection(false,
	function(field) {
		return field.name;
	});
	for (var i = 0, len = o.length; i < len; i++) {
		p.fields.add(new Ext.data.Field(o[i]));
	}
	f.getField = function(name) {
		return p.fields.get(name);
	};
	return f;
};

Ext.data.Record.AUTO_ID = 1000;
Ext.data.Record.EDIT = 'edit';
Ext.data.Record.REJECT = 'reject';
Ext.data.Record.COMMIT = 'commit';

Ext.data.Record.prototype = {

	dirty: false,
	editing: false,
	error: null,

	modified: null,

	join: function(store) {
		this.store = store;
	},

	set: function(name, value) {
		if (String(this.data[name]) == String(value)) {
			return;
		}
		this.dirty = true;
		if (!this.modified) {
			this.modified = {};
		}
		if (typeof this.modified[name] == 'undefined') {
			this.modified[name] = this.data[name];
		}
		this.data[name] = value;
		if (!this.editing && this.store) {
			this.store.afterEdit(this);
		}
	},

	get: function(name) {
		return this.data[name];
	},

	beginEdit: function() {
		this.editing = true;
		this.modified = {};
	},

	cancelEdit: function() {
		this.editing = false;
		delete this.modified;
	},

	endEdit: function() {
		this.editing = false;
		if (this.dirty && this.store) {
			this.store.afterEdit(this);
		}
	},

	reject: function(silent) {
		var m = this.modified;
		for (var n in m) {
			if (typeof m[n] != "function") {
				this.data[n] = m[n];
			}
		}
		this.dirty = false;
		delete this.modified;
		this.editing = false;
		if (this.store && silent !== true) {
			this.store.afterReject(this);
		}
	},

	commit: function(silent) {
		this.dirty = false;
		delete this.modified;
		this.editing = false;
		if (this.store && silent !== true) {
			this.store.afterCommit(this);
		}
	},

	getChanges: function() {
		var m = this.modified,
		cs = {};
		for (var n in m) {
			if (m.hasOwnProperty(n)) {
				cs[n] = this.data[n];
			}
		}
		return cs;
	},

	hasError: function() {
		return this.error != null;
	},

	clearError: function() {
		this.error = null;
	},

	copy: function(newId) {
		return new this.constructor(Ext.apply({},
		this.data), newId || this.id);
	},

	isModified: function(fieldName) {
		return !! (this.modified && this.modified.hasOwnProperty(fieldName));
	}
};

Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {

	register: function() {
		for (var i = 0, s; s = arguments[i]; i++) {
			this.add(s);
		}
	},

	unregister: function() {
		for (var i = 0, s; s = arguments[i]; i++) {
			this.remove(this.lookup(s));
		}
	},

	lookup: function(id) {
		return typeof id == "object" ? id: this.get(id);
	},

	getKey: function(o) {
		return o.storeId || o.id;
	}
});

Ext.data.Store = function(config) {
	this.data = new Ext.util.MixedCollection(false);
	this.data.getKey = function(o) {
		return o.id;
	};

	this.baseParams = {};
	this.paramNames = {
		"start": "start",
		"limit": "limit",
		"sort": "sort",
		"dir": "dir"
	};

	if (config && config.data) {
		this.inlineData = config.data;
		delete config.data;
	}

	Ext.apply(this, config);

	if (this.url && !this.proxy) {
		this.proxy = new Ext.data.HttpProxy({
			url: this.url
		});
	}

	if (this.reader) {
		if (!this.recordType) {
			this.recordType = this.reader.recordType;
		}
		if (this.reader.onMetaChange) {
			this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
		}
	}

	if (this.recordType) {
		this.fields = this.recordType.prototype.fields;
	}
	this.modified = [];

	this.addEvents(
	'datachanged',
	'metachange',
	'add',
	'remove',
	'update',
	'clear',
	'beforeload',
	'load',
	'loadexception');

	if (this.proxy) {
		this.relayEvents(this.proxy, ["loadexception"]);
	}

	this.sortToggle = {};
	if (this.sortInfo) {
		this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
	}

	Ext.data.Store.superclass.constructor.call(this);

	if (this.storeId || this.id) {
		Ext.StoreMgr.register(this);
	}
	if (this.inlineData) {
		this.loadData(this.inlineData);
		delete this.inlineData;
	} else if (this.autoLoad) {
		this.load.defer(10, this, [typeof this.autoLoad == 'object' ? this.autoLoad: undefined]);
	}
};
Ext.extend(Ext.data.Store, Ext.util.Observable, {

	remoteSort: false,

	pruneModifiedRecords: false,

	lastOptions: null,

	destroy: function() {
		if (this.id) {
			Ext.StoreMgr.unregister(this);
		}
		this.data = null;
		this.purgeListeners();
	},

	add: function(records) {
		records = [].concat(records);
		if (records.length < 1) {
			return;
		}
		for (var i = 0, len = records.length; i < len; i++) {
			records[i].join(this);
		}
		var index = this.data.length;
		this.data.addAll(records);
		if (this.snapshot) {
			this.snapshot.addAll(records);
		}
		this.fireEvent("add", this, records, index);
	},

	addSorted: function(record) {
		var index = this.findInsertIndex(record);
		this.insert(index, record);
	},

	remove: function(record) {
		var index = this.data.indexOf(record);
		this.data.removeAt(index);
		if (this.pruneModifiedRecords) {
			this.modified.remove(record);
		}
		if (this.snapshot) {
			this.snapshot.remove(record);
		}
		this.fireEvent("remove", this, record, index);
	},

	removeAll: function() {
		this.data.clear();
		if (this.snapshot) {
			this.snapshot.clear();
		}
		if (this.pruneModifiedRecords) {
			this.modified = [];
		}
		this.fireEvent("clear", this);
	},

	insert: function(index, records) {
		records = [].concat(records);
		for (var i = 0, len = records.length; i < len; i++) {
			this.data.insert(index, records[i]);
			records[i].join(this);
		}
		this.fireEvent("add", this, records, index);
	},

	indexOf: function(record) {
		return this.data.indexOf(record);
	},

	indexOfId: function(id) {
		return this.data.indexOfKey(id);
	},

	getById: function(id) {
		return this.data.key(id);
	},

	getAt: function(index) {
		return this.data.itemAt(index);
	},

	getRange: function(start, end) {
		return this.data.getRange(start, end);
	},

	storeOptions: function(o) {
		o = Ext.apply({},
		o);
		delete o.callback;
		delete o.scope;
		this.lastOptions = o;
	},

	load: function(options) {
		options = options || {};
		if (this.fireEvent("beforeload", this, options) !== false) {
			this.storeOptions(options);
			var p = Ext.apply(options.params || {},
			this.baseParams);
			if (this.sortInfo && this.remoteSort) {
				var pn = this.paramNames;
				p[pn["sort"]] = this.sortInfo.field;
				p[pn["dir"]] = this.sortInfo.direction;
			}
			this.proxy.load(p, this.reader, this.loadRecords, this, options);
			return true;
		} else {
			return false;
		}
	},

	reload: function(options) {
		this.load(Ext.applyIf(options || {},
		this.lastOptions));
	},

	loadRecords: function(o, options, success) {
		if (!o || success === false) {
			if (success !== false) {
				this.fireEvent("load", this, [], options);
			}
			if (options.callback) {
				options.callback.call(options.scope || this, [], options, false);
			}
			return;
		}
		var r = o.records,
		t = o.totalRecords || r.length;
		if (!options || options.add !== true) {
			if (this.pruneModifiedRecords) {
				this.modified = [];
			}
			for (var i = 0, len = r.length; i < len; i++) {
				r[i].join(this);
			}
			if (this.snapshot) {
				this.data = this.snapshot;
				delete this.snapshot;
			}
			this.data.clear();
			this.data.addAll(r);
			this.totalLength = t;
			this.applySort();
			this.fireEvent("datachanged", this);
		} else {
			this.totalLength = Math.max(t, this.data.length + r.length);
			this.add(r);
		}
		this.fireEvent("load", this, r, options);
		if (options.callback) {
			options.callback.call(options.scope || this, r, options, true);
		}
	},

	loadData: function(o, append) {
		var r = this.reader.readRecords(o);
		this.loadRecords(r, {
			add: append
		},
		true);
	},

	getCount: function() {
		return this.data.length || 0;
	},

	getTotalCount: function() {
		return this.totalLength || 0;
	},

	getSortState: function() {
		return this.sortInfo;
	},

	applySort: function() {
		if (this.sortInfo && !this.remoteSort) {
			var s = this.sortInfo,
			f = s.field;
			this.sortData(f, s.direction);
		}
	},

	sortData: function(f, direction) {
		direction = direction || 'ASC';
		var st = this.fields.get(f).sortType;
		var fn = function(r1, r2) {
			var v1 = st(r1.data[f]),
			v2 = st(r2.data[f]);
			return v1 > v2 ? 1: (v1 < v2 ? -1: 0);
		};
		this.data.sort(direction, fn);
		if (this.snapshot && this.snapshot != this.data) {
			this.snapshot.sort(direction, fn);
		}
	},

	setDefaultSort: function(field, dir) {
		dir = dir ? dir.toUpperCase() : "ASC";
		this.sortInfo = {
			field: field,
			direction: dir
		};
		this.sortToggle[field] = dir;
	},

	sort: function(fieldName, dir) {
		var f = this.fields.get(fieldName);
		if (!f) {
			return false;
		}
		if (!dir) {
			if (this.sortInfo && this.sortInfo.field == f.name) {
				dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
			} else {
				dir = f.sortDir;
			}
		}
		var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
		var si = (this.sortInfo) ? this.sortInfo: null;

		this.sortToggle[f.name] = dir;
		this.sortInfo = {
			field: f.name,
			direction: dir
		};
		if (!this.remoteSort) {
			this.applySort();
			this.fireEvent("datachanged", this);
		} else {
			if (!this.load(this.lastOptions)) {
				if (st) {
					this.sortToggle[f.name] = st;
				}
				if (si) {
					this.sortInfo = si;
				}
			}
		}
	},

	each: function(fn, scope) {
		this.data.each(fn, scope);
	},

	getModifiedRecords: function() {
		return this.modified;
	},

	createFilterFn: function(property, value, anyMatch, caseSensitive) {
		if (Ext.isEmpty(value, false)) {
			return false;
		}
		value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
		return function(r) {
			return value.test(r.data[property]);
		};
	},

	sum: function(property, start, end) {
		var rs = this.data.items,
		v = 0;
		start = start || 0;
		end = (end || end === 0) ? end: rs.length - 1;

		for (var i = start; i <= end; i++) {
			v += (rs[i].data[property] || 0);
		}
		return v;
	},

	filter: function(property, value, anyMatch, caseSensitive) {
		var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
		return fn ? this.filterBy(fn) : this.clearFilter();
	},

	filterBy: function(fn, scope) {
		this.snapshot = this.snapshot || this.data;
		this.data = this.queryBy(fn, scope || this);
		this.fireEvent("datachanged", this);
	},

	query: function(property, value, anyMatch, caseSensitive) {
		var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
		return fn ? this.queryBy(fn) : this.data.clone();
	},

	queryBy: function(fn, scope) {
		var data = this.snapshot || this.data;
		return data.filterBy(fn, scope || this);
	},

	find: function(property, value, start, anyMatch, caseSensitive) {
		var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
		return fn ? this.data.findIndexBy(fn, null, start) : -1;
	},

	findBy: function(fn, scope, start) {
		return this.data.findIndexBy(fn, scope, start);
	},

	collect: function(dataIndex, allowNull, bypassFilter) {
		var d = (bypassFilter === true && this.snapshot) ? this.snapshot.items: this.data.items;
		var v,
		sv,
		r = [],
		l = {};
		for (var i = 0, len = d.length; i < len; i++) {
			v = d[i].data[dataIndex];
			sv = String(v);
			if ((allowNull || !Ext.isEmpty(v)) && !l[sv]) {
				l[sv] = true;
				r[r.length] = v;
			}
		}
		return r;
	},

	clearFilter: function(suppressEvent) {
		if (this.isFiltered()) {
			this.data = this.snapshot;
			delete this.snapshot;
			if (suppressEvent !== true) {
				this.fireEvent("datachanged", this);
			}
		}
	},

	isFiltered: function() {
		return this.snapshot && this.snapshot != this.data;
	},

	afterEdit: function(record) {
		if (this.modified.indexOf(record) == -1) {
			this.modified.push(record);
		}
		this.fireEvent("update", this, record, Ext.data.Record.EDIT);
	},

	afterReject: function(record) {
		this.modified.remove(record);
		this.fireEvent("update", this, record, Ext.data.Record.REJECT);
	},

	afterCommit: function(record) {
		this.modified.remove(record);
		this.fireEvent("update", this, record, Ext.data.Record.COMMIT);
	},

	commitChanges: function() {
		var m = this.modified.slice(0);
		this.modified = [];
		for (var i = 0, len = m.length; i < len; i++) {
			m[i].commit();
		}
	},

	rejectChanges: function() {
		var m = this.modified.slice(0);
		this.modified = [];
		for (var i = 0, len = m.length; i < len; i++) {
			m[i].reject();
		}
	},

	onMetaChange: function(meta, rtype, o) {
		this.recordType = rtype;
		this.fields = rtype.prototype.fields;
		delete this.snapshot;
		this.sortInfo = meta.sortInfo;
		this.modified = [];
		this.fireEvent('metachange', this, this.reader.meta);
	},

	findInsertIndex: function(record) {
		this.suspendEvents();
		var data = this.data.clone();
		this.data.add(record);
		this.applySort();
		var index = this.data.indexOf(record);
		this.data = data;
		this.resumeEvents();
		return index;
	}
});

Ext.data.SimpleStore = function(config) {
	Ext.data.SimpleStore.superclass.constructor.call(this, Ext.apply(config, {
		reader: new Ext.data.ArrayReader({
			id: config.id
		},
		Ext.data.Record.create(config.fields))
	}));
};
Ext.extend(Ext.data.SimpleStore, Ext.data.Store, {
	loadData: function(data, append) {
		if (this.expandData === true) {
			var r = [];
			for (var i = 0, len = data.length; i < len; i++) {
				r[r.length] = [data[i]];
			}
			data = r;
		}
		Ext.data.SimpleStore.superclass.loadData.call(this, data, append);
	}
});

Ext.data.JsonStore = function(c) {

	Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(c, {
		proxy: c.proxy || (!c.data ? new Ext.data.HttpProxy({
			url: c.url
		}) : undefined),
		reader: new Ext.data.JsonReader(c, c.fields)
	}));
};
Ext.extend(Ext.data.JsonStore, Ext.data.Store);

Ext.data.Field = function(config) {
	if (typeof config == "string") {
		config = {
			name: config
		};
	}
	Ext.apply(this, config);

	if (!this.type) {
		this.type = "auto";
	}

	var st = Ext.data.SortTypes;

	if (typeof this.sortType == "string") {
		this.sortType = st[this.sortType];
	}

	if (!this.sortType) {
		switch (this.type) {
		case "string":
			this.sortType = st.asUCString;
			break;
		case "date":
			this.sortType = st.asDate;
			break;
		default:
			this.sortType = st.none;
		}
	}

	var stripRe = /[\$,%]/g;

	if (!this.convert) {
		var cv,
		dateFormat = this.dateFormat;
		switch (this.type) {
		case "":
		case "auto":
		case undefined:
			cv = function(v) {
				return v;
			};
			break;
		case "string":
			cv = function(v) {
				return (v === undefined || v === null) ? '': String(v);
			};
			break;
		case "int":
			cv = function(v) {
				return v !== undefined && v !== null && v !== '' ? parseInt(String(v).replace(stripRe, ""), 10) : '';
			};
			break;
		case "float":
			cv = function(v) {
				return v !== undefined && v !== null && v !== '' ? parseFloat(String(v).replace(stripRe, ""), 10) : '';
			};
			break;
		case "bool":
		case "boolean":
			cv = function(v) {
				return v === true || v === "true" || v == 1;
			};
			break;
		case "date":
			cv = function(v) {
				if (!v) {
					return '';
				}
				if (Ext.isDate(v)) {
					return v;
				}
				if (dateFormat) {
					if (dateFormat == "timestamp") {
						return new Date(v * 1000);
					}
					if (dateFormat == "time") {
						return new Date(parseInt(v, 10));
					}
					return Date.parseDate(v, dateFormat);
				}
				var parsed = Date.parse(v);
				return parsed ? new Date(parsed) : null;
			};
			break;

		}
		this.convert = cv;
	}
};

Ext.data.Field.prototype = {
	dateFormat: null,
	defaultValue: "",
	mapping: null,
	sortType: null,
	sortDir: "ASC"
};

Ext.data.DataReader = function(meta, recordType) {

	this.meta = meta;
	this.recordType = Ext.isArray(recordType) ? Ext.data.Record.create(recordType) : recordType;
};

Ext.data.DataReader.prototype = {
	};

Ext.data.DataProxy = function() {
	this.addEvents(
	'beforeload',
	'load');
	Ext.data.DataProxy.superclass.constructor.call(this);
};

Ext.extend(Ext.data.DataProxy, Ext.util.Observable);

Ext.data.MemoryProxy = function(data) {
	Ext.data.MemoryProxy.superclass.constructor.call(this);
	this.data = data;
};

Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {

	load: function(params, reader, callback, scope, arg) {
		params = params || {};
		var result;
		try {
			result = reader.readRecords(this.data);
		} catch(e) {
			this.fireEvent("loadexception", this, arg, null, e);
			callback.call(scope, null, arg, false);
			return;
		}
		callback.call(scope, result, arg, true);
	},

	update: function(params, records) {
		}
});

Ext.data.HttpProxy = function(conn) {
	Ext.data.HttpProxy.superclass.constructor.call(this);

	this.conn = conn;
	this.useAjax = !conn || !conn.events;

};

Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {

	getConnection: function() {
		return this.useAjax ? Ext.Ajax: this.conn;
	},

	load: function(params, reader, callback, scope, arg) {
		if (this.fireEvent("beforeload", this, params) !== false) {
			var o = {
				params: params || {},
				request: {
					callback: callback,
					scope: scope,
					arg: arg
				},
				reader: reader,
				callback: this.loadResponse,
				scope: this
			};
			if (this.useAjax) {
				Ext.applyIf(o, this.conn);
				if (this.activeRequest) {
					Ext.Ajax.abort(this.activeRequest);
				}
				this.activeRequest = Ext.Ajax.request(o);
			} else {
				this.conn.request(o);
			}
		} else {
			callback.call(scope || this, null, arg, false);
		}
	},

	loadResponse: function(o, success, response) {
		delete this.activeRequest;
		if (!success) {
			this.fireEvent("loadexception", this, o, response);
			o.request.callback.call(o.request.scope, null, o.request.arg, false);
			return;
		}
		var result;
		try {
			result = o.reader.read(response);
		} catch(e) {
			this.fireEvent("loadexception", this, o, response, e);
			o.request.callback.call(o.request.scope, null, o.request.arg, false);
			return;
		}
		this.fireEvent("load", this, o, o.request.arg);
		o.request.callback.call(o.request.scope, result, o.request.arg, true);
	},

	update: function(dataSet) {
		},

	updateResponse: function(dataSet) {
		}
});

Ext.data.ScriptTagProxy = function(config) {
	Ext.data.ScriptTagProxy.superclass.constructor.call(this);
	Ext.apply(this, config);
	this.head = document.getElementsByTagName("head")[0];

};

Ext.data.ScriptTagProxy.TRANS_ID = 1000;

Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {

	timeout: 30000,

	callbackParam: "callback",

	nocache: true,

	load: function(params, reader, callback, scope, arg) {
		if (this.fireEvent("beforeload", this, params) !== false) {

			var p = Ext.urlEncode(Ext.apply(params, this.extraParams));

			var url = this.url;
			url += (url.indexOf("?") != -1 ? "&": "?") + p;
			if (this.nocache) {
				url += "&_dc=" + (new Date().getTime());
			}
			var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
			var trans = {
				id: transId,
				cb: "stcCallback" + transId,
				scriptId: "stcScript" + transId,
				params: params,
				arg: arg,
				url: url,
				callback: callback,
				scope: scope,
				reader: reader
			};
			var conn = this;

			window[trans.cb] = function(o) {
				conn.handleResponse(o, trans);
			};

			url += String.format("&{0}={1}", this.callbackParam, trans.cb);

			if (this.autoAbort !== false) {
				this.abort();
			}

			trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);

			var script = document.createElement("script");
			script.setAttribute("src", url);
			script.setAttribute("type", "text/javascript");
			script.setAttribute("id", trans.scriptId);
			this.head.appendChild(script);

			this.trans = trans;
		} else {
			callback.call(scope || this, null, arg, false);
		}
	},

	isLoading: function() {
		return this.trans ? true: false;
	},

	abort: function() {
		if (this.isLoading()) {
			this.destroyTrans(this.trans);
		}
	},

	destroyTrans: function(trans, isLoaded) {
		this.head.removeChild(document.getElementById(trans.scriptId));
		clearTimeout(trans.timeoutId);
		if (isLoaded) {
			window[trans.cb] = undefined;
			try {
				delete window[trans.cb];
			} catch(e) {}
		} else {

			window[trans.cb] = function() {
				window[trans.cb] = undefined;
				try {
					delete window[trans.cb];
				} catch(e) {}
			};
		}
	},

	handleResponse: function(o, trans) {
		this.trans = false;
		this.destroyTrans(trans, true);
		var result;
		try {
			result = trans.reader.readRecords(o);
		} catch(e) {
			this.fireEvent("loadexception", this, o, trans.arg, e);
			trans.callback.call(trans.scope || window, null, trans.arg, false);
			return;
		}
		this.fireEvent("load", this, o, trans.arg);
		trans.callback.call(trans.scope || window, result, trans.arg, true);
	},

	handleFailure: function(trans) {
		this.trans = false;
		this.destroyTrans(trans, false);
		this.fireEvent("loadexception", this, null, trans.arg);
		trans.callback.call(trans.scope || window, null, trans.arg, false);
	}
});

Ext.data.JsonReader = function(meta, recordType) {
	meta = meta || {};
	Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {

	read: function(response) {
		var json = response.responseText;
		var o = eval("(" + json + ")");
		if (!o) {
			throw {
				message: "JsonReader.read: Json object not found"
			};
		}
		return this.readRecords(o);
	},

	onMetaChange: function(meta, recordType, o) {
		},

	simpleAccess: function(obj, subsc) {
		return obj[subsc];
	},

	getJsonAccessor: function() {
		var re = /[\[\.]/;
		return function(expr) {
			try {
				return (re.test(expr)) ? new Function("obj", "return obj." + expr) : function(obj) {
					return obj[expr];
				};
			} catch(e) {}
			return Ext.emptyFn;
		};
	} (),

	readRecords: function(o) {

		this.jsonData = o;
		if (o.metaData) {
			delete this.ef;
			this.meta = o.metaData;
			this.recordType = Ext.data.Record.create(o.metaData.fields);
			this.onMetaChange(this.meta, this.recordType, o);
		}
		var s = this.meta,
		Record = this.recordType,
		f = Record.prototype.fields,
		fi = f.items,
		fl = f.length;

		if (!this.ef) {
			if (s.totalProperty) {
				this.getTotal = this.getJsonAccessor(s.totalProperty);
			}
			if (s.successProperty) {
				this.getSuccess = this.getJsonAccessor(s.successProperty);
			}
			this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p) {
				return p;
			};
			if (s.id) {
				var g = this.getJsonAccessor(s.id);
				this.getId = function(rec) {
					var r = g(rec);
					return (r === undefined || r === "") ? null: r;
				};
			} else {
				this.getId = function() {
					return null;
				};
			}
			this.ef = [];
			for (var i = 0; i < fl; i++) {
				f = fi[i];
				var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping: f.name;
				this.ef[i] = this.getJsonAccessor(map);
			}
		}

		var root = this.getRoot(o),
		c = root.length,
		totalRecords = c,
		success = true;
		if (s.totalProperty) {
			var v = parseInt(this.getTotal(o), 10);
			if (!isNaN(v)) {
				totalRecords = v;
			}
		}
		if (s.successProperty) {
			var v = this.getSuccess(o);
			if (v === false || v === 'false') {
				success = false;
			}
		}
		var records = [];
		for (var i = 0; i < c; i++) {
			var n = root[i];
			var values = {};
			var id = this.getId(n);
			for (var j = 0; j < fl; j++) {
				f = fi[j];
				var v = this.ef[j](n);
				values[f.name] = f.convert((v !== undefined) ? v: f.defaultValue, n);
			}
			var record = new Record(values, id);
			record.json = n;
			records[i] = record;
		}
		return {
			success: success,
			records: records,
			totalRecords: totalRecords
		};
	}
});

Ext.data.XmlReader = function(meta, recordType) {
	meta = meta || {};
	Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {

	read: function(response) {
		var doc = response.responseXML;
		if (!doc) {
			throw {
				message: "XmlReader.read: XML Document not available"
			};
		}
		return this.readRecords(doc);
	},

	readRecords: function(doc) {

		this.xmlData = doc;
		var root = doc.documentElement || doc;
		var q = Ext.DomQuery;
		var recordType = this.recordType,
		fields = recordType.prototype.fields;
		var sid = this.meta.id;
		var totalRecords = 0,
		success = true;
		if (this.meta.totalRecords) {
			totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
		}

		if (this.meta.success) {
			var sv = q.selectValue(this.meta.success, root, true);
			success = sv !== false && sv !== 'false';
		}
		var records = [];
		var ns = q.select(this.meta.record, root);
		for (var i = 0, len = ns.length; i < len; i++) {
			var n = ns[i];
			var values = {};
			var id = sid ? q.selectValue(sid, n) : undefined;
			for (var j = 0, jlen = fields.length; j < jlen; j++) {
				var f = fields.items[j];
				var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
				v = f.convert(v, n);
				values[f.name] = v;
			}
			var record = new recordType(values, id);
			record.node = n;
			records[records.length] = record;
		}

		return {
			success: success,
			records: records,
			totalRecords: totalRecords || records.length
		};
	}
});

Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {

	readRecords: function(o) {
		var sid = this.meta ? this.meta.id: null;
		var recordType = this.recordType,
		fields = recordType.prototype.fields;
		var records = [];
		var root = o;
		for (var i = 0; i < root.length; i++) {
			var n = root[i];
			var values = {};
			var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
			for (var j = 0, jlen = fields.length; j < jlen; j++) {
				var f = fields.items[j];
				var k = f.mapping !== undefined && f.mapping !== null ? f.mapping: j;
				var v = n[k] !== undefined ? n[k] : f.defaultValue;
				v = f.convert(v, n);
				values[f.name] = v;
			}
			var record = new recordType(values, id);
			record.json = n;
			records[records.length] = record;
		}
		return {
			records: records,
			totalRecords: records.length
		};
	}
});

Ext.data.Tree = function(root) {
	this.nodeHash = {};

	this.root = null;
	if (root) {
		this.setRootNode(root);
	}
	this.addEvents(
	"append",
	"remove",
	"move",
	"insert",
	"beforeappend",
	"beforeremove",
	"beforemove",
	"beforeinsert");

	Ext.data.Tree.superclass.constructor.call(this);
};

Ext.extend(Ext.data.Tree, Ext.util.Observable, {

	pathSeparator: "/",

	proxyNodeEvent: function() {
		return this.fireEvent.apply(this, arguments);
	},

	getRootNode: function() {
		return this.root;
	},

	setRootNode: function(node) {
		this.root = node;
		node.ownerTree = this;
		node.isRoot = true;
		this.registerNode(node);
		return node;
	},

	getNodeById: function(id) {
		return this.nodeHash[id];
	},

	registerNode: function(node) {
		this.nodeHash[node.id] = node;
	},

	unregisterNode: function(node) {
		delete this.nodeHash[node.id];
	},

	toString: function() {
		return "[Tree" + (this.id ? " " + this.id: "") + "]";
	}
});

Ext.data.Node = function(attributes) {

	this.attributes = attributes || {};
	this.leaf = this.attributes.leaf;

	this.id = this.attributes.id;
	if (!this.id) {
		this.id = Ext.id(null, "ynode-");
		this.attributes.id = this.id;
	}

	this.childNodes = [];
	if (!this.childNodes.indexOf) {
		this.childNodes.indexOf = function(o) {
			for (var i = 0, len = this.length; i < len; i++) {
				if (this[i] == o) return i;
			}
			return - 1;
		};
	}

	this.parentNode = null;

	this.firstChild = null;

	this.lastChild = null;

	this.previousSibling = null;

	this.nextSibling = null;

	this.addEvents({

		"append": true,

		"remove": true,

		"move": true,

		"insert": true,

		"beforeappend": true,

		"beforeremove": true,

		"beforemove": true,

		"beforeinsert": true
	});
	this.listeners = this.attributes.listeners;
	Ext.data.Node.superclass.constructor.call(this);
};

Ext.extend(Ext.data.Node, Ext.util.Observable, {

	fireEvent: function(evtName) {

		if (Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false) {
			return false;
		}

		var ot = this.getOwnerTree();
		if (ot) {
			if (ot.proxyNodeEvent.apply(ot, arguments) === false) {
				return false;
			}
		}
		return true;
	},

	isLeaf: function() {
		return this.leaf === true;
	},

	setFirstChild: function(node) {
		this.firstChild = node;
	},

	setLastChild: function(node) {
		this.lastChild = node;
	},

	isLast: function() {
		return (!this.parentNode ? true: this.parentNode.lastChild == this);
	},

	isFirst: function() {
		return (!this.parentNode ? true: this.parentNode.firstChild == this);
	},

	hasChildNodes: function() {
		return ! this.isLeaf() && this.childNodes.length > 0;
	},

	isExpandable: function() {
		return this.attributes.expandable || this.hasChildNodes();
	},

	appendChild: function(node) {
		var multi = false;
		if (Ext.isArray(node)) {
			multi = node;
		} else if (arguments.length > 1) {
			multi = arguments;
		}

		if (multi) {
			for (var i = 0, len = multi.length; i < len; i++) {
				this.appendChild(multi[i]);
			}
		} else {
			if (this.fireEvent("beforeappend", this.ownerTree, this, node) === false) {
				return false;
			}
			var index = this.childNodes.length;
			var oldParent = node.parentNode;

			if (oldParent) {
				if (node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false) {
					return false;
				}
				oldParent.removeChild(node);
			}
			index = this.childNodes.length;
			if (index == 0) {
				this.setFirstChild(node);
			}
			this.childNodes.push(node);
			node.parentNode = this;
			var ps = this.childNodes[index - 1];
			if (ps) {
				node.previousSibling = ps;
				ps.nextSibling = node;
			} else {
				node.previousSibling = null;
			}
			node.nextSibling = null;
			this.setLastChild(node);
			node.setOwnerTree(this.getOwnerTree());
			this.fireEvent("append", this.ownerTree, this, node, index);
			if (oldParent) {
				node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
			}
			return node;
		}
	},

	removeChild: function(node) {
		var index = this.childNodes.indexOf(node);
		if (index == -1) {
			return false;
		}
		if (this.fireEvent("beforeremove", this.ownerTree, this, node) === false) {
			return false;
		}

		this.childNodes.splice(index, 1);

		if (node.previousSibling) {
			node.previousSibling.nextSibling = node.nextSibling;
		}
		if (node.nextSibling) {
			node.nextSibling.previousSibling = node.previousSibling;
		}

		if (this.firstChild == node) {
			this.setFirstChild(node.nextSibling);
		}
		if (this.lastChild == node) {
			this.setLastChild(node.previousSibling);
		}

		node.setOwnerTree(null);

		node.parentNode = null;
		node.previousSibling = null;
		node.nextSibling = null;
		this.fireEvent("remove", this.ownerTree, this, node);
		return node;
	},

	insertBefore: function(node, refNode) {
		if (!refNode) {
			return this.appendChild(node);
		}

		if (node == refNode) {
			return false;
		}

		if (this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false) {
			return false;
		}
		var index = this.childNodes.indexOf(refNode);
		var oldParent = node.parentNode;
		var refIndex = index;

		if (oldParent == this && this.childNodes.indexOf(node) < index) {
			refIndex--;
		}

		if (oldParent) {
			if (node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false) {
				return false;
			}
			oldParent.removeChild(node);
		}
		if (refIndex == 0) {
			this.setFirstChild(node);
		}
		this.childNodes.splice(refIndex, 0, node);
		node.parentNode = this;
		var ps = this.childNodes[refIndex - 1];
		if (ps) {
			node.previousSibling = ps;
			ps.nextSibling = node;
		} else {
			node.previousSibling = null;
		}
		node.nextSibling = refNode;
		refNode.previousSibling = node;
		node.setOwnerTree(this.getOwnerTree());
		this.fireEvent("insert", this.ownerTree, this, node, refNode);
		if (oldParent) {
			node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
		}
		return node;
	},

	remove: function() {
		this.parentNode.removeChild(this);
		return this;
	},

	item: function(index) {
		return this.childNodes[index];
	},

	replaceChild: function(newChild, oldChild) {
		this.insertBefore(newChild, oldChild);
		this.removeChild(oldChild);
		return oldChild;
	},

	indexOf: function(child) {
		return this.childNodes.indexOf(child);
	},

	getOwnerTree: function() {

		if (!this.ownerTree) {
			var p = this;
			while (p) {
				if (p.ownerTree) {
					this.ownerTree = p.ownerTree;
					break;
				}
				p = p.parentNode;
			}
		}
		return this.ownerTree;
	},

	getDepth: function() {
		var depth = 0;
		var p = this;
		while (p.parentNode) {++depth;
			p = p.parentNode;
		}
		return depth;
	},

	setOwnerTree: function(tree) {

		if (tree != this.ownerTree) {
			if (this.ownerTree) {
				this.ownerTree.unregisterNode(this);
			}
			this.ownerTree = tree;
			var cs = this.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				cs[i].setOwnerTree(tree);
			}
			if (tree) {
				tree.registerNode(this);
			}
		}
	},

	getPath: function(attr) {
		attr = attr || "id";
		var p = this.parentNode;
		var b = [this.attributes[attr]];
		while (p) {
			b.unshift(p.attributes[attr]);
			p = p.parentNode;
		}
		var sep = this.getOwnerTree().pathSeparator;
		return sep + b.join(sep);
	},

	bubble: function(fn, scope, args) {
		var p = this;
		while (p) {
			if (fn.apply(scope || p, args || [p]) === false) {
				break;
			}
			p = p.parentNode;
		}
	},

	cascade: function(fn, scope, args) {
		if (fn.apply(scope || this, args || [this]) !== false) {
			var cs = this.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				cs[i].cascade(fn, scope, args);
			}
		}
	},

	eachChild: function(fn, scope, args) {
		var cs = this.childNodes;
		for (var i = 0, len = cs.length; i < len; i++) {
			if (fn.apply(scope || this, args || [cs[i]]) === false) {
				break;
			}
		}
	},

	findChild: function(attribute, value) {
		var cs = this.childNodes;
		for (var i = 0, len = cs.length; i < len; i++) {
			if (cs[i].attributes[attribute] == value) {
				return cs[i];
			}
		}
		return null;
	},

	findChildBy: function(fn, scope) {
		var cs = this.childNodes;
		for (var i = 0, len = cs.length; i < len; i++) {
			if (fn.call(scope || cs[i], cs[i]) === true) {
				return cs[i];
			}
		}
		return null;
	},

	sort: function(fn, scope) {
		var cs = this.childNodes;
		var len = cs.length;
		if (len > 0) {
			var sortFn = scope ?
			function() {
				fn.apply(scope, arguments);
			}: fn;
			cs.sort(sortFn);
			for (var i = 0; i < len; i++) {
				var n = cs[i];
				n.previousSibling = cs[i - 1];
				n.nextSibling = cs[i + 1];
				if (i == 0) {
					this.setFirstChild(n);
				}
				if (i == len - 1) {
					this.setLastChild(n);
				}
			}
		}
	},

	contains: function(node) {
		return node.isAncestor(this);
	},

	isAncestor: function(node) {
		var p = this.parentNode;
		while (p) {
			if (p == node) {
				return true;
			}
			p = p.parentNode;
		}
		return false;
	},

	toString: function() {
		return "[Node" + (this.id ? " " + this.id: "") + "]";
	}
});

Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {

	remoteGroup: false,

	groupOnSort: false,

	clearGrouping: function() {
		this.groupField = false;
		if (this.remoteGroup) {
			if (this.baseParams) {
				delete this.baseParams.groupBy;
			}
			this.reload();
		} else {
			this.applySort();
			this.fireEvent('datachanged', this);
		}
	},

	groupBy: function(field, forceRegroup) {
		if (this.groupField == field && !forceRegroup) {
			return;
		}
		this.groupField = field;
		if (this.remoteGroup) {
			if (!this.baseParams) {
				this.baseParams = {};
			}
			this.baseParams['groupBy'] = field;
		}
		if (this.groupOnSort) {
			this.sort(field);
			return;
		}
		if (this.remoteGroup) {
			this.reload();
		} else {
			var si = this.sortInfo || {};
			if (si.field != field) {
				this.applySort();
			} else {
				this.sortData(field);
			}
			this.fireEvent('datachanged', this);
		}
	},

	applySort: function() {
		Ext.data.GroupingStore.superclass.applySort.call(this);
		if (!this.groupOnSort && !this.remoteGroup) {
			var gs = this.getGroupState();
			if (gs && gs != this.sortInfo.field) {
				this.sortData(this.groupField);
			}
		}
	},

	applyGrouping: function(alwaysFireChange) {
		if (this.groupField !== false) {
			this.groupBy(this.groupField, true);
			return true;
		} else {
			if (alwaysFireChange === true) {
				this.fireEvent('datachanged', this);
			}
			return false;
		}
	},

	getGroupState: function() {
		return this.groupOnSort && this.groupField !== false ? (this.sortInfo ? this.sortInfo.field: undefined) : this.groupField;
	}
});

Ext.ComponentMgr = function() {
	var all = new Ext.util.MixedCollection();
	var types = {};

	return {

		register: function(c) {
			all.add(c);
		},

		unregister: function(c) {
			all.remove(c);
		},

		get: function(id) {
			return all.get(id);
		},

		onAvailable: function(id, fn, scope) {
			all.on("add",
			function(index, o) {
				if (o.id == id) {
					fn.call(scope || o, o);
					all.un("add", fn, scope);
				}
			});
		},

		all: all,

		registerType: function(xtype, cls) {
			types[xtype] = cls;
			cls.xtype = xtype;
		},

		create: function(config, defaultType) {
			return new types[config.xtype || defaultType](config);
		}
	};
} ();

Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down

Ext.Component = function(config) {
	config = config || {};
	if (config.initialConfig) {
		if (config.isAction) {
			this.baseAction = config;
		}
		config = config.initialConfig;
	} else if (config.tagName || config.dom || typeof config == "string") {
		config = {
			applyTo: config,
			id: config.id || config
		};
	}

	this.initialConfig = config;

	Ext.apply(this, config);
	this.addEvents(
	'disable',
	'enable',
	'beforeshow',
	'show',
	'beforehide',
	'hide',
	'beforerender',
	'render',
	'beforedestroy',
	'destroy',
	'beforestaterestore',
	'staterestore',
	'beforestatesave',
	'statesave');
	this.getId();
	Ext.ComponentMgr.register(this);
	Ext.Component.superclass.constructor.call(this);

	if (this.baseAction) {
		this.baseAction.addComponent(this);
	}

	this.initComponent();

	if (this.plugins) {
		if (Ext.isArray(this.plugins)) {
			for (var i = 0, len = this.plugins.length; i < len; i++) {
				this.plugins[i] = this.initPlugin(this.plugins[i]);
			}
		} else {
			this.plugins = this.initPlugin(this.plugins);
		}
	}

	if (this.stateful !== false) {
		this.initState(config);
	}

	if (this.applyTo) {
		this.applyToMarkup(this.applyTo);
		delete this.applyTo;
	} else if (this.renderTo) {
		this.render(this.renderTo);
		delete this.renderTo;
	}
};

Ext.Component.AUTO_ID = 1000;

Ext.extend(Ext.Component, Ext.util.Observable, {

	disabledClass: "x-item-disabled",

	allowDomMove: true,

	autoShow: false,

	hideMode: 'display',

	hideParent: false,

	hidden: false,

	disabled: false,

	rendered: false,

	ctype: "Ext.Component",

	actionMode: "el",

	getActionEl: function() {
		return this[this.actionMode];
	},

	initPlugin: function(p) {
		p.init(this);
		return p;
	},

	initComponent: Ext.emptyFn,

	render: function(container, position) {
		if (!this.rendered && this.fireEvent("beforerender", this) !== false) {
			if (!container && this.el) {
				this.el = Ext.get(this.el);
				container = this.el.dom.parentNode;
				this.allowDomMove = false;
			}
			this.container = Ext.get(container);
			if (this.ctCls) {
				this.container.addClass(this.ctCls);
			}
			this.rendered = true;
			if (position !== undefined) {
				if (typeof position == 'number') {
					position = this.container.dom.childNodes[position];
				} else {
					position = Ext.getDom(position);
				}
			}
			this.onRender(this.container, position || null);
			if (this.autoShow) {
				this.el.removeClass(['x-hidden', 'x-hide-' + this.hideMode]);
			}
			if (this.cls) {
				this.el.addClass(this.cls);
				delete this.cls;
			}
			if (this.style) {
				this.el.applyStyles(this.style);
				delete this.style;
			}
			this.fireEvent("render", this);
			this.afterRender(this.container);
			if (this.hidden) {
				this.hide();
			}
			if (this.disabled) {
				this.disable();
			}

			if (this.stateful !== false) {
				this.initStateEvents();
			}
		}
		return this;
	},

	initState: function(config) {
		if (Ext.state.Manager) {
			var state = Ext.state.Manager.get(this.stateId || this.id);
			if (state) {
				if (this.fireEvent('beforestaterestore', this, state) !== false) {
					this.applyState(state);
					this.fireEvent('staterestore', this, state);
				}
			}
		}
	},

	initStateEvents: function() {
		if (this.stateEvents) {
			for (var i = 0, e; e = this.stateEvents[i]; i++) {
				this.on(e, this.saveState, this, {
					delay: 100
				});
			}
		}
	},

	applyState: function(state, config) {
		if (state) {
			Ext.apply(this, state);
		}
	},

	getState: function() {
		return null;
	},

	saveState: function() {
		if (Ext.state.Manager) {
			var state = this.getState();
			if (this.fireEvent('beforestatesave', this, state) !== false) {
				Ext.state.Manager.set(this.stateId || this.id, state);
				this.fireEvent('statesave', this, state);
			}
		}
	},

	applyToMarkup: function(el) {
		this.allowDomMove = false;
		this.el = Ext.get(el);
		this.render(this.el.dom.parentNode);
	},

	addClass: function(cls) {
		if (this.el) {
			this.el.addClass(cls);
		} else {
			this.cls = this.cls ? this.cls + ' ' + cls: cls;
		}
	},

	removeClass: function(cls) {
		if (this.el) {
			this.el.removeClass(cls);
		} else if (this.cls) {
			this.cls = this.cls.split(' ').remove(cls).join(' ');
		}
	},

	onRender: function(ct, position) {
		if (this.autoEl) {
			if (typeof this.autoEl == 'string') {
				this.el = document.createElement(this.autoEl);
			} else {
				var div = document.createElement('div');
				Ext.DomHelper.overwrite(div, this.autoEl);
				this.el = div.firstChild;
			}
			if (!this.el.id) {
				this.el.id = this.getId();
			}
		}
		if (this.el) {
			this.el = Ext.get(this.el);
			if (this.allowDomMove !== false) {
				ct.dom.insertBefore(this.el.dom, position);
			}
			if (this.overCls) {
				this.el.addClassOnOver(this.overCls);
			}
		}
	},

	getAutoCreate: function() {
		var cfg = typeof this.autoCreate == "object" ? this.autoCreate: Ext.apply({},
		this.defaultAutoCreate);
		if (this.id && !cfg.id) {
			cfg.id = this.id;
		}
		return cfg;
	},

	afterRender: Ext.emptyFn,

	destroy: function() {
		if (this.fireEvent("beforedestroy", this) !== false) {
			this.beforeDestroy();
			if (this.rendered) {
				this.el.removeAllListeners();
				this.el.remove();
				if (this.actionMode == "container") {
					this.container.remove();
				}
			}
			this.onDestroy();
			Ext.ComponentMgr.unregister(this);
			this.fireEvent("destroy", this);
			this.purgeListeners();
		}
	},

	beforeDestroy: Ext.emptyFn,

	onDestroy: Ext.emptyFn,

	getEl: function() {
		return this.el;
	},

	getId: function() {
		return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));
	},

	getItemId: function() {
		return this.itemId || this.getId();
	},

	focus: function(selectText, delay) {
		if (delay) {
			this.focus.defer(typeof delay == 'number' ? delay: 10, this, [selectText, false]);
			return;
		}
		if (this.rendered) {
			this.el.focus();
			if (selectText === true) {
				this.el.dom.select();
			}
		}
		return this;
	},

	blur: function() {
		if (this.rendered) {
			this.el.blur();
		}
		return this;
	},

	disable: function() {
		if (this.rendered) {
			this.onDisable();
		}
		this.disabled = true;
		this.fireEvent("disable", this);
		return this;
	},

	onDisable: function() {
		this.getActionEl().addClass(this.disabledClass);
		this.el.dom.disabled = true;
	},

	enable: function() {
		if (this.rendered) {
			this.onEnable();
		}
		this.disabled = false;
		this.fireEvent("enable", this);
		return this;
	},

	onEnable: function() {
		this.getActionEl().removeClass(this.disabledClass);
		this.el.dom.disabled = false;
	},

	setDisabled: function(disabled) {
		this[disabled ? "disable": "enable"]();
	},

	show: function() {
		if (this.fireEvent("beforeshow", this) !== false) {
			this.hidden = false;
			if (this.autoRender) {
				this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);
			}
			if (this.rendered) {
				this.onShow();
			}
			this.fireEvent("show", this);
		}
		return this;
	},

	onShow: function() {
		if (this.hideParent) {
			this.container.removeClass('x-hide-' + this.hideMode);
		} else {
			this.getActionEl().removeClass('x-hide-' + this.hideMode);
		}

	},

	hide: function() {
		if (this.fireEvent("beforehide", this) !== false) {
			this.hidden = true;
			if (this.rendered) {
				this.onHide();
			}
			this.fireEvent("hide", this);
		}
		return this;
	},

	onHide: function() {
		if (this.hideParent) {
			this.container.addClass('x-hide-' + this.hideMode);
		} else {
			this.getActionEl().addClass('x-hide-' + this.hideMode);
		}
	},

	setVisible: function(visible) {
		if (visible) {
			this.show();
		} else {
			this.hide();
		}
		return this;
	},

	isVisible: function() {
		return this.rendered && this.getActionEl().isVisible();
	},

	cloneConfig: function(overrides) {
		overrides = overrides || {};
		var id = overrides.id || Ext.id();
		var cfg = Ext.applyIf(overrides, this.initialConfig);
		cfg.id = id;
		return new this.constructor(cfg);
	},

	getXType: function() {
		return this.constructor.xtype;
	},

	isXType: function(xtype, shallow) {
		return ! shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.constructor.xtype == xtype;
	},

	getXTypes: function() {
		var tc = this.constructor;
		if (!tc.xtypes) {
			var c = [],
			sc = this;
			while (sc && sc.constructor.xtype) {
				c.unshift(sc.constructor.xtype);
				sc = sc.constructor.superclass;
			}
			tc.xtypeChain = c;
			tc.xtypes = c.join('/');
		}
		return tc.xtypes;
	},

	findParentBy: function(fn) {
		for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
		return p || null;
	},

	findParentByType: function(xtype) {
		return typeof xtype == 'function' ? this.findParentBy(function(p) {
			return p.constructor === xtype;
		}) : this.findParentBy(function(p) {
			return p.constructor.xtype === xtype;
		});
	},

	mon: function(item, ename, fn, scope, opt) {
		if (!this.mons) {
			this.mons = [];
			this.on('beforedestroy',
			function() {
				for (var i = 0, len = this.mons.length; i < len; i++) {
					var m = this.mons[i];
					m.item.un(m.ename, m.fn, m.scope);
				}
			},
			this);
		}
		this.mons.push({
			item: item,
			ename: ename,
			fn: fn,
			scope: scope
		});
		item.on(ename, fn, scope, opt);
	}
});

Ext.reg('component', Ext.Component);

Ext.Action = function(config) {
	this.initialConfig = config;
	this.items = [];
}

Ext.Action.prototype = {

	isAction: true,

	setText: function(text) {
		this.initialConfig.text = text;
		this.callEach('setText', [text]);
	},

	getText: function() {
		return this.initialConfig.text;
	},

	setIconClass: function(cls) {
		this.initialConfig.iconCls = cls;
		this.callEach('setIconClass', [cls]);
	},

	getIconClass: function() {
		return this.initialConfig.iconCls;
	},

	setDisabled: function(v) {
		this.initialConfig.disabled = v;
		this.callEach('setDisabled', [v]);
	},

	enable: function() {
		this.setDisabled(false);
	},

	disable: function() {
		this.setDisabled(true);
	},

	isDisabled: function() {
		return this.initialConfig.disabled;
	},

	setHidden: function(v) {
		this.initialConfig.hidden = v;
		this.callEach('setVisible', [!v]);
	},

	show: function() {
		this.setHidden(false);
	},

	hide: function() {
		this.setHidden(true);
	},

	isHidden: function() {
		return this.initialConfig.hidden;
	},

	setHandler: function(fn, scope) {
		this.initialConfig.handler = fn;
		this.initialConfig.scope = scope;
		this.callEach('setHandler', [fn, scope]);
	},

	each: function(fn, scope) {
		Ext.each(this.items, fn, scope);
	},

	callEach: function(fnName, args) {
		var cs = this.items;
		for (var i = 0, len = cs.length; i < len; i++) {
			cs[i][fnName].apply(cs[i], args);
		}
	},

	addComponent: function(comp) {
		this.items.push(comp);
		comp.on('destroy', this.removeComponent, this);
	},

	removeComponent: function(comp) {
		this.items.remove(comp);
	},

	execute: function() {
		this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
	}
};
 (function() {
	Ext.Layer = function(config, existingEl) {
		config = config || {};
		var dh = Ext.DomHelper;
		var cp = config.parentEl,
		pel = cp ? Ext.getDom(cp) : document.body;
		if (existingEl) {
			this.dom = Ext.getDom(existingEl);
		}
		if (!this.dom) {
			var o = config.dh || {
				tag: "div",
				cls: "x-layer"
			};
			this.dom = dh.append(pel, o);
		}
		if (config.cls) {
			this.addClass(config.cls);
		}
		this.constrain = config.constrain !== false;
		this.visibilityMode = Ext.Element.VISIBILITY;
		if (config.id) {
			this.id = this.dom.id = config.id;
		} else {
			this.id = Ext.id(this.dom);
		}
		this.zindex = config.zindex || this.getZIndex();
		this.position("absolute", this.zindex);
		if (config.shadow) {
			this.shadowOffset = config.shadowOffset || 4;
			this.shadow = new Ext.Shadow({
				offset: this.shadowOffset,
				mode: config.shadow
			});
		} else {
			this.shadowOffset = 0;
		}
		this.useShim = config.shim !== false && Ext.useShims;
		this.useDisplay = config.useDisplay;
		this.hide();
	};

	var supr = Ext.Element.prototype;

	var shims = [];

	Ext.extend(Ext.Layer, Ext.Element, {

		getZIndex: function() {
			return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
		},

		getShim: function() {
			if (!this.useShim) {
				return null;
			}
			if (this.shim) {
				return this.shim;
			}
			var shim = shims.shift();
			if (!shim) {
				shim = this.createShim();
				shim.enableDisplayMode('block');
				shim.dom.style.display = 'none';
				shim.dom.style.visibility = 'visible';
			}
			var pn = this.dom.parentNode;
			if (shim.dom.parentNode != pn) {
				pn.insertBefore(shim.dom, this.dom);
			}
			shim.setStyle('z-index', this.getZIndex() - 2);
			this.shim = shim;
			return shim;
		},

		hideShim: function() {
			if (this.shim) {
				this.shim.setDisplayed(false);
				shims.push(this.shim);
				delete this.shim;
			}
		},

		disableShadow: function() {
			if (this.shadow) {
				this.shadowDisabled = true;
				this.shadow.hide();
				this.lastShadowOffset = this.shadowOffset;
				this.shadowOffset = 0;
			}
		},

		enableShadow: function(show) {
			if (this.shadow) {
				this.shadowDisabled = false;
				this.shadowOffset = this.lastShadowOffset;
				delete this.lastShadowOffset;
				if (show) {
					this.sync(true);
				}
			}
		},

		sync: function(doShow) {
			var sw = this.shadow;
			if (!this.updating && this.isVisible() && (sw || this.useShim)) {
				var sh = this.getShim();

				var w = this.getWidth(),
				h = this.getHeight();

				var l = this.getLeft(true),
				t = this.getTop(true);

				if (sw && !this.shadowDisabled) {
					if (doShow && !sw.isVisible()) {
						sw.show(this);
					} else {
						sw.realign(l, t, w, h);
					}
					if (sh) {
						if (doShow) {
							sh.show();
						}

						var a = sw.adjusts,
						s = sh.dom.style;
						s.left = (Math.min(l, l + a.l)) + "px";
						s.top = (Math.min(t, t + a.t)) + "px";
						s.width = (w + a.w) + "px";
						s.height = (h + a.h) + "px";
					}
				} else if (sh) {
					if (doShow) {
						sh.show();
					}
					sh.setSize(w, h);
					sh.setLeftTop(l, t);
				}

			}
		},

		destroy: function() {
			this.hideShim();
			if (this.shadow) {
				this.shadow.hide();
			}
			this.removeAllListeners();
			Ext.removeNode(this.dom);
			Ext.Element.uncache(this.id);
		},

		remove: function() {
			this.destroy();
		},

		beginUpdate: function() {
			this.updating = true;
		},

		endUpdate: function() {
			this.updating = false;
			this.sync(true);
		},

		hideUnders: function(negOffset) {
			if (this.shadow) {
				this.shadow.hide();
			}
			this.hideShim();
		},

		constrainXY: function() {
			if (this.constrain) {
				var vw = Ext.lib.Dom.getViewWidth(),
				vh = Ext.lib.Dom.getViewHeight();
				var s = Ext.getDoc().getScroll();

				var xy = this.getXY();
				var x = xy[0],
				y = xy[1];
				var w = this.dom.offsetWidth + this.shadowOffset,
				h = this.dom.offsetHeight + this.shadowOffset;

				var moved = false;

				if ((x + w) > vw + s.left) {
					x = vw - w - this.shadowOffset;
					moved = true;
				}
				if ((y + h) > vh + s.top) {
					y = vh - h - this.shadowOffset;
					moved = true;
				}

				if (x < s.left) {
					x = s.left;
					moved = true;
				}
				if (y < s.top) {
					y = s.top;
					moved = true;
				}
				if (moved) {
					if (this.avoidY) {
						var ay = this.avoidY;
						if (y <= ay && (y + h) >= ay) {
							y = ay - h - 5;
						}
					}
					xy = [x, y];
					this.storeXY(xy);
					supr.setXY.call(this, xy);
					this.sync();
				}
			}
		},

		isVisible: function() {
			return this.visible;
		},

		showAction: function() {
			this.visible = true;
			if (this.useDisplay === true) {
				this.setDisplayed("");
			} else if (this.lastXY) {
				supr.setXY.call(this, this.lastXY);
			} else if (this.lastLT) {
				supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
			}
		},

		hideAction: function() {
			this.visible = false;
			if (this.useDisplay === true) {
				this.setDisplayed(false);
			} else {
				this.setLeftTop( - 10000, -10000);
			}
		},

		setVisible: function(v, a, d, c, e) {
			if (v) {
				this.showAction();
			}
			if (a && v) {
				var cb = function() {
					this.sync(true);
					if (c) {
						c();
					}
				}.createDelegate(this);
				supr.setVisible.call(this, true, true, d, cb, e);
			} else {
				if (!v) {
					this.hideUnders(true);
				}
				var cb = c;
				if (a) {
					cb = function() {
						this.hideAction();
						if (c) {
							c();
						}
					}.createDelegate(this);
				}
				supr.setVisible.call(this, v, a, d, cb, e);
				if (v) {
					this.sync(true);
				} else if (!a) {
					this.hideAction();
				}
			}
		},

		storeXY: function(xy) {
			delete this.lastLT;
			this.lastXY = xy;
		},

		storeLeftTop: function(left, top) {
			delete this.lastXY;
			this.lastLT = [left, top];
		},

		beforeFx: function() {
			this.beforeAction();
			return Ext.Layer.superclass.beforeFx.apply(this, arguments);
		},

		afterFx: function() {
			Ext.Layer.superclass.afterFx.apply(this, arguments);
			this.sync(this.isVisible());
		},

		beforeAction: function() {
			if (!this.updating && this.shadow) {
				this.shadow.hide();
			}
		},

		setLeft: function(left) {
			this.storeLeftTop(left, this.getTop(true));
			supr.setLeft.apply(this, arguments);
			this.sync();
		},

		setTop: function(top) {
			this.storeLeftTop(this.getLeft(true), top);
			supr.setTop.apply(this, arguments);
			this.sync();
		},

		setLeftTop: function(left, top) {
			this.storeLeftTop(left, top);
			supr.setLeftTop.apply(this, arguments);
			this.sync();
		},

		setXY: function(xy, a, d, c, e) {
			this.fixDisplay();
			this.beforeAction();
			this.storeXY(xy);
			var cb = this.createCB(c);
			supr.setXY.call(this, xy, a, d, cb, e);
			if (!a) {
				cb();
			}
		},

		createCB: function(c) {
			var el = this;
			return function() {
				el.constrainXY();
				el.sync(true);
				if (c) {
					c();
				}
			};
		},

		setX: function(x, a, d, c, e) {
			this.setXY([x, this.getY()], a, d, c, e);
		},

		setY: function(y, a, d, c, e) {
			this.setXY([this.getX(), y], a, d, c, e);
		},

		setSize: function(w, h, a, d, c, e) {
			this.beforeAction();
			var cb = this.createCB(c);
			supr.setSize.call(this, w, h, a, d, cb, e);
			if (!a) {
				cb();
			}
		},

		setWidth: function(w, a, d, c, e) {
			this.beforeAction();
			var cb = this.createCB(c);
			supr.setWidth.call(this, w, a, d, cb, e);
			if (!a) {
				cb();
			}
		},

		setHeight: function(h, a, d, c, e) {
			this.beforeAction();
			var cb = this.createCB(c);
			supr.setHeight.call(this, h, a, d, cb, e);
			if (!a) {
				cb();
			}
		},

		setBounds: function(x, y, w, h, a, d, c, e) {
			this.beforeAction();
			var cb = this.createCB(c);
			if (!a) {
				this.storeXY([x, y]);
				supr.setXY.call(this, [x, y]);
				supr.setSize.call(this, w, h, a, d, cb, e);
				cb();
			} else {
				supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
			}
			return this;
		},

		setZIndex: function(zindex) {
			this.zindex = zindex;
			this.setStyle("z-index", zindex + 2);
			if (this.shadow) {
				this.shadow.setZIndex(zindex + 1);
			}
			if (this.shim) {
				this.shim.setStyle("z-index", zindex);
			}
		}
	});
})();

Ext.Shadow = function(config) {
	Ext.apply(this, config);
	if (typeof this.mode != "string") {
		this.mode = this.defaultMode;
	}
	var o = this.offset,
	a = {
		h: 0
	};
	var rad = Math.floor(this.offset / 2);
	switch (this.mode.toLowerCase()) {
	case "drop":
		a.w = 0;
		a.l = a.t = o;
		a.t -= 1;
		if (Ext.isIE) {
			a.l -= this.offset + rad;
			a.t -= this.offset + rad;
			a.w -= rad;
			a.h -= rad;
			a.t += 1;
		}
		break;
	case "sides":
		a.w = (o * 2);
		a.l = -o;
		a.t = o - 1;
		if (Ext.isIE) {
			a.l -= (this.offset - rad);
			a.t -= this.offset + rad;
			a.l += 1;
			a.w -= (this.offset - rad) * 2;
			a.w -= rad + 1;
			a.h -= 1;
		}
		break;
	case "frame":
		a.w = a.h = (o * 2);
		a.l = a.t = -o;
		a.t += 1;
		a.h -= 2;
		if (Ext.isIE) {
			a.l -= (this.offset - rad);
			a.t -= (this.offset - rad);
			a.l += 1;
			a.w -= (this.offset + rad + 1);
			a.h -= (this.offset + rad);
			a.h += 1;
		}
		break;
	};

	this.adjusts = a;
};

Ext.Shadow.prototype = {

	offset: 4,

	defaultMode: "drop",

	show: function(target) {
		target = Ext.get(target);
		if (!this.el) {
			this.el = Ext.Shadow.Pool.pull();
			if (this.el.dom.nextSibling != target.dom) {
				this.el.insertBefore(target);
			}
		}
		this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
		if (Ext.isIE) {
			this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
		}
		this.realign(target.getLeft(true), target.getTop(true), target.getWidth(), target.getHeight());
		this.el.dom.style.display = "block";
	},

	isVisible: function() {
		return this.el ? true: false;
	},

	realign: function(l, t, w, h) {
		if (!this.el) {
			return;
		}
		var a = this.adjusts,
		d = this.el.dom,
		s = d.style;
		var iea = 0;
		s.left = (l + a.l) + "px";
		s.top = (t + a.t) + "px";
		var sw = (w + a.w),
		sh = (h + a.h),
		sws = sw + "px",
		shs = sh + "px";
		if (s.width != sws || s.height != shs) {
			s.width = sws;
			s.height = shs;
			if (!Ext.isIE) {
				var cn = d.childNodes;
				var sww = Math.max(0, (sw - 12)) + "px";
				cn[0].childNodes[1].style.width = sww;
				cn[1].childNodes[1].style.width = sww;
				cn[2].childNodes[1].style.width = sww;
				cn[1].style.height = Math.max(0, (sh - 12)) + "px";
			}
		}
	},

	hide: function() {
		if (this.el) {
			this.el.dom.style.display = "none";
			Ext.Shadow.Pool.push(this.el);
			delete this.el;
		}
	},

	setZIndex: function(z) {
		this.zIndex = z;
		if (this.el) {
			this.el.setStyle("z-index", z);
		}
	}
};

Ext.Shadow.Pool = function() {
	var p = [];
	var markup = Ext.isIE ? '<div class="x-ie-shadow"></div>': '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
	return {
		pull: function() {
			var sh = p.shift();
			if (!sh) {
				sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
				sh.autoBoxAdjust = false;
			}
			return sh;
		},

		push: function(sh) {
			p.push(sh);
		}
	};
} ();

Ext.BoxComponent = Ext.extend(Ext.Component, {

	initComponent: function() {
		Ext.BoxComponent.superclass.initComponent.call(this);
		this.addEvents(
		'resize',
		'move');
	},

	boxReady: false,
	deferHeight: false,

	setSize: function(w, h) {
		if (typeof w == 'object') {
			h = w.height;
			w = w.width;
		}
		if (!this.boxReady) {
			this.width = w;
			this.height = h;
			return this;
		}

		if (this.lastSize && this.lastSize.width == w && this.lastSize.height == h) {
			return this;
		}
		this.lastSize = {
			width: w,
			height: h
		};
		var adj = this.adjustSize(w, h);
		var aw = adj.width,
		ah = adj.height;
		if (aw !== undefined || ah !== undefined) {
			var rz = this.getResizeEl();
			if (!this.deferHeight && aw !== undefined && ah !== undefined) {
				rz.setSize(aw, ah);
			} else if (!this.deferHeight && ah !== undefined) {
				rz.setHeight(ah);
			} else if (aw !== undefined) {
				rz.setWidth(aw);
			}
			this.onResize(aw, ah, w, h);
			this.fireEvent('resize', this, aw, ah, w, h);
		}
		return this;
	},

	setWidth: function(width) {
		return this.setSize(width);
	},

	setHeight: function(height) {
		return this.setSize(undefined, height);
	},

	getSize: function() {
		return this.el.getSize();
	},

	getPosition: function(local) {
		if (local === true) {
			return [this.el.getLeft(true), this.el.getTop(true)];
		}
		return this.xy || this.el.getXY();
	},

	getBox: function(local) {
		var s = this.el.getSize();
		if (local === true) {
			s.x = this.el.getLeft(true);
			s.y = this.el.getTop(true);
		} else {
			var xy = this.xy || this.el.getXY();
			s.x = xy[0];
			s.y = xy[1];
		}
		return s;
	},

	updateBox: function(box) {
		this.setSize(box.width, box.height);
		this.setPagePosition(box.x, box.y);
		return this;
	},

	getResizeEl: function() {
		return this.resizeEl || this.el;
	},

	getPositionEl: function() {
		return this.positionEl || this.el;
	},

	setPosition: function(x, y) {
		if (x && typeof x[1] == 'number') {
			y = x[1];
			x = x[0];
		}
		this.x = x;
		this.y = y;
		if (!this.boxReady) {
			return this;
		}
		var adj = this.adjustPosition(x, y);
		var ax = adj.x,
		ay = adj.y;

		var el = this.getPositionEl();
		if (ax !== undefined || ay !== undefined) {
			if (ax !== undefined && ay !== undefined) {
				el.setLeftTop(ax, ay);
			} else if (ax !== undefined) {
				el.setLeft(ax);
			} else if (ay !== undefined) {
				el.setTop(ay);
			}
			this.onPosition(ax, ay);
			this.fireEvent('move', this, ax, ay);
		}
		return this;
	},

	setPagePosition: function(x, y) {
		if (x && typeof x[1] == 'number') {
			y = x[1];
			x = x[0];
		}
		this.pageX = x;
		this.pageY = y;
		if (!this.boxReady) {
			return;
		}
		if (x === undefined || y === undefined) {
			return;
		}
		var p = this.el.translatePoints(x, y);
		this.setPosition(p.left, p.top);
		return this;
	},

	onRender: function(ct, position) {
		Ext.BoxComponent.superclass.onRender.call(this, ct, position);
		if (this.resizeEl) {
			this.resizeEl = Ext.get(this.resizeEl);
		}
		if (this.positionEl) {
			this.positionEl = Ext.get(this.positionEl);
		}
	},

	afterRender: function() {
		Ext.BoxComponent.superclass.afterRender.call(this);
		this.boxReady = true;
		this.setSize(this.width, this.height);
		if (this.x || this.y) {
			this.setPosition(this.x, this.y);
		} else if (this.pageX || this.pageY) {
			this.setPagePosition(this.pageX, this.pageY);
		}
	},

	syncSize: function() {
		delete this.lastSize;
		this.setSize(this.autoWidth ? undefined: this.el.getWidth(), this.autoHeight ? undefined: this.el.getHeight());
		return this;
	},

	onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
		},

	onPosition: function(x, y) {
		},

	adjustSize: function(w, h) {
		if (this.autoWidth) {
			w = 'auto';
		}
		if (this.autoHeight) {
			h = 'auto';
		}
		return {
			width: w,
			height: h
		};
	},

	adjustPosition: function(x, y) {
		return {
			x: x,
			y: y
		};
	}
});
Ext.reg('box', Ext.BoxComponent);

Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy) {

	this.el = Ext.get(dragElement, true);
	this.el.dom.unselectable = "on";

	this.resizingEl = Ext.get(resizingElement, true);

	this.orientation = orientation || Ext.SplitBar.HORIZONTAL;

	this.minSize = 0;

	this.maxSize = 2000;

	this.animate = false;

	this.useShim = false;

	this.shim = null;

	if (!existingProxy) {

		this.proxy = Ext.SplitBar.createProxy(this.orientation);
	} else {
		this.proxy = Ext.get(existingProxy).dom;
	}

	this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {
		dragElId: this.proxy.id
	});

	this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);

	this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);

	this.dragSpecs = {};

	this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
	this.adapter.init(this);

	if (this.orientation == Ext.SplitBar.HORIZONTAL) {

		this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT: Ext.SplitBar.RIGHT);
		this.el.addClass("x-splitbar-h");
	} else {

		this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP: Ext.SplitBar.BOTTOM);
		this.el.addClass("x-splitbar-v");
	}

	this.addEvents(
	"resize",
	"moved",
	"beforeresize",
	"beforeapply");

	Ext.SplitBar.superclass.constructor.call(this);
};

Ext.extend(Ext.SplitBar, Ext.util.Observable, {
	onStartProxyDrag: function(x, y) {
		this.fireEvent("beforeresize", this);
		this.overlay = Ext.DomHelper.append(document.body, {
			cls: "x-drag-overlay",
			html: "&#160;"
		},
		true);
		this.overlay.unselectable();
		this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
		this.overlay.show();
		Ext.get(this.proxy).setDisplayed("block");
		var size = this.adapter.getElementSize(this);
		this.activeMinSize = this.getMinimumSize();;
		this.activeMaxSize = this.getMaximumSize();;
		var c1 = size - this.activeMinSize;
		var c2 = Math.max(this.activeMaxSize - size, 0);
		if (this.orientation == Ext.SplitBar.HORIZONTAL) {
			this.dd.resetConstraints();
			this.dd.setXConstraint(this.placement == Ext.SplitBar.LEFT ? c1: c2, this.placement == Ext.SplitBar.LEFT ? c2: c1);
			this.dd.setYConstraint(0, 0);
		} else {
			this.dd.resetConstraints();
			this.dd.setXConstraint(0, 0);
			this.dd.setYConstraint(this.placement == Ext.SplitBar.TOP ? c1: c2, this.placement == Ext.SplitBar.TOP ? c2: c1);
		}
		this.dragSpecs.startSize = size;
		this.dragSpecs.startPoint = [x, y];
		Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
	},

	onEndProxyDrag: function(e) {
		Ext.get(this.proxy).setDisplayed(false);
		var endPoint = Ext.lib.Event.getXY(e);
		if (this.overlay) {
			this.overlay.remove();
			delete this.overlay;
		}
		var newSize;
		if (this.orientation == Ext.SplitBar.HORIZONTAL) {
			newSize = this.dragSpecs.startSize + (this.placement == Ext.SplitBar.LEFT ? endPoint[0] - this.dragSpecs.startPoint[0] : this.dragSpecs.startPoint[0] - endPoint[0]);
		} else {
			newSize = this.dragSpecs.startSize + (this.placement == Ext.SplitBar.TOP ? endPoint[1] - this.dragSpecs.startPoint[1] : this.dragSpecs.startPoint[1] - endPoint[1]);
		}
		newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
		if (newSize != this.dragSpecs.startSize) {
			if (this.fireEvent('beforeapply', this, newSize) !== false) {
				this.adapter.setElementSize(this, newSize);
				this.fireEvent("moved", this, newSize);
				this.fireEvent("resize", this, newSize);
			}
		}
	},

	getAdapter: function() {
		return this.adapter;
	},

	setAdapter: function(adapter) {
		this.adapter = adapter;
		this.adapter.init(this);
	},

	getMinimumSize: function() {
		return this.minSize;
	},

	setMinimumSize: function(minSize) {
		this.minSize = minSize;
	},

	getMaximumSize: function() {
		return this.maxSize;
	},

	setMaximumSize: function(maxSize) {
		this.maxSize = maxSize;
	},

	setCurrentSize: function(size) {
		var oldAnimate = this.animate;
		this.animate = false;
		this.adapter.setElementSize(this, size);
		this.animate = oldAnimate;
	},

	destroy: function(removeEl) {
		if (this.shim) {
			this.shim.remove();
		}
		this.dd.unreg();
		Ext.removeNode(this.proxy);
		if (removeEl) {
			this.el.remove();
		}
	}
});

Ext.SplitBar.createProxy = function(dir) {
	var proxy = new Ext.Element(document.createElement("div"));
	proxy.unselectable();
	var cls = 'x-splitbar-proxy';
	proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls + '-h': cls + '-v'));
	document.body.appendChild(proxy.dom);
	return proxy.dom;
};

Ext.SplitBar.BasicLayoutAdapter = function() {};

Ext.SplitBar.BasicLayoutAdapter.prototype = {

	init: function(s) {
		},

	getElementSize: function(s) {
		if (s.orientation == Ext.SplitBar.HORIZONTAL) {
			return s.resizingEl.getWidth();
		} else {
			return s.resizingEl.getHeight();
		}
	},

	setElementSize: function(s, newSize, onComplete) {
		if (s.orientation == Ext.SplitBar.HORIZONTAL) {
			if (!s.animate) {
				s.resizingEl.setWidth(newSize);
				if (onComplete) {
					onComplete(s, newSize);
				}
			} else {
				s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
			}
		} else {

			if (!s.animate) {
				s.resizingEl.setHeight(newSize);
				if (onComplete) {
					onComplete(s, newSize);
				}
			} else {
				s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
			}
		}
	}
};

Ext.SplitBar.AbsoluteLayoutAdapter = function(container) {
	this.basic = new Ext.SplitBar.BasicLayoutAdapter();
	this.container = Ext.get(container);
};

Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
	init: function(s) {
		this.basic.init(s);
	},

	getElementSize: function(s) {
		return this.basic.getElementSize(s);
	},

	setElementSize: function(s, newSize, onComplete) {
		this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
	},

	moveSplitter: function(s) {
		var yes = Ext.SplitBar;
		switch (s.placement) {
		case yes.LEFT:
			s.el.setX(s.resizingEl.getRight());
			break;
		case yes.RIGHT:
			s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
			break;
		case yes.TOP:
			s.el.setY(s.resizingEl.getBottom());
			break;
		case yes.BOTTOM:
			s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
			break;
		}
	}
};

Ext.SplitBar.VERTICAL = 1;

Ext.SplitBar.HORIZONTAL = 2;

Ext.SplitBar.LEFT = 1;

Ext.SplitBar.RIGHT = 2;

Ext.SplitBar.TOP = 3;

Ext.SplitBar.BOTTOM = 4;

Ext.Container = Ext.extend(Ext.BoxComponent, {

	autoDestroy: true,

	defaultType: 'panel',

	initComponent: function() {
		Ext.Container.superclass.initComponent.call(this);

		this.addEvents(
		'afterlayout',
		'beforeadd',
		'beforeremove',
		'add',
		'remove');

		var items = this.items;
		if (items) {
			delete this.items;
			if (Ext.isArray(items)) {
				this.add.apply(this, items);
			} else {
				this.add(items);
			}
		}
	},

	initItems: function() {
		if (!this.items) {
			this.items = new Ext.util.MixedCollection(false, this.getComponentId);
			this.getLayout();
		}
	},

	setLayout: function(layout) {
		if (this.layout && this.layout != layout) {
			this.layout.setContainer(null);
		}
		this.initItems();
		this.layout = layout;
		layout.setContainer(this);
	},

	render: function() {
		Ext.Container.superclass.render.apply(this, arguments);
		if (this.layout) {
			if (typeof this.layout == 'string') {
				this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
			}
			this.setLayout(this.layout);

			if (this.activeItem !== undefined) {
				var item = this.activeItem;
				delete this.activeItem;
				this.layout.setActiveItem(item);
				return;
			}
		}
		if (!this.ownerCt) {
			this.doLayout();
		}
		if (this.monitorResize === true) {
			Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
		}
	},

	getLayoutTarget: function() {
		return this.el;
	},

	getComponentId: function(comp) {
		return comp.itemId || comp.id;
	},

	add: function(comp) {
		if (!this.items) {
			this.initItems();
		}
		var a = arguments,
		len = a.length;
		if (len > 1) {
			for (var i = 0; i < len; i++) {
				this.add(a[i]);
			}
			return;
		}
		var c = this.lookupComponent(this.applyDefaults(comp));
		var pos = this.items.length;
		if (this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false) {
			this.items.add(c);
			c.ownerCt = this;
			this.fireEvent('add', this, c, pos);
		}
		return c;
	},

	insert: function(index, comp) {
		if (!this.items) {
			this.initItems();
		}
		var a = arguments,
		len = a.length;
		if (len > 2) {
			for (var i = len - 1; i >= 1; --i) {
				this.insert(index, a[i]);
			}
			return;
		}
		var c = this.lookupComponent(this.applyDefaults(comp));

		if (c.ownerCt == this && this.items.indexOf(c) < index) {--index;
		}

		if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
			this.items.insert(index, c);
			c.ownerCt = this;
			this.fireEvent('add', this, c, index);
		}
		return c;
	},

	applyDefaults: function(c) {
		if (this.defaults) {
			if (typeof c == 'string') {
				c = Ext.ComponentMgr.get(c);
				Ext.apply(c, this.defaults);
			} else if (!c.events) {
				Ext.applyIf(c, this.defaults);
			} else {
				Ext.apply(c, this.defaults);
			}
		}
		return c;
	},

	onBeforeAdd: function(item) {
		if (item.ownerCt) {
			item.ownerCt.remove(item, false);
		}
		if (this.hideBorders === true) {
			item.border = (item.border === true);
		}
	},

	remove: function(comp, autoDestroy) {
		var c = this.getComponent(comp);
		if (c && this.fireEvent('beforeremove', this, c) !== false) {
			this.items.remove(c);
			delete c.ownerCt;
			if (autoDestroy === true || (autoDestroy !== false && this.autoDestroy)) {
				c.destroy();
			}
			if (this.layout && this.layout.activeItem == c) {
				delete this.layout.activeItem;
			}
			this.fireEvent('remove', this, c);
		}
		return c;
	},

	getComponent: function(comp) {
		if (typeof comp == 'object') {
			return comp;
		}
		return this.items.get(comp);
	},

	lookupComponent: function(comp) {
		if (typeof comp == 'string') {
			return Ext.ComponentMgr.get(comp);
		} else if (!comp.events) {
			return this.createComponent(comp);
		}
		return comp;
	},

	createComponent: function(config) {
		return Ext.ComponentMgr.create(config, this.defaultType);
	},

	doLayout: function(shallow) {
		if (this.rendered && this.layout) {
			this.layout.layout();
		}
		if (shallow !== false && this.items) {
			var cs = this.items.items;
			for (var i = 0, len = cs.length; i < len; i++) {
				var c = cs[i];
				if (c.doLayout) {
					c.doLayout();
				}
			}
		}
	},

	getLayout: function() {
		if (!this.layout) {
			var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
			this.setLayout(layout);
		}
		return this.layout;
	},

	beforeDestroy: function() {
		if (this.items) {
			Ext.destroy.apply(Ext, this.items.items);
		}
		if (this.monitorResize) {
			Ext.EventManager.removeResizeListener(this.doLayout, this);
		}
		if (this.layout && this.layout.destroy) {
			this.layout.destroy();
		}
		Ext.Container.superclass.beforeDestroy.call(this);
	},

	bubble: function(fn, scope, args) {
		var p = this;
		while (p) {
			if (fn.apply(scope || p, args || [p]) === false) {
				break;
			}
			p = p.ownerCt;
		}
	},

	cascade: function(fn, scope, args) {
		if (fn.apply(scope || this, args || [this]) !== false) {
			if (this.items) {
				var cs = this.items.items;
				for (var i = 0, len = cs.length; i < len; i++) {
					if (cs[i].cascade) {
						cs[i].cascade(fn, scope, args);
					} else {
						fn.apply(scope || cs[i], args || [cs[i]]);
					}
				}
			}
		}
	},

	findById: function(id) {
		var m,
		ct = this;
		this.cascade(function(c) {
			if (ct != c && c.id === id) {
				m = c;
				return false;
			}
		});
		return m || null;
	},

	findByType: function(xtype) {
		return typeof xtype == 'function' ? this.findBy(function(c) {
			return c.constructor === xtype;
		}) : this.findBy(function(c) {
			return c.constructor.xtype === xtype;
		});
	},

	find: function(prop, value) {
		return this.findBy(function(c) {
			return c[prop] === value;
		});
	},

	findBy: function(fn, scope) {
		var m = [],
		ct = this;
		this.cascade(function(c) {
			if (ct != c && fn.call(scope || c, c, ct) === true) {
				m.push(c);
			}
		});
		return m;
	}
});

Ext.Container.LAYOUTS = {};
Ext.reg('container', Ext.Container);

Ext.layout.ContainerLayout = function(config) {
	Ext.apply(this, config);
};

Ext.layout.ContainerLayout.prototype = {

	monitorResize: false,
	activeItem: null,

	layout: function() {
		var target = this.container.getLayoutTarget();
		this.onLayout(this.container, target);
		this.container.fireEvent('afterlayout', this.container, this);
	},

	onLayout: function(ct, target) {
		this.renderAll(ct, target);
	},

	isValidParent: function(c, target) {
		var el = c.getPositionEl ? c.getPositionEl() : c.getEl();
		return el.dom.parentNode == target.dom;
	},

	renderAll: function(ct, target) {
		var items = ct.items.items;
		for (var i = 0, len = items.length; i < len; i++) {
			var c = items[i];
			if (c && (!c.rendered || !this.isValidParent(c, target))) {
				this.renderItem(c, i, target);
			}
		}
	},

	renderItem: function(c, position, target) {
		if (c && !c.rendered) {
			c.render(target, position);
			if (this.extraCls) {
				var t = c.getPositionEl ? c.getPositionEl() : c;
				t.addClass(this.extraCls);
			}
			if (this.renderHidden && c != this.activeItem) {
				c.hide();
			}
		} else if (c && !this.isValidParent(c, target)) {
			if (this.extraCls) {
				c.addClass(this.extraCls);
			}
			if (typeof position == 'number') {
				position = target.dom.childNodes[position];
			}
			target.dom.insertBefore(c.getEl().dom, position || null);
			if (this.renderHidden && c != this.activeItem) {
				c.hide();
			}
		}
	},

	onResize: function() {
		if (this.container.collapsed) {
			return;
		}
		var b = this.container.bufferResize;
		if (b) {
			if (!this.resizeTask) {
				this.resizeTask = new Ext.util.DelayedTask(this.layout, this);
				this.resizeBuffer = typeof b == 'number' ? b: 100;
			}
			this.resizeTask.delay(this.resizeBuffer);
		} else {
			this.layout();
		}
	},

	setContainer: function(ct) {
		if (this.monitorResize && ct != this.container) {
			if (this.container) {
				this.container.un('resize', this.onResize, this);
			}
			if (ct) {
				ct.on('resize', this.onResize, this);
			}
		}
		this.container = ct;
	},

	parseMargins: function(v) {
		var ms = v.split(' ');
		var len = ms.length;
		if (len == 1) {
			ms[1] = ms[0];
			ms[2] = ms[0];
			ms[3] = ms[0];
		}
		if (len == 2) {
			ms[2] = ms[0];
			ms[3] = ms[1];
		}
		return {
			top: parseInt(ms[0], 10) || 0,
			right: parseInt(ms[1], 10) || 0,
			bottom: parseInt(ms[2], 10) || 0,
			left: parseInt(ms[3], 10) || 0
		};
	},

	destroy: Ext.emptyFn
};
Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;

Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {

	monitorResize: true,

	onLayout: function(ct, target) {
		Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
		if (!this.container.collapsed) {
			this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getStyleSize());
		}
	},

	setItemSize: function(item, size) {
		if (item && size.height > 0) {
			item.setSize(size);
		}
	}
});
Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;

Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {

	deferredRender: false,

	renderHidden: true,

	setActiveItem: function(item) {
		item = this.container.getComponent(item);
		if (this.activeItem != item) {
			if (this.activeItem) {
				this.activeItem.hide();
			}
			this.activeItem = item;
			item.show();
			this.layout();
		}
	},

	renderAll: function(ct, target) {
		if (this.deferredRender) {
			this.renderItem(this.activeItem, undefined, target);
		} else {
			Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
		}
	}
});
Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;

Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {

	monitorResize: true,

	getAnchorViewSize: function(ct, target) {
		return target.dom == document.body ? target.getViewSize() : target.getStyleSize();
	},

	onLayout: function(ct, target) {
		Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);

		var size = this.getAnchorViewSize(ct, target);

		var w = size.width,
		h = size.height;

		if (w < 20 || h < 20) {
			return;
		}

		var aw,
		ah;
		if (ct.anchorSize) {
			if (typeof ct.anchorSize == 'number') {
				aw = ct.anchorSize;
			} else {
				aw = ct.anchorSize.width;
				ah = ct.anchorSize.height;
			}
		} else {
			aw = ct.initialConfig.width;
			ah = ct.initialConfig.height;
		}

		var cs = ct.items.items,
		len = cs.length,
		i,
		c,
		a,
		cw,
		ch;
		for (i = 0; i < len; i++) {
			c = cs[i];
			if (c.anchor) {
				a = c.anchorSpec;
				if (!a) {
					var vs = c.anchor.split(' ');
					c.anchorSpec = a = {
						right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
						bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
					};
				}
				cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
				ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;

				if (cw || ch) {
					c.setSize(cw || undefined, ch || undefined);
				}
			}
		}
	},

	parseAnchor: function(a, start, cstart) {
		if (a && a != 'none') {
			var last;
			if (/^(r|right|b|bottom)$/i.test(a)) {
				var diff = cstart - start;
				return function(v) {
					if (v !== last) {
						last = v;
						return v - diff;
					}
				}
			} else if (a.indexOf('%') != -1) {
				var ratio = parseFloat(a.replace('%', '')) * .01;
				return function(v) {
					if (v !== last) {
						last = v;
						return Math.floor(v * ratio);
					}
				}
			} else {
				a = parseInt(a, 10);
				if (!isNaN(a)) {
					return function(v) {
						if (v !== last) {
							last = v;
							return v + a;
						}
					}
				}
			}
		}
		return false;
	},

	adjustWidthAnchor: function(value, comp) {
		return value;
	},

	adjustHeightAnchor: function(value, comp) {
		return value;
	}

});
Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;

Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {

	monitorResize: true,

	extraCls: 'x-column',

	scrollOffset: 0,

	isValidParent: function(c, target) {
		return c.getEl().dom.parentNode == this.innerCt.dom;
	},

	onLayout: function(ct, target) {
		var cs = ct.items.items,
		len = cs.length,
		c,
		i;

		if (!this.innerCt) {
			target.addClass('x-column-layout-ct');

			this.innerCt = target.createChild({
				cls: 'x-column-inner'
			});
			this.innerCt.createChild({
				cls: 'x-clear'
			});
		}
		this.renderAll(ct, this.innerCt);

		var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();

		if (size.width < 1 && size.height < 1) {
			return;
		}

		var w = size.width - target.getPadding('lr') - this.scrollOffset,
		h = size.height - target.getPadding('tb'),
		pw = w;

		this.innerCt.setWidth(w);

		for (i = 0; i < len; i++) {
			c = cs[i];
			if (!c.columnWidth) {
				pw -= (c.getSize().width + c.getEl().getMargins('lr'));
			}
		}

		pw = pw < 0 ? 0: pw;

		for (i = 0; i < len; i++) {
			c = cs[i];
			if (c.columnWidth) {
				c.setSize(Math.floor(c.columnWidth * pw) - c.getEl().getMargins('lr'));
			}
		}
	}

});

Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;

Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
	monitorResize: true,
	rendered: false,

	onLayout: function(ct, target) {
		var collapsed;
		if (!this.rendered) {
			target.position();
			target.addClass('x-border-layout-ct');
			var items = ct.items.items;
			collapsed = [];
			for (var i = 0, len = items.length; i < len; i++) {
				var c = items[i];
				var pos = c.region;
				if (c.collapsed) {
					collapsed.push(c);
				}
				c.collapsed = false;
				if (!c.rendered) {
					c.cls = c.cls ? c.cls + ' x-border-panel': 'x-border-panel';
					c.render(target, i);
				}
				this[pos] = pos != 'center' && c.split ? new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) : new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
				this[pos].render(target, c);
			}
			this.rendered = true;
		}

		var size = target.getViewSize();
		if (size.width < 20 || size.height < 20) {
			if (collapsed) {
				this.restoreCollapsed = collapsed;
			}
			return;
		} else if (this.restoreCollapsed) {
			collapsed = this.restoreCollapsed;
			delete this.restoreCollapsed;
		}

		var w = size.width,
		h = size.height;
		var centerW = w,
		centerH = h,
		centerY = 0,
		centerX = 0;

		var n = this.north,
		s = this.south,
		west = this.west,
		e = this.east,
		c = this.center;
		if (!c) {
			throw 'No center region defined in BorderLayout ' + ct.id;
		}

		if (n && n.isVisible()) {
			var b = n.getSize();
			var m = n.getMargins();
			b.width = w - (m.left + m.right);
			b.x = m.left;
			b.y = m.top;
			centerY = b.height + b.y + m.bottom;
			centerH -= centerY;
			n.applyLayout(b);
		}
		if (s && s.isVisible()) {
			var b = s.getSize();
			var m = s.getMargins();
			b.width = w - (m.left + m.right);
			b.x = m.left;
			var totalHeight = (b.height + m.top + m.bottom);
			b.y = h - totalHeight + m.top;
			centerH -= totalHeight;
			s.applyLayout(b);
		}
		if (west && west.isVisible()) {
			var b = west.getSize();
			var m = west.getMargins();
			b.height = centerH - (m.top + m.bottom);
			b.x = m.left;
			b.y = centerY + m.top;
			var totalWidth = (b.width + m.left + m.right);
			centerX += totalWidth;
			centerW -= totalWidth;
			west.applyLayout(b);
		}
		if (e && e.isVisible()) {
			var b = e.getSize();
			var m = e.getMargins();
			b.height = centerH - (m.top + m.bottom);
			var totalWidth = (b.width + m.left + m.right);
			b.x = w - totalWidth + m.left;
			b.y = centerY + m.top;
			centerW -= totalWidth;
			e.applyLayout(b);
		}

		var m = c.getMargins();
		var centerBox = {
			x: centerX + m.left,
			y: centerY + m.top,
			width: centerW - (m.left + m.right),
			height: centerH - (m.top + m.bottom)
		};
		c.applyLayout(centerBox);

		if (collapsed) {
			for (var i = 0, len = collapsed.length; i < len; i++) {
				collapsed[i].collapse(false);
			}
		}

		if (Ext.isIE && Ext.isStrict) {
			target.repaint();
		}
	},

	destroy: function() {
		var r = ['north', 'south', 'east', 'west'];
		for (var i = 0; i < r.length; i++) {
			var region = this[r[i]];
			if (region && region.split) {
				region.split.destroy(true);
			}
		}
		Ext.layout.BorderLayout.superclass.destroy.call(this);
	}

});

Ext.layout.BorderLayout.Region = function(layout, config, pos) {
	Ext.apply(this, config);
	this.layout = layout;
	this.position = pos;
	this.state = {};
	if (typeof this.margins == 'string') {
		this.margins = this.layout.parseMargins(this.margins);
	}
	this.margins = Ext.applyIf(this.margins || {},
	this.defaultMargins);
	if (this.collapsible) {
		if (typeof this.cmargins == 'string') {
			this.cmargins = this.layout.parseMargins(this.cmargins);
		}
		if (this.collapseMode == 'mini' && !this.cmargins) {
			this.cmargins = {
				left: 0,
				top: 0,
				right: 0,
				bottom: 0
			};
		} else {
			this.cmargins = Ext.applyIf(this.cmargins || {},
			pos == 'north' || pos == 'south' ? this.defaultNSCMargins: this.defaultEWCMargins);
		}
	}
};

Ext.layout.BorderLayout.Region.prototype = {

	collapsible: false,

	split: false,

	floatable: true,

	minWidth: 50,

	minHeight: 50,

	defaultMargins: {
		left: 0,
		top: 0,
		right: 0,
		bottom: 0
	},
	defaultNSCMargins: {
		left: 5,
		top: 5,
		right: 5,
		bottom: 5
	},
	defaultEWCMargins: {
		left: 5,
		top: 0,
		right: 5,
		bottom: 0
	},

	isCollapsed: false,

	render: function(ct, p) {
		this.panel = p;
		p.el.enableDisplayMode();
		this.targetEl = ct;
		this.el = p.el;

		var gs = p.getState,
		ps = this.position;
		p.getState = function() {
			return Ext.apply(gs.call(p) || {},
			this.state);
		}.createDelegate(this);

		if (ps != 'center') {
			p.allowQueuedExpand = false;
			p.on({
				beforecollapse: this.beforeCollapse,
				collapse: this.onCollapse,
				beforeexpand: this.beforeExpand,
				expand: this.onExpand,
				hide: this.onHide,
				show: this.onShow,
				scope: this
			});
			if (this.collapsible) {
				p.collapseEl = 'el';
				p.slideAnchor = this.getSlideAnchor();
			}
			if (p.tools && p.tools.toggle) {
				p.tools.toggle.addClass('x-tool-collapse-' + ps);
				p.tools.toggle.addClassOnOver('x-tool-collapse-' + ps + '-over');
			}
		}
	},

	getCollapsedEl: function() {
		if (!this.collapsedEl) {
			if (!this.toolTemplate) {
				var tt = new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');
				tt.disableFormats = true;
				tt.compile();
				Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
			}
			this.collapsedEl = this.targetEl.createChild({
				cls: "x-layout-collapsed x-layout-collapsed-" + this.position,
				id: this.panel.id + '-xcollapsed'
			});
			this.collapsedEl.enableDisplayMode('block');

			if (this.collapseMode == 'mini') {
				this.collapsedEl.addClass('x-layout-cmini-' + this.position);
				this.miniCollapsedEl = this.collapsedEl.createChild({
					cls: "x-layout-mini x-layout-mini-" + this.position,
					html: "&#160;"
				});
				this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
				this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
				this.collapsedEl.on('click', this.onExpandClick, this, {
					stopEvent: true
				});
			} else {
				var t = this.toolTemplate.append(this.collapsedEl.dom, {
					id: 'expand-' + this.position
				},
				true);
				t.addClassOnOver('x-tool-expand-' + this.position + '-over');
				t.on('click', this.onExpandClick, this, {
					stopEvent: true
				});

				if (this.floatable !== false) {
					this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
					this.collapsedEl.on("click", this.collapseClick, this);
				}
			}
		}
		return this.collapsedEl;
	},

	onExpandClick: function(e) {
		if (this.isSlid) {
			this.afterSlideIn();
			this.panel.expand(false);
		} else {
			this.panel.expand();
		}
	},

	onCollapseClick: function(e) {
		this.panel.collapse();
	},

	beforeCollapse: function(p, animate) {
		this.lastAnim = animate;
		if (this.splitEl) {
			this.splitEl.hide();
		}
		this.getCollapsedEl().show();
		this.panel.el.setStyle('z-index', 100);
		this.isCollapsed = true;
		this.layout.layout();
	},

	onCollapse: function(animate) {
		this.panel.el.setStyle('z-index', 1);
		if (this.lastAnim === false || this.panel.animCollapse === false) {
			this.getCollapsedEl().dom.style.visibility = 'visible';
		} else {
			this.getCollapsedEl().slideIn(this.panel.slideAnchor, {
				duration: .2
			});
		}
		this.state.collapsed = true;
		this.panel.saveState();
	},

	beforeExpand: function(animate) {
		var c = this.getCollapsedEl();
		this.el.show();
		if (this.position == 'east' || this.position == 'west') {
			this.panel.setSize(undefined, c.getHeight());
		} else {
			this.panel.setSize(c.getWidth(), undefined);
		}
		c.hide();
		c.dom.style.visibility = 'hidden';
		this.panel.el.setStyle('z-index', 100);
	},

	onExpand: function() {
		this.isCollapsed = false;
		if (this.splitEl) {
			this.splitEl.show();
		}
		this.layout.layout();
		this.panel.el.setStyle('z-index', 1);
		this.state.collapsed = false;
		this.panel.saveState();
	},

	collapseClick: function(e) {
		if (this.isSlid) {
			e.stopPropagation();
			this.slideIn();
		} else {
			e.stopPropagation();
			this.slideOut();
		}
	},

	onHide: function() {
		if (this.isCollapsed) {
			this.getCollapsedEl().hide();
		} else if (this.splitEl) {
			this.splitEl.hide();
		}
	},

	onShow: function() {
		if (this.isCollapsed) {
			this.getCollapsedEl().show();
		} else if (this.splitEl) {
			this.splitEl.show();
		}
	},

	isVisible: function() {
		return ! this.panel.hidden;
	},

	getMargins: function() {
		return this.isCollapsed && this.cmargins ? this.cmargins: this.margins;
	},

	getSize: function() {
		return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
	},

	setPanel: function(panel) {
		this.panel = panel;
	},

	getMinWidth: function() {
		return this.minWidth;
	},

	getMinHeight: function() {
		return this.minHeight;
	},

	applyLayoutCollapsed: function(box) {
		var ce = this.getCollapsedEl();
		ce.setLeftTop(box.x, box.y);
		ce.setSize(box.width, box.height);
	},

	applyLayout: function(box) {
		if (this.isCollapsed) {
			this.applyLayoutCollapsed(box);
		} else {
			this.panel.setPosition(box.x, box.y);
			this.panel.setSize(box.width, box.height);
		}
	},

	beforeSlide: function() {
		this.panel.beforeEffect();
	},

	afterSlide: function() {
		this.panel.afterEffect();
	},

	initAutoHide: function() {
		if (this.autoHide !== false) {
			if (!this.autoHideHd) {
				var st = new Ext.util.DelayedTask(this.slideIn, this);
				this.autoHideHd = {
					"mouseout": function(e) {
						if (!e.within(this.el, true)) {
							st.delay(500);
						}
					},
					"mouseover": function(e) {
						st.cancel();
					},
					scope: this
				};
			}
			this.el.on(this.autoHideHd);
		}
	},

	clearAutoHide: function() {
		if (this.autoHide !== false) {
			this.el.un("mouseout", this.autoHideHd.mouseout);
			this.el.un("mouseover", this.autoHideHd.mouseover);
		}
	},

	clearMonitor: function() {
		Ext.getDoc().un("click", this.slideInIf, this);
	},

	slideOut: function() {
		if (this.isSlid || this.el.hasActiveFx()) {
			return;
		}
		this.isSlid = true;
		var ts = this.panel.tools;
		if (ts && ts.toggle) {
			ts.toggle.hide();
		}
		this.el.show();
		if (this.position == 'east' || this.position == 'west') {
			this.panel.setSize(undefined, this.collapsedEl.getHeight());
		} else {
			this.panel.setSize(this.collapsedEl.getWidth(), undefined);
		}
		this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
		this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
		this.el.setStyle("z-index", 102);
		if (this.animFloat !== false) {
			this.beforeSlide();
			this.el.slideIn(this.getSlideAnchor(), {
				callback: function() {
					this.afterSlide();
					this.initAutoHide();
					Ext.getDoc().on("click", this.slideInIf, this);
				},
				scope: this,
				block: true
			});
		} else {
			this.initAutoHide();
			Ext.getDoc().on("click", this.slideInIf, this);
		}
	},

	afterSlideIn: function() {
		this.clearAutoHide();
		this.isSlid = false;
		this.clearMonitor();
		this.el.setStyle("z-index", "");
		this.el.dom.style.left = this.restoreLT[0];
		this.el.dom.style.top = this.restoreLT[1];

		var ts = this.panel.tools;
		if (ts && ts.toggle) {
			ts.toggle.show();
		}
	},

	slideIn: function(cb) {
		if (!this.isSlid || this.el.hasActiveFx()) {
			Ext.callback(cb);
			return;
		}
		this.isSlid = false;
		if (this.animFloat !== false) {
			this.beforeSlide();
			this.el.slideOut(this.getSlideAnchor(), {
				callback: function() {
					this.el.hide();
					this.afterSlide();
					this.afterSlideIn();
					Ext.callback(cb);
				},
				scope: this,
				block: true
			});
		} else {
			this.el.hide();
			this.afterSlideIn();
		}
	},

	slideInIf: function(e) {
		if (!e.within(this.el)) {
			this.slideIn();
		}
	},

	anchors: {
		"west": "left",
		"east": "right",
		"north": "top",
		"south": "bottom"
	},

	sanchors: {
		"west": "l",
		"east": "r",
		"north": "t",
		"south": "b"
	},

	canchors: {
		"west": "tl-tr",
		"east": "tr-tl",
		"north": "tl-bl",
		"south": "bl-tl"
	},

	getAnchor: function() {
		return this.anchors[this.position];
	},

	getCollapseAnchor: function() {
		return this.canchors[this.position];
	},

	getSlideAnchor: function() {
		return this.sanchors[this.position];
	},

	getAlignAdj: function() {
		var cm = this.cmargins;
		switch (this.position) {
		case "west":
			return [0, 0];
			break;
		case "east":
			return [0, 0];
			break;
		case "north":
			return [0, 0];
			break;
		case "south":
			return [0, 0];
			break;
		}
	},

	getExpandAdj: function() {
		var c = this.collapsedEl,
		cm = this.cmargins;
		switch (this.position) {
		case "west":
			return [ - (cm.right + c.getWidth() + cm.left), 0];
			break;
		case "east":
			return [cm.right + c.getWidth() + cm.left, 0];
			break;
		case "north":
			return [0, -(cm.top + cm.bottom + c.getHeight())];
			break;
		case "south":
			return [0, cm.top + cm.bottom + c.getHeight()];
			break;
		}
	}
};

Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos) {
	Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
	this.applyLayout = this.applyFns[pos];
};

Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {

	splitTip: "Drag to resize.",

	collapsibleSplitTip: "Drag to resize. Double click to hide.",

	useSplitTips: false,

	splitSettings: {
		north: {
			orientation: Ext.SplitBar.VERTICAL,
			placement: Ext.SplitBar.TOP,
			maxFn: 'getVMaxSize',
			minProp: 'minHeight',
			maxProp: 'maxHeight'
		},
		south: {
			orientation: Ext.SplitBar.VERTICAL,
			placement: Ext.SplitBar.BOTTOM,
			maxFn: 'getVMaxSize',
			minProp: 'minHeight',
			maxProp: 'maxHeight'
		},
		east: {
			orientation: Ext.SplitBar.HORIZONTAL,
			placement: Ext.SplitBar.RIGHT,
			maxFn: 'getHMaxSize',
			minProp: 'minWidth',
			maxProp: 'maxWidth'
		},
		west: {
			orientation: Ext.SplitBar.HORIZONTAL,
			placement: Ext.SplitBar.LEFT,
			maxFn: 'getHMaxSize',
			minProp: 'minWidth',
			maxProp: 'maxWidth'
		}
	},

	applyFns: {
		west: function(box) {
			if (this.isCollapsed) {
				return this.applyLayoutCollapsed(box);
			}
			var sd = this.splitEl.dom,
			s = sd.style;
			this.panel.setPosition(box.x, box.y);
			var sw = sd.offsetWidth;
			s.left = (box.x + box.width - sw) + 'px';
			s.top = (box.y) + 'px';
			s.height = Math.max(0, box.height) + 'px';
			this.panel.setSize(box.width - sw, box.height);
		},
		east: function(box) {
			if (this.isCollapsed) {
				return this.applyLayoutCollapsed(box);
			}
			var sd = this.splitEl.dom,
			s = sd.style;
			var sw = sd.offsetWidth;
			this.panel.setPosition(box.x + sw, box.y);
			s.left = (box.x) + 'px';
			s.top = (box.y) + 'px';
			s.height = Math.max(0, box.height) + 'px';
			this.panel.setSize(box.width - sw, box.height);
		},
		north: function(box) {
			if (this.isCollapsed) {
				return this.applyLayoutCollapsed(box);
			}
			var sd = this.splitEl.dom,
			s = sd.style;
			var sh = sd.offsetHeight;
			this.panel.setPosition(box.x, box.y);
			s.left = (box.x) + 'px';
			s.top = (box.y + box.height - sh) + 'px';
			s.width = Math.max(0, box.width) + 'px';
			this.panel.setSize(box.width, box.height - sh);
		},
		south: function(box) {
			if (this.isCollapsed) {
				return this.applyLayoutCollapsed(box);
			}
			var sd = this.splitEl.dom,
			s = sd.style;
			var sh = sd.offsetHeight;
			this.panel.setPosition(box.x, box.y + sh);
			s.left = (box.x) + 'px';
			s.top = (box.y) + 'px';
			s.width = Math.max(0, box.width) + 'px';
			this.panel.setSize(box.width, box.height - sh);
		}
	},

	render: function(ct, p) {
		Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);

		var ps = this.position;

		this.splitEl = ct.createChild({
			cls: "x-layout-split x-layout-split-" + ps,
			html: "&#160;",
			id: this.panel.id + '-xsplit'
		});

		if (this.collapseMode == 'mini') {
			this.miniSplitEl = this.splitEl.createChild({
				cls: "x-layout-mini x-layout-mini-" + ps,
				html: "&#160;"
			});
			this.miniSplitEl.addClassOnOver('x-layout-mini-over');
			this.miniSplitEl.on('click', this.onCollapseClick, this, {
				stopEvent: true
			});
		}

		var s = this.splitSettings[ps];

		this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
		this.split.placement = s.placement;
		this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
		this.split.minSize = this.minSize || this[s.minProp];
		this.split.on("beforeapply", this.onSplitMove, this);
		this.split.useShim = this.useShim === true;
		this.maxSize = this.maxSize || this[s.maxProp];

		if (p.hidden) {
			this.splitEl.hide();
		}

		if (this.useSplitTips) {
			this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip: this.splitTip;
		}
		if (this.collapsible) {
			this.splitEl.on("dblclick", this.onCollapseClick, this);
		}
	},

	getSize: function() {
		if (this.isCollapsed) {
			return this.collapsedEl.getSize();
		}
		var s = this.panel.getSize();
		if (this.position == 'north' || this.position == 'south') {
			s.height += this.splitEl.dom.offsetHeight;
		} else {
			s.width += this.splitEl.dom.offsetWidth;
		}
		return s;
	},

	getHMaxSize: function() {
		var cmax = this.maxSize || 10000;
		var center = this.layout.center;
		return Math.min(cmax, (this.el.getWidth() + center.el.getWidth()) - center.getMinWidth());
	},

	getVMaxSize: function() {
		var cmax = this.maxSize || 10000;
		var center = this.layout.center;
		return Math.min(cmax, (this.el.getHeight() + center.el.getHeight()) - center.getMinHeight());
	},

	onSplitMove: function(split, newSize) {
		var s = this.panel.getSize();
		this.lastSplitSize = newSize;
		if (this.position == 'north' || this.position == 'south') {
			this.panel.setSize(s.width, newSize);
			this.state.height = newSize;
		} else {
			this.panel.setSize(newSize, s.height);
			this.state.width = newSize;
		}
		this.layout.layout();
		this.panel.saveState();
		return false;
	},

	getSplitBar: function() {
		return this.split;
	}
});

Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;

Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {

	labelSeparator: ':',

	getAnchorViewSize: function(ct, target) {
		return ct.body.getStyleSize();
	},

	setContainer: function(ct) {
		Ext.layout.FormLayout.superclass.setContainer.call(this, ct);

		if (ct.labelAlign) {
			ct.addClass('x-form-label-' + ct.labelAlign);
		}

		if (ct.hideLabels) {
			this.labelStyle = "display:none";
			this.elementStyle = "padding-left:0;";
			this.labelAdjust = 0;
		} else {
			this.labelSeparator = ct.labelSeparator || this.labelSeparator;
			ct.labelWidth = ct.labelWidth || 100;
			if (typeof ct.labelWidth == 'number') {
				var pad = (typeof ct.labelPad == 'number' ? ct.labelPad: 5);
				this.labelAdjust = ct.labelWidth + pad;
				this.labelStyle = "width:" + ct.labelWidth + "px;";
				this.elementStyle = "padding-left:" + (ct.labelWidth + pad) + 'px';
			}
			if (ct.labelAlign == 'top') {
				this.labelStyle = "width:auto;";
				this.labelAdjust = 0;
				this.elementStyle = "padding-left:0;";
			}
		}

		if (!this.fieldTpl) {
			var t = new Ext.Template('<div class="x-form-item {5}" tabIndex="-1">', '<label for="{0}" style="{2}" class="x-form-item-label">{1}{4}</label>', '<div class="x-form-element" id="x-form-el-{0}" style="{3}">', '</div><div class="{6}"></div>', '</div>');
			t.disableFormats = true;
			t.compile();
			Ext.layout.FormLayout.prototype.fieldTpl = t;
		}
	},

	renderItem: function(c, position, target) {
		if (c && !c.rendered && c.isFormField && c.inputType != 'hidden') {
			var args = [c.id, c.fieldLabel, c.labelStyle || this.labelStyle || '', this.elementStyle || '', typeof c.labelSeparator == 'undefined' ? this.labelSeparator: c.labelSeparator, (c.itemCls || this.container.itemCls || '') + (c.hideLabel ? ' x-hide-label': ''), c.clearCls || 'x-form-clear-left'];
			if (typeof position == 'number') {
				position = target.dom.childNodes[position] || null;
			}
			if (position) {
				this.fieldTpl.insertBefore(position, args);
			} else {
				this.fieldTpl.append(target, args);
			}
			c.render('x-form-el-' + c.id);
		} else {
			Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
		}
	},

	adjustWidthAnchor: function(value, comp) {
		return value - (comp.isFormField ? (comp.hideLabel ? 0: this.labelAdjust) : 0);
	},

	isValidParent: function(c, target) {
		return true;
	}

});

Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;

Ext.layout.Accordion = Ext.extend(Ext.layout.FitLayout, {

	fill: true,

	autoWidth: true,

	titleCollapse: true,

	hideCollapseTool: false,

	collapseFirst: false,

	animate: false,

	sequence: false,

	activeOnTop: false,

	renderItem: function(c) {
		if (this.animate === false) {
			c.animCollapse = false;
		}
		c.collapsible = true;
		if (this.autoWidth) {
			c.autoWidth = true;
		}
		if (this.titleCollapse) {
			c.titleCollapse = true;
		}
		if (this.hideCollapseTool) {
			c.hideCollapseTool = true;
		}
		if (this.collapseFirst !== undefined) {
			c.collapseFirst = this.collapseFirst;
		}
		if (!this.activeItem && !c.collapsed) {
			this.activeItem = c;
		} else if (this.activeItem) {
			c.collapsed = true;
		}
		Ext.layout.Accordion.superclass.renderItem.apply(this, arguments);
		c.header.addClass('x-accordion-hd');
		c.on('beforeexpand', this.beforeExpand, this);
	},

	beforeExpand: function(p, anim) {
		var ai = this.activeItem;
		if (ai) {
			if (this.sequence) {
				delete this.activeItem;
				if (!ai.collapsed) {
					ai.collapse({
						callback: function() {
							p.expand(anim || true);
						},
						scope: this
					});
					return false;
				}
			} else {
				ai.collapse(this.animate);
			}
		}
		this.activeItem = p;
		if (this.activeOnTop) {
			p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
		}
		this.layout();
	},

	setItemSize: function(item, size) {
		if (this.fill && item) {
			var items = this.container.items.items;
			var hh = 0;
			for (var i = 0, len = items.length; i < len; i++) {
				var p = items[i];
				if (p != item) {
					hh += (p.getSize().height - p.bwrap.getHeight());
				}
			}
			size.height -= hh;
			item.setSize(size);
		}
	}
});
Ext.Container.LAYOUTS['accordion'] = Ext.layout.Accordion;

Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {

	monitorResize: false,

	setContainer: function(ct) {
		Ext.layout.TableLayout.superclass.setContainer.call(this, ct);

		this.currentRow = 0;
		this.currentColumn = 0;
		this.cells = [];
	},

	onLayout: function(ct, target) {
		var cs = ct.items.items,
		len = cs.length,
		c,
		i;

		if (!this.table) {
			target.addClass('x-table-layout-ct');

			this.table = target.createChild({
				tag: 'table',
				cls: 'x-table-layout',
				cellspacing: 0,
				cn: {
					tag: 'tbody'
				}
			},
			null, true);

			this.renderAll(ct, target);
		}
	},

	getRow: function(index) {
		var row = this.table.tBodies[0].childNodes[index];
		if (!row) {
			row = document.createElement('tr');
			this.table.tBodies[0].appendChild(row);
		}
		return row;
	},

	getNextCell: function(c) {
		var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
		var curCol = this.currentColumn = cell[0],
		curRow = this.currentRow = cell[1];
		for (var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++) {
			if (!this.cells[rowIndex]) {
				this.cells[rowIndex] = [];
			}
			for (var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++) {
				this.cells[rowIndex][colIndex] = true;
			}
		}
		var td = document.createElement('td');
		if (c.cellId) {
			td.id = c.cellId;
		}
		var cls = 'x-table-layout-cell';
		if (c.cellCls) {
			cls += ' ' + c.cellCls;
		}
		td.className = cls;
		if (c.colspan) {
			td.colSpan = c.colspan;
		}
		if (c.rowspan) {
			td.rowSpan = c.rowspan;
		}
		this.getRow(curRow).appendChild(td);
		return td;
	},

	getNextNonSpan: function(colIndex, rowIndex) {
		var cols = this.columns;
		while ((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
			if (cols && colIndex >= cols) {
				rowIndex++;
				colIndex = 0;
			} else {
				colIndex++;
			}
		}
		return [colIndex, rowIndex];
	},

	renderItem: function(c, position, target) {
		if (c && !c.rendered) {
			c.render(this.getNextCell(c));
		}
	},

	isValidParent: function(c, target) {
		return true;
	}

});

Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;

Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
	extraCls: 'x-abs-layout-item',
	isForm: false,

	setContainer: function(ct) {
		Ext.layout.AbsoluteLayout.superclass.setContainer.call(this, ct);
		if (ct.isXType('form')) {
			this.isForm = true;
		}
	},

	onLayout: function(ct, target) {
		if (this.isForm) {
			ct.body.position();
		} else {
			target.position();
		}
		Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
	},

	getAnchorViewSize: function(ct, target) {
		return this.isForm ? ct.body.getStyleSize() : Ext.layout.AbsoluteLayout.superclass.getAnchorViewSize.call(this, ct, target);
	},

	isValidParent: function(c, target) {
		return this.isForm ? true: Ext.layout.AbsoluteLayout.superclass.isValidParent.call(this, c, target);
	},

	adjustWidthAnchor: function(value, comp) {
		return value ? value - comp.getPosition(true)[0] : value;
	},

	adjustHeightAnchor: function(value, comp) {
		return value ? value - comp.getPosition(true)[1] : value;
	}

});
Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;

Ext.Viewport = Ext.extend(Ext.Container, {

	initComponent: function() {
		Ext.Viewport.superclass.initComponent.call(this);
		document.getElementsByTagName('html')[0].className += ' x-viewport';
		this.el = Ext.getBody();
		this.el.setHeight = Ext.emptyFn;
		this.el.setWidth = Ext.emptyFn;
		this.el.setSize = Ext.emptyFn;
		this.el.dom.scroll = 'no';
		this.allowDomMove = false;
		this.autoWidth = true;
		this.autoHeight = true;
		Ext.EventManager.onWindowResize(this.fireResize, this);
		this.renderTo = this.el;
	},

	fireResize: function(w, h) {
		this.fireEvent('resize', this, w, h, w, h);
	}
});
Ext.reg('viewport', Ext.Viewport);

Ext.Panel = Ext.extend(Ext.Container, {

	baseCls: 'x-panel',

	collapsedCls: 'x-panel-collapsed',

	maskDisabled: true,

	animCollapse: Ext.enableFx,

	headerAsText: true,

	buttonAlign: 'right',

	collapsed: false,

	collapseFirst: true,

	minButtonWidth: 75,

	elements: 'body',

	toolTarget: 'header',
	collapseEl: 'bwrap',
	slideAnchor: 't',
	disabledClass: '',

	deferHeight: true,
	expandDefaults: {
		duration: .25
	},
	collapseDefaults: {
		duration: .25
	},

	initComponent: function() {
		Ext.Panel.superclass.initComponent.call(this);

		this.addEvents(
		'bodyresize',
		'titlechange',
		'collapse',
		'expand',
		'beforecollapse',
		'beforeexpand',
		'beforeclose',
		'close',
		'activate',
		'deactivate');

		if (this.tbar) {
			this.elements += ',tbar';
			if (typeof this.tbar == 'object') {
				this.topToolbar = this.tbar;
			}
			delete this.tbar;
		}
		if (this.bbar) {
			this.elements += ',bbar';
			if (typeof this.bbar == 'object') {
				this.bottomToolbar = this.bbar;
			}
			delete this.bbar;
		}

		if (this.header === true) {
			this.elements += ',header';
			delete this.header;
		} else if (this.title && this.header !== false) {
			this.elements += ',header';
		}

		if (this.footer === true) {
			this.elements += ',footer';
			delete this.footer;
		}

		if (this.buttons) {
			var btns = this.buttons;

			this.buttons = [];
			for (var i = 0, len = btns.length; i < len; i++) {
				if (btns[i].render) {
					btns[i].ownerCt = this;
					this.buttons.push(btns[i]);
				} else {
					this.addButton(btns[i]);
				}
			}
		}
		if (this.autoLoad) {
			this.on('render', this.doAutoLoad, this, {
				delay: 10
			});
		}
	},

	createElement: function(name, pnode) {
		if (this[name]) {
			pnode.appendChild(this[name].dom);
			return;
		}

		if (name === 'bwrap' || this.elements.indexOf(name) != -1) {
			if (this[name + 'Cfg']) {
				this[name] = Ext.fly(pnode).createChild(this[name + 'Cfg']);
			} else {
				var el = document.createElement('div');
				el.className = this[name + 'Cls'];
				this[name] = Ext.get(pnode.appendChild(el));
			}
		}
	},

	onRender: function(ct, position) {
		Ext.Panel.superclass.onRender.call(this, ct, position);

		this.createClasses();

		if (this.el) {
			this.el.addClass(this.baseCls);
			this.header = this.el.down('.' + this.headerCls);
			this.bwrap = this.el.down('.' + this.bwrapCls);
			var cp = this.bwrap ? this.bwrap: this.el;
			this.tbar = cp.down('.' + this.tbarCls);
			this.body = cp.down('.' + this.bodyCls);
			this.bbar = cp.down('.' + this.bbarCls);
			this.footer = cp.down('.' + this.footerCls);
			this.fromMarkup = true;
		} else {
			this.el = ct.createChild({
				id: this.id,
				cls: this.baseCls
			},
			position);
		}
		var el = this.el,
		d = el.dom;

		if (this.cls) {
			this.el.addClass(this.cls);
		}

		if (this.buttons) {
			this.elements += ',footer';
		}

		if (this.frame) {
			el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));

			this.createElement('header', d.firstChild.firstChild.firstChild);
			this.createElement('bwrap', d);

			var bw = this.bwrap.dom;
			var ml = d.childNodes[1],
			bl = d.childNodes[2];
			bw.appendChild(ml);
			bw.appendChild(bl);

			var mc = bw.firstChild.firstChild.firstChild;
			this.createElement('tbar', mc);
			this.createElement('body', mc);
			this.createElement('bbar', mc);
			this.createElement('footer', bw.lastChild.firstChild.firstChild);

			if (!this.footer) {
				this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
			}
		} else {
			this.createElement('header', d);
			this.createElement('bwrap', d);

			var bw = this.bwrap.dom;
			this.createElement('tbar', bw);
			this.createElement('body', bw);
			this.createElement('bbar', bw);
			this.createElement('footer', bw);

			if (!this.header) {
				this.body.addClass(this.bodyCls + '-noheader');
				if (this.tbar) {
					this.tbar.addClass(this.tbarCls + '-noheader');
				}
			}
		}

		if (this.border === false) {
			this.el.addClass(this.baseCls + '-noborder');
			this.body.addClass(this.bodyCls + '-noborder');
			if (this.header) {
				this.header.addClass(this.headerCls + '-noborder');
			}
			if (this.footer) {
				this.footer.addClass(this.footerCls + '-noborder');
			}
			if (this.tbar) {
				this.tbar.addClass(this.tbarCls + '-noborder');
			}
			if (this.bbar) {
				this.bbar.addClass(this.bbarCls + '-noborder');
			}
		}

		if (this.bodyBorder === false) {
			this.body.addClass(this.bodyCls + '-noborder');
		}

		if (this.bodyStyle) {
			this.body.applyStyles(this.bodyStyle);
		}

		this.bwrap.enableDisplayMode('block');

		if (this.header) {
			this.header.unselectable();

			if (this.headerAsText) {
				this.header.dom.innerHTML = '<span class="' + this.headerTextCls + '">' + this.header.dom.innerHTML + '</span>';

				if (this.iconCls) {
					this.setIconClass(this.iconCls);
				}
			}
		}

		if (this.floating) {
			this.makeFloating(this.floating);
		}

		if (this.collapsible) {
			this.tools = this.tools ? this.tools.slice(0) : [];
			if (!this.hideCollapseTool) {
				this.tools[this.collapseFirst ? 'unshift': 'push']({
					id: 'toggle',
					handler: this.toggleCollapse,
					scope: this
				});
			}
			if (this.titleCollapse && this.header) {
				this.header.on('click', this.toggleCollapse, this);
				this.header.setStyle('cursor', 'pointer');
			}
		}
		if (this.tools) {
			var ts = this.tools;
			this.tools = {};
			this.addTool.apply(this, ts);
		} else {
			this.tools = {};
		}

		if (this.buttons && this.buttons.length > 0) {
			var tb = this.footer.createChild({
				cls: 'x-panel-btns-ct',
				cn: {
					cls: "x-panel-btns x-panel-btns-" + this.buttonAlign,
					html: '<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
				}
			},
			null, true);
			var tr = tb.getElementsByTagName('tr')[0];
			for (var i = 0, len = this.buttons.length; i < len; i++) {
				var b = this.buttons[i];
				var td = document.createElement('td');
				td.className = 'x-panel-btn-td';
				b.render(tr.appendChild(td));
			}
		}

		if (this.tbar && this.topToolbar) {
			if (Ext.isArray(this.topToolbar)) {
				this.topToolbar = new Ext.Toolbar(this.topToolbar);
			}
			this.topToolbar.render(this.tbar);
			this.topToolbar.ownerCt = this;
		}
		if (this.bbar && this.bottomToolbar) {
			if (Ext.isArray(this.bottomToolbar)) {
				this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
			}
			this.bottomToolbar.render(this.bbar);
			this.bottomToolbar.ownerCt = this;
		}
	},

	setIconClass: function(cls) {
		var old = this.iconCls;
		this.iconCls = cls;
		if (this.rendered && this.header) {
			if (this.frame) {
				this.header.addClass('x-panel-icon');
				this.header.replaceClass(old, this.iconCls);
			} else {
				var hd = this.header.dom;
				var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild: null;
				if (img) {
					Ext.fly(img).replaceClass(old, this.iconCls);
				} else {
					Ext.DomHelper.insertBefore(hd.firstChild, {
						tag: 'img',
						src: Ext.BLANK_IMAGE_URL,
						cls: 'x-panel-inline-icon ' + this.iconCls
					});
				}
			}
		}
	},

	makeFloating: function(cfg) {
		this.floating = true;
		this.el = new Ext.Layer(typeof cfg == 'object' ? cfg: {
			shadow: this.shadow !== undefined ? this.shadow: 'sides',
			shadowOffset: this.shadowOffset,
			constrain: false,
			shim: this.shim === false ? false: undefined
		},
		this.el);
	},

	getTopToolbar: function() {
		return this.topToolbar;
	},

	getBottomToolbar: function() {
		return this.bottomToolbar;
	},

	addButton: function(config, handler, scope) {
		var bc = {
			handler: handler,
			scope: scope,
			minWidth: this.minButtonWidth,
			hideParent: true
		};
		if (typeof config == "string") {
			bc.text = config;
		} else {
			Ext.apply(bc, config);
		}
		var btn = new Ext.Button(bc);
		btn.ownerCt = this;
		if (!this.buttons) {
			this.buttons = [];
		}
		this.buttons.push(btn);
		return btn;
	},

	addTool: function() {
		if (!this[this.toolTarget]) {
			return;
		}
		if (!this.toolTemplate) {
			var tt = new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>');
			tt.disableFormats = true;
			tt.compile();
			Ext.Panel.prototype.toolTemplate = tt;
		}
		for (var i = 0, a = arguments, len = a.length; i < len; i++) {
			var tc = a[i],
			overCls = 'x-tool-' + tc.id + '-over';
			var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
			this.tools[tc.id] = t;
			t.enableDisplayMode('block');
			t.on('click', this.createToolHandler(t, tc, overCls, this));
			if (tc.on) {
				t.on(tc.on);
			}
			if (tc.hidden) {
				t.hide();
			}
			if (tc.qtip) {
				if (typeof tc.qtip == 'object') {
					Ext.QuickTips.register(Ext.apply({
						target: t.id
					},
					tc.qtip));
				} else {
					t.dom.qtip = tc.qtip;
				}
			}
			t.addClassOnOver(overCls);
		}
	},

	onShow: function() {
		if (this.floating) {
			return this.el.show();
		}
		Ext.Panel.superclass.onShow.call(this);
	},

	onHide: function() {
		if (this.floating) {
			return this.el.hide();
		}
		Ext.Panel.superclass.onHide.call(this);
	},

	createToolHandler: function(t, tc, overCls, panel) {
		return function(e) {
			t.removeClass(overCls);
			e.stopEvent();
			if (tc.handler) {
				tc.handler.call(tc.scope || t, e, t, panel);
			}
		};
	},

	afterRender: function() {
		if (this.fromMarkup && this.height === undefined && !this.autoHeight) {
			this.height = this.el.getHeight();
		}
		if (this.floating && !this.hidden && !this.initHidden) {
			this.el.show();
		}
		if (this.title) {
			this.setTitle(this.title);
		}
		this.setAutoScroll();
		if (this.html) {
			this.body.update(typeof this.html == 'object' ? Ext.DomHelper.markup(this.html) : this.html);
			delete this.html;
		}
		if (this.contentEl) {
			var ce = Ext.getDom(this.contentEl);
			Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
			this.body.dom.appendChild(ce);
		}
		if (this.collapsed) {
			this.collapsed = false;
			this.collapse(false);
		}
		Ext.Panel.superclass.afterRender.call(this);
		this.initEvents();
	},

	setAutoScroll: function() {
		if (this.rendered && this.autoScroll) {
			var el = this.body || this.el;
			if (el) {
				el.setOverflow('auto');
			}
		}
	},

	getKeyMap: function() {
		if (!this.keyMap) {
			this.keyMap = new Ext.KeyMap(this.el, this.keys);
		}
		return this.keyMap;
	},

	initEvents: function() {
		if (this.keys) {
			this.getKeyMap();
		}
		if (this.draggable) {
			this.initDraggable();
		}
	},

	initDraggable: function() {

		this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null: this.draggable);
	},

	beforeEffect: function() {
		if (this.floating) {
			this.el.beforeAction();
		}
		this.el.addClass('x-panel-animated');
	},

	afterEffect: function() {
		this.syncShadow();
		this.el.removeClass('x-panel-animated');
	},

	createEffect: function(a, cb, scope) {
		var o = {
			scope: scope,
			block: true
		};
		if (a === true) {
			o.callback = cb;
			return o;
		} else if (!a.callback) {
			o.callback = cb;
		} else {
			o.callback = function() {
				cb.call(scope);
				Ext.callback(a.callback, a.scope);
			};
		}
		return Ext.applyIf(o, a);
	},

	collapse: function(animate) {
		if (this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false) {
			return;
		}
		var doAnim = animate === true || (animate !== false && this.animCollapse);
		this.beforeEffect();
		this.onCollapse(doAnim, animate);
		return this;
	},

	onCollapse: function(doAnim, animArg) {
		if (doAnim) {
			this[this.collapseEl].slideOut(this.slideAnchor, Ext.apply(this.createEffect(animArg || true, this.afterCollapse, this), this.collapseDefaults));
		} else {
			this[this.collapseEl].hide();
			this.afterCollapse();
		}
	},

	afterCollapse: function() {
		this.collapsed = true;
		this.el.addClass(this.collapsedCls);
		this.afterEffect();
		this.fireEvent('collapse', this);
	},

	expand: function(animate) {
		if (!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false) {
			return;
		}
		var doAnim = animate === true || (animate !== false && this.animCollapse);
		this.el.removeClass(this.collapsedCls);
		this.beforeEffect();
		this.onExpand(doAnim, animate);
		return this;
	},

	onExpand: function(doAnim, animArg) {
		if (doAnim) {
			this[this.collapseEl].slideIn(this.slideAnchor, Ext.apply(this.createEffect(animArg || true, this.afterExpand, this), this.expandDefaults));
		} else {
			this[this.collapseEl].show();
			this.afterExpand();
		}
	},

	afterExpand: function() {
		this.collapsed = false;
		this.afterEffect();
		this.fireEvent('expand', this);
	},

	toggleCollapse: function(animate) {
		this[this.collapsed ? 'expand': 'collapse'](animate);
		return this;
	},

	onDisable: function() {
		if (this.rendered && this.maskDisabled) {
			this.el.mask();
		}
		Ext.Panel.superclass.onDisable.call(this);
	},

	onEnable: function() {
		if (this.rendered && this.maskDisabled) {
			this.el.unmask();
		}
		Ext.Panel.superclass.onEnable.call(this);
	},

	onResize: function(w, h) {
		if (w !== undefined || h !== undefined) {
			if (!this.collapsed) {
				if (typeof w == 'number') {
					this.body.setWidth(this.adjustBodyWidth(w - this.getFrameWidth()));
				} else if (w == 'auto') {
					this.body.setWidth(w);
				}

				if (typeof h == 'number') {
					this.body.setHeight(this.adjustBodyHeight(h - this.getFrameHeight()));
				} else if (h == 'auto') {
					this.body.setHeight(h);
				}

				if (this.disabled && this.el._mask) {
					this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
				}
			} else {
				this.queuedBodySize = {
					width: w,
					height: h
				};
				if (!this.queuedExpand && this.allowQueuedExpand !== false) {
					this.queuedExpand = true;
					this.on('expand',
					function() {
						delete this.queuedExpand;
						this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
						this.doLayout();
					},
					this, {
						single: true
					});
				}
			}
			this.fireEvent('bodyresize', this, w, h);
		}
		this.syncShadow();
	},

	adjustBodyHeight: function(h) {
		return h;
	},

	adjustBodyWidth: function(w) {
		return w;
	},

	onPosition: function() {
		this.syncShadow();
	},

	getFrameWidth: function() {
		var w = this.el.getFrameWidth('lr');

		if (this.frame) {
			var l = this.bwrap.dom.firstChild;
			w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
			var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
			w += Ext.fly(mc).getFrameWidth('lr');
		}
		return w;
	},

	getFrameHeight: function() {
		var h = this.el.getFrameWidth('tb');
		h += (this.tbar ? this.tbar.getHeight() : 0) + (this.bbar ? this.bbar.getHeight() : 0);

		if (this.frame) {
			var hd = this.el.dom.firstChild;
			var ft = this.bwrap.dom.lastChild;
			h += (hd.offsetHeight + ft.offsetHeight);
			var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
			h += Ext.fly(mc).getFrameWidth('tb');
		} else {
			h += (this.header ? this.header.getHeight() : 0) + (this.footer ? this.footer.getHeight() : 0);
		}
		return h;
	},

	getInnerWidth: function() {
		return this.getSize().width - this.getFrameWidth();
	},

	getInnerHeight: function() {
		return this.getSize().height - this.getFrameHeight();
	},

	syncShadow: function() {
		if (this.floating) {
			this.el.sync(true);
		}
	},

	getLayoutTarget: function() {
		return this.body;
	},

	setTitle: function(title, iconCls) {
		this.title = title;
		if (this.header && this.headerAsText) {
			this.header.child('span').update(title);
		}
		if (iconCls) {
			this.setIconClass(iconCls);
		}
		this.fireEvent('titlechange', this, title);
		return this;
	},

	getUpdater: function() {
		return this.body.getUpdater();
	},

	load: function() {
		var um = this.body.getUpdater();
		um.update.apply(um, arguments);
		return this;
	},

	beforeDestroy: function() {
		Ext.Element.uncache(this.header, this.tbar, this.bbar, this.footer, this.body);
		if (this.tools) {
			for (var k in this.tools) {
				Ext.destroy(this.tools[k]);
			}
		}
		if (this.buttons) {
			for (var b in this.buttons) {
				Ext.destroy(this.buttons[b]);
			}
		}
		Ext.destroy(this.topToolbar, this.bottomToolbar);
		Ext.Panel.superclass.beforeDestroy.call(this);
	},

	createClasses: function() {
		this.headerCls = this.baseCls + '-header';
		this.headerTextCls = this.baseCls + '-header-text';
		this.bwrapCls = this.baseCls + '-bwrap';
		this.tbarCls = this.baseCls + '-tbar';
		this.bodyCls = this.baseCls + '-body';
		this.bbarCls = this.baseCls + '-bbar';
		this.footerCls = this.baseCls + '-footer';
	},

	createGhost: function(cls, useShim, appendTo) {
		var el = document.createElement('div');
		el.className = 'x-panel-ghost ' + (cls ? cls: '');
		if (this.header) {
			el.appendChild(this.el.dom.firstChild.cloneNode(true));
		}
		Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
		el.style.width = this.el.dom.offsetWidth + 'px';;
		if (!appendTo) {
			this.container.dom.appendChild(el);
		} else {
			Ext.getDom(appendTo).appendChild(el);
		}
		if (useShim !== false && this.el.useShim !== false) {
			var layer = new Ext.Layer({
				shadow: false,
				useDisplay: true,
				constrain: false
			},
			el);
			layer.show();
			return layer;
		} else {
			return new Ext.Element(el);
		}
	},

	doAutoLoad: function() {
		this.body.load(typeof this.autoLoad == 'object' ? this.autoLoad: {
			url: this.autoLoad
		});
	}

});
Ext.reg('panel', Ext.Panel);

Ext.Window = Ext.extend(Ext.Panel, {

	baseCls: 'x-window',

	resizable: true,

	draggable: true,

	closable: true,

	constrain: false,

	constrainHeader: false,

	plain: false,

	minimizable: false,

	maximizable: false,

	minHeight: 100,

	minWidth: 200,

	expandOnShow: true,

	closeAction: 'close',

	elements: 'header,body',

	collapsible: false,

	initHidden: true,

	monitorResize: true,

	frame: true,

	floating: true,

	initComponent: function() {
		Ext.Window.superclass.initComponent.call(this);
		this.addEvents(
		'resize',
		'maximize',
		'minimize',
		'restore');
	},

	getState: function() {
		return Ext.apply(Ext.Window.superclass.getState.call(this) || {},
		this.getBox());
	},

	onRender: function(ct, position) {
		Ext.Window.superclass.onRender.call(this, ct, position);

		if (this.plain) {
			this.el.addClass('x-window-plain');
		}

		this.focusEl = this.el.createChild({
			tag: "a",
			href: "#",
			cls: "x-dlg-focus",
			tabIndex: "-1",
			html: "&#160;"
		});
		this.focusEl.swallowEvent('click', true);

		this.proxy = this.el.createProxy("x-window-proxy");
		this.proxy.enableDisplayMode('block');

		if (this.modal) {
			this.mask = this.container.createChild({
				cls: "ext-el-mask"
			},
			this.el.dom);
			this.mask.enableDisplayMode("block");
			this.mask.hide();
		}
	},

	initEvents: function() {
		Ext.Window.superclass.initEvents.call(this);
		if (this.animateTarget) {
			this.setAnimateTarget(this.animateTarget);
		}

		if (this.resizable) {
			this.resizer = new Ext.Resizable(this.el, {
				minWidth: this.minWidth,
				minHeight: this.minHeight,
				handles: this.resizeHandles || "all",
				pinned: true,
				resizeElement: this.resizerAction
			});
			this.resizer.window = this;
			this.resizer.on("beforeresize", this.beforeResize, this);
		}

		if (this.draggable) {
			this.header.addClass("x-window-draggable");
		}
		this.initTools();

		this.el.on("mousedown", this.toFront, this);
		this.manager = this.manager || Ext.WindowMgr;
		this.manager.register(this);
		this.hidden = true;
		if (this.maximized) {
			this.maximized = false;
			this.maximize();
		}
		if (this.closable) {
			var km = this.getKeyMap();
			km.on(27, this.onEsc, this);
			km.disable();
		}
	},

	initDraggable: function() {

		this.dd = new Ext.Window.DD(this);
	},

	onEsc: function() {
		this[this.closeAction]();
	},

	beforeDestroy: function() {
		Ext.destroy(this.resizer, this.dd, this.proxy, this.mask);
		Ext.Window.superclass.beforeDestroy.call(this);
	},

	onDestroy: function() {
		if (this.manager) {
			this.manager.unregister(this);
		}
		Ext.Window.superclass.onDestroy.call(this);
	},

	initTools: function() {
		if (this.minimizable) {
			this.addTool({
				id: 'minimize',
				handler: this.minimize.createDelegate(this, [])
			});
		}
		if (this.maximizable) {
			this.addTool({
				id: 'maximize',
				handler: this.maximize.createDelegate(this, [])
			});
			this.addTool({
				id: 'restore',
				handler: this.restore.createDelegate(this, []),
				hidden: true
			});
			this.header.on('dblclick', this.toggleMaximize, this);
		}
		if (this.closable) {
			this.addTool({
				id: 'close',
				handler: this[this.closeAction].createDelegate(this, [])
			});
		}
	},

	resizerAction: function() {
		var box = this.proxy.getBox();
		this.proxy.hide();
		this.window.handleResize(box);
		return box;
	},

	beforeResize: function() {
		this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40);
		this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
		this.resizeBox = this.el.getBox();
	},

	updateHandles: function() {
		if (Ext.isIE && this.resizer) {
			this.resizer.syncHandleHeight();
			this.el.repaint();
		}
	},

	handleResize: function(box) {
		var rz = this.resizeBox;
		if (rz.x != box.x || rz.y != box.y) {
			this.updateBox(box);
		} else {
			this.setSize(box);
		}
		this.focus();
		this.updateHandles();
		this.saveState();
		if (this.layout) {
			this.doLayout();
		}
		this.fireEvent("resize", this, box.width, box.height);
	},

	focus: function() {
		var f = this.focusEl,
		db = this.defaultButton,
		t = typeof db;
		if (t != 'undefined') {
			if (t == 'number') {
				f = this.buttons[db];
			} else if (t == 'string') {
				f = Ext.getCmp(db);
			} else {
				f = db;
			}
		}
		f.focus.defer(10, f);
	},

	setAnimateTarget: function(el) {
		el = Ext.get(el);
		this.animateTarget = el;
	},

	beforeShow: function() {
		delete this.el.lastXY;
		delete this.el.lastLT;
		if (this.x === undefined || this.y === undefined) {
			var xy = this.el.getAlignToXY(this.container, 'c-c');
			var pos = this.el.translatePoints(xy[0], xy[1]);
			this.x = this.x === undefined ? pos.left: this.x;
			this.y = this.y === undefined ? pos.top: this.y;
		}
		this.el.setLeftTop(this.x, this.y);

		if (this.expandOnShow) {
			this.expand(false);
		}

		if (this.modal) {
			Ext.getBody().addClass("x-body-masked");
			this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
			this.mask.show();
		}
	},

	show: function(animateTarget, cb, scope) {
		if (!this.rendered) {
			this.render(Ext.getBody());
		}
		if (this.hidden === false) {
			this.toFront();
			return;
		}
		if (this.fireEvent("beforeshow", this) === false) {
			return;
		}
		if (cb) {
			this.on('show', cb, scope, {
				single: true
			});
		}
		this.hidden = false;
		if (animateTarget !== undefined) {
			this.setAnimateTarget(animateTarget);
		}
		this.beforeShow();
		if (this.animateTarget) {
			this.animShow();
		} else {
			this.afterShow();
		}
	},

	afterShow: function() {
		this.proxy.hide();
		this.el.setStyle('display', 'block');
		this.el.show();
		if (this.maximized) {
			this.fitContainer();
		}
		if (Ext.isMac && Ext.isGecko) {
			this.cascade(this.setAutoScroll);
		}

		if (this.monitorResize || this.modal || this.constrain || this.constrainHeader) {
			Ext.EventManager.onWindowResize(this.onWindowResize, this);
		}
		this.doConstrain();
		if (this.layout) {
			this.doLayout();
		}
		if (this.keyMap) {
			this.keyMap.enable();
		}
		this.toFront();
		this.updateHandles();
		this.fireEvent("show", this);
	},

	animShow: function() {
		this.proxy.show();
		this.proxy.setBox(this.animateTarget.getBox());
		this.proxy.setOpacity(0);
		var b = this.getBox(false);
		b.callback = this.afterShow;
		b.scope = this;
		b.duration = .25;
		b.easing = 'easeNone';
		b.opacity = .5;
		b.block = true;
		this.el.setStyle('display', 'none');
		this.proxy.shift(b);
	},

	hide: function(animateTarget, cb, scope) {
		if (this.activeGhost) {
			this.hide.defer(100, this, [animateTarget, cb, scope]);
			return;
		}
		if (this.hidden || this.fireEvent("beforehide", this) === false) {
			return;
		}
		if (cb) {
			this.on('hide', cb, scope, {
				single: true
			});
		}
		this.hidden = true;
		if (animateTarget !== undefined) {
			this.setAnimateTarget(animateTarget);
		}
		if (this.animateTarget) {
			this.animHide();
		} else {
			this.el.hide();
			this.afterHide();
		}
	},

	afterHide: function() {
		this.proxy.hide();
		if (this.monitorResize || this.modal || this.constrain || this.constrainHeader) {
			Ext.EventManager.removeResizeListener(this.onWindowResize, this);
		}
		if (this.modal) {
			this.mask.hide();
			Ext.getBody().removeClass("x-body-masked");
		}
		if (this.keyMap) {
			this.keyMap.disable();
		}
		this.fireEvent("hide", this);
	},

	animHide: function() {
		this.proxy.setOpacity(.5);
		this.proxy.show();
		var tb = this.getBox(false);
		this.proxy.setBox(tb);
		this.el.hide();
		var b = this.animateTarget.getBox();
		b.callback = this.afterHide;
		b.scope = this;
		b.duration = .25;
		b.easing = 'easeNone';
		b.block = true;
		b.opacity = 0;
		this.proxy.shift(b);
	},

	onWindowResize: function() {
		if (this.maximized) {
			this.fitContainer();
		}
		if (this.modal) {
			this.mask.setSize('100%', '100%');
			var force = this.mask.dom.offsetHeight;
			this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
		}
		this.doConstrain();
	},

	doConstrain: function() {
		if (this.constrain || this.constrainHeader) {
			var offsets;
			if (this.constrain) {
				offsets = {
					right: this.el.shadowOffset,
					left: this.el.shadowOffset,
					bottom: this.el.shadowOffset
				};
			} else {
				var s = this.getSize();
				offsets = {
					right: -(s.width - 100),
					bottom: -(s.height - 25)
				};
			}

			var xy = this.el.getConstrainToXY(this.container, true, offsets);
			if (xy) {
				this.setPosition(xy[0], xy[1]);
			}
		}
	},

	ghost: function(cls) {
		var ghost = this.createGhost(cls);
		var box = this.getBox(true);
		ghost.setLeftTop(box.x, box.y);
		ghost.setWidth(box.width);
		this.el.hide();
		this.activeGhost = ghost;
		return ghost;
	},

	unghost: function(show, matchPosition) {
		if (show !== false) {
			this.el.show();
			this.focus();
			if (Ext.isMac && Ext.isGecko) {
				this.cascade(this.setAutoScroll);
			}
		}
		if (matchPosition !== false) {
			this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
		}
		this.activeGhost.hide();
		this.activeGhost.remove();
		delete this.activeGhost;
	},

	minimize: function() {
		this.fireEvent('minimize', this);
	},

	close: function() {
		if (this.fireEvent("beforeclose", this) !== false) {
			this.hide(null,
			function() {
				this.fireEvent('close', this);
				this.destroy();
			},
			this);
		}
	},

	maximize: function() {
		if (!this.maximized) {
			this.expand(false);
			this.restoreSize = this.getSize();
			this.restorePos = this.getPosition(true);
			if (this.maximizable) {
				this.tools.maximize.hide();
				this.tools.restore.show();
			}
			this.maximized = true;
			this.el.disableShadow();

			if (this.dd) {
				this.dd.lock();
			}
			if (this.collapsible) {
				this.tools.toggle.hide();
			}
			this.el.addClass('x-window-maximized');
			this.container.addClass('x-window-maximized-ct');

			this.setPosition(0, 0);
			this.fitContainer();
			this.fireEvent('maximize', this);
		}
	},

	restore: function() {
		if (this.maximized) {
			this.el.removeClass('x-window-maximized');
			this.tools.restore.hide();
			this.tools.maximize.show();
			this.setPosition(this.restorePos[0], this.restorePos[1]);
			this.setSize(this.restoreSize.width, this.restoreSize.height);
			delete this.restorePos;
			delete this.restoreSize;
			this.maximized = false;
			this.el.enableShadow(true);

			if (this.dd) {
				this.dd.unlock();
			}
			if (this.collapsible) {
				this.tools.toggle.show();
			}
			this.container.removeClass('x-window-maximized-ct');

			this.doConstrain();
			this.fireEvent('restore', this);
		}
	},

	toggleMaximize: function() {
		this[this.maximized ? 'restore': 'maximize']();
	},

	fitContainer: function() {
		var vs = this.container.getViewSize();
		this.setSize(vs.width, vs.height);
	},

	setZIndex: function(index) {
		if (this.modal) {
			this.mask.setStyle("z-index", index);
		}
		this.el.setZIndex(++index);
		index += 5;

		if (this.resizer) {
			this.resizer.proxy.setStyle("z-index", ++index);
		}

		this.lastZIndex = index;
	},

	alignTo: function(element, position, offsets) {
		var xy = this.el.getAlignToXY(element, position, offsets);
		this.setPagePosition(xy[0], xy[1]);
		return this;
	},

	anchorTo: function(el, alignment, offsets, monitorScroll, _pname) {
		var action = function() {
			this.alignTo(el, alignment, offsets);
		};
		Ext.EventManager.onWindowResize(action, this);
		var tm = typeof monitorScroll;
		if (tm != 'undefined') {
			Ext.EventManager.on(window, 'scroll', action, this, {
				buffer: tm == 'number' ? monitorScroll: 50
			});
		}
		action.call(this);
		this[_pname] = action;
		return this;
	},

	toFront: function() {
		if (this.manager.bringToFront(this)) {
			this.focus();
		}
		return this;
	},

	setActive: function(active) {
		if (active) {
			if (!this.maximized) {
				this.el.enableShadow(true);
			}
			this.fireEvent('activate', this);
		} else {
			this.el.disableShadow();
			this.fireEvent('deactivate', this);
		}
	},

	toBack: function() {
		this.manager.sendToBack(this);
		return this;
	},

	center: function() {
		var xy = this.el.getAlignToXY(this.container, 'c-c');
		this.setPagePosition(xy[0], xy[1]);
		return this;
	}

});
Ext.reg('window', Ext.Window);

Ext.Window.DD = function(win) {
	this.win = win;
	Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-' + win.id);
	this.setHandleElId(win.header.id);
	this.scroll = false;
};

Ext.extend(Ext.Window.DD, Ext.dd.DD, {
	moveOnly: true,
	headerOffsets: [100, 25],
	startDrag: function() {
		var w = this.win;
		this.proxy = w.ghost();
		if (w.constrain !== false) {
			var so = w.el.shadowOffset;
			this.constrainTo(w.container, {
				right: so,
				left: so,
				bottom: so
			});
		} else if (w.constrainHeader !== false) {
			var s = this.proxy.getSize();
			this.constrainTo(w.container, {
				right: -(s.width - this.headerOffsets[0]),
				bottom: -(s.height - this.headerOffsets[1])
			});
		}
	},
	b4Drag: Ext.emptyFn,

	onDrag: function(e) {
		this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
	},

	endDrag: function(e) {
		this.win.unghost();
		this.win.saveState();
	}
});

Ext.WindowGroup = function() {
	var list = {};
	var accessList = [];
	var front = null;

	var sortWindows = function(d1, d2) {
		return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1: 1;
	};

	var orderWindows = function() {
		var a = accessList,
		len = a.length;
		if (len > 0) {
			a.sort(sortWindows);
			var seed = a[0].manager.zseed;
			for (var i = 0; i < len; i++) {
				var win = a[i];
				if (win && !win.hidden) {
					win.setZIndex(seed + (i * 10));
				}
			}
		}
		activateLast();
	};

	var setActiveWin = function(win) {
		if (win != front) {
			if (front) {
				front.setActive(false);
			}
			front = win;
			if (win) {
				win.setActive(true);
			}
		}
	};

	var activateLast = function() {
		for (var i = accessList.length - 1; i >= 0; --i) {
			if (!accessList[i].hidden) {
				setActiveWin(accessList[i]);
				return;
			}
		}
		setActiveWin(null);
	};

	return {

		zseed: 9000,

		register: function(win) {
			list[win.id] = win;
			accessList.push(win);
			win.on('hide', activateLast);
		},

		unregister: function(win) {
			delete list[win.id];
			win.un('hide', activateLast);
			accessList.remove(win);
		},

		get: function(id) {
			return typeof id == "object" ? id: list[id];
		},

		bringToFront: function(win) {
			win = this.get(win);
			if (win != front) {
				win._lastAccess = new Date().getTime();
				orderWindows();
				return true;
			}
			return false;
		},

		sendToBack: function(win) {
			win = this.get(win);
			win._lastAccess = -(new Date().getTime());
			orderWindows();
			return win;
		},

		hideAll: function() {
			for (var id in list) {
				if (list[id] && typeof list[id] != "function" && list[id].isVisible()) {
					list[id].hide();
				}
			}
		},

		getActive: function() {
			return front;
		},

		getBy: function(fn, scope) {
			var r = [];
			for (var i = accessList.length - 1; i >= 0; --i) {
				var win = accessList[i];
				if (fn.call(scope || win, win) !== false) {
					r.push(win);
				}
			}
			return r;
		},

		each: function(fn, scope) {
			for (var id in list) {
				if (list[id] && typeof list[id] != "function") {
					if (fn.call(scope || list[id], list[id]) === false) {
						return;
					}
				}
			}
		}
	};
};

Ext.WindowMgr = new Ext.WindowGroup();

Ext.dd.PanelProxy = function(panel, config) {
	this.panel = panel;
	this.id = this.panel.id + '-ddproxy';
	Ext.apply(this, config);
};

Ext.dd.PanelProxy.prototype = {

	insertProxy: true,

	setStatus: Ext.emptyFn,
	reset: Ext.emptyFn,
	update: Ext.emptyFn,
	stop: Ext.emptyFn,
	sync: Ext.emptyFn,

	getEl: function() {
		return this.ghost;
	},

	getGhost: function() {
		return this.ghost;
	},

	getProxy: function() {
		return this.proxy;
	},

	hide: function() {
		if (this.ghost) {
			if (this.proxy) {
				this.proxy.remove();
				delete this.proxy;
			}
			this.panel.el.dom.style.display = '';
			this.ghost.remove();
			delete this.ghost;
		}
	},

	show: function() {
		if (!this.ghost) {
			this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
			this.ghost.setXY(this.panel.el.getXY());
			if (this.insertProxy) {
				this.proxy = this.panel.el.insertSibling({
					cls: 'x-panel-dd-spacer'
				});
				this.proxy.setSize(this.panel.getSize());
			}
			this.panel.el.dom.style.display = 'none';
		}
	},

	repair: function(xy, callback, scope) {
		this.hide();
		if (typeof callback == "function") {
			callback.call(scope || this);
		}
	},

	moveProxy: function(parentNode, before) {
		if (this.proxy) {
			parentNode.insertBefore(this.proxy.dom, before);
		}
	}
};

Ext.Panel.DD = function(panel, cfg) {
	this.panel = panel;
	this.dragData = {
		panel: panel
	};
	this.proxy = new Ext.dd.PanelProxy(panel, cfg);
	Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
	var h = panel.header;
	if (h) {
		this.setHandleElId(h.id);
	} (h ? h: this.panel.body).setStyle('cursor', 'move');
	this.scroll = false;
};

Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
	showFrame: Ext.emptyFn,
	startDrag: Ext.emptyFn,
	b4StartDrag: function(x, y) {
		this.proxy.show();
	},
	b4MouseDown: function(e) {
		var x = e.getPageX();
		var y = e.getPageY();
		this.autoOffset(x, y);
	},
	onInitDrag: function(x, y) {
		this.onStartDrag(x, y);
		return true;
	},
	createFrame: Ext.emptyFn,
	getDragEl: function(e) {
		return this.proxy.ghost.dom;
	},
	endDrag: function(e) {
		this.proxy.hide();
		this.panel.saveState();
	},

	autoOffset: function(x, y) {
		x -= this.startPageX;
		y -= this.startPageY;
		this.setDelta(x, y);
	}
});

Ext.state.Provider = function() {

	this.addEvents("statechange");
	this.state = {};
	Ext.state.Provider.superclass.constructor.call(this);
};
Ext.extend(Ext.state.Provider, Ext.util.Observable, {

	get: function(name, defaultValue) {
		return typeof this.state[name] == "undefined" ? defaultValue: this.state[name];
	},

	clear: function(name) {
		delete this.state[name];
		this.fireEvent("statechange", this, name, null);
	},

	set: function(name, value) {
		this.state[name] = value;
		this.fireEvent("statechange", this, name, value);
	},

	decodeValue: function(cookie) {
		var re = /^(a|n|d|b|s|o)\:(.*)$/;
		var matches = re.exec(unescape(cookie));
		if (!matches || !matches[1]) return;
		var type = matches[1];
		var v = matches[2];
		switch (type) {
		case "n":
			return parseFloat(v);
		case "d":
			return new Date(Date.parse(v));
		case "b":
			return (v == "1");
		case "a":
			var all = [];
			var values = v.split("^");
			for (var i = 0, len = values.length; i < len; i++) {
				all.push(this.decodeValue(values[i]));
			}
			return all;
		case "o":
			var all = {};
			var values = v.split("^");
			for (var i = 0, len = values.length; i < len; i++) {
				var kv = values[i].split("=");
				all[kv[0]] = this.decodeValue(kv[1]);
			}
			return all;
		default:
			return v;
		}
	},

	encodeValue: function(v) {
		var enc;
		if (typeof v == "number") {
			enc = "n:" + v;
		} else if (typeof v == "boolean") {
			enc = "b:" + (v ? "1": "0");
		} else if (Ext.isDate(v)) {
			enc = "d:" + v.toGMTString();
		} else if (Ext.isArray(v)) {
			var flat = "";
			for (var i = 0, len = v.length; i < len; i++) {
				flat += this.encodeValue(v[i]);
				if (i != len - 1) flat += "^";
			}
			enc = "a:" + flat;
		} else if (typeof v == "object") {
			var flat = "";
			for (var key in v) {
				if (typeof v[key] != "function" && v[key] !== undefined) {
					flat += key + "=" + this.encodeValue(v[key]) + "^";
				}
			}
			enc = "o:" + flat.substring(0, flat.length - 1);
		} else {
			enc = "s:" + v;
		}
		return escape(enc);
	}
});

Ext.state.Manager = function() {
	var provider = new Ext.state.Provider();

	return {

		setProvider: function(stateProvider) {
			provider = stateProvider;
		},

		get: function(key, defaultValue) {
			return provider.get(key, defaultValue);
		},

		set: function(key, value) {
			provider.set(key, value);
		},

		clear: function(key) {
			provider.clear(key);
		},

		getProvider: function() {
			return provider;
		}
	};
} ();

Ext.state.CookieProvider = function(config) {
	Ext.state.CookieProvider.superclass.constructor.call(this);
	this.path = "/";
	this.expires = new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 7));
	this.domain = null;
	this.secure = false;
	Ext.apply(this, config);
	this.state = this.readCookies();
};

Ext.extend(Ext.state.CookieProvider, Ext.state.Provider, {

	set: function(name, value) {
		if (typeof value == "undefined" || value === null) {
			this.clear(name);
			return;
		}
		this.setCookie(name, value);
		Ext.state.CookieProvider.superclass.set.call(this, name, value);
	},

	clear: function(name) {
		this.clearCookie(name);
		Ext.state.CookieProvider.superclass.clear.call(this, name);
	},

	readCookies: function() {
		var cookies = {};
		var c = document.cookie + ";";
		var re = /\s?(.*?)=(.*?);/g;
		var matches;
		while ((matches = re.exec(c)) != null) {
			var name = matches[1];
			var value = matches[2];
			if (name && name.substring(0, 3) == "ys-") {
				cookies[name.substr(3)] = this.decodeValue(value);
			}
		}
		return cookies;
	},

	setCookie: function(name, value) {
		document.cookie = "ys-" + name + "=" + this.encodeValue(value) + ((this.expires == null) ? "": ("; expires=" + this.expires.toGMTString())) + ((this.path == null) ? "": ("; path=" + this.path)) + ((this.domain == null) ? "": ("; domain=" + this.domain)) + ((this.secure == true) ? "; secure": "");
	},

	clearCookie: function(name) {
		document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" + ((this.path == null) ? "": ("; path=" + this.path)) + ((this.domain == null) ? "": ("; domain=" + this.domain)) + ((this.secure == true) ? "; secure": "");
	}
});

Ext.DataView = Ext.extend(Ext.BoxComponent, {

	selectedClass: "x-view-selected",

	emptyText: "",

	deferEmptyText: true,

	trackOver: false,

	last: false,

	initComponent: function() {
		Ext.DataView.superclass.initComponent.call(this);
		if (typeof this.tpl == "string") {
			this.tpl = new Ext.XTemplate(this.tpl);
		}

		this.addEvents(
		"beforeclick",
		"click",
		"mouseenter",
		"mouseleave",
		"containerclick",
		"dblclick",
		"contextmenu",
		"selectionchange",
		"beforeselect");

		this.all = new Ext.CompositeElementLite();
		this.selected = new Ext.CompositeElementLite();
	},

	onRender: function() {
		if (!this.el) {
			this.el = document.createElement('div');
			this.el.id = this.id;
		}
		Ext.DataView.superclass.onRender.apply(this, arguments);
	},

	afterRender: function() {
		Ext.DataView.superclass.afterRender.call(this);

		this.el.on({
			"click": this.onClick,
			"dblclick": this.onDblClick,
			"contextmenu": this.onContextMenu,
			scope: this
		});

		if (this.overClass || this.trackOver) {
			this.el.on({
				"mouseover": this.onMouseOver,
				"mouseout": this.onMouseOut,
				scope: this
			});
		}

		if (this.store) {
			this.setStore(this.store, true);
		}
	},

	refresh: function() {
		this.clearSelections(false, true);
		this.el.update("");
		var records = this.store.getRange();
		if (records.length < 1) {
			if (!this.deferEmptyText || this.hasSkippedEmptyText) {
				this.el.update(this.emptyText);
			}
			this.hasSkippedEmptyText = true;
			this.all.clear();
			return;
		}
		this.tpl.overwrite(this.el, this.collectData(records, 0));
		this.all.fill(Ext.query(this.itemSelector, this.el.dom));
		this.updateIndexes(0);
	},

	prepareData: function(data) {
		return data;
	},

	collectData: function(records, startIndex) {
		var r = [];
		for (var i = 0, len = records.length; i < len; i++) {
			r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
		}
		return r;
	},

	bufferRender: function(records) {
		var div = document.createElement('div');
		this.tpl.overwrite(div, this.collectData(records));
		return Ext.query(this.itemSelector, div);
	},

	onUpdate: function(ds, record) {
		var index = this.store.indexOf(record);
		var sel = this.isSelected(index);
		var original = this.all.elements[index];
		var node = this.bufferRender([record], index)[0];

		this.all.replaceElement(index, node, true);
		if (sel) {
			this.selected.replaceElement(original, node);
			this.all.item(index).addClass(this.selectedClass);
		}
		this.updateIndexes(index, index);
	},

	onAdd: function(ds, records, index) {
		if (this.all.getCount() == 0) {
			this.refresh();
			return;
		}
		var nodes = this.bufferRender(records, index),
		n,
		a = this.all.elements;
		if (index < this.all.getCount()) {
			n = this.all.item(index).insertSibling(nodes, 'before', true);
			a.splice.apply(a, [index, 0].concat(nodes));
		} else {
			n = this.all.last().insertSibling(nodes, 'after', true);
			a.push.apply(a, nodes);
		}
		this.updateIndexes(index);
	},

	onRemove: function(ds, record, index) {
		this.deselect(index);
		this.all.removeElement(index, true);
		this.updateIndexes(index);
	},

	refreshNode: function(index) {
		this.onUpdate(this.store, this.store.getAt(index));
	},

	updateIndexes: function(startIndex, endIndex) {
		var ns = this.all.elements;
		startIndex = startIndex || 0;
		endIndex = endIndex || ((endIndex === 0) ? 0: (ns.length - 1));
		for (var i = startIndex; i <= endIndex; i++) {
			ns[i].viewIndex = i;
		}
	},

	setStore: function(store, initial) {
		if (!initial && this.store) {
			this.store.un("beforeload", this.onBeforeLoad, this);
			this.store.un("datachanged", this.refresh, this);
			this.store.un("add", this.onAdd, this);
			this.store.un("remove", this.onRemove, this);
			this.store.un("update", this.onUpdate, this);
			this.store.un("clear", this.refresh, this);
		}
		if (store) {
			store = Ext.StoreMgr.lookup(store);
			store.on("beforeload", this.onBeforeLoad, this);
			store.on("datachanged", this.refresh, this);
			store.on("add", this.onAdd, this);
			store.on("remove", this.onRemove, this);
			store.on("update", this.onUpdate, this);
			store.on("clear", this.refresh, this);
		}
		this.store = store;
		if (store) {
			this.refresh();
		}
	},

	findItemFromChild: function(node) {
		return Ext.fly(node).findParent(this.itemSelector, this.el);
	},

	onClick: function(e) {
		var item = e.getTarget(this.itemSelector, this.el);
		if (item) {
			var index = this.indexOf(item);
			if (this.onItemClick(item, index, e) !== false) {
				this.fireEvent("click", this, index, item, e);
			}
		} else {
			if (this.fireEvent("containerclick", this, e) !== false) {
				this.clearSelections();
			}
		}
	},

	onContextMenu: function(e) {
		var item = e.getTarget(this.itemSelector, this.el);
		if (item) {
			this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
		}
	},

	onDblClick: function(e) {
		var item = e.getTarget(this.itemSelector, this.el);
		if (item) {
			this.fireEvent("dblclick", this, this.indexOf(item), item, e);
		}
	},

	onMouseOver: function(e) {
		var item = e.getTarget(this.itemSelector, this.el);
		if (item && item !== this.lastItem) {
			this.lastItem = item;
			Ext.fly(item).addClass(this.overClass);
			this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
		}
	},

	onMouseOut: function(e) {
		if (this.lastItem) {
			if (!e.within(this.lastItem, true)) {
				Ext.fly(this.lastItem).removeClass(this.overClass);
				this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
				delete this.lastItem;
			}
		}
	},

	onItemClick: function(item, index, e) {
		if (this.fireEvent("beforeclick", this, index, item, e) === false) {
			return false;
		}
		if (this.multiSelect) {
			this.doMultiSelection(item, index, e);
			e.preventDefault();
		} else if (this.singleSelect) {
			this.doSingleSelection(item, index, e);
			e.preventDefault();
		}
		return true;
	},

	doSingleSelection: function(item, index, e) {
		if (e.ctrlKey && this.isSelected(index)) {
			this.deselect(index);
		} else {
			this.select(index, false);
		}
	},

	doMultiSelection: function(item, index, e) {
		if (e.shiftKey && this.last !== false) {
			var last = this.last;
			this.selectRange(last, index, e.ctrlKey);
			this.last = last;
		} else {
			if ((e.ctrlKey || this.simpleSelect) && this.isSelected(index)) {
				this.deselect(index);
			} else {
				this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
			}
		}
	},

	getSelectionCount: function() {
		return this.selected.getCount()
	},

	getSelectedNodes: function() {
		return this.selected.elements;
	},

	getSelectedIndexes: function() {
		var indexes = [],
		s = this.selected.elements;
		for (var i = 0, len = s.length; i < len; i++) {
			indexes.push(s[i].viewIndex);
		}
		return indexes;
	},

	getSelectedRecords: function() {
		var r = [],
		s = this.selected.elements;
		for (var i = 0, len = s.length; i < len; i++) {
			r[r.length] = this.store.getAt(s[i].viewIndex);
		}
		return r;
	},

	getRecords: function(nodes) {
		var r = [],
		s = nodes;
		for (var i = 0, len = s.length; i < len; i++) {
			r[r.length] = this.store.getAt(s[i].viewIndex);
		}
		return r;
	},

	getRecord: function(node) {
		return this.store.getAt(node.viewIndex);
	},

	clearSelections: function(suppressEvent, skipUpdate) {
		if ((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0) {
			if (!skipUpdate) {
				this.selected.removeClass(this.selectedClass);
			}
			this.selected.clear();
			this.last = false;
			if (!suppressEvent) {
				this.fireEvent("selectionchange", this, this.selected.elements);
			}
		}
	},

	isSelected: function(node) {
		return this.selected.contains(this.getNode(node));
	},

	deselect: function(node) {
		if (this.isSelected(node)) {
			node = this.getNode(node);
			this.selected.removeElement(node);
			if (this.last == node.viewIndex) {
				this.last = false;
			}
			Ext.fly(node).removeClass(this.selectedClass);
			this.fireEvent("selectionchange", this, this.selected.elements);
		}
	},

	select: function(nodeInfo, keepExisting, suppressEvent) {
		if (Ext.isArray(nodeInfo)) {
			if (!keepExisting) {
				this.clearSelections(true);
			}
			for (var i = 0, len = nodeInfo.length; i < len; i++) {
				this.select(nodeInfo[i], true, true);
			}
			if (!suppressEvent) {
				this.fireEvent("selectionchange", this, this.selected.elements);
			}
		} else {
			var node = this.getNode(nodeInfo);
			if (!keepExisting) {
				this.clearSelections(true);
			}
			if (node && !this.isSelected(node)) {
				if (this.fireEvent("beforeselect", this, node, this.selected.elements) !== false) {
					Ext.fly(node).addClass(this.selectedClass);
					this.selected.add(node);
					this.last = node.viewIndex;
					if (!suppressEvent) {
						this.fireEvent("selectionchange", this, this.selected.elements);
					}
				}
			}
		}
	},

	selectRange: function(start, end, keepExisting) {
		if (!keepExisting) {
			this.clearSelections(true);
		}
		this.select(this.getNodes(start, end), true);
	},

	getNode: function(nodeInfo) {
		if (typeof nodeInfo == "string") {
			return document.getElementById(nodeInfo);
		} else if (typeof nodeInfo == "number") {
			return this.all.elements[nodeInfo];
		}
		return nodeInfo;
	},

	getNodes: function(start, end) {
		var ns = this.all.elements;
		start = start || 0;
		end = typeof end == "undefined" ? Math.max(ns.length - 1, 0) : end;
		var nodes = [],
		i;
		if (start <= end) {
			for (i = start; i <= end && ns[i]; i++) {
				nodes.push(ns[i]);
			}
		} else {
			for (i = start; i >= end && ns[i]; i--) {
				nodes.push(ns[i]);
			}
		}
		return nodes;
	},

	indexOf: function(node) {
		node = this.getNode(node);
		if (typeof node.viewIndex == "number") {
			return node.viewIndex;
		}
		return this.all.indexOf(node);
	},

	onBeforeLoad: function() {
		if (this.loadingText) {
			this.clearSelections(false, true);
			this.el.update('<div class="loading-indicator">' + this.loadingText + '</div>');
			this.all.clear();
		}
	},

	onDestroy: function() {
		Ext.DataView.superclass.onDestroy.call(this);
		this.setStore(null);
	}
});

Ext.reg('dataview', Ext.DataView);

Ext.ColorPalette = function(config) {
	Ext.ColorPalette.superclass.constructor.call(this, config);
	this.addEvents(
	'select');

	if (this.handler) {
		this.on("select", this.handler, this.scope, true);
	}
};
Ext.extend(Ext.ColorPalette, Ext.Component, {

	itemCls: "x-color-palette",

	value: null,
	clickEvent: 'click',
	ctype: "Ext.ColorPalette",

	allowReselect: false,

	colors: ["000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333", "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080", "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696", "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0", "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"],

	onRender: function(container, position) {
		var t = this.tpl || new Ext.XTemplate('<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>');
		var el = document.createElement("div");
		el.className = this.itemCls;
		t.overwrite(el, this.colors);
		container.dom.insertBefore(el, position);
		this.el = Ext.get(el);
		this.el.on(this.clickEvent, this.handleClick, this, {
			delegate: "a"
		});
		if (this.clickEvent != 'click') {
			this.el.on('click', Ext.emptyFn, this, {
				delegate: "a",
				preventDefault: true
			});
		}
	},

	afterRender: function() {
		Ext.ColorPalette.superclass.afterRender.call(this);
		if (this.value) {
			var s = this.value;
			this.value = null;
			this.select(s);
		}
	},

	handleClick: function(e, t) {
		e.preventDefault();
		if (!this.disabled) {
			var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
			this.select(c.toUpperCase());
		}
	},

	select: function(color) {
		color = color.replace("#", "");
		if (color != this.value || this.allowReselect) {
			var el = this.el;
			if (this.value) {
				el.child("a.color-" + this.value).removeClass("x-color-palette-sel");
			}
			el.child("a.color-" + color).addClass("x-color-palette-sel");
			this.value = color;
			this.fireEvent("select", this, color);
		}
	}

});
Ext.reg('colorpalette', Ext.ColorPalette);

Ext.DatePicker = Ext.extend(Ext.Component, {

	todayText: "Today",

	okText: "&#160;OK&#160;",

	cancelText: "Cancel",

	todayTip: "{0} (Spacebar)",

	minText: "This date is before the minimum date",

	maxText: "This date is after the maximum date",

	format: "m/d/y",

	disabledDaysText: "Disabled",

	disabledDatesText: "Disabled",

	constrainToViewport: true,

	monthNames: Date.monthNames,

	dayNames: Date.dayNames,

	nextText: 'Next Month (Control+Right)',

	prevText: 'Previous Month (Control+Left)',

	monthYearText: 'Choose a month (Control+Up/Down to move years)',

	startDay: 0,

	showToday: true,

	initComponent: function() {
		Ext.DatePicker.superclass.initComponent.call(this);

		this.value = this.value ? this.value.clearTime() : new Date().clearTime();

		this.addEvents(
		'select');

		if (this.handler) {
			this.on("select", this.handler, this.scope || this);
		}

		this.initDisabledDays();
	},

	initDisabledDays: function() {
		if (!this.disabledDatesRE && this.disabledDates) {
			var dd = this.disabledDates;
			var re = "(?:";
			for (var i = 0; i < dd.length; i++) {
				re += dd[i];
				if (i != dd.length - 1) re += "|";
			}
			this.disabledDatesRE = new RegExp(re + ")");
		}
	},

	setDisabledDates: function(dd) {
		if (Ext.isArray(dd)) {
			this.disabledDates = dd;
			this.disabledDatesRE = null;
		} else {
			this.disabledDatesRE = dd;
		}
		this.initDisabledDays();
		this.update(this.value, true);
	},

	setDisabledDays: function(dd) {
		this.disabledDays = dd;
		this.update(this.value, true);
	},

	setMinDate: function(dt) {
		this.minDate = dt;
		this.update(this.value, true);
	},

	setMaxDate: function(dt) {
		this.maxDate = dt;
		this.update(this.value, true);
	},

	setValue: function(value) {
		var old = this.value;
		this.value = value.clearTime(true);
		if (this.el) {
			this.update(this.value);
		}
	},

	getValue: function() {
		return this.value;
	},

	focus: function() {
		if (this.el) {
			this.update(this.activeDate);
		}
	},

	onRender: function(container, position) {
		var m = ['<table cellspacing="0">', '<tr><td class="x-date-left"><a href="#" title="', this.prevText, '">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText, '">&#160;</a></td></tr>', '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
		var dn = this.dayNames;
		for (var i = 0; i < 7; i++) {
			var d = this.startDay + i;
			if (d > 6) {
				d = d - 7;
			}
			m.push("<th><span>", dn[d].substr(0, 1), "</span></th>");
		}
		m[m.length] = "</tr></thead><tbody><tr>";
		for (var i = 0; i < 42; i++) {
			if (i % 7 == 0 && i != 0) {
				m[m.length] = "</tr><tr>";
			}
			m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
		}
		m.push('</tr></tbody></table></td></tr>', this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>': '', '</table><div class="x-date-mp"></div>');

		var el = document.createElement("div");
		el.className = "x-date-picker";
		el.innerHTML = m.join("");

		container.dom.insertBefore(el, position);

		this.el = Ext.get(el);
		this.eventEl = Ext.get(el.firstChild);

		new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
			handler: this.showPrevMonth,
			scope: this,
			preventDefault: true,
			stopDefault: true
		});

		new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
			handler: this.showNextMonth,
			scope: this,
			preventDefault: true,
			stopDefault: true
		});

		this.eventEl.on("mousewheel", this.handleMouseWheel, this);

		this.monthPicker = this.el.down('div.x-date-mp');
		this.monthPicker.enableDisplayMode('block');

		var kn = new Ext.KeyNav(this.eventEl, {
			"left": function(e) {
				e.ctrlKey ? this.showPrevMonth() : this.update(this.activeDate.add("d", -1));
			},

			"right": function(e) {
				e.ctrlKey ? this.showNextMonth() : this.update(this.activeDate.add("d", 1));
			},

			"up": function(e) {
				e.ctrlKey ? this.showNextYear() : this.update(this.activeDate.add("d", -7));
			},

			"down": function(e) {
				e.ctrlKey ? this.showPrevYear() : this.update(this.activeDate.add("d", 7));
			},

			"pageUp": function(e) {
				this.showNextMonth();
			},

			"pageDown": function(e) {
				this.showPrevMonth();
			},

			"enter": function(e) {
				e.stopPropagation();
				return true;
			},

			scope: this
		});

		this.eventEl.on("click", this.handleDateClick, this, {
			delegate: "a.x-date-date"
		});

		this.el.unselectable();

		this.cells = this.el.select("table.x-date-inner tbody td");
		this.textNodes = this.el.query("table.x-date-inner tbody span");

		this.mbtn = new Ext.Button({
			text: "&#160;",
			tooltip: this.monthYearText,
			renderTo: this.el.child("td.x-date-middle", true)
		});

		this.mbtn.on('click', this.showMonthPicker, this);
		this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");

		if (this.showToday) {
			this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
			var today = (new Date()).dateFormat(this.format);
			this.todayBtn = new Ext.Button({
				renderTo: this.el.child("td.x-date-bottom", true),
				text: String.format(this.todayText, today),
				tooltip: String.format(this.todayTip, today),
				handler: this.selectToday,
				scope: this
			});
		}

		if (Ext.isIE) {
			this.el.repaint();
		}
		this.update(this.value);
	},

	createMonthPicker: function() {
		if (!this.monthPicker.dom.firstChild) {
			var buf = ['<table border="0" cellspacing="0">'];
			for (var i = 0; i < 6; i++) {
				buf.push('<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>', '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i + 6].substr(0, 3), '</a></td>', i == 0 ? '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>': '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>');
			}
			buf.push('<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">', this.okText, '</button><button type="button" class="x-date-mp-cancel">', this.cancelText, '</button></td></tr>', '</table>');
			this.monthPicker.update(buf.join(''));
			this.monthPicker.on('click', this.onMonthClick, this);
			this.monthPicker.on('dblclick', this.onMonthDblClick, this);

			this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
			this.mpYears = this.monthPicker.select('td.x-date-mp-year');

			this.mpMonths.each(function(m, a, i) {
				i += 1;
				if ((i % 2) == 0) {
					m.dom.xmonth = 5 + Math.round(i * .5);
				} else {
					m.dom.xmonth = Math.round((i - 1) * .5);
				}
			});
		}
	},

	showMonthPicker: function() {
		this.createMonthPicker();
		var size = this.el.getSize();
		this.monthPicker.setSize(size);
		this.monthPicker.child('table').setSize(size);

		this.mpSelMonth = (this.activeDate || this.value).getMonth();
		this.updateMPMonth(this.mpSelMonth);
		this.mpSelYear = (this.activeDate || this.value).getFullYear();
		this.updateMPYear(this.mpSelYear);

		this.monthPicker.slideIn('t', {
			duration: .2
		});
	},

	updateMPYear: function(y) {
		this.mpyear = y;
		var ys = this.mpYears.elements;
		for (var i = 1; i <= 10; i++) {
			var td = ys[i - 1],
			y2;
			if ((i % 2) == 0) {
				y2 = y + Math.round(i * .5);
				td.firstChild.innerHTML = y2;
				td.xyear = y2;
			} else {
				y2 = y - (5 - Math.round(i * .5));
				td.firstChild.innerHTML = y2;
				td.xyear = y2;
			}
			this.mpYears.item(i - 1)[y2 == this.mpSelYear ? 'addClass': 'removeClass']('x-date-mp-sel');
		}
	},

	updateMPMonth: function(sm) {
		this.mpMonths.each(function(m, a, i) {
			m[m.dom.xmonth == sm ? 'addClass': 'removeClass']('x-date-mp-sel');
		});
	},

	selectMPMonth: function(m) {
		},

	onMonthClick: function(e, t) {
		e.stopEvent();
		var el = new Ext.Element(t),
		pn;
		if (el.is('button.x-date-mp-cancel')) {
			this.hideMonthPicker();
		} else if (el.is('button.x-date-mp-ok')) {
			var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
			if (d.getMonth() != this.mpSelMonth) {

				d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
			}
			this.update(d);
			this.hideMonthPicker();
		} else if (pn = el.up('td.x-date-mp-month', 2)) {
			this.mpMonths.removeClass('x-date-mp-sel');
			pn.addClass('x-date-mp-sel');
			this.mpSelMonth = pn.dom.xmonth;
		} else if (pn = el.up('td.x-date-mp-year', 2)) {
			this.mpYears.removeClass('x-date-mp-sel');
			pn.addClass('x-date-mp-sel');
			this.mpSelYear = pn.dom.xyear;
		} else if (el.is('a.x-date-mp-prev')) {
			this.updateMPYear(this.mpyear - 10);
		} else if (el.is('a.x-date-mp-next')) {
			this.updateMPYear(this.mpyear + 10);
		}
	},

	onMonthDblClick: function(e, t) {
		e.stopEvent();
		var el = new Ext.Element(t),
		pn;
		if (pn = el.up('td.x-date-mp-month', 2)) {
			this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
			this.hideMonthPicker();
		} else if (pn = el.up('td.x-date-mp-year', 2)) {
			this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
			this.hideMonthPicker();
		}
	},

	hideMonthPicker: function(disableAnim) {
		if (this.monthPicker) {
			if (disableAnim === true) {
				this.monthPicker.hide();
			} else {
				this.monthPicker.slideOut('t', {
					duration: .2
				});
			}
		}
	},

	showPrevMonth: function(e) {
		this.update(this.activeDate.add("mo", -1));
	},

	showNextMonth: function(e) {
		this.update(this.activeDate.add("mo", 1));
	},

	showPrevYear: function() {
		this.update(this.activeDate.add("y", -1));
	},

	showNextYear: function() {
		this.update(this.activeDate.add("y", 1));
	},

	handleMouseWheel: function(e) {
		var delta = e.getWheelDelta();
		if (delta > 0) {
			this.showPrevMonth();
			e.stopEvent();
		} else if (delta < 0) {
			this.showNextMonth();
			e.stopEvent();
		}
	},

	handleDateClick: function(e, t) {
		e.stopEvent();
		if (t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")) {
			this.setValue(new Date(t.dateValue));
			this.fireEvent("select", this, this.value);
		}
	},

	selectToday: function() {
		if (this.todayBtn && !this.todayBtn.disabled) {
			this.setValue(new Date().clearTime());
			this.fireEvent("select", this, this.value);
		}
	},

	update: function(date, forceRefresh) {
		var vd = this.activeDate;
		this.activeDate = date;
		if (!forceRefresh && vd && this.el) {
			var t = date.getTime();
			if (vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()) {
				this.cells.removeClass("x-date-selected");
				this.cells.each(function(c) {
					if (c.dom.firstChild.dateValue == t) {
						c.addClass("x-date-selected");
						setTimeout(function() {
							try {
								c.dom.firstChild.focus();
							} catch(e) {}
						},
						50);
						return false;
					}
				});
				return;
			}
		}
		var days = date.getDaysInMonth();
		var firstOfMonth = date.getFirstDateOfMonth();
		var startingPos = firstOfMonth.getDay() - this.startDay;

		if (startingPos <= this.startDay) {
			startingPos += 7;
		}

		var pm = date.add("mo", -1);
		var prevStart = pm.getDaysInMonth() - startingPos;

		var cells = this.cells.elements;
		var textEls = this.textNodes;
		days += startingPos;

		var day = 86400000;
		var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
		var today = new Date().clearTime().getTime();
		var sel = date.clearTime().getTime();
		var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
		var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
		var ddMatch = this.disabledDatesRE;
		var ddText = this.disabledDatesText;
		var ddays = this.disabledDays ? this.disabledDays.join("") : false;
		var ddaysText = this.disabledDaysText;
		var format = this.format;

		if (this.showToday) {
			var td = new Date().clearTime();
			var disable = (td < min || td > max || (ddMatch && format && ddMatch.test(td.dateFormat(format))) || (ddays && ddays.indexOf(td.getDay()) != -1));

			this.todayBtn.setDisabled(disable);
			this.todayKeyListener[disable ? 'disable': 'enable']();
		}

		var setCellClass = function(cal, cell) {
			cell.title = "";
			var t = d.getTime();
			cell.firstChild.dateValue = t;
			if (t == today) {
				cell.className += " x-date-today";
				cell.title = cal.todayText;
			}
			if (t == sel) {
				cell.className += " x-date-selected";
				setTimeout(function() {
					try {
						cell.firstChild.focus();
					} catch(e) {}
				},
				50);
			}

			if (t < min) {
				cell.className = " x-date-disabled";
				cell.title = cal.minText;
				return;
			}
			if (t > max) {
				cell.className = " x-date-disabled";
				cell.title = cal.maxText;
				return;
			}
			if (ddays) {
				if (ddays.indexOf(d.getDay()) != -1) {
					cell.title = ddaysText;
					cell.className = " x-date-disabled";
				}
			}
			if (ddMatch && format) {
				var fvalue = d.dateFormat(format);
				if (ddMatch.test(fvalue)) {
					cell.title = ddText.replace("%0", fvalue);
					cell.className = " x-date-disabled";
				}
			}
		};

		var i = 0;
		for (; i < startingPos; i++) {
			textEls[i].innerHTML = (++prevStart);
			d.setDate(d.getDate() + 1);
			cells[i].className = "x-date-prevday";
			setCellClass(this, cells[i]);
		}
		for (; i < days; i++) {
			intDay = i - startingPos + 1;
			textEls[i].innerHTML = (intDay);
			d.setDate(d.getDate() + 1);
			cells[i].className = "x-date-active";
			setCellClass(this, cells[i]);
		}
		var extraDays = 0;
		for (; i < 42; i++) {
			textEls[i].innerHTML = (++extraDays);
			d.setDate(d.getDate() + 1);
			cells[i].className = "x-date-nextday";
			setCellClass(this, cells[i]);
		}

		this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());

		if (!this.internalRender) {
			var main = this.el.dom.firstChild;
			var w = main.offsetWidth;
			this.el.setWidth(w + this.el.getBorderWidth("lr"));
			Ext.fly(main).setWidth(w);
			this.internalRender = true;

			if (Ext.isOpera && !this.secondPass) {
				main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth + main.rows[0].cells[2].offsetWidth)) + "px";
				this.secondPass = true;
				this.update.defer(10, this, [date]);
			}
		}
	},

	beforeDestroy: function() {
		if (this.rendered) {
			Ext.destroy(this.mbtn, this.todayBtn);
		}
	}

});
Ext.reg('datepicker', Ext.DatePicker);

Ext.TabPanel = Ext.extend(Ext.Panel, {

	monitorResize: true,

	deferredRender: true,

	tabWidth: 120,

	minTabWidth: 30,

	resizeTabs: false,

	enableTabScroll: false,

	scrollIncrement: 0,

	scrollRepeatInterval: 400,

	scrollDuration: .35,

	animScroll: true,

	tabPosition: 'top',

	baseCls: 'x-tab-panel',

	autoTabs: false,

	autoTabSelector: 'div.x-tab',

	activeTab: null,

	tabMargin: 2,

	plain: false,

	wheelIncrement: 20,

	idDelimiter: '__',

	itemCls: 'x-tab-item',

	elements: 'body',
	headerAsText: false,
	frame: false,
	hideBorders: true,

	initComponent: function() {
		this.frame = false;
		Ext.TabPanel.superclass.initComponent.call(this);
		this.addEvents(
		'beforetabchange',
		'tabchange',
		'contextmenu');
		this.setLayout(new Ext.layout.CardLayout({
			deferredRender: this.deferredRender
		}));
		if (this.tabPosition == 'top') {
			this.elements += ',header';
			this.stripTarget = 'header';
		} else {
			this.elements += ',footer';
			this.stripTarget = 'footer';
		}
		if (!this.stack) {
			this.stack = Ext.TabPanel.AccessStack();
		}
		this.initItems();
	},

	render: function() {
		Ext.TabPanel.superclass.render.apply(this, arguments);
		if (this.activeTab !== undefined) {
			var item = this.activeTab;
			delete this.activeTab;
			this.setActiveTab(item);
		}
	},

	onRender: function(ct, position) {
		Ext.TabPanel.superclass.onRender.call(this, ct, position);

		if (this.plain) {
			var pos = this.tabPosition == 'top' ? 'header': 'footer';
			this[pos].addClass('x-tab-panel-' + pos + '-plain');
		}

		var st = this[this.stripTarget];

		this.stripWrap = st.createChild({
			cls: 'x-tab-strip-wrap',
			cn: {
				tag: 'ul',
				cls: 'x-tab-strip x-tab-strip-' + this.tabPosition
			}
		});

		var beforeEl = (this.tabPosition == 'bottom' ? this.stripWrap: null);
		this.stripSpacer = st.createChild({
			cls: 'x-tab-strip-spacer'
		},
		beforeEl);
		this.strip = new Ext.Element(this.stripWrap.dom.firstChild);

		this.edge = this.strip.createChild({
			tag: 'li',
			cls: 'x-tab-edge'
		});
		this.strip.createChild({
			cls: 'x-clear'
		});

		this.body.addClass('x-tab-panel-body-' + this.tabPosition);

		if (!this.itemTpl) {
			var tt = new Ext.Template('<li class="{cls}" id="{id}"><a class="x-tab-strip-close" onclick="return false;"></a>', '<a class="x-tab-right" href="#" onclick="return false;"><em class="x-tab-left">', '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>', '</em></a></li>');
			tt.disableFormats = true;
			tt.compile();
			Ext.TabPanel.prototype.itemTpl = tt;
		}

		this.items.each(this.initTab, this);
	},

	afterRender: function() {
		Ext.TabPanel.superclass.afterRender.call(this);
		if (this.autoTabs) {
			this.readTabs(false);
		}
	},

	initEvents: function() {
		Ext.TabPanel.superclass.initEvents.call(this);
		this.on('add', this.onAdd, this);
		this.on('remove', this.onRemove, this);

		this.strip.on('mousedown', this.onStripMouseDown, this);
		this.strip.on('contextmenu', this.onStripContextMenu, this);
		if (this.enableTabScroll) {
			this.strip.on('mousewheel', this.onWheel, this);
		}
	},

	findTargets: function(e) {
		var item = null;
		var itemEl = e.getTarget('li', this.strip);
		if (itemEl) {
			item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
			if (item.disabled) {
				return {
					close: null,
					item: null,
					el: null
				};
			}
		}
		return {
			close: e.getTarget('.x-tab-strip-close', this.strip),
			item: item,
			el: itemEl
		};
	},

	onStripMouseDown: function(e) {
		if (e.button != 0) {
			return;
		}
		e.preventDefault();
		var t = this.findTargets(e);
		if (t.close) {
			this.remove(t.item);
			return;
		}
		if (t.item && t.item != this.activeTab) {
			this.setActiveTab(t.item);
		}
	},

	onStripContextMenu: function(e) {
		e.preventDefault();
		var t = this.findTargets(e);
		if (t.item) {
			this.fireEvent('contextmenu', this, t.item, e);
		}
	},

	readTabs: function(removeExisting) {
		if (removeExisting === true) {
			this.items.each(function(item) {
				this.remove(item);
			},
			this);
		}
		var tabs = this.el.query(this.autoTabSelector);
		for (var i = 0, len = tabs.length; i < len; i++) {
			var tab = tabs[i];
			var title = tab.getAttribute('title');
			tab.removeAttribute('title');
			this.add({
				title: title,
				el: tab
			});
		}
	},

	initTab: function(item, index) {
		var before = this.strip.dom.childNodes[index];
		var cls = item.closable ? 'x-tab-strip-closable': '';
		if (item.disabled) {
			cls += ' x-item-disabled';
		}
		if (item.iconCls) {
			cls += ' x-tab-with-icon';
		}
		if (item.tabCls) {
			cls += ' ' + item.tabCls;
		}

		var p = {
			id: this.id + this.idDelimiter + item.getItemId(),
			text: item.title,
			cls: cls,
			iconCls: item.iconCls || ''
		};
		var el = before ? this.itemTpl.insertBefore(before, p) : this.itemTpl.append(this.strip, p);

		Ext.fly(el).addClassOnOver('x-tab-strip-over');

		if (item.tabTip) {
			Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;
		}
		item.on('disable', this.onItemDisabled, this);
		item.on('enable', this.onItemEnabled, this);
		item.on('titlechange', this.onItemTitleChanged, this);
		item.on('beforeshow', this.onBeforeShowItem, this);
	},

	onAdd: function(tp, item, index) {
		this.initTab(item, index);
		if (this.items.getCount() == 1) {
			this.syncSize();
		}
		this.delegateUpdates();
	},

	onBeforeAdd: function(item) {
		var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item: null) : this.items.get(item);
		if (existing) {
			this.setActiveTab(item);
			return false;
		}
		Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
		var es = item.elements;
		item.elements = es ? es.replace(',header', '') : es;
		item.border = (item.border === true);
	},

	onRemove: function(tp, item) {
		Ext.removeNode(this.getTabEl(item));
		this.stack.remove(item);
		item.un('disable', this.onItemDisabled, this);
		item.un('enable', this.onItemEnabled, this);
		item.un('titlechange', this.onItemTitleChanged, this);
		item.un('beforeshow', this.onBeforeShowItem, this);
		if (item == this.activeTab) {
			var next = this.stack.next();
			if (next) {
				this.setActiveTab(next);
			} else {
				this.setActiveTab(0);
			}
		}
		this.delegateUpdates();
	},

	onBeforeShowItem: function(item) {
		if (item != this.activeTab) {
			this.setActiveTab(item);
			return false;
		}
	},

	onItemDisabled: function(item) {
		var el = this.getTabEl(item);
		if (el) {
			Ext.fly(el).addClass('x-item-disabled');
		}
		this.stack.remove(item);
	},

	onItemEnabled: function(item) {
		var el = this.getTabEl(item);
		if (el) {
			Ext.fly(el).removeClass('x-item-disabled');
		}
	},

	onItemTitleChanged: function(item) {
		var el = this.getTabEl(item);
		if (el) {
			Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
		}
	},

	getTabEl: function(item) {
		var itemId = (typeof item === 'number') ? this.items.items[item].getItemId() : item.getItemId();
		return document.getElementById(this.id + this.idDelimiter + itemId);
	},

	onResize: function() {
		Ext.TabPanel.superclass.onResize.apply(this, arguments);
		this.delegateUpdates();
	},

	beginUpdate: function() {
		this.suspendUpdates = true;
	},

	endUpdate: function() {
		this.suspendUpdates = false;
		this.delegateUpdates();
	},

	hideTabStripItem: function(item) {
		item = this.getComponent(item);
		var el = this.getTabEl(item);
		if (el) {
			el.style.display = 'none';
			this.delegateUpdates();
		}
		this.stack.remove(item);
	},

	unhideTabStripItem: function(item) {
		item = this.getComponent(item);
		var el = this.getTabEl(item);
		if (el) {
			el.style.display = '';
			this.delegateUpdates();
		}
	},

	delegateUpdates: function() {
		if (this.suspendUpdates) {
			return;
		}
		if (this.resizeTabs && this.rendered) {
			this.autoSizeTabs();
		}
		if (this.enableTabScroll && this.rendered) {
			this.autoScrollTabs();
		}
	},

	autoSizeTabs: function() {
		var count = this.items.length;
		var ce = this.tabPosition != 'bottom' ? 'header': 'footer';
		var ow = this[ce].dom.offsetWidth;
		var aw = this[ce].dom.clientWidth;

		if (!this.resizeTabs || count < 1 || !aw) {
			return;
		}

		var each = Math.max(Math.min(Math.floor((aw - 4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth);
		this.lastTabWidth = each;
		var lis = this.stripWrap.dom.getElementsByTagName('li');
		for (var i = 0, len = lis.length - 1; i < len; i++) {
			var li = lis[i];
			var inner = li.childNodes[1].firstChild.firstChild;
			var tw = li.offsetWidth;
			var iw = inner.offsetWidth;
			inner.style.width = (each - (tw - iw)) + 'px';
		}
	},

	adjustBodyWidth: function(w) {
		if (this.header) {
			this.header.setWidth(w);
		}
		if (this.footer) {
			this.footer.setWidth(w);
		}
		return w;
	},

	setActiveTab: function(item) {
		item = this.getComponent(item);
		if (!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false) {
			return;
		}
		if (!this.rendered) {
			this.activeTab = item;
			return;
		}
		if (this.activeTab != item) {
			if (this.activeTab) {
				var oldEl = this.getTabEl(this.activeTab);
				if (oldEl) {
					Ext.fly(oldEl).removeClass('x-tab-strip-active');
				}
				this.activeTab.fireEvent('deactivate', this.activeTab);
			}
			var el = this.getTabEl(item);
			Ext.fly(el).addClass('x-tab-strip-active');
			this.activeTab = item;
			this.stack.add(item);

			this.layout.setActiveItem(item);
			if (this.layoutOnTabChange && item.doLayout) {
				item.doLayout();
			}
			if (this.scrolling) {
				this.scrollToTab(item, this.animScroll);
			}

			item.fireEvent('activate', item);
			this.fireEvent('tabchange', this, item);
		}
	},

	getActiveTab: function() {
		return this.activeTab || null;
	},

	getItem: function(item) {
		return this.getComponent(item);
	},

	autoScrollTabs: function() {
		var count = this.items.length;
		var ow = this.header.dom.offsetWidth;
		var tw = this.header.dom.clientWidth;

		var wrap = this.stripWrap;
		var wd = wrap.dom;
		var cw = wd.offsetWidth;
		var pos = this.getScrollPos();
		var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;

		if (!this.enableTabScroll || count < 1 || cw < 20) {
			return;
		}
		if (l <= tw) {
			wd.scrollLeft = 0;
			wrap.setWidth(tw);
			if (this.scrolling) {
				this.scrolling = false;
				this.header.removeClass('x-tab-scrolling');
				this.scrollLeft.hide();
				this.scrollRight.hide();
				if (Ext.isAir) {
					wd.style.marginLeft = '';
					wd.style.marginRight = '';
				}
			}
		} else {
			if (!this.scrolling) {
				this.header.addClass('x-tab-scrolling');
				if (Ext.isAir) {
					wd.style.marginLeft = '18px';
					wd.style.marginRight = '18px';
				}
			}
			tw -= wrap.getMargins('lr');
			wrap.setWidth(tw > 20 ? tw: 20);
			if (!this.scrolling) {
				if (!this.scrollLeft) {
					this.createScrollers();
				} else {
					this.scrollLeft.show();
					this.scrollRight.show();
				}
			}
			this.scrolling = true;
			if (pos > (l - tw)) {
				wd.scrollLeft = l - tw;
			} else {
				this.scrollToTab(this.activeTab, false);
			}
			this.updateScrollButtons();
		}
	},

	createScrollers: function() {
		var h = this.stripWrap.dom.offsetHeight;

		var sl = this.header.insertFirst({
			cls: 'x-tab-scroller-left'
		});
		sl.setHeight(h);
		sl.addClassOnOver('x-tab-scroller-left-over');
		this.leftRepeater = new Ext.util.ClickRepeater(sl, {
			interval: this.scrollRepeatInterval,
			handler: this.onScrollLeft,
			scope: this
		});
		this.scrollLeft = sl;

		var sr = this.header.insertFirst({
			cls: 'x-tab-scroller-right'
		});
		sr.setHeight(h);
		sr.addClassOnOver('x-tab-scroller-right-over');
		this.rightRepeater = new Ext.util.ClickRepeater(sr, {
			interval: this.scrollRepeatInterval,
			handler: this.onScrollRight,
			scope: this
		});
		this.scrollRight = sr;
	},

	getScrollWidth: function() {
		return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
	},

	getScrollPos: function() {
		return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
	},

	getScrollArea: function() {
		return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
	},

	getScrollAnim: function() {
		return {
			duration: this.scrollDuration,
			callback: this.updateScrollButtons,
			scope: this
		};
	},

	getScrollIncrement: function() {
		return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth + 2: 100);
	},

	scrollToTab: function(item, animate) {
		if (!item) {
			return;
		}
		var el = this.getTabEl(item);
		var pos = this.getScrollPos(),
		area = this.getScrollArea();
		var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
		var right = left + el.offsetWidth;
		if (left < pos) {
			this.scrollTo(left, animate);
		} else if (right > (pos + area)) {
			this.scrollTo(right - area, animate);
		}
	},

	scrollTo: function(pos, animate) {
		this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
		if (!animate) {
			this.updateScrollButtons();
		}
	},

	onWheel: function(e) {
		var d = e.getWheelDelta() * this.wheelIncrement * -1;
		e.stopEvent();

		var pos = this.getScrollPos();
		var newpos = pos + d;
		var sw = this.getScrollWidth() - this.getScrollArea();

		var s = Math.max(0, Math.min(sw, newpos));
		if (s != pos) {
			this.scrollTo(s, false);
		}
	},

	onScrollRight: function() {
		var sw = this.getScrollWidth() - this.getScrollArea();
		var pos = this.getScrollPos();
		var s = Math.min(sw, pos + this.getScrollIncrement());
		if (s != pos) {
			this.scrollTo(s, this.animScroll);
		}
	},

	onScrollLeft: function() {
		var pos = this.getScrollPos();
		var s = Math.max(0, pos - this.getScrollIncrement());
		if (s != pos) {
			this.scrollTo(s, this.animScroll);
		}
	},

	updateScrollButtons: function() {
		var pos = this.getScrollPos();
		this.scrollLeft[pos == 0 ? 'addClass': 'removeClass']('x-tab-scroller-left-disabled');
		this.scrollRight[pos >= (this.getScrollWidth() - this.getScrollArea()) ? 'addClass': 'removeClass']('x-tab-scroller-right-disabled');
	}

});
Ext.reg('tabpanel', Ext.TabPanel);

Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;

Ext.TabPanel.AccessStack = function() {
	var items = [];
	return {
		add: function(item) {
			items.push(item);
			if (items.length > 10) {
				items.shift();
			}
		},

		remove: function(item) {
			var s = [];
			for (var i = 0, len = items.length; i < len; i++) {
				if (items[i] != item) {
					s.push(items[i]);
				}
			}
			items = s;
		},

		next: function() {
			return items.pop();
		}
	};
};

Ext.Button = Ext.extend(Ext.Component, {

	hidden: false,

	disabled: false,

	pressed: false,

	enableToggle: false,

	menuAlign: "tl-bl?",

	type: 'button',

	menuClassTarget: 'tr',

	clickEvent: 'click',

	handleMouseEvents: true,

	tooltipType: 'qtip',

	buttonSelector: "button:first",

	initComponent: function() {
		Ext.Button.superclass.initComponent.call(this);

		this.addEvents(
		"click",
		"toggle",
		'mouseover',
		'mouseout',
		'menushow',
		'menuhide',
		'menutriggerover',
		'menutriggerout');
		if (this.menu) {
			this.menu = Ext.menu.MenuMgr.get(this.menu);
		}
		if (typeof this.toggleGroup === 'string') {
			this.enableToggle = true;
		}
	},

	onRender: function(ct, position) {
		if (!this.template) {
			if (!Ext.Button.buttonTemplate) {
				Ext.Button.buttonTemplate = new Ext.Template('<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>', '<td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}">{0}</button></em></td><td class="x-btn-right"><i>&#160;</i></td>', "</tr></tbody></table>");
			}
			this.template = Ext.Button.buttonTemplate;
		}
		var btn,
		targs = [this.text || '&#160;', this.type];

		if (position) {
			btn = this.template.insertBefore(position, targs, true);
		} else {
			btn = this.template.append(ct, targs, true);
		}
		var btnEl = btn.child(this.buttonSelector);
		btnEl.on('focus', this.onFocus, this);
		btnEl.on('blur', this.onBlur, this);

		this.initButtonEl(btn, btnEl);

		if (this.menu) {
			this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
		}
		Ext.ButtonToggleMgr.register(this);
	},

	initButtonEl: function(btn, btnEl) {

		this.el = btn;
		btn.addClass("x-btn");

		if (this.icon) {
			btnEl.setStyle('background-image', 'url(' + this.icon + ')');
		}
		if (this.iconCls) {
			btnEl.addClass(this.iconCls);
			if (!this.cls) {
				btn.addClass(this.text ? 'x-btn-text-icon': 'x-btn-icon');
			}
		}
		if (this.tabIndex !== undefined) {
			btnEl.dom.tabIndex = this.tabIndex;
		}
		if (this.tooltip) {
			if (typeof this.tooltip == 'object') {
				Ext.QuickTips.register(Ext.apply({
					target: btnEl.id
				},
				this.tooltip));
			} else {
				btnEl.dom[this.tooltipType] = this.tooltip;
			}
		}

		if (this.pressed) {
			this.el.addClass("x-btn-pressed");
		}

		if (this.handleMouseEvents) {
			btn.on("mouseover", this.onMouseOver, this);
			btn.on("mousedown", this.onMouseDown, this);
		}

		if (this.menu) {
			this.menu.on("show", this.onMenuShow, this);
			this.menu.on("hide", this.onMenuHide, this);
		}

		if (this.id) {
			this.el.dom.id = this.el.id = this.id;
		}

		if (this.repeat) {
			var repeater = new Ext.util.ClickRepeater(btn, typeof this.repeat == "object" ? this.repeat: {});
			repeater.on("click", this.onClick, this);
		}

		btn.on(this.clickEvent, this.onClick, this);
	},

	afterRender: function() {
		Ext.Button.superclass.afterRender.call(this);
		if (Ext.isIE6) {
			this.autoWidth.defer(1, this);
		} else {
			this.autoWidth();
		}
	},

	setIconClass: function(cls) {
		if (this.el) {
			this.el.child(this.buttonSelector).replaceClass(this.iconCls, cls);
		}
		this.iconCls = cls;
	},

	beforeDestroy: function() {
		if (this.rendered) {
			var btn = this.el.child(this.buttonSelector);
			if (btn) {
				btn.removeAllListeners();
			}
		}
		if (this.menu) {
			Ext.destroy(this.menu);
		}
	},

	onDestroy: function() {
		if (this.rendered) {
			Ext.ButtonToggleMgr.unregister(this);
		}
	},

	autoWidth: function() {
		if (this.el) {
			this.el.setWidth("auto");
			if (Ext.isIE7 && Ext.isStrict) {
				var ib = this.el.child(this.buttonSelector);
				if (ib && ib.getWidth() > 20) {
					ib.clip();
					ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width + ib.getFrameWidth('lr'));
				}
			}
			if (this.minWidth) {
				if (this.el.getWidth() < this.minWidth) {
					this.el.setWidth(this.minWidth);
				}
			}
		}
	},

	setHandler: function(handler, scope) {
		this.handler = handler;
		this.scope = scope;
	},

	setText: function(text) {
		this.text = text;
		if (this.el) {
			this.el.child("td.x-btn-center " + this.buttonSelector).update(text);
		}
		this.autoWidth();
	},

	getText: function() {
		return this.text;
	},

	toggle: function(state) {
		state = state === undefined ? !this.pressed: state;
		if (state != this.pressed) {
			if (state) {
				this.el.addClass("x-btn-pressed");
				this.pressed = true;
				this.fireEvent("toggle", this, true);
			} else {
				this.el.removeClass("x-btn-pressed");
				this.pressed = false;
				this.fireEvent("toggle", this, false);
			}
			if (this.toggleHandler) {
				this.toggleHandler.call(this.scope || this, this, state);
			}
		}
	},

	focus: function() {
		this.el.child(this.buttonSelector).focus();
	},

	onDisable: function() {
		if (this.el) {
			if (!Ext.isIE6 || !this.text) {
				this.el.addClass(this.disabledClass);
			}
			this.el.dom.disabled = true;
		}
		this.disabled = true;
	},

	onEnable: function() {
		if (this.el) {
			if (!Ext.isIE6 || !this.text) {
				this.el.removeClass(this.disabledClass);
			}
			this.el.dom.disabled = false;
		}
		this.disabled = false;
	},

	showMenu: function() {
		if (this.menu) {
			this.menu.show(this.el, this.menuAlign);
		}
		return this;
	},

	hideMenu: function() {
		if (this.menu) {
			this.menu.hide();
		}
		return this;
	},

	hasVisibleMenu: function() {
		return this.menu && this.menu.isVisible();
	},

	onClick: function(e) {
		if (e) {
			e.preventDefault();
		}
		if (e.button != 0) {
			return;
		}
		if (!this.disabled) {
			if (this.enableToggle && (this.allowDepress !== false || !this.pressed)) {
				this.toggle();
			}
			if (this.menu && !this.menu.isVisible() && !this.ignoreNextClick) {
				this.showMenu();
			}
			this.fireEvent("click", this, e);
			if (this.handler) {
				this.handler.call(this.scope || this, this, e);
			}
		}
	},

	isMenuTriggerOver: function(e, internal) {
		return this.menu && !internal;
	},

	isMenuTriggerOut: function(e, internal) {
		return this.menu && !internal;
	},

	onMouseOver: function(e) {
		if (!this.disabled) {
			var internal = e.within(this.el, true);
			if (!internal) {
				this.el.addClass("x-btn-over");
				if (!this.monitoringMouseOver) {
					Ext.getDoc().on('mouseover', this.monitorMouseOver, this);
					this.monitoringMouseOver = true;
				}
				this.fireEvent('mouseover', this, e);
			}
			if (this.isMenuTriggerOver(e, internal)) {
				this.fireEvent('menutriggerover', this, this.menu, e);
			}
		}
	},

	monitorMouseOver: function(e) {
		if (e.target != this.el.dom && !e.within(this.el)) {
			if (this.monitoringMouseOver) {
				Ext.getDoc().un('mouseover', this.monitorMouseOver, this);
				this.monitoringMouseOver = false;
			}
			this.onMouseOut(e);
		}
	},

	onMouseOut: function(e) {
		var internal = e.within(this.el) && e.target != this.el.dom;
		this.el.removeClass("x-btn-over");
		this.fireEvent('mouseout', this, e);
		if (this.isMenuTriggerOut(e, internal)) {
			this.fireEvent('menutriggerout', this, this.menu, e);
		}
	},
	onFocus: function(e) {
		if (!this.disabled) {
			this.el.addClass("x-btn-focus");
		}
	},
	onBlur: function(e) {
		this.el.removeClass("x-btn-focus");
	},

	getClickEl: function(e, isUp) {
		return this.el;
	},

	onMouseDown: function(e) {
		if (!this.disabled && e.button == 0) {
			this.getClickEl(e).addClass("x-btn-click");
			Ext.getDoc().on('mouseup', this.onMouseUp, this);
		}
	},
	onMouseUp: function(e) {
		if (e.button == 0) {
			this.getClickEl(e, true).removeClass("x-btn-click");
			Ext.getDoc().un('mouseup', this.onMouseUp, this);
		}
	},
	onMenuShow: function(e) {
		this.ignoreNextClick = 0;
		this.el.addClass("x-btn-menu-active");
		this.fireEvent('menushow', this, this.menu);
	},
	onMenuHide: function(e) {
		this.el.removeClass("x-btn-menu-active");
		this.ignoreNextClick = this.restoreClick.defer(250, this);
		this.fireEvent('menuhide', this, this.menu);
	},

	restoreClick: function() {
		this.ignoreNextClick = 0;
	}

});
Ext.reg('button', Ext.Button);

Ext.ButtonToggleMgr = function() {
	var groups = {};

	function toggleGroup(btn, state) {
		if (state) {
			var g = groups[btn.toggleGroup];
			for (var i = 0, l = g.length; i < l; i++) {
				if (g[i] != btn) {
					g[i].toggle(false);
				}
			}
		}
	}

	return {
		register: function(btn) {
			if (!btn.toggleGroup) {
				return;
			}
			var g = groups[btn.toggleGroup];
			if (!g) {
				g = groups[btn.toggleGroup] = [];
			}
			g.push(btn);
			btn.on("toggle", toggleGroup);
		},

		unregister: function(btn) {
			if (!btn.toggleGroup) {
				return;
			}
			var g = groups[btn.toggleGroup];
			if (g) {
				g.remove(btn);
				btn.un("toggle", toggleGroup);
			}
		}
	};
} ();

Ext.SplitButton = Ext.extend(Ext.Button, {

	arrowSelector: 'button:last',

	initComponent: function() {
		Ext.SplitButton.superclass.initComponent.call(this);

		this.addEvents("arrowclick");
	},

	onRender: function(ct, position) {

		var tpl = new Ext.Template('<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>', '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>', '<tr><td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><button class="x-btn-text" type="{1}">{0}</button></td></tr>', "</tbody></table></td><td>", '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>', '<tr><td class="x-btn-center"><button class="x-btn-menu-arrow-el" type="button">&#160;</button></td><td class="x-btn-right"><i>&#160;</i></td></tr>', "</tbody></table></td></tr></table>");
		var btn,
		targs = [this.text || '&#160;', this.type];
		if (position) {
			btn = tpl.insertBefore(position, targs, true);
		} else {
			btn = tpl.append(ct, targs, true);
		}
		var btnEl = btn.child(this.buttonSelector);

		this.initButtonEl(btn, btnEl);
		this.arrowBtnTable = btn.child("table:last");
		if (this.arrowTooltip) {
			btn.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
		}
	},

	autoWidth: function() {
		if (this.el) {
			var tbl = this.el.child("table:first");
			var tbl2 = this.el.child("table:last");
			this.el.setWidth("auto");
			tbl.setWidth("auto");
			if (Ext.isIE7 && Ext.isStrict) {
				var ib = this.el.child(this.buttonSelector);
				if (ib && ib.getWidth() > 20) {
					ib.clip();
					ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width + ib.getFrameWidth('lr'));
				}
			}
			if (this.minWidth) {
				if ((tbl.getWidth() + tbl2.getWidth()) < this.minWidth) {
					tbl.setWidth(this.minWidth - tbl2.getWidth());
				}
			}
			this.el.setWidth(tbl.getWidth() + tbl2.getWidth());
		}
	},

	setArrowHandler: function(handler, scope) {
		this.arrowHandler = handler;
		this.scope = scope;
	},

	onClick: function(e) {
		e.preventDefault();
		if (!this.disabled) {
			if (e.getTarget(".x-btn-menu-arrow-wrap")) {
				if (this.menu && !this.menu.isVisible() && !this.ignoreNextClick) {
					this.showMenu();
				}
				this.fireEvent("arrowclick", this, e);
				if (this.arrowHandler) {
					this.arrowHandler.call(this.scope || this, this, e);
				}
			} else {
				if (this.enableToggle) {
					this.toggle();
				}
				this.fireEvent("click", this, e);
				if (this.handler) {
					this.handler.call(this.scope || this, this, e);
				}
			}
		}
	},

	getClickEl: function(e, isUp) {
		if (!isUp) {
			return (this.lastClickEl = e.getTarget("table", 10, true));
		}
		return this.lastClickEl;
	},

	onDisable: function() {
		if (this.el) {
			if (!Ext.isIE6) {
				this.el.addClass("x-item-disabled");
			}
			this.el.child(this.buttonSelector).dom.disabled = true;
			this.el.child(this.arrowSelector).dom.disabled = true;
		}
		this.disabled = true;
	},

	onEnable: function() {
		if (this.el) {
			if (!Ext.isIE6) {
				this.el.removeClass("x-item-disabled");
			}
			this.el.child(this.buttonSelector).dom.disabled = false;
			this.el.child(this.arrowSelector).dom.disabled = false;
		}
		this.disabled = false;
	},

	isMenuTriggerOver: function(e) {
		return this.menu && e.within(this.arrowBtnTable) && !e.within(this.arrowBtnTable, true);
	},

	isMenuTriggerOut: function(e, internal) {
		return this.menu && !e.within(this.arrowBtnTable);
	},

	onDestroy: function() {
		Ext.destroy(this.arrowBtnTable);
		Ext.SplitButton.superclass.onDestroy.call(this);
	}
});

Ext.MenuButton = Ext.SplitButton;

Ext.reg('splitbutton', Ext.SplitButton);

Ext.CycleButton = Ext.extend(Ext.SplitButton, {

	getItemText: function(item) {
		if (item && this.showText === true) {
			var text = '';
			if (this.prependText) {
				text += this.prependText;
			}
			text += item.text;
			return text;
		}
		return undefined;
	},

	setActiveItem: function(item, suppressEvent) {
		if (typeof item != 'object') {
			item = this.menu.items.get(item);
		}
		if (item) {
			if (!this.rendered) {
				this.text = this.getItemText(item);
				this.iconCls = item.iconCls;
			} else {
				var t = this.getItemText(item);
				if (t) {
					this.setText(t);
				}
				this.setIconClass(item.iconCls);
			}
			this.activeItem = item;
			if (!item.checked) {
				item.setChecked(true, true);
			}
			if (this.forceIcon) {
				this.setIconClass(this.forceIcon);
			}
			if (!suppressEvent) {
				this.fireEvent('change', this, item);
			}
		}
	},

	getActiveItem: function() {
		return this.activeItem;
	},

	initComponent: function() {
		this.addEvents(
		"change");

		if (this.changeHandler) {
			this.on('change', this.changeHandler, this.scope || this);
			delete this.changeHandler;
		}

		this.itemCount = this.items.length;

		this.menu = {
			cls: 'x-cycle-menu',
			items: []
		};
		var checked;
		for (var i = 0, len = this.itemCount; i < len; i++) {
			var item = this.items[i];
			item.group = item.group || this.id;
			item.itemIndex = i;
			item.checkHandler = this.checkHandler;
			item.scope = this;
			item.checked = item.checked || false;
			this.menu.items.push(item);
			if (item.checked) {
				checked = item;
			}
		}
		this.setActiveItem(checked, true);
		Ext.CycleButton.superclass.initComponent.call(this);

		this.on('click', this.toggleSelected, this);
	},

	checkHandler: function(item, pressed) {
		if (pressed) {
			this.setActiveItem(item);
		}
	},

	toggleSelected: function() {
		this.menu.render();

		var nextIdx,
		checkItem;
		for (var i = 1; i < this.itemCount; i++) {
			nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;

			checkItem = this.menu.items.itemAt(nextIdx);

			if (!checkItem.disabled) {
				checkItem.setChecked(true);
				break;
			}
		}
	}
});
Ext.reg('cycle', Ext.CycleButton);

Ext.Toolbar = function(config) {
	if (Ext.isArray(config)) {
		config = {
			buttons: config
		};
	}
	Ext.Toolbar.superclass.constructor.call(this, config);
};
 (function() {

	var T = Ext.Toolbar;

	Ext.extend(T, Ext.BoxComponent, {

		trackMenus: true,

		initComponent: function() {
			T.superclass.initComponent.call(this);

			if (this.items) {
				this.buttons = this.items;
			}

			this.items = new Ext.util.MixedCollection(false,
			function(o) {
				return o.itemId || o.id || Ext.id();
			});
		},

		autoCreate: {
			cls: 'x-toolbar x-small-editor',
			html: '<table cellspacing="0"><tr></tr></table>'
		},

		onRender: function(ct, position) {
			this.el = ct.createChild(Ext.apply({
				id: this.id
			},
			this.autoCreate), position);
			this.tr = this.el.child("tr", true);
		},

		afterRender: function() {
			T.superclass.afterRender.call(this);
			if (this.buttons) {
				this.add.apply(this, this.buttons);
				delete this.buttons;
			}
		},

		add: function() {
			var a = arguments,
			l = a.length;
			for (var i = 0; i < l; i++) {
				var el = a[i];
				if (el.isFormField) {
					this.addField(el);
				} else if (el.render) {
					this.addItem(el);
				} else if (typeof el == "string") {
					if (el == "separator" || el == "-") {
						this.addSeparator();
					} else if (el == " ") {
						this.addSpacer();
					} else if (el == "->") {
						this.addFill();
					} else {
						this.addText(el);
					}
				} else if (el.tagName) {
					this.addElement(el);
				} else if (typeof el == "object") {
					if (el.xtype) {
						this.addField(Ext.ComponentMgr.create(el, 'button'));
					} else {
						this.addButton(el);
					}
				}
			}
		},

		addSeparator: function() {
			return this.addItem(new T.Separator());
		},

		addSpacer: function() {
			return this.addItem(new T.Spacer());
		},

		addFill: function() {
			return this.addItem(new T.Fill());
		},

		addElement: function(el) {
			return this.addItem(new T.Item(el));
		},

		addItem: function(item) {
			var td = this.nextBlock();
			this.initMenuTracking(item);
			item.render(td);
			this.items.add(item);
			return item;
		},

		addButton: function(config) {
			if (Ext.isArray(config)) {
				var buttons = [];
				for (var i = 0, len = config.length; i < len; i++) {
					buttons.push(this.addButton(config[i]));
				}
				return buttons;
			}
			var b = config;
			if (! (config instanceof T.Button)) {
				b = config.split ? new T.SplitButton(config) : new T.Button(config);
			}
			var td = this.nextBlock();
			this.initMenuTracking(b);
			b.render(td);
			this.items.add(b);
			return b;
		},

		initMenuTracking: function(item) {
			if (this.trackMenus && item.menu) {
				item.on({
					'menutriggerover': this.onButtonTriggerOver,
					'menushow': this.onButtonMenuShow,
					'menuhide': this.onButtonMenuHide,
					scope: this
				})
			}
		},

		addText: function(text) {
			return this.addItem(new T.TextItem(text));
		},

		insertButton: function(index, item) {
			if (Ext.isArray(item)) {
				var buttons = [];
				for (var i = 0, len = item.length; i < len; i++) {
					buttons.push(this.insertButton(index + i, item[i]));
				}
				return buttons;
			}
			if (! (item instanceof T.Button)) {
				item = new T.Button(item);
			}
			var td = document.createElement("td");
			this.tr.insertBefore(td, this.tr.childNodes[index]);
			this.initMenuTracking(item);
			item.render(td);
			this.items.insert(index, item);
			return item;
		},

		addDom: function(config, returnEl) {
			var td = this.nextBlock();
			Ext.DomHelper.overwrite(td, config);
			var ti = new T.Item(td.firstChild);
			ti.render(td);
			this.items.add(ti);
			return ti;
		},

		addField: function(field) {
			var td = this.nextBlock();
			field.render(td);
			var ti = new T.Item(td.firstChild);
			ti.render(td);
			this.items.add(field);
			return ti;
		},

		nextBlock: function() {
			var td = document.createElement("td");
			this.tr.appendChild(td);
			return td;
		},

		onDestroy: function() {
			Ext.Toolbar.superclass.onDestroy.call(this);
			if (this.rendered) {
				if (this.items) {
					Ext.destroy.apply(Ext, this.items.items);
				}
				Ext.Element.uncache(this.tr);
			}
		},

		onDisable: function() {
			this.items.each(function(item) {
				if (item.disable) {
					item.disable();
				}
			});
		},

		onEnable: function() {
			this.items.each(function(item) {
				if (item.enable) {
					item.enable();
				}
			});
		},

		onButtonTriggerOver: function(btn) {
			if (this.activeMenuBtn && this.activeMenuBtn != btn) {
				this.activeMenuBtn.hideMenu();
				btn.showMenu();
				this.activeMenuBtn = btn;
			}
		},

		onButtonMenuShow: function(btn) {
			this.activeMenuBtn = btn;
		},

		onButtonMenuHide: function(btn) {
			delete this.activeMenuBtn;
		}

	});
	Ext.reg('toolbar', Ext.Toolbar);

	T.Item = function(el) {
		this.el = Ext.getDom(el);
		this.id = Ext.id(this.el);
		this.hidden = false;
	};

	T.Item.prototype = {

		getEl: function() {
			return this.el;
		},

		render: function(td) {
			this.td = td;
			td.appendChild(this.el);
		},

		destroy: function() {
			if (this.td && this.td.parentNode) {
				this.td.parentNode.removeChild(this.td);
			}
		},

		show: function() {
			this.hidden = false;
			this.td.style.display = "";
		},

		hide: function() {
			this.hidden = true;
			this.td.style.display = "none";
		},

		setVisible: function(visible) {
			if (visible) {
				this.show();
			} else {
				this.hide();
			}
		},

		focus: function() {
			Ext.fly(this.el).focus();
		},

		disable: function() {
			Ext.fly(this.td).addClass("x-item-disabled");
			this.disabled = true;
			this.el.disabled = true;
		},

		enable: function() {
			Ext.fly(this.td).removeClass("x-item-disabled");
			this.disabled = false;
			this.el.disabled = false;
		}
	};
	Ext.reg('tbitem', T.Item);

	T.Separator = function() {
		var s = document.createElement("span");
		s.className = "ytb-sep";
		T.Separator.superclass.constructor.call(this, s);
	};
	Ext.extend(T.Separator, T.Item, {
		enable: Ext.emptyFn,
		disable: Ext.emptyFn,
		focus: Ext.emptyFn
	});
	Ext.reg('tbseparator', T.Separator);

	T.Spacer = function() {
		var s = document.createElement("div");
		s.className = "ytb-spacer";
		T.Spacer.superclass.constructor.call(this, s);
	};
	Ext.extend(T.Spacer, T.Item, {
		enable: Ext.emptyFn,
		disable: Ext.emptyFn,
		focus: Ext.emptyFn
	});

	Ext.reg('tbspacer', T.Spacer);

	T.Fill = Ext.extend(T.Spacer, {

		render: function(td) {
			td.style.width = '100%';
			T.Fill.superclass.render.call(this, td);
		}
	});
	Ext.reg('tbfill', T.Fill);

	T.TextItem = function(t) {
		var s = document.createElement("span");
		s.className = "ytb-text";
		s.innerHTML = t.text ? t.text: t;
		T.TextItem.superclass.constructor.call(this, s);
	};
	Ext.extend(T.TextItem, T.Item, {
		enable: Ext.emptyFn,
		disable: Ext.emptyFn,
		focus: Ext.emptyFn
	});
	Ext.reg('tbtext', T.TextItem);

	T.Button = Ext.extend(Ext.Button, {
		hideParent: true,

		onDestroy: function() {
			T.Button.superclass.onDestroy.call(this);
			if (this.container) {
				this.container.remove();
			}
		}
	});
	Ext.reg('tbbutton', T.Button);

	T.SplitButton = Ext.extend(Ext.SplitButton, {
		hideParent: true,

		onDestroy: function() {
			T.SplitButton.superclass.onDestroy.call(this);
			if (this.container) {
				this.container.remove();
			}
		}
	});

	Ext.reg('tbsplit', T.SplitButton);

	T.MenuButton = T.SplitButton;

})();

Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {

	pageSize: 20,

	displayMsg: 'Displaying {0} - {1} of {2}',

	emptyMsg: 'No data to display',

	beforePageText: "Page",

	afterPageText: "of {0}",

	firstText: "First Page",

	prevText: "Previous Page",

	nextText: "Next Page",

	lastText: "Last Page",

	refreshText: "Refresh",

	paramNames: {
		start: 'start',
		limit: 'limit'
	},

	initComponent: function() {
		this.addEvents('change', 'beforechange');
		Ext.PagingToolbar.superclass.initComponent.call(this);
		this.cursor = 0;
		this.bind(this.store);
	},

	onRender: function(ct, position) {
		Ext.PagingToolbar.superclass.onRender.call(this, ct, position);
		this.first = this.addButton({
			tooltip: this.firstText,
			iconCls: "x-tbar-page-first",
			disabled: true,
			handler: this.onClick.createDelegate(this, ["first"])
		});
		this.prev = this.addButton({
			tooltip: this.prevText,
			iconCls: "x-tbar-page-prev",
			disabled: true,
			handler: this.onClick.createDelegate(this, ["prev"])
		});
		this.addSeparator();
		this.add(this.beforePageText);
		this.field = Ext.get(this.addDom({
			tag: "input",
			type: "text",
			size: "3",
			value: "1",
			cls: "x-tbar-page-number"
		}).el);
		this.field.on("keydown", this.onPagingKeydown, this);
		this.field.on("focus",
		function() {
			this.dom.select();
		});
		this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
		this.field.setHeight(18);
		this.addSeparator();
		this.next = this.addButton({
			tooltip: this.nextText,
			iconCls: "x-tbar-page-next",
			disabled: true,
			handler: this.onClick.createDelegate(this, ["next"])
		});
		this.last = this.addButton({
			tooltip: this.lastText,
			iconCls: "x-tbar-page-last",
			disabled: true,
			handler: this.onClick.createDelegate(this, ["last"])
		});
		this.addSeparator();
		this.loading = this.addButton({
			tooltip: this.refreshText,
			iconCls: "x-tbar-loading",
			handler: this.onClick.createDelegate(this, ["refresh"])
		});

		if (this.displayInfo) {
			this.displayEl = Ext.fly(this.el.dom).createChild({
				cls: 'x-paging-info'
			});
		}
		if (this.dsLoaded) {
			this.onLoad.apply(this, this.dsLoaded);
		}
	},

	updateInfo: function() {
		if (this.displayEl) {
			var count = this.store.getCount();
			var msg = count == 0 ? this.emptyMsg: String.format(this.displayMsg, this.cursor + 1, this.cursor + count, this.store.getTotalCount());
			this.displayEl.update(msg);
		}
	},

	onLoad: function(store, r, o) {
		if (!this.rendered) {
			this.dsLoaded = [store, r, o];
			return;
		}
		this.cursor = o.params ? o.params[this.paramNames.start] : 0;
		var d = this.getPageData(),
		ap = d.activePage,
		ps = d.pages;

		this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
		this.field.dom.value = ap;
		this.first.setDisabled(ap == 1);
		this.prev.setDisabled(ap == 1);
		this.next.setDisabled(ap == ps);
		this.last.setDisabled(ap == ps);
		this.loading.enable();
		this.updateInfo();
		this.fireEvent('change', this, d);
	},

	getPageData: function() {
		var total = this.store.getTotalCount();
		return {
			total: total,
			activePage: Math.ceil((this.cursor + this.pageSize) / this.pageSize),
			pages: total < this.pageSize ? 1: Math.ceil(total / this.pageSize)
		};
	},

	onLoadError: function() {
		if (!this.rendered) {
			return;
		}
		this.loading.enable();
	},

	readPage: function(d) {
		var v = this.field.dom.value,
		pageNum;
		if (!v || isNaN(pageNum = parseInt(v, 10))) {
			this.field.dom.value = d.activePage;
			return false;
		}
		return pageNum;
	},

	onPagingKeydown: function(e) {
		var k = e.getKey(),
		d = this.getPageData(),
		pageNum;
		if (k == e.RETURN) {
			e.stopEvent();
			pageNum = this.readPage(d);
			if (pageNum !== false) {
				pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
				this.doLoad(pageNum * this.pageSize);
			}
		} else if (k == e.HOME || k == e.END) {
			e.stopEvent();
			pageNum = k == e.HOME ? 1: d.pages;
			this.field.dom.value = pageNum;
		} else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
			e.stopEvent();
			if (pageNum = this.readPage(d)) {
				var increment = e.shiftKey ? 10: 1;
				if (k == e.DOWN || k == e.PAGEDOWN) {
					increment *= -1;
				}
				pageNum += increment;
				if (pageNum >= 1 & pageNum <= d.pages) {
					this.field.dom.value = pageNum;
				}
			}
		}
	},

	beforeLoad: function() {
		if (this.rendered && this.loading) {
			this.loading.disable();
		}
	},

	doLoad: function(start) {
		var o = {},
		pn = this.paramNames;
		o[pn.start] = start;
		o[pn.limit] = this.pageSize;
		if (this.fireEvent('beforechange', this, o) !== false) {
			this.store.load({
				params: o
			});
		}
	},

	changePage: function(page) {
		this.doLoad(((page - 1) * this.pageSize).constrain(0, this.store.getTotalCount()));
	},

	onClick: function(which) {
		var store = this.store;
		switch (which) {
		case "first":
			this.doLoad(0);
			break;
		case "prev":
			this.doLoad(Math.max(0, this.cursor - this.pageSize));
			break;
		case "next":
			this.doLoad(this.cursor + this.pageSize);
			break;
		case "last":
			var total = store.getTotalCount();
			var extra = total % this.pageSize;
			var lastStart = extra ? (total - extra) : total - this.pageSize;
			this.doLoad(lastStart);
			break;
		case "refresh":
			this.doLoad(this.cursor);
			break;
		}
	},

	unbind: function(store) {
		store = Ext.StoreMgr.lookup(store);
		store.un("beforeload", this.beforeLoad, this);
		store.un("load", this.onLoad, this);
		store.un("loadexception", this.onLoadError, this);
		this.store = undefined;
	},

	bind: function(store) {
		store = Ext.StoreMgr.lookup(store);
		store.on("beforeload", this.beforeLoad, this);
		store.on("load", this.onLoad, this);
		store.on("loadexception", this.onLoadError, this);
		this.store = store;
	}
});
Ext.reg('paging', Ext.PagingToolbar);

Ext.Resizable = function(el, config) {
	this.el = Ext.get(el);

	if (config && config.wrap) {
		config.resizeChild = this.el;
		this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap: {
			cls: "xresizable-wrap"
		});
		this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";
		this.el.setStyle("overflow", "hidden");
		this.el.setPositioning(config.resizeChild.getPositioning());
		config.resizeChild.clearPositioning();
		if (!config.width || !config.height) {
			var csize = config.resizeChild.getSize();
			this.el.setSize(csize.width, csize.height);
		}
		if (config.pinned && !config.adjustments) {
			config.adjustments = "auto";
		}
	}

	this.proxy = this.el.createProxy({
		tag: "div",
		cls: "x-resizable-proxy",
		id: this.el.id + "-rzproxy"
	},
	Ext.getBody());
	this.proxy.unselectable();
	this.proxy.enableDisplayMode('block');

	Ext.apply(this, config);

	if (this.pinned) {
		this.disableTrackOver = true;
		this.el.addClass("x-resizable-pinned");
	}

	var position = this.el.getStyle("position");
	if (position != "absolute" && position != "fixed") {
		this.el.setStyle("position", "relative");
	}
	if (!this.handles) {
		this.handles = 's,e,se';
		if (this.multiDirectional) {
			this.handles += ',n,w';
		}
	}
	if (this.handles == "all") {
		this.handles = "n s e w ne nw se sw";
	}
	var hs = this.handles.split(/\s*?[,;]\s*?| /);
	var ps = Ext.Resizable.positions;
	for (var i = 0, len = hs.length; i < len; i++) {
		if (hs[i] && ps[hs[i]]) {
			var pos = ps[hs[i]];
			this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
		}
	}

	this.corner = this.southeast;

	if (this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1) {
		this.updateBox = true;
	}

	this.activeHandle = null;

	if (this.resizeChild) {
		if (typeof this.resizeChild == "boolean") {
			this.resizeChild = Ext.get(this.el.dom.firstChild, true);
		} else {
			this.resizeChild = Ext.get(this.resizeChild, true);
		}
	}

	if (this.adjustments == "auto") {
		var rc = this.resizeChild;
		var hw = this.west,
		he = this.east,
		hn = this.north,
		hs = this.south;
		if (rc && (hw || hn)) {
			rc.position("relative");
			rc.setLeft(hw ? hw.el.getWidth() : 0);
			rc.setTop(hn ? hn.el.getHeight() : 0);
		}
		this.adjustments = [(he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0), (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) - 1];
	}

	if (this.draggable) {
		this.dd = this.dynamic ? this.el.initDD(null) : this.el.initDDProxy(null, {
			dragElId: this.proxy.id
		});
		this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id: this.el.id);
	}

	this.addEvents("beforeresize", "resize");

	if (this.width !== null && this.height !== null) {
		this.resizeTo(this.width, this.height);
	} else {
		this.updateChildSize();
	}
	if (Ext.isIE) {
		this.el.dom.style.zoom = 1;
	}
	Ext.Resizable.superclass.constructor.call(this);
};

Ext.extend(Ext.Resizable, Ext.util.Observable, {
	resizeChild: false,
	adjustments: [0, 0],
	minWidth: 5,
	minHeight: 5,
	maxWidth: 10000,
	maxHeight: 10000,
	enabled: true,
	animate: false,
	duration: .35,
	dynamic: false,
	handles: false,
	multiDirectional: false,
	disableTrackOver: false,
	easing: 'easeOutStrong',
	widthIncrement: 0,
	heightIncrement: 0,
	pinned: false,
	width: null,
	height: null,
	preserveRatio: false,
	transparent: false,
	minX: 0,
	minY: 0,
	draggable: false,

	resizeTo: function(width, height) {
		this.el.setSize(width, height);
		this.updateChildSize();
		this.fireEvent("resize", this, width, height, null);
	},

	startSizing: function(e, handle) {
		this.fireEvent("beforeresize", this, e);
		if (this.enabled) {

			if (!this.overlay) {
				this.overlay = this.el.createProxy({
					tag: "div",
					cls: "x-resizable-overlay",
					html: "&#160;"
				},
				Ext.getBody());
				this.overlay.unselectable();
				this.overlay.enableDisplayMode("block");
				this.overlay.on("mousemove", this.onMouseMove, this);
				this.overlay.on("mouseup", this.onMouseUp, this);
			}
			this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));

			this.resizing = true;
			this.startBox = this.el.getBox();
			this.startPoint = e.getXY();
			this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0], (this.startBox.y + this.startBox.height) - this.startPoint[1]];

			this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
			this.overlay.show();

			if (this.constrainTo) {
				var ct = Ext.get(this.constrainTo);
				this.resizeRegion = ct.getRegion().adjust(ct.getFrameWidth('t'), ct.getFrameWidth('l'), -ct.getFrameWidth('b'), -ct.getFrameWidth('r'));
			}

			this.proxy.setStyle('visibility', 'hidden');
			this.proxy.show();
			this.proxy.setBox(this.startBox);
			if (!this.dynamic) {
				this.proxy.setStyle('visibility', 'visible');
			}
		}
	},

	onMouseDown: function(handle, e) {
		if (this.enabled) {
			e.stopEvent();
			this.activeHandle = handle;
			this.startSizing(e, handle);
		}
	},

	onMouseUp: function(e) {
		var size = this.resizeElement();
		this.resizing = false;
		this.handleOut();
		this.overlay.hide();
		this.proxy.hide();
		this.fireEvent("resize", this, size.width, size.height, e);
	},

	updateChildSize: function() {
		if (this.resizeChild) {
			var el = this.el;
			var child = this.resizeChild;
			var adj = this.adjustments;
			if (el.dom.offsetWidth) {
				var b = el.getSize(true);
				child.setSize(b.width + adj[0], b.height + adj[1]);
			}

			if (Ext.isIE) {
				setTimeout(function() {
					if (el.dom.offsetWidth) {
						var b = el.getSize(true);
						child.setSize(b.width + adj[0], b.height + adj[1]);
					}
				},
				10);
			}
		}
	},

	snap: function(value, inc, min) {
		if (!inc || !value) return value;
		var newValue = value;
		var m = value % inc;
		if (m > 0) {
			if (m > (inc / 2)) {
				newValue = value + (inc - m);
			} else {
				newValue = value - m;
			}
		}
		return Math.max(min, newValue);
	},

	resizeElement: function() {
		var box = this.proxy.getBox();
		if (this.updateBox) {
			this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
		} else {
			this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
		}
		this.updateChildSize();
		if (!this.dynamic) {
			this.proxy.hide();
		}
		return box;
	},

	constrain: function(v, diff, m, mx) {
		if (v - diff < m) {
			diff = v - m;
		} else if (v - diff > mx) {
			diff = mx - v;
		}
		return diff;
	},

	onMouseMove: function(e) {
		if (this.enabled) {
			try {

				if (this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
					return;
				}

				var curSize = this.curSize || this.startBox;
				var x = this.startBox.x,
				y = this.startBox.y;
				var ox = x,
				oy = y;
				var w = curSize.width,
				h = curSize.height;
				var ow = w,
				oh = h;
				var mw = this.minWidth,
				mh = this.minHeight;
				var mxw = this.maxWidth,
				mxh = this.maxHeight;
				var wi = this.widthIncrement;
				var hi = this.heightIncrement;

				var eventXY = e.getXY();
				var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
				var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));

				var pos = this.activeHandle.position;

				switch (pos) {
				case "east":
					w += diffX;
					w = Math.min(Math.max(mw, w), mxw);
					break;
				case "south":
					h += diffY;
					h = Math.min(Math.max(mh, h), mxh);
					break;
				case "southeast":
					w += diffX;
					h += diffY;
					w = Math.min(Math.max(mw, w), mxw);
					h = Math.min(Math.max(mh, h), mxh);
					break;
				case "north":
					diffY = this.constrain(h, diffY, mh, mxh);
					y += diffY;
					h -= diffY;
					break;
				case "west":
					diffX = this.constrain(w, diffX, mw, mxw);
					x += diffX;
					w -= diffX;
					break;
				case "northeast":
					w += diffX;
					w = Math.min(Math.max(mw, w), mxw);
					diffY = this.constrain(h, diffY, mh, mxh);
					y += diffY;
					h -= diffY;
					break;
				case "northwest":
					diffX = this.constrain(w, diffX, mw, mxw);
					diffY = this.constrain(h, diffY, mh, mxh);
					y += diffY;
					h -= diffY;
					x += diffX;
					w -= diffX;
					break;
				case "southwest":
					diffX = this.constrain(w, diffX, mw, mxw);
					h += diffY;
					h = Math.min(Math.max(mh, h), mxh);
					x += diffX;
					w -= diffX;
					break;
				}

				var sw = this.snap(w, wi, mw);
				var sh = this.snap(h, hi, mh);
				if (sw != w || sh != h) {
					switch (pos) {
					case "northeast":
						y -= sh - h;
						break;
					case "north":
						y -= sh - h;
						break;
					case "southwest":
						x -= sw - w;
						break;
					case "west":
						x -= sw - w;
						break;
					case "northwest":
						x -= sw - w;
						y -= sh - h;
						break;
					}
					w = sw;
					h = sh;
				}

				if (this.preserveRatio) {
					switch (pos) {
					case "southeast":
					case "east":
						h = oh * (w / ow);
						h = Math.min(Math.max(mh, h), mxh);
						w = ow * (h / oh);
						break;
					case "south":
						w = ow * (h / oh);
						w = Math.min(Math.max(mw, w), mxw);
						h = oh * (w / ow);
						break;
					case "northeast":
						w = ow * (h / oh);
						w = Math.min(Math.max(mw, w), mxw);
						h = oh * (w / ow);
						break;
					case "north":
						var tw = w;
						w = ow * (h / oh);
						w = Math.min(Math.max(mw, w), mxw);
						h = oh * (w / ow);
						x += (tw - w) / 2;
						break;
					case "southwest":
						h = oh * (w / ow);
						h = Math.min(Math.max(mh, h), mxh);
						var tw = w;
						w = ow * (h / oh);
						x += tw - w;
						break;
					case "west":
						var th = h;
						h = oh * (w / ow);
						h = Math.min(Math.max(mh, h), mxh);
						y += (th - h) / 2;
						var tw = w;
						w = ow * (h / oh);
						x += tw - w;
						break;
					case "northwest":
						var tw = w;
						var th = h;
						h = oh * (w / ow);
						h = Math.min(Math.max(mh, h), mxh);
						w = ow * (h / oh);
						y += th - h;
						x += tw - w;
						break;

					}
				}
				this.proxy.setBounds(x, y, w, h);
				if (this.dynamic) {
					this.resizeElement();
				}
			} catch(e) {}
		}
	},

	handleOver: function() {
		if (this.enabled) {
			this.el.addClass("x-resizable-over");
		}
	},

	handleOut: function() {
		if (!this.resizing) {
			this.el.removeClass("x-resizable-over");
		}
	},

	getEl: function() {
		return this.el;
	},

	getResizeChild: function() {
		return this.resizeChild;
	},

	destroy: function(removeEl) {
		this.proxy.remove();
		if (this.overlay) {
			this.overlay.removeAllListeners();
			this.overlay.remove();
		}
		var ps = Ext.Resizable.positions;
		for (var k in ps) {
			if (typeof ps[k] != "function" && this[ps[k]]) {
				var h = this[ps[k]];
				h.el.removeAllListeners();
				h.el.remove();
			}
		}
		if (removeEl) {
			this.el.update("");
			this.el.remove();
		}
	},

	syncHandleHeight: function() {
		var h = this.el.getHeight(true);
		if (this.west) {
			this.west.el.setHeight(h);
		}
		if (this.east) {
			this.east.el.setHeight(h);
		}
	}
});

Ext.Resizable.positions = {
	n: "north",
	s: "south",
	e: "east",
	w: "west",
	se: "southeast",
	sw: "southwest",
	nw: "northwest",
	ne: "northeast"
};

Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent) {
	if (!this.tpl) {

		var tpl = Ext.DomHelper.createTemplate({
			tag: "div",
			cls: "x-resizable-handle x-resizable-handle-{0}"
		});
		tpl.compile();
		Ext.Resizable.Handle.prototype.tpl = tpl;
	}
	this.position = pos;
	this.rz = rz;
	this.el = this.tpl.append(rz.el.dom, [this.position], true);
	this.el.unselectable();
	if (transparent) {
		this.el.setOpacity(0);
	}
	this.el.on("mousedown", this.onMouseDown, this);
	if (!disableTrackOver) {
		this.el.on("mouseover", this.onMouseOver, this);
		this.el.on("mouseout", this.onMouseOut, this);
	}
};

Ext.Resizable.Handle.prototype = {
	afterResize: function(rz) {
		},

	onMouseDown: function(e) {
		this.rz.onMouseDown(this, e);
	},

	onMouseOver: function(e) {
		this.rz.handleOver(this, e);
	},

	onMouseOut: function(e) {
		this.rz.handleOut(this, e);
	}
};

Ext.Editor = function(field, config) {
	this.field = field;
	Ext.Editor.superclass.constructor.call(this, config);
};

Ext.extend(Ext.Editor, Ext.Component, {

	value: "",

	alignment: "c-c?",

	shadow: "frame",

	constrain: false,

	swallowKeys: true,

	completeOnEnter: false,

	cancelOnEsc: false,

	updateEl: false,

	initComponent: function() {
		Ext.Editor.superclass.initComponent.call(this);
		this.addEvents(
		"beforestartedit",
		"startedit",
		"beforecomplete",
		"complete",
		"canceledit",
		"specialkey");
	},

	onRender: function(ct, position) {
		this.el = new Ext.Layer({
			shadow: this.shadow,
			cls: "x-editor",
			parentEl: ct,
			shim: this.shim,
			shadowOffset: 4,
			id: this.id,
			constrain: this.constrain
		});
		this.el.setStyle("overflow", Ext.isGecko ? "auto": "hidden");
		if (this.field.msgTarget != 'title') {
			this.field.msgTarget = 'qtip';
		}
		this.field.inEditor = true;
		this.field.render(this.el);
		if (Ext.isGecko) {
			this.field.el.dom.setAttribute('autocomplete', 'off');
		}
		this.field.on("specialkey", this.onSpecialKey, this);
		if (this.swallowKeys) {
			this.field.el.swallowEvent(['keydown', 'keypress']);
		}
		this.field.show();
		this.field.on("blur", this.onBlur, this);
		if (this.field.grow) {
			this.field.on("autosize", this.el.sync, this.el, {
				delay: 1
			});
		}
	},

	onSpecialKey: function(field, e) {
		var key = e.getKey();
		if (this.completeOnEnter && key == e.ENTER) {
			e.stopEvent();
			this.completeEdit();
		} else if (this.cancelOnEsc && key == e.ESC) {
			this.cancelEdit();
		} else {
			this.fireEvent('specialkey', field, e);
		}
		if (this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)) {
			this.field.triggerBlur();
		}
	},

	startEdit: function(el, value) {
		if (this.editing) {
			this.completeEdit();
		}
		this.boundEl = Ext.get(el);
		var v = value !== undefined ? value: this.boundEl.dom.innerHTML;
		if (!this.rendered) {
			this.render(this.parentEl || document.body);
		}
		if (this.fireEvent("beforestartedit", this, this.boundEl, v) === false) {
			return;
		}
		this.startValue = v;
		this.field.setValue(v);
		this.doAutoSize();
		this.el.alignTo(this.boundEl, this.alignment);
		this.editing = true;
		this.show();
	},

	doAutoSize: function() {
		if (this.autoSize) {
			var sz = this.boundEl.getSize();
			switch (this.autoSize) {
			case "width":
				this.setSize(sz.width, "");
				break;
			case "height":
				this.setSize("", sz.height);
				break;
			default:
				this.setSize(sz.width, sz.height);
			}
		}
	},

	setSize: function(w, h) {
		delete this.field.lastSize;
		this.field.setSize(w, h);
		if (this.el) {
			if (Ext.isGecko2 || Ext.isOpera) {
				this.el.setSize(w, h);
			}
			this.el.sync();
		}
	},

	realign: function() {
		this.el.alignTo(this.boundEl, this.alignment);
	},

	completeEdit: function(remainVisible) {
		if (!this.editing) {
			return;
		}
		var v = this.getValue();
		if (this.revertInvalid !== false && !this.field.isValid()) {
			v = this.startValue;
			this.cancelEdit(true);
		}
		if (String(v) === String(this.startValue) && this.ignoreNoChange) {
			this.editing = false;
			this.hide();
			return;
		}
		if (this.fireEvent("beforecomplete", this, v, this.startValue) !== false) {
			this.editing = false;
			if (this.updateEl && this.boundEl) {
				this.boundEl.update(v);
			}
			if (remainVisible !== true) {
				this.hide();
			}
			this.fireEvent("complete", this, v, this.startValue);
		}
	},

	onShow: function() {
		this.el.show();
		if (this.hideEl !== false) {
			this.boundEl.hide();
		}
		this.field.show();
		if (Ext.isIE && !this.fixIEFocus) {
			this.fixIEFocus = true;
			this.deferredFocus.defer(50, this);
		} else {
			this.field.focus();
		}
		this.fireEvent("startedit", this.boundEl, this.startValue);
	},

	deferredFocus: function() {
		if (this.editing) {
			this.field.focus();
		}
	},

	cancelEdit: function(remainVisible) {
		if (this.editing) {
			var v = this.getValue();
			this.setValue(this.startValue);
			if (remainVisible !== true) {
				this.hide();
			}
			this.fireEvent("canceledit", this, v, this.startValue);
		}
	},

	onBlur: function() {
		if (this.allowBlur !== true && this.editing) {
			this.completeEdit();
		}
	},

	onHide: function() {
		if (this.editing) {
			this.completeEdit();
			return;
		}
		this.field.blur();
		if (this.field.collapse) {
			this.field.collapse();
		}
		this.el.hide();
		if (this.hideEl !== false) {
			this.boundEl.show();
		}
	},

	setValue: function(v) {
		this.field.setValue(v);
	},

	getValue: function() {
		return this.field.getValue();
	},

	beforeDestroy: function() {
		this.field.destroy();
		this.field = null;
	}
});
Ext.reg('editor', Ext.Editor);

Ext.MessageBox = function() {
	var dlg,
	opt,
	mask,
	waitTimer;
	var bodyEl,
	msgEl,
	textboxEl,
	textareaEl,
	progressBar,
	pp,
	iconEl,
	spacerEl;
	var buttons,
	activeTextEl,
	bwidth,
	iconCls = '';

	var handleButton = function(button) {
		if (dlg.isVisible()) {
			dlg.hide();
			Ext.callback(opt.fn, opt.scope || window, [button, activeTextEl.dom.value], 1);
		}
	};

	var handleHide = function() {
		if (opt && opt.cls) {
			dlg.el.removeClass(opt.cls);
		}
		progressBar.reset();
	};

	var handleEsc = function(d, k, e) {
		if (opt && opt.closable !== false) {
			dlg.hide();
		}
		if (e) {
			e.stopEvent();
		}
	};

	var updateButtons = function(b) {
		var width = 0;
		if (!b) {
			buttons["ok"].hide();
			buttons["cancel"].hide();
			buttons["yes"].hide();
			buttons["no"].hide();
			return width;
		}
		dlg.footer.dom.style.display = '';
		for (var k in buttons) {
			if (typeof buttons[k] != "function") {
				if (b[k]) {
					buttons[k].show();
					buttons[k].setText(typeof b[k] == "string" ? b[k] : Ext.MessageBox.buttonText[k]);
					width += buttons[k].el.getWidth() + 15;
				} else {
					buttons[k].hide();
				}
			}
		}
		return width;
	};

	return {

		getDialog: function(titleText) {
			if (!dlg) {
				dlg = new Ext.Window({
					autoCreate: true,
					title: titleText,
					resizable: false,
					constrain: true,
					constrainHeader: true,
					minimizable: false,
					maximizable: false,
					stateful: false,
					modal: true,
					shim: true,
					buttonAlign: "center",
					width: 400,
					height: 100,
					minHeight: 80,
					plain: true,
					footer: true,
					closable: true,
					close: function() {
						if (opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel) {
							handleButton("no");
						} else {
							handleButton("cancel");
						}
					}
				});
				buttons = {};
				var bt = this.buttonText;
				buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
				buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
				buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
				buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
				buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';
				dlg.render(document.body);
				dlg.getEl().addClass('x-window-dlg');
				mask = dlg.mask;
				bodyEl = dlg.body.createChild({
					html: '<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
				});
				iconEl = Ext.get(bodyEl.dom.firstChild);
				var contentEl = bodyEl.dom.childNodes[1];
				msgEl = Ext.get(contentEl.firstChild);
				textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
				textboxEl.enableDisplayMode();
				textboxEl.addKeyListener([10, 13],
				function() {
					if (dlg.isVisible() && opt && opt.buttons) {
						if (opt.buttons.ok) {
							handleButton("ok");
						} else if (opt.buttons.yes) {
							handleButton("yes");
						}
					}
				});
				textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
				textareaEl.enableDisplayMode();
				progressBar = new Ext.ProgressBar({
					renderTo: bodyEl
				});
				bodyEl.createChild({
					cls: 'x-clear'
				});
			}
			return dlg;
		},

		updateText: function(text) {
			if (!dlg.isVisible() && !opt.width) {
				dlg.setSize(this.maxWidth, 100);
			}
			msgEl.update(text || '&#160;');

			var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;
			var mw = msgEl.getWidth() + msgEl.getMargins('lr');
			var fw = dlg.getFrameWidth('lr');
			var bw = dlg.body.getFrameWidth('lr');
			if (Ext.isIE && iw > 0) {
				iw += 3;
			}
			var w = Math.max(Math.min(opt.width || iw + mw + fw + bw, this.maxWidth), Math.max(opt.minWidth || this.minWidth, bwidth || 0));

			if (opt.prompt === true) {
				activeTextEl.setWidth(w - iw - fw - bw);
			}
			if (opt.progress === true || opt.wait === true) {
				progressBar.setSize(w - iw - fw - bw);
			}
			dlg.setSize(w, 'auto').center();
			return this;
		},

		updateProgress: function(value, progressText, msg) {
			progressBar.updateProgress(value, progressText);
			if (msg) {
				this.updateText(msg);
			}
			return this;
		},

		isVisible: function() {
			return dlg && dlg.isVisible();
		},

		hide: function() {
			if (this.isVisible()) {
				dlg.hide();
				handleHide();
			}
			return this;
		},

		show: function(options) {
			if (this.isVisible()) {
				this.hide();
			}
			opt = options;
			var d = this.getDialog(opt.title || "&#160;");

			d.setTitle(opt.title || "&#160;");
			var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
			d.tools.close.setDisplayed(allowClose);
			activeTextEl = textboxEl;
			opt.prompt = opt.prompt || (opt.multiline ? true: false);
			if (opt.prompt) {
				if (opt.multiline) {
					textboxEl.hide();
					textareaEl.show();
					textareaEl.setHeight(typeof opt.multiline == "number" ? opt.multiline: this.defaultTextHeight);
					activeTextEl = textareaEl;
				} else {
					textboxEl.show();
					textareaEl.hide();
				}
			} else {
				textboxEl.hide();
				textareaEl.hide();
			}
			activeTextEl.dom.value = opt.value || "";
			if (opt.prompt) {
				d.focusEl = activeTextEl;
			} else {
				var bs = opt.buttons;
				var db = null;
				if (bs && bs.ok) {
					db = buttons["ok"];
				} else if (bs && bs.yes) {
					db = buttons["yes"];
				}
				if (db) {
					d.focusEl = db;
				}
			}
			if (opt.iconCls) {
				d.setIconClass(opt.iconCls);
			}
			this.setIcon(opt.icon);
			bwidth = updateButtons(opt.buttons);
			progressBar.setVisible(opt.progress === true || opt.wait === true);
			this.updateProgress(0, opt.progressText);
			this.updateText(opt.msg);
			if (opt.cls) {
				d.el.addClass(opt.cls);
			}
			d.proxyDrag = opt.proxyDrag === true;
			d.modal = opt.modal !== false;
			d.mask = opt.modal !== false ? mask: false;
			if (!d.isVisible()) {
				document.body.appendChild(dlg.el.dom);
				d.setAnimateTarget(opt.animEl);
				d.show(opt.animEl);
			}

			d.on('show',
			function() {
				if (allowClose === true) {
					d.keyMap.enable();
				} else {
					d.keyMap.disable();
				}
			},
			this, {
				single: true
			});

			if (opt.wait === true) {
				progressBar.wait(opt.waitConfig);
			}
			return this;
		},

		setIcon: function(icon) {
			if (icon && icon != '') {
				iconEl.removeClass('x-hidden');
				iconEl.replaceClass(iconCls, icon);
				iconCls = icon;
			} else {
				iconEl.replaceClass(iconCls, 'x-hidden');
				iconCls = '';
			}
			return this;
		},

		progress: function(title, msg, progressText) {
			this.show({
				title: title,
				msg: msg,
				buttons: false,
				progress: true,
				closable: false,
				minWidth: this.minProgressWidth,
				progressText: progressText
			});
			return this;
		},

		wait: function(msg, title, config) {
			this.show({
				title: title,
				msg: msg,
				buttons: false,
				closable: false,
				wait: true,
				modal: true,
				minWidth: this.minProgressWidth,
				waitConfig: config
			});
			return this;
		},

		alert: function(title, msg, fn, scope) {
			this.show({
				title: title,
				msg: msg,
				buttons: this.OK,
				fn: fn,
				scope: scope
			});
			return this;
		},

		confirm: function(title, msg, fn, scope) {
			this.show({
				title: title,
				msg: msg,
				buttons: this.YESNO,
				fn: fn,
				scope: scope,
				icon: this.QUESTION
			});
			return this;
		},

		prompt: function(title, msg, fn, scope, multiline, value) {
			this.show({
				title: title,
				msg: msg,
				buttons: this.OKCANCEL,
				fn: fn,
				minWidth: 250,
				scope: scope,
				prompt: true,
				multiline: multiline,
				value: value
			});
			return this;
		},

		OK: {
			ok: true
		},

		CANCEL: {
			cancel: true
		},

		OKCANCEL: {
			ok: true,
			cancel: true
		},

		YESNO: {
			yes: true,
			no: true
		},

		YESNOCANCEL: {
			yes: true,
			no: true,
			cancel: true
		},

		INFO: 'ext-mb-info',

		WARNING: 'ext-mb-warning',

		QUESTION: 'ext-mb-question',

		ERROR: 'ext-mb-error',

		defaultTextHeight: 75,

		maxWidth: 600,

		minWidth: 100,

		minProgressWidth: 250,

		buttonText: {
			ok: "OK",
			cancel: "Cancel",
			yes: "Yes",
			no: "No"
		}
	};
} ();

Ext.Msg = Ext.MessageBox;

Ext.Tip = Ext.extend(Ext.Panel, {

	minWidth: 40,

	maxWidth: 300,

	shadow: "sides",

	defaultAlign: "tl-bl?",
	autoRender: true,
	quickShowInterval: 250,

	frame: true,
	hidden: true,
	baseCls: 'x-tip',
	floating: {
		shadow: true,
		shim: true,
		useDisplay: true,
		constrain: false
	},
	autoHeight: true,

	initComponent: function() {
		Ext.Tip.superclass.initComponent.call(this);
		if (this.closable && !this.title) {
			this.elements += ',header';
		}
	},

	afterRender: function() {
		Ext.Tip.superclass.afterRender.call(this);
		if (this.closable) {
			this.addTool({
				id: 'close',
				handler: this.hide,
				scope: this
			});
		}
	},

	showAt: function(xy) {
		Ext.Tip.superclass.show.call(this);
		if (this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')) {
			this.doAutoWidth();
		}
		if (this.constrainPosition) {
			xy = this.el.adjustForConstraints(xy);
		}
		this.setPagePosition(xy[0], xy[1]);
	},

	doAutoWidth: function() {
		var bw = this.body.getTextWidth();
		if (this.title) {
			bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
		}
		bw += this.getFrameWidth() + (this.closable ? 20: 0) + this.body.getPadding("lr");
		this.setWidth(bw.constrain(this.minWidth, this.maxWidth));

		if (Ext.isIE7 && !this.repainted) {
			this.el.repaint();
			this.repainted = true;
		}
	},

	showBy: function(el, pos) {
		if (!this.rendered) {
			this.render(Ext.getBody());
		}
		this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
	},

	initDraggable: function() {
		this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null: this.draggable);
		this.header.addClass('x-tip-draggable');
	}
});

Ext.Tip.DD = function(tip, config) {
	Ext.apply(this, config);
	this.tip = tip;
	Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-' + tip.id);
	this.setHandleElId(tip.header.id);
	this.scroll = false;
};

Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
	moveOnly: true,
	scroll: false,
	headerOffsets: [100, 25],
	startDrag: function() {
		this.tip.el.disableShadow();
	},
	endDrag: function(e) {
		this.tip.el.enableShadow(true);
	}
});

Ext.ToolTip = Ext.extend(Ext.Tip, {

	showDelay: 500,

	hideDelay: 200,

	dismissDelay: 5000,

	mouseOffset: [15, 18],

	trackMouse: false,
	constrainPosition: true,

	initComponent: function() {
		Ext.ToolTip.superclass.initComponent.call(this);
		this.lastActive = new Date();
		this.initTarget();
	},

	initTarget: function() {
		if (this.target) {
			this.target = Ext.get(this.target);
			this.target.on('mouseover', this.onTargetOver, this);
			this.target.on('mouseout', this.onTargetOut, this);
			this.target.on('mousemove', this.onMouseMove, this);
		}
	},

	onMouseMove: function(e) {
		this.targetXY = e.getXY();
		if (!this.hidden && this.trackMouse) {
			this.setPagePosition(this.getTargetXY());
		}
	},

	getTargetXY: function() {
		return [this.targetXY[0] + this.mouseOffset[0], this.targetXY[1] + this.mouseOffset[1]];
	},

	onTargetOver: function(e) {
		if (this.disabled || e.within(this.target.dom, true)) {
			return;
		}
		this.clearTimer('hide');
		this.targetXY = e.getXY();
		this.delayShow();
	},

	delayShow: function() {
		if (this.hidden && !this.showTimer) {
			if (this.lastActive.getElapsed() < this.quickShowInterval) {
				this.show();
			} else {
				this.showTimer = this.show.defer(this.showDelay, this);
			}
		} else if (!this.hidden && this.autoHide !== false) {
			this.show();
		}
	},

	onTargetOut: function(e) {
		if (this.disabled || e.within(this.target.dom, true)) {
			return;
		}
		this.clearTimer('show');
		if (this.autoHide !== false) {
			this.delayHide();
		}
	},

	delayHide: function() {
		if (!this.hidden && !this.hideTimer) {
			this.hideTimer = this.hide.defer(this.hideDelay, this);
		}
	},

	hide: function() {
		this.clearTimer('dismiss');
		this.lastActive = new Date();
		Ext.ToolTip.superclass.hide.call(this);
	},

	show: function() {
		this.showAt(this.getTargetXY());
	},

	showAt: function(xy) {
		this.lastActive = new Date();
		this.clearTimers();
		Ext.ToolTip.superclass.showAt.call(this, xy);
		if (this.dismissDelay && this.autoHide !== false) {
			this.dismissTimer = this.hide.defer(this.dismissDelay, this);
		}
	},

	clearTimer: function(name) {
		name = name + 'Timer';
		clearTimeout(this[name]);
		delete this[name];
	},

	clearTimers: function() {
		this.clearTimer('show');
		this.clearTimer('dismiss');
		this.clearTimer('hide');
	},

	onShow: function() {
		Ext.ToolTip.superclass.onShow.call(this);
		Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
	},

	onHide: function() {
		Ext.ToolTip.superclass.onHide.call(this);
		Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
	},

	onDocMouseDown: function(e) {
		if (this.autoHide !== false && !e.within(this.el.dom)) {
			this.disable();
			this.enable.defer(100, this);
		}
	},

	onDisable: function() {
		this.clearTimers();
		this.hide();
	},

	adjustPosition: function(x, y) {

		var ay = this.targetXY[1],
		h = this.getSize().height;
		if (this.constrainPosition && y <= ay && (y + h) >= ay) {
			y = ay - h - 5;
		}
		return {
			x: x,
			y: y
		};
	},

	onDestroy: function() {
		Ext.ToolTip.superclass.onDestroy.call(this);
		if (this.target) {
			this.target.un('mouseover', this.onTargetOver, this);
			this.target.un('mouseout', this.onTargetOut, this);
			this.target.un('mousemove', this.onMouseMove, this);
		}
	}
});

Ext.QuickTip = Ext.extend(Ext.ToolTip, {

	interceptTitles: false,

	tagConfig: {
		namespace: "ext",
		attribute: "qtip",
		width: "qwidth",
		target: "target",
		title: "qtitle",
		hide: "hide",
		cls: "qclass",
		align: "qalign"
	},

	initComponent: function() {
		this.target = this.target || Ext.getDoc();
		this.targets = this.targets || {};
		Ext.QuickTip.superclass.initComponent.call(this);
	},

	register: function(config) {
		var cs = Ext.isArray(config) ? config: arguments;
		for (var i = 0, len = cs.length; i < len; i++) {
			var c = cs[i];
			var target = c.target;
			if (target) {
				if (Ext.isArray(target)) {
					for (var j = 0, jlen = target.length; j < jlen; j++) {
						this.targets[Ext.id(target[j])] = c;
					}
				} else {
					this.targets[Ext.id(target)] = c;
				}
			}
		}
	},

	unregister: function(el) {
		delete this.targets[Ext.id(el)];
	},

	onTargetOver: function(e) {
		if (this.disabled) {
			return;
		}
		this.targetXY = e.getXY();
		var t = e.getTarget();
		if (!t || t.nodeType !== 1 || t == document || t == document.body) {
			return;
		}
		if (this.activeTarget && t == this.activeTarget.el) {
			this.clearTimer('hide');
			this.show();
			return;
		}
		if (t && this.targets[t.id]) {
			this.activeTarget = this.targets[t.id];
			this.activeTarget.el = t;
			this.delayShow();
			return;
		}
		var ttp,
		et = Ext.fly(t),
		cfg = this.tagConfig;
		var ns = cfg.namespace;
		if (this.interceptTitles && t.title) {
			ttp = t.title;
			t.qtip = ttp;
			t.removeAttribute("title");
			e.preventDefault();
		} else {
			ttp = t.qtip || et.getAttributeNS(ns, cfg.attribute);
		}
		if (ttp) {
			var autoHide = et.getAttributeNS(ns, cfg.hide);
			this.activeTarget = {
				el: t,
				text: ttp,
				width: et.getAttributeNS(ns, cfg.width),
				autoHide: autoHide != "user" && autoHide !== 'false',
				title: et.getAttributeNS(ns, cfg.title),
				cls: et.getAttributeNS(ns, cfg.cls),
				align: et.getAttributeNS(ns, cfg.align)
			};
			this.delayShow();
		}
	},

	onTargetOut: function(e) {
		this.clearTimer('show');
		if (this.autoHide !== false) {
			this.delayHide();
		}
	},

	showAt: function(xy) {
		var t = this.activeTarget;
		if (t) {
			if (!this.rendered) {
				this.render(Ext.getBody());
				this.activeTarget = t;
			}
			if (t.width) {
				this.setWidth(t.width);
				this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
				this.measureWidth = false;
			} else {
				this.measureWidth = true;
			}
			this.setTitle(t.title || '');
			this.body.update(t.text);
			this.autoHide = t.autoHide;
			this.dismissDelay = t.dismissDelay || this.dismissDelay;
			if (this.lastCls) {
				this.el.removeClass(this.lastCls);
				delete this.lastCls;
			}
			if (t.cls) {
				this.el.addClass(t.cls);
				this.lastCls = t.cls;
			}
			if (t.align) {
				xy = this.el.getAlignToXY(t.el, t.align);
				this.constrainPosition = false;
			} else {
				this.constrainPosition = true;
			}
		}
		Ext.QuickTip.superclass.showAt.call(this, xy);
	},

	hide: function() {
		delete this.activeTarget;
		Ext.QuickTip.superclass.hide.call(this);
	}
});

Ext.QuickTips = function() {
	var tip,
	locks = [];
	return {

		init: function(autoRender) {
			if (!tip) {
				if (!Ext.isReady) {
					Ext.onReady(function() {
						Ext.QuickTips.init(autoRender);
					});
					return;
				}
				tip = new Ext.QuickTip({
					elements: 'header,body'
				});
				if (autoRender !== false) {
					tip.render(Ext.getBody());
				}
			}
		},

		enable: function() {
			if (tip) {
				locks.pop();
				if (locks.length < 1) {
					tip.enable();
				}
			}
		},

		disable: function() {
			if (tip) {
				tip.disable();
			}
			locks.push(1);
		},

		isEnabled: function() {
			return tip !== undefined && !tip.disabled;
		},

		getQuickTip: function() {
			return tip;
		},

		register: function() {
			tip.register.apply(tip, arguments);
		},

		unregister: function() {
			tip.unregister.apply(tip, arguments);
		},

		tips: function() {
			tip.register.apply(tip, arguments);
		}
	}
} ();

Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
	rootVisible: true,
	animate: Ext.enableFx,
	lines: true,
	enableDD: false,
	hlDrop: Ext.enableFx,
	pathSeparator: "/",

	initComponent: function() {
		Ext.tree.TreePanel.superclass.initComponent.call(this);

		if (!this.eventModel) {
			this.eventModel = new Ext.tree.TreeEventModel(this);
		}

		var l = this.loader;
		if (!l) {
			l = new Ext.tree.TreeLoader({
				dataUrl: this.dataUrl
			});
		} else if (typeof l == 'object' && !l.load) {
			l = new Ext.tree.TreeLoader(l);
		}
		this.loader = l;

		this.nodeHash = {};

		if (this.root) {
			this.setRootNode(this.root);
		}

		this.addEvents(
		"append",
		"remove",
		"movenode",
		"insert",
		"beforeappend",
		"beforeremove",
		"beforemovenode",
		"beforeinsert",
		"beforeload",
		"load",
		"textchange",
		"beforeexpandnode",
		"beforecollapsenode",
		"expandnode",
		"disabledchange",
		"collapsenode",
		"beforeclick",
		"click",
		"checkchange",
		"dblclick",
		"contextmenu",
		"beforechildrenrendered",
		"startdrag",
		"enddrag",
		"dragdrop",
		"beforenodedrop",
		"nodedrop",
		"nodedragover");
		if (this.singleExpand) {
			this.on("beforeexpandnode", this.restrictExpand, this);
		}
	},

	proxyNodeEvent: function(ename, a1, a2, a3, a4, a5, a6) {
		if (ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove') {
			ename = ename + 'node';
		}

		return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
	},

	getRootNode: function() {
		return this.root;
	},

	setRootNode: function(node) {
		if (!node.render) {
			node = this.loader.createNode(node);
		}
		this.root = node;
		node.ownerTree = this;
		node.isRoot = true;
		this.registerNode(node);
		if (!this.rootVisible) {
			var uiP = node.attributes.uiProvider;
			node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
		}
		return node;
	},

	getNodeById: function(id) {
		return this.nodeHash[id];
	},

	registerNode: function(node) {
		this.nodeHash[node.id] = node;
	},

	unregisterNode: function(node) {
		delete this.nodeHash[node.id];
	},

	toString: function() {
		return "[Tree" + (this.id ? " " + this.id: "") + "]";
	},

	restrictExpand: function(node) {
		var p = node.parentNode;
		if (p) {
			if (p.expandedChild && p.expandedChild.parentNode == p) {
				p.expandedChild.collapse();
			}
			p.expandedChild = node;
		}
	},

	getChecked: function(a, startNode) {
		startNode = startNode || this.root;
		var r = [];
		var f = function() {
			if (this.attributes.checked) {
				r.push(!a ? this: (a == 'id' ? this.id: this.attributes[a]));
			}
		}
		startNode.cascade(f);
		return r;
	},

	getEl: function() {
		return this.el;
	},

	getLoader: function() {
		return this.loader;
	},

	expandAll: function() {
		this.root.expand(true);
	},

	collapseAll: function() {
		this.root.collapse(true);
	},

	getSelectionModel: function() {
		if (!this.selModel) {
			this.selModel = new Ext.tree.DefaultSelectionModel();
		}
		return this.selModel;
	},

	expandPath: function(path, attr, callback) {
		attr = attr || "id";
		var keys = path.split(this.pathSeparator);
		var curNode = this.root;
		if (curNode.attributes[attr] != keys[1]) {
			if (callback) {
				callback(false, null);
			}
			return;
		}
		var index = 1;
		var f = function() {
			if (++index == keys.length) {
				if (callback) {
					callback(true, curNode);
				}
				return;
			}
			var c = curNode.findChild(attr, keys[index]);
			if (!c) {
				if (callback) {
					callback(false, curNode);
				}
				return;
			}
			curNode = c;
			c.expand(false, false, f);
		};
		curNode.expand(false, false, f);
	},

	selectPath: function(path, attr, callback) {
		attr = attr || "id";
		var keys = path.split(this.pathSeparator);
		var v = keys.pop();
		if (keys.length > 0) {
			var f = function(success, node) {
				if (success && node) {
					var n = node.findChild(attr, v);
					if (n) {
						n.select();
						if (callback) {
							callback(true, n);
						}
					} else if (callback) {
						callback(false, n);
					}
				} else {
					if (callback) {
						callback(false, n);
					}
				}
			};
			this.expandPath(keys.join(this.pathSeparator), attr, f);
		} else {
			this.root.select();
			if (callback) {
				callback(true, this.root);
			}
		}
	},

	getTreeEl: function() {
		return this.body;
	},

	onRender: function(ct, position) {
		Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
		this.el.addClass('x-tree');
		this.innerCt = this.body.createChild({
			tag: "ul",
			cls: "x-tree-root-ct " + (this.useArrows ? 'x-tree-arrows': this.lines ? "x-tree-lines": "x-tree-no-lines")
		});
	},

	initEvents: function() {
		Ext.tree.TreePanel.superclass.initEvents.call(this);

		if (this.containerScroll) {
			Ext.dd.ScrollManager.register(this.body);
		}
		if ((this.enableDD || this.enableDrop) && !this.dropZone) {

			this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
				ddGroup: this.ddGroup || "TreeDD",
				appendOnly: this.ddAppendOnly === true
			});
		}
		if ((this.enableDD || this.enableDrag) && !this.dragZone) {

			this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
				ddGroup: this.ddGroup || "TreeDD",
				scroll: this.ddScroll
			});
		}
		this.getSelectionModel().init(this);
	},

	afterRender: function() {
		Ext.tree.TreePanel.superclass.afterRender.call(this);
		this.root.render();
		if (!this.rootVisible) {
			this.root.renderChildren();
		}
	},

	onDestroy: function() {
		if (this.rendered) {
			this.body.removeAllListeners();
			Ext.dd.ScrollManager.unregister(this.body);
			if (this.dropZone) {
				this.dropZone.unreg();
			}
			if (this.dragZone) {
				this.dragZone.unreg();
			}
		}
		this.root.destroy();
		this.nodeHash = null;
		Ext.tree.TreePanel.superclass.onDestroy.call(this);
	}

});

Ext.tree.TreePanel.nodeTypes = {};

Ext.reg('treepanel', Ext.tree.TreePanel);
Ext.tree.TreeEventModel = function(tree) {
	this.tree = tree;
	this.tree.on('render', this.initEvents, this);
}

Ext.tree.TreeEventModel.prototype = {
	initEvents: function() {
		var el = this.tree.getTreeEl();
		el.on('click', this.delegateClick, this);
		if (this.tree.trackMouseOver !== false) {
			el.on('mouseover', this.delegateOver, this);
			el.on('mouseout', this.delegateOut, this);
		}
		el.on('dblclick', this.delegateDblClick, this);
		el.on('contextmenu', this.delegateContextMenu, this);
	},

	getNode: function(e) {
		var t;
		if (t = e.getTarget('.x-tree-node-el', 10)) {
			var id = Ext.fly(t, '_treeEvents').getAttributeNS('ext', 'tree-node-id');
			if (id) {
				return this.tree.getNodeById(id);
			}
		}
		return null;
	},

	getNodeTarget: function(e) {
		var t = e.getTarget('.x-tree-node-icon', 1);
		if (!t) {
			t = e.getTarget('.x-tree-node-el', 6);
		}
		return t;
	},

	delegateOut: function(e, t) {
		if (!this.beforeEvent(e)) {
			return;
		}
		if (e.getTarget('.x-tree-ec-icon', 1)) {
			var n = this.getNode(e);
			this.onIconOut(e, n);
			if (n == this.lastEcOver) {
				delete this.lastEcOver;
			}
		}
		if ((t = this.getNodeTarget(e)) && !e.within(t, true)) {
			this.onNodeOut(e, this.getNode(e));
		}
	},

	delegateOver: function(e, t) {
		if (!this.beforeEvent(e)) {
			return;
		}
		if (this.lastEcOver) {
			this.onIconOut(e, this.lastEcOver);
			delete this.lastEcOver;
		}
		if (e.getTarget('.x-tree-ec-icon', 1)) {
			this.lastEcOver = this.getNode(e);
			this.onIconOver(e, this.lastEcOver);
		}
		if (t = this.getNodeTarget(e)) {
			this.onNodeOver(e, this.getNode(e));
		}
	},

	delegateClick: function(e, t) {
		if (!this.beforeEvent(e)) {
			return;
		}

		if (e.getTarget('input[type=checkbox]', 1)) {
			this.onCheckboxClick(e, this.getNode(e));
		} else if (e.getTarget('.x-tree-ec-icon', 1)) {
			this.onIconClick(e, this.getNode(e));
		} else if (this.getNodeTarget(e)) {
			this.onNodeClick(e, this.getNode(e));
		}
	},

	delegateDblClick: function(e, t) {
		if (this.beforeEvent(e) && this.getNodeTarget(e)) {
			this.onNodeDblClick(e, this.getNode(e));
		}
	},

	delegateContextMenu: function(e, t) {
		if (this.beforeEvent(e) && this.getNodeTarget(e)) {
			this.onNodeContextMenu(e, this.getNode(e));
		}
	},

	onNodeClick: function(e, node) {
		node.ui.onClick(e);
	},

	onNodeOver: function(e, node) {
		node.ui.onOver(e);
	},

	onNodeOut: function(e, node) {
		node.ui.onOut(e);
	},

	onIconOver: function(e, node) {
		node.ui.addClass('x-tree-ec-over');
	},

	onIconOut: function(e, node) {
		node.ui.removeClass('x-tree-ec-over');
	},

	onIconClick: function(e, node) {
		node.ui.ecClick(e);
	},

	onCheckboxClick: function(e, node) {
		node.ui.onCheckChange(e);
	},

	onNodeDblClick: function(e, node) {
		node.ui.onDblClick(e);
	},

	onNodeContextMenu: function(e, node) {
		node.ui.onContextMenu(e);
	},

	beforeEvent: function(e) {
		if (this.disabled) {
			e.stopEvent();
			return false;
		}
		return true;
	},

	disable: function() {
		this.disabled = true;
	},

	enable: function() {
		this.disabled = false;
	}
};

Ext.tree.DefaultSelectionModel = function(config) {
	this.selNode = null;

	this.addEvents(
	"selectionchange",
	"beforeselect");

	Ext.apply(this, config);
	Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
	init: function(tree) {
		this.tree = tree;
		tree.getTreeEl().on("keydown", this.onKeyDown, this);
		tree.on("click", this.onNodeClick, this);
	},

	onNodeClick: function(node, e) {
		this.select(node);
	},

	select: function(node) {
		var last = this.selNode;
		if (last != node && this.fireEvent('beforeselect', this, node, last) !== false) {
			if (last) {
				last.ui.onSelectedChange(false);
			}
			this.selNode = node;
			node.ui.onSelectedChange(true);
			this.fireEvent("selectionchange", this, node, last);
		}
		return node;
	},

	unselect: function(node) {
		if (this.selNode == node) {
			this.clearSelections();
		}
	},

	clearSelections: function() {
		var n = this.selNode;
		if (n) {
			n.ui.onSelectedChange(false);
			this.selNode = null;
			this.fireEvent("selectionchange", this, null);
		}
		return n;
	},

	getSelectedNode: function() {
		return this.selNode;
	},

	isSelected: function(node) {
		return this.selNode == node;
	},

	selectPrevious: function() {
		var s = this.selNode || this.lastSelNode;
		if (!s) {
			return null;
		}
		var ps = s.previousSibling;
		if (ps) {
			if (!ps.isExpanded() || ps.childNodes.length < 1) {
				return this.select(ps);
			} else {
				var lc = ps.lastChild;
				while (lc && lc.isExpanded() && lc.childNodes.length > 0) {
					lc = lc.lastChild;
				}
				return this.select(lc);
			}
		} else if (s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)) {
			return this.select(s.parentNode);
		}
		return null;
	},

	selectNext: function() {
		var s = this.selNode || this.lastSelNode;
		if (!s) {
			return null;
		}
		if (s.firstChild && s.isExpanded()) {
			return this.select(s.firstChild);
		} else if (s.nextSibling) {
			return this.select(s.nextSibling);
		} else if (s.parentNode) {
			var newS = null;
			s.parentNode.bubble(function() {
				if (this.nextSibling) {
					newS = this.getOwnerTree().selModel.select(this.nextSibling);
					return false;
				}
			});
			return newS;
		}
		return null;
	},

	onKeyDown: function(e) {
		var s = this.selNode || this.lastSelNode;

		var sm = this;
		if (!s) {
			return;
		}
		var k = e.getKey();
		switch (k) {
		case e.DOWN:
			e.stopEvent();
			this.selectNext();
			break;
		case e.UP:
			e.stopEvent();
			this.selectPrevious();
			break;
		case e.RIGHT:
			e.preventDefault();
			if (s.hasChildNodes()) {
				if (!s.isExpanded()) {
					s.expand();
				} else if (s.firstChild) {
					this.select(s.firstChild, e);
				}
			}
			break;
		case e.LEFT:
			e.preventDefault();
			if (s.hasChildNodes() && s.isExpanded()) {
				s.collapse();
			} else if (s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())) {
				this.select(s.parentNode, e);
			}
			break;
		};
	}
});

Ext.tree.MultiSelectionModel = function(config) {
	this.selNodes = [];
	this.selMap = {};
	this.addEvents(
	"selectionchange");
	Ext.apply(this, config);
	Ext.tree.MultiSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
	init: function(tree) {
		this.tree = tree;
		tree.getTreeEl().on("keydown", this.onKeyDown, this);
		tree.on("click", this.onNodeClick, this);
	},

	onNodeClick: function(node, e) {
		this.select(node, e, e.ctrlKey);
	},

	select: function(node, e, keepExisting) {
		if (keepExisting !== true) {
			this.clearSelections(true);
		}
		if (this.isSelected(node)) {
			this.lastSelNode = node;
			return node;
		}
		this.selNodes.push(node);
		this.selMap[node.id] = node;
		this.lastSelNode = node;
		node.ui.onSelectedChange(true);
		this.fireEvent("selectionchange", this, this.selNodes);
		return node;
	},

	unselect: function(node) {
		if (this.selMap[node.id]) {
			node.ui.onSelectedChange(false);
			var sn = this.selNodes;
			var index = sn.indexOf(node);
			if (index != -1) {
				this.selNodes.splice(index, 1);
			}
			delete this.selMap[node.id];
			this.fireEvent("selectionchange", this, this.selNodes);
		}
	},

	clearSelections: function(suppressEvent) {
		var sn = this.selNodes;
		if (sn.length > 0) {
			for (var i = 0, len = sn.length; i < len; i++) {
				sn[i].ui.onSelectedChange(false);
			}
			this.selNodes = [];
			this.selMap = {};
			if (suppressEvent !== true) {
				this.fireEvent("selectionchange", this, this.selNodes);
			}
		}
	},

	isSelected: function(node) {
		return this.selMap[node.id] ? true: false;
	},

	getSelectedNodes: function() {
		return this.selNodes;
	},

	onKeyDown: Ext.tree.DefaultSelectionModel.prototype.onKeyDown,

	selectNext: Ext.tree.DefaultSelectionModel.prototype.selectNext,

	selectPrevious: Ext.tree.DefaultSelectionModel.prototype.selectPrevious
});

Ext.tree.TreeNode = function(attributes) {
	attributes = attributes || {};
	if (typeof attributes == "string") {
		attributes = {
			text: attributes
		};
	}
	this.childrenRendered = false;
	this.rendered = false;
	Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
	this.expanded = attributes.expanded === true;
	this.isTarget = attributes.isTarget !== false;
	this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
	this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;

	this.text = attributes.text;

	this.disabled = attributes.disabled === true;

	this.addEvents(
	"textchange",
	"beforeexpand",
	"beforecollapse",
	"expand",
	"disabledchange",
	"collapse",
	"beforeclick",
	"click",
	"checkchange",
	"dblclick",
	"contextmenu",
	"beforechildrenrendered");

	var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;

	this.ui = new uiClass(this);
};
Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
	preventHScroll: true,

	isExpanded: function() {
		return this.expanded;
	},

	getUI: function() {
		return this.ui;
	},

	getLoader: function() {
		var owner;
		return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader: new Ext.tree.TreeLoader());
	},

	setFirstChild: function(node) {
		var of = this.firstChild;
		Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
		if (this.childrenRendered && of && node != of) {
			of.renderIndent(true, true);
		}
		if (this.rendered) {
			this.renderIndent(true, true);
		}
	},

	setLastChild: function(node) {
		var ol = this.lastChild;
		Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
		if (this.childrenRendered && ol && node != ol) {
			ol.renderIndent(true, true);
		}
		if (this.rendered) {
			this.renderIndent(true, true);
		}
	},

	appendChild: function(n) {
		if (!n.render && !Ext.isArray(n)) {
			n = this.getLoader().createNode(n);
		}
		var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
		if (node && this.childrenRendered) {
			node.render();
		}
		this.ui.updateExpandIcon();
		return node;
	},

	removeChild: function(node) {
		this.ownerTree.getSelectionModel().unselect(node);
		Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);

		if (this.childrenRendered) {
			node.ui.remove();
		}
		if (this.childNodes.length < 1) {
			this.collapse(false, false);
		} else {
			this.ui.updateExpandIcon();
		}
		if (!this.firstChild && !this.isHiddenRoot()) {
			this.childrenRendered = false;
		}
		return node;
	},

	insertBefore: function(node, refNode) {
		if (!node.render) {
			node = this.getLoader().createNode(node);
		}
		var newNode = Ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
		if (newNode && refNode && this.childrenRendered) {
			node.render();
		}
		this.ui.updateExpandIcon();
		return newNode;
	},

	setText: function(text) {
		var oldText = this.text;
		this.text = text;
		this.attributes.text = text;
		if (this.rendered) {
			this.ui.onTextChange(this, text, oldText);
		}
		this.fireEvent("textchange", this, text, oldText);
	},

	select: function() {
		this.getOwnerTree().getSelectionModel().select(this);
	},

	unselect: function() {
		this.getOwnerTree().getSelectionModel().unselect(this);
	},

	isSelected: function() {
		return this.getOwnerTree().getSelectionModel().isSelected(this);
	},

	expand: function(deep, anim, callback) {
		if (!this.expanded) {
			if (this.fireEvent("beforeexpand", this, deep, anim) === false) {
				return;
			}
			if (!this.childrenRendered) {
				this.renderChildren();
			}
			this.expanded = true;
			if (!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim) {
				this.ui.animExpand(function() {
					this.fireEvent("expand", this);
					if (typeof callback == "function") {
						callback(this);
					}
					if (deep === true) {
						this.expandChildNodes(true);
					}
				}.createDelegate(this));
				return;
			} else {
				this.ui.expand();
				this.fireEvent("expand", this);
				if (typeof callback == "function") {
					callback(this);
				}
			}
		} else {
			if (typeof callback == "function") {
				callback(this);
			}
		}
		if (deep === true) {
			this.expandChildNodes(true);
		}
	},

	isHiddenRoot: function() {
		return this.isRoot && !this.getOwnerTree().rootVisible;
	},

	collapse: function(deep, anim) {
		if (this.expanded && !this.isHiddenRoot()) {
			if (this.fireEvent("beforecollapse", this, deep, anim) === false) {
				return;
			}
			this.expanded = false;
			if ((this.getOwnerTree().animate && anim !== false) || anim) {
				this.ui.animCollapse(function() {
					this.fireEvent("collapse", this);
					if (deep === true) {
						this.collapseChildNodes(true);
					}
				}.createDelegate(this));
				return;
			} else {
				this.ui.collapse();
				this.fireEvent("collapse", this);
			}
		}
		if (deep === true) {
			var cs = this.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				cs[i].collapse(true, false);
			}
		}
	},

	delayedExpand: function(delay) {
		if (!this.expandProcId) {
			this.expandProcId = this.expand.defer(delay, this);
		}
	},

	cancelExpand: function() {
		if (this.expandProcId) {
			clearTimeout(this.expandProcId);
		}
		this.expandProcId = false;
	},

	toggle: function() {
		if (this.expanded) {
			this.collapse();
		} else {
			this.expand();
		}
	},

	ensureVisible: function(callback) {
		var tree = this.getOwnerTree();
		tree.expandPath(this.parentNode.getPath(), false,
		function() {
			var node = tree.getNodeById(this.id);
			tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
			Ext.callback(callback);
		}.createDelegate(this));
	},

	expandChildNodes: function(deep) {
		var cs = this.childNodes;
		for (var i = 0, len = cs.length; i < len; i++) {
			cs[i].expand(deep);
		}
	},

	collapseChildNodes: function(deep) {
		var cs = this.childNodes;
		for (var i = 0, len = cs.length; i < len; i++) {
			cs[i].collapse(deep);
		}
	},

	disable: function() {
		this.disabled = true;
		this.unselect();
		if (this.rendered && this.ui.onDisableChange) {
			this.ui.onDisableChange(this, true);
		}
		this.fireEvent("disabledchange", this, true);
	},

	enable: function() {
		this.disabled = false;
		if (this.rendered && this.ui.onDisableChange) {
			this.ui.onDisableChange(this, false);
		}
		this.fireEvent("disabledchange", this, false);
	},

	renderChildren: function(suppressEvent) {
		if (suppressEvent !== false) {
			this.fireEvent("beforechildrenrendered", this);
		}
		var cs = this.childNodes;
		for (var i = 0, len = cs.length; i < len; i++) {
			cs[i].render(true);
		}
		this.childrenRendered = true;
	},

	sort: function(fn, scope) {
		Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
		if (this.childrenRendered) {
			var cs = this.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				cs[i].render(true);
			}
		}
	},

	render: function(bulkRender) {
		this.ui.render(bulkRender);
		if (!this.rendered) {

			this.getOwnerTree().registerNode(this);
			this.rendered = true;
			if (this.expanded) {
				this.expanded = false;
				this.expand(false, false);
			}
		}
	},

	renderIndent: function(deep, refresh) {
		if (refresh) {
			this.ui.childIndent = null;
		}
		this.ui.renderIndent();
		if (deep === true && this.childrenRendered) {
			var cs = this.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				cs[i].renderIndent(true, refresh);
			}
		}
	},

	beginUpdate: function() {
		this.childrenRendered = false;
	},

	endUpdate: function() {
		if (this.expanded && this.rendered) {
			this.renderChildren();
		}
	},

	destroy: function() {
		if (this.childNodes) {
			for (var i = 0, l = this.childNodes.length; i < l; i++) {
				this.childNodes[i].destroy();
			}
			this.childNodes = null;
		}
		if (this.ui.destroy) {
			this.ui.destroy();
		}
	}
});

Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;

Ext.tree.AsyncTreeNode = function(config) {
	this.loaded = config && config.loaded === true;
	this.loading = false;
	Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);

	this.addEvents('beforeload', 'load');

};
Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
	expand: function(deep, anim, callback) {
		if (this.loading) {
			var timer;
			var f = function() {
				if (!this.loading) {
					clearInterval(timer);
					this.expand(deep, anim, callback);
				}
			}.createDelegate(this);
			timer = setInterval(f, 200);
			return;
		}
		if (!this.loaded) {
			if (this.fireEvent("beforeload", this) === false) {
				return;
			}
			this.loading = true;
			this.ui.beforeLoad(this);
			var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
			if (loader) {
				loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback]));
				return;
			}
		}
		Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback);
	},

	isLoading: function() {
		return this.loading;
	},

	loadComplete: function(deep, anim, callback) {
		this.loading = false;
		this.loaded = true;
		this.ui.afterLoad(this);
		this.fireEvent("load", this);
		this.expand(deep, anim, callback);
	},

	isLoaded: function() {
		return this.loaded;
	},

	hasChildNodes: function() {
		if (!this.isLeaf() && !this.loaded) {
			return true;
		} else {
			return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
		}
	},

	reload: function(callback) {
		this.collapse(false, false);
		while (this.firstChild) {
			this.removeChild(this.firstChild);
		}
		this.childrenRendered = false;
		this.loaded = false;
		if (this.isHiddenRoot()) {
			this.expanded = false;
		}
		this.expand(false, false, callback);
	}
});

Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;

Ext.tree.TreeNodeUI = function(node) {
	this.node = node;
	this.rendered = false;
	this.animating = false;
	this.wasLeaf = true;
	this.ecc = 'x-tree-ec-icon x-tree-elbow';
	this.emptyIcon = Ext.BLANK_IMAGE_URL;
};

Ext.tree.TreeNodeUI.prototype = {

	removeChild: function(node) {
		if (this.rendered) {
			this.ctNode.removeChild(node.ui.getEl());
		}
	},

	beforeLoad: function() {
		this.addClass("x-tree-node-loading");
	},

	afterLoad: function() {
		this.removeClass("x-tree-node-loading");
	},

	onTextChange: function(node, text, oldText) {
		if (this.rendered) {
			this.textNode.innerHTML = text;
		}
	},

	onDisableChange: function(node, state) {
		this.disabled = state;
		if (this.checkbox) {
			this.checkbox.disabled = state;
		}
		if (state) {
			this.addClass("x-tree-node-disabled");
		} else {
			this.removeClass("x-tree-node-disabled");
		}
	},

	onSelectedChange: function(state) {
		if (state) {
			this.focus();
			this.addClass("x-tree-selected");
		} else {

			this.removeClass("x-tree-selected");
		}
	},

	onMove: function(tree, node, oldParent, newParent, index, refNode) {
		this.childIndent = null;
		if (this.rendered) {
			var targetNode = newParent.ui.getContainer();
			if (!targetNode) {
				this.holder = document.createElement("div");
				this.holder.appendChild(this.wrap);
				return;
			}
			var insertBefore = refNode ? refNode.ui.getEl() : null;
			if (insertBefore) {
				targetNode.insertBefore(this.wrap, insertBefore);
			} else {
				targetNode.appendChild(this.wrap);
			}
			this.node.renderIndent(true);
		}
	},

	addClass: function(cls) {
		if (this.elNode) {
			Ext.fly(this.elNode).addClass(cls);
		}
	},

	removeClass: function(cls) {
		if (this.elNode) {
			Ext.fly(this.elNode).removeClass(cls);
		}
	},

	remove: function() {
		if (this.rendered) {
			this.holder = document.createElement("div");
			this.holder.appendChild(this.wrap);
		}
	},

	fireEvent: function() {
		return this.node.fireEvent.apply(this.node, arguments);
	},

	initEvents: function() {
		this.node.on("move", this.onMove, this);

		if (this.node.disabled) {
			this.addClass("x-tree-node-disabled");
			if (this.checkbox) {
				this.checkbox.disabled = true;
			}
		}
		if (this.node.hidden) {
			this.hide();
		}
		var ot = this.node.getOwnerTree();
		var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
		if (dd && (!this.node.isRoot || ot.rootVisible)) {
			Ext.dd.Registry.register(this.elNode, {
				node: this.node,
				handles: this.getDDHandles(),
				isHandle: false
			});
		}
	},

	getDDHandles: function() {
		return [this.iconNode, this.textNode, this.elNode];
	},

	hide: function() {
		this.node.hidden = true;
		if (this.wrap) {
			this.wrap.style.display = "none";
		}
	},

	show: function() {
		this.node.hidden = false;
		if (this.wrap) {
			this.wrap.style.display = "";
		}
	},

	onContextMenu: function(e) {
		if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
			e.preventDefault();
			this.focus();
			this.fireEvent("contextmenu", this.node, e);
		}
	},

	onClick: function(e) {
		if (this.dropping) {
			e.stopEvent();
			return;
		}
		if (this.fireEvent("beforeclick", this.node, e) !== false) {
			var a = e.getTarget('a');
			if (!this.disabled && this.node.attributes.href && a) {
				this.fireEvent("click", this.node, e);
				return;
			} else if (a && e.ctrlKey) {
				e.stopEvent();
			}
			e.preventDefault();
			if (this.disabled) {
				return;
			}

			if (this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()) {
				this.node.toggle();
			}

			this.fireEvent("click", this.node, e);
		} else {
			e.stopEvent();
		}
	},

	onDblClick: function(e) {
		e.preventDefault();
		if (this.disabled) {
			return;
		}
		if (this.checkbox) {
			this.toggleCheck();
		}
		if (!this.animating && this.node.isExpandable()) {
			this.node.toggle();
		}
		this.fireEvent("dblclick", this.node, e);
	},

	onOver: function(e) {
		this.addClass('x-tree-node-over');
	},

	onOut: function(e) {
		this.removeClass('x-tree-node-over');
	},

	onCheckChange: function() {
		var checked = this.checkbox.checked;

		this.checkbox.defaultChecked = checked;
		this.node.attributes.checked = checked;
		this.fireEvent('checkchange', this.node, checked);
	},

	ecClick: function(e) {
		if (!this.animating && this.node.isExpandable()) {
			this.node.toggle();
		}
	},

	startDrop: function() {
		this.dropping = true;
	},

	endDrop: function() {
		setTimeout(function() {
			this.dropping = false;
		}.createDelegate(this), 50);
	},

	expand: function() {
		this.updateExpandIcon();
		this.ctNode.style.display = "";
	},

	focus: function() {
		if (!this.node.preventHScroll) {
			try {
				this.anchor.focus();
			} catch(e) {}
		} else if (!Ext.isIE) {
			try {
				var noscroll = this.node.getOwnerTree().getTreeEl().dom;
				var l = noscroll.scrollLeft;
				this.anchor.focus();
				noscroll.scrollLeft = l;
			} catch(e) {}
		}
	},

	toggleCheck: function(value) {
		var cb = this.checkbox;
		if (cb) {
			cb.checked = (value === undefined ? !cb.checked: value);
			this.onCheckChange();
		}
	},

	blur: function() {
		try {
			this.anchor.blur();
		} catch(e) {}
	},

	animExpand: function(callback) {
		var ct = Ext.get(this.ctNode);
		ct.stopFx();
		if (!this.node.isExpandable()) {
			this.updateExpandIcon();
			this.ctNode.style.display = "";
			Ext.callback(callback);
			return;
		}
		this.animating = true;
		this.updateExpandIcon();

		ct.slideIn('t', {
			callback: function() {
				this.animating = false;
				Ext.callback(callback);
			},
			scope: this,
			duration: this.node.ownerTree.duration || .25
		});
	},

	highlight: function() {
		var tree = this.node.getOwnerTree();
		Ext.fly(this.wrap).highlight(tree.hlColor || "C3DAF9", {
			endColor: tree.hlBaseColor
		});
	},

	collapse: function() {
		this.updateExpandIcon();
		this.ctNode.style.display = "none";
	},

	animCollapse: function(callback) {
		var ct = Ext.get(this.ctNode);
		ct.enableDisplayMode('block');
		ct.stopFx();

		this.animating = true;
		this.updateExpandIcon();

		ct.slideOut('t', {
			callback: function() {
				this.animating = false;
				Ext.callback(callback);
			},
			scope: this,
			duration: this.node.ownerTree.duration || .25
		});
	},

	getContainer: function() {
		return this.ctNode;
	},

	getEl: function() {
		return this.wrap;
	},

	appendDDGhost: function(ghostNode) {
		ghostNode.appendChild(this.elNode.cloneNode(true));
	},

	getDDRepairXY: function() {
		return Ext.lib.Dom.getXY(this.iconNode);
	},

	onRender: function() {
		this.render();
	},

	render: function(bulkRender) {
		var n = this.node,
		a = n.attributes;
		var targetNode = n.parentNode ? n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;

		if (!this.rendered) {
			this.rendered = true;

			this.renderElements(n, a, targetNode, bulkRender);

			if (a.qtip) {
				if (this.textNode.setAttributeNS) {
					this.textNode.setAttributeNS("ext", "qtip", a.qtip);
					if (a.qtipTitle) {
						this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
					}
				} else {
					this.textNode.setAttribute("ext:qtip", a.qtip);
					if (a.qtipTitle) {
						this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
					}
				}
			} else if (a.qtipCfg) {
				a.qtipCfg.target = Ext.id(this.textNode);
				Ext.QuickTips.register(a.qtipCfg);
			}
			this.initEvents();
			if (!this.node.expanded) {
				this.updateExpandIcon(true);
			}
		} else {
			if (bulkRender === true) {
				targetNode.appendChild(this.wrap);
			}
		}
	},

	renderElements: function(n, a, targetNode, bulkRender) {

		this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

		var cb = typeof a.checked == 'boolean';

		var href = a.href ? a.href: Ext.isGecko ? "": "#";
		var buf = ['<li class="x-tree-node"><div ext:tree-node-id="', n.id, '" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls, '" unselectable="on">', '<span class="x-tree-node-indent">', this.indentMarkup, "</span>", '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />', '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon', (a.icon ? " x-tree-node-inline-icon": ""), (a.iconCls ? " " + a.iconCls: ""), '" unselectable="on" />', cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />': '/>')) : '', '<a hidefocus="on" class="x-tree-node-anchor" href="', href, '" tabIndex="1" ', a.hrefTarget ? ' target="' + a.hrefTarget + '"': "", '><span unselectable="on">', n.text, "</span></a></div>", '<ul class="x-tree-node-ct" style="display:none;"></ul>', "</li>"].join('');

		var nel;
		if (bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())) {
			this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
		} else {
			this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
		}

		this.elNode = this.wrap.childNodes[0];
		this.ctNode = this.wrap.childNodes[1];
		var cs = this.elNode.childNodes;
		this.indentNode = cs[0];
		this.ecNode = cs[1];
		this.iconNode = cs[2];
		var index = 3;
		if (cb) {
			this.checkbox = cs[3];

			this.checkbox.defaultChecked = this.checkbox.checked;
			index++;
		}
		this.anchor = cs[index];
		this.textNode = cs[index].firstChild;
	},

	getAnchor: function() {
		return this.anchor;
	},

	getTextEl: function() {
		return this.textNode;
	},

	getIconEl: function() {
		return this.iconNode;
	},

	isChecked: function() {
		return this.checkbox ? this.checkbox.checked: false;
	},

	updateExpandIcon: function() {
		if (this.rendered) {
			var n = this.node,
			c1,
			c2;
			var cls = n.isLast() ? "x-tree-elbow-end": "x-tree-elbow";
			if (n.isExpandable()) {
				if (n.expanded) {
					cls += "-minus";
					c1 = "x-tree-node-collapsed";
					c2 = "x-tree-node-expanded";
				} else {
					cls += "-plus";
					c1 = "x-tree-node-expanded";
					c2 = "x-tree-node-collapsed";
				}
				if (this.wasLeaf) {
					this.removeClass("x-tree-node-leaf");
					this.wasLeaf = false;
				}
				if (this.c1 != c1 || this.c2 != c2) {
					Ext.fly(this.elNode).replaceClass(c1, c2);
					this.c1 = c1;
					this.c2 = c2;
				}
			} else {
				if (!this.wasLeaf) {
					Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
					delete this.c1;
					delete this.c2;
					this.wasLeaf = true;
				}
			}
			var ecc = "x-tree-ec-icon " + cls;
			if (this.ecc != ecc) {
				this.ecNode.className = ecc;
				this.ecc = ecc;
			}
		}
	},

	getChildIndent: function() {
		if (!this.childIndent) {
			var buf = [];
			var p = this.node;
			while (p) {
				if (!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)) {
					if (!p.isLast()) {
						buf.unshift('<img src="' + this.emptyIcon + '" class="x-tree-elbow-line" />');
					} else {
						buf.unshift('<img src="' + this.emptyIcon + '" class="x-tree-icon" />');
					}
				}
				p = p.parentNode;
			}
			this.childIndent = buf.join("");
		}
		return this.childIndent;
	},

	renderIndent: function() {
		if (this.rendered) {
			var indent = "";
			var p = this.node.parentNode;
			if (p) {
				indent = p.ui.getChildIndent();
			}
			if (this.indentMarkup != indent) {
				this.indentNode.innerHTML = indent;
				this.indentMarkup = indent;
			}
			this.updateExpandIcon();
		}
	},

	destroy: function() {
		if (this.elNode) {
			Ext.dd.Registry.unregister(this.elNode.id);
		}
		delete this.elNode;
		delete this.ctNode;
		delete this.indentNode;
		delete this.ecNode;
		delete this.iconNode;
		delete this.checkbox;
		delete this.anchor;
		delete this.textNode;
		Ext.removeNode(this.ctNode);
	}
};

Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {

	render: function() {
		if (!this.rendered) {
			var targetNode = this.node.ownerTree.innerCt.dom;
			this.node.expanded = true;
			targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
			this.wrap = this.ctNode = targetNode.firstChild;
		}
	},
	collapse: Ext.emptyFn,
	expand: Ext.emptyFn
});

Ext.tree.TreeLoader = function(config) {
	this.baseParams = {};
	Ext.apply(this, config);

	this.addEvents(
	"beforeload",
	"load",
	"loadexception");

	Ext.tree.TreeLoader.superclass.constructor.call(this);
};

Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {

	uiProviders: {},

	clearOnLoad: true,

	load: function(node, callback) {
		if (this.clearOnLoad) {
			while (node.firstChild) {
				node.removeChild(node.firstChild);
			}
		}
		if (this.doPreload(node)) {
			if (typeof callback == "function") {
				callback();
			}
		} else if (this.dataUrl || this.url) {
			this.requestData(node, callback);
		}
	},

	doPreload: function(node) {
		if (node.attributes.children) {
			if (node.childNodes.length < 1) {
				var cs = node.attributes.children;
				node.beginUpdate();
				for (var i = 0, len = cs.length; i < len; i++) {
					var cn = node.appendChild(this.createNode(cs[i]));
					if (this.preloadChildren) {
						this.doPreload(cn);
					}
				}
				node.endUpdate();
			}
			return true;
		} else {
			return false;
		}
	},

	getParams: function(node) {
		var buf = [],
		bp = this.baseParams;
		for (var key in bp) {
			if (typeof bp[key] != "function") {
				buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
			}
		}
		buf.push("node=", encodeURIComponent(node.id));
		return buf.join("");
	},

	requestData: function(node, callback) {
		if (this.fireEvent("beforeload", this, node, callback) !== false) {
			this.transId = Ext.Ajax.request({
				method: this.requestMethod,
				url: this.dataUrl || this.url,
				success: this.handleResponse,
				failure: this.handleFailure,
				scope: this,
				argument: {
					callback: callback,
					node: node
				},
				params: this.getParams(node)
			});
		} else {

			if (typeof callback == "function") {
				callback();
			}
		}
	},

	isLoading: function() {
		return !! this.transId;
	},

	abort: function() {
		if (this.isLoading()) {
			Ext.Ajax.abort(this.transId);
		}
	},

	createNode: function(attr) {

		if (this.baseAttrs) {
			Ext.applyIf(attr, this.baseAttrs);
		}
		if (this.applyLoader !== false) {
			attr.loader = this;
		}
		if (typeof attr.uiProvider == 'string') {
			attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
		}
		if (attr.nodeType) {
			return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
		} else {
			return attr.leaf ? new Ext.tree.TreeNode(attr) : new Ext.tree.AsyncTreeNode(attr);
		}
	},

	processResponse: function(response, node, callback) {
		var json = response.responseText;
		try {
			var o = eval("(" + json + ")");
			node.beginUpdate();
			for (var i = 0, len = o.length; i < len; i++) {
				var n = this.createNode(o[i]);
				if (n) {
					node.appendChild(n);
				}
			}
			node.endUpdate();
			if (typeof callback == "function") {
				callback(this, node);
			}
		} catch(e) {
			this.handleFailure(response);
		}
	},

	handleResponse: function(response) {
		this.transId = false;
		var a = response.argument;
		this.processResponse(response, a.node, a.callback);
		this.fireEvent("load", this, a.node, response);
	},

	handleFailure: function(response) {
		this.transId = false;
		var a = response.argument;
		this.fireEvent("loadexception", this, a.node, response);
		if (typeof a.callback == "function") {
			a.callback(this, a.node);
		}
	}
});

Ext.tree.TreeFilter = function(tree, config) {
	this.tree = tree;
	this.filtered = {};
	Ext.apply(this, config);
};

Ext.tree.TreeFilter.prototype = {
	clearBlank: false,
	reverse: false,
	autoClear: false,
	remove: false,

	filter: function(value, attr, startNode) {
		attr = attr || "text";
		var f;
		if (typeof value == "string") {
			var vlen = value.length;

			if (vlen == 0 && this.clearBlank) {
				this.clear();
				return;
			}
			value = value.toLowerCase();
			f = function(n) {
				return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
			};
		} else if (value.exec) {
			f = function(n) {
				return value.test(n.attributes[attr]);
			};
		} else {
			throw 'Illegal filter type, must be string or regex';
		}
		this.filterBy(f, null, startNode);
	},

	filterBy: function(fn, scope, startNode) {
		startNode = startNode || this.tree.root;
		if (this.autoClear) {
			this.clear();
		}
		var af = this.filtered,
		rv = this.reverse;
		var f = function(n) {
			if (n == startNode) {
				return true;
			}
			if (af[n.id]) {
				return false;
			}
			var m = fn.call(scope || n, n);
			if (!m || rv) {
				af[n.id] = n;
				n.ui.hide();
				return false;
			}
			return true;
		};
		startNode.cascade(f);
		if (this.remove) {
			for (var id in af) {
				if (typeof id != "function") {
					var n = af[id];
					if (n && n.parentNode) {
						n.parentNode.removeChild(n);
					}
				}
			}
		}
	},

	clear: function() {
		var t = this.tree;
		var af = this.filtered;
		for (var id in af) {
			if (typeof id != "function") {
				var n = af[id];
				if (n) {
					n.ui.show();
				}
			}
		}
		this.filtered = {};
	}
};

Ext.tree.TreeSorter = function(tree, config) {

	Ext.apply(this, config);
	tree.on("beforechildrenrendered", this.doSort, this);
	tree.on("append", this.updateSort, this);
	tree.on("insert", this.updateSort, this);
	tree.on("textchange", this.updateSortParent, this);

	var dsc = this.dir && this.dir.toLowerCase() == "desc";
	var p = this.property || "text";
	var sortType = this.sortType;
	var fs = this.folderSort;
	var cs = this.caseSensitive === true;
	var leafAttr = this.leafAttr || 'leaf';

	this.sortFn = function(n1, n2) {
		if (fs) {
			if (n1.attributes[leafAttr] && !n2.attributes[leafAttr]) {
				return 1;
			}
			if (!n1.attributes[leafAttr] && n2.attributes[leafAttr]) {
				return - 1;
			}
		}
		var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
		var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
		if (v1 < v2) {
			return dsc ? +1: -1;
		} else if (v1 > v2) {
			return dsc ? -1: +1;
		} else {
			return 0;
		}
	};
};

Ext.tree.TreeSorter.prototype = {
	doSort: function(node) {
		node.sort(this.sortFn);
	},

	compareNodes: function(n1, n2) {
		return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1: -1);
	},

	updateSort: function(tree, node) {
		if (node.childrenRendered) {
			this.doSort.defer(1, this, [node]);
		}
	},

	updateSortParent: function(node) {
		var p = node.parentNode;
		if (p && p.childrenRendered) {
			this.doSort.defer(1, this, [p]);
		}
	}
};

if (Ext.dd.DropZone) {

	Ext.tree.TreeDropZone = function(tree, config) {

		this.allowParentInsert = false;

		this.allowContainerDrop = false;

		this.appendOnly = false;
		Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.innerCt, config);

		this.tree = tree;

		this.dragOverData = {};

		this.lastInsertClass = "x-tree-no-status";
	};

	Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {

		ddGroup: "TreeDD",

		expandDelay: 1000,

		expandNode: function(node) {
			if (node.hasChildNodes() && !node.isExpanded()) {
				node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
			}
		},

		queueExpand: function(node) {
			this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
		},

		cancelExpand: function() {
			if (this.expandProcId) {
				clearTimeout(this.expandProcId);
				this.expandProcId = false;
			}
		},

		isValidDropPoint: function(n, pt, dd, e, data) {
			if (!n || !data) {
				return false;
			}
			var targetNode = n.node;
			var dropNode = data.node;

			if (! (targetNode && targetNode.isTarget && pt)) {
				return false;
			}
			if (pt == "append" && targetNode.allowChildren === false) {
				return false;
			}
			if ((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)) {
				return false;
			}
			if (dropNode && (targetNode == dropNode || dropNode.contains(targetNode))) {
				return false;
			}

			var overEvent = this.dragOverData;
			overEvent.tree = this.tree;
			overEvent.target = targetNode;
			overEvent.data = data;
			overEvent.point = pt;
			overEvent.source = dd;
			overEvent.rawEvent = e;
			overEvent.dropNode = dropNode;
			overEvent.cancel = false;
			var result = this.tree.fireEvent("nodedragover", overEvent);
			return overEvent.cancel === false && result !== false;
		},

		getDropPoint: function(e, n, dd) {
			var tn = n.node;
			if (tn.isRoot) {
				return tn.allowChildren !== false ? "append": false;
			}
			var dragEl = n.ddel;
			var t = Ext.lib.Dom.getY(dragEl),
			b = t + dragEl.offsetHeight;
			var y = Ext.lib.Event.getPageY(e);
			var noAppend = tn.allowChildren === false || tn.isLeaf();
			if (this.appendOnly || tn.parentNode.allowChildren === false) {
				return noAppend ? false: "append";
			}
			var noBelow = false;
			if (!this.allowParentInsert) {
				noBelow = tn.hasChildNodes() && tn.isExpanded();
			}
			var q = (b - t) / (noAppend ? 2: 3);
			if (y >= t && y < (t + q)) {
				return "above";
			} else if (!noBelow && (noAppend || y >= b - q && y <= b)) {
				return "below";
			} else {
				return "append";
			}
		},

		onNodeEnter: function(n, dd, e, data) {
			this.cancelExpand();
		},

		onNodeOver: function(n, dd, e, data) {
			var pt = this.getDropPoint(e, n, dd);
			var node = n.node;

			if (!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()) {
				this.queueExpand(node);
			} else if (pt != "append") {
				this.cancelExpand();
			}

			var returnCls = this.dropNotAllowed;
			if (this.isValidDropPoint(n, pt, dd, e, data)) {
				if (pt) {
					var el = n.ddel;
					var cls;
					if (pt == "above") {
						returnCls = n.node.isFirst() ? "x-tree-drop-ok-above": "x-tree-drop-ok-between";
						cls = "x-tree-drag-insert-above";
					} else if (pt == "below") {
						returnCls = n.node.isLast() ? "x-tree-drop-ok-below": "x-tree-drop-ok-between";
						cls = "x-tree-drag-insert-below";
					} else {
						returnCls = "x-tree-drop-ok-append";
						cls = "x-tree-drag-append";
					}
					if (this.lastInsertClass != cls) {
						Ext.fly(el).replaceClass(this.lastInsertClass, cls);
						this.lastInsertClass = cls;
					}
				}
			}
			return returnCls;
		},

		onNodeOut: function(n, dd, e, data) {
			this.cancelExpand();
			this.removeDropIndicators(n);
		},

		onNodeDrop: function(n, dd, e, data) {
			var point = this.getDropPoint(e, n, dd);
			var targetNode = n.node;
			targetNode.ui.startDrop();
			if (!this.isValidDropPoint(n, point, dd, e, data)) {
				targetNode.ui.endDrop();
				return false;
			}

			var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
			var dropEvent = {
				tree: this.tree,
				target: targetNode,
				data: data,
				point: point,
				source: dd,
				rawEvent: e,
				dropNode: dropNode,
				cancel: !dropNode,
				dropStatus: false
			};
			var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
			if (retval === false || dropEvent.cancel === true || !dropEvent.dropNode) {
				targetNode.ui.endDrop();
				return dropEvent.dropStatus;
			}

			targetNode = dropEvent.target;
			if (point == "append" && !targetNode.isExpanded()) {
				targetNode.expand(false, null,
				function() {
					this.completeDrop(dropEvent);
				}.createDelegate(this));
			} else {
				this.completeDrop(dropEvent);
			}
			return true;
		},

		completeDrop: function(de) {
			var ns = de.dropNode,
			p = de.point,
			t = de.target;
			if (!Ext.isArray(ns)) {
				ns = [ns];
			}
			var n;
			for (var i = 0, len = ns.length; i < len; i++) {
				n = ns[i];
				if (p == "above") {
					t.parentNode.insertBefore(n, t);
				} else if (p == "below") {
					t.parentNode.insertBefore(n, t.nextSibling);
				} else {
					t.appendChild(n);
				}
			}
			n.ui.focus();
			if (Ext.enableFx && this.tree.hlDrop) {
				n.ui.highlight();
			}
			t.ui.endDrop();
			this.tree.fireEvent("nodedrop", de);
		},

		afterNodeMoved: function(dd, data, e, targetNode, dropNode) {
			if (Ext.enableFx && this.tree.hlDrop) {
				dropNode.ui.focus();
				dropNode.ui.highlight();
			}
			this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
		},

		getTree: function() {
			return this.tree;
		},

		removeDropIndicators: function(n) {
			if (n && n.ddel) {
				var el = n.ddel;
				Ext.fly(el).removeClass(["x-tree-drag-insert-above", "x-tree-drag-insert-below", "x-tree-drag-append"]);
				this.lastInsertClass = "_noclass";
			}
		},

		beforeDragDrop: function(target, e, id) {
			this.cancelExpand();
			return true;
		},

		afterRepair: function(data) {
			if (data && Ext.enableFx) {
				data.node.ui.highlight();
			}
			this.hideProxy();
		}
	});

}

if (Ext.dd.DragZone) {
	Ext.tree.TreeDragZone = function(tree, config) {
		Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getTreeEl(), config);

		this.tree = tree;
	};

	Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {

		ddGroup: "TreeDD",

		onBeforeDrag: function(data, e) {
			var n = data.node;
			return n && n.draggable && !n.disabled;
		},

		onInitDrag: function(e) {
			var data = this.dragData;
			this.tree.getSelectionModel().select(data.node);
			this.tree.eventModel.disable();
			this.proxy.update("");
			data.node.ui.appendDDGhost(this.proxy.ghost.dom);
			this.tree.fireEvent("startdrag", this.tree, data.node, e);
		},

		getRepairXY: function(e, data) {
			return data.node.ui.getDDRepairXY();
		},

		onEndDrag: function(data, e) {
			this.tree.eventModel.enable.defer(100, this.tree.eventModel);
			this.tree.fireEvent("enddrag", this.tree, data.node, e);
		},

		onValidDrop: function(dd, e, id) {
			this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
			this.hideProxy();
		},

		beforeInvalidDrop: function(e, id) {

			var sm = this.tree.getSelectionModel();
			sm.clearSelections();
			sm.select(this.dragData.node);
		},

		afterRepair: function() {
			if (Ext.enableFx && this.tree.hlDrop) {
				Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
			}
			this.dragging = false;
		}
	});
}

Ext.tree.TreeEditor = function(tree, fc, config) {
	fc = fc || {};
	var field = fc.events ? fc: new Ext.form.TextField(fc);
	Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);

	this.tree = tree;

	if (!tree.rendered) {
		tree.on('render', this.initEditor, this);
	} else {
		this.initEditor(tree);
	}
};

Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {

	alignment: "l-l",
	autoSize: false,

	hideEl: false,

	cls: "x-small-editor x-tree-editor",

	shim: false,
	shadow: "frame",

	maxWidth: 250,

	editDelay: 350,

	initEditor: function(tree) {
		tree.on('beforeclick', this.beforeNodeClick, this);
		tree.on('dblclick', this.onNodeDblClick, this);
		this.on('complete', this.updateNode, this);
		this.on('beforestartedit', this.fitToTree, this);
		this.on('startedit', this.bindScroll, this, {
			delay: 10
		});
		this.on('specialkey', this.onSpecialKey, this);
	},

	fitToTree: function(ed, el) {
		var td = this.tree.getTreeEl().dom,
		nd = el.dom;
		if (td.scrollLeft > nd.offsetLeft) {
			td.scrollLeft = nd.offsetLeft;
		}
		var w = Math.min(this.maxWidth, (td.clientWidth > 20 ? td.clientWidth: td.offsetWidth) - Math.max(0, nd.offsetLeft - td.scrollLeft) - 5);
		this.setSize(w, '');
	},

	triggerEdit: function(node, defer) {
		this.completeEdit();
		if (node.attributes.editable !== false) {

			this.editNode = node;
			if (this.tree.autoScroll) {
				node.ui.getEl().scrollIntoView(this.tree.body);
			}
			this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);
			return false;
		}
	},

	bindScroll: function() {
		this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
	},

	beforeNodeClick: function(node, e) {
		clearTimeout(this.autoEditTimer);
		if (this.tree.getSelectionModel().isSelected(node)) {
			e.stopEvent();
			return this.triggerEdit(node);
		}
	},

	onNodeDblClick: function(node, e) {
		clearTimeout(this.autoEditTimer);
	},

	updateNode: function(ed, value) {
		this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
		this.editNode.setText(value);
	},

	onHide: function() {
		Ext.tree.TreeEditor.superclass.onHide.call(this);
		if (this.editNode) {
			this.editNode.ui.focus.defer(50, this.editNode.ui);
		}
	},

	onSpecialKey: function(field, e) {
		var k = e.getKey();
		if (k == e.ESC) {
			e.stopEvent();
			this.cancelEdit();
		} else if (k == e.ENTER && !e.hasModifier()) {
			e.stopEvent();
			this.completeEdit();
		}
	}
});

Ext.menu.Menu = function(config) {
	if (Ext.isArray(config)) {
		config = {
			items: config
		};
	}
	Ext.apply(this, config);
	this.id = this.id || Ext.id();
	this.addEvents(
	'beforeshow',
	'beforehide',
	'show',
	'hide',
	'click',
	'mouseover',
	'mouseout',
	'itemclick');
	Ext.menu.MenuMgr.register(this);
	Ext.menu.Menu.superclass.constructor.call(this);
	var mis = this.items;

	this.items = new Ext.util.MixedCollection();
	if (mis) {
		this.add.apply(this, mis);
	}
};

Ext.extend(Ext.menu.Menu, Ext.util.Observable, {

	minWidth: 120,

	shadow: "sides",

	subMenuAlign: "tl-tr?",

	defaultAlign: "tl-bl?",

	allowOtherMenus: false,

	ignoreParentClicks: false,

	hidden: true,

	createEl: function() {
		return new Ext.Layer({
			cls: "x-menu",
			shadow: this.shadow,
			constrain: false,
			parentEl: this.parentEl || document.body,
			zindex: 15000
		});
	},

	render: function() {
		if (this.el) {
			return;
		}
		var el = this.el = this.createEl();

		if (!this.keyNav) {
			this.keyNav = new Ext.menu.MenuNav(this);
		}
		if (this.plain) {
			el.addClass("x-menu-plain");
		}
		if (this.cls) {
			el.addClass(this.cls);
		}
		this.focusEl = el.createChild({
			tag: "a",
			cls: "x-menu-focus",
			href: "#",
			onclick: "return false;",
			tabIndex: "-1"
		});
		var ul = el.createChild({
			tag: "ul",
			cls: "x-menu-list"
		});
		ul.on("click", this.onClick, this);
		ul.on("mouseover", this.onMouseOver, this);
		ul.on("mouseout", this.onMouseOut, this);
		this.items.each(function(item) {
			var li = document.createElement("li");
			li.className = "x-menu-list-item";
			ul.dom.appendChild(li);
			item.render(li, this);
		},
		this);
		this.ul = ul;
		this.autoWidth();
	},

	autoWidth: function() {
		var el = this.el,
		ul = this.ul;
		if (!el) {
			return;
		}
		var w = this.width;
		if (w) {
			el.setWidth(w);
		} else if (Ext.isIE) {
			el.setWidth(this.minWidth);
			var t = el.dom.offsetWidth;
			el.setWidth(ul.getWidth() + el.getFrameWidth("lr"));
		}
	},

	delayAutoWidth: function() {
		if (this.el) {
			if (!this.awTask) {
				this.awTask = new Ext.util.DelayedTask(this.autoWidth, this);
			}
			this.awTask.delay(20);
		}
	},

	findTargetItem: function(e) {
		var t = e.getTarget(".x-menu-list-item", this.ul, true);
		if (t && t.menuItemId) {
			return this.items.get(t.menuItemId);
		}
	},

	onClick: function(e) {
		var t;
		if (t = this.findTargetItem(e)) {
			if (t.menu && this.ignoreParentClicks) {
				t.expandMenu();
			} else {
				t.onClick(e);
				this.fireEvent("click", this, t, e);
			}
		}
	},

	setActiveItem: function(item, autoExpand) {
		if (item != this.activeItem) {
			if (this.activeItem) {
				this.activeItem.deactivate();
			}
			this.activeItem = item;
			item.activate(autoExpand);
		} else if (autoExpand) {
			item.expandMenu();
		}
	},

	tryActivate: function(start, step) {
		var items = this.items;
		for (var i = start, len = items.length; i >= 0 && i < len; i += step) {
			var item = items.get(i);
			if (!item.disabled && item.canActivate) {
				this.setActiveItem(item, false);
				return item;
			}
		}
		return false;
	},

	onMouseOver: function(e) {
		var t;
		if (t = this.findTargetItem(e)) {
			if (t.canActivate && !t.disabled) {
				this.setActiveItem(t, true);
			}
		}
		this.over = true;
		this.fireEvent("mouseover", this, e, t);
	},

	onMouseOut: function(e) {
		var t;
		if (t = this.findTargetItem(e)) {
			if (t == this.activeItem && t.shouldDeactivate(e)) {
				this.activeItem.deactivate();
				delete this.activeItem;
			}
		}
		this.over = false;
		this.fireEvent("mouseout", this, e, t);
	},

	isVisible: function() {
		return this.el && !this.hidden;
	},

	show: function(el, pos, parentMenu) {
		this.parentMenu = parentMenu;
		if (!this.el) {
			this.render();
		}
		this.fireEvent("beforeshow", this);
		this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
	},

	showAt: function(xy, parentMenu, _e) {
		this.parentMenu = parentMenu;
		if (!this.el) {
			this.render();
		}
		if (_e !== false) {
			this.fireEvent("beforeshow", this);
			xy = this.el.adjustForConstraints(xy);
		}
		this.el.setXY(xy);
		this.el.show();
		this.hidden = false;
		this.focus();
		this.fireEvent("show", this);
	},

	focus: function() {
		if (!this.hidden) {
			this.doFocus.defer(50, this);
		}
	},

	doFocus: function() {
		if (!this.hidden) {
			this.focusEl.focus();
		}
	},

	hide: function(deep) {
		if (this.el && this.isVisible()) {
			this.fireEvent("beforehide", this);
			if (this.activeItem) {
				this.activeItem.deactivate();
				this.activeItem = null;
			}
			this.el.hide();
			this.hidden = true;
			this.fireEvent("hide", this);
		}
		if (deep === true && this.parentMenu) {
			this.parentMenu.hide(true);
		}
	},

	add: function() {
		var a = arguments,
		l = a.length,
		item;
		for (var i = 0; i < l; i++) {
			var el = a[i];
			if (el.render) {
				item = this.addItem(el);
			} else if (typeof el == "string") {
				if (el == "separator" || el == "-") {
					item = this.addSeparator();
				} else {
					item = this.addText(el);
				}
			} else if (el.tagName || el.el) {
				item = this.addElement(el);
			} else if (typeof el == "object") {
				Ext.applyIf(el, this.defaults);
				item = this.addMenuItem(el);
			}
		}
		return item;
	},

	getEl: function() {
		if (!this.el) {
			this.render();
		}
		return this.el;
	},

	addSeparator: function() {
		return this.addItem(new Ext.menu.Separator());
	},

	addElement: function(el) {
		return this.addItem(new Ext.menu.BaseItem(el));
	},

	addItem: function(item) {
		this.items.add(item);
		if (this.ul) {
			var li = document.createElement("li");
			li.className = "x-menu-list-item";
			this.ul.dom.appendChild(li);
			item.render(li, this);
			this.delayAutoWidth();
		}
		return item;
	},

	addMenuItem: function(config) {
		if (! (config instanceof Ext.menu.Item)) {
			if (typeof config.checked == "boolean") {
				config = new Ext.menu.CheckItem(config);
			} else {
				config = new Ext.menu.Item(config);
			}
		}
		return this.addItem(config);
	},

	addText: function(text) {
		return this.addItem(new Ext.menu.TextItem(text));
	},

	insert: function(index, item) {
		this.items.insert(index, item);
		if (this.ul) {
			var li = document.createElement("li");
			li.className = "x-menu-list-item";
			this.ul.dom.insertBefore(li, this.ul.dom.childNodes[index]);
			item.render(li, this);
			this.delayAutoWidth();
		}
		return item;
	},

	remove: function(item) {
		this.items.removeKey(item.id);
		item.destroy();
	},

	removeAll: function() {
		if (this.items) {
			var f;
			while (f = this.items.first()) {
				this.remove(f);
			}
		}
	},

	destroy: function() {
		this.beforeDestroy();
		Ext.menu.MenuMgr.unregister(this);
		if (this.keyNav) {
			this.keyNav.disable();
		}
		this.removeAll();
		if (this.ul) {
			this.ul.removeAllListeners();
		}
		if (this.el) {
			this.el.destroy();
		}
	},

	beforeDestroy: Ext.emptyFn

});

Ext.menu.MenuNav = function(menu) {
	Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
	this.scope = this.menu = menu;
};

Ext.extend(Ext.menu.MenuNav, Ext.KeyNav, {
	doRelay: function(e, h) {
		var k = e.getKey();
		if (!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN) {
			this.menu.tryActivate(0, 1);
			return false;
		}
		return h.call(this.scope || this, e, this.menu);
	},

	up: function(e, m) {
		if (!m.tryActivate(m.items.indexOf(m.activeItem) - 1, -1)) {
			m.tryActivate(m.items.length - 1, -1);
		}
	},

	down: function(e, m) {
		if (!m.tryActivate(m.items.indexOf(m.activeItem) + 1, 1)) {
			m.tryActivate(0, 1);
		}
	},

	right: function(e, m) {
		if (m.activeItem) {
			m.activeItem.expandMenu(true);
		}
	},

	left: function(e, m) {
		m.hide();
		if (m.parentMenu && m.parentMenu.activeItem) {
			m.parentMenu.activeItem.activate();
		}
	},

	enter: function(e, m) {
		if (m.activeItem) {
			e.stopPropagation();
			m.activeItem.onClick(e);
			m.fireEvent("click", this, m.activeItem);
			return true;
		}
	}
});

Ext.menu.MenuMgr = function() {
	var menus,
	active,
	groups = {},
	attached = false,
	lastShow = new Date();

	function init() {
		menus = {};
		active = new Ext.util.MixedCollection();
		Ext.getDoc().addKeyListener(27,
		function() {
			if (active.length > 0) {
				hideAll();
			}
		});
	}

	function hideAll() {
		if (active && active.length > 0) {
			var c = active.clone();
			c.each(function(m) {
				m.hide();
			});
		}
	}

	function onHide(m) {
		active.remove(m);
		if (active.length < 1) {
			Ext.getDoc().un("mousedown", onMouseDown);
			attached = false;
		}
	}

	function onShow(m) {
		var last = active.last();
		lastShow = new Date();
		active.add(m);
		if (!attached) {
			Ext.getDoc().on("mousedown", onMouseDown);
			attached = true;
		}
		if (m.parentMenu) {
			m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
			m.parentMenu.activeChild = m;
		} else if (last && last.isVisible()) {
			m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
		}
	}

	function onBeforeHide(m) {
		if (m.activeChild) {
			m.activeChild.hide();
		}
		if (m.autoHideTimer) {
			clearTimeout(m.autoHideTimer);
			delete m.autoHideTimer;
		}
	}

	function onBeforeShow(m) {
		var pm = m.parentMenu;
		if (!pm && !m.allowOtherMenus) {
			hideAll();
		} else if (pm && pm.activeChild) {
			pm.activeChild.hide();
		}
	}

	function onMouseDown(e) {
		if (lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")) {
			hideAll();
		}
	}

	function onBeforeCheck(mi, state) {
		if (state) {
			var g = groups[mi.group];
			for (var i = 0, l = g.length; i < l; i++) {
				if (g[i] != mi) {
					g[i].setChecked(false);
				}
			}
		}
	}

	return {

		hideAll: function() {
			hideAll();
		},

		register: function(menu) {
			if (!menus) {
				init();
			}
			menus[menu.id] = menu;
			menu.on("beforehide", onBeforeHide);
			menu.on("hide", onHide);
			menu.on("beforeshow", onBeforeShow);
			menu.on("show", onShow);
			var g = menu.group;
			if (g && menu.events["checkchange"]) {
				if (!groups[g]) {
					groups[g] = [];
				}
				groups[g].push(menu);
				menu.on("checkchange", onCheck);
			}
		},

		get: function(menu) {
			if (typeof menu == "string") {
				if (!menus) {
					return null;
				}
				return menus[menu];
			} else if (menu.events) {
				return menu;
			} else if (typeof menu.length == 'number') {
				return new Ext.menu.Menu({
					items: menu
				});
			} else {
				return new Ext.menu.Menu(menu);
			}
		},

		unregister: function(menu) {
			delete menus[menu.id];
			menu.un("beforehide", onBeforeHide);
			menu.un("hide", onHide);
			menu.un("beforeshow", onBeforeShow);
			menu.un("show", onShow);
			var g = menu.group;
			if (g && menu.events["checkchange"]) {
				groups[g].remove(menu);
				menu.un("checkchange", onCheck);
			}
		},

		registerCheckable: function(menuItem) {
			var g = menuItem.group;
			if (g) {
				if (!groups[g]) {
					groups[g] = [];
				}
				groups[g].push(menuItem);
				menuItem.on("beforecheckchange", onBeforeCheck);
			}
		},

		unregisterCheckable: function(menuItem) {
			var g = menuItem.group;
			if (g) {
				groups[g].remove(menuItem);
				menuItem.un("beforecheckchange", onBeforeCheck);
			}
		},

		getCheckedItem: function(groupId) {
			var g = groups[groupId];
			if (g) {
				for (var i = 0, l = g.length; i < l; i++) {
					if (g[i].checked) {
						return g[i];
					}
				}
			}
			return null;
		},

		setCheckedItem: function(groupId, itemId) {
			var g = groups[groupId];
			if (g) {
				for (var i = 0, l = g.length; i < l; i++) {
					if (g[i].id == itemId) {
						g[i].setChecked(true);
					}
				}
			}
			return null;
		}
	};
} ();

Ext.menu.BaseItem = function(config) {
	Ext.menu.BaseItem.superclass.constructor.call(this, config);

	this.addEvents(
	'click',
	'activate',
	'deactivate');

	if (this.handler) {
		this.on("click", this.handler, this.scope);
	}
};

Ext.extend(Ext.menu.BaseItem, Ext.Component, {

	canActivate: false,

	activeClass: "x-menu-item-active",

	hideOnClick: true,

	hideDelay: 100,

	ctype: "Ext.menu.BaseItem",

	actionMode: "container",

	render: function(container, parentMenu) {

		this.parentMenu = parentMenu;
		Ext.menu.BaseItem.superclass.render.call(this, container);
		this.container.menuItemId = this.id;
	},

	onRender: function(container, position) {
		this.el = Ext.get(this.el);
		container.dom.appendChild(this.el.dom);
	},

	setHandler: function(handler, scope) {
		if (this.handler) {
			this.un("click", this.handler, this.scope);
		}
		this.on("click", this.handler = handler, this.scope = scope);
	},

	onClick: function(e) {
		if (!this.disabled && this.fireEvent("click", this, e) !== false && this.parentMenu.fireEvent("itemclick", this, e) !== false) {
			this.handleClick(e);
		} else {
			e.stopEvent();
		}
	},

	activate: function() {
		if (this.disabled) {
			return false;
		}
		var li = this.container;
		li.addClass(this.activeClass);
		this.region = li.getRegion().adjust(2, 2, -2, -2);
		this.fireEvent("activate", this);
		return true;
	},

	deactivate: function() {
		this.container.removeClass(this.activeClass);
		this.fireEvent("deactivate", this);
	},

	shouldDeactivate: function(e) {
		return ! this.region || !this.region.contains(e.getPoint());
	},

	handleClick: function(e) {
		if (this.hideOnClick) {
			this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);
		}
	},

	expandMenu: function(autoActivate) {},

	hideMenu: function() {}
});

Ext.menu.TextItem = function(cfg) {
	if (typeof cfg == 'string') {
		cfg = {
			text: cfg
		}
	}
	Ext.menu.TextItem.superclass.constructor.call(this, cfg);
};

Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {

	hideOnClick: false,

	itemCls: "x-menu-text",

	onRender: function() {
		var s = document.createElement("span");
		s.className = this.itemCls;
		s.innerHTML = this.text;
		this.el = s;
		Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
	}
});

Ext.menu.Separator = function(config) {
	Ext.menu.Separator.superclass.constructor.call(this, config);
};

Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {

	itemCls: "x-menu-sep",

	hideOnClick: false,

	onRender: function(li) {
		var s = document.createElement("span");
		s.className = this.itemCls;
		s.innerHTML = "&#160;";
		this.el = s;
		li.addClass("x-menu-sep-li");
		Ext.menu.Separator.superclass.onRender.apply(this, arguments);
	}
});

Ext.menu.Item = function(config) {
	Ext.menu.Item.superclass.constructor.call(this, config);
	if (this.menu) {
		this.menu = Ext.menu.MenuMgr.get(this.menu);
	}
};
Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {

	itemCls: "x-menu-item",

	canActivate: true,

	showDelay: 200,
	hideDelay: 200,

	ctype: "Ext.menu.Item",

	onRender: function(container, position) {
		var el = document.createElement("a");
		el.hideFocus = true;
		el.unselectable = "on";
		el.href = this.href || "#";
		if (this.hrefTarget) {
			el.target = this.hrefTarget;
		}
		el.className = this.itemCls + (this.menu ? " x-menu-item-arrow": "") + (this.cls ? " " + this.cls: "");
		el.innerHTML = String.format('<img src="{0}" class="x-menu-item-icon {2}" />{1}', this.icon || Ext.BLANK_IMAGE_URL, this.itemText || this.text, this.iconCls || '');
		this.el = el;
		Ext.menu.Item.superclass.onRender.call(this, container, position);
	},

	setText: function(text) {
		this.text = text;
		if (this.rendered) {
			this.el.update(String.format('<img src="{0}" class="x-menu-item-icon {2}">{1}', this.icon || Ext.BLANK_IMAGE_URL, this.text, this.iconCls || ''));
			this.parentMenu.autoWidth();
		}
	},

	setIconClass: function(cls) {
		var oldCls = this.iconCls;
		this.iconCls = cls;
		if (this.rendered) {
			this.el.child('img.x-menu-item-icon').replaceClass(oldCls, this.iconCls);
		}
	},

	handleClick: function(e) {
		if (!this.href) {
			e.stopEvent();
		}
		Ext.menu.Item.superclass.handleClick.apply(this, arguments);
	},

	activate: function(autoExpand) {
		if (Ext.menu.Item.superclass.activate.apply(this, arguments)) {
			this.focus();
			if (autoExpand) {
				this.expandMenu();
			}
		}
		return true;
	},

	shouldDeactivate: function(e) {
		if (Ext.menu.Item.superclass.shouldDeactivate.call(this, e)) {
			if (this.menu && this.menu.isVisible()) {
				return ! this.menu.getEl().getRegion().contains(e.getPoint());
			}
			return true;
		}
		return false;
	},

	deactivate: function() {
		Ext.menu.Item.superclass.deactivate.apply(this, arguments);
		this.hideMenu();
	},

	expandMenu: function(autoActivate) {
		if (!this.disabled && this.menu) {
			clearTimeout(this.hideTimer);
			delete this.hideTimer;
			if (!this.menu.isVisible() && !this.showTimer) {
				this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
			} else if (this.menu.isVisible() && autoActivate) {
				this.menu.tryActivate(0, 1);
			}
		}
	},

	deferExpand: function(autoActivate) {
		delete this.showTimer;
		this.menu.show(this.container, this.parentMenu.subMenuAlign || "tl-tr?", this.parentMenu);
		if (autoActivate) {
			this.menu.tryActivate(0, 1);
		}
	},

	hideMenu: function() {
		clearTimeout(this.showTimer);
		delete this.showTimer;
		if (!this.hideTimer && this.menu && this.menu.isVisible()) {
			this.hideTimer = this.deferHide.defer(this.hideDelay, this);
		}
	},

	deferHide: function() {
		delete this.hideTimer;
		if (this.menu.over) {
			this.parentMenu.setActiveItem(this, false);
		} else {
			this.menu.hide();
		}
	}
});

Ext.menu.CheckItem = function(config) {
	Ext.menu.CheckItem.superclass.constructor.call(this, config);
	this.addEvents(
	"beforecheckchange",
	"checkchange");

	if (this.checkHandler) {
		this.on('checkchange', this.checkHandler, this.scope);
	}
	Ext.menu.MenuMgr.registerCheckable(this);
};
Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {

	itemCls: "x-menu-item x-menu-check-item",

	groupClass: "x-menu-group-item",

	checked: false,

	ctype: "Ext.menu.CheckItem",

	onRender: function(c) {
		Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
		if (this.group) {
			this.el.addClass(this.groupClass);
		}
		if (this.checked) {
			this.checked = false;
			this.setChecked(true, true);
		}
	},

	destroy: function() {
		Ext.menu.MenuMgr.unregisterCheckable(this);
		Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
	},

	setChecked: function(state, suppressEvent) {
		if (this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false) {
			if (this.container) {
				this.container[state ? "addClass": "removeClass"]("x-menu-item-checked");
			}
			this.checked = state;
			if (suppressEvent !== true) {
				this.fireEvent("checkchange", this, state);
			}
		}
	},

	handleClick: function(e) {
		if (!this.disabled && !(this.checked && this.group)) {
			this.setChecked(!this.checked);
		}
		Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
	}
});

Ext.menu.Adapter = function(component, config) {
	Ext.menu.Adapter.superclass.constructor.call(this, config);
	this.component = component;
};
Ext.extend(Ext.menu.Adapter, Ext.menu.BaseItem, {
	canActivate: true,

	onRender: function(container, position) {
		this.component.render(container);
		this.el = this.component.getEl();
	},

	activate: function() {
		if (this.disabled) {
			return false;
		}
		this.component.focus();
		this.fireEvent("activate", this);
		return true;
	},

	deactivate: function() {
		this.fireEvent("deactivate", this);
	},

	disable: function() {
		this.component.disable();
		Ext.menu.Adapter.superclass.disable.call(this);
	},

	enable: function() {
		this.component.enable();
		Ext.menu.Adapter.superclass.enable.call(this);
	}
});

Ext.menu.DateItem = function(config) {
	Ext.menu.DateItem.superclass.constructor.call(this, new Ext.DatePicker(config), config);

	this.picker = this.component;
	this.addEvents('select');

	this.picker.on("render",
	function(picker) {
		picker.getEl().swallowEvent("click");
		picker.container.addClass("x-menu-date-item");
	});

	this.picker.on("select", this.onSelect, this);
};

Ext.extend(Ext.menu.DateItem, Ext.menu.Adapter, {
	onSelect: function(picker, date) {
		this.fireEvent("select", this, date, picker);
		Ext.menu.DateItem.superclass.handleClick.call(this);
	}
});

Ext.menu.ColorItem = function(config) {
	Ext.menu.ColorItem.superclass.constructor.call(this, new Ext.ColorPalette(config), config);

	this.palette = this.component;
	this.relayEvents(this.palette, ["select"]);
	if (this.selectHandler) {
		this.on('select', this.selectHandler, this.scope);
	}
};
Ext.extend(Ext.menu.ColorItem, Ext.menu.Adapter);

Ext.menu.DateMenu = function(config) {
	Ext.menu.DateMenu.superclass.constructor.call(this, config);
	this.plain = true;
	var di = new Ext.menu.DateItem(config);
	this.add(di);

	this.picker = di.picker;

	this.relayEvents(di, ["select"]);

	this.on('beforeshow',
	function() {
		if (this.picker) {
			this.picker.hideMonthPicker(true);
		}
	},
	this);
};
Ext.extend(Ext.menu.DateMenu, Ext.menu.Menu, {
	cls: 'x-date-menu',

	beforeDestroy: function() {
		this.picker.destroy();
	}
});

Ext.menu.ColorMenu = function(config) {
	Ext.menu.ColorMenu.superclass.constructor.call(this, config);
	this.plain = true;
	var ci = new Ext.menu.ColorItem(config);
	this.add(ci);

	this.palette = ci.palette;

	this.relayEvents(ci, ["select"]);
};
Ext.extend(Ext.menu.ColorMenu, Ext.menu.Menu);

Ext.form.Field = Ext.extend(Ext.BoxComponent, {

	invalidClass: "x-form-invalid",

	invalidText: "The value in this field is invalid",

	focusClass: "x-form-focus",

	validationEvent: "keyup",

	validateOnBlur: true,

	validationDelay: 250,

	defaultAutoCreate: {
		tag: "input",
		type: "text",
		size: "20",
		autocomplete: "off"
	},

	fieldClass: "x-form-field",

	msgTarget: 'qtip',

	msgFx: 'normal',

	readOnly: false,

	disabled: false,

	isFormField: true,

	hasFocus: false,

	initComponent: function() {
		Ext.form.Field.superclass.initComponent.call(this);
		this.addEvents(
		'focus',
		'blur',
		'specialkey',
		'change',
		'invalid',
		'valid');
	},

	getName: function() {
		return this.rendered && this.el.dom.name ? this.el.dom.name: (this.hiddenName || '');
	},

	onRender: function(ct, position) {
		Ext.form.Field.superclass.onRender.call(this, ct, position);
		if (!this.el) {
			var cfg = this.getAutoCreate();
			if (!cfg.name) {
				cfg.name = this.name || this.id;
			}
			if (this.inputType) {
				cfg.type = this.inputType;
			}
			this.el = ct.createChild(cfg, position);
		}
		var type = this.el.dom.type;
		if (type) {
			if (type == 'password') {
				type = 'text';
			}
			this.el.addClass('x-form-' + type);
		}
		if (this.readOnly) {
			this.el.dom.readOnly = true;
		}
		if (this.tabIndex !== undefined) {
			this.el.dom.setAttribute('tabIndex', this.tabIndex);
		}

		this.el.addClass([this.fieldClass, this.cls]);
	},

	initValue: function() {
		if (this.value !== undefined) {
			this.setValue(this.value);
		} else if (this.el.dom.value.length > 0 && this.el.dom.value != this.emptyText) {
			this.setValue(this.el.dom.value);
		}
		this.originalValue = this.getValue();
	},

	isDirty: function() {
		if (this.disabled) {
			return false;
		}
		return String(this.getValue()) !== String(this.originalValue);
	},

	afterRender: function() {
		Ext.form.Field.superclass.afterRender.call(this);
		this.initEvents();
		this.initValue();
	},

	fireKey: function(e) {
		if (e.isSpecialKey()) {
			this.fireEvent("specialkey", this, e);
		}
	},

	reset: function() {
		this.setValue(this.originalValue);
		this.clearInvalid();
	},

	initEvents: function() {
		this.el.on(Ext.isIE || Ext.isSafari3 ? "keydown": "keypress", this.fireKey, this);
		this.el.on("focus", this.onFocus, this);

		var o = this.inEditor && Ext.isWindows && Ext.isGecko ? {
			buffer: 10
		}: null;
		this.el.on("blur", this.onBlur, this, o);

		this.originalValue = this.getValue();
	},

	onFocus: function() {
		if (!Ext.isOpera && this.focusClass) {
			this.el.addClass(this.focusClass);
		}
		if (!this.hasFocus) {
			this.hasFocus = true;
			this.startValue = this.getValue();
			this.fireEvent("focus", this);
		}
	},

	beforeBlur: Ext.emptyFn,

	onBlur: function() {
		this.beforeBlur();
		if (!Ext.isOpera && this.focusClass) {
			this.el.removeClass(this.focusClass);
		}
		this.hasFocus = false;
		if (this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur") {
			this.validate();
		}
		var v = this.getValue();
		if (String(v) !== String(this.startValue)) {
			this.fireEvent('change', this, v, this.startValue);
		}
		this.fireEvent("blur", this);
	},

	isValid: function(preventMark) {
		if (this.disabled) {
			return true;
		}
		var restore = this.preventMark;
		this.preventMark = preventMark === true;
		var v = this.validateValue(this.processValue(this.getRawValue()));
		this.preventMark = restore;
		return v;
	},

	validate: function() {
		if (this.disabled || this.validateValue(this.processValue(this.getRawValue()))) {
			this.clearInvalid();
			return true;
		}
		return false;
	},

	processValue: function(value) {
		return value;
	},

	validateValue: function(value) {
		return true;
	},

	markInvalid: function(msg) {
		if (!this.rendered || this.preventMark) {
			return;
		}
		this.el.addClass(this.invalidClass);
		msg = msg || this.invalidText;

		switch (this.msgTarget) {
		case 'qtip':
			this.el.dom.qtip = msg;
			this.el.dom.qclass = 'x-form-invalid-tip';
			if (Ext.QuickTips) {
				Ext.QuickTips.enable();
			}
			break;
		case 'title':
			this.el.dom.title = msg;
			break;
		case 'under':
			if (!this.errorEl) {
				var elp = this.getErrorCt();
				if (!elp) {
					this.el.dom.title = msg;
					break;
				}
				this.errorEl = elp.createChild({
					cls: 'x-form-invalid-msg'
				});
				this.errorEl.setWidth(elp.getWidth(true) - 20);
			}
			this.errorEl.update(msg);
			Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
			break;
		case 'side':
			if (!this.errorIcon) {
				var elp = this.getErrorCt();
				if (!elp) {
					this.el.dom.title = msg;
					break;
				}
				this.errorIcon = elp.createChild({
					cls: 'x-form-invalid-icon'
				});
			}
			this.alignErrorIcon();
			this.errorIcon.dom.qtip = msg;
			this.errorIcon.dom.qclass = 'x-form-invalid-tip';
			this.errorIcon.show();
			this.on('resize', this.alignErrorIcon, this);
			break;
		default:
			var t = Ext.getDom(this.msgTarget);
			t.innerHTML = msg;
			t.style.display = this.msgDisplay;
			break;
		}
		this.fireEvent('invalid', this, msg);
	},

	getErrorCt: function() {
		return this.el.findParent('.x-form-element', 5, true) || this.el.findParent('.x-form-field-wrap', 5, true);
	},

	alignErrorIcon: function() {
		this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
	},

	clearInvalid: function() {
		if (!this.rendered || this.preventMark) {
			return;
		}
		this.el.removeClass(this.invalidClass);
		switch (this.msgTarget) {
		case 'qtip':
			this.el.dom.qtip = '';
			break;
		case 'title':
			this.el.dom.title = '';
			break;
		case 'under':
			if (this.errorEl) {
				Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
			}
			break;
		case 'side':
			if (this.errorIcon) {
				this.errorIcon.dom.qtip = '';
				this.errorIcon.hide();
				this.un('resize', this.alignErrorIcon, this);
			}
			break;
		default:
			var t = Ext.getDom(this.msgTarget);
			t.innerHTML = '';
			t.style.display = 'none';
			break;
		}
		this.fireEvent('valid', this);
	},

	getRawValue: function() {
		var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
		if (v === this.emptyText) {
			v = '';
		}
		return v;
	},

	getValue: function() {
		if (!this.rendered) {
			return this.value;
		}
		var v = this.el.getValue();
		if (v === this.emptyText || v === undefined) {
			v = '';
		}
		return v;
	},

	setRawValue: function(v) {
		return this.el.dom.value = (v === null || v === undefined ? '': v);
	},

	setValue: function(v) {
		this.value = v;
		if (this.rendered) {
			this.el.dom.value = (v === null || v === undefined ? '': v);
			this.validate();
		}
	},

	adjustSize: function(w, h) {
		var s = Ext.form.Field.superclass.adjustSize.call(this, w, h);
		s.width = this.adjustWidth(this.el.dom.tagName, s.width);
		return s;
	},

	adjustWidth: function(tag, w) {
		tag = tag.toLowerCase();
		if (typeof w == 'number' && !Ext.isSafari) {
			if (Ext.isIE && (tag == 'input' || tag == 'textarea')) {
				if (tag == 'input' && !Ext.isStrict) {
					return this.inEditor ? w: w - 3;
				}
				if (tag == 'input' && Ext.isStrict) {
					return w - (Ext.isIE6 ? 4: 1);
				}
				if (tag == 'textarea' && Ext.isStrict) {
					return w - 2;
				}
			} else if (Ext.isOpera && Ext.isStrict) {
				if (tag == 'input') {
					return w + 2;
				}
				if (tag == 'textarea') {
					return w - 2;
				}
			}
		}
		return w;
	}

});

Ext.form.MessageTargets = {
	'qtip': {
		mark: function(f) {
			this.el.dom.qtip = msg;
			this.el.dom.qclass = 'x-form-invalid-tip';
			if (Ext.QuickTips) {
				Ext.QuickTips.enable();
			}
		},
		clear: function(f) {
			this.el.dom.qtip = '';
		}
	},
	'title': {
		mark: function(f) {
			this.el.dom.title = msg;
		},
		clear: function(f) {
			this.el.dom.title = '';
		}
	},
	'under': {
		mark: function(f) {
			if (!this.errorEl) {
				var elp = this.getErrorCt();
				if (!elp) {
					this.el.dom.title = msg;
					return;
				}
				this.errorEl = elp.createChild({
					cls: 'x-form-invalid-msg'
				});
				this.errorEl.setWidth(elp.getWidth(true) - 20);
			}
			this.errorEl.update(msg);
			Ext.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
		},
		clear: function(f) {
			if (this.errorEl) {
				Ext.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
			} else {
				this.el.dom.title = '';
			}
		}
	},
	'side': {
		mark: function(f) {
			if (!this.errorIcon) {
				var elp = this.getErrorCt();
				if (!elp) {
					this.el.dom.title = msg;
					return;
				}
				this.errorIcon = elp.createChild({
					cls: 'x-form-invalid-icon'
				});
			}
			this.alignErrorIcon();
			this.errorIcon.dom.qtip = msg;
			this.errorIcon.dom.qclass = 'x-form-invalid-tip';
			this.errorIcon.show();
			this.on('resize', this.alignErrorIcon, this);
		},
		clear: function(f) {
			if (this.errorIcon) {
				this.errorIcon.dom.qtip = '';
				this.errorIcon.hide();
				this.un('resize', this.alignErrorIcon, this);
			} else {
				this.el.dom.title = '';
			}
		}
	},
	'around': {
		mark: function(f) {
			},
		clear: function(f) {
			}
	}
};

Ext.form.Field.msgFx = {
	normal: {
		show: function(msgEl, f) {
			msgEl.setDisplayed('block');
		},

		hide: function(msgEl, f) {
			msgEl.setDisplayed(false).update('');
		}
	},

	slide: {
		show: function(msgEl, f) {
			msgEl.slideIn('t', {
				stopFx: true
			});
		},

		hide: function(msgEl, f) {
			msgEl.slideOut('t', {
				stopFx: true,
				useDisplay: true
			});
		}
	},

	slideRight: {
		show: function(msgEl, f) {
			msgEl.fixDisplay();
			msgEl.alignTo(f.el, 'tl-tr');
			msgEl.slideIn('l', {
				stopFx: true
			});
		},

		hide: function(msgEl, f) {
			msgEl.slideOut('l', {
				stopFx: true,
				useDisplay: true
			});
		}
	}
};
Ext.reg('field', Ext.form.Field);

Ext.form.TextField = Ext.extend(Ext.form.Field, {

	grow: false,

	growMin: 30,

	growMax: 800,

	vtype: null,

	maskRe: null,

	disableKeyFilter: false,

	allowBlank: true,

	minLength: 0,

	maxLength: Number.MAX_VALUE,

	minLengthText: "The minimum length for this field is {0}",

	maxLengthText: "The maximum length for this field is {0}",

	selectOnFocus: false,

	blankText: "This field is required",

	validator: null,

	regex: null,

	regexText: "",

	emptyText: null,

	emptyClass: 'x-form-empty-field',

	initComponent: function() {
		Ext.form.TextField.superclass.initComponent.call(this);
		this.addEvents(
		'autosize',
		'keydown',
		'keyup',
		'keypress');
	},

	initEvents: function() {
		Ext.form.TextField.superclass.initEvents.call(this);
		if (this.validationEvent == 'keyup') {
			this.validationTask = new Ext.util.DelayedTask(this.validate, this);
			this.el.on('keyup', this.filterValidation, this);
		} else if (this.validationEvent !== false) {
			this.el.on(this.validationEvent, this.validate, this, {
				buffer: this.validationDelay
			});
		}
		if (this.selectOnFocus || this.emptyText) {
			this.on("focus", this.preFocus, this);
			this.el.on('mousedown',
			function() {
				if (!this.hasFocus) {
					this.el.on('mouseup',
					function(e) {
						e.preventDefault();
					},
					this, {
						single: true
					});
				}
			},
			this);
			if (this.emptyText) {
				this.on('blur', this.postBlur, this);
				this.applyEmptyText();
			}
		}
		if (this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype + 'Mask']))) {
			this.el.on("keypress", this.filterKeys, this);
		}
		if (this.grow) {
			this.el.on("keyup", this.onKeyUpBuffered, this, {
				buffer: 50
			});
			this.el.on("click", this.autoSize, this);
		}

		if (this.enableKeyEvents) {
			this.el.on("keyup", this.onKeyUp, this);
			this.el.on("keydown", this.onKeyDown, this);
			this.el.on("keypress", this.onKeyPress, this);
		}
	},

	processValue: function(value) {
		if (this.stripCharsRe) {
			var newValue = value.replace(this.stripCharsRe, '');
			if (newValue !== value) {
				this.setRawValue(newValue);
				return newValue;
			}
		}
		return value;
	},

	filterValidation: function(e) {
		if (!e.isNavKeyPress()) {
			this.validationTask.delay(this.validationDelay);
		}
	},

	onKeyUpBuffered: function(e) {
		if (!e.isNavKeyPress()) {
			this.autoSize();
		}
	},

	onKeyUp: function(e) {
		this.fireEvent('keyup', this, e);
	},

	onKeyDown: function(e) {
		this.fireEvent('keydown', this, e);
	},

	onKeyPress: function(e) {
		this.fireEvent('keypress', this, e);
	},

	reset: function() {
		Ext.form.TextField.superclass.reset.call(this);
		this.applyEmptyText();
	},

	applyEmptyText: function() {
		if (this.rendered && this.emptyText && this.getRawValue().length < 1) {
			this.setRawValue(this.emptyText);
			this.el.addClass(this.emptyClass);
		}
	},

	preFocus: function() {
		if (this.emptyText) {
			if (this.el.dom.value == this.emptyText) {
				this.setRawValue('');
			}
			this.el.removeClass(this.emptyClass);
		}
		if (this.selectOnFocus) {
			this.el.dom.select();
		}
	},

	postBlur: function() {
		this.applyEmptyText();
	},

	filterKeys: function(e) {
		if (e.ctrlKey) {
			return;
		}
		var k = e.getKey();
		if (Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))) {
			return;
		}
		var c = e.getCharCode(),
		cc = String.fromCharCode(c);
		if (!Ext.isGecko && e.isSpecialKey() && !cc) {
			return;
		}
		if (!this.maskRe.test(cc)) {
			e.stopEvent();
		}
	},

	setValue: function(v) {
		if (this.emptyText && this.el && v !== undefined && v !== null && v !== '') {
			this.el.removeClass(this.emptyClass);
		}
		Ext.form.TextField.superclass.setValue.apply(this, arguments);
		this.applyEmptyText();
		this.autoSize();
	},

	validateValue: function(value) {
		if (value.length < 1 || value === this.emptyText) {
			if (this.allowBlank) {
				this.clearInvalid();
				return true;
			} else {
				this.markInvalid(this.blankText);
				return false;
			}
		}
		if (value.length < this.minLength) {
			this.markInvalid(String.format(this.minLengthText, this.minLength));
			return false;
		}
		if (value.length > this.maxLength) {
			this.markInvalid(String.format(this.maxLengthText, this.maxLength));
			return false;
		}
		if (this.vtype) {
			var vt = Ext.form.VTypes;
			if (!vt[this.vtype](value, this)) {
				this.markInvalid(this.vtypeText || vt[this.vtype + 'Text']);
				return false;
			}
		}
		if (typeof this.validator == "function") {
			var msg = this.validator(value);
			if (msg !== true) {
				this.markInvalid(msg);
				return false;
			}
		}
		if (this.regex && !this.regex.test(value)) {
			this.markInvalid(this.regexText);
			return false;
		}
		return true;
	},

	selectText: function(start, end) {
		var v = this.getRawValue();
		if (v.length > 0) {
			start = start === undefined ? 0: start;
			end = end === undefined ? v.length: end;
			var d = this.el.dom;
			if (d.setSelectionRange) {
				d.setSelectionRange(start, end);
			} else if (d.createTextRange) {
				var range = d.createTextRange();
				range.moveStart("character", start);
				range.moveEnd("character", end - v.length);
				range.select();
			}
		}
	},

	autoSize: function() {
		if (!this.grow || !this.rendered) {
			return;
		}
		if (!this.metrics) {
			this.metrics = Ext.util.TextMetrics.createInstance(this.el);
		}
		var el = this.el;
		var v = el.dom.value;
		var d = document.createElement('div');
		d.appendChild(document.createTextNode(v));
		v = d.innerHTML;
		d = null;
		v += "&#160;";
		var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) + 10, this.growMin));
		this.el.setWidth(w);
		this.fireEvent("autosize", this, w);
	}
});
Ext.reg('textfield', Ext.form.TextField);

Ext.form.TriggerField = Ext.extend(Ext.form.TextField, {

	defaultAutoCreate: {
		tag: "input",
		type: "text",
		size: "16",
		autocomplete: "off"
	},

	hideTrigger: false,

	autoSize: Ext.emptyFn,
	monitorTab: true,
	deferHeight: true,
	mimicing: false,

	onResize: function(w, h) {
		Ext.form.TriggerField.superclass.onResize.call(this, w, h);
		if (typeof w == 'number') {
			this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));
		}
		this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
	},

	adjustSize: Ext.BoxComponent.prototype.adjustSize,

	getResizeEl: function() {
		return this.wrap;
	},

	getPositionEl: function() {
		return this.wrap;
	},

	alignErrorIcon: function() {
		if (this.wrap) {
			this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
		}
	},

	onRender: function(ct, position) {
		Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
		this.wrap = this.el.wrap({
			cls: "x-form-field-wrap"
		});
		this.trigger = this.wrap.createChild(this.triggerConfig || {
			tag: "img",
			src: Ext.BLANK_IMAGE_URL,
			cls: "x-form-trigger " + this.triggerClass
		});
		if (this.hideTrigger) {
			this.trigger.setDisplayed(false);
		}
		this.initTrigger();
		if (!this.width) {
			this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
		}
	},

	afterRender: function() {
		Ext.form.TriggerField.superclass.afterRender.call(this);
		var y;
		if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) {
			this.el.position();
			this.el.setY(y);
		}
	},

	initTrigger: function() {
		this.trigger.on("click", this.onTriggerClick, this, {
			preventDefault: true
		});
		this.trigger.addClassOnOver('x-form-trigger-over');
		this.trigger.addClassOnClick('x-form-trigger-click');
	},

	onDestroy: function() {
		if (this.trigger) {
			this.trigger.removeAllListeners();
			this.trigger.remove();
		}
		if (this.wrap) {
			this.wrap.remove();
		}
		Ext.form.TriggerField.superclass.onDestroy.call(this);
	},

	onFocus: function() {
		Ext.form.TriggerField.superclass.onFocus.call(this);
		if (!this.mimicing) {
			this.wrap.addClass('x-trigger-wrap-focus');
			this.mimicing = true;
			Ext.get(Ext.isIE ? document.body: document).on("mousedown", this.mimicBlur, this, {
				delay: 10
			});
			if (this.monitorTab) {
				this.el.on("keydown", this.checkTab, this);
			}
		}
	},

	checkTab: function(e) {
		if (e.getKey() == e.TAB) {
			this.triggerBlur();
		}
	},

	onBlur: function() {},

	mimicBlur: function(e) {
		if (!this.wrap.contains(e.target) && this.validateBlur(e)) {
			this.triggerBlur();
		}
	},

	triggerBlur: function() {
		this.mimicing = false;
		Ext.get(Ext.isIE ? document.body: document).un("mousedown", this.mimicBlur, this);
		if (this.monitorTab) {
			this.el.un("keydown", this.checkTab, this);
		}
		this.beforeBlur();
		this.wrap.removeClass('x-trigger-wrap-focus');
		Ext.form.TriggerField.superclass.onBlur.call(this);
	},

	beforeBlur: Ext.emptyFn,

	validateBlur: function(e) {
		return true;
	},

	onDisable: function() {
		Ext.form.TriggerField.superclass.onDisable.call(this);
		if (this.wrap) {
			this.wrap.addClass(this.disabledClass);
			this.el.removeClass(this.disabledClass);
		}
	},

	onEnable: function() {
		Ext.form.TriggerField.superclass.onEnable.call(this);
		if (this.wrap) {
			this.wrap.removeClass(this.disabledClass);
		}
	},

	onShow: function() {
		if (this.wrap) {
			this.wrap.dom.style.display = '';
			this.wrap.dom.style.visibility = 'visible';
		}
	},

	onHide: function() {
		this.wrap.dom.style.display = 'none';
	},

	onTriggerClick: Ext.emptyFn

});

Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
	initComponent: function() {
		Ext.form.TwinTriggerField.superclass.initComponent.call(this);

		this.triggerConfig = {
			tag: 'span',
			cls: 'x-form-twin-triggers',
			cn: [{
				tag: "img",
				src: Ext.BLANK_IMAGE_URL,
				cls: "x-form-trigger " + this.trigger1Class
			},
			{
				tag: "img",
				src: Ext.BLANK_IMAGE_URL,
				cls: "x-form-trigger " + this.trigger2Class
			}]
		};
	},

	getTrigger: function(index) {
		return this.triggers[index];
	},

	initTrigger: function() {
		var ts = this.trigger.select('.x-form-trigger', true);
		this.wrap.setStyle('overflow', 'hidden');
		var triggerField = this;
		ts.each(function(t, all, index) {
			t.hide = function() {
				var w = triggerField.wrap.getWidth();
				this.dom.style.display = 'none';
				triggerField.el.setWidth(w - triggerField.trigger.getWidth());
			};
			t.show = function() {
				var w = triggerField.wrap.getWidth();
				this.dom.style.display = '';
				triggerField.el.setWidth(w - triggerField.trigger.getWidth());
			};
			var triggerIndex = 'Trigger' + (index + 1);

			if (this['hide' + triggerIndex]) {
				t.dom.style.display = 'none';
			}
			t.on("click", this['on' + triggerIndex + 'Click'], this, {
				preventDefault: true
			});
			t.addClassOnOver('x-form-trigger-over');
			t.addClassOnClick('x-form-trigger-click');
		},
		this);
		this.triggers = ts.elements;
	},

	onTrigger1Click: Ext.emptyFn,
	onTrigger2Click: Ext.emptyFn
});
Ext.reg('trigger', Ext.form.TriggerField);

Ext.form.TextArea = Ext.extend(Ext.form.TextField, {

	growMin: 60,

	growMax: 1000,
	growAppend: '&#160;\n&#160;',
	growPad: 0,

	enterIsSpecial: false,

	preventScrollbars: false,

	onRender: function(ct, position) {
		if (!this.el) {
			this.defaultAutoCreate = {
				tag: "textarea",
				style: "width:100px;height:60px;",
				autocomplete: "off"
			};
		}
		Ext.form.TextArea.superclass.onRender.call(this, ct, position);
		if (this.grow) {
			this.textSizeEl = Ext.DomHelper.append(document.body, {
				tag: "pre",
				cls: "x-form-grow-sizer"
			});
			if (this.preventScrollbars) {
				this.el.setStyle("overflow", "hidden");
			}
			this.el.setHeight(this.growMin);
		}
	},

	onDestroy: function() {
		if (this.textSizeEl) {
			Ext.removeNode(this.textSizeEl);
		}
		Ext.form.TextArea.superclass.onDestroy.call(this);
	},

	fireKey: function(e) {
		if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))) {
			this.fireEvent("specialkey", this, e);
		}
	},

	onKeyUp: function(e) {
		if (!e.isNavKeyPress() || e.getKey() == e.ENTER) {
			this.autoSize();
		}
		Ext.form.TextArea.superclass.onKeyUp.call(this, e);
	},

	autoSize: function() {
		if (!this.grow || !this.textSizeEl) {
			return;
		}
		var el = this.el;
		var v = el.dom.value;
		var ts = this.textSizeEl;
		ts.innerHTML = '';
		ts.appendChild(document.createTextNode(v));
		v = ts.innerHTML;

		Ext.fly(ts).setWidth(this.el.getWidth());
		if (v.length < 1) {
			v = "&#160;&#160;";
		} else {
			if (Ext.isIE) {
				v = v.replace(/\n/g, '<p>&#160;</p>');
			}
			v += this.growAppend;
		}
		ts.innerHTML = v;
		var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin) + this.growPad);
		if (h != this.lastHeight) {
			this.lastHeight = h;
			this.el.setHeight(h);
			this.fireEvent("autosize", this, h);
		}
	}
});
Ext.reg('textarea', Ext.form.TextArea);

Ext.form.NumberField = Ext.extend(Ext.form.TextField, {

	fieldClass: "x-form-field x-form-num-field",

	allowDecimals: true,

	decimalSeparator: ".",

	decimalPrecision: 2,

	allowNegative: true,

	minValue: Number.NEGATIVE_INFINITY,

	maxValue: Number.MAX_VALUE,

	minText: "The minimum value for this field is {0}",

	maxText: "The maximum value for this field is {0}",

	nanText: "{0} is not a valid number",

	baseChars: "0123456789",

	initEvents: function() {
		Ext.form.NumberField.superclass.initEvents.call(this);
		var allowed = this.baseChars + '';
		if (this.allowDecimals) {
			allowed += this.decimalSeparator;
		}
		if (this.allowNegative) {
			allowed += "-";
		}
		this.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
		var keyPress = function(e) {
			var k = e.getKey();
			if (!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)) {
				return;
			}
			var c = e.getCharCode();
			if (allowed.indexOf(String.fromCharCode(c)) === -1) {
				e.stopEvent();
			}
		};
		this.el.on("keypress", keyPress, this);
	},

	validateValue: function(value) {
		if (!Ext.form.NumberField.superclass.validateValue.call(this, value)) {
			return false;
		}
		if (value.length < 1) {
			return true;
		}
		value = String(value).replace(this.decimalSeparator, ".");
		if (isNaN(value)) {
			this.markInvalid(String.format(this.nanText, value));
			return false;
		}
		var num = this.parseValue(value);
		if (num < this.minValue) {
			this.markInvalid(String.format(this.minText, this.minValue));
			return false;
		}
		if (num > this.maxValue) {
			this.markInvalid(String.format(this.maxText, this.maxValue));
			return false;
		}
		return true;
	},

	getValue: function() {
		return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
	},

	setValue: function(v) {
		v = typeof v == 'number' ? v: parseFloat(String(v).replace(this.decimalSeparator, "."));
		v = isNaN(v) ? '': String(v).replace(".", this.decimalSeparator);
		Ext.form.NumberField.superclass.setValue.call(this, v);
	},

	parseValue: function(value) {
		value = parseFloat(String(value).replace(this.decimalSeparator, "."));
		return isNaN(value) ? '': value;
	},

	fixPrecision: function(value) {
		var nan = isNaN(value);
		if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
			return nan ? '': value;
		}
		return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
	},

	beforeBlur: function() {
		var v = this.parseValue(this.getRawValue());
		if (v) {
			this.setValue(this.fixPrecision(v));
		}
	}
});
Ext.reg('numberfield', Ext.form.NumberField);

Ext.form.DateField = Ext.extend(Ext.form.TriggerField, {

	format: "m/d/Y",

	altFormats: "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d",

	disabledDaysText: "Disabled",

	disabledDatesText: "Disabled",

	minText: "The date in this field must be equal to or after {0}",

	maxText: "The date in this field must be equal to or before {0}",

	invalidText: "{0} is not a valid date - it must be in the format {1}",

	triggerClass: 'x-form-date-trigger',

	showToday: true,

	defaultAutoCreate: {
		tag: "input",
		type: "text",
		size: "10",
		autocomplete: "off"
	},

	initComponent: function() {
		Ext.form.DateField.superclass.initComponent.call(this);
		if (typeof this.minValue == "string") {
			this.minValue = this.parseDate(this.minValue);
		}
		if (typeof this.maxValue == "string") {
			this.maxValue = this.parseDate(this.maxValue);
		}
		this.ddMatch = null;
		this.initDisabledDays();
	},

	initDisabledDays: function() {
		if (this.disabledDates) {
			var dd = this.disabledDates;
			var re = "(?:";
			for (var i = 0; i < dd.length; i++) {
				re += dd[i];
				if (i != dd.length - 1) re += "|";
			}
			this.disabledDatesRE = new RegExp(re + ")");
		}
	},

	setDisabledDates: function(dd) {
		this.disabledDates = dd;
		this.initDisabledDays();
		if (this.menu) {
			this.menu.picker.setDisabledDates(this.disabledDatesRE);
		}
	},

	setDisabledDays: function(dd) {
		this.disabledDays = dd;
		if (this.menu) {
			this.menu.picker.setDisabledDays(dd);
		}
	},

	setMinValue: function(dt) {
		this.minValue = (typeof dt == "string" ? this.parseDate(dt) : dt);
		if (this.menu) {
			this.menu.picker.setMinDate(this.minValue);
		}
	},

	setMaxValue: function(dt) {
		this.maxValue = (typeof dt == "string" ? this.parseDate(dt) : dt);
		if (this.menu) {
			this.menu.picker.setMaxDate(this.maxValue);
		}
	},

	validateValue: function(value) {
		value = this.formatDate(value);
		if (!Ext.form.DateField.superclass.validateValue.call(this, value)) {
			return false;
		}
		if (value.length < 1) {
			return true;
		}
		var svalue = value;
		value = this.parseDate(value);
		if (!value) {
			this.markInvalid(String.format(this.invalidText, svalue, this.format));
			return false;
		}
		var time = value.getTime();
		if (this.minValue && time < this.minValue.getTime()) {
			this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
			return false;
		}
		if (this.maxValue && time > this.maxValue.getTime()) {
			this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
			return false;
		}
		if (this.disabledDays) {
			var day = value.getDay();
			for (var i = 0; i < this.disabledDays.length; i++) {
				if (day === this.disabledDays[i]) {
					this.markInvalid(this.disabledDaysText);
					return false;
				}
			}
		}
		var fvalue = this.formatDate(value);
		if (this.ddMatch && this.ddMatch.test(fvalue)) {
			this.markInvalid(String.format(this.disabledDatesText, fvalue));
			return false;
		}
		return true;
	},

	validateBlur: function() {
		return ! this.menu || !this.menu.isVisible();
	},

	getValue: function() {
		return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
	},

	setValue: function(date) {
		Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
	},

	parseDate: function(value) {
		if (!value || Ext.isDate(value)) {
			return value;
		}
		var v = Date.parseDate(value, this.format);
		if (!v && this.altFormats) {
			if (!this.altFormatsArray) {
				this.altFormatsArray = this.altFormats.split("|");
			}
			for (var i = 0, len = this.altFormatsArray.length; i < len && !v; i++) {
				v = Date.parseDate(value, this.altFormatsArray[i]);
			}
		}
		return v;
	},

	onDestroy: function() {
		if (this.menu) {
			this.menu.destroy();
		}
		if (this.wrap) {
			this.wrap.remove();
		}
		Ext.form.DateField.superclass.onDestroy.call(this);
	},

	formatDate: function(date) {
		return Ext.isDate(date) ? date.dateFormat(this.format) : date;
	},

	menuListeners: {
		select: function(m, d) {
			this.setValue(d);
		},
		show: function() {
			this.onFocus();
		},
		hide: function() {
			this.focus.defer(10, this);
			var ml = this.menuListeners;
			this.menu.un("select", ml.select, this);
			this.menu.un("show", ml.show, this);
			this.menu.un("hide", ml.hide, this);
		}
	},

	onTriggerClick: function() {
		if (this.disabled) {
			return;
		}
		if (this.menu == null) {
			this.menu = new Ext.menu.DateMenu();
		}
		Ext.apply(this.menu.picker, {
			minDate: this.minValue,
			maxDate: this.maxValue,
			disabledDatesRE: this.ddMatch,
			disabledDatesText: this.disabledDatesText,
			disabledDays: this.disabledDays,
			disabledDaysText: this.disabledDaysText,
			format: this.format,
			showToday: this.showToday,
			minText: String.format(this.minText, this.formatDate(this.minValue)),
			maxText: String.format(this.maxText, this.formatDate(this.maxValue))
		});
		this.menu.on(Ext.apply({},
		this.menuListeners, {
			scope: this
		}));
		this.menu.picker.setValue(this.getValue() || new Date());
		this.menu.show(this.el, "tl-bl?");
	},

	beforeBlur: function() {
		var v = this.parseDate(this.getRawValue());
		if (v) {
			this.setValue(v);
		}
	}

});
Ext.reg('datefield', Ext.form.DateField);

Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {

	defaultAutoCreate: {
		tag: "input",
		type: "text",
		size: "24",
		autocomplete: "off"
	},

	listClass: '',

	selectedClass: 'x-combo-selected',

	triggerClass: 'x-form-arrow-trigger',

	shadow: 'sides',

	listAlign: 'tl-bl?',

	maxHeight: 300,

	minHeight: 90,

	triggerAction: 'query',

	minChars: 4,

	typeAhead: false,

	queryDelay: 500,

	pageSize: 0,

	selectOnFocus: false,

	queryParam: 'query',

	loadingText: 'Loading...',

	resizable: false,

	handleHeight: 8,

	editable: true,

	allQuery: '',

	mode: 'remote',

	minListWidth: 70,

	forceSelection: false,

	typeAheadDelay: 250,

	lazyInit: true,

	initComponent: function() {
		Ext.form.ComboBox.superclass.initComponent.call(this);
		this.addEvents(
		'expand',
		'collapse',
		'beforeselect',
		'select',
		'beforequery');
		if (this.transform) {
			this.allowDomMove = false;
			var s = Ext.getDom(this.transform);
			if (!this.hiddenName) {
				this.hiddenName = s.name;
			}
			if (!this.store) {
				this.mode = 'local';
				var d = [],
				opts = s.options;
				for (var i = 0, len = opts.length; i < len; i++) {
					var o = opts[i];
					var value = (Ext.isIE ? o.getAttributeNode('value').specified: o.hasAttribute('value')) ? o.value: o.text;
					if (o.selected) {
						this.value = value;
					}
					d.push([value, o.text]);
				}
				this.store = new Ext.data.SimpleStore({
					'id': 0,
					fields: ['value', 'text'],
					data: d
				});
				this.valueField = 'value';
				this.displayField = 'text';
			}
			s.name = Ext.id();
			if (!this.lazyRender) {
				this.target = true;
				this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
				Ext.removeNode(s);
				this.render(this.el.parentNode);
			} else {
				Ext.removeNode(s);
			}
		} else if (Ext.isArray(this.store)) {
			if (Ext.isArray(this.store[0])) {
				this.store = new Ext.data.SimpleStore({
					fields: ['value', 'text'],
					data: this.store
				});
				this.valueField = 'value';
			} else {
				this.store = new Ext.data.SimpleStore({
					fields: ['text'],
					data: this.store,
					expandData: true
				});
				this.valueField = 'text';
			}
			this.displayField = 'text';
			this.mode = 'local';
		}

		this.selectedIndex = -1;
		if (this.mode == 'local') {
			if (this.initialConfig.queryDelay === undefined) {
				this.queryDelay = 10;
			}
			if (this.initialConfig.minChars === undefined) {
				this.minChars = 0;
			}
		}
	},

	onRender: function(ct, position) {
		Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
		if (this.hiddenName) {
			this.hiddenField = this.el.insertSibling({
				tag: 'input',
				type: 'hidden',
				name: this.hiddenName,
				id: (this.hiddenId || this.hiddenName)
			},
			'before', true);

			this.el.dom.removeAttribute('name');
		}
		if (Ext.isGecko) {
			this.el.dom.setAttribute('autocomplete', 'off');
		}

		if (!this.lazyInit) {
			this.initList();
		} else {
			this.on('focus', this.initList, this, {
				single: true
			});
		}

		if (!this.editable) {
			this.editable = true;
			this.setEditable(false);
		}
	},

	initValue: function() {
		Ext.form.ComboBox.superclass.initValue.call(this);
		if (this.hiddenField) {
			this.hiddenField.value = this.hiddenValue !== undefined ? this.hiddenValue: this.value !== undefined ? this.value: '';
		}
	},

	initList: function() {
		if (!this.list) {
			var cls = 'x-combo-list';

			this.list = new Ext.Layer({
				shadow: this.shadow,
				cls: [cls, this.listClass].join(' '),
				constrain: false
			});

			var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
			this.list.setWidth(lw);
			this.list.swallowEvent('mousewheel');
			this.assetHeight = 0;

			if (this.title) {
				this.header = this.list.createChild({
					cls: cls + '-hd',
					html: this.title
				});
				this.assetHeight += this.header.getHeight();
			}

			this.innerList = this.list.createChild({
				cls: cls + '-inner'
			});
			this.innerList.on('mouseover', this.onViewOver, this);
			this.innerList.on('mousemove', this.onViewMove, this);
			this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));

			if (this.pageSize) {
				this.footer = this.list.createChild({
					cls: cls + '-ft'
				});
				this.pageTb = new Ext.PagingToolbar({
					store: this.store,
					pageSize: this.pageSize,
					renderTo: this.footer
				});
				this.assetHeight += this.footer.getHeight();
			}

			if (!this.tpl) {

				this.tpl = '<tpl for="."><div class="' + cls + '-item">{' + this.displayField + '}</div></tpl>';

			}

			this.view = new Ext.DataView({
				applyTo: this.innerList,
				tpl: this.tpl,
				singleSelect: true,
				selectedClass: this.selectedClass,
				itemSelector: this.itemSelector || '.' + cls + '-item'
			});

			this.view.on('click', this.onViewClick, this);

			this.bindStore(this.store, true);

			if (this.resizable) {
				this.resizer = new Ext.Resizable(this.list, {
					pinned: true,
					handles: 'se'
				});
				this.resizer.on('resize',
				function(r, w, h) {
					this.maxHeight = h - this.handleHeight - this.list.getFrameWidth('tb') - this.assetHeight;
					this.listWidth = w;
					this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
					this.restrictHeight();
				},
				this);
				this[this.pageSize ? 'footer': 'innerList'].setStyle('margin-bottom', this.handleHeight + 'px');
			}
		}
	},

	bindStore: function(store, initial) {
		if (this.store && !initial) {
			this.store.un('beforeload', this.onBeforeLoad, this);
			this.store.un('load', this.onLoad, this);
			this.store.un('loadexception', this.collapse, this);
			if (!store) {
				this.store = null;
				if (this.view) {
					this.view.setStore(null);
				}
			}
		}
		if (store) {
			this.store = Ext.StoreMgr.lookup(store);

			this.store.on('beforeload', this.onBeforeLoad, this);
			this.store.on('load', this.onLoad, this);
			this.store.on('loadexception', this.collapse, this);

			if (this.view) {
				this.view.setStore(store);
			}
		}
	},

	initEvents: function() {
		Ext.form.ComboBox.superclass.initEvents.call(this);

		this.keyNav = new Ext.KeyNav(this.el, {
			"up": function(e) {
				this.inKeyMode = true;
				this.selectPrev();
			},

			"down": function(e) {
				if (!this.isExpanded()) {
					this.onTriggerClick();
				} else {
					this.inKeyMode = true;
					this.selectNext();
				}
			},

			"enter": function(e) {
				this.onViewClick();
				this.delayedCheck = true;
				this.unsetDelayCheck.defer(10, this);
			},

			"esc": function(e) {
				this.collapse();
			},

			"tab": function(e) {
				this.onViewClick(false);
				return true;
			},

			scope: this,

			doRelay: function(foo, bar, hname) {
				if (hname == 'down' || this.scope.isExpanded()) {
					return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
				}
				return true;
			},

			forceKeyDown: true
		});
		this.queryDelay = Math.max(this.queryDelay || 10, this.mode == 'local' ? 10: 250);
		this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
		if (this.typeAhead) {
			this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
		}
		if (this.editable !== false) {
			this.el.on("keyup", this.onKeyUp, this);
		}
		if (this.forceSelection) {
			this.on('blur', this.doForce, this);
		}
	},

	onDestroy: function() {
		if (this.view) {
			this.view.el.removeAllListeners();
			this.view.el.remove();
			this.view.purgeListeners();
		}
		if (this.list) {
			this.list.destroy();
		}
		this.bindStore(null);
		Ext.form.ComboBox.superclass.onDestroy.call(this);
	},

	unsetDelayCheck: function() {
		delete this.delayedCheck;
	},

	fireKey: function(e) {
		if (e.isNavKeyPress() && !this.isExpanded() && !this.delayedCheck) {
			this.fireEvent("specialkey", this, e);
		}
	},

	onResize: function(w, h) {
		Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
		if (this.list && this.listWidth === undefined) {
			var lw = Math.max(w, this.minListWidth);
			this.list.setWidth(lw);
			this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
		}
	},

	onEnable: function() {
		Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
		if (this.hiddenField) {
			this.hiddenField.disabled = false;
		}
	},

	onDisable: function() {
		Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
		if (this.hiddenField) {
			this.hiddenField.disabled = true;
		}
	},

	setEditable: function(value) {
		if (value == this.editable) {
			return;
		}
		this.editable = value;
		if (!value) {
			this.el.dom.setAttribute('readOnly', true);
			this.el.on('mousedown', this.onTriggerClick, this);
			this.el.addClass('x-combo-noedit');
		} else {
			this.el.dom.setAttribute('readOnly', false);
			this.el.un('mousedown', this.onTriggerClick, this);
			this.el.removeClass('x-combo-noedit');
		}
	},

	onBeforeLoad: function() {
		if (!this.hasFocus) {
			return;
		}
		this.innerList.update(this.loadingText ? '<div class="loading-indicator">' + this.loadingText + '</div>': '');
		this.restrictHeight();
		this.selectedIndex = -1;
	},

	onLoad: function() {
		if (!this.hasFocus) {
			return;
		}
		if (this.store.getCount() > 0) {
			this.expand();
			this.restrictHeight();
			if (this.lastQuery == this.allQuery) {
				if (this.editable) {
					this.el.dom.select();
				}
				if (!this.selectByValue(this.value, true)) {
					this.select(0, true);
				}
			} else {
				this.selectNext();
				if (this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
					this.taTask.delay(this.typeAheadDelay);
				}
			}
		} else {
			this.onEmptyResults();
		}
	},

	onTypeAhead: function() {
		if (this.store.getCount() > 0) {
			var r = this.store.getAt(0);
			var newValue = r.data[this.displayField];
			var len = newValue.length;
			var selStart = this.getRawValue().length;
			if (selStart != len) {
				this.setRawValue(newValue);
				this.selectText(selStart, newValue.length);
			}
		}
	},

	onSelect: function(record, index) {
		if (this.fireEvent('beforeselect', this, record, index) !== false) {
			this.setValue(record.data[this.valueField || this.displayField]);
			this.collapse();
			this.fireEvent('select', this, record, index);
		}
	},

	getValue: function() {
		if (this.valueField) {
			return typeof this.value != 'undefined' ? this.value: '';
		} else {
			return Ext.form.ComboBox.superclass.getValue.call(this);
		}
	},

	clearValue: function() {
		if (this.hiddenField) {
			this.hiddenField.value = '';
		}
		this.setRawValue('');
		this.lastSelectionText = '';
		this.applyEmptyText();
		this.value = '';
	},

	setValue: function(v) {
		var text = v;
		if (this.valueField) {
			var r = this.findRecord(this.valueField, v);
			if (r) {
				text = r.data[this.displayField];
			} else if (this.valueNotFoundText !== undefined) {
				text = this.valueNotFoundText;
			}
		}
		this.lastSelectionText = text;
		if (this.hiddenField) {
			this.hiddenField.value = v;
		}
		Ext.form.ComboBox.superclass.setValue.call(this, text);
		this.value = v;
	},

	findRecord: function(prop, value) {
		var record;
		if (this.store.getCount() > 0) {
			this.store.each(function(r) {
				if (r.data[prop] == value) {
					record = r;
					return false;
				}
			});
		}
		return record;
	},

	onViewMove: function(e, t) {
		this.inKeyMode = false;
	},

	onViewOver: function(e, t) {
		if (this.inKeyMode) {
			return;
		}
		var item = this.view.findItemFromChild(t);
		if (item) {
			var index = this.view.indexOf(item);
			this.select(index, false);
		}
	},

	onViewClick: function(doFocus) {
		var index = this.view.getSelectedIndexes()[0];
		var r = this.store.getAt(index);
		if (r) {
			this.onSelect(r, index);
		}
		if (doFocus !== false) {
			this.el.focus();
		}
	},

	restrictHeight: function() {
		this.innerList.dom.style.height = '';
		var inner = this.innerList.dom;
		var pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight: 0) + this.assetHeight;
		var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
		var ha = this.getPosition()[1] - Ext.getBody().getScroll().top;
		var hb = Ext.lib.Dom.getViewHeight() - ha - this.getSize().height;
		var space = Math.max(ha, hb, this.minHeight || 0) - this.list.shadowOffset - pad - 5;
		h = Math.min(h, space, this.maxHeight);

		this.innerList.setHeight(h);
		this.list.beginUpdate();
		this.list.setHeight(h + pad);
		this.list.alignTo(this.wrap, this.listAlign);
		this.list.endUpdate();
	},

	onEmptyResults: function() {
		this.collapse();
	},

	isExpanded: function() {
		return this.list && this.list.isVisible();
	},

	selectByValue: function(v, scrollIntoView) {
		if (v !== undefined && v !== null) {
			var r = this.findRecord(this.valueField || this.displayField, v);
			if (r) {
				this.select(this.store.indexOf(r), scrollIntoView);
				return true;
			}
		}
		return false;
	},

	select: function(index, scrollIntoView) {
		this.selectedIndex = index;
		this.view.select(index);
		if (scrollIntoView !== false) {
			var el = this.view.getNode(index);
			if (el) {
				this.innerList.scrollChildIntoView(el, false);
			}
		}
	},

	selectNext: function() {
		var ct = this.store.getCount();
		if (ct > 0) {
			if (this.selectedIndex == -1) {
				this.select(0);
			} else if (this.selectedIndex < ct - 1) {
				this.select(this.selectedIndex + 1);
			}
		}
	},

	selectPrev: function() {
		var ct = this.store.getCount();
		if (ct > 0) {
			if (this.selectedIndex == -1) {
				this.select(0);
			} else if (this.selectedIndex != 0) {
				this.select(this.selectedIndex - 1);
			}
		}
	},

	onKeyUp: function(e) {
		if (this.editable !== false && !e.isSpecialKey()) {
			this.lastKey = e.getKey();
			this.dqTask.delay(this.queryDelay);
		}
	},

	validateBlur: function() {
		return ! this.list || !this.list.isVisible();
	},

	initQuery: function() {
		this.doQuery(this.getRawValue());
	},

	doForce: function() {
		if (this.el.dom.value.length > 0) {
			this.el.dom.value = this.lastSelectionText === undefined ? '': this.lastSelectionText;
			this.applyEmptyText();
		}
	},

	doQuery: function(q, forceAll) {
		if (q === undefined || q === null) {
			q = '';
		}
		var qe = {
			query: q,
			forceAll: forceAll,
			combo: this,
			cancel: false
		};
		if (this.fireEvent('beforequery', qe) === false || qe.cancel) {
			return false;
		}
		q = qe.query;
		forceAll = qe.forceAll;
		if (forceAll === true || (q.length >= this.minChars)) {
			if (this.lastQuery !== q) {
				this.lastQuery = q;
				if (this.mode == 'local') {
					this.selectedIndex = -1;
					if (forceAll) {
						this.store.clearFilter();
					} else {
						this.store.filter(this.displayField, q);
					}
					this.onLoad();
				} else {
					this.store.baseParams[this.queryParam] = q;
					this.store.load({
						params: this.getParams(q)
					});
					this.expand();
				}
			} else {
				this.selectedIndex = -1;
				this.onLoad();
			}
		}
	},

	getParams: function(q) {
		var p = {};
		if (this.pageSize) {
			p.start = 0;
			p.limit = this.pageSize;
		}
		return p;
	},

	collapse: function() {
		if (!this.isExpanded()) {
			return;
		}
		this.list.hide();
		Ext.getDoc().un('mousewheel', this.collapseIf, this);
		Ext.getDoc().un('mousedown', this.collapseIf, this);
		this.fireEvent('collapse', this);
	},

	collapseIf: function(e) {
		if (!e.within(this.wrap) && !e.within(this.list)) {
			this.collapse();
		}
	},

	expand: function() {
		if (this.isExpanded() || !this.hasFocus) {
			return;
		}
		this.list.alignTo(this.wrap, this.listAlign);
		this.list.show();
		this.innerList.setOverflow('auto');
		Ext.getDoc().on('mousewheel', this.collapseIf, this);
		Ext.getDoc().on('mousedown', this.collapseIf, this);
		this.fireEvent('expand', this);
	},

	onTriggerClick: function() {
		if (this.disabled) {
			return;
		}
		if (this.isExpanded()) {
			this.collapse();
			this.el.focus();
		} else {
			this.onFocus({});
			if (this.triggerAction == 'all') {
				this.doQuery(this.allQuery, true);
			} else {
				this.doQuery(this.getRawValue());
			}
			this.el.focus();
		}
	}

});
Ext.reg('combo', Ext.form.ComboBox);

Ext.form.Checkbox = Ext.extend(Ext.form.Field, {

	checkedCls: 'x-form-check-checked',

	focusCls: 'x-form-check-focus',

	overCls: 'x-form-check-over',

	mouseDownCls: 'x-form-check-down',

	tabIndex: 0,

	checked: false,

	defaultAutoCreate: {
		tag: 'input',
		type: 'checkbox',
		autocomplete: 'off'
	},

	baseCls: 'x-form-check',

	initComponent: function() {
		Ext.form.Checkbox.superclass.initComponent.call(this);
		this.addEvents(
		'check');
	},

	initEvents: function() {
		Ext.form.Checkbox.superclass.initEvents.call(this);
		this.initCheckEvents();
	},

	initCheckEvents: function() {
		this.innerWrap.removeAllListeners();
		this.innerWrap.addClassOnOver(this.overCls);
		this.innerWrap.addClassOnClick(this.mouseDownCls);
		this.innerWrap.on('click', this.onClick, this);
		this.innerWrap.on('keyup', this.onKeyUp, this);
	},

	onRender: function(ct, position) {
		Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
		if (this.inputValue !== undefined) {
			this.el.dom.value = this.inputValue;
		}
		this.el.addClass('x-hidden');

		this.innerWrap = this.el.wrap({
			tabIndex: this.tabIndex,
			cls: this.baseCls + '-wrap-inner'
		});
		this.wrap = this.innerWrap.wrap({
			cls: this.baseCls + '-wrap'
		});

		if (this.boxLabel) {
			this.labelEl = this.innerWrap.createChild({
				tag: 'label',
				htmlFor: this.el.id,
				cls: 'x-form-cb-label',
				html: this.boxLabel
			});
		}

		this.imageEl = this.innerWrap.createChild({
			tag: 'img',
			src: Ext.BLANK_IMAGE_URL,
			cls: this.baseCls
		},
		this.el);

		if (this.checked) {
			this.setValue(true);
		} else {
			this.checked = this.el.dom.checked;
		}
		this.originalValue = this.checked;
	},

	onDestroy: function() {
		if (this.rendered) {
			Ext.destroy(this.imageEl, this.labelEl, this.innerWrap, this.wrap);
		}
		Ext.form.Checkbox.superclass.onDestroy.call(this);
	},

	onFocus: function(e) {
		Ext.form.Checkbox.superclass.onFocus.call(this, e);
		this.el.addClass(this.focusCls);
	},

	onBlur: function(e) {
		Ext.form.Checkbox.superclass.onBlur.call(this, e);
		this.el.removeClass(this.focusCls);
	},

	onResize: function() {
		Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
		if (!this.boxLabel && !this.fieldLabel) {
			this.el.alignTo(this.wrap, 'c-c');
		}
	},

	onKeyUp: function(e) {
		if (e.getKey() == Ext.EventObject.SPACE) {
			this.onClick(e);
		}
	},

	onClick: function(e) {
		if (!this.disabled && !this.readOnly) {
			this.toggleValue();
		}
		e.stopEvent();
	},

	onEnable: function() {
		Ext.form.Checkbox.superclass.onEnable.call(this);
		this.initCheckEvents();
	},

	onDisable: function() {
		Ext.form.Checkbox.superclass.onDisable.call(this);
		this.innerWrap.removeAllListeners();
	},

	toggleValue: function() {
		this.setValue(!this.checked);
	},

	getResizeEl: function() {
		if (!this.resizeEl) {
			this.resizeEl = Ext.isSafari ? this.wrap: (this.wrap.up('.x-form-element', 5) || this.wrap);
		}
		return this.resizeEl;
	},

	getPositionEl: function() {
		return this.wrap;
	},

	getActionEl: function() {
		return this.wrap;
	},

	markInvalid: Ext.emptyFn,

	clearInvalid: Ext.emptyFn,

	initValue: Ext.emptyFn,

	getValue: function() {
		if (this.rendered) {
			return this.el.dom.checked;
		}
		return false;
	},

	setValue: function(v) {
		var checked = this.checked;
		this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');

		if (this.el && this.el.dom) {
			this.el.dom.checked = this.checked;
			this.el.dom.defaultChecked = this.checked;
		}
		this.wrap[this.checked ? 'addClass': 'removeClass'](this.checkedCls);

		if (checked != this.checked) {
			this.fireEvent("check", this, this.checked);
			if (this.handler) {
				this.handler.call(this.scope || this, this, this.checked);
			}
		}
	}

});
Ext.reg('checkbox', Ext.form.Checkbox);

Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {

	columns: 'auto',

	vertical: false,

	allowBlank: true,

	blankText: "You must select at least one item in this group",

	defaultType: 'checkbox',

	groupCls: 'x-form-check-group',

	onRender: function(ct, position) {
		if (!this.el) {
			var panelCfg = {
				cls: this.groupCls,
				layout: 'column',
				border: false,
				renderTo: ct
			};
			var colCfg = {
				defaultType: this.defaultType,
				layout: 'form',
				border: false,
				defaults: {
					hideLabel: true,
					anchor: '100%'
				}
			}

			if (this.items[0].items) {

				Ext.apply(panelCfg, {
					layoutConfig: {
						columns: this.items.length
					},
					defaults: this.defaults,
					items: this.items
				});
				for (var i = 0, len = this.items.length; i < len; i++) {
					Ext.applyIf(this.items[i], colCfg);
				};

			} else {

				var numCols,
				cols = [];

				if (typeof this.columns == 'string') {
					this.columns = this.items.length;
				}
				if (!Ext.isArray(this.columns)) {
					var cs = [];
					for (var i = 0; i < this.columns; i++) {
						cs.push((100 / this.columns) * .01);
					}
					this.columns = cs;
				}

				numCols = this.columns.length;

				for (var i = 0; i < numCols; i++) {
					var cc = Ext.apply({
						items: []
					},
					colCfg);
					cc[this.columns[i] <= 1 ? 'columnWidth': 'width'] = this.columns[i];
					if (this.defaults) {
						cc.defaults = Ext.apply(cc.defaults || {},
						this.defaults)
					}
					cols.push(cc);
				};

				if (this.vertical) {
					var rows = Math.ceil(this.items.length / numCols),
					ri = 0;
					for (var i = 0, len = this.items.length; i < len; i++) {
						if (i > 0 && i % rows == 0) {
							ri++;
						}
						if (this.items[i].fieldLabel) {
							this.items[i].hideLabel = false;
						}
						cols[ri].items.push(this.items[i]);
					};
				} else {
					for (var i = 0, len = this.items.length; i < len; i++) {
						var ci = i % numCols;
						if (this.items[i].fieldLabel) {
							this.items[i].hideLabel = false;
						}
						cols[ci].items.push(this.items[i]);
					};
				}

				Ext.apply(panelCfg, {
					layoutConfig: {
						columns: numCols
					},
					items: cols
				});
			}

			this.panel = new Ext.Panel(panelCfg);
			this.el = this.panel.getEl();

			if (this.forId && this.itemCls) {
				var l = this.el.up(this.itemCls).child('label', true);
				if (l) {
					l.setAttribute('htmlFor', this.forId);
				}
			}

			var fields = this.panel.findBy(function(c) {
				return c.isFormField;
			},
			this);

			this.items = new Ext.util.MixedCollection();
			this.items.addAll(fields);
		}
		Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
	},

	validateValue: function(value) {
		if (!this.allowBlank) {
			var blank = true;
			this.items.each(function(f) {
				if (f.checked) {
					return blank = false;
				}
			},
			this);
			if (blank) {
				this.markInvalid(this.blankText);
				return false;
			}
		}
		return true;
	},

	onDisable: function() {
		this.items.each(function(item) {
			item.disable();
		})
	},

	onEnable: function() {
		this.items.each(function(item) {
			item.enable();
		})
	},

	onResize: function(w, h) {
		this.panel.setSize(w, h);
		this.panel.doLayout();
	},

	reset: function() {
		Ext.form.CheckboxGroup.superclass.reset.call(this);
		this.items.each(function(c) {
			if (c.reset) {
				c.reset();
			}
		},
		this);
	},

	initValue: Ext.emptyFn,

	getValue: Ext.emptyFn,

	getRawValue: Ext.emptyFn,

	setValue: Ext.emptyFn,

	setRawValue: Ext.emptyFn

});

Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);

Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
	inputType: 'radio',
	baseCls: 'x-form-radio',

	getGroupValue: function() {
		var c = this.getParent().child('input[name=' + this.el.dom.name + ']:checked', true);
		return c ? c.value: null;
	},

	getParent: function() {
		return this.el.up('form') || Ext.getBody();
	},

	toggleValue: function() {
		if (!this.checked) {
			var els = this.getParent().select('input[name=' + this.el.dom.name + ']');
			els.each(function(el) {
				if (el.dom.id == this.id) {
					this.setValue(true);
				} else {
					Ext.getCmp(el.dom.id).setValue(false);
				}
			},
			this);
		}
	},

	setValue: function(v) {
		if (typeof v == 'boolean') {
			Ext.form.Radio.superclass.setValue.call(this, v);
		} else {
			var r = this.getParent().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
			if (r && !r.checked) {
				Ext.getCmp(r.id).toggleValue();
			};
		}
	},

	markInvalid: Ext.emptyFn,

	clearInvalid: Ext.emptyFn

});
Ext.reg('radio', Ext.form.Radio);

Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {

	allowBlank: true,

	blankText: "You must select one item in this group",

	defaultType: 'radio',

	groupCls: 'x-form-radio-group'
});

Ext.reg('radiogroup', Ext.form.RadioGroup);

Ext.form.Hidden = Ext.extend(Ext.form.Field, {

	inputType: 'hidden',

	onRender: function() {
		Ext.form.Hidden.superclass.onRender.apply(this, arguments);
	},

	initEvents: function() {
		this.originalValue = this.getValue();
	},

	setSize: Ext.emptyFn,
	setWidth: Ext.emptyFn,
	setHeight: Ext.emptyFn,
	setPosition: Ext.emptyFn,
	setPagePosition: Ext.emptyFn,
	markInvalid: Ext.emptyFn,
	clearInvalid: Ext.emptyFn
});
Ext.reg('hidden', Ext.form.Hidden);

Ext.form.BasicForm = function(el, config) {
	Ext.apply(this, config);

	this.items = new Ext.util.MixedCollection(false,
	function(o) {
		return o.id || (o.id = Ext.id());
	});
	this.addEvents(
	'beforeaction',
	'actionfailed',
	'actioncomplete');

	if (el) {
		this.initEl(el);
	}
	Ext.form.BasicForm.superclass.constructor.call(this);
};

Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {

	timeout: 30,

	activeAction: null,

	trackResetOnLoad: false,

	initEl: function(el) {
		this.el = Ext.get(el);
		this.id = this.el.id || Ext.id();
		if (!this.standardSubmit) {
			this.el.on('submit', this.onSubmit, this);
		}
		this.el.addClass('x-form');
	},

	getEl: function() {
		return this.el;
	},

	onSubmit: function(e) {
		e.stopEvent();
	},

	destroy: function() {
		this.items.each(function(f) {
			Ext.destroy(f);
		});
		if (this.el) {
			this.el.removeAllListeners();
			this.el.remove();
		}
		this.purgeListeners();
	},

	isValid: function() {
		var valid = true;
		this.items.each(function(f) {
			if (!f.validate()) {
				valid = false;
			}
		});
		return valid;
	},

	isDirty: function() {
		var dirty = false;
		this.items.each(function(f) {
			if (f.isDirty()) {
				dirty = true;
				return false;
			}
		});
		return dirty;
	},

	doAction: function(action, options) {
		if (typeof action == 'string') {
			action = new Ext.form.Action.ACTION_TYPES[action](this, options);
		}
		if (this.fireEvent('beforeaction', this, action) !== false) {
			this.beforeAction(action);
			action.run.defer(100, action);
		}
		return this;
	},

	submit: function(options) {
		if (this.standardSubmit) {
			var v = this.isValid();
			if (v) {
				this.el.dom.submit();
			}
			return v;
		}
		this.doAction('submit', options);
		return this;
	},

	load: function(options) {
		this.doAction('load', options);
		return this;
	},

	updateRecord: function(record) {
		record.beginEdit();
		var fs = record.fields;
		fs.each(function(f) {
			var field = this.findField(f.name);
			if (field) {
				record.set(f.name, field.getValue());
			}
		},
		this);
		record.endEdit();
		return this;
	},

	loadRecord: function(record) {
		this.setValues(record.data);
		return this;
	},

	beforeAction: function(action) {
		var o = action.options;
		if (o.waitMsg) {
			if (this.waitMsgTarget === true) {
				this.el.mask(o.waitMsg, 'x-mask-loading');
			} else if (this.waitMsgTarget) {
				this.waitMsgTarget = Ext.get(this.waitMsgTarget);
				this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
			} else {
				Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
			}
		}
	},

	afterAction: function(action, success) {
		this.activeAction = null;
		var o = action.options;
		if (o.waitMsg) {
			if (this.waitMsgTarget === true) {
				this.el.unmask();
			} else if (this.waitMsgTarget) {
				this.waitMsgTarget.unmask();
			} else {
				Ext.MessageBox.updateProgress(1);
				Ext.MessageBox.hide();
			}
		}
		if (success) {
			if (o.reset) {
				this.reset();
			}
			Ext.callback(o.success, o.scope, [this, action]);
			this.fireEvent('actioncomplete', this, action);
		} else {
			Ext.callback(o.failure, o.scope, [this, action]);
			this.fireEvent('actionfailed', this, action);
		}
	},

	findField: function(id) {
		var field = this.items.get(id);
		if (!field) {
			this.items.each(function(f) {
				if (f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)) {
					field = f;
					return false;
				}
			});
		}
		return field || null;
	},

	markInvalid: function(errors) {
		if (Ext.isArray(errors)) {
			for (var i = 0, len = errors.length; i < len; i++) {
				var fieldError = errors[i];
				var f = this.findField(fieldError.id);
				if (f) {
					f.markInvalid(fieldError.msg);
				}
			}
		} else {
			var field,
			id;
			for (id in errors) {
				if (typeof errors[id] != 'function' && (field = this.findField(id))) {
					field.markInvalid(errors[id]);
				}
			}
		}
		return this;
	},

	setValues: function(values) {
		if (Ext.isArray(values)) {
			for (var i = 0, len = values.length; i < len; i++) {
				var v = values[i];
				var f = this.findField(v.id);
				if (f) {
					f.setValue(v.value);
					if (this.trackResetOnLoad) {
						f.originalValue = f.getValue();
					}
				}
			}
		} else {
			var field,
			id;
			for (id in values) {
				if (typeof values[id] != 'function' && (field = this.findField(id))) {
					field.setValue(values[id]);
					if (this.trackResetOnLoad) {
						field.originalValue = field.getValue();
					}
				}
			}
		}
		return this;
	},

	getValues: function(asString) {
		var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
		if (asString === true) {
			return fs;
		}
		return Ext.urlDecode(fs);
	},

	clearInvalid: function() {
		this.items.each(function(f) {
			f.clearInvalid();
		});
		return this;
	},

	reset: function() {
		this.items.each(function(f) {
			f.reset();
		});
		return this;
	},

	add: function() {
		this.items.addAll(Array.prototype.slice.call(arguments, 0));
		return this;
	},

	remove: function(field) {
		this.items.remove(field);
		return this;
	},

	render: function() {
		this.items.each(function(f) {
			if (f.isFormField && !f.rendered && document.getElementById(f.id)) {
				f.applyToMarkup(f.id);
			}
		});
		return this;
	},

	applyToFields: function(o) {
		this.items.each(function(f) {
			Ext.apply(f, o);
		});
		return this;
	},

	applyIfToFields: function(o) {
		this.items.each(function(f) {
			Ext.applyIf(f, o);
		});
		return this;
	}
});

Ext.BasicForm = Ext.form.BasicForm;

Ext.FormPanel = Ext.extend(Ext.Panel, {

	buttonAlign: 'center',

	minButtonWidth: 75,

	labelAlign: 'left',

	monitorValid: false,

	monitorPoll: 200,

	layout: 'form',

	initComponent: function() {
		this.form = this.createForm();

		this.bodyCfg = {
			tag: 'form',
			cls: this.baseCls + '-body',
			method: this.method || 'POST',
			id: this.formId || Ext.id()
		};
		if (this.fileUpload) {
			this.bodyCfg.enctype = 'multipart/form-data';
		}

		Ext.FormPanel.superclass.initComponent.call(this);

		this.addEvents(
		'clientvalidation');

		this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
	},

	createForm: function() {
		delete this.initialConfig.listeners;
		return new Ext.form.BasicForm(null, this.initialConfig);
	},

	initFields: function() {
		var f = this.form;
		var formPanel = this;
		var fn = function(c) {
			if (c.isFormField) {
				f.add(c);
			} else if (c.doLayout && c != formPanel) {
				Ext.applyIf(c, {
					labelAlign: c.ownerCt.labelAlign,
					labelWidth: c.ownerCt.labelWidth,
					itemCls: c.ownerCt.itemCls
				});
				if (c.items) {
					c.items.each(fn);
				}
			}
		}
		this.items.each(fn);
	},

	getLayoutTarget: function() {
		return this.form.el;
	},

	getForm: function() {
		return this.form;
	},

	onRender: function(ct, position) {
		this.initFields();

		Ext.FormPanel.superclass.onRender.call(this, ct, position);
		this.form.initEl(this.body);
	},

	beforeDestroy: function() {
		Ext.FormPanel.superclass.beforeDestroy.call(this);
		this.stopMonitoring();
		Ext.destroy(this.form);
	},

	initEvents: function() {
		Ext.FormPanel.superclass.initEvents.call(this);
		this.items.on('remove', this.onRemove, this);
		this.items.on('add', this.onAdd, this);
		if (this.monitorValid) {
			this.startMonitoring();
		}
	},

	onAdd: function(ct, c) {
		if (c.isFormField) {
			this.form.add(c);
		}
	},

	onRemove: function(c) {
		if (c.isFormField) {
			Ext.destroy(c.container.up('.x-form-item'));
			this.form.remove(c);
		}
	},

	startMonitoring: function() {
		if (!this.bound) {
			this.bound = true;
			Ext.TaskMgr.start({
				run: this.bindHandler,
				interval: this.monitorPoll || 200,
				scope: this
			});
		}
	},

	stopMonitoring: function() {
		this.bound = false;
	},

	load: function() {
		this.form.load.apply(this.form, arguments);
	},

	onDisable: function() {
		Ext.FormPanel.superclass.onDisable.call(this);
		if (this.form) {
			this.form.items.each(function() {
				this.disable();
			});
		}
	},

	onEnable: function() {
		Ext.FormPanel.superclass.onEnable.call(this);
		if (this.form) {
			this.form.items.each(function() {
				this.enable();
			});
		}
	},

	bindHandler: function() {
		if (!this.bound) {
			return false;
		}
		var valid = true;
		this.form.items.each(function(f) {
			if (!f.isValid(true)) {
				valid = false;
				return false;
			}
		});
		if (this.buttons) {
			for (var i = 0, len = this.buttons.length; i < len; i++) {
				var btn = this.buttons[i];
				if (btn.formBind === true && btn.disabled === valid) {
					btn.setDisabled(!valid);
				}
			}
		}
		this.fireEvent('clientvalidation', this, valid);
	}
});
Ext.reg('form', Ext.FormPanel);

Ext.form.FormPanel = Ext.FormPanel;

Ext.form.FieldSet = Ext.extend(Ext.Panel, {

	baseCls: 'x-fieldset',

	layout: 'form',

	onRender: function(ct, position) {
		if (!this.el) {
			this.el = document.createElement('fieldset');
			this.el.id = this.id;
			if (this.title || this.header || this.checkboxToggle) {
				this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';
			}
		}

		Ext.form.FieldSet.superclass.onRender.call(this, ct, position);

		if (this.checkboxToggle) {
			var o = typeof this.checkboxToggle == 'object' ? this.checkboxToggle: {
				tag: 'input',
				type: 'checkbox',
				name: this.checkboxName || this.id + '-checkbox'
			};
			this.checkbox = this.header.insertFirst(o);
			this.checkbox.dom.checked = !this.collapsed;
			this.checkbox.on('click', this.onCheckClick, this);
		}
	},

	onCollapse: function(doAnim, animArg) {
		if (this.checkbox) {
			this.checkbox.dom.checked = false;
		}
		this.afterCollapse();

	},

	onExpand: function(doAnim, animArg) {
		if (this.checkbox) {
			this.checkbox.dom.checked = true;
		}
		this.afterExpand();
	},

	onCheckClick: function() {
		this[this.checkbox.dom.checked ? 'expand': 'collapse']();
	}

});
Ext.reg('fieldset', Ext.form.FieldSet);

Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {

	enableFormat: true,

	enableFontSize: true,

	enableColors: true,

	enableAlignments: true,

	enableLists: true,

	enableSourceEdit: true,

	enableLinks: true,

	enableFont: true,

	createLinkText: 'Please enter the URL for the link:',

	defaultLinkValue: 'http:/' + '/',

	fontFamilies: ['Arial', 'Courier New', 'Tahoma', 'Times New Roman', 'Verdana'],
	defaultFont: 'tahoma',

	validationEvent: false,
	deferHeight: true,
	initialized: false,
	activated: false,
	sourceEditMode: false,
	onFocus: Ext.emptyFn,
	iframePad: 3,
	hideMode: 'offsets',
	defaultAutoCreate: {
		tag: "textarea",
		style: "width:500px;height:300px;",
		autocomplete: "off"
	},

	initComponent: function() {
		this.addEvents(
		'initialize',
		'activate',
		'beforesync',
		'beforepush',
		'sync',
		'push',
		'editmodechange')
	},

	createFontOptions: function() {
		var buf = [],
		fs = this.fontFamilies,
		ff,
		lc;
		for (var i = 0, len = fs.length; i < len; i++) {
			ff = fs[i];
			lc = ff.toLowerCase();
			buf.push('<option value="', lc, '" style="font-family:', ff, ';"', (this.defaultFont == lc ? ' selected="true">': '>'), ff, '</option>');
		}
		return buf.join('');
	},

	createToolbar: function(editor) {

		var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();

		function btn(id, toggle, handler) {
			return {
				itemId: id,
				cls: 'x-btn-icon x-edit-' + id,
				enableToggle: toggle !== false,
				scope: editor,
				handler: handler || editor.relayBtnCmd,
				clickEvent: 'mousedown',
				tooltip: tipsEnabled ? editor.buttonTips[id] || undefined: undefined,
				tabIndex: -1
			};
		}

		var tb = new Ext.Toolbar({
			renderTo: this.wrap.dom.firstChild
		});

		tb.el.on('click',
		function(e) {
			e.preventDefault();
		});

		if (this.enableFont && !Ext.isSafari2) {
			this.fontSelect = tb.el.createChild({
				tag: 'select',
				cls: 'x-font-select',
				html: this.createFontOptions()
			});
			this.fontSelect.on('change',
			function() {
				var font = this.fontSelect.dom.value;
				this.relayCmd('fontname', font);
				this.deferFocus();
			},
			this);
			tb.add(this.fontSelect.dom, '-');
		};

		if (this.enableFormat) {
			tb.add(btn('bold'), btn('italic'), btn('underline'));
		};

		if (this.enableFontSize) {
			tb.add('-', btn('increasefontsize', false, this.adjustFont), btn('decreasefontsize', false, this.adjustFont));
		};

		if (this.enableColors) {
			tb.add('-', {
				itemId: 'forecolor',
				cls: 'x-btn-icon x-edit-forecolor',
				clickEvent: 'mousedown',
				tooltip: tipsEnabled ? editor.buttonTips['forecolor'] || undefined: undefined,
				tabIndex: -1,
				menu: new Ext.menu.ColorMenu({
					allowReselect: true,
					focus: Ext.emptyFn,
					value: '000000',
					plain: true,
					selectHandler: function(cp, color) {
						this.execCmd('forecolor', Ext.isSafari || Ext.isIE ? '#' + color: color);
						this.deferFocus();
					},
					scope: this,
					clickEvent: 'mousedown'
				})
			},
			{
				itemId: 'backcolor',
				cls: 'x-btn-icon x-edit-backcolor',
				clickEvent: 'mousedown',
				tooltip: tipsEnabled ? editor.buttonTips['backcolor'] || undefined: undefined,
				tabIndex: -1,
				menu: new Ext.menu.ColorMenu({
					focus: Ext.emptyFn,
					value: 'FFFFFF',
					plain: true,
					allowReselect: true,
					selectHandler: function(cp, color) {
						if (Ext.isGecko) {
							this.execCmd('useCSS', false);
							this.execCmd('hilitecolor', color);
							this.execCmd('useCSS', true);
							this.deferFocus();
						} else {
							this.execCmd(Ext.isOpera ? 'hilitecolor': 'backcolor', Ext.isSafari || Ext.isIE ? '#' + color: color);
							this.deferFocus();
						}
					},
					scope: this,
					clickEvent: 'mousedown'
				})
			});
		};

		if (this.enableAlignments) {
			tb.add('-', btn('justifyleft'), btn('justifycenter'), btn('justifyright'));
		};

		if (!Ext.isSafari2) {
			if (this.enableLinks) {
				tb.add('-', btn('createlink', false, this.createLink));
			};

			if (this.enableLists) {
				tb.add('-', btn('insertorderedlist'), btn('insertunorderedlist'));
			}
			if (this.enableSourceEdit) {
				tb.add('-', btn('sourceedit', true,
				function(btn) {
					this.toggleSourceEdit(btn.pressed);
				}));
			}
		}

		this.tb = tb;
	},

	getDocMarkup: function() {
		return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
	},

	getEditorBody: function() {
		return this.doc.body || this.doc.documentElement;
	},

	getDoc: function() {
		return Ext.isIE ? this.getWin().document: (this.iframe.contentDocument || this.getWin().document);
	},

	getWin: function() {
		return Ext.isIE ? this.iframe.contentWindow: window.frames[this.iframe.name];
	},

	onRender: function(ct, position) {
		Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
		this.el.dom.style.border = '0 none';
		this.el.dom.setAttribute('tabIndex', -1);
		this.el.addClass('x-hidden');
		if (Ext.isIE) {
			this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
		}
		this.wrap = this.el.wrap({
			cls: 'x-html-editor-wrap',
			cn: {
				cls: 'x-html-editor-tb'
			}
		});

		this.createToolbar(this);

		this.tb.items.each(function(item) {
			if (item.itemId != 'sourceedit') {
				item.disable();
			}
		});

		var iframe = document.createElement('iframe');
		iframe.name = Ext.id();
		iframe.frameBorder = '0';

		iframe.src = Ext.isIE ? Ext.SSL_SECURE_URL: "javascript:;";

		this.wrap.dom.appendChild(iframe);

		this.iframe = iframe;

		this.initFrame();

		if (this.autoMonitorDesignMode !== false) {
			this.monitorTask = Ext.TaskMgr.start({
				run: this.checkDesignMode,
				scope: this,
				interval: 100
			});
		}

		if (!this.width) {
			var sz = this.el.getSize();
			this.setSize(sz.width, this.height || sz.height);
		}
	},

	initFrame: function() {
		this.doc = this.getDoc();
		this.win = this.getWin();

		this.doc.open();
		this.doc.write(this.getDocMarkup());
		this.doc.close();

		var task = {
			run: function() {
				if (this.doc.body || this.doc.readyState == 'complete') {
					Ext.TaskMgr.stop(task);
					this.doc.designMode = "on";
					this.initEditor.defer(10, this);
				}
			},
			interval: 10,
			duration: 10000,
			scope: this
		};
		Ext.TaskMgr.start(task);
	},

	checkDesignMode: function() {
		if (this.wrap && this.wrap.dom.offsetWidth) {
			var doc = this.getDoc();
			if (!doc) {
				return;
			}
			if (!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on') {
				this.initFrame();
			}
		}
	},

	onResize: function(w, h) {
		Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
		if (this.el && this.iframe) {
			if (typeof w == 'number') {
				var aw = w - this.wrap.getFrameWidth('lr');
				this.el.setWidth(this.adjustWidth('textarea', aw));
				this.iframe.style.width = aw + 'px';
			}
			if (typeof h == 'number') {
				var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
				this.el.setHeight(this.adjustWidth('textarea', ah));
				this.iframe.style.height = ah + 'px';
				if (this.doc) {
					this.getEditorBody().style.height = (ah - (this.iframePad * 2)) + 'px';
				}
			}
		}
	},

	toggleSourceEdit: function(sourceEditMode) {
		if (sourceEditMode === undefined) {
			sourceEditMode = !this.sourceEditMode;
		}
		this.sourceEditMode = sourceEditMode === true;
		var btn = this.tb.items.get('sourceedit');
		if (btn.pressed !== this.sourceEditMode) {
			btn.toggle(this.sourceEditMode);
			return;
		}
		if (this.sourceEditMode) {
			this.tb.items.each(function(item) {
				if (item.itemId != 'sourceedit') {
					item.disable();
				}
			});
			this.syncValue();
			this.iframe.className = 'x-hidden';
			this.el.removeClass('x-hidden');
			this.el.dom.removeAttribute('tabIndex');
			this.el.focus();
		} else {
			if (this.initialized) {
				this.tb.items.each(function(item) {
					item.enable();
				});
			}
			this.pushValue();
			this.iframe.className = '';
			this.el.addClass('x-hidden');
			this.el.dom.setAttribute('tabIndex', -1);
			this.deferFocus();
		}
		var lastSize = this.lastSize;
		if (lastSize) {
			delete this.lastSize;
			this.setSize(lastSize);
		}
		this.fireEvent('editmodechange', this, this.sourceEditMode);
	},

	createLink: function() {
		var url = prompt(this.createLinkText, this.defaultLinkValue);
		if (url && url != 'http:/' + '/') {
			this.relayCmd('createlink', url);
		}
	},

	adjustSize: Ext.BoxComponent.prototype.adjustSize,

	getResizeEl: function() {
		return this.wrap;
	},

	getPositionEl: function() {
		return this.wrap;
	},

	initEvents: function() {
		this.originalValue = this.getValue();
	},

	markInvalid: Ext.emptyFn,

	clearInvalid: Ext.emptyFn,

	setValue: function(v) {
		Ext.form.HtmlEditor.superclass.setValue.call(this, v);
		this.pushValue();
	},

	cleanHtml: function(html) {
		html = String(html);
		if (html.length > 5) {
			if (Ext.isSafari) {
				html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
			}
		}
		if (html == '&nbsp;') {
			html = '';
		}
		return html;
	},

	syncValue: function() {
		if (this.initialized) {
			var bd = this.getEditorBody();
			var html = bd.innerHTML;
			if (Ext.isSafari) {
				var bs = bd.getAttribute('style');
				var m = bs.match(/text-align:(.*?);/i);
				if (m && m[1]) {
					html = '<div style="' + m[0] + '">' + html + '</div>';
				}
			}
			html = this.cleanHtml(html);
			if (this.fireEvent('beforesync', this, html) !== false) {
				this.el.dom.value = html;
				this.fireEvent('sync', this, html);
			}
		}
	},

	pushValue: function() {
		if (this.initialized) {
			var v = this.el.dom.value;
			if (!this.activated && v.length < 1) {
				v = '&nbsp;';
			}
			if (this.fireEvent('beforepush', this, v) !== false) {
				this.getEditorBody().innerHTML = v;
				this.fireEvent('push', this, v);
			}
		}
	},

	deferFocus: function() {
		this.focus.defer(10, this);
	},

	focus: function() {
		if (this.win && !this.sourceEditMode) {
			this.win.focus();
		} else {
			this.el.focus();
		}
	},

	initEditor: function() {
		var dbody = this.getEditorBody();
		var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
		ss['background-attachment'] = 'fixed';
		dbody.bgProperties = 'fixed';

		Ext.DomHelper.applyStyles(dbody, ss);

		if (this.doc) {
			try {
				Ext.EventManager.removeAll(this.doc);
			} catch(e) {}
		}

		this.doc = this.getDoc();

		Ext.EventManager.on(this.doc, {
			'mousedown': this.onEditorEvent,
			'dblclick': this.onEditorEvent,
			'click': this.onEditorEvent,
			'keyup': this.onEditorEvent,
			buffer: 100,
			scope: this
		});

		if (Ext.isGecko) {
			Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
		}
		if (Ext.isIE || Ext.isSafari || Ext.isOpera) {
			Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
		}
		this.initialized = true;

		this.fireEvent('initialize', this);

		this.doc.editorInitialized = true;

		this.pushValue();
	},

	onDestroy: function() {
		if (this.monitorTask) {
			Ext.TaskMgr.stop(this.monitorTask);
		}
		if (this.rendered) {
			this.tb.items.each(function(item) {
				if (item.menu) {
					item.menu.removeAll();
					if (item.menu.el) {
						item.menu.el.destroy();
					}
				}
				item.destroy();
			});
			this.wrap.dom.innerHTML = '';
			this.wrap.remove();
		}
	},

	onFirstFocus: function() {
		this.activated = true;
		this.tb.items.each(function(item) {
			item.enable();
		});
		if (Ext.isGecko) {
			this.win.focus();
			var s = this.win.getSelection();
			if (!s.focusNode || s.focusNode.nodeType != 3) {
				var r = s.getRangeAt(0);
				r.selectNodeContents(this.getEditorBody());
				r.collapse(true);
				this.deferFocus();
			}
			try {
				this.execCmd('useCSS', true);
				this.execCmd('styleWithCSS', false);
			} catch(e) {}
		}
		this.fireEvent('activate', this);
	},

	adjustFont: function(btn) {
		var adjust = btn.itemId == 'increasefontsize' ? 1: -1;

		var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);
		if (Ext.isSafari3 || Ext.isAir) {

			if (v <= 10) {
				v = 1 + adjust;
			} else if (v <= 13) {
				v = 2 + adjust;
			} else if (v <= 16) {
				v = 3 + adjust;
			} else if (v <= 18) {
				v = 4 + adjust;
			} else if (v <= 24) {
				v = 5 + adjust;
			} else {
				v = 6 + adjust;
			}
			v = v.constrain(1, 6);
		} else {
			if (Ext.isSafari) {
				adjust *= 2;
			}
			v = Math.max(1, v + adjust) + (Ext.isSafari ? 'px': 0);
		}
		this.execCmd('FontSize', v);
	},

	onEditorEvent: function(e) {
		this.updateToolbar();
	},

	updateToolbar: function() {

		if (!this.activated) {
			this.onFirstFocus();
			return;
		}

		var btns = this.tb.items.map,
		doc = this.doc;

		if (this.enableFont && !Ext.isSafari2) {
			var name = (this.doc.queryCommandValue('FontName') || this.defaultFont).toLowerCase();
			if (name != this.fontSelect.dom.value) {
				this.fontSelect.dom.value = name;
			}
		}
		if (this.enableFormat) {
			btns.bold.toggle(doc.queryCommandState('bold'));
			btns.italic.toggle(doc.queryCommandState('italic'));
			btns.underline.toggle(doc.queryCommandState('underline'));
		}
		if (this.enableAlignments) {
			btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
			btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
			btns.justifyright.toggle(doc.queryCommandState('justifyright'));
		}
		if (!Ext.isSafari2 && this.enableLists) {
			btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
			btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
		}

		Ext.menu.MenuMgr.hideAll();

		this.syncValue();
	},

	relayBtnCmd: function(btn) {
		this.relayCmd(btn.itemId);
	},

	relayCmd: function(cmd, value) { (function() {
			this.focus();
			this.execCmd(cmd, value);
			this.updateToolbar();
		}).defer(10, this);
	},

	execCmd: function(cmd, value) {
		this.doc.execCommand(cmd, false, value === undefined ? null: value);
		this.syncValue();
	},

	applyCommand: function(e) {
		if (e.ctrlKey) {
			var c = e.getCharCode(),
			cmd;
			if (c > 0) {
				c = String.fromCharCode(c);
				switch (c) {
				case 'b':
					cmd = 'bold';
					break;
				case 'i':
					cmd = 'italic';
					break;
				case 'u':
					cmd = 'underline';
					break;
				}
				if (cmd) {
					this.win.focus();
					this.execCmd(cmd);
					this.deferFocus();
					e.preventDefault();
				}
			}
		}
	},

	insertAtCursor: function(text) {
		if (!this.activated) {
			return;
		}
		if (Ext.isIE) {
			this.win.focus();
			var r = this.doc.selection.createRange();
			if (r) {
				r.collapse(true);
				r.pasteHTML(text);
				this.syncValue();
				this.deferFocus();
			}
		} else if (Ext.isGecko || Ext.isOpera) {
			this.win.focus();
			this.execCmd('InsertHTML', text);
			this.deferFocus();
		} else if (Ext.isSafari) {
			this.execCmd('InsertText', text);
			this.deferFocus();
		}
	},

	fixKeys: function() {
		if (Ext.isIE) {
			return function(e) {
				var k = e.getKey(),
				r;
				if (k == e.TAB) {
					e.stopEvent();
					r = this.doc.selection.createRange();
					if (r) {
						r.collapse(true);
						r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
						this.deferFocus();
					}
				} else if (k == e.ENTER) {
					r = this.doc.selection.createRange();
					if (r) {
						var target = r.parentElement();
						if (!target || target.tagName.toLowerCase() != 'li') {
							e.stopEvent();
							r.pasteHTML('<br />');
							r.collapse(false);
							r.select();
						}
					}
				}
			};
		} else if (Ext.isOpera) {
			return function(e) {
				var k = e.getKey();
				if (k == e.TAB) {
					e.stopEvent();
					this.win.focus();
					this.execCmd('InsertHTML', '&nbsp;&nbsp;&nbsp;&nbsp;');
					this.deferFocus();
				}
			};
		} else if (Ext.isSafari) {
			return function(e) {
				var k = e.getKey();
				if (k == e.TAB) {
					e.stopEvent();
					this.execCmd('InsertText', '\t');
					this.deferFocus();
				}
			};
		}
	} (),

	getToolbar: function() {
		return this.tb;
	},

	buttonTips: {
		bold: {
			title: 'Bold (Ctrl+B)',
			text: 'Make the selected text bold.',
			cls: 'x-html-editor-tip'
		},
		italic: {
			title: 'Italic (Ctrl+I)',
			text: 'Make the selected text italic.',
			cls: 'x-html-editor-tip'
		},
		underline: {
			title: 'Underline (Ctrl+U)',
			text: 'Underline the selected text.',
			cls: 'x-html-editor-tip'
		},
		increasefontsize: {
			title: 'Grow Text',
			text: 'Increase the font size.',
			cls: 'x-html-editor-tip'
		},
		decreasefontsize: {
			title: 'Shrink Text',
			text: 'Decrease the font size.',
			cls: 'x-html-editor-tip'
		},
		backcolor: {
			title: 'Text Highlight Color',
			text: 'Change the background color of the selected text.',
			cls: 'x-html-editor-tip'
		},
		forecolor: {
			title: 'Font Color',
			text: 'Change the color of the selected text.',
			cls: 'x-html-editor-tip'
		},
		justifyleft: {
			title: 'Align Text Left',
			text: 'Align text to the left.',
			cls: 'x-html-editor-tip'
		},
		justifycenter: {
			title: 'Center Text',
			text: 'Center text in the editor.',
			cls: 'x-html-editor-tip'
		},
		justifyright: {
			title: 'Align Text Right',
			text: 'Align text to the right.',
			cls: 'x-html-editor-tip'
		},
		insertunorderedlist: {
			title: 'Bullet List',
			text: 'Start a bulleted list.',
			cls: 'x-html-editor-tip'
		},
		insertorderedlist: {
			title: 'Numbered List',
			text: 'Start a numbered list.',
			cls: 'x-html-editor-tip'
		},
		createlink: {
			title: 'Hyperlink',
			text: 'Make the selected text a hyperlink.',
			cls: 'x-html-editor-tip'
		},
		sourceedit: {
			title: 'Source Edit',
			text: 'Switch to source editing mode.',
			cls: 'x-html-editor-tip'
		}
	}

});
Ext.reg('htmleditor', Ext.form.HtmlEditor);

Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {

	minValue: null,

	maxValue: null,

	minText: "The time in this field must be equal to or after {0}",

	maxText: "The time in this field must be equal to or before {0}",

	invalidText: "{0} is not a valid time",

	format: "g:i A",

	altFormats: "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H",

	increment: 15,

	mode: 'local',

	triggerAction: 'all',

	typeAhead: false,

	initDate: '1/1/2008',

	initComponent: function() {
		Ext.form.TimeField.superclass.initComponent.call(this);

		if (typeof this.minValue == "string") {
			this.minValue = this.parseDate(this.minValue);
		}
		if (typeof this.maxValue == "string") {
			this.maxValue = this.parseDate(this.maxValue);
		}

		if (!this.store) {
			var min = this.parseDate(this.minValue);
			if (!min) {
				min = new Date(this.initDate).clearTime();
			}
			var max = this.parseDate(this.maxValue);
			if (!max) {
				max = new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1);
			}
			var times = [];
			while (min <= max) {
				times.push([min.dateFormat(this.format)]);
				min = min.add('mi', this.increment);
			}
			this.store = new Ext.data.SimpleStore({
				fields: ['text'],
				data: times
			});
			this.displayField = 'text';
		}
	},

	getValue: function() {
		var v = Ext.form.TimeField.superclass.getValue.call(this);
		return this.formatDate(this.parseDate(v)) || '';
	},

	setValue: function(value) {
		Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
	},

	validateValue: Ext.form.DateField.prototype.validateValue,
	parseDate: Ext.form.DateField.prototype.parseDate,
	formatDate: Ext.form.DateField.prototype.formatDate,

	beforeBlur: function() {
		var v = this.parseDate(this.getRawValue());
		if (v) {
			this.setValue(v.dateFormat(this.format));
		}
	}

});
Ext.reg('timefield', Ext.form.TimeField);

Ext.form.Label = Ext.extend(Ext.BoxComponent, {

	onRender: function(ct, position) {
		if (!this.el) {
			this.el = document.createElement('label');
			this.el.id = this.getId();
			this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
			if (this.forId) {
				this.el.setAttribute('htmlFor', this.forId);
			}
		}
		Ext.form.Label.superclass.onRender.call(this, ct, position);
	},

	setText: function(t, encode) {
		this.text = t;
		if (this.rendered) {
			this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
		}
		return this;
	}
});

Ext.reg('label', Ext.form.Label);

Ext.form.Action = function(form, options) {
	this.form = form;
	this.options = options || {};
};

Ext.form.Action.CLIENT_INVALID = 'client';

Ext.form.Action.SERVER_INVALID = 'server';

Ext.form.Action.CONNECT_FAILURE = 'connect';

Ext.form.Action.LOAD_FAILURE = 'load';

Ext.form.Action.prototype = {

	type: 'default',

	run: function(options) {
		},

	success: function(response) {
		},

	handleResponse: function(response) {
		},

	failure: function(response) {
		this.response = response;
		this.failureType = Ext.form.Action.CONNECT_FAILURE;
		this.form.afterAction(this, false);
	},

	processResponse: function(response) {
		this.response = response;
		if (!response.responseText) {
			return true;
		}
		this.result = this.handleResponse(response);
		return this.result;
	},

	getUrl: function(appendParams) {
		var url = this.options.url || this.form.url || this.form.el.dom.action;
		if (appendParams) {
			var p = this.getParams();
			if (p) {
				url += (url.indexOf('?') != -1 ? '&': '?') + p;
			}
		}
		return url;
	},

	getMethod: function() {
		return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
	},

	getParams: function() {
		var bp = this.form.baseParams;
		var p = this.options.params;
		if (p) {
			if (typeof p == "object") {
				p = Ext.urlEncode(Ext.applyIf(p, bp));
			} else if (typeof p == 'string' && bp) {
				p += '&' + Ext.urlEncode(bp);
			}
		} else if (bp) {
			p = Ext.urlEncode(bp);
		}
		return p;
	},

	createCallback: function(opts) {
		var opts = opts || {};
		return {
			success: this.success,
			failure: this.failure,
			scope: this,
			timeout: (opts.timeout * 1000) || (this.form.timeout * 1000),
			upload: this.form.fileUpload ? this.success: undefined
		};
	}
};

Ext.form.Action.Submit = function(form, options) {
	Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
};

Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {

	type: 'submit',

	run: function() {
		var o = this.options;
		var method = this.getMethod();
		var isGet = method == 'GET';
		if (o.clientValidation === false || this.form.isValid()) {
			Ext.Ajax.request(Ext.apply(this.createCallback(o), {
				form: this.form.el.dom,
				url: this.getUrl(isGet),
				method: method,
				headers: o.headers,
				params: !isGet ? this.getParams() : null,
				isUpload: this.form.fileUpload
			}));
		} else if (o.clientValidation !== false) {
			this.failureType = Ext.form.Action.CLIENT_INVALID;
			this.form.afterAction(this, false);
		}
	},

	success: function(response) {
		var result = this.processResponse(response);
		if (result === true || result.success) {
			this.form.afterAction(this, true);
			return;
		}
		if (result.errors) {
			this.form.markInvalid(result.errors);
			this.failureType = Ext.form.Action.SERVER_INVALID;
		}
		this.form.afterAction(this, false);
	},

	handleResponse: function(response) {
		if (this.form.errorReader) {
			var rs = this.form.errorReader.read(response);
			var errors = [];
			if (rs.records) {
				for (var i = 0, len = rs.records.length; i < len; i++) {
					var r = rs.records[i];
					errors[i] = r.data;
				}
			}
			if (errors.length < 1) {
				errors = null;
			}
			return {
				success: rs.success,
				errors: errors
			};
		}
		return Ext.decode(response.responseText);
	}
});

Ext.form.Action.Load = function(form, options) {
	Ext.form.Action.Load.superclass.constructor.call(this, form, options);
	this.reader = this.form.reader;
};

Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
	type: 'load',

	run: function() {
		Ext.Ajax.request(Ext.apply(this.createCallback(this.options), {
			method: this.getMethod(),
			url: this.getUrl(false),
			headers: this.options.headers,
			params: this.getParams()
		}));
	},

	success: function(response) {
		var result = this.processResponse(response);
		if (result === true || !result.success || !result.data) {
			this.failureType = Ext.form.Action.LOAD_FAILURE;
			this.form.afterAction(this, false);
			return;
		}
		this.form.clearInvalid();
		this.form.setValues(result.data);
		this.form.afterAction(this, true);
	},

	handleResponse: function(response) {
		if (this.form.reader) {
			var rs = this.form.reader.read(response);
			var data = rs.records && rs.records[0] ? rs.records[0].data: null;
			return {
				success: rs.success,
				data: data
			};
		}
		return Ext.decode(response.responseText);
	}
});

Ext.form.Action.ACTION_TYPES = {
	'load': Ext.form.Action.Load,
	'submit': Ext.form.Action.Submit
};

Ext.form.VTypes = function() {
	var alpha = /^[a-zA-Z_]+$/;
	var alphanum = /^[a-zA-Z0-9_]+$/;
	var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
	var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;

	return {

		'email': function(v) {
			return email.test(v);
		},

		'emailText': 'This field should be an e-mail address in the format "user@domain.com"',

		'emailMask': /[a-z0-9_\.\-@]/i,

		'url': function(v) {
			return url.test(v);
		},

		'urlText': 'This field should be a URL in the format "http:/' + '/www.domain.com"',

		'alpha': function(v) {
			return alpha.test(v);
		},

		'alphaText': 'This field should only contain letters and _',

		'alphaMask': /[a-z_]/i,

		'alphanum': function(v) {
			return alphanum.test(v);
		},

		'alphanumText': 'This field should only contain letters, numbers and _',

		'alphanumMask': /[a-z0-9_]/i
	};
} ();

Ext.grid.GridPanel = Ext.extend(Ext.Panel, {

	ddText: "{0} selected row{1}",

	minColumnWidth: 25,

	trackMouseOver: true,

	enableDragDrop: false,

	enableColumnMove: true,

	enableColumnHide: true,

	enableHdMenu: true,

	stripeRows: false,

	autoExpandColumn: false,

	autoExpandMin: 50,

	autoExpandMax: 1000,

	view: null,

	loadMask: false,

	deferRowRender: true,

	rendered: false,

	viewReady: false,

	stateEvents: ["columnmove", "columnresize", "sortchange"],

	initComponent: function() {
		Ext.grid.GridPanel.superclass.initComponent.call(this);

		this.autoScroll = false;
		this.autoWidth = false;

		if (Ext.isArray(this.columns)) {
			this.colModel = new Ext.grid.ColumnModel(this.columns);
			delete this.columns;
		}

		if (this.ds) {
			this.store = this.ds;
			delete this.ds;
		}
		if (this.cm) {
			this.colModel = this.cm;
			delete this.cm;
		}
		if (this.sm) {
			this.selModel = this.sm;
			delete this.sm;
		}
		this.store = Ext.StoreMgr.lookup(this.store);

		this.addEvents(
		"click",
		"dblclick",
		"contextmenu",
		"mousedown",
		"mouseup",
		"mouseover",
		"mouseout",
		"keypress",
		"keydown",
		"cellmousedown",
		"rowmousedown",
		"headermousedown",
		"cellclick",
		"celldblclick",
		"rowclick",
		"rowdblclick",
		"headerclick",
		"headerdblclick",
		"rowcontextmenu",
		"cellcontextmenu",
		"headercontextmenu",
		"bodyscroll",
		"columnresize",
		"columnmove",
		"sortchange");
	},

	onRender: function(ct, position) {
		Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);

		var c = this.body;

		this.el.addClass('x-grid-panel');

		var view = this.getView();
		view.init(this);

		c.on("mousedown", this.onMouseDown, this);
		c.on("click", this.onClick, this);
		c.on("dblclick", this.onDblClick, this);
		c.on("contextmenu", this.onContextMenu, this);
		c.on("keydown", this.onKeyDown, this);

		this.relayEvents(c, ["mousedown", "mouseup", "mouseover", "mouseout", "keypress"]);

		this.getSelectionModel().init(this);
		this.view.render();
	},

	initEvents: function() {
		Ext.grid.GridPanel.superclass.initEvents.call(this);

		if (this.loadMask) {
			this.loadMask = new Ext.LoadMask(this.bwrap, Ext.apply({
				store: this.store
			},
			this.loadMask));
		}
	},

	initStateEvents: function() {
		Ext.grid.GridPanel.superclass.initStateEvents.call(this);
		this.colModel.on('hiddenchange', this.saveState, this, {
			delay: 100
		});
	},

	applyState: function(state) {
		var cm = this.colModel;
		var cs = state.columns;
		if (cs) {
			for (var i = 0, len = cs.length; i < len; i++) {
				var s = cs[i];
				var c = cm.getColumnById(s.id);
				if (c) {
					c.hidden = s.hidden;
					c.width = s.width;
					var oldIndex = cm.getIndexById(s.id);
					if (oldIndex != i) {
						cm.moveColumn(oldIndex, i);
					}
				}
			}
		}
		if (state.sort) {
			this.store[this.store.remoteSort ? 'setDefaultSort': 'sort'](state.sort.field, state.sort.direction);
		}
	},

	getState: function() {
		var o = {
			columns: []
		};
		for (var i = 0, c; c = this.colModel.config[i]; i++) {
			o.columns[i] = {
				id: c.id,
				width: c.width
			};
			if (c.hidden) {
				o.columns[i].hidden = true;
			}
		}
		var ss = this.store.getSortState();
		if (ss) {
			o.sort = ss;
		}
		return o;
	},

	afterRender: function() {
		Ext.grid.GridPanel.superclass.afterRender.call(this);
		this.view.layout();
		if (this.deferRowRender) {
			this.view.afterRender.defer(10, this.view);
		} else {
			this.view.afterRender();
		}
		this.viewReady = true;
	},

	reconfigure: function(store, colModel) {
		if (this.loadMask) {
			this.loadMask.destroy();
			this.loadMask = new Ext.LoadMask(this.bwrap, Ext.apply({
				store: store
			},
			this.initialConfig.loadMask));
		}
		this.view.bind(store, colModel);
		this.store = store;
		this.colModel = colModel;
		if (this.rendered) {
			this.view.refresh(true);
		}
	},

	onKeyDown: function(e) {
		this.fireEvent("keydown", e);
	},

	onDestroy: function() {
		if (this.rendered) {
			if (this.loadMask) {
				this.loadMask.destroy();
			}
			var c = this.body;
			c.removeAllListeners();
			this.view.destroy();
			c.update("");
		}
		this.colModel.purgeListeners();
		Ext.grid.GridPanel.superclass.onDestroy.call(this);
	},

	processEvent: function(name, e) {
		this.fireEvent(name, e);
		var t = e.getTarget();
		var v = this.view;
		var header = v.findHeaderIndex(t);
		if (header !== false) {
			this.fireEvent("header" + name, this, header, e);
		} else {
			var row = v.findRowIndex(t);
			var cell = v.findCellIndex(t);
			if (row !== false) {
				this.fireEvent("row" + name, this, row, e);
				if (cell !== false) {
					this.fireEvent("cell" + name, this, row, cell, e);
				}
			}
		}
	},

	onClick: function(e) {
		this.processEvent("click", e);
	},

	onMouseDown: function(e) {
		this.processEvent("mousedown", e);
	},

	onContextMenu: function(e, t) {
		this.processEvent("contextmenu", e);
	},

	onDblClick: function(e) {
		this.processEvent("dblclick", e);
	},

	walkCells: function(row, col, step, fn, scope) {
		var cm = this.colModel,
		clen = cm.getColumnCount();
		var ds = this.store,
		rlen = ds.getCount(),
		first = true;
		if (step < 0) {
			if (col < 0) {
				row--;
				first = false;
			}
			while (row >= 0) {
				if (!first) {
					col = clen - 1;
				}
				first = false;
				while (col >= 0) {
					if (fn.call(scope || this, row, col, cm) === true) {
						return [row, col];
					}
					col--;
				}
				row--;
			}
		} else {
			if (col >= clen) {
				row++;
				first = false;
			}
			while (row < rlen) {
				if (!first) {
					col = 0;
				}
				first = false;
				while (col < clen) {
					if (fn.call(scope || this, row, col, cm) === true) {
						return [row, col];
					}
					col++;
				}
				row++;
			}
		}
		return null;
	},

	getSelections: function() {
		return this.selModel.getSelections();
	},

	onResize: function() {
		Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);
		if (this.viewReady) {
			this.view.layout();
		}
	},

	getGridEl: function() {
		return this.body;
	},

	stopEditing: function() {},

	getSelectionModel: function() {
		if (!this.selModel) {
			this.selModel = new Ext.grid.RowSelectionModel(this.disableSelection ? {
				selectRow: Ext.emptyFn
			}: null);
		}
		return this.selModel;
	},

	getStore: function() {
		return this.store;
	},

	getColumnModel: function() {
		return this.colModel;
	},

	getView: function() {
		if (!this.view) {
			this.view = new Ext.grid.GridView(this.viewConfig);
		}
		return this.view;
	},

	getDragDropText: function() {
		var count = this.selModel.getCount();
		return String.format(this.ddText, count, count == 1 ? '': 's');
	}

});
Ext.reg('grid', Ext.grid.GridPanel);

Ext.grid.GridView = function(config) {
	Ext.apply(this, config);
	this.addEvents(
	"beforerowremoved",
	"beforerowsinserted",
	"beforerefresh",
	"rowremoved",
	"rowsinserted",
	"rowupdated",
	"refresh");
	Ext.grid.GridView.superclass.constructor.call(this);
};

Ext.extend(Ext.grid.GridView, Ext.util.Observable, {

	deferEmptyText: true,

	scrollOffset: 19,

	autoFill: false,

	forceFit: false,

	sortClasses: ["sort-asc", "sort-desc"],

	sortAscText: "Sort Ascending",

	sortDescText: "Sort Descending",

	columnsText: "Columns",

	borderWidth: 2,
	tdClass: 'x-grid3-cell',
	hdCls: 'x-grid3-hd',

	cellSelectorDepth: 4,

	rowSelectorDepth: 10,

	cellSelector: 'td.x-grid3-cell',

	rowSelector: 'div.x-grid3-row',

	initTemplates: function() {
		var ts = this.templates || {};
		if (!ts.master) {
			ts.master = new Ext.Template('<div class="x-grid3" hidefocus="true">', '<div class="x-grid3-viewport">', '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{header}</div></div><div class="x-clear"></div></div>', '<div class="x-grid3-scroller"><div class="x-grid3-body">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>', "</div>", '<div class="x-grid3-resize-marker">&#160;</div>', '<div class="x-grid3-resize-proxy">&#160;</div>', "</div>");
		}

		if (!ts.header) {
			ts.header = new Ext.Template('<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>', "</table>");
		}

		if (!ts.hcell) {
			ts.hcell = new Ext.Template('<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>': '', '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />', "</div></td>");
		}

		if (!ts.body) {
			ts.body = new Ext.Template('{rows}');
		}

		if (!ts.row) {
			ts.row = new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', '<tbody><tr>{cells}</tr>', (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>': ''), '</tbody></table></div>');
		}

		if (!ts.cell) {
			ts.cell = new Ext.Template('<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>', '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>', "</td>");
		}

		for (var k in ts) {
			var t = ts[k];
			if (t && typeof t.compile == 'function' && !t.compiled) {
				t.disableFormats = true;
				t.compile();
			}
		}

		this.templates = ts;
		this.colRe = new RegExp("x-grid3-td-([^\\s]+)", "");
	},

	fly: function(el) {
		if (!this._flyweight) {
			this._flyweight = new Ext.Element.Flyweight(document.body);
		}
		this._flyweight.dom = el;
		return this._flyweight;
	},

	getEditorParent: function(ed) {
		return this.scroller.dom;
	},

	initElements: function() {
		var E = Ext.Element;

		var el = this.grid.getGridEl().dom.firstChild;
		var cs = el.childNodes;

		this.el = new E(el);

		this.mainWrap = new E(cs[0]);
		this.mainHd = new E(this.mainWrap.dom.firstChild);

		if (this.grid.hideHeaders) {
			this.mainHd.setDisplayed(false);
		}

		this.innerHd = this.mainHd.dom.firstChild;
		this.scroller = new E(this.mainWrap.dom.childNodes[1]);
		if (this.forceFit) {
			this.scroller.setStyle('overflow-x', 'hidden');
		}
		this.mainBody = new E(this.scroller.dom.firstChild);

		this.focusEl = new E(this.scroller.dom.childNodes[1]);
		this.focusEl.swallowEvent("click", true);

		this.resizeMarker = new E(cs[1]);
		this.resizeProxy = new E(cs[2]);
	},

	getRows: function() {
		return this.hasRows() ? this.mainBody.dom.childNodes: [];
	},

	findCell: function(el) {
		if (!el) {
			return false;
		}
		return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
	},

	findCellIndex: function(el, requiredCls) {
		var cell = this.findCell(el);
		if (cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))) {
			return this.getCellIndex(cell);
		}
		return false;
	},

	getCellIndex: function(el) {
		if (el) {
			var m = el.className.match(this.colRe);
			if (m && m[1]) {
				return this.cm.getIndexById(m[1]);
			}
		}
		return false;
	},

	findHeaderCell: function(el) {
		var cell = this.findCell(el);
		return cell && this.fly(cell).hasClass(this.hdCls) ? cell: null;
	},

	findHeaderIndex: function(el) {
		return this.findCellIndex(el, this.hdCls);
	},

	findRow: function(el) {
		if (!el) {
			return false;
		}
		return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
	},

	findRowIndex: function(el) {
		var r = this.findRow(el);
		return r ? r.rowIndex: false;
	},

	getRow: function(row) {
		return this.getRows()[row];
	},

	getCell: function(row, col) {
		return this.getRow(row).getElementsByTagName('td')[col];
	},

	getHeaderCell: function(index) {
		return this.mainHd.dom.getElementsByTagName('td')[index];
	},

	addRowClass: function(row, cls) {
		var r = this.getRow(row);
		if (r) {
			this.fly(r).addClass(cls);
		}
	},

	removeRowClass: function(row, cls) {
		var r = this.getRow(row);
		if (r) {
			this.fly(r).removeClass(cls);
		}
	},

	removeRow: function(row) {
		Ext.removeNode(this.getRow(row));
		this.focusRow(row);
	},

	removeRows: function(firstRow, lastRow) {
		var bd = this.mainBody.dom;
		for (var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
			Ext.removeNode(bd.childNodes[firstRow]);
		}
		this.focusRow(firstRow);
	},

	getScrollState: function() {
		var sb = this.scroller.dom;
		return {
			left: sb.scrollLeft,
			top: sb.scrollTop
		};
	},

	restoreScroll: function(state) {
		var sb = this.scroller.dom;
		sb.scrollLeft = state.left;
		sb.scrollTop = state.top;
	},

	scrollToTop: function() {
		this.scroller.dom.scrollTop = 0;
		this.scroller.dom.scrollLeft = 0;
	},

	syncScroll: function() {
		this.syncHeaderScroll();
		var mb = this.scroller.dom;
		this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);
	},

	syncHeaderScroll: function() {
		var mb = this.scroller.dom;
		this.innerHd.scrollLeft = mb.scrollLeft;
		this.innerHd.scrollLeft = mb.scrollLeft;
	},

	updateSortIcon: function(col, dir) {
		var sc = this.sortClasses;
		var hds = this.mainHd.select('td').removeClass(sc);
		hds.item(col).addClass(sc[dir == "DESC" ? 1: 0]);
	},

	updateAllColumnWidths: function() {
		var tw = this.getTotalWidth();
		var clen = this.cm.getColumnCount();
		var ws = [];
		for (var i = 0; i < clen; i++) {
			ws[i] = this.getColumnWidth(i);
		}

		this.innerHd.firstChild.firstChild.style.width = tw;

		for (var i = 0; i < clen; i++) {
			var hd = this.getHeaderCell(i);
			hd.style.width = ws[i];
		}

		var ns = this.getRows();
		for (var i = 0, len = ns.length; i < len; i++) {
			ns[i].style.width = tw;
			ns[i].firstChild.style.width = tw;
			var row = ns[i].firstChild.rows[0];
			for (var j = 0; j < clen; j++) {
				row.childNodes[j].style.width = ws[j];
			}
		}

		this.onAllColumnWidthsUpdated(ws, tw);
	},

	updateColumnWidth: function(col, width) {
		var w = this.getColumnWidth(col);
		var tw = this.getTotalWidth();

		this.innerHd.firstChild.firstChild.style.width = tw;
		var hd = this.getHeaderCell(col);
		hd.style.width = w;

		var ns = this.getRows();
		for (var i = 0, len = ns.length; i < len; i++) {
			ns[i].style.width = tw;
			ns[i].firstChild.style.width = tw;
			ns[i].firstChild.rows[0].childNodes[col].style.width = w;
		}

		this.onColumnWidthUpdated(col, w, tw);
	},

	updateColumnHidden: function(col, hidden) {
		var tw = this.getTotalWidth();

		this.innerHd.firstChild.firstChild.style.width = tw;

		var display = hidden ? 'none': '';

		var hd = this.getHeaderCell(col);
		hd.style.display = display;

		var ns = this.getRows();
		for (var i = 0, len = ns.length; i < len; i++) {
			ns[i].style.width = tw;
			ns[i].firstChild.style.width = tw;
			ns[i].firstChild.rows[0].childNodes[col].style.display = display;
		}

		this.onColumnHiddenUpdated(col, hidden, tw);

		delete this.lastViewWidth;
		this.layout();
	},

	doRender: function(cs, rs, ds, startRow, colCount, stripe) {
		var ts = this.templates,
		ct = ts.cell,
		rt = ts.row,
		last = colCount - 1;
		var tstyle = 'width:' + this.getTotalWidth() + ';';
		var buf = [],
		cb,
		c,
		p = {},
		rp = {
			tstyle: tstyle
		},
		r;
		for (var j = 0, len = rs.length; j < len; j++) {
			r = rs[j];
			cb = [];
			var rowIndex = (j + startRow);
			for (var i = 0; i < colCount; i++) {
				c = cs[i];
				p.id = c.id;
				p.css = i == 0 ? 'x-grid3-cell-first ': (i == last ? 'x-grid3-cell-last ': '');
				p.attr = p.cellAttr = "";
				p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
				p.style = c.style;
				if (p.value == undefined || p.value === "") p.value = "&#160;";
				if (r.dirty && typeof r.modified[c.name] !== 'undefined') {
					p.css += ' x-grid3-dirty-cell';
				}
				cb[cb.length] = ct.apply(p);
			}
			var alt = [];
			if (stripe && ((rowIndex + 1) % 2 == 0)) {
				alt[0] = "x-grid3-row-alt";
			}
			if (r.dirty) {
				alt[1] = " x-grid3-dirty-row";
			}
			rp.cols = colCount;
			if (this.getRowClass) {
				alt[2] = this.getRowClass(r, rowIndex, rp, ds);
			}
			rp.alt = alt.join(" ");
			rp.cells = cb.join("");
			buf[buf.length] = rt.apply(rp);
		}
		return buf.join("");
	},

	processRows: function(startRow, skipStripe) {
		if (this.ds.getCount() < 1) {
			return;
		}
		skipStripe = skipStripe || !this.grid.stripeRows;
		startRow = startRow || 0;
		var rows = this.getRows();
		var cls = ' x-grid3-row-alt ';
		for (var i = startRow, len = rows.length; i < len; i++) {
			var row = rows[i];
			row.rowIndex = i;
			if (!skipStripe) {
				var isAlt = ((i + 1) % 2 == 0);
				var hasAlt = (' ' + row.className + ' ').indexOf(cls) != -1;
				if (isAlt == hasAlt) {
					continue;
				}
				if (isAlt) {
					row.className += " x-grid3-row-alt";
				} else {
					row.className = row.className.replace("x-grid3-row-alt", "");
				}
			}
		}
	},

	afterRender: function() {
		this.mainBody.dom.innerHTML = this.renderRows();
		this.processRows(0, true);

		if (this.deferEmptyText !== true) {
			this.applyEmptyText();
		}
	},

	renderUI: function() {

		var header = this.renderHeaders();
		var body = this.templates.body.apply({
			rows: ''
		});

		var html = this.templates.master.apply({
			body: body,
			header: header
		});

		var g = this.grid;

		g.getGridEl().dom.innerHTML = html;

		this.initElements();

		Ext.fly(this.innerHd).on("click", this.handleHdDown, this);
		this.mainHd.on("mouseover", this.handleHdOver, this);
		this.mainHd.on("mouseout", this.handleHdOut, this);
		this.mainHd.on("mousemove", this.handleHdMove, this);

		this.scroller.on('scroll', this.syncScroll, this);
		if (g.enableColumnResize !== false) {
			this.splitone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
		}

		if (g.enableColumnMove) {
			this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
			this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
		}

		if (g.enableHdMenu !== false) {
			if (g.enableColumnHide !== false) {
				this.colMenu = new Ext.menu.Menu({
					id: g.id + "-hcols-menu"
				});
				this.colMenu.on("beforeshow", this.beforeColMenuShow, this);
				this.colMenu.on("itemclick", this.handleHdMenuClick, this);
			}
			this.hmenu = new Ext.menu.Menu({
				id: g.id + "-hctx"
			});
			this.hmenu.add({
				id: "asc",
				text: this.sortAscText,
				cls: "xg-hmenu-sort-asc"
			},
			{
				id: "desc",
				text: this.sortDescText,
				cls: "xg-hmenu-sort-desc"
			});
			if (g.enableColumnHide !== false) {
				this.hmenu.add('-', {
					id: "columns",
					text: this.columnsText,
					menu: this.colMenu,
					iconCls: 'x-cols-icon'
				});
			}
			this.hmenu.on("itemclick", this.handleHdMenuClick, this);

		}

		if (g.enableDragDrop || g.enableDrag) {
			this.dragZone = new Ext.grid.GridDragZone(g, {
				ddGroup: g.ddGroup || 'GridDD'
			});
		}

		this.updateHeaderSortState();

	},

	layout: function() {
		if (!this.mainBody) {
			return;
		}
		var g = this.grid;
		var c = g.getGridEl();
		var csize = c.getSize(true);
		var vw = csize.width;

		if (vw < 20 || csize.height < 20) {
			return;
		}

		if (g.autoHeight) {
			this.scroller.dom.style.overflow = 'visible';
		} else {
			this.el.setSize(csize.width, csize.height);

			var hdHeight = this.mainHd.getHeight();
			var vh = csize.height - (hdHeight);

			this.scroller.setSize(vw, vh);
			if (this.innerHd) {
				this.innerHd.style.width = (vw) + 'px';
			}
		}
		if (this.forceFit) {
			if (this.lastViewWidth != vw) {
				this.fitColumns(false, false);
				this.lastViewWidth = vw;
			}
		} else {
			this.autoExpand();
			this.syncHeaderScroll();
		}
		this.onLayout(vw, vh);
	},

	onLayout: function(vw, vh) {},

	onColumnWidthUpdated: function(col, w, tw) {},

	onAllColumnWidthsUpdated: function(ws, tw) {},

	onColumnHiddenUpdated: function(col, hidden, tw) {},

	updateColumnText: function(col, text) {},

	afterMove: function(colIndex) {},

	init: function(grid) {
		this.grid = grid;

		this.initTemplates();
		this.initData(grid.store, grid.colModel);
		this.initUI(grid);
	},

	getColumnId: function(index) {
		return this.cm.getColumnId(index);
	},

	renderHeaders: function() {
		var cm = this.cm,
		ts = this.templates;
		var ct = ts.hcell;

		var cb = [],
		sb = [],
		p = {};

		for (var i = 0, len = cm.getColumnCount(); i < len; i++) {
			p.id = cm.getColumnId(i);
			p.value = cm.getColumnHeader(i) || "";
			p.style = this.getColumnStyle(i, true);
			p.tooltip = this.getColumnTooltip(i);
			if (cm.config[i].align == 'right') {
				p.istyle = 'padding-right:16px';
			} else {
				delete p.istyle;
			}
			cb[cb.length] = ct.apply(p);
		}
		return ts.header.apply({
			cells: cb.join(""),
			tstyle: 'width:' + this.getTotalWidth() + ';'
		});
	},

	getColumnTooltip: function(i) {
		var tt = this.cm.getColumnTooltip(i);
		if (tt) {
			if (Ext.QuickTips.isEnabled()) {
				return 'ext:qtip="' + tt + '"';
			} else {
				return 'title="' + tt + '"';
			}
		}
		return "";
	},

	beforeUpdate: function() {
		this.grid.stopEditing(true);
	},

	updateHeaders: function() {
		this.innerHd.firstChild.innerHTML = this.renderHeaders();
	},

	focusRow: function(row) {
		this.focusCell(row, 0, false);
	},

	focusCell: function(row, col, hscroll) {
		row = Math.min(row, Math.max(0, this.getRows().length - 1));
		var xy = this.ensureVisible(row, col, hscroll);
		this.focusEl.setXY(xy || this.scroller.getXY());

		if (Ext.isGecko) {
			this.focusEl.focus();
		} else {
			this.focusEl.focus.defer(1, this.focusEl);
		}
	},

	ensureVisible: function(row, col, hscroll) {
		if (typeof row != "number") {
			row = row.rowIndex;
		}
		if (!this.ds) {
			return;
		}
		if (row < 0 || row >= this.ds.getCount()) {
			return;
		}
		col = (col !== undefined ? col: 0);

		var rowEl = this.getRow(row),
		cellEl;
		if (! (hscroll === false && col === 0)) {
			while (this.cm.isHidden(col)) {
				col++;
			}
			cellEl = this.getCell(row, col);
		}
		if (!rowEl) {
			return;
		}

		var c = this.scroller.dom;

		var ctop = 0;
		var p = rowEl,
		stop = this.el.dom;
		while (p && p != stop) {
			ctop += p.offsetTop;
			p = p.offsetParent;
		}
		ctop -= this.mainHd.dom.offsetHeight;

		var cbot = ctop + rowEl.offsetHeight;

		var ch = c.clientHeight;
		var stop = parseInt(c.scrollTop, 10);
		var sbot = stop + ch;

		if (ctop < stop) {
			c.scrollTop = ctop;
		} else if (cbot > sbot) {
			c.scrollTop = cbot - ch;
		}

		if (hscroll !== false) {
			var cleft = parseInt(cellEl.offsetLeft, 10);
			var cright = cleft + cellEl.offsetWidth;

			var sleft = parseInt(c.scrollLeft, 10);
			var sright = sleft + c.clientWidth;
			if (cleft < sleft) {
				c.scrollLeft = cleft;
			} else if (cright > sright) {
				c.scrollLeft = cright - c.clientWidth;
			}
		}
		return cellEl ? Ext.fly(cellEl).getXY() : [c.scrollLeft + this.el.getX(), Ext.fly(rowEl).getY()];
	},

	insertRows: function(dm, firstRow, lastRow, isUpdate) {
		if (!isUpdate && firstRow === 0 && lastRow >= dm.getCount() - 1) {
			this.refresh();
		} else {
			if (!isUpdate) {
				this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
			}
			var html = this.renderRows(firstRow, lastRow);
			var before = this.getRow(firstRow);
			if (before) {
				Ext.DomHelper.insertHtml('beforeBegin', before, html);
			} else {
				Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
			}
			if (!isUpdate) {
				this.fireEvent("rowsinserted", this, firstRow, lastRow);
				this.processRows(firstRow);
			}
		}
		this.focusRow(firstRow);
	},

	deleteRows: function(dm, firstRow, lastRow) {
		if (dm.getRowCount() < 1) {
			this.refresh();
		} else {
			this.fireEvent("beforerowsdeleted", this, firstRow, lastRow);

			this.removeRows(firstRow, lastRow);

			this.processRows(firstRow);
			this.fireEvent("rowsdeleted", this, firstRow, lastRow);
		}
	},

	getColumnStyle: function(col, isHeader) {
		var style = !isHeader ? (this.cm.config[col].css || '') : '';
		style += 'width:' + this.getColumnWidth(col) + ';';
		if (this.cm.isHidden(col)) {
			style += 'display:none;';
		}
		var align = this.cm.config[col].align;
		if (align) {
			style += 'text-align:' + align + ';';
		}
		return style;
	},

	getColumnWidth: function(col) {
		var w = this.cm.getColumnWidth(col);
		if (typeof w == 'number') {
			return (Ext.isBorderBox ? w: (w - this.borderWidth > 0 ? w - this.borderWidth: 0)) + 'px';
		}
		return w;
	},

	getTotalWidth: function() {
		return this.cm.getTotalWidth() + 'px';
	},

	fitColumns: function(preventRefresh, onlyExpand, omitColumn) {
		var cm = this.cm,
		leftOver,
		dist,
		i;
		var tw = cm.getTotalWidth(false);
		var aw = this.grid.getGridEl().getWidth(true) - this.scrollOffset;

		if (aw < 20) {
			return;
		}
		var extra = aw - tw;

		if (extra === 0) {
			return false;
		}

		var vc = cm.getColumnCount(true);
		var ac = vc - (typeof omitColumn == 'number' ? 1: 0);
		if (ac === 0) {
			ac = 1;
			omitColumn = undefined;
		}
		var colCount = cm.getColumnCount();
		var cols = [];
		var extraCol = 0;
		var width = 0;
		var w;
		for (i = 0; i < colCount; i++) {
			if (!cm.isHidden(i) && !cm.isFixed(i) && i !== omitColumn) {
				w = cm.getColumnWidth(i);
				cols.push(i);
				extraCol = i;
				cols.push(w);
				width += w;
			}
		}
		var frac = (aw - cm.getTotalWidth()) / width;
		while (cols.length) {
			w = cols.pop();
			i = cols.pop();
			cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w * frac)), true);
		}

		if ((tw = cm.getTotalWidth(false)) > aw) {
			var adjustCol = ac != vc ? omitColumn: extraCol;
			cm.setColumnWidth(adjustCol, Math.max(1, cm.getColumnWidth(adjustCol) - (tw - aw)), true);
		}

		if (preventRefresh !== true) {
			this.updateAllColumnWidths();
		}

		return true;
	},

	autoExpand: function(preventUpdate) {
		var g = this.grid,
		cm = this.cm;
		if (!this.userResized && g.autoExpandColumn) {
			var tw = cm.getTotalWidth(false);
			var aw = this.grid.getGridEl().getWidth(true) - this.scrollOffset;
			if (tw != aw) {
				var ci = cm.getIndexById(g.autoExpandColumn);
				var currentWidth = cm.getColumnWidth(ci);
				var cw = Math.min(Math.max(((aw - tw) + currentWidth), g.autoExpandMin), g.autoExpandMax);
				if (cw != currentWidth) {
					cm.setColumnWidth(ci, cw, true);
					if (preventUpdate !== true) {
						this.updateColumnWidth(ci, cw);
					}
				}
			}
		}
	},

	getColumnData: function() {
		var cs = [],
		cm = this.cm,
		colCount = cm.getColumnCount();
		for (var i = 0; i < colCount; i++) {
			var name = cm.getDataIndex(i);
			cs[i] = {
				name: (typeof name == 'undefined' ? this.ds.fields.get(i).name: name),
				renderer: cm.getRenderer(i),
				id: cm.getColumnId(i),
				style: this.getColumnStyle(i)
			};
		}
		return cs;
	},

	renderRows: function(startRow, endRow) {
		var g = this.grid,
		cm = g.colModel,
		ds = g.store,
		stripe = g.stripeRows;
		var colCount = cm.getColumnCount();

		if (ds.getCount() < 1) {
			return "";
		}

		var cs = this.getColumnData();

		startRow = startRow || 0;
		endRow = typeof endRow == "undefined" ? ds.getCount() - 1: endRow;

		var rs = ds.getRange(startRow, endRow);

		return this.doRender(cs, rs, ds, startRow, colCount, stripe);
	},

	renderBody: function() {
		var markup = this.renderRows();
		return this.templates.body.apply({
			rows: markup
		});
	},

	refreshRow: function(record) {
		var ds = this.ds,
		index;
		if (typeof record == 'number') {
			index = record;
			record = ds.getAt(index);
		} else {
			index = ds.indexOf(record);
		}
		var cls = [];
		this.insertRows(ds, index, index, true);
		this.getRow(index).rowIndex = index;
		this.onRemove(ds, record, index + 1, true);
		this.fireEvent("rowupdated", this, index, record);
	},

	refresh: function(headersToo) {
		this.fireEvent("beforerefresh", this);
		this.grid.stopEditing(true);

		var result = this.renderBody();
		this.mainBody.update(result);

		if (headersToo === true) {
			this.updateHeaders();
			this.updateHeaderSortState();
		}
		this.processRows(0, true);
		this.layout();
		this.applyEmptyText();
		this.fireEvent("refresh", this);
	},

	applyEmptyText: function() {
		if (this.emptyText && !this.hasRows()) {
			this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
		}
	},

	updateHeaderSortState: function() {
		var state = this.ds.getSortState();
		if (!state) {
			return;
		}
		if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
			this.grid.fireEvent('sortchange', this.grid, state);
		}
		this.sortState = state;
		var sortColumn = this.cm.findColumnIndex(state.field);
		if (sortColumn != -1) {
			var sortDir = state.direction;
			this.updateSortIcon(sortColumn, sortDir);
		}
	},

	destroy: function() {
		if (this.colMenu) {
			this.colMenu.removeAll();
			Ext.menu.MenuMgr.unregister(this.colMenu);
			this.colMenu.getEl().remove();
			delete this.colMenu;
		}
		if (this.hmenu) {
			this.hmenu.removeAll();
			Ext.menu.MenuMgr.unregister(this.hmenu);
			this.hmenu.getEl().remove();
			delete this.hmenu;
		}
		if (this.grid.enableColumnMove) {
			var dds = Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
			if (dds) {
				for (var dd in dds) {
					if (!dds[dd].config.isTarget && dds[dd].dragElId) {
						var elid = dds[dd].dragElId;
						dds[dd].unreg();
						Ext.get(elid).remove();
					} else if (dds[dd].config.isTarget) {
						dds[dd].proxyTop.remove();
						dds[dd].proxyBottom.remove();
						dds[dd].unreg();
					}
					if (Ext.dd.DDM.locationCache[dd]) {
						delete Ext.dd.DDM.locationCache[dd];
					}
				}
				delete Ext.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
			}
		}

		Ext.destroy(this.resizeMarker, this.resizeProxy);

		if (this.dragZone) {
			this.dragZone.unreg();
		}

		this.initData(null, null);
		Ext.EventManager.removeResizeListener(this.onWindowResize, this);
	},

	onDenyColumnHide: function() {
		},

	render: function() {

		if (this.autoFill) {
			this.fitColumns(true, true);
		} else if (this.forceFit) {
			this.fitColumns(true, false);
		} else if (this.grid.autoExpandColumn) {
			this.autoExpand(true);
		}

		this.renderUI();
	},

	initData: function(ds, cm) {
		if (this.ds) {
			this.ds.un("load", this.onLoad, this);
			this.ds.un("datachanged", this.onDataChange, this);
			this.ds.un("add", this.onAdd, this);
			this.ds.un("remove", this.onRemove, this);
			this.ds.un("update", this.onUpdate, this);
			this.ds.un("clear", this.onClear, this);
		}
		if (ds) {
			ds.on("load", this.onLoad, this);
			ds.on("datachanged", this.onDataChange, this);
			ds.on("add", this.onAdd, this);
			ds.on("remove", this.onRemove, this);
			ds.on("update", this.onUpdate, this);
			ds.on("clear", this.onClear, this);
		}
		this.ds = ds;

		if (this.cm) {
			this.cm.un("configchange", this.onColConfigChange, this);
			this.cm.un("widthchange", this.onColWidthChange, this);
			this.cm.un("headerchange", this.onHeaderChange, this);
			this.cm.un("hiddenchange", this.onHiddenChange, this);
			this.cm.un("columnmoved", this.onColumnMove, this);
			this.cm.un("columnlockchange", this.onColumnLock, this);
		}
		if (cm) {
			delete this.lastViewWidth;
			cm.on("configchange", this.onColConfigChange, this);
			cm.on("widthchange", this.onColWidthChange, this);
			cm.on("headerchange", this.onHeaderChange, this);
			cm.on("hiddenchange", this.onHiddenChange, this);
			cm.on("columnmoved", this.onColumnMove, this);
			cm.on("columnlockchange", this.onColumnLock, this);
		}
		this.cm = cm;
	},

	onDataChange: function() {
		this.refresh();
		this.updateHeaderSortState();
	},

	onClear: function() {
		this.refresh();
	},

	onUpdate: function(ds, record) {
		this.refreshRow(record);
	},

	onAdd: function(ds, records, index) {
		this.insertRows(ds, index, index + (records.length - 1));
	},

	onRemove: function(ds, record, index, isUpdate) {
		if (isUpdate !== true) {
			this.fireEvent("beforerowremoved", this, index, record);
		}
		this.removeRow(index);
		if (isUpdate !== true) {
			this.processRows(index);
			this.applyEmptyText();
			this.fireEvent("rowremoved", this, index, record);
		}
	},

	onLoad: function() {
		this.scrollToTop();
	},

	onColWidthChange: function(cm, col, width) {
		this.updateColumnWidth(col, width);
	},

	onHeaderChange: function(cm, col, text) {
		this.updateHeaders();
	},

	onHiddenChange: function(cm, col, hidden) {
		this.updateColumnHidden(col, hidden);
	},

	onColumnMove: function(cm, oldIndex, newIndex) {
		this.indexMap = null;
		var s = this.getScrollState();
		this.refresh(true);
		this.restoreScroll(s);
		this.afterMove(newIndex);
	},

	onColConfigChange: function() {
		delete this.lastViewWidth;
		this.indexMap = null;
		this.refresh(true);
	},

	initUI: function(grid) {
		grid.on("headerclick", this.onHeaderClick, this);

		if (grid.trackMouseOver) {
			grid.on("mouseover", this.onRowOver, this);
			grid.on("mouseout", this.onRowOut, this);
		}
	},

	initEvents: function() {
		},

	onHeaderClick: function(g, index) {
		if (this.headersDisabled || !this.cm.isSortable(index)) {
			return;
		}
		g.stopEditing(true);
		g.store.sort(this.cm.getDataIndex(index));
	},

	onRowOver: function(e, t) {
		var row;
		if ((row = this.findRowIndex(t)) !== false) {
			this.addRowClass(row, "x-grid3-row-over");
		}
	},

	onRowOut: function(e, t) {
		var row;
		if ((row = this.findRowIndex(t)) !== false && row !== this.findRowIndex(e.getRelatedTarget())) {
			this.removeRowClass(row, "x-grid3-row-over");
		}
	},

	handleWheel: function(e) {
		e.stopPropagation();
	},

	onRowSelect: function(row) {
		this.addRowClass(row, "x-grid3-row-selected");
	},

	onRowDeselect: function(row) {
		this.removeRowClass(row, "x-grid3-row-selected");
	},

	onCellSelect: function(row, col) {
		var cell = this.getCell(row, col);
		if (cell) {
			this.fly(cell).addClass("x-grid3-cell-selected");
		}
	},

	onCellDeselect: function(row, col) {
		var cell = this.getCell(row, col);
		if (cell) {
			this.fly(cell).removeClass("x-grid3-cell-selected");
		}
	},

	onColumnSplitterMoved: function(i, w) {
		this.userResized = true;
		var cm = this.grid.colModel;
		cm.setColumnWidth(i, w, true);

		if (this.forceFit) {
			this.fitColumns(true, false, i);
			this.updateAllColumnWidths();
		} else {
			this.updateColumnWidth(i, w);
		}

		this.grid.fireEvent("columnresize", i, w);
	},

	handleHdMenuClick: function(item) {
		var index = this.hdCtxIndex;
		var cm = this.cm,
		ds = this.ds;
		switch (item.id) {
		case "asc":
			ds.sort(cm.getDataIndex(index), "ASC");
			break;
		case "desc":
			ds.sort(cm.getDataIndex(index), "DESC");
			break;
		default:
			index = cm.getIndexById(item.id.substr(4));
			if (index != -1) {
				if (item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1) {
					this.onDenyColumnHide();
					return false;
				}
				cm.setHidden(index, item.checked);
			}
		}
		return true;
	},

	isHideableColumn: function(c) {
		return ! c.hidden && !c.fixed;
	},

	beforeColMenuShow: function() {
		var cm = this.cm,
		colCount = cm.getColumnCount();
		this.colMenu.removeAll();
		for (var i = 0; i < colCount; i++) {
			if (cm.config[i].fixed !== true && cm.config[i].hideable !== false) {
				this.colMenu.add(new Ext.menu.CheckItem({
					id: "col-" + cm.getColumnId(i),
					text: cm.getColumnHeader(i),
					checked: !cm.isHidden(i),
					hideOnClick: false,
					disabled: cm.config[i].hideable === false
				}));
			}
		}
	},

	handleHdDown: function(e, t) {
		if (Ext.fly(t).hasClass('x-grid3-hd-btn')) {
			e.stopEvent();
			var hd = this.findHeaderCell(t);
			Ext.fly(hd).addClass('x-grid3-hd-menu-open');
			var index = this.getCellIndex(hd);
			this.hdCtxIndex = index;
			var ms = this.hmenu.items,
			cm = this.cm;
			ms.get("asc").setDisabled(!cm.isSortable(index));
			ms.get("desc").setDisabled(!cm.isSortable(index));
			this.hmenu.on("hide",
			function() {
				Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
			},
			this, {
				single: true
			});
			this.hmenu.show(t, "tl-bl?");
		}
	},

	handleHdOver: function(e, t) {
		var hd = this.findHeaderCell(t);
		if (hd && !this.headersDisabled) {
			this.activeHd = hd;
			this.activeHdIndex = this.getCellIndex(hd);
			var fly = this.fly(hd);
			this.activeHdRegion = fly.getRegion();
			if (!this.cm.isMenuDisabled(this.activeHdIndex)) {
				fly.addClass("x-grid3-hd-over");
				this.activeHdBtn = fly.child('.x-grid3-hd-btn');
				if (this.activeHdBtn) {
					this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight - 1) + 'px';
				}
			}
		}
	},

	handleHdMove: function(e, t) {
		if (this.activeHd && !this.headersDisabled) {
			var hw = this.splitHandleWidth || 5;
			var r = this.activeHdRegion;
			var x = e.getPageX();
			var ss = this.activeHd.style;
			if (x - r.left <= hw && this.cm.isResizable(this.activeHdIndex - 1)) {
				ss.cursor = Ext.isAir ? 'move': Ext.isSafari ? 'e-resize': 'col-resize';
			} else if (r.right - x <= (!this.activeHdBtn ? hw: 2) && this.cm.isResizable(this.activeHdIndex)) {
				ss.cursor = Ext.isAir ? 'move': Ext.isSafari ? 'w-resize': 'col-resize';
			} else {
				ss.cursor = '';
			}
		}
	},

	handleHdOut: function(e, t) {
		var hd = this.findHeaderCell(t);
		if (hd && (!Ext.isIE || !e.within(hd, true))) {
			this.activeHd = null;
			this.fly(hd).removeClass("x-grid3-hd-over");
			hd.style.cursor = '';
		}
	},

	hasRows: function() {
		var fc = this.mainBody.dom.firstChild;
		return fc && fc.className != 'x-grid-empty';
	},

	bind: function(d, c) {
		this.initData(d, c);
	}
});

Ext.grid.GridView.SplitDragZone = function(grid, hd) {
	this.grid = grid;
	this.view = grid.getView();
	this.marker = this.view.resizeMarker;
	this.proxy = this.view.resizeProxy;
	Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd, "gridSplitters" + this.grid.getGridEl().id, {
		dragElId: Ext.id(this.proxy.dom),
		resizeFrame: false
	});
	this.scroll = false;
	this.hw = this.view.splitHandleWidth || 5;
};
Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {

	b4StartDrag: function(x, y) {
		this.view.headersDisabled = true;
		var h = this.view.mainWrap.getHeight();
		this.marker.setHeight(h);
		this.marker.show();
		this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [ - 2, 0]);
		this.proxy.setHeight(h);
		var w = this.cm.getColumnWidth(this.cellIndex);
		var minw = Math.max(w - this.grid.minColumnWidth, 0);
		this.resetConstraints();
		this.setXConstraint(minw, 1000);
		this.setYConstraint(0, 0);
		this.minX = x - minw;
		this.maxX = x + 1000;
		this.startPos = x;
		Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
	},

	handleMouseDown: function(e) {
		var t = this.view.findHeaderCell(e.getTarget());
		if (t) {
			var xy = this.view.fly(t).getXY(),
			x = xy[0],
			y = xy[1];
			var exy = e.getXY(),
			ex = exy[0],
			ey = exy[1];
			var w = t.offsetWidth,
			adjust = false;
			if ((ex - x) <= this.hw) {
				adjust = -1;
			} else if ((x + w) - ex <= this.hw) {
				adjust = 0;
			}
			if (adjust !== false) {
				this.cm = this.grid.colModel;
				var ci = this.view.getCellIndex(t);
				if (adjust == -1) {
					if (ci + adjust < 0) {
						return;
					}
					while (this.cm.isHidden(ci + adjust)) {--adjust;
						if (ci + adjust < 0) {
							return;
						}
					}
				}
				this.cellIndex = ci + adjust;
				this.split = t.dom;
				if (this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)) {
					Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
				}
			} else if (this.view.columnDrag) {
				this.view.columnDrag.callHandleMouseDown(e);
			}
		}
	},

	endDrag: function(e) {
		this.marker.hide();
		var v = this.view;
		var endX = Math.max(this.minX, e.getPageX());
		var diff = endX - this.startPos;
		v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + diff);
		setTimeout(function() {
			v.headersDisabled = false;
		},
		50);
	},

	autoOffset: function() {
		this.setDelta(0, 0);
	}
});

Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {

	hideGroupedColumn: false,

	showGroupName: true,

	startCollapsed: false,

	enableGrouping: true,

	enableGroupingMenu: true,

	enableNoGroups: true,

	emptyGroupText: '(None)',

	ignoreAdd: false,

	groupTextTpl: '{text}',

	gidSeed: 1000,

	initTemplates: function() {
		Ext.grid.GroupingView.superclass.initTemplates.call(this);
		this.state = {};

		var sm = this.grid.getSelectionModel();
		sm.on(sm.selectRow ? 'beforerowselect': 'beforecellselect', this.onBeforeRowSelect, this);

		if (!this.startGroup) {
			this.startGroup = new Ext.XTemplate('<div id="{groupId}" class="x-grid-group {cls}">', '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div>', this.groupTextTpl, '</div></div>', '<div id="{groupId}-bd" class="x-grid-group-body">');
		}
		this.startGroup.compile();
		this.endGroup = '</div></div>';
	},

	findGroup: function(el) {
		return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
	},

	getGroups: function() {
		return this.hasRows() ? this.mainBody.dom.childNodes: [];
	},

	onAdd: function() {
		if (this.enableGrouping && !this.ignoreAdd) {
			var ss = this.getScrollState();
			this.refresh();
			this.restoreScroll(ss);
		} else if (!this.enableGrouping) {
			Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
		}
	},

	onRemove: function(ds, record, index, isUpdate) {
		Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
		var g = document.getElementById(record._groupId);
		if (g && g.childNodes[1].childNodes.length < 1) {
			Ext.removeNode(g);
		}
		this.applyEmptyText();
	},

	refreshRow: function(record) {
		if (this.ds.getCount() == 1) {
			this.refresh();
		} else {
			this.isUpdating = true;
			Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
			this.isUpdating = false;
		}
	},

	beforeMenuShow: function() {
		var field = this.getGroupField();
		var g = this.hmenu.items.get('groupBy');
		if (g) {
			g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
		}
		var s = this.hmenu.items.get('showGroups');
		if (s) {
			s.setDisabled(!field && this.cm.config[this.hdCtxIndex].groupable === false);
			s.setChecked( !! field, true);
		}
	},

	renderUI: function() {
		Ext.grid.GroupingView.superclass.renderUI.call(this);
		this.mainBody.on('mousedown', this.interceptMouse, this);

		if (this.enableGroupingMenu && this.hmenu) {
			this.hmenu.add('-', {
				id: 'groupBy',
				text: this.groupByText,
				handler: this.onGroupByClick,
				scope: this,
				iconCls: 'x-group-by-icon'
			});
			if (this.enableNoGroups) {
				this.hmenu.add({
					id: 'showGroups',
					text: this.showGroupsText,
					checked: true,
					checkHandler: this.onShowGroupsClick,
					scope: this
				});
			}
			this.hmenu.on('beforeshow', this.beforeMenuShow, this);
		}
	},

	onGroupByClick: function() {
		this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
		this.beforeMenuShow();
	},

	onShowGroupsClick: function(mi, checked) {
		if (checked) {
			this.onGroupByClick();
		} else {
			this.grid.store.clearGrouping();
		}
	},

	toggleGroup: function(group, expanded) {
		this.grid.stopEditing(true);
		group = Ext.getDom(group);
		var gel = Ext.fly(group);
		expanded = expanded !== undefined ? expanded: gel.hasClass('x-grid-group-collapsed');

		this.state[gel.dom.id] = expanded;
		gel[expanded ? 'removeClass': 'addClass']('x-grid-group-collapsed');
	},

	toggleAllGroups: function(expanded) {
		var groups = this.getGroups();
		for (var i = 0, len = groups.length; i < len; i++) {
			this.toggleGroup(groups[i], expanded);
		}
	},

	expandAllGroups: function() {
		this.toggleAllGroups(true);
	},

	collapseAllGroups: function() {
		this.toggleAllGroups(false);
	},

	interceptMouse: function(e) {
		var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
		if (hd) {
			e.stopEvent();
			this.toggleGroup(hd.parentNode);
		}
	},

	getGroup: function(v, r, groupRenderer, rowIndex, colIndex, ds) {
		var g = groupRenderer ? groupRenderer(v, {},
		r, rowIndex, colIndex, ds) : String(v);
		if (g === '') {
			g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
		}
		return g;
	},

	getGroupField: function() {
		return this.grid.store.getGroupState();
	},

	renderRows: function() {
		var groupField = this.getGroupField();
		var eg = !!groupField;

		if (this.hideGroupedColumn) {
			var colIndex = this.cm.findColumnIndex(groupField);
			if (!eg && this.lastGroupField !== undefined) {
				this.mainBody.update('');
				this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
				delete this.lastGroupField;
			} else if (eg && this.lastGroupField === undefined) {
				this.lastGroupField = groupField;
				this.cm.setHidden(colIndex, true);
			} else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {
				this.mainBody.update('');
				var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
				this.cm.setHidden(oldIndex, false);
				this.lastGroupField = groupField;
				this.cm.setHidden(colIndex, true);
			}
		}
		return Ext.grid.GroupingView.superclass.renderRows.apply(this, arguments);
	},

	doRender: function(cs, rs, ds, startRow, colCount, stripe) {
		if (rs.length < 1) {
			return '';
		}
		var groupField = this.getGroupField();
		var colIndex = this.cm.findColumnIndex(groupField);

		this.enableGrouping = !!groupField;

		if (!this.enableGrouping || this.isUpdating) {
			return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
		}
		var gstyle = 'width:' + this.getTotalWidth() + ';';

		var gidPrefix = this.grid.getGridEl().id;
		var cfg = this.cm.config[colIndex];
		var groupRenderer = cfg.groupRenderer || cfg.renderer;
		var prefix = this.showGroupName ? (cfg.groupName || cfg.header) + ': ': '';

		var groups = [],
		curGroup,
		i,
		len,
		gid;
		for (i = 0, len = rs.length; i < len; i++) {
			var rowIndex = startRow + i;
			var r = rs[i],
			gvalue = r.data[groupField],
			g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
			if (!curGroup || curGroup.group != g) {
				gid = gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(g);

				var isCollapsed = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;
				var gcls = isCollapsed ? 'x-grid-group-collapsed': '';
				curGroup = {
					group: g,
					gvalue: gvalue,
					text: prefix + g,
					groupId: gid,
					startRow: rowIndex,
					rs: [r],
					cls: gcls,
					style: gstyle
				};
				groups.push(curGroup);
			} else {
				curGroup.rs.push(r);
			}
			r._groupId = gid;
		}

		var buf = [];
		for (i = 0, len = groups.length; i < len; i++) {
			var g = groups[i];
			this.doGroupStart(buf, g, cs, ds, colCount);
			buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(this, cs, g.rs, ds, g.startRow, colCount, stripe);

			this.doGroupEnd(buf, g, cs, ds, colCount);
		}
		return buf.join('');
	},

	getGroupId: function(value) {
		var gidPrefix = this.grid.getGridEl().id;
		var groupField = this.getGroupField();
		var colIndex = this.cm.findColumnIndex(groupField);
		var cfg = this.cm.config[colIndex];
		var groupRenderer = cfg.groupRenderer || cfg.renderer;
		var gtext = this.getGroup(value, {
			data: {}
		},
		groupRenderer, 0, colIndex, this.ds);
		return gidPrefix + '-gp-' + groupField + '-' + Ext.util.Format.htmlEncode(value);
	},

	doGroupStart: function(buf, g, cs, ds, colCount) {
		buf[buf.length] = this.startGroup.apply(g);
	},

	doGroupEnd: function(buf, g, cs, ds, colCount) {
		buf[buf.length] = this.endGroup;
	},

	getRows: function() {
		if (!this.enableGrouping) {
			return Ext.grid.GroupingView.superclass.getRows.call(this);
		}
		var r = [];
		var g,
		gs = this.getGroups();
		for (var i = 0, len = gs.length; i < len; i++) {
			g = gs[i].childNodes[1].childNodes;
			for (var j = 0, jlen = g.length; j < jlen; j++) {
				r[r.length] = g[j];
			}
		}
		return r;
	},

	updateGroupWidths: function() {
		if (!this.enableGrouping || !this.hasRows()) {
			return;
		}
		var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth - this.scrollOffset) + 'px';
		var gs = this.getGroups();
		for (var i = 0, len = gs.length; i < len; i++) {
			gs[i].firstChild.style.width = tw;
		}
	},

	onColumnWidthUpdated: function(col, w, tw) {
		this.updateGroupWidths();
	},

	onAllColumnWidthsUpdated: function(ws, tw) {
		this.updateGroupWidths();
	},

	onColumnHiddenUpdated: function(col, hidden, tw) {
		this.updateGroupWidths();
	},

	onLayout: function() {
		this.updateGroupWidths();
	},

	onBeforeRowSelect: function(sm, rowIndex) {
		if (!this.enableGrouping) {
			return;
		}
		var row = this.getRow(rowIndex);
		if (row && !row.offsetParent) {
			var g = this.findGroup(row);
			this.toggleGroup(g, true);
		}
	},

	groupByText: 'Group By This Field',

	showGroupsText: 'Show in Groups'
});

Ext.grid.GroupingView.GROUP_ID = 1000;

Ext.grid.HeaderDragZone = function(grid, hd, hd2) {
	this.grid = grid;
	this.view = grid.getView();
	this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
	Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
	if (hd2) {
		this.setHandleElId(Ext.id(hd));
		this.setOuterHandleElId(Ext.id(hd2));
	}
	this.scroll = false;
};
Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {
	maxDragWidth: 120,
	getDragData: function(e) {
		var t = Ext.lib.Event.getTarget(e);
		var h = this.view.findHeaderCell(t);
		if (h) {
			return {
				ddel: h.firstChild,
				header: h
			};
		}
		return false;
	},

	onInitDrag: function(e) {
		this.view.headersDisabled = true;
		var clone = this.dragData.ddel.cloneNode(true);
		clone.id = Ext.id();
		clone.style.width = Math.min(this.dragData.header.offsetWidth, this.maxDragWidth) + "px";
		this.proxy.update(clone);
		return true;
	},

	afterValidDrop: function() {
		var v = this.view;
		setTimeout(function() {
			v.headersDisabled = false;
		},
		50);
	},

	afterInvalidDrop: function() {
		var v = this.view;
		setTimeout(function() {
			v.headersDisabled = false;
		},
		50);
	}
});

Ext.grid.HeaderDropZone = function(grid, hd, hd2) {
	this.grid = grid;
	this.view = grid.getView();

	this.proxyTop = Ext.DomHelper.append(document.body, {
		cls: "col-move-top",
		html: "&#160;"
	},
	true);
	this.proxyBottom = Ext.DomHelper.append(document.body, {
		cls: "col-move-bottom",
		html: "&#160;"
	},
	true);
	this.proxyTop.hide = this.proxyBottom.hide = function() {
		this.setLeftTop( - 100, -100);
		this.setStyle("visibility", "hidden");
	};
	this.ddGroup = "gridHeader" + this.grid.getGridEl().id;

	Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
};
Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {
	proxyOffsets: [ - 4, -9],
	fly: Ext.Element.fly,

	getTargetFromEvent: function(e) {
		var t = Ext.lib.Event.getTarget(e);
		var cindex = this.view.findCellIndex(t);
		if (cindex !== false) {
			return this.view.getHeaderCell(cindex);
		}
	},

	nextVisible: function(h) {
		var v = this.view,
		cm = this.grid.colModel;
		h = h.nextSibling;
		while (h) {
			if (!cm.isHidden(v.getCellIndex(h))) {
				return h;
			}
			h = h.nextSibling;
		}
		return null;
	},

	prevVisible: function(h) {
		var v = this.view,
		cm = this.grid.colModel;
		h = h.prevSibling;
		while (h) {
			if (!cm.isHidden(v.getCellIndex(h))) {
				return h;
			}
			h = h.prevSibling;
		}
		return null;
	},

	positionIndicator: function(h, n, e) {
		var x = Ext.lib.Event.getPageX(e);
		var r = Ext.lib.Dom.getRegion(n.firstChild);
		var px,
		pt,
		py = r.top + this.proxyOffsets[1];
		if ((r.right - x) <= (r.right - r.left) / 2) {
			px = r.right + this.view.borderWidth;
			pt = "after";
		} else {
			px = r.left;
			pt = "before";
		}
		var oldIndex = this.view.getCellIndex(h);
		var newIndex = this.view.getCellIndex(n);

		if (this.grid.colModel.isFixed(newIndex)) {
			return false;
		}

		var locked = this.grid.colModel.isLocked(newIndex);

		if (pt == "after") {
			newIndex++;
		}
		if (oldIndex < newIndex) {
			newIndex--;
		}
		if (oldIndex == newIndex && (locked == this.grid.colModel.isLocked(oldIndex))) {
			return false;
		}
		px += this.proxyOffsets[0];
		this.proxyTop.setLeftTop(px, py);
		this.proxyTop.show();
		if (!this.bottomOffset) {
			this.bottomOffset = this.view.mainHd.getHeight();
		}
		this.proxyBottom.setLeftTop(px, py + this.proxyTop.dom.offsetHeight + this.bottomOffset);
		this.proxyBottom.show();
		return pt;
	},

	onNodeEnter: function(n, dd, e, data) {
		if (data.header != n) {
			this.positionIndicator(data.header, n, e);
		}
	},

	onNodeOver: function(n, dd, e, data) {
		var result = false;
		if (data.header != n) {
			result = this.positionIndicator(data.header, n, e);
		}
		if (!result) {
			this.proxyTop.hide();
			this.proxyBottom.hide();
		}
		return result ? this.dropAllowed: this.dropNotAllowed;
	},

	onNodeOut: function(n, dd, e, data) {
		this.proxyTop.hide();
		this.proxyBottom.hide();
	},

	onNodeDrop: function(n, dd, e, data) {
		var h = data.header;
		if (h != n) {
			var cm = this.grid.colModel;
			var x = Ext.lib.Event.getPageX(e);
			var r = Ext.lib.Dom.getRegion(n.firstChild);
			var pt = (r.right - x) <= ((r.right - r.left) / 2) ? "after": "before";
			var oldIndex = this.view.getCellIndex(h);
			var newIndex = this.view.getCellIndex(n);
			var locked = cm.isLocked(newIndex);
			if (pt == "after") {
				newIndex++;
			}
			if (oldIndex < newIndex) {
				newIndex--;
			}
			if (oldIndex == newIndex && (locked == cm.isLocked(oldIndex))) {
				return false;
			}
			cm.setLocked(oldIndex, locked, true);
			cm.moveColumn(oldIndex, newIndex);
			this.grid.fireEvent("columnmove", oldIndex, newIndex);
			return true;
		}
		return false;
	}
});

Ext.grid.GridView.ColumnDragZone = function(grid, hd) {
	Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
	this.proxy.el.addClass('x-grid3-col-dd');
};

Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {
	handleMouseDown: function(e) {
		},

	callHandleMouseDown: function(e) {
		Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
	}
});
Ext.grid.SplitDragZone = function(grid, hd, hd2) {
	this.grid = grid;
	this.view = grid.getView();
	this.proxy = this.view.resizeProxy;
	Ext.grid.SplitDragZone.superclass.constructor.call(this, hd, "gridSplitters" + this.grid.getGridEl().id, {
		dragElId: Ext.id(this.proxy.dom),
		resizeFrame: false
	});
	this.setHandleElId(Ext.id(hd));
	this.setOuterHandleElId(Ext.id(hd2));
	this.scroll = false;
};
Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {
	fly: Ext.Element.fly,

	b4StartDrag: function(x, y) {
		this.view.headersDisabled = true;
		this.proxy.setHeight(this.view.mainWrap.getHeight());
		var w = this.cm.getColumnWidth(this.cellIndex);
		var minw = Math.max(w - this.grid.minColumnWidth, 0);
		this.resetConstraints();
		this.setXConstraint(minw, 1000);
		this.setYConstraint(0, 0);
		this.minX = x - minw;
		this.maxX = x + 1000;
		this.startPos = x;
		Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
	},

	handleMouseDown: function(e) {
		ev = Ext.EventObject.setEvent(e);
		var t = this.fly(ev.getTarget());
		if (t.hasClass("x-grid-split")) {
			this.cellIndex = this.view.getCellIndex(t.dom);
			this.split = t.dom;
			this.cm = this.grid.colModel;
			if (this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)) {
				Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
			}
		}
	},

	endDrag: function(e) {
		this.view.headersDisabled = false;
		var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
		var diff = endX - this.startPos;
		this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + diff);
	},

	autoOffset: function() {
		this.setDelta(0, 0);
	}
});

Ext.grid.GridDragZone = function(grid, config) {
	this.view = grid.getView();
	Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
	if (this.view.lockedBody) {
		this.setHandleElId(Ext.id(this.view.mainBody.dom));
		this.setOuterHandleElId(Ext.id(this.view.lockedBody.dom));
	}
	this.scroll = false;
	this.grid = grid;
	this.ddel = document.createElement('div');
	this.ddel.className = 'x-grid-dd-wrap';
};

Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
	ddGroup: "GridDD",

	getDragData: function(e) {
		var t = Ext.lib.Event.getTarget(e);
		var rowIndex = this.view.findRowIndex(t);
		if (rowIndex !== false) {
			var sm = this.grid.selModel;
			if (!sm.isSelected(rowIndex) || e.hasModifier()) {
				sm.handleMouseDown(this.grid, rowIndex, e);
			}
			return {
				grid: this.grid,
				ddel: this.ddel,
				rowIndex: rowIndex,
				selections: sm.getSelections()
			};
		}
		return false;
	},

	onInitDrag: function(e) {
		var data = this.dragData;
		this.ddel.innerHTML = this.grid.getDragDropText();
		this.proxy.update(this.ddel);
	},

	afterRepair: function() {
		this.dragging = false;
	},

	getRepairXY: function(e, data) {
		return false;
	},

	onEndDrag: function(data, e) {},

	onValidDrop: function(dd, e, id) {
		this.hideProxy();
	},

	beforeInvalidDrop: function(e, id) {
		}
});

Ext.grid.ColumnModel = function(config) {

	this.defaultWidth = 100;

	this.defaultSortable = false;

	if (config.columns) {
		Ext.apply(this, config);
		this.setConfig(config.columns, true);
	} else {
		this.setConfig(config, true);
	}
	this.addEvents(
	"widthchange",
	"headerchange",
	"hiddenchange",
	"columnmoved", "columnlockchange",
	"configchange");
	Ext.grid.ColumnModel.superclass.constructor.call(this);
};
Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {

	getColumnId: function(index) {
		return this.config[index].id;
	},

	setConfig: function(config, initial) {
		if (!initial) {
			delete this.totalWidth;
			for (var i = 0, len = this.config.length; i < len; i++) {
				var c = this.config[i];
				if (c.editor) {
					c.editor.destroy();
				}
			}
		}
		this.config = config;
		this.lookup = {};
		for (var i = 0, len = config.length; i < len; i++) {
			var c = config[i];
			if (typeof c.renderer == "string") {
				c.renderer = Ext.util.Format[c.renderer];
			}
			if (typeof c.id == "undefined") {
				c.id = i;
			}
			if (c.editor && c.editor.isFormField) {
				c.editor = new Ext.grid.GridEditor(c.editor);
			}
			this.lookup[c.id] = c;
		}
		if (!initial) {
			this.fireEvent('configchange', this);
		}
	},

	getColumnById: function(id) {
		return this.lookup[id];
	},

	getIndexById: function(id) {
		for (var i = 0, len = this.config.length; i < len; i++) {
			if (this.config[i].id == id) {
				return i;
			}
		}
		return - 1;
	},

	moveColumn: function(oldIndex, newIndex) {
		var c = this.config[oldIndex];
		this.config.splice(oldIndex, 1);
		this.config.splice(newIndex, 0, c);
		this.dataMap = null;
		this.fireEvent("columnmoved", this, oldIndex, newIndex);
	},

	isLocked: function(colIndex) {
		return this.config[colIndex].locked === true;
	},

	setLocked: function(colIndex, value, suppressEvent) {
		if (this.isLocked(colIndex) == value) {
			return;
		}
		this.config[colIndex].locked = value;
		if (!suppressEvent) {
			this.fireEvent("columnlockchange", this, colIndex, value);
		}
	},

	getTotalLockedWidth: function() {
		var totalWidth = 0;
		for (var i = 0; i < this.config.length; i++) {
			if (this.isLocked(i) && !this.isHidden(i)) {
				this.totalWidth += this.getColumnWidth(i);
			}
		}
		return totalWidth;
	},

	getLockedCount: function() {
		for (var i = 0, len = this.config.length; i < len; i++) {
			if (!this.isLocked(i)) {
				return i;
			}
		}
	},

	getColumnCount: function(visibleOnly) {
		if (visibleOnly === true) {
			var c = 0;
			for (var i = 0, len = this.config.length; i < len; i++) {
				if (!this.isHidden(i)) {
					c++;
				}
			}
			return c;
		}
		return this.config.length;
	},

	getColumnsBy: function(fn, scope) {
		var r = [];
		for (var i = 0, len = this.config.length; i < len; i++) {
			var c = this.config[i];
			if (fn.call(scope || this, c, i) === true) {
				r[r.length] = c;
			}
		}
		return r;
	},

	isSortable: function(col) {
		if (typeof this.config[col].sortable == "undefined") {
			return this.defaultSortable;
		}
		return this.config[col].sortable;
	},

	isMenuDisabled: function(col) {
		return !! this.config[col].menuDisabled;
	},

	getRenderer: function(col) {
		if (!this.config[col].renderer) {
			return Ext.grid.ColumnModel.defaultRenderer;
		}
		return this.config[col].renderer;
	},

	setRenderer: function(col, fn) {
		this.config[col].renderer = fn;
	},

	getColumnWidth: function(col) {
		return this.config[col].width || this.defaultWidth;
	},

	setColumnWidth: function(col, width, suppressEvent) {
		this.config[col].width = width;
		this.totalWidth = null;
		if (!suppressEvent) {
			this.fireEvent("widthchange", this, col, width);
		}
	},

	getTotalWidth: function(includeHidden) {
		if (!this.totalWidth) {
			this.totalWidth = 0;
			for (var i = 0, len = this.config.length; i < len; i++) {
				if (includeHidden || !this.isHidden(i)) {
					this.totalWidth += this.getColumnWidth(i);
				}
			}
		}
		return this.totalWidth;
	},

	getColumnHeader: function(col) {
		return this.config[col].header;
	},

	setColumnHeader: function(col, header) {
		this.config[col].header = header;
		this.fireEvent("headerchange", this, col, header);
	},

	getColumnTooltip: function(col) {
		return this.config[col].tooltip;
	},

	setColumnTooltip: function(col, tooltip) {
		this.config[col].tooltip = tooltip;
	},

	getDataIndex: function(col) {
		return this.config[col].dataIndex;
	},

	setDataIndex: function(col, dataIndex) {
		this.config[col].dataIndex = dataIndex;
	},

	findColumnIndex: function(dataIndex) {
		var c = this.config;
		for (var i = 0, len = c.length; i < len; i++) {
			if (c[i].dataIndex == dataIndex) {
				return i;
			}
		}
		return - 1;
	},

	isCellEditable: function(colIndex, rowIndex) {
		return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true: false;
	},

	getCellEditor: function(colIndex, rowIndex) {
		return this.config[colIndex].editor;
	},

	setEditable: function(col, editable) {
		this.config[col].editable = editable;
	},

	isHidden: function(colIndex) {
		return this.config[colIndex].hidden;
	},

	isFixed: function(colIndex) {
		return this.config[colIndex].fixed;
	},

	isResizable: function(colIndex) {
		return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
	},

	setHidden: function(colIndex, hidden) {
		var c = this.config[colIndex];
		if (c.hidden !== hidden) {
			c.hidden = hidden;
			this.totalWidth = null;
			this.fireEvent("hiddenchange", this, colIndex, hidden);
		}
	},

	setEditor: function(col, editor) {
		this.config[col].editor = editor;
	}
});

Ext.grid.ColumnModel.defaultRenderer = function(value) {
	if (typeof value == "string" && value.length < 1) {
		return "&#160;";
	}
	return value;
};

Ext.grid.DefaultColumnModel = Ext.grid.ColumnModel;

Ext.grid.AbstractSelectionModel = function() {
	this.locked = false;
	Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable, {

	init: function(grid) {
		this.grid = grid;
		this.initEvents();
	},

	lock: function() {
		this.locked = true;
	},

	unlock: function() {
		this.locked = false;
	},

	isLocked: function() {
		return this.locked;
	}
});

Ext.grid.RowSelectionModel = function(config) {
	Ext.apply(this, config);
	this.selections = new Ext.util.MixedCollection(false,
	function(o) {
		return o.id;
	});

	this.last = false;
	this.lastActive = false;

	this.addEvents(
	"selectionchange",
	"beforerowselect",
	"rowselect",
	"rowdeselect");

	Ext.grid.RowSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel, {

	singleSelect: false,

	initEvents: function() {

		if (!this.grid.enableDragDrop && !this.grid.enableDrag) {
			this.grid.on("rowmousedown", this.handleMouseDown, this);
		} else {
			this.grid.on("rowclick",
			function(grid, rowIndex, e) {
				if (e.button === 0 && !e.shiftKey && !e.ctrlKey) {
					this.selectRow(rowIndex, false);
					grid.view.focusRow(rowIndex);
				}
			},
			this);
		}

		this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
			"up": function(e) {
				if (!e.shiftKey) {
					this.selectPrevious(e.shiftKey);
				} else if (this.last !== false && this.lastActive !== false) {
					var last = this.last;
					this.selectRange(this.last, this.lastActive - 1);
					this.grid.getView().focusRow(this.lastActive);
					if (last !== false) {
						this.last = last;
					}
				} else {
					this.selectFirstRow();
				}
			},
			"down": function(e) {
				if (!e.shiftKey) {
					this.selectNext(e.shiftKey);
				} else if (this.last !== false && this.lastActive !== false) {
					var last = this.last;
					this.selectRange(this.last, this.lastActive + 1);
					this.grid.getView().focusRow(this.lastActive);
					if (last !== false) {
						this.last = last;
					}
				} else {
					this.selectFirstRow();
				}
			},
			scope: this
		});

		var view = this.grid.view;
		view.on("refresh", this.onRefresh, this);
		view.on("rowupdated", this.onRowUpdated, this);
		view.on("rowremoved", this.onRemove, this);
	},

	onRefresh: function() {
		var ds = this.grid.store,
		index;
		var s = this.getSelections();
		this.clearSelections(true);
		for (var i = 0, len = s.length; i < len; i++) {
			var r = s[i];
			if ((index = ds.indexOfId(r.id)) != -1) {
				this.selectRow(index, true);
			}
		}
		if (s.length != this.selections.getCount()) {
			this.fireEvent("selectionchange", this);
		}
	},

	onRemove: function(v, index, r) {
		if (this.selections.remove(r) !== false) {
			this.fireEvent('selectionchange', this);
		}
	},

	onRowUpdated: function(v, index, r) {
		if (this.isSelected(r)) {
			v.onRowSelect(index);
		}
	},

	selectRecords: function(records, keepExisting) {
		if (!keepExisting) {
			this.clearSelections();
		}
		var ds = this.grid.store;
		for (var i = 0, len = records.length; i < len; i++) {
			this.selectRow(ds.indexOf(records[i]), true);
		}
	},

	getCount: function() {
		return this.selections.length;
	},

	selectFirstRow: function() {
		this.selectRow(0);
	},

	selectLastRow: function(keepExisting) {
		this.selectRow(this.grid.store.getCount() - 1, keepExisting);
	},

	selectNext: function(keepExisting) {
		if (this.hasNext()) {
			this.selectRow(this.last + 1, keepExisting);
			this.grid.getView().focusRow(this.last);
			return true;
		}
		return false;
	},

	selectPrevious: function(keepExisting) {
		if (this.hasPrevious()) {
			this.selectRow(this.last - 1, keepExisting);
			this.grid.getView().focusRow(this.last);
			return true;
		}
		return false;
	},

	hasNext: function() {
		return this.last !== false && (this.last + 1) < this.grid.store.getCount();
	},

	hasPrevious: function() {
		return !! this.last;
	},

	getSelections: function() {
		return [].concat(this.selections.items);
	},

	getSelected: function() {
		return this.selections.itemAt(0);
	},

	each: function(fn, scope) {
		var s = this.getSelections();
		for (var i = 0, len = s.length; i < len; i++) {
			if (fn.call(scope || this, s[i], i) === false) {
				return false;
			}
		}
		return true;
	},

	clearSelections: function(fast) {
		if (this.locked) return;
		if (fast !== true) {
			var ds = this.grid.store;
			var s = this.selections;
			s.each(function(r) {
				this.deselectRow(ds.indexOfId(r.id));
			},
			this);
			s.clear();
		} else {
			this.selections.clear();
		}
		this.last = false;
	},

	selectAll: function() {
		if (this.locked) return;
		this.selections.clear();
		for (var i = 0, len = this.grid.store.getCount(); i < len; i++) {
			this.selectRow(i, true);
		}
	},

	hasSelection: function() {
		return this.selections.length > 0;
	},

	isSelected: function(index) {
		var r = typeof index == "number" ? this.grid.store.getAt(index) : index;
		return (r && this.selections.key(r.id) ? true: false);
	},

	isIdSelected: function(id) {
		return (this.selections.key(id) ? true: false);
	},

	handleMouseDown: function(g, rowIndex, e) {
		if (e.button !== 0 || this.isLocked()) {
			return;
		};
		var view = this.grid.getView();
		if (e.shiftKey && this.last !== false) {
			var last = this.last;
			this.selectRange(last, rowIndex, e.ctrlKey);
			this.last = last;
			view.focusRow(rowIndex);
		} else {
			var isSelected = this.isSelected(rowIndex);
			if (e.ctrlKey && isSelected) {
				this.deselectRow(rowIndex);
			} else if (!isSelected || this.getCount() > 1) {
				this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
				view.focusRow(rowIndex);
			}
		}
	},

	selectRows: function(rows, keepExisting) {
		if (!keepExisting) {
			this.clearSelections();
		}
		for (var i = 0, len = rows.length; i < len; i++) {
			this.selectRow(rows[i], true);
		}
	},

	selectRange: function(startRow, endRow, keepExisting) {
		if (this.locked) return;
		if (!keepExisting) {
			this.clearSelections();
		}
		if (startRow <= endRow) {
			for (var i = startRow; i <= endRow; i++) {
				this.selectRow(i, true);
			}
		} else {
			for (var i = startRow; i >= endRow; i--) {
				this.selectRow(i, true);
			}
		}
	},

	deselectRange: function(startRow, endRow, preventViewNotify) {
		if (this.locked) return;
		for (var i = startRow; i <= endRow; i++) {
			this.deselectRow(i, preventViewNotify);
		}
	},

	selectRow: function(index, keepExisting, preventViewNotify) {
		if (this.locked || (index < 0 || index >= this.grid.store.getCount()) || this.isSelected(index)) return;
		var r = this.grid.store.getAt(index);
		if (r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false) {
			if (!keepExisting || this.singleSelect) {
				this.clearSelections();
			}
			this.selections.add(r);
			this.last = this.lastActive = index;
			if (!preventViewNotify) {
				this.grid.getView().onRowSelect(index);
			}
			this.fireEvent("rowselect", this, index, r);
			this.fireEvent("selectionchange", this);
		}
	},

	deselectRow: function(index, preventViewNotify) {
		if (this.locked) return;
		if (this.last == index) {
			this.last = false;
		}
		if (this.lastActive == index) {
			this.lastActive = false;
		}
		var r = this.grid.store.getAt(index);
		if (r) {
			this.selections.remove(r);
			if (!preventViewNotify) {
				this.grid.getView().onRowDeselect(index);
			}
			this.fireEvent("rowdeselect", this, index, r);
			this.fireEvent("selectionchange", this);
		}
	},

	restoreLast: function() {
		if (this._last) {
			this.last = this._last;
		}
	},

	acceptsNav: function(row, col, cm) {
		return ! cm.isHidden(col) && cm.isCellEditable(col, row);
	},

	onEditorKey: function(field, e) {
		var k = e.getKey(),
		newCell,
		g = this.grid,
		ed = g.activeEditor;
		var shift = e.shiftKey;
		if (k == e.TAB) {
			e.stopEvent();
			ed.completeEdit();
			if (shift) {
				newCell = g.walkCells(ed.row, ed.col - 1, -1, this.acceptsNav, this);
			} else {
				newCell = g.walkCells(ed.row, ed.col + 1, 1, this.acceptsNav, this);
			}
		} else if (k == e.ENTER) {
			e.stopEvent();
			ed.completeEdit();
			if (this.moveEditorOnEnter !== false) {
				if (shift) {
					newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);
				} else {
					newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);
				}
			}
		} else if (k == e.ESC) {
			ed.cancelEdit();
		}
		if (newCell) {
			g.startEditing(newCell[0], newCell[1]);
		}
	}
});

Ext.grid.CellSelectionModel = function(config) {
	Ext.apply(this, config);

	this.selection = null;

	this.addEvents(
	"beforecellselect",
	"cellselect",
	"selectionchange");

	Ext.grid.CellSelectionModel.superclass.constructor.call(this);
};

Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel, {

	initEvents: function() {
		this.grid.on("cellmousedown", this.handleMouseDown, this);
		this.grid.getGridEl().on(Ext.isIE || Ext.isSafari3 ? "keydown": "keypress", this.handleKeyDown, this);
		var view = this.grid.view;
		view.on("refresh", this.onViewChange, this);
		view.on("rowupdated", this.onRowUpdated, this);
		view.on("beforerowremoved", this.clearSelections, this);
		view.on("beforerowsinserted", this.clearSelections, this);
		if (this.grid.isEditor) {
			this.grid.on("beforeedit", this.beforeEdit, this);
		}
	},

	beforeEdit: function(e) {
		this.select(e.row, e.column, false, true, e.record);
	},

	onRowUpdated: function(v, index, r) {
		if (this.selection && this.selection.record == r) {
			v.onCellSelect(index, this.selection.cell[1]);
		}
	},

	onViewChange: function() {
		this.clearSelections(true);
	},

	getSelectedCell: function() {
		return this.selection ? this.selection.cell: null;
	},

	clearSelections: function(preventNotify) {
		var s = this.selection;
		if (s) {
			if (preventNotify !== true) {
				this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
			}
			this.selection = null;
			this.fireEvent("selectionchange", this, null);
		}
	},

	hasSelection: function() {
		return this.selection ? true: false;
	},

	handleMouseDown: function(g, row, cell, e) {
		if (e.button !== 0 || this.isLocked()) {
			return;
		};
		this.select(row, cell);
	},

	select: function(rowIndex, colIndex, preventViewNotify, preventFocus, r) {
		if (this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false) {
			this.clearSelections();
			r = r || this.grid.store.getAt(rowIndex);
			this.selection = {
				record: r,
				cell: [rowIndex, colIndex]
			};
			if (!preventViewNotify) {
				var v = this.grid.getView();
				v.onCellSelect(rowIndex, colIndex);
				if (preventFocus !== true) {
					v.focusCell(rowIndex, colIndex);
				}
			}
			this.fireEvent("cellselect", this, rowIndex, colIndex);
			this.fireEvent("selectionchange", this, this.selection);
		}
	},

	isSelectable: function(rowIndex, colIndex, cm) {
		return ! cm.isHidden(colIndex);
	},

	handleKeyDown: function(e) {
		if (!e.isNavKeyPress()) {
			return;
		}
		var g = this.grid,
		s = this.selection;
		if (!s) {
			e.stopEvent();
			var cell = g.walkCells(0, 0, 1, this.isSelectable, this);
			if (cell) {
				this.select(cell[0], cell[1]);
			}
			return;
		}
		var sm = this;
		var walk = function(row, col, step) {
			return g.walkCells(row, col, step, sm.isSelectable, sm);
		};
		var k = e.getKey(),
		r = s.cell[0],
		c = s.cell[1];
		var newCell;

		switch (k) {
		case e.TAB:
			if (e.shiftKey) {
				newCell = walk(r, c - 1, -1);
			} else {
				newCell = walk(r, c + 1, 1);
			}
			break;
		case e.DOWN:
			newCell = walk(r + 1, c, 1);
			break;
		case e.UP:
			newCell = walk(r - 1, c, -1);
			break;
		case e.RIGHT:
			newCell = walk(r, c + 1, 1);
			break;
		case e.LEFT:
			newCell = walk(r, c - 1, -1);
			break;
		case e.ENTER:
			if (g.isEditor && !g.editing) {
				g.startEditing(r, c);
				e.stopEvent();
				return;
			}
			break;
		};
		if (newCell) {
			this.select(newCell[0], newCell[1]);
			e.stopEvent();
		}
	},

	acceptsNav: function(row, col, cm) {
		return ! cm.isHidden(col) && cm.isCellEditable(col, row);
	},

	onEditorKey: function(field, e) {
		var k = e.getKey(),
		newCell,
		g = this.grid,
		ed = g.activeEditor;
		if (k == e.TAB) {
			if (e.shiftKey) {
				newCell = g.walkCells(ed.row, ed.col - 1, -1, this.acceptsNav, this);
			} else {
				newCell = g.walkCells(ed.row, ed.col + 1, 1, this.acceptsNav, this);
			}
			e.stopEvent();
		} else if (k == e.ENTER) {
			ed.completeEdit();
			e.stopEvent();
		} else if (k == e.ESC) {
			e.stopEvent();
			ed.cancelEdit();
		}
		if (newCell) {
			g.startEditing(newCell[0], newCell[1]);
		}
	}
});

Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {

	clicksToEdit: 2,

	isEditor: true,
	detectEdit: false,

	autoEncode: false,

	trackMouseOver: false,
	initComponent: function() {
		Ext.grid.EditorGridPanel.superclass.initComponent.call(this);

		if (!this.selModel) {

			this.selModel = new Ext.grid.CellSelectionModel();
		}

		this.activeEditor = null;

		this.addEvents(
		"beforeedit",
		"afteredit",
		"validateedit");
	},

	initEvents: function() {
		Ext.grid.EditorGridPanel.superclass.initEvents.call(this);

		this.on("bodyscroll", this.stopEditing, this, [true]);

		if (this.clicksToEdit == 1) {
			this.on("cellclick", this.onCellDblClick, this);
		} else {
			if (this.clicksToEdit == 'auto' && this.view.mainBody) {
				this.view.mainBody.on("mousedown", this.onAutoEditClick, this);
			}
			this.on("celldblclick", this.onCellDblClick, this);
		}
		this.getGridEl().addClass("xedit-grid");
	},

	onCellDblClick: function(g, row, col) {
		this.startEditing(row, col);
	},

	onAutoEditClick: function(e, t) {
		if (e.button !== 0) {
			return;
		}
		var row = this.view.findRowIndex(t);
		var col = this.view.findCellIndex(t);
		if (row !== false && col !== false) {
			this.stopEditing();
			if (this.selModel.getSelectedCell) {
				var sc = this.selModel.getSelectedCell();
				if (sc && sc.cell[0] === row && sc.cell[1] === col) {
					this.startEditing(row, col);
				}
			} else {
				if (this.selModel.isSelected(row)) {
					this.startEditing(row, col);
				}
			}
		}
	},

	onEditComplete: function(ed, value, startValue) {
		this.editing = false;
		this.activeEditor = null;
		ed.un("specialkey", this.selModel.onEditorKey, this.selModel);
		var r = ed.record;
		var field = this.colModel.getDataIndex(ed.col);
		value = this.postEditValue(value, startValue, r, field);
		if (String(value) !== String(startValue)) {
			var e = {
				grid: this,
				record: r,
				field: field,
				originalValue: startValue,
				value: value,
				row: ed.row,
				column: ed.col,
				cancel: false
			};
			if (this.fireEvent("validateedit", e) !== false && !e.cancel) {
				r.set(field, e.value);
				delete e.cancel;
				this.fireEvent("afteredit", e);
			}
		}
		this.view.focusCell(ed.row, ed.col);
	},

	startEditing: function(row, col) {
		this.stopEditing();
		if (this.colModel.isCellEditable(col, row)) {
			this.view.ensureVisible(row, col, true);
			var r = this.store.getAt(row);
			var field = this.colModel.getDataIndex(col);
			var e = {
				grid: this,
				record: r,
				field: field,
				value: r.data[field],
				row: row,
				column: col,
				cancel: false
			};
			if (this.fireEvent("beforeedit", e) !== false && !e.cancel) {
				this.editing = true;
				var ed = this.colModel.getCellEditor(col, row);
				if (!ed.rendered) {
					ed.render(this.view.getEditorParent(ed));
				} (function() {
					ed.row = row;
					ed.col = col;
					ed.record = r;
					ed.on("complete", this.onEditComplete, this, {
						single: true
					});
					ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
					this.activeEditor = ed;
					var v = this.preEditValue(r, field);
					ed.startEdit(this.view.getCell(row, col).firstChild, v);
				}).defer(50, this);
			}
		}
	},

	preEditValue: function(r, field) {
		var value = r.data[field];
		return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlDecode(value) : value;
	},

	postEditValue: function(value, originalValue, r, field) {
		return this.autoEncode && typeof value == 'string' ? Ext.util.Format.htmlEncode(value) : value;
	},

	stopEditing: function(cancel) {
		if (this.activeEditor) {
			this.activeEditor[cancel === true ? 'cancelEdit': 'completeEdit']();
		}
		this.activeEditor = null;
	},

	onDestroy: function() {
		if (this.rendered) {
			var cols = this.colModel.config;
			for (var i = 0, len = cols.length; i < len; i++) {
				var c = cols[i];
				Ext.destroy(c.editor);
			}
		}
		Ext.grid.EditorGridPanel.superclass.onDestroy.call(this);
	}
});
Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
Ext.grid.GridEditor = function(field, config) {
	Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
	field.monitorTab = false;
};

Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
	alignment: "tl-tl",
	autoSize: "width",
	hideEl: false,
	cls: "x-small-editor x-grid-editor",
	shim: false,
	shadow: false
});

Ext.grid.PropertyRecord = Ext.data.Record.create([{
	name: 'name',
	type: 'string'
},
'value']);

Ext.grid.PropertyStore = function(grid, source) {
	this.grid = grid;
	this.store = new Ext.data.Store({
		recordType: Ext.grid.PropertyRecord
	});
	this.store.on('update', this.onUpdate, this);
	if (source) {
		this.setSource(source);
	}
	Ext.grid.PropertyStore.superclass.constructor.call(this);
};
Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
	setSource: function(o) {
		this.source = o;
		this.store.removeAll();
		var data = [];
		for (var k in o) {
			if (this.isEditableValue(o[k])) {
				data.push(new Ext.grid.PropertyRecord({
					name: k,
					value: o[k]
				},
				k));
			}
		}
		this.store.loadRecords({
			records: data
		},
		{},
		true);
	},

	onUpdate: function(ds, record, type) {
		if (type == Ext.data.Record.EDIT) {
			var v = record.data['value'];
			var oldValue = record.modified['value'];
			if (this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false) {
				this.source[record.id] = v;
				record.commit();
				this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
			} else {
				record.reject();
			}
		}
	},

	getProperty: function(row) {
		return this.store.getAt(row);
	},

	isEditableValue: function(val) {
		if (Ext.isDate(val)) {
			return true;
		} else if (typeof val == 'object' || typeof val == 'function') {
			return false;
		}
		return true;
	},

	setValue: function(prop, value) {
		this.source[prop] = value;
		this.store.getById(prop).set('value', value);
	},

	getSource: function() {
		return this.source;
	}
});

Ext.grid.PropertyColumnModel = function(grid, store) {
	this.grid = grid;
	var g = Ext.grid;
	g.PropertyColumnModel.superclass.constructor.call(this, [{
		header: this.nameText,
		width: 50,
		sortable: true,
		dataIndex: 'name',
		id: 'name',
		menuDisabled: true
	},
	{
		header: this.valueText,
		width: 50,
		resizable: false,
		dataIndex: 'value',
		id: 'value',
		menuDisabled: true
	}]);
	this.store = store;
	this.bselect = Ext.DomHelper.append(document.body, {
		tag: 'select',
		cls: 'x-grid-editor x-hide-display',
		children: [{
			tag: 'option',
			value: 'true',
			html: 'true'
		},
		{
			tag: 'option',
			value: 'false',
			html: 'false'
		}]
	});
	var f = Ext.form;

	var bfield = new f.Field({
		el: this.bselect,
		bselect: this.bselect,
		autoShow: true,
		getValue: function() {
			return this.bselect.value == 'true';
		}
	});
	this.editors = {
		'date': new g.GridEditor(new f.DateField({
			selectOnFocus: true
		})),
		'string': new g.GridEditor(new f.TextField({
			selectOnFocus: true
		})),
		'number': new g.GridEditor(new f.NumberField({
			selectOnFocus: true,
			style: 'text-align:left;'
		})),
		'boolean': new g.GridEditor(bfield)
	};
	this.renderCellDelegate = this.renderCell.createDelegate(this);
	this.renderPropDelegate = this.renderProp.createDelegate(this);
};

Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
	nameText: 'Name',
	valueText: 'Value',
	dateFormat: 'm/j/Y',

	renderDate: function(dateVal) {
		return dateVal.dateFormat(this.dateFormat);
	},

	renderBool: function(bVal) {
		return bVal ? 'true': 'false';
	},

	isCellEditable: function(colIndex, rowIndex) {
		return colIndex == 1;
	},

	getRenderer: function(col) {
		return col == 1 ? this.renderCellDelegate: this.renderPropDelegate;
	},

	renderProp: function(v) {
		return this.getPropertyName(v);
	},

	renderCell: function(val) {
		var rv = val;
		if (Ext.isDate(val)) {
			rv = this.renderDate(val);
		} else if (typeof val == 'boolean') {
			rv = this.renderBool(val);
		}
		return Ext.util.Format.htmlEncode(rv);
	},

	getPropertyName: function(name) {
		var pn = this.grid.propertyNames;
		return pn && pn[name] ? pn[name] : name;
	},

	getCellEditor: function(colIndex, rowIndex) {
		var p = this.store.getProperty(rowIndex);
		var n = p.data['name'],
		val = p.data['value'];
		if (this.grid.customEditors[n]) {
			return this.grid.customEditors[n];
		}
		if (Ext.isDate(val)) {
			return this.editors['date'];
		} else if (typeof val == 'number') {
			return this.editors['number'];
		} else if (typeof val == 'boolean') {
			return this.editors['boolean'];
		} else {
			return this.editors['string'];
		}
	}
});

Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {

	enableColumnMove: false,
	stripeRows: false,
	trackMouseOver: false,
	clicksToEdit: 1,
	enableHdMenu: false,
	viewConfig: {
		forceFit: true
	},

	initComponent: function() {
		this.customEditors = this.customEditors || {};
		this.lastEditRow = null;
		var store = new Ext.grid.PropertyStore(this);
		this.propStore = store;
		var cm = new Ext.grid.PropertyColumnModel(this, store);
		store.store.sort('name', 'ASC');
		this.addEvents(
		'beforepropertychange',
		'propertychange');
		this.cm = cm;
		this.ds = store.store;
		Ext.grid.PropertyGrid.superclass.initComponent.call(this);

		this.selModel.on('beforecellselect',
		function(sm, rowIndex, colIndex) {
			if (colIndex === 0) {
				this.startEditing.defer(200, this, [rowIndex, 1]);
				return false;
			}
		},
		this);
	},

	onRender: function() {
		Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);

		this.getGridEl().addClass('x-props-grid');
	},

	afterRender: function() {
		Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
		if (this.source) {
			this.setSource(this.source);
		}
	},

	setSource: function(source) {
		this.propStore.setSource(source);
	},

	getSource: function() {
		return this.propStore.getSource();
	}
});
Ext.reg("propertygrid", Ext.grid.PropertyGrid);

Ext.grid.RowNumberer = function(config) {
	Ext.apply(this, config);
	if (this.rowspan) {
		this.renderer = this.renderer.createDelegate(this);
	}
};

Ext.grid.RowNumberer.prototype = {

	header: "",

	width: 23,

	sortable: false,

	fixed: true,
	menuDisabled: true,
	dataIndex: '',
	id: 'numberer',
	rowspan: undefined,

	renderer: function(v, p, record, rowIndex) {
		if (this.rowspan) {
			p.cellAttr = 'rowspan="' + this.rowspan + '"';
		}
		return rowIndex + 1;
	}
};

Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {

	header: '<div class="x-grid3-hd-checker">&#160;</div>',

	width: 20,

	sortable: false,

	menuDisabled: true,
	fixed: true,
	dataIndex: '',
	id: 'checker',

	initEvents: function() {
		Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
		this.grid.on('render',
		function() {
			var view = this.grid.getView();
			view.mainBody.on('mousedown', this.onMouseDown, this);
			Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);

		},
		this);
	},

	onMouseDown: function(e, t) {
		if (e.button === 0 && t.className == 'x-grid3-row-checker') {
			e.stopEvent();
			var row = e.getTarget('.x-grid3-row');
			if (row) {
				var index = row.rowIndex;
				if (this.isSelected(index)) {
					this.deselectRow(index);
				} else {
					this.selectRow(index, true);
				}
			}
		}
	},

	onHdMouseDown: function(e, t) {
		if (t.className == 'x-grid3-hd-checker') {
			e.stopEvent();
			var hd = Ext.fly(t.parentNode);
			var isChecked = hd.hasClass('x-grid3-hd-checker-on');
			if (isChecked) {
				hd.removeClass('x-grid3-hd-checker-on');
				this.clearSelections();
			} else {
				hd.addClass('x-grid3-hd-checker-on');
				this.selectAll();
			}
		}
	},

	renderer: function(v, p, record) {
		return '<div class="x-grid3-row-checker">&#160;</div>';
	}
});

Ext.LoadMask = function(el, config) {
	this.el = Ext.get(el);
	Ext.apply(this, config);
	if (this.store) {
		this.store.on('beforeload', this.onBeforeLoad, this);
		this.store.on('load', this.onLoad, this);
		this.store.on('loadexception', this.onLoad, this);
		this.removeMask = Ext.value(this.removeMask, false);
	} else {
		var um = this.el.getUpdater();
		um.showLoadIndicator = false;
		um.on('beforeupdate', this.onBeforeLoad, this);
		um.on('update', this.onLoad, this);
		um.on('failure', this.onLoad, this);
		this.removeMask = Ext.value(this.removeMask, true);
	}
};

Ext.LoadMask.prototype = {

	msg: 'Loading...',

	msgCls: 'x-mask-loading',

	disabled: false,

	disable: function() {
		this.disabled = true;
	},

	enable: function() {
		this.disabled = false;
	},

	onLoad: function() {
		this.el.unmask(this.removeMask);
	},

	onBeforeLoad: function() {
		if (!this.disabled) {
			this.el.mask(this.msg, this.msgCls);
		}
	},

	show: function() {
		this.onBeforeLoad();
	},

	hide: function() {
		this.onLoad();
	},

	destroy: function() {
		if (this.store) {
			this.store.un('beforeload', this.onBeforeLoad, this);
			this.store.un('load', this.onLoad, this);
			this.store.un('loadexception', this.onLoad, this);
		} else {
			var um = this.el.getUpdater();
			um.un('beforeupdate', this.onBeforeLoad, this);
			um.un('update', this.onLoad, this);
			um.un('failure', this.onLoad, this);
		}
	}
};

Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {

	baseCls: 'x-progress',

	waitTimer: null,

	initComponent: function() {
		Ext.ProgressBar.superclass.initComponent.call(this);
		this.addEvents(
		"update");
	},

	onRender: function(ct, position) {
		Ext.ProgressBar.superclass.onRender.call(this, ct, position);

		var tpl = new Ext.Template('<div class="{cls}-wrap">', '<div class="{cls}-inner">', '<div class="{cls}-bar">', '<div class="{cls}-text">', '<div>&#160;</div>', '</div>', '</div>', '<div class="{cls}-text {cls}-text-back">', '<div>&#160;</div>', '</div>', '</div>', '</div>');

		if (position) {
			this.el = tpl.insertBefore(position, {
				cls: this.baseCls
			},
			true);
		} else {
			this.el = tpl.append(ct, {
				cls: this.baseCls
			},
			true);
		}
		if (this.id) {
			this.el.dom.id = this.id;
		}
		var inner = this.el.dom.firstChild;
		this.progressBar = Ext.get(inner.firstChild);

		if (this.textEl) {

			this.textEl = Ext.get(this.textEl);
			delete this.textTopEl;
		} else {

			this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
			var textBackEl = Ext.get(inner.childNodes[1]);
			this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
			this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
			this.textEl.setWidth(inner.offsetWidth);
		}
		this.progressBar.setHeight(inner.offsetHeight);
	},

	afterRender: function() {
		Ext.ProgressBar.superclass.afterRender.call(this);
		if (this.value) {
			this.updateProgress(this.value, this.text);
		} else {
			this.updateText(this.text);
		}
	},

	updateProgress: function(value, text) {
		this.value = value || 0;
		if (text) {
			this.updateText(text);
		}
		if (this.rendered) {
			var w = Math.floor(value * this.el.dom.firstChild.offsetWidth);
			this.progressBar.setWidth(w);
			if (this.textTopEl) {

				this.textTopEl.removeClass('x-hidden').setWidth(w);
			}
		}
		this.fireEvent('update', this, value, text);
		return this;
	},

	wait: function(o) {
		if (!this.waitTimer) {
			var scope = this;
			o = o || {};
			this.updateText(o.text);
			this.waitTimer = Ext.TaskMgr.start({
				run: function(i) {
					var inc = o.increment || 10;
					this.updateProgress(((((i + inc) % inc) + 1) * (100 / inc)) * .01);
				},
				interval: o.interval || 1000,
				duration: o.duration,
				onStop: function() {
					if (o.fn) {
						o.fn.apply(o.scope || this);
					}
					this.reset();
				},
				scope: scope
			});
		}
		return this;
	},

	isWaiting: function() {
		return this.waitTimer != null;
	},

	updateText: function(text) {
		this.text = text || '&#160;';
		if (this.rendered) {
			this.textEl.update(this.text);
		}
		return this;
	},

	syncProgressBar: function() {
		if (this.value) {
			this.updateProgress(this.value, this.text);
		}
		return this;
	},

	setSize: function(w, h) {
		Ext.ProgressBar.superclass.setSize.call(this, w, h);
		if (this.textTopEl) {
			var inner = this.el.dom.firstChild;
			this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
		}
		this.syncProgressBar();
		return this;
	},

	reset: function(hide) {
		this.updateProgress(0);
		if (this.textTopEl) {
			this.textTopEl.addClass('x-hidden');
		}
		if (this.waitTimer) {
			this.waitTimer.onStop = null;
			Ext.TaskMgr.stop(this.waitTimer);
			this.waitTimer = null;
		}
		if (hide === true) {
			this.hide();
		}
		return this;
	}
});
Ext.reg('progress', Ext.ProgressBar);

Ext.Slider = Ext.extend(Ext.BoxComponent, {

	vertical: false,

	minValue: 0,

	maxValue: 100,

	keyIncrement: 1,

	increment: 0,

	clickRange: [5, 15],

	clickToChange: true,

	animate: true,

	dragging: false,

	initComponent: function() {
		if (this.value === undefined) {
			this.value = this.minValue;
		}
		Ext.Slider.superclass.initComponent.call(this);
		this.keyIncrement = Math.max(this.increment, this.keyIncrement);
		this.addEvents(
		'beforechange',
		'change',
		'changecomplete',
		'dragstart',
		'drag',
		'dragend');

		if (this.vertical) {
			Ext.apply(this, Ext.Slider.Vertical);
		}
	},

	onRender: function() {
		this.autoEl = {
			cls: 'x-slider ' + (this.vertical ? 'x-slider-vert': 'x-slider-horz'),
			cn: {
				cls: 'x-slider-end',
				cn: {
					cls: 'x-slider-inner',
					cn: [{
						cls: 'x-slider-thumb'
					},
					{
						tag: 'a',
						cls: 'x-slider-focus',
						href: "#",
						tabIndex: '-1',
						hidefocus: 'on'
					}]
				}
			}
		};
		Ext.Slider.superclass.onRender.apply(this, arguments);
		this.endEl = this.el.first();
		this.innerEl = this.endEl.first();
		this.thumb = this.innerEl.first();
		this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth()) / 2;
		this.focusEl = this.thumb.next();
		this.initEvents();
	},

	initEvents: function() {
		this.thumb.addClassOnOver('x-slider-thumb-over');
		this.mon(this.el, 'mousedown', this.onMouseDown, this);
		this.mon(this.el, 'keydown', this.onKeyDown, this);

		this.focusEl.swallowEvent("click", true);

		this.tracker = new Ext.dd.DragTracker({
			onBeforeStart: this.onBeforeDragStart.createDelegate(this),
			onStart: this.onDragStart.createDelegate(this),
			onDrag: this.onDrag.createDelegate(this),
			onEnd: this.onDragEnd.createDelegate(this),
			tolerance: 3,
			autoStart: 300
		});
		this.tracker.initEl(this.thumb);
		this.on('beforedestroy', this.tracker.destroy, this.tracker);
	},

	onMouseDown: function(e) {
		if (this.disabled) {
			return;
		}
		if (this.clickToChange && e.target != this.thumb.dom) {
			var local = this.innerEl.translatePoints(e.getXY());
			this.onClickChange(local);
		}
		this.focus();
	},

	onClickChange: function(local) {
		if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
			this.setValue(Math.round(this.reverseValue(local.left)), undefined, true);
		}
	},

	onKeyDown: function(e) {
		if (this.disabled) {
			e.preventDefault();
			return;
		}
		var k = e.getKey();
		switch (k) {
		case e.UP:
		case e.RIGHT:
			e.stopEvent();
			if (e.ctrlKey) {
				this.setValue(this.maxValue, undefined, true);
			} else {
				this.setValue(this.value + this.keyIncrement, undefined, true);
			}
			break;
		case e.DOWN:
		case e.LEFT:
			e.stopEvent();
			if (e.ctrlKey) {
				this.setValue(this.minValue, undefined, true);
			} else {
				this.setValue(this.value - this.keyIncrement, undefined, true);
			}
			break;
		default:
			e.preventDefault();
		}
	},

	doSnap: function(value) {
		if (!this.increment || this.increment == 1 || !value) {
			return value;
		}
		var newValue = value,
		inc = this.increment;
		var m = value % inc;
		if (m > 0) {
			if (m > (inc / 2)) {
				newValue = value + (inc - m);
			} else {
				newValue = value - m;
			}
		}
		return newValue.constrain(this.minValue, this.maxValue);
	},

	afterRender: function() {
		Ext.Slider.superclass.afterRender.apply(this, arguments);
		if (this.value !== undefined) {
			var v = this.normalizeValue(this.value);
			if (v !== this.value) {
				delete this.value;
				this.setValue(v, false);
			} else {
				this.moveThumb(this.translateValue(v), false);
			}
		}
	},

	getRatio: function() {
		var w = this.innerEl.getWidth();
		var v = this.maxValue - this.minValue;
		return v == 0 ? w: (w / v);
	},

	normalizeValue: function(v) {
		if (typeof v != 'number') {
			v = parseInt(v);
		}
		v = Math.round(v);
		v = this.doSnap(v);
		v = v.constrain(this.minValue, this.maxValue);
		return v;
	},

	setValue: function(v, animate, changeComplete) {
		v = this.normalizeValue(v);
		if (v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false) {
			this.value = v;
			this.moveThumb(this.translateValue(v), animate !== false);
			this.fireEvent('change', this, v);
			if (changeComplete) {
				this.fireEvent('changecomplete', this, v);
			}
		}
	},

	translateValue: function(v) {
		var ratio = this.getRatio();
		return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
	},

	reverseValue: function(pos) {
		var ratio = this.getRatio();
		return (pos + this.halfThumb + (this.minValue * ratio)) / ratio;
	},

	moveThumb: function(v, animate) {
		if (!animate || this.animate === false) {
			this.thumb.setLeft(v);
		} else {
			this.thumb.shift({
				left: v,
				stopFx: true,
				duration: .35
			});
		}
	},

	focus: function() {
		this.focusEl.focus(10);
	},

	onBeforeDragStart: function(e) {
		return ! this.disabled;
	},

	onDragStart: function(e) {
		this.thumb.addClass('x-slider-thumb-drag');
		this.dragging = true;
		this.dragStartValue = this.value;
		this.fireEvent('dragstart', this, e);
	},

	onDrag: function(e) {
		var pos = this.innerEl.translatePoints(this.tracker.getXY());
		this.setValue(Math.round(this.reverseValue(pos.left)), false);
		this.fireEvent('drag', this, e);
	},

	onDragEnd: function(e) {
		this.thumb.removeClass('x-slider-thumb-drag');
		this.dragging = false;
		this.fireEvent('dragend', this, e);
		if (this.dragStartValue != this.value) {
			this.fireEvent('changecomplete', this, this.value);
		}
	},

	onResize: function(w, h) {
		this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
		this.syncThumb();
	},

	syncThumb: function() {
		if (this.rendered) {
			this.moveThumb(this.translateValue(this.value));
		}
	},

	getValue: function() {
		return this.value;
	}
});
Ext.reg('slider', Ext.Slider);

Ext.Slider.Vertical = {
	onResize: function(w, h) {
		this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
		this.syncThumb();
	},

	getRatio: function() {
		var h = this.innerEl.getHeight();
		var v = this.maxValue - this.minValue;
		return h / v;
	},

	moveThumb: function(v, animate) {
		if (!animate || this.animate === false) {
			this.thumb.setBottom(v);
		} else {
			this.thumb.shift({
				bottom: v,
				stopFx: true,
				duration: .35
			});
		}
	},

	onDrag: function(e) {
		var pos = this.innerEl.translatePoints(this.tracker.getXY());
		var bottom = this.innerEl.getHeight() - pos.top;
		this.setValue(Math.round(bottom / this.getRatio()), false);
		this.fireEvent('drag', this, e);
	},

	onClickChange: function(local) {
		if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
			var bottom = this.innerEl.getHeight() - local.top;
			this.setValue(Math.round(bottom / this.getRatio()), undefined, true);
		}
	}
};

Ext.StatusBar = Ext.extend(Ext.Toolbar, {

	cls: 'x-statusbar',

	busyIconCls: 'x-status-busy',

	busyText: 'Loading...',

	autoClear: 5000,

	activeThreadId: 0,

	initComponent: function() {
		if (this.statusAlign == 'right') {
			this.cls += ' x-status-right';
		}
		Ext.StatusBar.superclass.initComponent.call(this);
	},

	afterRender: function() {
		Ext.StatusBar.superclass.afterRender.call(this);

		var right = this.statusAlign == 'right',
		td = Ext.get(this.nextBlock());

		if (right) {
			this.tr.appendChild(td.dom);
		} else {
			td.insertBefore(this.tr.firstChild);
		}

		this.statusEl = td.createChild({
			cls: 'x-status-text ' + (this.iconCls || this.defaultIconCls || ''),
			html: this.text || this.defaultText || ''
		});
		this.statusEl.unselectable();

		this.spacerEl = td.insertSibling({
			tag: 'td',
			style: 'width:100%',
			cn: [{
				cls: 'ytb-spacer'
			}]
		},
		right ? 'before': 'after');
	},

	setStatus: function(o) {
		o = o || {};

		if (typeof o == 'string') {
			o = {
				text: o
			};
		}
		if (o.text !== undefined) {
			this.setText(o.text);
		}
		if (o.iconCls !== undefined) {
			this.setIcon(o.iconCls);
		}

		if (o.clear) {
			var c = o.clear,
			wait = this.autoClear,
			defaults = {
				useDefaults: true,
				anim: true
			};

			if (typeof c == 'object') {
				c = Ext.applyIf(c, defaults);
				if (c.wait) {
					wait = c.wait;
				}
			} else if (typeof c == 'number') {
				wait = c;
				c = defaults;
			} else if (typeof c == 'boolean') {
				c = defaults;
			}

			c.threadId = this.activeThreadId;
			this.clearStatus.defer(wait, this, [c]);
		}
		return this;
	},

	clearStatus: function(o) {
		o = o || {};

		if (o.threadId && o.threadId !== this.activeThreadId) {
			return this;
		}

		var text = o.useDefaults ? this.defaultText: '',
		iconCls = o.useDefaults ? (this.defaultIconCls ? this.defaultIconCls: '') : '';

		if (o.anim) {
			this.statusEl.fadeOut({
				remove: false,
				useDisplay: true,
				scope: this,
				callback: function() {
					this.setStatus({
						text: text,
						iconCls: iconCls
					});
					this.statusEl.show();
				}
			});
		} else {
			this.statusEl.hide();
			this.setStatus({
				text: text,
				iconCls: iconCls
			});
			this.statusEl.show();
		}
		return this;
	},

	setText: function(text) {
		this.activeThreadId++;
		this.text = text || '';
		if (this.rendered) {
			this.statusEl.update(this.text);
		}
		return this;
	},

	getText: function() {
		return this.text;
	},

	setIcon: function(cls) {
		this.activeThreadId++;
		cls = cls || '';

		if (this.rendered) {
			if (this.currIconCls) {
				this.statusEl.removeClass(this.currIconCls);
				this.currIconCls = null;
			}
			if (cls.length > 0) {
				this.statusEl.addClass(cls);
				this.currIconCls = cls;
			}
		} else {
			this.currIconCls = cls;
		}
		return this;
	},

	showBusy: function(o) {
		if (typeof o == 'string') {
			o = {
				text: o
			};
		}
		o = Ext.applyIf(o || {},
		{
			text: this.busyText,
			iconCls: this.busyIconCls
		});
		return this.setStatus(o);
	}
});
Ext.reg('statusbar', Ext.StatusBar);

Ext.History = (function() {
	var iframe,
	hiddenField;
	var ready = false;
	var currentToken;

	function getHash() {
		var href = top.location.href,
		i = href.indexOf("#");
		return i >= 0 ? href.substr(i + 1) : null;
	}

	function doSave() {
		hiddenField.value = currentToken;
	}

	function handleStateChange(token) {
		currentToken = token;
		Ext.History.fireEvent('change', token);
	}

	function updateIFrame(token) {
		var html = ['<html><body><div id="state">', token, '</div></body></html>'].join('');
		try {
			var doc = iframe.contentWindow.document;
			doc.open();
			doc.write(html);
			doc.close();
			return true;
		} catch(e) {
			return false;
		}
	}

	function checkIFrame() {
		if (!iframe.contentWindow || !iframe.contentWindow.document) {
			setTimeout(checkIFrame, 10);
			return;
		}

		var doc = iframe.contentWindow.document;
		var elem = doc.getElementById("state");
		var token = elem ? elem.innerText: null;

		var hash = getHash();

		setInterval(function() {

			doc = iframe.contentWindow.document;
			elem = doc.getElementById("state");

			var newtoken = elem ? elem.innerText: null;

			var newHash = getHash();

			if (newtoken !== token) {
				token = newtoken;
				handleStateChange(token);
				top.location.hash = token;
				hash = token;
				doSave();
			} else if (newHash !== hash) {
				hash = newHash;
				updateIFrame(newHash);
			}

		},
		50);

		ready = true;

		Ext.History.fireEvent('ready', Ext.History);
	}

	function startUp() {
		currentToken = hiddenField.value;

		if (Ext.isIE) {
			checkIFrame();
		} else {
			var hash = getHash();
			setInterval(function() {
				var newHash = getHash();
				if (newHash !== hash) {
					hash = newHash;
					handleStateChange(hash);
					doSave();
				}
			},
			50);
			ready = true;
			Ext.History.fireEvent('ready', Ext.History);
		}
	}

	return {

		fieldId: 'x-history-field',

		iframeId: 'x-history-frame',

		events: {},

		init: function(onReady, scope) {
			if (ready) {
				Ext.callback(onReady, scope, [this]);
				return;
			}
			if (!Ext.isReady) {
				Ext.onReady(function() {
					Ext.History.init(onReady, scope);
				});
				return;
			}
			hiddenField = Ext.getDom(Ext.History.fieldId);
			if (Ext.isIE) {
				iframe = Ext.getDom(Ext.History.iframeId);
			}
			this.addEvents('ready', 'change');
			if (onReady) {
				this.on('ready', onReady, scope, {
					single: true
				});
			}
			startUp();
		},

		add: function(token, preventDup) {
			if (preventDup !== false) {
				if (this.getToken() == token) {
					return true;
				}
			}
			if (Ext.isIE) {
				return updateIFrame(token);
			} else {
				top.location.hash = token;
				return true;
			}
		},

		back: function() {
			history.go( - 1);
		},

		forward: function() {
			history.go(1);
		},

		getToken: function() {
			return ready ? currentToken: getHash();
		}
	};
})();
Ext.apply(Ext.History, new Ext.util.Observable());
Ext.debug = {};
 (function() {

	var cp;

	function createConsole() {

		var scriptPanel = new Ext.debug.ScriptsPanel();
		var logView = new Ext.debug.LogPanel();
		var tree = new Ext.debug.DomTree();

		var tabs = new Ext.TabPanel({
			activeTab: 0,
			border: false,
			tabPosition: 'bottom',
			items: [{
				title: 'Debug Console',
				layout: 'border',
				items: [logView, scriptPanel]
			},
			{
				title: 'DOM Inspector',
				layout: 'border',
				items: [tree]
			}]
		});

		cp = new Ext.Panel({
			id: 'x-debug-browser',
			title: 'Console',
			collapsible: true,
			animCollapse: false,
			style: 'position:absolute;left:0;bottom:0;',
			height: 200,
			logView: logView,
			layout: 'fit',

			tools: [{
				id: 'close',
				handler: function() {
					cp.destroy();
					cp = null;
					Ext.EventManager.removeResizeListener(handleResize);
				}
			}],

			items: tabs
		});

		cp.render(document.body);

		cp.resizer = new Ext.Resizable(cp.el, {
			minHeight: 50,
			handles: "n",
			pinned: true,
			transparent: true,
			resizeElement: function() {
				var box = this.proxy.getBox();
				this.proxy.hide();
				cp.setHeight(box.height);
				return box;
			}
		});

		function handleResize() {
			cp.setWidth(Ext.getBody().getViewSize().width);
		}
		Ext.EventManager.onWindowResize(handleResize);

		handleResize();
	}

	Ext.apply(Ext, {
		log: function() {
			if (!cp) {
				createConsole();
			}
			cp.logView.log.apply(cp.logView, arguments);
		},

		logf: function(format, arg1, arg2, etc) {
			Ext.log(String.format.apply(String, arguments));
		},

		dump: function(o) {
			if (typeof o == 'string' || typeof o == 'number' || typeof o == 'undefined' || Ext.isDate(o)) {
				Ext.log(o);
			} else if (!o) {
				Ext.log("null");
			} else if (typeof o != "object") {
				Ext.log('Unknown return type');
			} else if (Ext.isArray(o)) {
				Ext.log('[' + o.join(',') + ']');
			} else {
				var b = ["{\n"];
				for (var key in o) {
					var to = typeof o[key];
					if (to != "function" && to != "object") {
						b.push(String.format("  {0}: {1},\n", key, o[key]));
					}
				}
				var s = b.join("");
				if (s.length > 3) {
					s = s.substr(0, s.length - 2);
				}
				Ext.log(s + "\n}");
			}
		},

		_timers: {},

		time: function(name) {
			name = name || "def";
			Ext._timers[name] = new Date().getTime();
		},

		timeEnd: function(name, printResults) {
			var t = new Date().getTime();
			name = name || "def";
			var v = String.format("{0} ms", t - Ext._timers[name]);
			Ext._timers[name] = new Date().getTime();
			if (printResults !== false) {
				Ext.log('Timer ' + (name == "def" ? v: name + ": " + v));
			}
			return v;
		}
	});

})();

Ext.debug.ScriptsPanel = Ext.extend(Ext.Panel, {
	id: 'x-debug-scripts',
	region: 'east',
	minWidth: 200,
	split: true,
	width: 350,
	border: false,
	layout: 'anchor',
	style: 'border-width:0 0 0 1px;',

	initComponent: function() {

		this.scriptField = new Ext.form.TextArea({
			anchor: '100% -26',
			style: 'border-width:0;'
		});

		this.trapBox = new Ext.form.Checkbox({
			id: 'console-trap',
			boxLabel: 'Trap Errors',
			checked: true
		});

		this.toolbar = new Ext.Toolbar([{
			text: 'Run',
			scope: this,
			handler: this.evalScript
		},
		{
			text: 'Clear',
			scope: this,
			handler: this.clear
		},
		'->', this.trapBox, ' ', ' ']);

		this.items = [this.toolbar, this.scriptField];

		Ext.debug.ScriptsPanel.superclass.initComponent.call(this);
	},

	evalScript: function() {
		var s = this.scriptField.getValue();
		if (this.trapBox.getValue()) {
			try {
				var rt = eval(s);
				Ext.dump(rt === undefined ? '(no return)': rt);
			} catch(e) {
				Ext.log(e.message || e.descript);
			}
		} else {
			var rt = eval(s);
			Ext.dump(rt === undefined ? '(no return)': rt);
		}
	},

	clear: function() {
		this.scriptField.setValue('');
		this.scriptField.focus();
	}

});

Ext.debug.LogPanel = Ext.extend(Ext.Panel, {
	autoScroll: true,
	region: 'center',
	border: false,
	style: 'border-width:0 1px 0 0',

	log: function() {
		var markup = ['<div style="padding:5px !important;border-bottom:1px solid #ccc;">', Ext.util.Format.htmlEncode(Array.prototype.join.call(arguments, ', ')).replace(/\n/g, '<br />').replace(/\s/g, '&#160;'), '</div>'].join('');

		this.body.insertHtml('beforeend', markup);
		this.body.scrollTo('top', 100000);
	},

	clear: function() {
		this.body.update('');
		this.body.dom.scrollTop = 0;
	}
});

Ext.debug.DomTree = Ext.extend(Ext.tree.TreePanel, {
	enableDD: false,
	lines: false,
	rootVisible: false,
	animate: false,
	hlColor: 'ffff9c',
	autoScroll: true,
	region: 'center',
	border: false,

	initComponent: function() {

		Ext.debug.DomTree.superclass.initComponent.call(this);

		var styles = false,
		hnode;
		var nonSpace = /^\s*$/;
		var html = Ext.util.Format.htmlEncode;
		var ellipsis = Ext.util.Format.ellipsis;
		var styleRe = /\s?([a-z\-]*)\:([^;]*)(?:[;\s\n\r]*)/gi;

		function findNode(n) {
			if (!n || n.nodeType != 1 || n == document.body || n == document) {
				return false;
			}
			var pn = [n],
			p = n;
			while ((p = p.parentNode) && p.nodeType == 1 && p.tagName.toUpperCase() != 'HTML') {
				pn.unshift(p);
			}
			var cn = hnode;
			for (var i = 0, len = pn.length; i < len; i++) {
				cn.expand();
				cn = cn.findChild('htmlNode', pn[i]);
				if (!cn) {
					return false;
				}
			}
			cn.select();
			var a = cn.ui.anchor;
			treeEl.dom.scrollTop = Math.max(0, a.offsetTop - 10);
			cn.highlight();
			return true;
		}

		function nodeTitle(n) {
			var s = n.tagName;
			if (n.id) {
				s += '#' + n.id;
			} else if (n.className) {
				s += '.' + n.className;
			}
			return s;
		}

		function onNodeSelect(t, n, last) {
			return;
			if (last && last.unframe) {
				last.unframe();
			}
			var props = {};
			if (n && n.htmlNode) {
				if (frameEl.pressed) {
					n.frame();
				}
				if (inspecting) {
					return;
				}
				addStyle.enable();
				reload.setDisabled(n.leaf);
				var dom = n.htmlNode;
				stylePanel.setTitle(nodeTitle(dom));
				if (styles && !showAll.pressed) {
					var s = dom.style ? dom.style.cssText: '';
					if (s) {
						var m;
						while ((m = styleRe.exec(s)) != null) {
							props[m[1].toLowerCase()] = m[2];
						}
					}
				} else if (styles) {
					var cl = Ext.debug.cssList;
					var s = dom.style,
					fly = Ext.fly(dom);
					if (s) {
						for (var i = 0, len = cl.length; i < len; i++) {
							var st = cl[i];
							var v = s[st] || fly.getStyle(st);
							if (v != undefined && v !== null && v !== '') {
								props[st] = v;
							}
						}
					}
				} else {
					for (var a in dom) {
						var v = dom[a];
						if ((isNaN(a + 10)) && v != undefined && v !== null && v !== '' && !(Ext.isGecko && a[0] == a[0].toUpperCase())) {
							props[a] = v;
						}
					}
				}
			} else {
				if (inspecting) {
					return;
				}
				addStyle.disable();
				reload.disabled();
			}
			stylesGrid.setSource(props);
			stylesGrid.treeNode = n;
			stylesGrid.view.fitColumns();
		}

		this.loader = new Ext.tree.TreeLoader();
		this.loader.load = function(n, cb) {
			var isBody = n.htmlNode == document.body;
			var cn = n.htmlNode.childNodes;
			for (var i = 0, c; c = cn[i]; i++) {
				if (isBody && c.id == 'x-debug-browser') {
					continue;
				}
				if (c.nodeType == 1) {
					n.appendChild(new Ext.debug.HtmlNode(c));
				} else if (c.nodeType == 3 && !nonSpace.test(c.nodeValue)) {
					n.appendChild(new Ext.tree.TreeNode({
						text: '<em>' + ellipsis(html(String(c.nodeValue)), 35) + '</em>',
						cls: 'x-tree-noicon'
					}));
				}
			}
			cb();
		};

		this.root = this.setRootNode(new Ext.tree.TreeNode('Ext'));

		hnode = this.root.appendChild(new Ext.debug.HtmlNode(document.getElementsByTagName('html')[0]));

	}
});

Ext.debug.HtmlNode = function() {
	var html = Ext.util.Format.htmlEncode;
	var ellipsis = Ext.util.Format.ellipsis;
	var nonSpace = /^\s*$/;

	var attrs = [{
		n: 'id',
		v: 'id'
	},
	{
		n: 'className',
		v: 'class'
	},
	{
		n: 'name',
		v: 'name'
	},
	{
		n: 'type',
		v: 'type'
	},
	{
		n: 'src',
		v: 'src'
	},
	{
		n: 'href',
		v: 'href'
	}];

	function hasChild(n) {
		for (var i = 0, c; c = n.childNodes[i]; i++) {
			if (c.nodeType == 1) {
				return true;
			}
		}
		return false;
	}

	function renderNode(n, leaf) {
		var tag = n.tagName.toLowerCase();
		var s = '&lt;' + tag;
		for (var i = 0, len = attrs.length; i < len; i++) {
			var a = attrs[i];
			var v = n[a.n];
			if (v && !nonSpace.test(v)) {
				s += ' ' + a.v + '=&quot;<i>' + html(v) + '</i>&quot;';
			}
		}
		var style = n.style ? n.style.cssText: '';
		if (style) {
			s += ' style=&quot;<i>' + html(style.toLowerCase()) + '</i>&quot;';
		}
		if (leaf && n.childNodes.length > 0) {
			s += '&gt;<em>' + ellipsis(html(String(n.innerHTML)), 35) + '</em>&lt;/' + tag + '&gt;';
		} else if (leaf) {
			s += ' /&gt;';
		} else {
			s += '&gt;';
		}
		return s;
	}

	var HtmlNode = function(n) {
		var leaf = !hasChild(n);
		this.htmlNode = n;
		this.tagName = n.tagName.toLowerCase();
		var attr = {
			text: renderNode(n, leaf),
			leaf: leaf,
			cls: 'x-tree-noicon'
		};
		HtmlNode.superclass.constructor.call(this, attr);
		this.attributes.htmlNode = n;
		if (!leaf) {
			this.on('expand', this.onExpand, this);
			this.on('collapse', this.onCollapse, this);
		}
	};

	Ext.extend(HtmlNode, Ext.tree.AsyncTreeNode, {
		cls: 'x-tree-noicon',
		preventHScroll: true,
		refresh: function(highlight) {
			var leaf = !hasChild(this.htmlNode);
			this.setText(renderNode(this.htmlNode, leaf));
			if (highlight) {
				Ext.fly(this.ui.textNode).highlight();
			}
		},

		onExpand: function() {
			if (!this.closeNode && this.parentNode) {
				this.closeNode = this.parentNode.insertBefore(new Ext.tree.TreeNode({
					text: '&lt;/' + this.tagName + '&gt;',
					cls: 'x-tree-noicon'
				}), this.nextSibling);
			} else if (this.closeNode) {
				this.closeNode.ui.show();
			}
		},

		onCollapse: function() {
			if (this.closeNode) {
				this.closeNode.ui.hide();
			}
		},

		render: function(bulkRender) {
			HtmlNode.superclass.render.call(this, bulkRender);
		},

		highlightNode: function() {},

		highlight: function() {},

		frame: function() {
			this.htmlNode.style.border = '1px solid #0000ff';
		},

		unframe: function() {
			this.htmlNode.style.border = '';
		}
	});

	return HtmlNode;
}();
//<script>
/*
 * German translation
 * By schmidetzki and humpdi
 * 04-07-2007
 * Updated by wm003 10-31-2007
 */

Ext.UpdateManager.defaults.indicatorText = '<div class="loading-indicator">Ãœbertrage Daten ...</div>';

if(Ext.View){
   Ext.View.prototype.emptyText = "";
}

if(Ext.grid.Grid){
   Ext.grid.Grid.prototype.ddText = "{0} Zeile(n) ausgewÃ¤hlt";
}

if(Ext.TabPanelItem){
   Ext.TabPanelItem.prototype.closeText = "Diesen Tab schlieÃŸen";
}

if(Ext.form.Field){
   Ext.form.Field.prototype.invalidText = "Der Wert des Feldes ist nicht korrekt";
}

if(Ext.LoadMask){
  Ext.LoadMask.prototype.msg = "Ãœbertrage Daten...";
}

Date.monthNames = [
   "Januar",
   "Februar",
   "MÃ¤rz",
   "April",
   "Mai",
   "Juni",
   "Juli",
   "August",
   "September",
   "Oktober",
   "November",
   "Dezember"
];

Date.getShortMonthName = function(month) {
  return Date.monthNames[month].substring(0, 3);
};

Date.monthNumbers = {
  Jan : 0,
  Feb : 1,
  Mar : 2,
  Apr : 3,
  May : 4,
  Jun : 5,
  Jul : 6,
  Aug : 7,
  Sep : 8,
  Oct : 9,
  Nov : 10,
  Dec : 11
};

Date.getMonthNumber = function(name) {
  return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
};

Date.dayNames = [
   "Sonntag",
   "Montag",
   "Dienstag",
   "Mittwoch",
   "Donnerstag",
   "Freitag",
   "Samstag"
];

Date.getShortDayName = function(day) {
  return Date.dayNames[day].substring(0, 3);
};

if(Ext.MessageBox){
   Ext.MessageBox.buttonText = {
      ok     : "OK",
      cancel : "Abbrechen",
      yes    : "Ja",
      no     : "Nein"
   };
}

if(Ext.util.Format){
   Ext.util.Format.date = function(v, format){
      if(!v) return "";
      if(!(v instanceof Date)) v = new Date(Date.parse(v));
      return v.dateFormat(format || "d.m.Y");
   };
}

if(Ext.DatePicker){
   Ext.apply(Ext.DatePicker.prototype, {
      todayText         : "Heute",
      minText           : "Dieses Datum liegt von dem erstmÃ¶glichen Datum",
      maxText           : "Dieses Datum liegt nach dem letztmÃ¶glichen Datum",
      disabledDaysText  : "",
      disabledDatesText : "",
      monthNames	    : Date.monthNames,
      dayNames		    : Date.dayNames,
      nextText          : "NÃ¤chster Monat (Strg/Control + Rechts)",
      prevText          : "Vorheriger Monat (Strg/Control + Links)",
      monthYearText     : "Monat auswÃ¤hlen (Strg/Control + Hoch/Runter, um ein Jahr auszuwÃ¤hlen)",
      todayTip          : "Heute ({0}) (Leertaste)",
      format            : "d.m.Y",
      okText            : "&#160;OK&#160;",
      cancelText        : "Abbrechen",
      startDay          : 0
   });
}

if(Ext.PagingToolbar){
   Ext.apply(Ext.PagingToolbar.prototype, {
      beforePageText : "Seite",
      afterPageText  : "von {0}",
      firstText      : "Erste Seite",
      prevText       : "vorherige Seite",
      nextText       : "nÃ¤chste Seite",
      lastText       : "letzte Seite",
      refreshText    : "Aktualisieren",
      displayMsg     : "Anzeige Eintrag {0} - {1} von {2}",
      emptyMsg       : "Keine Daten vorhanden"
   });
}

if(Ext.form.TextField){
   Ext.apply(Ext.form.TextField.prototype, {
      minLengthText : "Bitte geben Sie mindestens {0} Zeichen ein",
      maxLengthText : "Bitte geben Sie maximal {0} Zeichen ein",
      blankText     : "Dieses Feld darf nicht leer sein",
      regexText     : "",
      emptyText     : null
   });
}

if(Ext.form.NumberField){
   Ext.apply(Ext.form.NumberField.prototype, {
      minText : "Der Mindestwert fÃ¼r dieses Feld ist {0}",
      maxText : "Der Maximalwert fÃ¼r dieses Feld ist {0}",
      nanText : "{0} ist keine Zahl"
   });
}

if(Ext.form.DateField){
   Ext.apply(Ext.form.DateField.prototype, {
      disabledDaysText  : "nicht erlaubt",
      disabledDatesText : "nicht erlaubt",
      minText           : "Das Datum in diesem Feld muÃŸ nach dem {0} liegen",
      maxText           : "Das Datum in diesem Feld muÃŸ vor dem {0} liegen",
      invalidText       : "{0} ist kein valides Datum - es muÃŸ im Format {1} eingegeben werden",
      format            : "d.m.Y",
      altFormats        : "d.m.Y|d/m/Y|d-m-y|d-m-Y|d/m|d-m|dm|dmy|dmY|d|Y-m-d"
   });
}

if(Ext.form.ComboBox){
   Ext.apply(Ext.form.ComboBox.prototype, {
      loadingText       : "Lade Daten ...",
      valueNotFoundText : undefined
   });
}

if(Ext.form.VTypes){
   Ext.apply(Ext.form.VTypes, {
      emailText    : 'Dieses Feld sollte eine E-Mail-Adresse enthalten. Format: "user@domain.com"',
      urlText      : 'Dieses Feld sollte eine URL enthalten. Format: "http:/'+'/www.domain.com"',
      alphaText    : 'Dieses Feld darf nur Buchstaben enthalten und _',
      alphanumText : 'Dieses Feld darf nur Buchstaben und Zahlen enthalten und _'
   });
}

if(Ext.form.HtmlEditor){
  Ext.apply(Ext.form.HtmlEditor.prototype, {
    createLinkText : 'Bitte geben Sie die URL fÃ¼r den Link ein:',
    buttonTips : {
      bold : {
        title: 'Fett (Ctrl+B)',
        text: 'Erstellt den ausgewÃ¤hlten Text in Fettschrift.',
        cls: 'x-html-editor-tip'
      },
      italic : {
        title: 'Kursiv (Ctrl+I)',
        text: 'Erstellt den ausgewÃ¤hlten Text in SchrÃ¤gschrift.',
        cls: 'x-html-editor-tip'
      },
      underline : {
        title: 'Unterstrichen (Ctrl+U)',
        text: 'Unterstreicht den ausgewÃ¤hlten Text.',
        cls: 'x-html-editor-tip'
      },
      increasefontsize : {
        title: 'Text vergÃ¶ÃŸern',
        text: 'ErhÃ¶ht die SchriftgrÃ¶ÃŸe.',
        cls: 'x-html-editor-tip'
      },
      decreasefontsize : {
        title: 'Text verkleinern',
        text: 'Verringert die SchriftgrÃ¶ÃŸe.',
        cls: 'x-html-editor-tip'
      },
      backcolor : {
        title: 'Text farblich hervorheben',
        text: 'Hintergrundfarbe des ausgewÃ¤hlten Textes Ã¤ndern.',
        cls: 'x-html-editor-tip'
      },
      forecolor : {
        title: 'Schriftfarbe',
        text: 'Farbe des ausgewÃ¤hlten Textes Ã¤ndern.',
        cls: 'x-html-editor-tip'
      },
      justifyleft : {
        title: 'LinksbÃ¼ndig',
        text: 'Setzt den Text linksbÃ¼ndig.',
        cls: 'x-html-editor-tip'
      },
      justifycenter : {
        title: 'Zentrieren',
        text: 'Zentriert den Text in Editor.',
        cls: 'x-html-editor-tip'
      },
      justifyright : {
        title: 'Align Text Right',
        text: 'Align text to the right.',
        cls: 'x-html-editor-tip'
      },
      insertunorderedlist : {
        title: 'AufzÃ¤hlungsliste',
        text: 'Beginnt eine AufzÃ¤hlungsliste mit Spiegelstrichen.',
        cls: 'x-html-editor-tip'
      },
      insertorderedlist : {
        title: 'Numerierte Liste',
        text: 'Beginnt eine numerierte Liste.',
        cls: 'x-html-editor-tip'
      },
      createlink : {
        title: 'Hyperlink',
        text: 'Erstellt einen Hyperlink aus dem ausgewÃ¤hlten text.',
        cls: 'x-html-editor-tip'
      },
      sourceedit : {
        title: 'Source bearbeiten',
        text: 'Zur Bearbeitung des Quelltextes wechseln.',
        cls: 'x-html-editor-tip'
      }
    }
  });
}

if(Ext.grid.GridView){
   Ext.apply(Ext.grid.GridView.prototype, {
      sortAscText  : "Aufsteigend sortieren",
      sortDescText : "Absteigend sortieren",
      lockText     : "Spalte sperren",
      unlockText   : "Spalte freigeben (entsperren)",
      columnsText  : "Spalten"
   });
}

if(Ext.grid.GroupingView){
  Ext.apply(Ext.grid.GroupingView.prototype, {
    emptyGroupText : '(Keine)',
    groupByText    : 'Dieses Feld gruppieren',
    showGroupsText : 'In Gruppen anzeigen'
  });
}

if(Ext.grid.PropertyColumnModel){
  Ext.apply(Ext.grid.PropertyColumnModel.prototype, {
      nameText   : "Name",
      valueText  : "Wert",
      dateFormat : "d.m.Y"
  });
}

if(Ext.layout.BorderLayout.SplitRegion){
  Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype, {
    splitTip            : "Ziehen, um GrÃ¶ÃŸe zu Ã¤ndern.",
    collapsibleSplitTip : "Ziehen, um GrÃ¶ÃŸe zu Ã¤ndern. Doppelklick um Panel auszublenden."
  });
}

ï»¿//<script> ext-ux.js
/*
	Achtung: 
		- overrides, die mit dem Kommentar "//FIX" versehen sind mÃ¼ssen bei einem
		  Versions-Update von Ext Ã¼berprÃ¼ft werden !!!
		    * Ob sich das override inzwischen vielleicht erÃ¼brigt.
		    * Ob Ã„nderungen des Originalcodes in den kopierten Code des Overrides zu Ã¼bernehmen sind !!!! 
		- In overrides zum Fixen von Problemen sollten die geÃ¤nderten Stellen
		  nach MÃ¶glichkeit kenntlich gemacht werden.
*/

Ext.namespace("Ext.ux");


/**	Funktionen zur besseren Handhabung von Vererbung,
	speziell den Zugriff auf den eigenen Typ und die Basisklasse
	@author jtoland
	@version 1.1
	@see http://extjs.com/forum/showthread.php?t=27019
 */
(function() {
	function init( mixer, space, base ) {
		var o = {self : space, config : mixer}, autoConstructor;
		if (typeof space == 'string') {
			Ext.ns(space);
			if (base) { autoConstructor = base; space += '=function(){autoConstructor.apply(this, arguments);}'; }
			o.self = eval(space);
		}
		if (typeof mixer == 'function') { o.config = base ? mixer(base.prototype, o.self) : mixer(o.self); }
		if (autoConstructor && o.config.Constructor) {
			autoConstructor = o.config.Constructor;
			delete o.config.Constructor;
		}
		if (o.self.prototype && o.self !== space && !o.config.ctype) {
			o.config.ctype = !autoConstructor ? space : space.substring(0, space.lastIndexOf('='));
		}
		return o;
	}
	
	/**
	 * intended to wrap module files
	 * @param {String/Object} module value automatically namespaced
	 * @param {Function/Object} mixin passed single argument of module expected to return Object
	 * @param {Function} callback (optional) called after mixin has been applied to module
	 * @param {Object} scope (optional) of the callback defaults to module
	 * @return {Object} module
	 *//*
	 * <code>
	 * Ext.ux.applyMixin('Ext.ux.application', function( $module ) { return {
	 *     //application methods and properties
	 *     init : function() {}
	 * }; }, function() { Ext.onReady(this.init); });
	 * </code>
	 */
	Ext.ux.applyMixin = function( module, mixin, callback, scope ) {
		var args = init(mixin, module);
		Ext.apply(module = args.self, mixin = args.config);
		if (callback) { callback.call(scope || module); }
		return module;
	};
	
	/**
	 * intended to wrap class files
	 * @param {String/Function} subclass value automatically namespaced
	 * @param {Function} superclass
	 * @param {Function/Object} mixin passed subclass and superclass.prototype expected to return Object
	 * @param {Function} callback (optional) called after mixin has been applied to module
	 * @param {Object} scope (optional) of the callback defaults to subclass
	 * @param {String} xtype (optional) final String argument registers xtype
	 * @return {Function} subclass
	 *//*
	 * <code>
	 * Ext.ux.extend('Ext.ux.NewClass', Ext.Superclass, function( $super, $class ) { return {
	 *     Constructor : function() {
	 *     //...
	 *         $super.constructor.apply(this, arguments);
	 *     //...
	 *     }
	 * }; }, 'xtype');
	 * </code>
	 */
	Ext.ux.extend = function( subclass, superclass, mixin, callback, scope ) {
		var args = init(mixin, subclass, superclass);
		Ext.extend(subclass = args.self, superclass, mixin = args.config);
		if (typeof callback == 'function') { callback.call(typeof scope == 'object' ? scope : subclass); }
		var xtype = arguments[arguments.length - 1];
		if (arguments.length > 3 && typeof xtype == 'string') { Ext.reg(xtype, subclass); }
		return subclass;
	};
})();


/**	Ein paar Ã„nderungen an den Einstellungen fÃ¼r den ScrollManager */
Ext.dd.ScrollManager.animate=false;
Ext.dd.ScrollManager.increment=50;
Ext.dd.ScrollManager.frequency=50;
Ext.dd.ScrollManager.frequency=50;
Ext.dd.ScrollManager.hthresh=30;
Ext.dd.ScrollManager.vthresh=30;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**	Resourcen-Url aus Resourcenamen */
Ext.ux.resourceUrl = function(resName, assemblyName, timeStamp)
{
	return  url="res.ashx?Res="+resName
					   +"&t="+(timeStamp || 0)
					   +"&"+(assemblyName ? "Assembly="+assemblyName : "");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**	Clone Function */
Ext.ux.clone = function(o)
{
    if('object' !== typeof o)
         return o;
 
    var c = 'function' === typeof o.pop ? [] : {};
    var p, v;
    for(p in o)
    {
        if(o.hasOwnProperty(p))
        {
            v = o[p];
            if(null != v && 'object' === typeof v)
                c[p] = Ext.ux.clone(v);
            else
                c[p] = v;
        }
    }
    return c;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Dictionary from Array Funktion */
Ext.ux.dictFromArray = function(arr, keyName)
{
	var ret={};
	for(var i=0; i<arr.length; i++)
		ret[arr[i][keyName]]=arr[i];
	return ret;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Encoding Funktionen */
Ext.apply(Ext.util.Format,
{
	scriptEncode: function(value)
	{
		return !value ? value :  String(value).replace(/(\\|'|")/g, "\\$1").replace(/\n/g, "\\n").replace(/\r/g, "\\r");
	},

	//FIX - um Singlequote erweitert
	htmlEncode: function(value)
	{
		return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
	},

	//FIX - um Singlequote erweitert
	htmlDecode: function(value)
	{
		return !value ? value : String(value).replace(/&amp;/g, "&").replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&#39;|#[xX]27;/g, "'");
	},
	
	sqlEncode: function(value)
	{
		return !value ? value : String(value).replace(/'/g, "''");
	}
});

/** Shortcuts */
Ext.apply(Ext, {
	he:Ext.util.Format.htmlEncode,
	se:Ext.util.Format.scriptEncode,
	ue:Ext.urlEncode,
	sqle:Ext.util.Format.sqlEncode
});
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Erweiterungen/Fixes fÃ¼r CellSelectionModel */
Ext.override(Ext.grid.CellSelectionModel, {
	//FIX - gibt im Original nur "selection.cell" zurÃ¼ck, sollte mal laut Doku (2.1) "selection" zurÃ¼ckgeben,
	//		inzwischen ist die Doku angepasst, aber wir lassen das hier so, weil das viel praktischer ist
	getSelectedCell : function(){
        return this.selection ? this.selection : null;
    }	
});

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Fix fÃ¼r Ext.form.Checkbox; */
Ext.override(Ext.form.Checkbox, {
    //FIX - Checkbox.getValue() liefert jetzt, wenn noch nicht gerendert, den Wert von Checkbox.checked */
    getValue: function()
    {
        if (this.rendered)
        {
            return this.el.dom.checked;
        }
        return this.checked;
    }
});
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Erweiterungen von TreeNode */
Ext.override(Ext.tree.TreeNode, {
	
	/** entfernt recursiv alle childNodes, wenn true Ã¼bergeben wird auch sich selbst noch*/
	clear: function(removeThisNode)
	{
		for(var i=this.childNodes.length-1; i>=0; i--)
			this.childNodes[i].clear(true);
			
		if(removeThisNode)
			this.remove();
	},
	/** vereinfachter Zugriff auf die additional-Attribute eines Nodes (lesen und schreiben)*/
	additional: function(key, value)
	{
		if(typeof value!='undefined')
		{
			if(!this.attributes.additional)
				this.attributes.additional={};
			this.attributes.additional[key]=value;
		}
		
		return this.attributes.additional && this.attributes.additional[key];
	},
	/** hat im TreeNode keine Funktion (nur wegen KompatibilitÃ¤t zu AsyncTreeNode) */
	ensureLoaded: Ext.emptyFn
});
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Erweiterungsfunktionen fÃ¼r AsyncTreeNode */
Ext.override(Ext.tree.AsyncTreeNode, {
	/** Stellt sicher, dass childNodes aus dem JSON oder von der Remotequelle geladen sind
		(nÃ¼tzlich und wichtig z.B. vor appendChild an einem asynchronen Knoten)
	*/
	ensureLoaded: function(callback)
	{
		if(!this.loaded && !this.loading)
		{
			if(this.fireEvent("beforeload", this) === false){
                return;
            }
            this.loading = true;
            this.ui.beforeLoad(this);
            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
            if(loader){
                loader.load(this, this.ensureLoadComplete.createDelegate(this, [callback]));
                return;
            }
		}
	},
	ensureLoadComplete: function(callback)
	{
		this.loading = false;
        this.loaded = true;
        this.ui.afterLoad(this);
        this.fireEvent("load", this);
        if(callback)
			callback();
	}
});

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** Dieses Plugin stellt noch ein Event "nodedragoverext" fÃ¼r Drag-Over in Trees bereit,
	mit dem die css-Klasse fÃ¼r den Proxy an der Maus modifiziert werden kann.
	Der Handler wird aufgerufen mit den Argumenten (n, dd, e, data, tree, defaultClass)
	und muss die zu verwendende css-Classe zurÃ¼ckgeben.
*/
Ext.ux.NodeDragOverExtPlugIn = function()
{
	this.savedOriginalNodeDragOverFn=null;
	
	this.init = function(tree)
	{
		var _this=this;
		tree.initEvents=tree.initEvents.createSequence(function()
		{
			if(tree.dropZone)
			{
				_this.savedOriginalNodeDragOverFn=tree.dropZone.onNodeOver;
				
				tree.addEvents(
					'nodedragoverext'
				);
				
				tree.dropZone.onNodeOver=function(n, dd, e, data)
				{
					// das Original aufrufen
					var ret=_this.savedOriginalNodeDragOverFn.apply(tree.dropZone, arguments); 
					
					var args=["nodedragoverext"];
					
					for(var i=0; i<arguments.length; i++)
						args.push(arguments[i])
					
					var o={
						tree:this.tree,
						target:n.node,
						data:data,
						source:dd,
						rawEvent:e,
						dropNode:data.node,
						cssClass:ret
					}  
										
					tree.fireEvent.call(tree, "nodedragoverext", o);
					ret=o.cssClass;
		
					return ret;
				}
			}
		}, _this);
	}
}

/** MixIn - Stellt die Hilfsmethode "ajaxCheck" fÃ¼r die erbende Klasse bereit */
Ext.ux.AjaxChecker = {
	/** Kappselt die eigentlichen Callback-Funktionen und ...
		- macht im Fehlerfall automatisch Meldung (alert) und blockt die AusfÃ¼hrung der eigentlichen CallbackFn !!!
		- managed die Lademaske, wenn der Viewport mit dem Plug-In "Ext.ux.ViewPortMask" versehen ist.
		@param {function} fn Callback Funktion
		@param {string|bool} [maskText] optional der Anzuzeigende Text fÃ¼r die Lade-Maske oder false um die Maske nicht anzuzeigen
	*/
	ajaxCheck: function(fn, maskText, delay)
	{
		if(maskText!==false)
			Ext.ux.ViewPortMask.show(maskText, delay);
		return fn.createDelegate(this).createInterceptor(this.checkAjaxResponse, this);
	},
	
	/** @private */
	checkAjaxResponse: function(res)
	{
		Ext.ux.ViewPortMask.hide();
		if(res.error)
		{
			if(res.error.Type=="System.NotSupportedException" && res.error.Message=="This method is either not marked with an AjaxMethod or is not available.")
			{
				//die umgebende aspx-Seite einfach mal anfordern um die Kompilierung anzuschubsen
				//eventuelle Querystring Argumente werden entfernt und nur ein CacheBuster angehangen
				//(die Seite muss so nicht funktionieren - sie soll nur kompilieren) 
				(new Image()).src=location.href.replace(/\?.*/, "")+"?noCache="+((new Date()).getTime());
				
				alert("Die aufgerufene Methode ist nicht verfÃ¼gbar.\n\nDie Server-Anwendung wird neu initialisiert.\nBitte versuchen Sie die Aktion in einigen Sekunden erneut auszufÃ¼hren.");
			}
			else
				alert(res.error.Message);

			if(typeof this.afterAjaxRequest == 'function')
				this.afterAjaxRequest("Aktion mit Fehler abgebrochen", true);
			return false; // die den AjaxRequest abarbeitende Funktion wird nicht aufgerufen
		}
		else
			return true;
	}
}

/** Maskenplugin fÃ¼r den Viewport - gedacht zur einfachen globalen Nutzung */
Ext.ux.extend("Ext.ux.ViewPortMask", Object, function(Superclass, Class) { 
	// statische Member
	Ext.apply(Class, {
		maskCls:null,
		msgCls:null,
		defaultText:"Moment",
		defaultDelay:250, //VerzÃ¶gerung in ms
		showOnInit:false,
		disabled:false,
		maskBodyOnly:false,
		
		init: function(container)
		{
			Class.initialInit=function()
			{
				var el=null;
				if(Class.maskBodyOnly)
					el=container.body;
				if(!el)				
					var el=container.getEl();

				Class.loadMask=new Ext.LoadMask(el, {removeMask:false});
				if(Class.maskCls)
					el.addClass(Class.maskCls);

				delete Class.initialInit;
			}	
			//untested
			if(Class.showOnInit)
				(function() {Class.show(null, 1);}).defer(10);
			
		},
		
		prepare: function(config) // convenience function zum Defaultwerte belegen beim zuweisen ans Plug-In
		{
			Ext.apply(Class, config || {});
			return Class;
		},
		
		show: function(text, delay)
		{
			if(Class.initialInit)
				Class.initialInit();
			if(!Class.disabled && Class.loadMask)
			{
				Class.loadMask.msg="&nbsp;&nbsp;"+(text || Class.defaultText)+"&nbsp;...";
				if(Class.msgCls)
					Class.loadMask.msgCls=Class.msgClass;
				if(delay==null || delay<0)
					delay=Class.defaultDelay;
				
				var fn = function()
				{
					Ext.get(Ext.isIE ? document.body: document).on("dblclick", Class.hide, Class, {delay:10} );
					Class.loadMask.show();
				}
				
				if(delay>0)
					Class.cancelId=fn.defer(delay);
				else
					fn();
			}
		},
		
		hide: function()
		{
			if(!Class.disabled && Class.loadMask)
			{
				if(Class.cancelId)
					window.clearTimeout(Class.cancelId);
				
				Ext.get(Ext.isIE ? document.body: document).un("dblclick", Class.hide);
				Class.loadMask.hide();
			}
		}
	});
	return {
		//nichts hier, weil nur statische Member			
	}
});

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** 
	TreeNodeUI-Subclass fÃ¼r die Anzeige beliebiger Icons am TreeNode - mit und ohne Status
	
	@class Ext.ux.ActionsTreeNodeUI
	@extends TreeNodeUI
	
	Verwendung:
		- dem TreeNode den uiProvider Ext.ux.ActionsTreeNodeUI zuweisen und
		  unter attributes noch ein Array mit Actions-Objekten anfÃ¼gen
		- nicht vergesse dem TreeLoader (falls async) den UI-Provider bekanntzugeben uiProviders:{..., "Ext.ux.ActionsTreeNodeUI":Ext.ux.ActionsTreeNodeUI}
		- am TreeNode oder am Tree gibts dann die Events ([action] ist der Name der Action):
			beforeactionclick_[action]
			actionclick_[action]
			beforeactionstatechange_[action]
			
	Hinweis:
		Im Namespace IDU.ASPNet.AjaxResult (WebControls) gibts volle serverseitige UnterstÃ¼tzung dafÃ¼r.
		Die Klasse ExtTreeNode benutzen und dort die Liste "actions" befÃ¼llen. (Intellisense hilft)
	
	Ein Actions-Objekt sieht so aus (Pflichtfelder haben einen *):
		placement:0,                  //  0 - BeforeText, 1 - AfterText
		action: "MeinActionName",     //* beliebiger Kurzname fÃ¼r die Aktion z.B. "info"
		changeableState:false,        //  oder true; legt fest, ob das nur ein "dummes" Bild ist oder beim Draufklicken der Status geÃ¤ndert wird
		iconCls: "ux-meinBildKlasse", //* css-Klasse fÃ¼r das Icon (wenn changeableState==true, dann ist das der ausgeschaltete Zustand)
		iconClsTripleState:null,      //  css-Klasse fÃ¼r das Folder im TripleState (nur wenn changeableState==true)
		iconClsSelected:null,         //  css-Klasse fÃ¼r das Icon im Zustand angeschaltet (nur wenn changeableState==true)
		state:0,                      //  0 - UnSelelected, 2 - Selected	
		tooltip: "mein Tooltipp"      //  anzuzeigender Tooltipp, wird nur angezeigt wenn Ext.QuickTips.init schon aufgerufen
		tooltipTitel:"Tooltipp-Titel" //  anzuzeigender Tooltipp-Titel, wird nur angezeigt wenn Ext.QuickTips.init schon aufgerufen
		
		
	Beispiel:
		new Ext.tree.TreeNode({
			id:1,
			text:"TestKnoten",
			uiProvider:Ext.ux.ActionsTreeNodeUI,
			attributes:{
				actions:[{
					action:"info",
					iconCls:"ux-info-icon"	
				}]
			},
			// listeners sollten vorzugsweise am Tree eingetragen werden (hier nur zur Demo)
			listeners:{
				actionclick_info:function(node) { alert(node.id); }
			}
		}
*/

Ext.ux.ActionsTreeNodeUI = function(node)
{
	Ext.ux.ActionsTreeNodeUI.superclass.constructor.call(this, node);

	if(!node.attributes.actions)
		var temp=[];
	else if(Ext.type(node.attributes.actions)!="array")
		var temp=[node.attributes.actions];
	else
		var temp=node.attributes.actions;
	
	//node.attributes.actions=Ext.ux.clone(temp); //tiefe Kopie!!!
	node.attributes.actions=temp;
	
	this.actions=node.attributes.actions;
	this.actionsMap={};
	for(var i=this.actions.length-1; i>=0; i--)
	{
		this.actions[i].initialized=node.text;
		if(this.actionsMap[this.actions[i].action])
			this.actions.splice(i, 1); // doppelte actions nicht zulassen
		else
		{
			var action=this.actionsMap[this.actions[i].action]=this.actions[i];
			
			action.state=action.state || 0; // Standardwert
			action.state=action.state==2 ? 2 : 0; // sicher stellen, dass nur 0 oder 2 drin steht
		
			if(action.changeableState)
				action.iconCls=[action.iconCls, action.iconClsTripleState, action.iconClsSelected];
			
			if(action.placement==0)
				action.placement="beforeText";
			else if(action.placement==1)
				action.placement="afterText";
		}
	}
	//node.addEvents(); ist nicht zwingend nÃ¶tig und in diesem Fall auch nicht gut mÃ¶glich, weil
	//					jede action eigene events feuert, die den action-Namen als Sufix haben.
		
	node.isActionsNode=true;
}

Ext.extend(Ext.ux.ActionsTreeNodeUI, Ext.tree.TreeNodeUI,
{
	initEvents : function()
	{
		Ext.ux.ActionsTreeNodeUI.superclass.initEvents.call(this);
		for(var k in this.actionsMap)
			if(this.actionsMap[k].dom)
				Ext.EventManager.on(this.actionsMap[k].dom, "click", this.actionClick.createDelegate(this, [k], true), null, true);
	
		var ot=this.node.getOwnerTree();
		if(!ot.actionsHandlerAssigned)
		{	
			ot.on("append", this.reflectChangesOnAppendRemove, this);
			ot.on("remove", this.reflectChangesOnAppendRemove, this);
			ot.actionsHandlerAssigned=true;
		}	
	},
	
	reflectChangesOnAppendRemove : function(tree, parentNode, childNode, idx)
	{
		if(Ext.ux.ActionsTreeNodeUI.isStateReflectionByEventSuspended(tree))
			return;
		
		Ext.ux.ActionsTreeNodeUI.suspendStateReflectionByEvent(tree);
		
		//TODO: evtl. mal machen, dass auch nach oben geupdated wird, wenn der direkte Parent
		//		kein ActionsTreeNodeUI ist
		if((!parentNode.isLoading || !parentNode.isLoading()) && childNode.isActionsNode && parentNode.isActionsNode)
		{
			
			for(var i=0; i<childNode.ui.actions.length; i++)
				parentNode.ui.reflectChildNodesActionState(childNode.ui.actions[i].action);
		}
		
		Ext.ux.ActionsTreeNodeUI.resumeStateReflectionByEvent(tree);
	},
		
	renderElements: function(n, a, targetNode, bulkRender)
	{
		Ext.ux.ActionsTreeNodeUI.superclass.renderElements.apply(this, arguments); // Methode der Basisklasse
		
		for(var i=this.actions.length-1; i>=0; i--)
		{
			var action=this.actions[i];
			var iconCls=action.changeableState ? action.iconCls[action.state] : action.iconCls;
			if(action.placement=="beforeText")
				action.dom=Ext.DomHelper.insertAfter(this.iconNode, '<img src="'+this.emptyIcon+'" class="'+iconCls+'" />');
			else // afterText
				action.dom=Ext.DomHelper.insertAfter(this.textNode, '<img src="'+this.emptyIcon+'" class="'+iconCls+'" />');
				
			//wenn ein Tooltipp definiert, diesen registrieren	
		    if( action.tooltip || action.tooltipTitle )
		    {
		        //nur wenn QuickTips initialisiert ist (Ext.QuickTips.init() muss im aufrufenden Program stehen)
		        if( Ext.QuickTips.getQuickTip() )
		        {
                    Ext.QuickTips.register({
                        target:  action.dom,
                        title: action.tooltipTitle,
                        text: action.tooltip,
                        enabled: true
                    });
                }
		    }
		}
	},
	
	destroy: function()
	{
		for(var i=0; i<this.actions.length; i++)
			delete this.actions[i].dom;
		
		Ext.ux.ActionsTreeNodeUI.superclass.destroy.apply(this, arguments); // Methode der Basisklasse
	},
	
	actionClick : function(e, targetEl, o, action)
	{
		e.stopEvent();
		
		if(this.node.disabled)
			return;

		if(this.fireEvent("beforeactionclick_"+action, this.node) === false)
			return;

		var state=this.actionsMap[action].state<2 ? 2 : 0;
		this.setActionState(action, state);

		this.fireEvent("actionclick_"+action, this.node);
	},
	
	setActionState : function(action, state, notificationConstraints)
	{
		if(this.actionsMap[action] && !this.actionsMap[action].changeableState)
			return;
				
	//	this.node.ensureLoaded();
		
		if(this.node.isLeaf())
			if(this.fireEvent("beforeactionstatechange_"+action, this.node, state)===false)
				return;
		
		notificationConstraints=notificationConstraints || {};
		
		var a=this.actionsMap[action];
		a.state=state;
		
		if(this.rendered)
			a.dom.className=a.iconCls[a.state];
		
		if(this.node.isLeaf())
			this.fireEvent("actionstatechange_"+action, this.node, state);

		//------------------------------------
		// setzen von children und parents
		//------------------------------------
		var _this=this;
		if(!notificationConstraints.suppressChildNodes && a.changeableState)
			this.node.cascade(function(n)
			{
				if(_this.node.id!=n.id)
				{
					if(n.isActionsNode/*n.getUI() instanceof Ext.ux.ActionsTreeNodeUI*/)
						n.getUI().setActionState(action, state, {suppressParentNodes:true, suppressChildNodes:true});
				}
			});
        
        if(!notificationConstraints.suppressParentNodes && a.changeableState)
			this.node.bubble(function(n)
			{
				if(_this.node.id!=n.id)
				{
					if(n.isActionsNode/*n.getUI() instanceof Ext.ux.ActionsTreeNodeUI*/)
					{
						n.getUI().reflectChildNodesActionState(action);
						return false; // beim ersten Parent abbrechen, der auch vom Typ Ext.ux.ActionsTreeNodeUI ist
					}
				}
			});
	},
	
	reflectChildNodesActionState : function(action, checkOnly)
	{
		if(this.actionsMap[action] && !this.actionsMap[action].changeableState)
			return;
		
		var expected=0;
		var achieved=0;
			
		for(var i=0; i<this.node.childNodes.length; i++)
		{
			//TODO: evtl. mal machen, dass nicht nur die direkten Kinder gecheckt werden, sonder alle
			//		(falls das performancetechnisch ertrÃ¤glich ist)
			var cn=this.node.childNodes[i];
			var ui=cn.getUI();
			if(cn.isActionsNode && !cn.disabled && ui.actionsMap[action])
			{
				expected+=2;
				if(!cn.isLeaf())
				{
					if(cn.ui.actionsMap[action].stateAcknowledged)
						achieved+=ui.actionsMap[action].state;
					else
						achieved+=cn.ui.reflectChildNodesActionState(action, true);	
				}
				else
					achieved+=ui.actionsMap[action].state;
			}
		}
		
		if(achieved==0)
			this.setActionState(action, 0, {suppressChildNodes:true, suppressParentNodes:checkOnly});
		else if(achieved==expected)
			this.setActionState(action, 2, {suppressChildNodes:true, suppressParentNodes:checkOnly});
		else
			this.setActionState(action, 1, {suppressChildNodes:true, suppressParentNodes:checkOnly});
	
		this.actionsMap[action].stateAcknowledged=true;
		return this.actionsMap[action].state;
	}
});

Ext.ux.ActionsTreeNodeUI.NodeActionState = {
    Selected: 2,
    Unselected: 0
}

//statische Methoden
Ext.apply(Ext.ux.ActionsTreeNodeUI, {
	getAllSelectedSubLeafesByAction : function(node, action)
	{
		var ret=[];
		this.cascade(function(n) 
		{
			if(n.isActionsNode/*n.getUI() instanceof Ext.ux.ActionsTreeNodeUI*/)
				if(n.isLeaf() && n.actionsMap[action].state==2)
					ret.push(n);
		});
		
		return ret;
	},
	suspendStateReflectionByEvent : function(ownerTree)
	{
		if(typeof ownerTree.suspendStateReflectionIndicator == 'undefined')
			ownerTree.suspendStateReflectionIndicator=0;
		
		ownerTree.suspendStateReflectionIndicator++;
	},
	resumeStateReflectionByEvent : function(ownerTree)
	{
		ownerTree.suspendStateReflectionIndicator--;
	},
	isStateReflectionByEventSuspended : function(ownerTree)
	{
		if(typeof ownerTree.suspendStateReflectionIndicator == 'undefined')
			ownerTree.suspendStateReflectionIndicator=0;

		return ownerTree.suspendStateReflectionIndicator>0;
	}
});

/**
 * Ext.ux.form.XCheckbox - checkbox with configurable submit values
 *
 * @author  Ing. Jozef Sakalos
 * @version $Id: Ext.ux.form.XCheckbox.js 82 2008-03-21 00:17:40Z jozo $
 * @date    10. February 2008
 *
 *
 * @license Ext.ux.form.XCheckbox is licensed under the terms of
 * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
 * that the code/component(s) do NOT become part of another Open Source or Commercially
 * licensed development library or toolkit without explicit permission.
 * 
 * License details: http://www.gnu.org/licenses/lgpl.html
 */

/*global Ext */

/**
  * @class Ext.ux.XCheckbox
  * @extends Ext.form.Checkbox
  */
Ext.ns('Ext.ux.form');
Ext.ux.form.XCheckbox = Ext.extend(Ext.form.Checkbox, {
     submitOffValue:'false'
    ,submitOnValue:'true'
	
	,getResizeEl: function() {
		return this.wrap;
	}
	
    ,onRender:function(ct) {

        this.inputValue = this.submitOnValue;

        // call parent
        Ext.ux.form.XCheckbox.superclass.onRender.apply(this, arguments);

        // create hidden field that is submitted if checkbox is not checked
        this.hiddenField = this.wrap.insertFirst({tag:'input', type:'hidden'});

        // update value of hidden field
        this.updateHidden();

    } // eo function onRender

    /**
     * Calls parent and updates hiddenField
     * @private
     */
    ,setValue:function(v) {
        var checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
        this.updateHidden(checked);
        Ext.ux.form.XCheckbox.superclass.setValue.apply(this, arguments);
    } // eo function setValue

    /**
     * Updates hiddenField
     * @private
     */
    ,updateHidden:function(checked) {
        checked = checked !== undefined ? checked : this.checked;
        if(this.hiddenField) {
            this.hiddenField.dom.value = checked ? this.submitOnValue : this.submitOffValue;
            this.hiddenField.dom.name = checked ? '' : this.el.dom.name;
        }
    } // eo function updateHidden

}); // eo extend

// register xtype
Ext.reg('xcheckbox', Ext.ux.form.XCheckbox);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
	@class Ext.ux.form.BigTextField
	Einzeiliges Textfeld mit Trigger fÃ¼r groÃŸe Texte (Ã¶ffnet Dialog fÃ¼r die Texteingabe).
	Besonders geeignet als Edit-Feld in Grids oder anderswo	
*/
Ext.ux.extend("Ext.ux.form.BigTextField", Ext.form.TriggerField, function(Superclass, Class) { 
	Ext.apply(Class, {
		defaultGridRenderer: function(v)
		{
			v=(v===0 ? String(v) : String(v||""));
			var lines=v.split("\n");
			return Ext.he(lines[0]+(lines.length>1 ? " ..." : ""));
		}
	});
	return {
		triggerClass: 'x-form-general-trigger',
		selectOnFocus:false,
		defaultAutoCreate: {
			tag: "input",
			autocomplete: "off",
			style:"height:21px; overflow:hidden;",
			wrap:"off",
			readonly:true
		},
		
		getDefaultGridRenderer: function()
		{
			return Class.defaultGridRenderer;
		},
			
		onDestroy: function()
		{
			if(Class.dialog)
				Class.dialog.destroy();
			
			delete Class.dialog;
			delete Class.textFieldId;
			delete Class.setValueCallback;
			
			Superclass.onDestroy.apply(this, arguments);
		},
		
		onRender: function()
		{
			Class.superclass.onRender.apply(this, arguments);
			this.getEl().on("click", this.onTriggerClick, this);
		},
		
		validateBlur: function(e)
		{
			if(Class.dialog && Class.dialog.isVisible())
				return false;
			else
				return true;
		},
			
		onTriggerClick: function()
		{
			if (this.disabled)
				return;
			
			var value=this.getValue();
			var _this=this;
			
			//nur *eine* Instanz des Hilfsfensters in einer statischen Variable zur Klasse speichern
			if(!Class.dialog)
			{
				Class.textFieldId=Ext.id();
				Class.dialog = new Ext.Window({
					title:'',
					width:400,
					height:400,
					closeAction:'hide',
					plain: false,
					resizable:false,
					modal:true,
					items:{
						xtype:"textarea",
						id:Class.textFieldId,
						width:388,
						height:350,
						autoCreate:{
							tag:"textArea",
							autocomplete:"off",
							wrap:"off"
						},
						selectOnFocus:false,
						value:value
					},
					keys: [{
						key:27,
						handler:function() { Class.dialog.hide(); }
					}],
					buttons: [{
						text:' &nbsp; OK &nbsp; ',
						listeners:{
							click: function(btn, evt)
							{
								if(typeof Class.setValueCallback == 'function')
									Class.setValueCallback(Ext.getCmp(Class.textFieldId).getValue());
								//das setTimeout ist nur eine "kosmetische" Sache, damit das hide nicht vor dem validateBlur kommt
								window.setTimeout(function() {btn.ownerCt.hide();}, 100);
							},
							scope:this
						}
					},{
						text: 'Abbrechen',
						handler: function(btn, evt)
						{
							//das setTimeout ist nur eine "kosmetische" Sache, damit das hide nicht vor dem validateBlur kommt
							window.setTimeout(function() {btn.ownerCt.hide();}, 100);
						}
					}],
					listeners: {
						show:function() { (function() {Ext.getCmp(Class.textFieldId).getEl().dom.focus();}).defer(50); }
					}			
				});
			}
			
			Class.setValueCallback=this.setValue.createDelegate(this)
			var ta=Ext.getCmp(Class.textFieldId);
			if(ta)
				ta.setValue(value);
			
			Class.dialog.show();
		}
	}
});

/** Textfeld fÃ¼r Passworteingabe incl. vorbereitetem GridRenderer */
Ext.ux.extend("Ext.ux.form.PasswordField", Ext.form.TextField, function(Superclass, Class) {
	Ext.apply(Class, {
		defaultGridRenderer: function(v, r)
		{
			return String(v||"").replace(/./g, "&#x25CF;");
		}
	});
	return {
		selectOnFocus:true,
		inputType:"password",
		
		getDefaultGridRenderer: function()
		{
			return Class.defaultGridRenderer;
		}
	}
});

/** ComboBox fÃ¼r Bool Werte - speziell fÃ¼r den Einsatz in Grids */
Ext.ux.extend("Ext.ux.form.BoolComboBox", Ext.form.ComboBox, function(Superclass, Class) {
	Ext.apply(Class, {
		defaultGridRenderer: function(v, record)
		{
			return v===false || v==='false' ? 'nein' : (v===true || v==='true' ? 'ja' : '');
		}
	});
	return {
		store:[
			["", ""],
			["true", "ja"],
			["false", "nein"]
		],
		displayField:"text",
		triggerAction:'all',
		editable:false,
		tpl:'<tpl for="."><div class="x-combo-list-item">{text}&nbsp;</div></tpl>',
		
		getDefaultGridRenderer: function()
		{
			return Class.defaultGridRenderer;
		},
		
		setValue: function(v)
		{
			if(v===true || v==='true')
				Superclass.setValue.call(this, 'true');
			else if(v===false || v==='false')
				Superclass.setValue.call(this, 'false');
			else
				Superclass.setValue.call(this, '');
		},
		
		getValue: function()
		{
			var v=Superclass.getValue.call(this);
			if(v == 'true')
				return true;
			else if(v == 'false')
				return false;
			else
				return ''; // das finde ich nicht so schÃ¶n, weil nicht correct vom typ her, aber machen alle so
		}
	}
});

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Array-Prototyp-Erweiterung
//
Ext.apply(Array.prototype,
{
    /**
     * Vergleicht diesen Array mit dem Ã¼bergebenen Argument array auf Gleichhet der Elemente beider Arrays, also nicht nur auf Gleichheit der Referenzen.
     * @param {Object} array Der Vergleichs-Array
     */
	objectEquals: function(array)
	{
		if (array instanceof Array)
		{
			if (this === array)
			{
				return true;
			}
			
			if (this.length !== array.length)
			{
				return false;
			}
			
			var indices = [];
			for (var i = 0; i < this.length; i++)
			{
				var idx = -1;
				do
				{
					idx = this.objectIndexOf(array[i], idx+1);
					if (idx === -1)
					{
						return false;
					}					
				} while (indices[idx] !== undefined);
				
				indices[idx] = i;
			}
			
			return true;
		}
		return false;
	},
	
    /**
     * PrÃ¼ft, ob der Array das angegebene Objekt enthÃ¤lt.
     * @param {Object} obj
     */
	objectContains: function(obj)
	{
		return this.objectIndexOf(obj) !== -1;
	},
	
    /**
     * Gibt den Index des Ã¼bergebenen Objekts zurÃ¼ck, oder -1, wenn das Objekt nicht im Array enthalten ist.
     * Der Vergleich der Elemente dieses Arrays mit dem Ã¼bergebenen Objekt wird entweder mittels === oder falls vorhanden mittels equals() durchgefÃ¼hrt.
     * @param {Object} obj das zu prÃ¼fende Objekt.
     * @param {Object} startIndex der Index ab dem die Elemente verglichen werden sollen
     */
	objectIndexOf: function(obj, startIndex)
	{
		if (obj === undefined || obj === null)
		{
			return -1;
		}
		
		for (var i = (startIndex || 0); i < this.length; i++)
		{
			if (this[i] === obj || (this[i].equals && this[i].equals(obj)))
			{
				return i;
			}
		}
		return -1;
	}
});
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// die Funktion gabs mal in ExtJs1 und wird hier beibehalten, um "alten" Code direkt weiternutzen zu kÃ¶nnen
Ext.override(Ext.Element, {
	fitToParent : function(monitorResize, targetParent){
        var p = Ext.get(targetParent || this.dom.parentNode);
        this.setSize(p.getComputedWidth()-p.getFrameWidth('lr'), p.getComputedHeight()-p.getFrameWidth('tb'));
        if(monitorResize === true){
            Ext.EventManager.onWindowResize(this.fitToParent.createDelegate(this, []));
        }
        return this;
    }
})

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Fix fÃ¼r Checkbox
Ext.override(Ext.form.Checkbox, {
	//FIX
	setValue: function(v) {
		var checked = this.checked;
		this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');

		if (this.el && this.el.dom) {
			this.el.dom.checked = this.checked;
			this.el.dom.defaultChecked = this.checked;
		}
		if(this.wrap) //das if gabs vorher nicht
			this.wrap[this.checked ? 'addClass': 'removeClass'](this.checkedCls);

		if (checked != this.checked) {
			this.fireEvent("check", this, this.checked);
			if (this.handler) {
				this.handler.call(this.scope || this, this, this.checked);
			}
		}
	}
});

Ext.override(Ext.tree.TreeLoader, {
    //FIX
    doPreload: function(node) {
		if (node.attributes.children) {
			if (node.childNodes.length < 1) {
				var cs = node.attributes.children;
				node.beginUpdate();
				for (var i = 0, len = cs.length; i < len; i++) {
					var cn = node.appendChild(this.createNode(cs[i]));
					if (this.preloadChildren) {
						this.doPreload(cn);
					}
				}
				node.endUpdate();
			}
            node.loaded=true; //diese Zeile gabs vorher nicht
			return true;
		} else {
			return false;
		}
	}
})

Ext.override(Ext.tree.TreeEditor, {
	//FIX - sollte mit Version die neuer als Ext 2.2 sind gefixt sein und ist dann hier wieder zu entfernen
	triggerEdit: function(node, defer) {
		this.completeEdit();
		if (node.attributes.editable !== false) {

			this.editNode = node;
			if (this.tree.autoScroll) {
				var el=node.ui.getEl()
				//el.scrollIntoView(this.tree.body); //diese Zeile weg und statt dessen:
				this.tree.body.scrollChildIntoView(node.ui.getEl()); //diese Zeile hier
			}
			this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, node.text]);
			return false;
		}
	}
});

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// fixes fÃ¼rs BorderLayout (see: https://extjs.com/forum/showthread.php?p=212649)
Ext.override(Ext.layout.BorderLayout.Region, {
	//FIX
	render : function(ct, p){
		this.panel = p;
		p.el.enableDisplayMode();
		this.targetEl = ct;
		this.el = p.el;
		var gs = p.getState, ps = this.position;
		p.getState = function(){
			return Ext.apply(gs.call(p) || {}, this.state);
		}.createDelegate(this);
		if(ps != 'center'){
			p.allowQueuedExpand = false;
			p.on({
				beforecollapse: this.beforeCollapse,
				collapse: this.onCollapse,
				beforeexpand: this.beforeExpand,
				expand: this.onExpand,
				hide: this.onHide,
				show: this.onShow,
				scope: this
			});
			//if(this.collapsible){
			if(this.collapsible || this.floatable){
				p.collapseEl = 'el';
				p.slideAnchor = this.getSlideAnchor();
			}
			if(p.tools && p.tools.toggle){
				p.tools.toggle.addClass('x-tool-collapse-'+ps);
				p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
			}
		}
	},
	//FIX
	getCollapsedEl : function(){
		if(!this.collapsedEl){
			if(!this.toolTemplate){
				var tt = new Ext.Template(
					 '<div class="x-tool x-tool-{id}">&#160;</div>'
				);
				tt.disableFormats = true;
				tt.compile();
				Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
			}
			this.collapsedEl = this.targetEl.createChild({
				cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
				id: this.panel.id + '-xcollapsed'
			});
			this.collapsedEl.enableDisplayMode('block');

			if(this.collapseMode == 'mini'){
				this.collapsedEl.addClass('x-layout-cmini-'+this.position);
				if((this.collapsible !== false) && !this.hideCollapseTool) { //das if gabs vorher nicht
					this.miniCollapsedEl = this.collapsedEl.createChild({
						cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
					});
					this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
					this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
					this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
				}
			}else {
				if((this.collapsible !== false) && !this.hideCollapseTool) { //das if gabs vorher nicht
					var t = this.toolTemplate.append(
							this.collapsedEl.dom,
							{id:'expand-'+this.position}, true);
					t.addClassOnOver('x-tool-expand-'+this.position+'-over');
					t.on('click', this.onExpandClick, this, {stopEvent:true});
				}
				//if(this.floatable !== false) {
				if((this.floatable !== false) || this.titleCollapse) {
				   this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
				   //this.collapsedEl.on("click", this.collapseClick, this);
				   this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
				}
			}
		}
		return this.collapsedEl;
	}
});ï»¿//<script>

/**
	@class
	Global verfÃ¼gbare Instanz von <a href="EventObject.html">EventObject</a>
	@static
*/
glbEventObject = new EventObject();

/**
	@class
	EventObject (steht zum einen als <a href="glbEventObject.html">glbEventObject</a> global zur VerfÃ¼gung, kann aber auch von anderen "Klassen" als kontextgebundener EventManager instanziert werden).<br><br>
	Es ermÃ¶glicht lose gekoppelte Ereignisse bei der Kommunikation innerhalb von und zwischen Komponenten. FÃ¼r ein Ereignis kÃ¶nnen beliebig viele
	Handler registriert werden.
	<br>
	Ereignisse haben einen Namen (casesensitiver String). Ein AuslÃ¶ser ruft einfach <i>fireEvent</i> auf. Ist bereits ein Handler zu diesem
	Namen in der betreffenden EventObject-Instanz registriert, wird/werden die Callbackfunktion/en aufgerufen. Eine Komponente muss daher dokumentieren, welche Ereignisse ausgelÃ¶st werden,
	damit andere sich dafÃ¼r registrieren kÃ¶nnen.
	<br>
	FÃ¼r cancelable events (typischerweise sind dies onBeforeDoSomthing Ereignisse) sollte ein Cancel-Flag im EventArgument-Objekt angeboten
	und ausgewertet werden. Das PrÃ¼fen des RÃ¼ckgabewertes der Handlerfunktion ist auch mÃ¶glich, ist aber bei mehreren Handlern fÃ¼r ein Ereignis u.U.
	nicht gut zu handhaben.
	
	@constructor
*/
function EventObject()
{
	/**	@private
		ZÃ¤hler zur eindeutigen Vergabe von Handles, mit denen Ereignisse wieder unregistriert werden kÃ¶nnen.
		Wird hochgezÃ¤hlt und als Handle vergeben um releaseEvent() damit aufrufen zu kÃ¶nnen.
		@type int*/
	this.handleCounter=0;
	
	/**	@private
		Dictionary der Event-Abonnements (subscriptions)
		@type object
	*/
	this.events=new Object();
	
	/**
		LÃ¶st ein Event aus, d.h. alle auf <i>name</i> registrierten Handler werden in umgekehrter Reihenfolge ihrer Registrierung ausgefÃ¼hrt.<br>
		Events, die es erlauben die anstehende Aktion abzubrechen sollten mit "onBefore..." beginnen und im Event-Argument die Eigenschaft
		<i>cancel=false</i> bereitstellen, die von den Handlern bei Bedarf auf true gesetzt wird. Die Verwendung von <i>stopOnNegativeReturn</i>
		kann ebenfalls in Betracht gezogen werden.
		
		@param {string} name Name des Events
		@param {object} obj EventArgs-Objekt, welches der Callbackfunktion Ã¼bergeben wird
		@param {bool} [stopOnNegativeReturn] Bei true wird die Verarbeitung weiterer registrierter Handler abgebrochen, sobald der RÃ¼ckgabewert einer Callbackfunktion gleich false ist.
											 (Ereignisse, die dies nutzen sollten mit onBefore... beginnen.)
		@returns {bool/object} RÃ¼ckgabewert der als letztes ausgefÃ¼hrten Callback-Funktion
	*/		
	this.fireEvent = function(name, obj, stopOnNegativeReturn)
	{
		var ret;
		var arr=this.events[name];
		if(typeof(arr)!='object')
			return true; // keine Events registriert
		for(var i=arr.length-1; i>=0; i--) // Events werden in umgekehrter Reihenfolge ausgefÃ¼hrt
		{
	//		try
	//		{
				if(arr[i].executionContext)
					ret=arr[i].fnPtr.call(arr[i].executionContext, obj, arr[i].arg);
					// dadurch findet man sich in der Methode bereits wieder im richtigen
					// AusfÃ¼hrungskontext und kann mit this.XYZ weiteroperieren
				else
					ret=arr[i].fnPtr(obj, arr[i].arg);
					
				if(stopOnNegativeReturn && ret === false)
					return ret;		
	//		}
	//		catch(err)
	//		{
	//			return true; // nichts tun - auÃŸer true zurÃ¼ckgeben fÃ¼r onBefore... Events
				//alert(err.description+'\n\nUngÃ¼ltiger Funktionszeiger in Eventobjekt\n\nHandel: '+arr[i].handle);
	//		}
		}
		return ret;
	}
	
	/**
		registriert einen Eventhandler
		@param {string} name casesensitiver Name des Events, fÃ¼r das die Registrierung erflogt
		@param {function} fnPtr Callbackfunktion mit der Signatur: <i>{bool} function(object eventArgs[, object customArgs])</i> (bei onBefore... Events muss true zurÃ¼ckgegeben werden, damit die Bearbeitung fortgesetzt wird)
		@param {object} [customArg] optionales Objekt, welches im Ereignisfall der Callbackfunktion als zweites Argument (<i>customArgs</i>) Ã¼bergeben wird
		@param {object} [scope] optionales Objekt, welches als AusfÃ¼hrungskontext (this) fÃ¼r die Callbackfunktion dienen soll
		@returns {int} releaseHandle (zur Verwendung mit releaseEvent)
	*/
	this.attachEvent = function(name, fnPtr, customArg, scope/*fÃ¼r Methoden eines Objektes*/)
	{
		if(typeof(this.events[name])=='undefined')
			this.events[name]=new Array();
		var arr=this.events[name];
		var handle=this.handleCounter++;
		arr[arr.length]={fnPtr:fnPtr, arg:customArg, handle:handle, executionContext:scope};
		return handle;
	}
	
	/**
		Hebt eine Event-Registrierung mit Hilfe der bei der Registrierung erhaltenen Kennung wieder auf.
		@param {int} handle Kennung (handle) des Event-Handlers, der abgemeldet werden soll. 
	*/
	this.releaseEvent = function(handle)
	{
		var i;
		for(var e in this.events)
		{
			arr=this.events[e];
			for(i=arr.length-1; i>=0; i--) // rÃ¼ckwÃ¤rts gehen, weil evtl. Elemente entfernt werden
				if(arr[i].handle==handle)
				{
					// hier nicht arr nehmen, weil es eine neue Zuweisung ist
					this.events[e]=arr.slice(0,i).concat(arr.slice(i+1,arr.length));
					return;
				}
		}	
	}
}

// Ende EventObject