(function (undefined) {
	function getValueFromArray(key, index, m, format) {
		var lang = m.lang();
		return lang[key].call ? lang[key](m, format) : lang[key][index]
	}
	function padToken(func, count) {
		return function (a) {
			return leftZeroFill(func.call(this, a), count)
		}
	}
	function ordinalizeToken(func) {
		return function (a) {
			var b = func.call(this, a);
			return b + this.lang().ordinal(b)
		}
	}
	function Moment(date, isUTC, lang) {
		this._d = date;
		this._isUTC = !!isUTC;
		this._a = date._a || null;
		this._lang = lang || false
	}
	function Duration(duration) {
		var data = this._data = {};
		var years = duration.years || duration.y || 0;
		var months = duration.months || duration.M || 0;
		var weeks = duration.weeks || duration.w || 0;
		var days = duration.days || duration.d || 0;
		var hours = duration.hours || duration.h || 0;
		var minutes = duration.minutes || duration.m || 0;
		var seconds = duration.seconds || duration.s || 0;
		var milliseconds = duration.milliseconds || duration.ms || 0;
		this._milliseconds = milliseconds + seconds * 1E3 + minutes * 6E4 + hours * 36E5;
		this._days = days + weeks * 7;
		this._months = months + years * 12;
		data.milliseconds = milliseconds % 1E3;
		seconds += absRound(milliseconds / 1E3);
		data.seconds = seconds % 60;
		minutes += absRound(seconds / 60);
		data.minutes = minutes % 60;
		hours += absRound(minutes / 60);
		data.hours = hours % 24;
		days += absRound(hours / 24);
		days += weeks * 7;
		data.days = days % 30;
		months += absRound(days / 30);
		data.months = months % 12;
		years += absRound(months / 12);
		data.years = years;
		this._lang = false
	}
	function absRound(number) {
		if (number < 0)
			return Math.ceil(number);
		else
			return Math.floor(number)
	}
	function leftZeroFill(number, targetLength) {
		for (var output = number + ""; output.length <
			targetLength; )
			output = "0" + output;
		return output
	}
	function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
		var ms = duration._milliseconds;
		var d = duration._days;
		var M = duration._months;
		var currentDate;
		if (ms)
			mom._d.setTime(+mom + ms * isAdding);
		if (d)
			mom.date(mom.date() + d * isAdding);
		if (M) {
			currentDate = mom.date();
			mom.date(1).month(mom.month() + M * isAdding).date(Math.min(currentDate, mom.daysInMonth()))
		}
	}
	function isArray(input) {
		return Object.prototype.toString.call(input) === "[object Array]"
	}
	function compareArrays(array1,
		array2) {
		var len = Math.min(array1.length, array2.length);
		var lengthDiff = Math.abs(array1.length - array2.length);
		var diffs = 0;
		var i;
		for (i = 0; i < len; i++)
			if (~~array1[i] !== ~~array2[i])
				diffs++;
		return diffs + lengthDiff
	}
	function dateFromArray(input, asUTC, hoursOffset, minutesOffset) {
		var i;
		var date;
		var forValid = [];
		for (i = 0; i < 7; i++)
			forValid[i] = input[i] = input[i] == null ? i === 2 ? 1 : 0 : input[i];
		input[7] = forValid[7] = asUTC;
		if (input[8] != null)
			forValid[8] = input[8];
		input[3] += hoursOffset || 0;
		input[4] += minutesOffset || 0;
		date = new Date(0);
		if (asUTC) {
			date.setUTCFullYear(input[0], input[1], input[2]);
			date.setUTCHours(input[3], input[4], input[5], input[6])
		} else {
			date.setFullYear(input[0], input[1], input[2]);
			date.setHours(input[3], input[4], input[5], input[6])
		}
		date._a = forValid;
		return date
	}
	function loadLang(key, values) {
		var i;
		var m;
		var parse = [];
		if (!values && hasModule)
			values = require("./lang/" + key);
		for (i = 0; i < langConfigProperties.length; i++)
			values[langConfigProperties[i]] = values[langConfigProperties[i]] || languages.en[langConfigProperties[i]];
		for (i = 0; i <
			12; i++) {
			m = moment([2E3, i]);
			parse[i] = new RegExp("^" + (values.months[i] || values.months(m, "")) + "|^" + (values.monthsShort[i] || values.monthsShort(m, "")).replace(".", ""), "i")
		}
		values.monthsParse = values.monthsParse || parse;
		languages[key] = values;
		return values
	}
	function getLangDefinition(m) {
		var langKey = typeof m === "string" && m || m && m._lang || null;
		return langKey ? languages[langKey] || loadLang(langKey) : moment
	}
	function removeFormattingTokens(input) {
		if (input.match(/\[.*\]/))
			return input.replace(/^\[|\]$/g, "");
		return input.replace(/\\/g,
			"")
	}
	function makeFormatFunction(format) {
		var array = format.match(formattingTokens);
		var i;
		var length;
		for (i = 0, length = array.length; i < length; i++)
			if (formatTokenFunctions[array[i]])
				array[i] = formatTokenFunctions[array[i]];
			else
				array[i] = removeFormattingTokens(array[i]);
		return function (mom) {
			var output = "";
			for (i = 0; i < length; i++)
				output += typeof array[i].call === "function" ? array[i].call(mom, format) : array[i];
			return output
		}
	}
	function formatMoment(m, format) {
		function replaceLongDateFormatTokens(input) {
			return m.lang().longDateFormat[input] ||
			input
		}
		for (var i = 5; i-- && localFormattingTokens.test(format); )
			format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
		if (!formatFunctions[format])
			formatFunctions[format] = makeFormatFunction(format);
		return formatFunctions[format](m)
	}
	function getParseRegexForToken(token) {
		switch (token) {
		case "DDDD":
			return parseTokenThreeDigits;
		case "YYYY":
			return parseTokenFourDigits;
		case "S":
		case "SS":
		case "SSS":
		case "DDD":
			return parseTokenOneToThreeDigits;
		case "MMM":
		case "MMMM":
		case "dd":
		case "ddd":
		case "dddd":
		case "a":
		case "A":
			return parseTokenWord;
		case "Z":
		case "ZZ":
			return parseTokenTimezone;
		case "T":
			return parseTokenT;
		case "MM":
		case "DD":
		case "YY":
		case "HH":
		case "hh":
		case "mm":
		case "ss":
		case "M":
		case "D":
		case "d":
		case "H":
		case "h":
		case "m":
		case "s":
			return parseTokenOneOrTwoDigits;
		default:
			return new RegExp(token.replace("\\", ""))
		}
	}
	function addTimeToArrayFromToken(token, input, datePartArray, config) {
		var a;
		var b;
		switch (token) {
		case "M":
		case "MM":
			datePartArray[1] = input == null ? 0 : ~~input - 1;
			break;
		case "MMM":
		case "MMMM":
			for (a = 0; a < 12; a++)
				if (getLangDefinition().monthsParse[a].test(input)) {
					datePartArray[1] =
						a;
					b = true;
					break
				}
			if (!b)
				datePartArray[8] = false;
			break;
		case "D":
		case "DD":
		case "DDD":
		case "DDDD":
			if (input != null)
				datePartArray[2] = ~~input;
			break;
		case "YY":
			datePartArray[0] = ~~input + (~~input > 70 ? 1900 : 2E3);
			break;
		case "YYYY":
			datePartArray[0] = ~~Math.abs(input);
			break;
		case "a":
		case "A":
			config.isPm = (input + "").toLowerCase() === "pm";
			break;
		case "H":
		case "HH":
		case "h":
		case "hh":
			datePartArray[3] = ~~input;
			break;
		case "m":
		case "mm":
			datePartArray[4] = ~~input;
			break;
		case "s":
		case "ss":
			datePartArray[5] = ~~input;
			break;
		case "S":
		case "SS":
		case "SSS":
			datePartArray[6] =
				~~(("0." + input) * 1E3);
			break;
		case "Z":
		case "ZZ":
			config.isUTC = true;
			a = (input + "").match(parseTimezoneChunker);
			if (a && a[1])
				config.tzh = ~~a[1];
			if (a && a[2])
				config.tzm = ~~a[2];
			if (a && a[0] === "+") {
				config.tzh = -config.tzh;
				config.tzm = -config.tzm
			}
			break
		}
		if (input == null)
			datePartArray[8] = false
	}
	function makeDateFromStringAndFormat(string, format) {
		var datePartArray = [0, 0, 1, 0, 0, 0, 0];
		var config = {
			tzh : 0,
			tzm : 0
		};
		var tokens = format.match(formattingTokens);
		var i;
		var parsedInput;
		for (i = 0; i < tokens.length; i++) {
			parsedInput = (getParseRegexForToken(tokens[i]).exec(string) ||
				[])[0];
			if (parsedInput)
				string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
			if (formatTokenFunctions[tokens[i]])
				addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config)
		}
		if (config.isPm && datePartArray[3] < 12)
			datePartArray[3] += 12;
		if (config.isPm === false && datePartArray[3] === 12)
			datePartArray[3] = 0;
		return dateFromArray(datePartArray, config.isUTC, config.tzh, config.tzm)
	}
	function makeDateFromStringAndArray(string, formats) {
		var output;
		var inputParts = string.match(parseMultipleFormatChunker) ||
			[];
		var formattedInputParts;
		var scoreToBeat = 99;
		var i;
		var currentDate;
		var currentScore;
		for (i = 0; i < formats.length; i++) {
			currentDate = makeDateFromStringAndFormat(string, formats[i]);
			formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
			currentScore = compareArrays(inputParts, formattedInputParts);
			if (currentScore < scoreToBeat) {
				scoreToBeat = currentScore;
				output = currentDate
			}
		}
		return output
	}
	function makeDateFromString(string) {
		var format = "YYYY-MM-DDT";
		var i;
		if (isoRegex.exec(string)) {
			for (i =
					0; i < 4; i++)
				if (isoTimes[i][1].exec(string)) {
					format += isoTimes[i][0];
					break
				}
			return parseTokenTimezone.exec(string) ? makeDateFromStringAndFormat(string, format + " Z") : makeDateFromStringAndFormat(string, format)
		}
		return new Date(string)
	}
	function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
		var rt = lang.relativeTime[string];
		return typeof rt === "function" ? rt(number || 1, !!withoutSuffix, string, isFuture) : rt.replace(/%d/i, number || 1)
	}
	function relativeTime(milliseconds, withoutSuffix, lang) {
		var seconds = round(Math.abs(milliseconds) /
				1E3);
		var minutes = round(seconds / 60);
		var hours = round(minutes / 60);
		var days = round(hours / 24);
		var years = round(days / 365);
		var args = seconds < 45 && ["s", seconds] || minutes === 1 && ["m"] || minutes < 45 && ["mm", minutes] || hours === 1 && ["h"] || hours < 22 && ["hh", hours] || days === 1 && ["d"] || days <= 25 && ["dd", days] || days <= 45 && ["M"] || days < 345 && ["MM", round(days / 30)] || years === 1 && ["y"] || ["yy", years];
		args[2] = withoutSuffix;
		args[3] = milliseconds > 0;
		args[4] = lang;
		return substituteTimeAgo.apply({}, args)
	}
	function makeGetterAndSetter(name, key) {
		moment.fn[name] =
		function (input) {
			var utc = this._isUTC ? "UTC" : "";
			if (input != null) {
				this._d["set" + utc + key](input);
				return this
			} else
				return this._d["get" + utc + key]()
		}
	}
	function makeDurationGetter(name) {
		moment.duration.fn[name] = function () {
			return this._data[name]
		}
	}
	function makeDurationAsGetter(name, factor) {
		moment.duration.fn["as" + name] = function () {
			return +this / factor
		}
	}
	var moment;
	var VERSION = "1.7.2";
	var round = Math.round;
	var i$$0;
	var languages = {};
	var currentLanguage = "en";
	var hasModule = typeof module !== "undefined" && module.exports;
	var langConfigProperties = "months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|");
	var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
	var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g;
	var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g;
	var parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi;
	var parseTokenOneOrTwoDigits = /\d\d?/;
	var parseTokenOneToThreeDigits = /\d{1,3}/;
	var parseTokenThreeDigits = /\d{3}/;
	var parseTokenFourDigits = /\d{1,4}/;
	var parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i;
	var parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i;
	var parseTokenT = /T/i;
	var isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/;
	var isoFormat = "YYYY-MM-DDTHH:mm:ssZ";
	var isoTimes = [["HH:mm:ss.S", /T\d\d:\d\d:\d\d\.\d{1,3}/], ["HH:mm:ss", /T\d\d:\d\d:\d\d/], ["HH:mm", /T\d\d:\d\d/], ["HH", /T\d\d/]];
	var parseTimezoneChunker = /([\+\-]|\d\d)/gi;
	var proxyGettersAndSetters = "Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|");
	var unitMillisecondFactors = {
		"Milliseconds" : 1,
		"Seconds" : 1E3,
		"Minutes" : 6E4,
		"Hours" : 36E5,
		"Days" : 864E5,
		"Months" : 2592E6,
		"Years" : 31536E6
	};
	var formatFunctions = {};
	var ordinalizeTokens = "DDD w M D d".split(" ");
	var paddedTokens = "M D H h m s w".split(" ");
	for (var formatTokenFunctions = {
			M : function () {
				return this.month() + 1
			},
			MMM : function (format) {
				return getValueFromArray("monthsShort", this.month(),
					this, format)
			},
			MMMM : function (format) {
				return getValueFromArray("months", this.month(), this, format)
			},
			D : function () {
				return this.date()
			},
			DDD : function () {
				var a = new Date(this.year(), this.month(), this.date());
				var b = new Date(this.year(), 0, 1);
				return ~~((a - b) / 864E5 + 1.5)
			},
			d : function () {
				return this.day()
			},
			dd : function (format) {
				return getValueFromArray("weekdaysMin", this.day(), this, format)
			},
			ddd : function (format) {
				return getValueFromArray("weekdaysShort", this.day(), this, format)
			},
			dddd : function (format) {
				return getValueFromArray("weekdays",
					this.day(), this, format)
			},
			w : function () {
				var a = new Date(this.year(), this.month(), this.date() - this.day() + 5);
				var b = new Date(a.getFullYear(), 0, 4);
				return ~~((a - b) / 864E5 / 7 + 1.5)
			},
			YY : function () {
				return leftZeroFill(this.year() % 100, 2)
			},
			YYYY : function () {
				return leftZeroFill(this.year(), 4)
			},
			a : function () {
				return this.lang().meridiem(this.hours(), this.minutes(), true)
			},
			A : function () {
				return this.lang().meridiem(this.hours(), this.minutes(), false)
			},
			H : function () {
				return this.hours()
			},
			h : function () {
				return this.hours() % 12 || 12
			},
			m : function () {
				return this.minutes()
			},
			s : function () {
				return this.seconds()
			},
			S : function () {
				return ~~(this.milliseconds() / 100)
			},
			SS : function () {
				return leftZeroFill(~~(this.milliseconds() / 10), 2)
			},
			SSS : function () {
				return leftZeroFill(this.milliseconds(), 3)
			},
			Z : function () {
				var a = -this.zone();
				var b = "+";
				if (a < 0) {
					a = -a;
					b = "-"
				}
				return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2)
			},
			ZZ : function () {
				var a = -this.zone();
				var b = "+";
				if (a < 0) {
					a = -a;
					b = "-"
				}
				return b + leftZeroFill(~~(10 * a / 6), 4)
			}
		}; ordinalizeTokens.length; ) {
		i$$0 = ordinalizeTokens.pop();
		formatTokenFunctions[i$$0 + "o"] = ordinalizeToken(formatTokenFunctions[i$$0])
	}
	for (; paddedTokens.length; ) {
		i$$0 = paddedTokens.pop();
		formatTokenFunctions[i$$0 + i$$0] = padToken(formatTokenFunctions[i$$0], 2)
	}
	formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
	moment = function (input, format) {
		if (input === null || input === "")
			return null;
		var date;
		var matched;
		if (moment.isMoment(input))
			return new Moment(new Date(+input._d), input._isUTC, input._lang);
		else if (format)
			if (isArray(format))
				date = makeDateFromStringAndArray(input,
						format);
			else
				date = makeDateFromStringAndFormat(input, format);
		else {
			matched = aspNetJsonRegex.exec(input);
			date = input === undefined ? new Date : matched ? new Date(+matched[1]) : input instanceof Date ? input : isArray(input) ? dateFromArray(input) : typeof input === "string" ? makeDateFromString(input) : new Date(input)
		}
		return new Moment(date)
	};
	moment.utc = function (input, format) {
		if (isArray(input))
			return new Moment(dateFromArray(input, true), true);
		if (typeof input === "string" && !parseTokenTimezone.exec(input)) {
			input += " +0000";
			if (format)
				format +=
				" Z"
		}
		return moment(input, format).utc()
	};
	moment.unix = function (input) {
		return moment(input * 1E3)
	};
	moment.duration = function (input, key) {
		var isDuration = moment.isDuration(input);
		var isNumber = typeof input === "number";
		var duration = isDuration ? input._data : isNumber ? {}

		 : input;
		var ret;
		if (isNumber)
			if (key)
				duration[key] = input;
			else
				duration.milliseconds = input;
		ret = new Duration(duration);
		if (isDuration)
			ret._lang = input._lang;
		return ret
	};
	moment.humanizeDuration = function (num, type, withSuffix) {
		return moment.duration(num, type ===
			true ? null : type).humanize(type === true ? true : withSuffix)
	};
	moment.version = VERSION;
	moment.defaultFormat = isoFormat;
	moment.lang = function (key, values) {
		var i;
		if (!key)
			return currentLanguage;
		if (values || !languages[key])
			loadLang(key, values);
		if (languages[key]) {
			for (i = 0; i < langConfigProperties.length; i++)
				moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]];
			moment.monthsParse = languages[key].monthsParse;
			currentLanguage = key
		}
	};
	moment.langData = getLangDefinition;
	moment.isMoment = function (obj) {
		return obj instanceof
		Moment
	};
	moment.isDuration = function (obj) {
		return obj instanceof Duration
	};
	moment.lang("en", {
		months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
		monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
		weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
		weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
		weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
		longDateFormat : {
			LT : "h:mm A",
			L : "MM/DD/YYYY",
			LL : "MMMM D YYYY",
			LLL : "MMMM D YYYY LT",
			LLLL : "dddd, MMMM D YYYY LT"
		},
		meridiem : function (hours, minutes, isLower) {
			if (hours > 11)
				return isLower ? "pm" : "PM";
			else
				return isLower ? "am" : "AM"
		},
		calendar : {
			sameDay : "[Today at] LT",
			nextDay : "[Tomorrow at] LT",
			nextWeek : "dddd [at] LT",
			lastDay : "[Yesterday at] LT",
			lastWeek : "[last] dddd [at] LT",
			sameElse : "L"
		},
		relativeTime : {
			future : "in %s",
			past : "%s ago",
			s : "a few seconds",
			m : "a minute",
			mm : "%d minutes",
			h : "an hour",
			hh : "%d hours",
			d : "a day",
			dd : "%d days",
			M : "a month",
			MM : "%d months",
			y : "a year",
			yy : "%d years"
		},
		ordinal : function (number) {
			var b = number % 10;
			return ~~(number % 100 / 10) === 1 ? "th" : b === 1 ? "st" : b === 2 ? "nd" : b === 3 ? "rd" : "th"
		}
	});
	moment.fn = Moment.prototype = {
		clone : function () {
			return moment(this)
		},
		valueOf : function () {
			return +this._d
		},
		unix : function () {
			return Math.floor(+this._d / 1E3)
		},
		toString : function () {
			return this._d.toString()
		},
		toDate : function () {
			return this._d
		},
		toArray : function () {
			var m = this;
			return [m.year(), m.month(), m.date(), m.hours(), m.minutes(), m.seconds(), m.milliseconds(), !!this._isUTC]
		},
		isValid : function () {
			if (this._a) {
				if (this._a[8] !=
					null)
					return !!this._a[8];
				return !compareArrays(this._a, (this._a[7] ? moment.utc(this._a) : moment(this._a)).toArray())
			}
			return !isNaN(this._d.getTime())
		},
		utc : function () {
			this._isUTC = true;
			return this
		},
		local : function () {
			this._isUTC = false;
			return this
		},
		format : function (inputString) {
			return formatMoment(this, inputString ? inputString : moment.defaultFormat)
		},
		add : function (input, val) {
			var dur = val ? moment.duration(+val, input) : moment.duration(input);
			addOrSubtractDurationFromMoment(this, dur, 1);
			return this
		},
		subtract : function (input,
			val) {
			var dur = val ? moment.duration(+val, input) : moment.duration(input);
			addOrSubtractDurationFromMoment(this, dur, -1);
			return this
		},
		diff : function (input, val, asFloat) {
			var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local();
			var zoneDiff = (this.zone() - inputMoment.zone()) * 6E4;
			var diff = this._d - inputMoment._d - zoneDiff;
			var year = this.year() - inputMoment.year();
			var month = this.month() - inputMoment.month();
			var date = this.date() - inputMoment.date();
			var output;
			if (val === "months")
				output = year * 12 + month + date / 30;
			else if (val === "years")
				output = year + (month + date / 30) / 12;
			else
				output = val === "seconds" ? diff / 1E3 : val === "minutes" ? diff / 6E4 : val === "hours" ? diff / 36E5 : val === "days" ? diff / 864E5 : val === "weeks" ? diff / 6048E5 : diff;
			return asFloat ? output : round(output)
		},
		from : function (time, withoutSuffix) {
			return moment.duration(this.diff(time)).lang(this._lang).humanize(!withoutSuffix)
		},
		fromNow : function (withoutSuffix) {
			return this.from(moment(), withoutSuffix)
		},
		calendar : function () {
			var diff = this.diff(moment().sod(), "days", true);
			var calendar =
				this.lang().calendar;
			var allElse = calendar.sameElse;
			var format = diff < -6 ? allElse : diff < -1 ? calendar.lastWeek : diff < 0 ? calendar.lastDay : diff < 1 ? calendar.sameDay : diff < 2 ? calendar.nextDay : diff < 7 ? calendar.nextWeek : allElse;
			return this.format(typeof format === "function" ? format.apply(this) : format)
		},
		isLeapYear : function () {
			var year = this.year();
			return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0
		},
		isDST : function () {
			return this.zone() < moment([this.year()]).zone() || this.zone() < moment([this.year(), 5]).zone()
		},
		day : function (input) {
			var day =
				this._isUTC ? this._d.getUTCDay() : this._d.getDay();
			return input == null ? day : this.add({
				d : input - day
			})
		},
		startOf : function (val) {
			switch (val.replace(/s$/, "")) {
			case "year":
				this.month(0);
			case "month":
				this.date(1);
			case "day":
				this.hours(0);
			case "hour":
				this.minutes(0);
			case "minute":
				this.seconds(0);
			case "second":
				this.milliseconds(0)
			}
			return this
		},
		endOf : function (val) {
			return this.startOf(val).add(val.replace(/s?$/, "s"), 1).subtract("ms", 1)
		},
		sod : function () {
			return this.clone().startOf("day")
		},
		eod : function () {
			return this.clone().endOf("day")
		},
		zone : function () {
			return this._isUTC ? 0 : this._d.getTimezoneOffset()
		},
		daysInMonth : function () {
			return moment.utc([this.year(), this.month() + 1, 0]).date()
		},
		lang : function (lang) {
			if (lang === undefined)
				return getLangDefinition(this);
			else {
				this._lang = lang;
				return this
			}
		}
	};
	for (i$$0 = 0; i$$0 < proxyGettersAndSetters.length; i$$0++)
		makeGetterAndSetter(proxyGettersAndSetters[i$$0].toLowerCase(), proxyGettersAndSetters[i$$0]);
	makeGetterAndSetter("year", "FullYear");
	moment.duration.fn = Duration.prototype = {
		weeks : function () {
			return absRound(this.days() /
				7)
		},
		valueOf : function () {
			return this._milliseconds + this._days * 864E5 + this._months * 2592E6
		},
		humanize : function (withSuffix) {
			var difference = +this;
			var rel = this.lang().relativeTime;
			var output = relativeTime(difference, !withSuffix, this.lang());
			var fromNow = difference <= 0 ? rel.past : rel.future;
			if (withSuffix)
				if (typeof fromNow === "function")
					output = fromNow(output);
				else
					output = fromNow.replace(/%s/i, output);
			return output
		},
		lang : moment.fn.lang
	};
	for (i$$0 in unitMillisecondFactors)
		if (unitMillisecondFactors.hasOwnProperty(i$$0)) {
			makeDurationAsGetter(i$$0,
				unitMillisecondFactors[i$$0]);
			makeDurationGetter(i$$0.toLowerCase())
		}
	makeDurationAsGetter("Weeks", 6048E5);
	if (hasModule)
		module.exports = moment;
	if (typeof ender === "undefined")
		this["moment"] = moment;
	if (typeof define === "function" && define.amd)
		define("moment", [], function () {
			return moment
		})
}).call(this);
String.prototype.endsWith = function (suffix) {
	return this.indexOf(suffix, this.length - suffix.length) !== -1
};
String.prototype.contains = function (val) {
	return this.indexOf(val) >= 0
};
window.undefined = window.undefined;
Ext = {
	version : "3.4.0",
	versionDetail : {
		major : 3,
		minor : 4,
		patch : 0
	}
};
Ext.apply = function (d, e, b) {
	if (b)
		Ext.apply(d, b);
	if (d && e && typeof e == "object")
		for (var a in e)
			d[a] = e[a];
	return d
};
(function () {
	var g = 0;
	var u = Object.prototype.toString;
	var v = navigator.userAgent.toLowerCase();
	var A = function (e) {
		return e.test(v)
	};
	var i = document;
	var n = i.documentMode;
	var l = i.compatMode == "CSS1Compat";
	var C = A(/opera/);
	var h = A(/\bchrome\b/);
	var w = A(/webkit/);
	var z = !h && A(/safari/);
	var f = z && A(/applewebkit\/4/);
	var b = z && A(/version\/3/);
	var D = z && A(/version\/4/);
	var t = !C && A(/msie/);
	var r = t && (A(/msie 7/) || n == 7);
	var q = t && A(/msie 8/) && n != 7;
	var p = t && A(/msie 9/);
	var s = t && !r && !q && !p;
	var o = !w && A(/gecko/);
	var d = o &&
		A(/rv:1\.8/);
	var a = o && A(/rv:1\.9/);
	var x = t && !l;
	var B = A(/windows|win32/);
	var k = A(/macintosh|mac os x/);
	var j = A(/adobeair/);
	var m = A(/linux/);
	var c = /^https/i.test(window.location.protocol);
	if (s)
		try {
			i.execCommand("BackgroundImageCache", false, true)
		} catch (y) {}

	Ext.apply(Ext, {
		SSL_SECURE_URL : c && t ? 'javascript:""' : "about:blank",
		isStrict : l,
		isSecure : c,
		isReady : false,
		enableForcedBoxModel : false,
		enableGarbageCollector : true,
		enableListenerCollection : false,
		enableNestedListenerRemoval : false,
		USE_NATIVE_JSON : false,
		applyIf : function (E,
			F) {
			if (E)
				for (var e in F)
					if (!Ext.isDefined(E[e]))
						E[e] = F[e];
			return E
		},
		id : function (e, E) {
			e = Ext.getDom(e, true) || {};
			if (!e.id)
				e.id = (E || "ext-gen") + ++g;
			return e.id
		},
		extend : function () {
			var E = function (G) {
				for (var F in G)
					this[F] = G[F]
			};
			var e = Object.prototype.constructor;
			return function (L, I, K) {
				if (typeof I == "object") {
					K = I;
					I = L;
					L = K.constructor != e ? K.constructor : function () {
						I.apply(this, arguments)
					}
				}
				var H = function () {};
				var J;
				var G = I.prototype;
				H.prototype = G;
				J = L.prototype = new H;
				J.constructor = L;
				L.superclass = G;
				if (G.constructor ==
					e)
					G.constructor = I;
				L.override = function (F) {
					Ext.override(L, F)
				};
				J.superclass = J.supr = function () {
					return G
				};
				J.override = E;
				Ext.override(L, K);
				L.extend = function (F) {
					return Ext.extend(L, F)
				};
				return L
			}
		}
		(),
		override : function (e, F) {
			if (F) {
				var E = e.prototype;
				Ext.apply(E, F);
				if (Ext.isIE && F.hasOwnProperty("toString"))
					E.toString = F.toString
			}
		},
		namespace : function () {
			var G = arguments.length;
			var H = 0;
			var E;
			var F;
			var e;
			var J;
			var I;
			for (var K; H < G; ++H) {
				e = arguments[H];
				J = arguments[H].split(".");
				K = window[J[0]];
				if (K === undefined)
					K = window[J[0]] = {};
				I = J.slice(1);
				E = I.length;
				for (F = 0; F < E; ++F)
					K = K[I[F]] = K[I[F]] || {}

			}
			return K
		},
		urlEncode : function (I, H) {
			var F;
			var E = [];
			var G = encodeURIComponent;
			Ext.iterate(I, function (e, J) {
				F = Ext.isEmpty(J);
				Ext.each(F ? e : J, function (K) {
					E.push("\x26", G(e), "\x3d", !Ext.isEmpty(K) && (K != e || !F) ? Ext.isDate(K) ? Ext.encode(K).replace(/"/g, "") : G(K) : "")
				})
			});
			if (!H) {
				E.shift();
				H = ""
			}
			return H + E.join("")
		},
		urlDecode : function (F, E) {
			if (Ext.isEmpty(F))
				return {};
			var I = {};
			var H = F.split("\x26");
			var J = decodeURIComponent;
			var e;
			var G;
			Ext.each(H, function (K) {
				K =
					K.split("\x3d");
				e = J(K[0]);
				G = J(K[1]);
				I[e] = E || !I[e] ? G : [].concat(I[e]).concat(G)
			});
			return I
		},
		urlAppend : function (e, E) {
			if (!Ext.isEmpty(E))
				return e + (e.indexOf("?") === -1 ? "?" : "\x26") + E;
			return e
		},
		toArray : function () {
			return t ? function (F, I, G, H) {
				H = [];
				var E = 0;
				for (var e = F.length; E < e; E++)
					H.push(F[E]);
				return H.slice(I || 0, G || H.length)
			}
			 : function (e, F, E) {
				return Array.prototype.slice.call(e, F || 0, E || e.length)
			}
		}
		(),
		isIterable : function (e) {
			if (Ext.isArray(e) || e.callee)
				return true;
			if (/NodeList|HTMLCollection/.test(u.call(e)))
				return true;
			return (typeof e.nextNode != "undefined" || e.item) && Ext.isNumber(e.length)
		},
		each : function (H, G, F) {
			if (Ext.isEmpty(H, true))
				return;
			if (!Ext.isIterable(H) || Ext.isPrimitive(H))
				H = [H];
			var E = 0;
			for (var e = H.length; E < e; E++)
				if (G.call(F || H[E], H[E], E, H) === false)
					return E
		},
		iterate : function (F, E, e) {
			if (Ext.isEmpty(F))
				return;
			if (Ext.isIterable(F)) {
				Ext.each(F, E, e);
				return
			} else if (typeof F == "object")
				for (var G in F)
					if (F.hasOwnProperty(G))
						if (E.call(e || F, G, F[G], F) === false)
							return
		},
		getDom : function (F, E) {
			if (!F || !i)
				return null;
			if (F.dom)
				return F.dom;
			else if (typeof F == "string") {
				var G = i.getElementById(F);
				if (G && t && E)
					if (F == G.getAttribute("id"))
						return G;
					else
						return null;
				return G
			} else
				return F
		},
		getBody : function () {
			return Ext.get(i.body || i.documentElement)
		},
		getHead : function () {
			var e;
			return function () {
				if (e == undefined)
					e = Ext.get(i.getElementsByTagName("head")[0]);
				return e
			}
		}
		(),
		removeNode : t && !q ? function () {
			var e;
			return function (E) {
				if (E && E.tagName != "BODY") {
					Ext.enableNestedListenerRemoval ? Ext.EventManager.purgeElement(E, true) : Ext.EventManager.removeAll(E);
					e =
						e || i.createElement("div");
					e.appendChild(E);
					e.innerHTML = "";
					delete Ext.elCache[E.id]
				}
			}
		}
		() : function (e) {
			if (e && e.parentNode && e.tagName != "BODY") {
				Ext.enableNestedListenerRemoval ? Ext.EventManager.purgeElement(e, true) : Ext.EventManager.removeAll(e);
				e.parentNode.removeChild(e);
				delete Ext.elCache[e.id]
			}
		},
		isEmpty : function (E, e) {
			return E === null || E === undefined || Ext.isArray(E) && !E.length || (!e ? E === "" : false)
		},
		isArray : function (e) {
			return u.apply(e) === "[object Array]"
		},
		isDate : function (e) {
			return u.apply(e) === "[object Date]"
		},
		isObject : function (e) {
			return !!e && Object.prototype.toString.call(e) === "[object Object]"
		},
		isPrimitive : function (e) {
			return Ext.isString(e) || Ext.isNumber(e) || Ext.isBoolean(e)
		},
		isFunction : function (e) {
			return u.apply(e) === "[object Function]"
		},
		isNumber : function (e) {
			return typeof e === "number" && isFinite(e)
		},
		isString : function (e) {
			return typeof e === "string"
		},
		isBoolean : function (e) {
			return typeof e === "boolean"
		},
		isElement : function (e) {
			return e ? !!e.tagName : false
		},
		isDefined : function (e) {
			return typeof e !== "undefined"
		},
		isOpera : C,
		isWebKit : w,
		isChrome : h,
		isSafari : z,
		isSafari3 : b,
		isSafari4 : D,
		isSafari2 : f,
		isIE : t,
		isIE6 : s,
		isIE7 : r,
		isIE8 : q,
		isIE9 : p,
		isGecko : o,
		isGecko2 : d,
		isGecko3 : a,
		isBorderBox : x,
		isLinux : m,
		isWindows : B,
		isMac : k,
		isAir : j
	});
	Ext.ns = Ext.namespace
})();
Ext.ns("Ext.util", "Ext.lib", "Ext.data", "Ext.supports");
Ext.elCache = {};
Ext.apply(Function.prototype, {
	createInterceptor : function (b, a) {
		var c = this;
		return !Ext.isFunction(b) ? this : function () {
			var e = this;
			var d = arguments;
			b.target = e;
			b.method = c;
			return b.apply(a || e || window, d) !== false ? c.apply(e || window, d) : null
		}
	},
	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 (Ext.isNumber(a)) {
				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 > 0)
			return setTimeout(d, c);
		d();
		return 0
	}
});
Ext.applyIf(String, {
	format : function (b) {
		var a = Ext.toArray(arguments, 1);
		return b.replace(/\{(\d+)\}/g, function (c, d) {
			return a[d]
		})
	}
});
Ext.applyIf(Array.prototype, {
	indexOf : function (b, c) {
		var a = this.length;
		c = c || 0;
		for (c += c < 0 ? a : 0; c < a; ++c)
			if (this[c] === b)
				return c;
		return -1
	},
	remove : function (b) {
		var a = this.indexOf(b);
		if (a != -1)
			this.splice(a, 1);
		return this
	}
});
Ext.util.TaskRunner = function (e) {
	e = e || 10;
	var f = [];
	var a = [];
	var b = 0;
	var g = false;
	var d = function () {
		g = false;
		clearInterval(b);
		b = 0
	};
	var h = function () {
		if (!g) {
			g = true;
			b = setInterval(i, e)
		}
	};
	var c = function (j) {
		a.push(j);
		if (j.onStop)
			j.onStop.apply(j.scope || j)
	};
	var i = function () {
		var l = a.length;
		var n = (new Date).getTime();
		if (l > 0) {
			for (var p = 0; p < l; p++)
				f.remove(a[p]);
			a = [];
			if (f.length < 1) {
				d();
				return
			}
		}
		p = 0;
		var o;
		var k;
		var m;
		for (var j = f.length; p < j; ++p) {
			o = f[p];
			k = n - o.taskRunTime;
			if (o.interval <= k) {
				m = o.run.apply(o.scope || o, o.args ||
						[++o.taskRunCount]);
				o.taskRunTime = n;
				if (m === false || o.taskRunCount === o.repeat) {
					c(o);
					return
				}
			}
			if (o.duration && o.duration <= n - o.taskStartTime)
				c(o)
		}
	};
	this.start = function (j) {
		f.push(j);
		j.taskStartTime = (new Date).getTime();
		j.taskRunTime = 0;
		j.taskRunCount = 0;
		h();
		return j
	};
	this.stop = function (j) {
		c(j);
		return j
	};
	this.stopAll = function () {
		d();
		var k = 0;
		for (var j = f.length; k < j; k++)
			if (f[k].onStop)
				f[k].onStop();
		f = [];
		a = []
	}
};
Ext.TaskMgr = new Ext.util.TaskRunner;
(function () {
	function c(d) {
		if (!b)
			b = new Ext.Element.Flyweight;
		b.dom = d;
		return b
	}
	var b;
	(function () {
		var g = document;
		var e = g.compatMode == "CSS1Compat";
		var f = Math.max;
		var d = Math.round;
		var h = parseInt;
		Ext.lib.Dom = {
			isAncestor : function (j, k) {
				var i = false;
				j = Ext.getDom(j);
				k = Ext.getDom(k);
				if (j && k)
					if (j.contains)
						return j.contains(k);
					else if (j.compareDocumentPosition)
						return !!(j.compareDocumentPosition(k) & 16);
					else
						for (; k = k.parentNode; )
							i = k == j || i;
				return i
			},
			getViewWidth : function (i) {
				return i ? this.getDocumentWidth() : this.getViewportWidth()
			},
			getViewHeight : function (i) {
				return i ? this.getDocumentHeight() : this.getViewportHeight()
			},
			getDocumentHeight : function () {
				return f(!e ? g.body.scrollHeight : g.documentElement.scrollHeight, this.getViewportHeight())
			},
			getDocumentWidth : function () {
				return f(!e ? g.body.scrollWidth : g.documentElement.scrollWidth, this.getViewportWidth())
			},
			getViewportHeight : function () {
				return Ext.isIE ? Ext.isStrict ? g.documentElement.clientHeight : g.body.clientHeight : self.innerHeight
			},
			getViewportWidth : function () {
				return !Ext.isStrict && !Ext.isOpera ?
				g.body.clientWidth : Ext.isIE ? g.documentElement.clientWidth : self.innerWidth
			},
			getY : function (i) {
				return this.getXY(i)[1]
			},
			getX : function (i) {
				return this.getXY(i)[0]
			},
			getXY : function (k) {
				var j;
				var q;
				var s;
				var v;
				var l;
				var m;
				var u = 0;
				var r = 0;
				var t;
				var i;
				var n = g.body || g.documentElement;
				var o = [0, 0];
				k = Ext.getDom(k);
				if (k != n)
					if (k.getBoundingClientRect) {
						s = k.getBoundingClientRect();
						t = c(document).getScroll();
						o = [d(s.left + t.left), d(s.top + t.top)]
					} else {
						j = k;
						for (i = c(k).isStyle("position", "absolute"); j; ) {
							q = c(j);
							u += j.offsetLeft;
							r += j.offsetTop;
							i = i || q.isStyle("position", "absolute");
							if (Ext.isGecko) {
								r += v = h(q.getStyle("borderTopWidth"), 10) || 0;
								u += l = h(q.getStyle("borderLeftWidth"), 10) || 0;
								if (j != k && !q.isStyle("overflow", "visible")) {
									u += l;
									r += v
								}
							}
							j = j.offsetParent
						}
						if (Ext.isSafari && i) {
							u -= n.offsetLeft;
							r -= n.offsetTop
						}
						if (Ext.isGecko && !i) {
							m = c(n);
							u += h(m.getStyle("borderLeftWidth"), 10) || 0;
							r += h(m.getStyle("borderTopWidth"), 10) || 0
						}
						for (j = k.parentNode; j && j != n; ) {
							if (!Ext.isOpera || j.tagName != "TR" && !c(j).isStyle("display", "inline")) {
								u -= j.scrollLeft;
								r -= j.scrollTop
							}
							j = j.parentNode
						}
						o = [u, r]
					}
				return o
			},
			setXY : function (j, k) {
				(j = Ext.fly(j, "_setXY")).position();
				var l = j.translatePoints(k);
				var i = j.dom.style;
				for (var m in l)
					if (!isNaN(l[m]))
						i[m] = l[m] + "px"
			},
			setX : function (j, i) {
				this.setXY(j, [i, false])
			},
			setY : function (i, j) {
				this.setXY(i, [false, j])
			}
		}
	})();
	Ext.lib.Event = function () {
		function n(F) {
			return !u(F.currentTarget, x.getRelatedTarget(F))
		}
		function u(F, G) {
			if (F && F.firstChild)
				for (; G; ) {
					if (G === F)
						return true;
					G = G.parentNode;
					if (G && G.nodeType != 1)
						G = null
				}
			return false
		}
		function B() {
			var G =
				false;
			var L = [];
			var J;
			var I;
			var F;
			var H;
			var K = !v || z > 0;
			if (!A) {
				A = true;
				for (I = 0; I < o.length; ++I) {
					F = o[I];
					if (F && (J = E.getElementById(F.id)))
						if (!F.checkReady || v || J.nextSibling || E && E.body) {
							H = F.override;
							J = H ? H === true ? F.obj : H : J;
							F.fn.call(J, F.obj);
							o.remove(F);
							--I
						} else
							L.push(F)
				}
				z = L.length === 0 ? 0 : z - 1;
				if (K)
					m();
				else {
					clearInterval(d);
					d = null
				}
				G = !(A = false)
			}
			return G
		}
		function m() {
			if (!d) {
				var F = function () {
					B()
				};
				d = setInterval(F, r)
			}
		}
		function C() {
			var F = E.documentElement;
			var G = E.body;
			if (F && (F[q] || F[t]))
				return [F[t], F[q]];
			else if (G)
				return [G[t],
					G[q]];
			else
				return [0, 0]
		}
		function j(F, G) {
			F = F.browserEvent || F;
			var H = F["page" + G];
			if (!H && H !== 0) {
				H = F["client" + G] || 0;
				if (Ext.isIE)
					H += C()[G == "X" ? 0 : 1]
			}
			return H
		}
		var v = false;
		var f = {};
		var z = 0;
		var o = [];
		var d;
		var A = false;
		var k = window;
		var E = document;
		var l = 200;
		var r = 20;
		var p = 0;
		var i = 1;
		var s = 2;
		var w = 3;
		var t = "scrollLeft";
		var q = "scrollTop";
		var g = "unload";
		var y = "mouseover";
		var D = "mouseout";
		var e = function () {
			var F;
			if (k.addEventListener)
				F = function (J, H, I, G) {
					if (H == "mouseenter") {
						I = I.createInterceptor(n);
						J.addEventListener(y,
							I, G)
					} else if (H == "mouseleave") {
						I = I.createInterceptor(n);
						J.addEventListener(D, I, G)
					} else
						J.addEventListener(H, I, G);
					return I
				};
			else if (k.attachEvent)
				F = function (J, H, I, G) {
					J.attachEvent("on" + H, I);
					return I
				};
			else
				F = function () {};
			return F
		}
		();
		var h = function () {
			var F;
			if (k.removeEventListener)
				F = function (J, H, I, G) {
					if (H == "mouseenter")
						H = y;
					else if (H == "mouseleave")
						H = D;
					J.removeEventListener(H, I, G)
				};
			else if (k.detachEvent)
				F = function (I, G, H) {
					I.detachEvent("on" + G, H)
				};
			else
				F = function () {};
			return F
		}
		();
		var x = {
			extAdapter : true,
			onAvailable : function (H,
				F, I, G) {
				o.push({
					id : H,
					fn : F,
					obj : I,
					override : G,
					checkReady : false
				});
				z = l;
				m()
			},
			addListener : function (H, F, G) {
				H = Ext.getDom(H);
				if (H && G) {
					if (F == g) {
						if (f[H.id] === undefined)
							f[H.id] = [];
						f[H.id].push([F, G]);
						return G
					}
					return e(H, F, G, false)
				}
				return false
			},
			removeListener : function (L, H, K) {
				L = Ext.getDom(L);
				var J;
				var G;
				var F;
				var I;
				if (L && K) {
					if (H == g) {
						if ((I = f[L.id]) !== undefined)
							for (J = 0, G = I.length; J < G; J++)
								if ((F = I[J]) && F[p] == H && F[i] == K)
									f[L.id].splice(J, 1);
						return
					}
					h(L, H, K, false)
				}
			},
			getTarget : function (F) {
				F = F.browserEvent || F;
				return this.resolveTextNode(F.target ||
					F.srcElement)
			},
			resolveTextNode : Ext.isGecko ? function (G) {
				if (!G)
					return;
				var F = HTMLElement.prototype.toString.call(G);
				if (F == "[xpconnect wrapped native prototype]" || F == "[object XULElement]")
					return;
				return G.nodeType == 3 ? G.parentNode : G
			}
			 : function (F) {
				return F && F.nodeType == 3 ? F.parentNode : F
			},
			getRelatedTarget : function (F) {
				F = F.browserEvent || F;
				return this.resolveTextNode(F.relatedTarget || (/(mouseout|mouseleave)/.test(F.type) ? F.toElement : /(mouseover|mouseenter)/.test(F.type) ? F.fromElement : null))
			},
			getPageX : function (F) {
				return j(F,
					"X")
			},
			getPageY : function (F) {
				return j(F, "Y")
			},
			getXY : function (F) {
				return [this.getPageX(F), this.getPageY(F)]
			},
			stopEvent : function (F) {
				this.stopPropagation(F);
				this.preventDefault(F)
			},
			stopPropagation : function (F) {
				F = F.browserEvent || F;
				if (F.stopPropagation)
					F.stopPropagation();
				else
					F.cancelBubble = true
			},
			preventDefault : function (F) {
				F = F.browserEvent || F;
				if (F.preventDefault)
					F.preventDefault();
				else {
					if (F.keyCode)
						F.keyCode = 0;
					F.returnValue = false
				}
			},
			getEvent : function (F) {
				F = F || k.event;
				if (!F)
					for (var G = this.getEvent.caller; G; ) {
						F =
							G.arguments[0];
						if (F && Event == F.constructor)
							break;
						G = G.caller
					}
				return F
			},
			getCharCode : function (F) {
				F = F.browserEvent || F;
				return F.charCode || F.keyCode || 0
			},
			getListeners : function (G, F) {
				Ext.EventManager.getListeners(G, F)
			},
			purgeElement : function (G, H, F) {
				Ext.EventManager.purgeElement(G, H, F)
			},
			_load : function (F) {
				v = true;
				if (Ext.isIE && F !== true)
					h(k, "load", arguments.callee)
			},
			_unload : function (J) {
				var G = Ext.lib.Event;
				var H;
				var M;
				var K;
				var F;
				var I;
				var N;
				for (F in f) {
					K = f[F];
					for (H = 0, I = K.length; H < I; H++) {
						M = K[H];
						if (M)
							try {
								N = M[w] ? M[w] ===
									true ? M[s] : M[w] : k;
								M[i].call(N, G.getEvent(J), M[s])
							} catch (L) {}

					}
				}
				Ext.EventManager._unload();
				h(k, g, G._unload)
			}
		};
		x.on = x.addListener;
		x.un = x.removeListener;
		if (E && E.body)
			x._load(true);
		else
			e(k, "load", x._load);
		e(k, g, x._unload);
		B();
		return x
	}
	();
	Ext.lib.Ajax = function () {
		function h(v) {
			function s(x, y) {
				for (w in y)
					if (y.hasOwnProperty(w))
						x.setRequestHeader(w, y[w])
			}
			var t = v.conn;
			var w;
			var u = {};
			Ext.apply(u, k.headers, k.defaultHeaders);
			s(t, u);
			delete k.headers
		}
		function e(v, u, t, s) {
			return {
				tId : v,
				status : t ? -1 : 0,
				statusText : t ? "transaction aborted" :
				"communication failure",
				isAbort : t,
				isTimeout : s,
				argument : u
			}
		}
		function j(s, t) {
			(k.headers = k.headers || {})[s] = t
		}
		function p(u, y) {
			var C = {};
			var x;
			var w = u.conn;
			var A;
			var B;
			var v = w.status == 1223;
			try {
				x = u.conn.getAllResponseHeaders();
				Ext.each(x.replace(/\r\n/g, "\n").split("\n"), function (s) {
					A = s.indexOf(":");
					if (A >= 0) {
						B = s.substr(0, A).toLowerCase();
						if (s.charAt(A + 1) == " ")
							++A;
						C[B] = s.substr(A + 1)
					}
				})
			} catch (z) {}

			return {
				tId : u.tId,
				status : v ? 204 : w.status,
				statusText : v ? "No Content" : w.statusText,
				getResponseHeader : function (s) {
					return C[s.toLowerCase()]
				},
				getAllResponseHeaders : function () {
					return x
				},
				responseText : w.responseText,
				responseXML : w.responseXML,
				argument : y
			}
		}
		function o(s) {
			if (s.tId)
				k.conn[s.tId] = null;
			s.conn = null;
			s = null
		}
		function f(x, y, t, s) {
			if (!y) {
				o(x);
				return
			}
			var v;
			var u;
			try {
				if (x.conn.status !== undefined && x.conn.status != 0)
					v = x.conn.status;
				else
					v = 13030
			} catch (w) {
				v = 13030
			}
			if (v >= 200 && v < 300 || Ext.isIE && v == 1223) {
				u = p(x, y.argument);
				if (y.success)
					if (!y.scope)
						y.success(u);
					else
						y.success.apply(y.scope, [u])
			} else
				switch (v) {
				case 12002:
				case 12029:
				case 12030:
				case 12031:
				case 12152:
				case 13030:
					u =
						e(x.tId, y.argument, t ? t : false, s);
					if (y.failure)
						if (!y.scope)
							y.failure(u);
						else
							y.failure.apply(y.scope, [u]);
					break;
				default:
					u = p(x, y.argument);
					if (y.failure)
						if (!y.scope)
							y.failure(u);
						else
							y.failure.apply(y.scope, [u])
				}
			o(x);
			u = null
		}
		function m(u, x, s, w, t, v) {
			if (s && s.readyState == 4) {
				clearInterval(t[w]);
				t[w] = null;
				if (v) {
					clearTimeout(k.timeout[w]);
					k.timeout[w] = null
				}
				f(u, x)
			}
		}
		function r(s, t) {
			k.abort(s, t, true)
		}
		function n(u, x) {
			x = x || {};
			var s = u.conn;
			var w = u.tId;
			var t = k.poll;
			var v = x.timeout || null;
			if (v) {
				k.conn[w] = s;
				k.timeout[w] =
					setTimeout(r.createCallback(u, x), v)
			}
			t[w] = setInterval(m.createCallback(u, x, s, w, t, v), k.pollInterval)
		}
		function i(w, t, v, s) {
			var u = l() || null;
			if (u) {
				u.conn.open(w, t, true);
				if (k.useDefaultXhrHeader)
					j("X-Requested-With", k.defaultXhrHeader);
				if (s && k.useDefaultHeader && (!k.headers || !k.headers[d]))
					j(d, k.defaultPostHeader);
				if (k.defaultHeaders || k.headers)
					h(u);
				n(u, v);
				u.conn.send(s || null)
			}
			return u
		}
		function l() {
			var t;
			try {
				if (t = q(k.transactionId))
					k.transactionId++
			} catch (s) {}

			finally {
				return t
			}
		}
		function q(v) {
			var s;
			try {
				s = new XMLHttpRequest
			} catch (u) {
				for (var t =
						Ext.isIE6 ? 1 : 0; t < g.length; ++t)
					try {
						s = new ActiveXObject(g[t]);
						break
					} catch (u$$0) {}

			}
			finally {
				return {
					conn : s,
					tId : v
				}
			}
		}
		var g = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP"];
		var d = "Content-Type";
		var k = {
			request : function (s, u, v, w, A) {
				if (A) {
					var x = this;
					var t = A.xmlData;
					var y = A.jsonData;
					var z;
					Ext.applyIf(x, A);
					if (t || y) {
						z = x.headers;
						if (!z || !z[d])
							j(d, t ? "text/xml" : "application/json");
						w = t || (!Ext.isPrimitive(y) ? Ext.encode(y) : y)
					}
				}
				return i(s || A.method || "POST", u, v, w)
			},
			serializeForm : function (y) {
				var x = y.elements ||
					(document.forms[y] || Ext.getDom(y)).elements;
				var s = false;
				var w = encodeURIComponent;
				var t;
				var z = "";
				var v;
				var u;
				Ext.each(x, function (A) {
					t = A.name;
					v = A.type;
					if (!A.disabled && t)
						if (/select-(one|multiple)/i.test(v))
							Ext.each(A.options, function (B) {
								if (B.selected) {
									u = B.hasAttribute ? B.hasAttribute("value") : B.getAttributeNode("value").specified;
									z += String.format("{0}\x3d{1}\x26", w(t), w(u ? B.value : B.text))
								}
							});
						else if (!/file|undefined|reset|button/i.test(v))
							if (!(/radio|checkbox/i.test(v) && !A.checked) && !(v == "submit" && s)) {
								z +=
								w(t) + "\x3d" + w(A.value) + "\x26";
								s = /submit/i.test(v)
							}
				});
				return z.substr(0, z.length - 1)
			},
			useDefaultHeader : true,
			defaultPostHeader : "application/x-www-form-urlencoded; charset\x3dUTF-8",
			useDefaultXhrHeader : true,
			defaultXhrHeader : "XMLHttpRequest",
			poll : {},
			timeout : {},
			conn : {},
			pollInterval : 50,
			transactionId : 0,
			abort : function (v, x, s) {
				var u = this;
				var w = v.tId;
				var t = false;
				if (u.isCallInProgress(v)) {
					v.conn.abort();
					clearInterval(u.poll[w]);
					u.poll[w] = null;
					clearTimeout(k.timeout[w]);
					u.timeout[w] = null;
					f(v, x, t = true, s)
				}
				return t
			},
			isCallInProgress : function (s) {
				return s.conn && !{
					0 : true,
					4 : true
				}
				[s.conn.readyState]
			}
		};
		return k
	}
	();
	(function () {
		var g = Ext.lib;
		var i = /width|height|opacity|padding/i;
		var f = /^((width|height)|(top|left))$/;
		var d = /width|height|top$|bottom$|left$|right$/i;
		var h = /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i;
		var j = function (k) {
			return typeof k !== "undefined"
		};
		var e = function () {
			return new Date
		};
		g.Anim = {
			motion : function (n, l, o, p, k, m) {
				return this.run(n, l, o, p, k, m, Ext.lib.Motion)
			},
			run : function (o, l, q, r, k, n, m) {
				m = m || Ext.lib.AnimBase;
				if (typeof r ==
					"string")
					r = Ext.lib.Easing[r];
				var p = new m(o, l, q, r);
				p.animateX(function () {
					if (Ext.isFunction(k))
						k.call(n)
				});
				return p
			}
		};
		g.AnimBase = function (l, k, m, n) {
			if (l)
				this.init(l, k, m, n)
		};
		g.AnimBase.prototype = {
			doMethod : function (k, n, l) {
				var m = this;
				return m.method(m.curFrame, n, l - n, m.totalFrames)
			},
			setAttr : function (k, m, l) {
				if (i.test(k) && m < 0)
					m = 0;
				Ext.fly(this.el, "_anim").setStyle(k, m + l)
			},
			getAttr : function (k) {
				var m = Ext.fly(this.el);
				var n = m.getStyle(k);
				var l = f.exec(k) || [];
				if (n !== "auto" && !h.test(n))
					return parseFloat(n);
				return !!l[2] ||
				m.getStyle("position") == "absolute" && !!l[3] ? m.dom["offset" + l[0].charAt(0).toUpperCase() + l[0].substr(1)] : 0
			},
			getDefaultUnit : function (k) {
				return d.test(k) ? "px" : ""
			},
			animateX : function (n, k) {
				var l = this;
				var m = function () {
					l.onComplete.removeListener(m);
					if (Ext.isFunction(n))
						n.call(k || l, l)
				};
				l.onComplete.addListener(m, l);
				l.animate()
			},
			setRunAttr : function (p) {
				var r = this;
				var s = this.attributes[p];
				var t = s.to;
				var q = s.by;
				var u = s.from;
				var v = s.unit;
				var l = this.runAttrs[p] = {};
				var m;
				if (!j(t) && !j(q))
					return false;
				var k = j(u) ? u :
					r.getAttr(p);
				if (j(t))
					m = t;
				else if (j(q))
					if (Ext.isArray(k)) {
						m = [];
						var n = 0;
						for (var o = k.length; n < o; n++)
							m[n] = k[n] + q[n]
					} else
						m = k + q;
				Ext.apply(l, {
					start : k,
					end : m,
					unit : j(v) ? v : r.getDefaultUnit(p)
				})
			},
			init : function (l, p, o, k) {
				var r = this;
				var n = 0;
				var s = g.AnimMgr;
				Ext.apply(r, {
					isAnimated : false,
					startTime : null,
					el : Ext.getDom(l),
					attributes : p || {},
					duration : o || 1,
					method : k || g.Easing.easeNone,
					useSec : true,
					curFrame : 0,
					totalFrames : s.fps,
					runAttrs : {},
					animate : function () {
						var u = this;
						var v = u.duration;
						if (u.isAnimated)
							return false;
						u.curFrame =
							0;
						u.totalFrames = u.useSec ? Math.ceil(s.fps * v) : v;
						s.registerElement(u)
					},
					stop : function (u) {
						var v = this;
						if (u) {
							v.curFrame = v.totalFrames;
							v._onTween.fire()
						}
						s.stop(v)
					}
				});
				var t = function () {
					var v = this;
					var u;
					v.onStart.fire();
					v.runAttrs = {};
					for (u in this.attributes)
						this.setRunAttr(u);
					v.isAnimated = true;
					v.startTime = e();
					n = 0
				};
				var q = function () {
					var v = this;
					v.onTween.fire({
						duration : e() - v.startTime,
						curFrame : v.curFrame
					});
					var w = v.runAttrs;
					for (var u in w)
						this.setAttr(u, v.doMethod(u, w[u].start, w[u].end), w[u].unit);
					++n
				};
				var m = function () {
					var u =
						this;
					var w = (e() - u.startTime) / 1E3;
					var v = {
						duration : w,
						frames : n,
						fps : n / w
					};
					u.isAnimated = false;
					n = 0;
					u.onComplete.fire(v)
				};
				r.onStart = new Ext.util.Event(r);
				r.onTween = new Ext.util.Event(r);
				r.onComplete = new Ext.util.Event(r);
				(r._onStart = new Ext.util.Event(r)).addListener(t);
				(r._onTween = new Ext.util.Event(r)).addListener(q);
				(r._onComplete = new Ext.util.Event(r)).addListener(m)
			}
		};
		Ext.lib.AnimMgr = new function () {
			var o = this;
			var m = null;
			var l = [];
			var k = 0;
			Ext.apply(o, {
				fps : 1E3,
				delay : 1,
				registerElement : function (q) {
					l.push(q);
					++k;
					q._onStart.fire();
					o.start()
				},
				unRegister : function (r, q) {
					r._onComplete.fire();
					q = q || p(r);
					if (q != -1)
						l.splice(q, 1);
					if (--k <= 0)
						o.stop()
				},
				start : function () {
					if (m === null)
						m = setInterval(o.run, o.delay)
				},
				stop : function (s) {
					if (!s) {
						clearInterval(m);
						var r = 0;
						for (var q = l.length; r < q; ++r)
							if (l[0].isAnimated)
								o.unRegister(l[0], 0);
						l = [];
						m = null;
						k = 0
					} else
						o.unRegister(s)
				},
				run : function () {
					var t;
					var s;
					var q;
					var r;
					for (s = 0, q = l.length; s < q; s++) {
						r = l[s];
						if (r && r.isAnimated) {
							t = r.totalFrames;
							if (r.curFrame < t || t === null) {
								++r.curFrame;
								if (r.useSec)
									n(r);
								r._onTween.fire()
							} else
								o.stop(r)
						}
					}
				}
			});
			var p = function (s) {
				var r;
				var q;
				for (r = 0, q = l.length; r < q; r++)
					if (l[r] === s)
						return r;
				return -1
			};
			var n = function (r) {
				var v = r.totalFrames;
				var u = r.curFrame;
				var t = r.duration;
				var s = u * t * 1E3 / v;
				var q = e() - r.startTime;
				var w = 0;
				if (q < t * 1E3)
					w = Math.round((q / s - 1) * u);
				else
					w = v - (u + 1);
				if (w > 0 && isFinite(w)) {
					if (r.curFrame + w >= v)
						w = v - (u + 1);
					r.curFrame += w
				}
			}
		};
		g.Bezier = new function () {
			this.getPosition = function (p, o) {
				var r = p.length;
				var m = [];
				var q = 1 - o;
				var l;
				var k;
				for (l = 0; l < r; ++l)
					m[l] = [p[l][0], p[l][1]];
				for (k = 1; k < r; ++k)
					for (l = 0; l < r - k; ++l) {
						m[l][0] = q * m[l][0] + o * m[parseInt(l + 1, 10)][0];
						m[l][1] = q * m[l][1] + o * m[parseInt(l + 1, 10)][1]
					}
				return [m[0][0], m[0][1]]
			}
		};
		g.Easing = {
			easeNone : function (l, k, n, m) {
				return n * l / m + k
			},
			easeIn : function (l, k, n, m) {
				return n * (l /= m) * l + k
			},
			easeOut : function (l, k, n, m) {
				return -n * (l /= m) * (l - 2) + k
			}
		};
		(function () {
			g.Motion = function (o, n, p, q) {
				if (o)
					g.Motion.superclass.constructor.call(this, o, n, p, q)
			};
			Ext.extend(g.Motion, Ext.lib.AnimBase);
			var m = g.Motion.superclass;
			var l = /^points$/i;
			Ext.apply(g.Motion.prototype, {
				setAttr : function (n, r, q) {
					var p = this;
					var o = m.setAttr;
					if (l.test(n)) {
						q = q || "px";
						o.call(p, "left", r[0], q);
						o.call(p, "top", r[1], q)
					} else
						o.call(p, n, r, q)
				},
				getAttr : function (n) {
					var p = this;
					var o = m.getAttr;
					return l.test(n) ? [o.call(p, "left"), o.call(p, "top")] : o.call(p, n)
				},
				doMethod : function (n, q, o) {
					var p = this;
					return l.test(n) ? g.Bezier.getPosition(p.runAttrs[n], p.method(p.curFrame, 0, 100, p.totalFrames) / 100) : m.doMethod.call(p, n, q, o)
				},
				setRunAttr : function (u) {
					if (l.test(u)) {
						var w = this;
						var p = this.el;
						var z = this.attributes.points;
						var s = z.control || [];
						var x = z.from;
						var y = z.to;
						var v = z.by;
						var A = g.Dom;
						var o;
						var r;
						var q;
						var t;
						var n;
						if (s.length > 0 && !Ext.isArray(s[0]))
							s = [s];
						else ;
						Ext.fly(p, "_anim").position();
						A.setXY(p, j(x) ? x : A.getXY(p));
						o = w.getAttr("points");
						if (j(y)) {
							q = k.call(w, y, o);
							for (r = 0, t = s.length; r < t; ++r)
								s[r] = k.call(w, s[r], o)
						} else if (j(v)) {
							q = [o[0] + v[0], o[1] + v[1]];
							for (r = 0, t = s.length; r < t; ++r)
								s[r] = [o[0] + s[r][0], o[1] + s[r][1]]
						}
						n = this.runAttrs[u] = [o];
						if (s.length > 0)
							n = n.concat(s);
						n[n.length] = q
					} else
						m.setRunAttr.call(this, u)
				}
			});
			var k = function (n,
				p) {
				var o = g.Dom.getXY(this.el);
				return [n[0] - o[0] + p[0], n[1] - o[1] + p[1]]
			}
		})()
	})();
	(function () {
		var d = Math.abs;
		var i = Math.PI;
		var h = Math.asin;
		var g = Math.pow;
		var e = Math.sin;
		var f = Ext.lib;
		Ext.apply(f.Easing, {
			easeBoth : function (k, j, m, l) {
				return (k /= l / 2) < 1 ? m / 2 * k * k + j : -m / 2 * (--k * (k - 2) - 1) + j
			},
			easeInStrong : function (k, j, m, l) {
				return m * (k /= l) * k * k * k + j
			},
			easeOutStrong : function (k, j, m, l) {
				return -m * ((k = k / l - 1) * k * k * k - 1) + j
			},
			easeBothStrong : function (k, j, m, l) {
				return (k /= l / 2) < 1 ? m / 2 * k * k * k * k + j : -m / 2 * ((k -= 2) * k * k * k - 2) + j
			},
			elasticIn : function (l,
				j, q, o, k, n) {
				if (l == 0 || (l /= o) == 1)
					return l == 0 ? j : j + q;
				n = n || o * 0.3;
				var m;
				if (k >= d(q))
					m = n / (2 * i) * h(q / k);
				else {
					k = q;
					m = n / 4
				}
				return  - (k * g(2, 10 * (l -= 1)) * e((l * o - m) * 2 * i / n)) + j
			},
			elasticOut : function (l, j, q, o, k, n) {
				if (l == 0 || (l /= o) == 1)
					return l == 0 ? j : j + q;
				n = n || o * 0.3;
				var m;
				if (k >= d(q))
					m = n / (2 * i) * h(q / k);
				else {
					k = q;
					m = n / 4
				}
				return k * g(2, -10 * l) * e((l * o - m) * 2 * i / n) + q + j
			},
			elasticBoth : function (l, j, q, o, k, n) {
				if (l == 0 || (l /= o / 2) == 2)
					return l == 0 ? j : j + q;
				n = n || o * 0.3 * 1.5;
				var m;
				if (k >= d(q))
					m = n / (2 * i) * h(q / k);
				else {
					k = q;
					m = n / 4
				}
				return l < 1 ? -0.5 * k * g(2, 10 * (l -= 1)) * e((l *
						o - m) * 2 * i / n) + j : k * g(2, -10 * (l -= 1)) * e((l * o - m) * 2 * i / n) * 0.5 + q + j
			},
			backIn : function (k, j, n, m, l) {
				l = l || 1.70158;
				return n * (k /= m) * k * ((l + 1) * k - l) + j
			},
			backOut : function (k, j, n, m, l) {
				if (!l)
					l = 1.70158;
				return n * ((k = k / m - 1) * k * ((l + 1) * k + l) + 1) + j
			},
			backBoth : function (k, j, n, m, l) {
				l = l || 1.70158;
				return (k /= m / 2) < 1 ? n / 2 * k * k * (((l *= 1.525) + 1) * k - l) + j : n / 2 * ((k -= 2) * k * (((l *= 1.525) + 1) * k + l) + 2) + j
			},
			bounceIn : function (k, j, m, l) {
				return m - f.Easing.bounceOut(l - k, 0, m, l) + j
			},
			bounceOut : function (k, j, m, l) {
				if ((k /= l) < 1 / 2.75)
					return m * 7.5625 * k * k + j;
				else if (k < 2 / 2.75)
					return m *
					(7.5625 * (k -= 1.5 / 2.75) * k + 0.75) + j;
				else if (k < 2.5 / 2.75)
					return m * (7.5625 * (k -= 2.25 / 2.75) * k + 0.9375) + j;
				return m * (7.5625 * (k -= 2.625 / 2.75) * k + 0.984375) + j
			},
			bounceBoth : function (k, j, m, l) {
				return k < l / 2 ? f.Easing.bounceIn(k * 2, 0, m, l) * 0.5 + j : f.Easing.bounceOut(k * 2 - l, 0, m, l) * 0.5 + m * 0.5 + j
			}
		})
	})();
	(function () {
		function k(n) {
			var p = parseInt;
			var o;
			var m = null;
			var q;
			if (n.length == 3)
				return n;
			Ext.each([d, l, e], function (s, r) {
				o = r % 2 == 0 ? 16 : 10;
				q = s.exec(n);
				if (q && q.length == 4) {
					m = [p(q[1], o), p(q[2], o), p(q[3], o)];
					return false
				}
			});
			return m
		}
		var h =
			Ext.lib;
		h.Anim.color = function (p, n, q, r, m, o) {
			return h.Anim.run(p, n, q, r, m, o, h.ColorAnim)
		};
		h.ColorAnim = function (n, m, o, p) {
			h.ColorAnim.superclass.constructor.call(this, n, m, o, p)
		};
		Ext.extend(h.ColorAnim, h.AnimBase);
		var j = h.ColorAnim.superclass;
		var i = /color$/i;
		var f = /^transparent|rgba\(0, 0, 0, 0\)$/;
		var l = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
		var d = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
		var e = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
		var g = function (m) {
			return typeof m !== "undefined"
		};
		Ext.apply(h.ColorAnim.prototype, {
			getAttr : function (m) {
				var o = this;
				var n = o.el;
				var p;
				if (i.test(m))
					for (; n && f.test(p = Ext.fly(n).getStyle(m)); ) {
						n = n.parentNode;
						p = "fff"
					}
				else
					p = j.getAttr.call(o, m);
				return p
			},
			doMethod : function (s, m, o) {
				var t = this;
				var n;
				var q = Math.floor;
				var p;
				var r;
				var u;
				if (i.test(s)) {
					n = [];
					o = o || [];
					for (p = 0, r = m.length; p < r; p++) {
						u = m[p];
						n[p] = j.doMethod.call(t, s, u, o[p])
					}
					n = "rgb(" + q(n[0]) + "," + q(n[1]) + "," + q(n[2]) + ")"
				} else
					n = j.doMethod.call(t, s, m, o);
				return n
			},
			setRunAttr : function (r) {
				var t = this;
				var u = t.attributes[r];
				var v = u.to;
				var s = u.by;
				var n;
				j.setRunAttr.call(t, r);
				n = t.runAttrs[r];
				if (i.test(r)) {
					var m = k(n.start);
					var o = k(n.end);
					if (!g(v) && g(s)) {
						o = k(s);
						var p = 0;
						for (var q = m.length; p < q; p++)
							o[p] = m[p] + o[p]
					}
					n.start = m;
					n.end = o
				}
			}
		})
	})();
	(function () {
		var d = Ext.lib;
		d.Anim.scroll = function (j, h, k, l, g, i) {
			return d.Anim.run(j, h, k, l, g, i, d.Scroll)
		};
		d.Scroll = function (h, g, i, j) {
			if (h)
				d.Scroll.superclass.constructor.call(this, h, g, i, j)
		};
		Ext.extend(d.Scroll, d.ColorAnim);
		var f = d.Scroll.superclass;
		var e = "scroll";
		Ext.apply(d.Scroll.prototype, {
			doMethod : function (g, m, h) {
				var k;
				var j = this;
				var l = j.curFrame;
				var i = j.totalFrames;
				if (g == e)
					k = [j.method(l, m[0], h[0] - m[0], i), j.method(l, m[1], h[1] - m[1], i)];
				else
					k = f.doMethod.call(j, g, m, h);
				return k
			},
			getAttr : function (g) {
				var h = this;
				if (g == e)
					return [h.el.scrollLeft, h.el.scrollTop];
				else
					return f.getAttr.call(h, g)
			},
			setAttr : function (g, j, i) {
				var h = this;
				if (g == e) {
					h.el.scrollLeft = j[0];
					h.el.scrollTop = j[1]
				} else
					f.setAttr.call(h, g, j, i)
			}
		})
	})();
	if (Ext.isIE) {
		var a = function () {
			var d = Function.prototype;
			delete d.createSequence;
			delete d.defer;
			delete d.createDelegate;
			delete d.createCallback;
			delete d.createInterceptor;
			window.detachEvent("onunload", a)
		};
		window.attachEvent("onunload", a)
	}
})();
(function () {
	function createTargeted(h, o, scope) {
		return function () {
			if (o.target == arguments[0])
				h.apply(scope, Array.prototype.slice.call(arguments, 0))
		}
	}
	function createBuffered(h, o, l, scope) {
		l.task = new EXTUTIL.DelayedTask;
		return function () {
			l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0))
		}
	}
	function createSingle(h, e, fn, scope) {
		return function () {
			e.removeListener(fn, scope);
			return h.apply(scope, arguments)
		}
	}
	function createDelayed(h, o, l, scope) {
		return function () {
			var task = new EXTUTIL.DelayedTask;
			var args = Array.prototype.slice.call(arguments, 0);
			if (!l.tasks)
				l.tasks = [];
			l.tasks.push(task);
			task.delay(o.delay || 10, function () {
				l.tasks.remove(task);
				h.apply(scope, args)
			}, scope)
		}
	}
	var EXTUTIL = Ext.util;
	var EACH = Ext.each;
	var TRUE = true;
	var FALSE = false;
	EXTUTIL.Observable = function () {
		var me = this;
		var e = me.events;
		if (me.listeners) {
			me.on(me.listeners);
			delete me.listeners
		}
		me.events = e || {}

	};
	EXTUTIL.Observable.prototype = {
		filterOptRe : /^(?:scope|delay|buffer|single)$/,
		fireEvent : function () {
			var a = Array.prototype.slice.call(arguments,
					0);
			var ename = a[0].toLowerCase();
			var me = this;
			var ret = TRUE;
			var ce = me.events[ename];
			var cc;
			var q;
			var c;
			if (me.eventsSuspended === TRUE) {
				if (q = me.eventQueue)
					q.push(a)
			} else if (typeof ce == "object")
				if (ce.bubble) {
					if (ce.fire.apply(ce, a.slice(1)) === FALSE)
						return FALSE;
					c = me.getBubbleTarget && me.getBubbleTarget();
					if (c && c.enableBubble) {
						cc = c.events[ename];
						if (!cc || typeof cc != "object" || !cc.bubble)
							c.enableBubble(ename);
						return c.fireEvent.apply(c, a)
					}
				} else {
					a.shift();
					ret = ce.fire.apply(ce, a)
				}
			return ret
		},
		addListener : function (eventName,
			fn, scope, o) {
			var me = this;
			var e;
			var oe;
			var ce;
			if (typeof eventName == "object") {
				o = eventName;
				for (e in o) {
					oe = o[e];
					if (!me.filterOptRe.test(e))
						me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o)
				}
			} else {
				eventName = eventName.toLowerCase();
				ce = me.events[eventName] || TRUE;
				if (typeof ce == "boolean")
					me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
				ce.addListener(fn, scope, typeof o == "object" ? o : {})
			}
		},
		removeListener : function (eventName, fn, scope) {
			var ce = this.events[eventName.toLowerCase()];
			if (typeof ce == "object")
				ce.removeListener(fn,
					scope)
		},
		purgeListeners : function () {
			var events = this.events;
			var evt;
			for (var key in events) {
				evt = events[key];
				if (typeof evt == "object")
					evt.clearListeners()
			}
		},
		addEvents : function (o) {
			var me = this;
			me.events = me.events || {};
			if (typeof o == "string") {
				var a = arguments;
				for (var i = a.length; i--; )
					me.events[a[i]] = me.events[a[i]] || TRUE
			} else
				Ext.applyIf(me.events, o)
		},
		hasListener : function (eventName) {
			var e = this.events[eventName.toLowerCase()];
			return typeof e == "object" && e.listeners.length > 0
		},
		suspendEvents : function (queueSuspended) {
			this.eventsSuspended =
				TRUE;
			if (queueSuspended && !this.eventQueue)
				this.eventQueue = []
		},
		resumeEvents : function () {
			var me = this;
			var queued = me.eventQueue || [];
			me.eventsSuspended = FALSE;
			delete me.eventQueue;
			EACH(queued, function (e) {
				me.fireEvent.apply(me, e)
			})
		}
	};
	var OBSERVABLE = EXTUTIL.Observable.prototype;
	OBSERVABLE.on = OBSERVABLE.addListener;
	OBSERVABLE.un = OBSERVABLE.removeListener;
	EXTUTIL.Observable.releaseCapture = function (o) {
		o.fireEvent = OBSERVABLE.fireEvent
	};
	EXTUTIL.Event = function (obj, name) {
		this.name = name;
		this.obj = obj;
		this.listeners =
			[]
	};
	EXTUTIL.Event.prototype = {
		addListener : function (fn, scope, options) {
			var me = this;
			var l;
			scope = scope || me.obj;
			if (!me.isListening(fn, scope)) {
				l = me.createListener(fn, scope, options);
				if (me.firing)
					me.listeners = me.listeners.slice(0);
				me.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.target)
				h = createTargeted(h, o, scope);
			if (o.delay)
				h = createDelayed(h, o, l, scope);
			if (o.single)
				h = createSingle(h, this, fn, scope);
			if (o.buffer)
				h = createBuffered(h,
						o, l, scope);
			l.fireFn = h;
			return l
		},
		findListener : function (fn, scope) {
			var list = this.listeners;
			var i = list.length;
			var l;
			for (scope = scope || this.obj; i--; ) {
				l = list[i];
				if (l)
					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;
			var l;
			var k;
			var me = this;
			var ret = FALSE;
			if ((index = me.findListener(fn, scope)) != -1) {
				if (me.firing)
					me.listeners = me.listeners.slice(0);
				l = me.listeners[index];
				if (l.task) {
					l.task.cancel();
					delete l.task
				}
				k =
					l.tasks && l.tasks.length;
				if (k) {
					for (; k--; )
						l.tasks[k].cancel();
					delete l.tasks
				}
				me.listeners.splice(index, 1);
				ret = TRUE
			}
			return ret
		},
		clearListeners : function () {
			var me = this;
			var l = me.listeners;
			for (var i = l.length; i--; )
				me.removeListener(l[i].fn, l[i].scope)
		},
		fire : function () {
			var me = this;
			var listeners = me.listeners;
			var len = listeners.length;
			var i = 0;
			var l;
			if (len > 0) {
				me.firing = TRUE;
				for (var args = Array.prototype.slice.call(arguments, 0); i < len; i++) {
					l = listeners[i];
					if (l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE)
						return me.firing =
							FALSE
				}
			}
			me.firing = FALSE;
			return TRUE
		}
	}
})();
Ext.DomHelper = function () {
	function doInsert(el, o, returnElement, pos, sibling, append) {
		var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
		return returnElement ? Ext.get(newNode, true) : newNode
	}
	function createHtml(o) {
		var b = "";
		var attr;
		var val;
		var key;
		var cn;
		if (typeof o == "string")
			b = o;
		else if (Ext.isArray(o))
			for (var i = 0; i < o.length; i++) {
				if (o[i])
					b += createHtml(o[i])
			}
		else {
			b += "\x3c" + (o.tag = o.tag || "div");
			for (attr in o) {
				val = o[attr];
				if (!confRe.test(attr))
					if (typeof val == "object") {
						b += " " + attr + '\x3d"';
						for (key in val)
							b +=
							key + ":" + val[key] + ";";
						b += '"'
					} else
						b += " " + ({
							cls : "class",
							htmlFor : "for"
						}
							[attr] || attr) + '\x3d"' + val + '"'
			}
			if (emptyTags.test(o.tag))
				b += "/\x3e";
			else {
				b += "\x3e";
				if (cn = o.children || o.cn)
					b += createHtml(cn);
				else if (o.html)
					b += o.html;
				b += "\x3c/" + o.tag + "\x3e"
			}
		}
		return b
	}
	function ieTable(depth, s, h, e) {
		tempTableEl.innerHTML = [s, h, e].join("");
		var i = -1;
		var el = tempTableEl;
		for (var ns; ++i < depth; )
			el = el.firstChild;
		if (ns = el.nextSibling) {
			for (var df = document.createDocumentFragment(); el; ) {
				ns = el.nextSibling;
				df.appendChild(el);
				el = ns
			}
			el =
				df
		}
		return el
	}
	function insertIntoTable(tag, where, el, html) {
		var node;
		var before;
		tempTableEl = tempTableEl || document.createElement("div");
		if (tag == "td" && (where == afterbegin || where == beforeend) || !tableElRe.test(tag) && (where == beforebegin || where == afterend))
			return;
		before = where == beforebegin ? el : where == afterend ? el.nextSibling : where == afterbegin ? el.firstChild : null;
		if (where == beforebegin || where == afterend)
			el = el.parentNode;
		if (tag == "td" || tag == "tr" && (where == beforeend || where == afterbegin))
			node = ieTable(4, trs, html, tre);
		else if (tag ==
			"tbody" && (where == beforeend || where == afterbegin) || tag == "tr" && (where == beforebegin || where == afterend))
			node = ieTable(3, tbs, html, tbe);
		else
			node = ieTable(2, ts, html, te);
		el.insertBefore(node, before);
		return node
	}
	function createContextualFragment(html) {
		var div = document.createElement("div");
		var fragment = document.createDocumentFragment();
		var i = 0;
		var length;
		var childNodes;
		div.innerHTML = html;
		childNodes = div.childNodes;
		for (length = childNodes.length; i < length; i++)
			fragment.appendChild(childNodes[i].cloneNode(true));
		return fragment
	}
	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 confRe = /tag|children|cn|html$/i;
	var tableElRe = /td|tr|tbody/i;
	var cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi;
	var endRe = /end/i;
	var pub;
	var afterbegin = "afterbegin";
	var afterend = "afterend";
	var beforebegin = "beforebegin";
	var beforeend = "beforeend";
	var ts = "\x3ctable\x3e";
	var te = "\x3c/table\x3e";
	var tbs = ts + "\x3ctbody\x3e";
	var tbe = "\x3c/tbody\x3e" + te;
	var trs = tbs + "\x3ctr\x3e";
	var tre = "\x3c/tr\x3e" + tbe;
	pub = {
		markup : function (o) {
			return createHtml(o)
		},
		applyStyles : function (el, styles) {
			if (styles) {
				var matches;
				el = Ext.fly(el);
				if (typeof styles == "function")
					styles = styles.call();
				if (typeof styles == "string")
					for (cssRe.lastIndex = 0; matches = cssRe.exec(styles); )
						el.setStyle(matches[1], matches[2]);
				else if (typeof styles == "object")
					el.setStyle(styles)
			}
		},
		insertHtml : function (where, el, html) {
			var hash = {};
			var hashVal;
			var range;
			var rangeEl;
			var setStart;
			var frag;
			var rs;
			where = where.toLowerCase();
			hash[beforebegin] = ["BeforeBegin", "previousSibling"];
			hash[afterend] = ["AfterEnd", "nextSibling"];
			if (el.insertAdjacentHTML) {
				if (tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)))
					return rs;
				hash[afterbegin] = ["AfterBegin", "firstChild"];
				hash[beforeend] = ["BeforeEnd", "lastChild"];
				if (hashVal = hash[where]) {
					el.insertAdjacentHTML(hashVal[0], html);
					return el[hashVal[1]]
				}
			} else {
				range = el.ownerDocument.createRange();
				setStart = "setStart" + (endRe.test(where) ? "After" : "Before");
				if (hash[where]) {
					range[setStart](el);
					if (!range.createContextualFragment)
						frag = createContextualFragment(html);
					else
						frag = range.createContextualFragment(html);
					el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
					return el[(where == beforebegin ? "previous" : "next") + "Sibling"]
				} else {
					rangeEl = (where == afterbegin ? "first" : "last") + "Child";
					if (el.firstChild) {
						range[setStart](el[rangeEl]);
						if (!range.createContextualFragment)
							frag = createContextualFragment(html);
						else
							frag = range.createContextualFragment(html);
						if (where == afterbegin)
							el.insertBefore(frag,
								el.firstChild);
						else
							el.appendChild(frag)
					} else
						el.innerHTML = html;
					return el[rangeEl]
				}
			}
			throw 'Illegal insertion point -\x3e "' + where + '"';
		},
		insertBefore : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, beforebegin)
		},
		insertAfter : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, afterend, "nextSibling")
		},
		insertFirst : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, afterbegin, "firstChild")
		},
		append : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, beforeend,
				"", true)
		},
		overwrite : function (el, o, returnElement) {
			el = Ext.getDom(el);
			el.innerHTML = createHtml(o);
			return returnElement ? Ext.get(el.firstChild) : el.firstChild
		},
		createHtml : createHtml
	};
	return pub
}
();
Ext.Template = function (html) {
	var me = this;
	var a = arguments;
	var buf = [];
	var v;
	if (Ext.isArray(html))
		html = html.join("");
	else if (a.length > 1) {
		var i = 0;
		for (var len = a.length; i < len; i++) {
			v = a[i];
			if (typeof v == "object")
				Ext.apply(me, v);
			else
				buf.push(v)
		}
		html = buf.join("")
	}
	me.html = html;
	if (me.compiled)
		me.compile()
};
Ext.Template.prototype = {
	re : /\{([\w\-]+)\}/g,
	applyTemplate : function (values) {
		var me = this;
		return me.compiled ? me.compiled(values) : me.html.replace(me.re, function (m, name) {
			return values[name] !== undefined ? values[name] : ""
		})
	},
	set : function (html, compile) {
		var me = this;
		me.html = html;
		me.compiled = null;
		return compile ? me.compile() : me
	},
	compile : function () {
		function fn(m, name) {
			name = "values['" + name + "']";
			return "'" + sep + "(" + name + " \x3d\x3d undefined ? '' : " + name + ")" + sep + "'"
		}
		var me = this;
		var sep = Ext.isGecko ? "+" : ",";
		eval("this.compiled \x3d function(values){ return " +
			(Ext.isGecko ? "'" : "['") + me.html.replace(/\\/g, "\\\\").replace(/(\r\n|\n)/g, "\\n").replace(/'/g, "\\'").replace(this.re, fn) + (Ext.isGecko ? "';};" : "'].join('');};"));
		return me
	},
	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.Template.from = function (el, config) {
	el = Ext.getDom(el);
	return new Ext.Template(el.value || el.innerHTML, config || "")
};
Ext.DomQuery = function () {
	function child(parent, index) {
		var i = 0;
		for (var n = parent.firstChild; n; ) {
			if (n.nodeType == 1)
				if (++i == index)
					return n;
			n = n.nextSibling
		}
		return null
	}
	function next(n) {
		for (; (n = n.nextSibling) && n.nodeType != 1; );
		return n
	}
	function prev(n) {
		for (; (n = n.previousSibling) && n.nodeType != 1; );
		return n
	}
	function children(parent) {
		var n = parent.firstChild;
		var nodeIndex = -1;
		for (var nextNode; n; ) {
			nextNode = n.nextSibling;
			if (n.nodeType == 3 && !nonSpace.test(n.nodeValue))
				parent.removeChild(n);
			else
				n.nodeIndex = ++nodeIndex;
			n = nextNode
		}
		return this
	}
	function byClassName(nodeSet, cls) {
		if (!cls)
			return nodeSet;
		var result = [];
		var ri = -1;
		var i = 0;
		for (var ci; ci = nodeSet[i]; i++)
			if ((" " + ci.className + " ").indexOf(cls) != -1)
				result[++ri] = ci;
		return result
	}
	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 = [];
		var ri = -1;
		var cs;
		if (!ns)
			return result;
		tagName = tagName || "*";
		if (typeof ns.getElementsByTagName != "undefined")
			ns = [ns];
		if (!mode) {
			var i = 0;
			for (var ni; ni = ns[i]; i++) {
				cs = ni.getElementsByTagName(tagName);
				var j = 0;
				for (var ci; ci = cs[j]; j++)
					result[++ri] = ci
			}
		} else if (mode == "/" || mode == "\x3e") {
			var utag = tagName.toUpperCase();
			i = 0;
			for (var cn; ni = ns[i]; i++) {
				cn = ni.childNodes;
				j = 0;
				for (var cj; cj = cn[j]; j++)
					if (cj.nodeName == utag || cj.nodeName == tagName || tagName == "*")
						result[++ri] = cj
			}
		} else if (mode == "+") {
			utag = tagName.toUpperCase();
			i = 0;
			for (var n; n = ns[i]; i++) {
				for (; (n = n.nextSibling) &&
					n.nodeType != 1; );
				if (n && (n.nodeName == utag || n.nodeName == tagName || tagName == "*"))
					result[++ri] = n
			}
		} else if (mode == "~") {
			utag = tagName.toUpperCase();
			for (i = 0; n = ns[i]; i++)
				for (; n = n.nextSibling; )
					if (n.nodeName == utag || n.nodeName == tagName || tagName == "*")
						result[++ri] = n
		}
		return result
	}
	function concat(a, b) {
		if (b.slice)
			return a.concat(b);
		var i = 0;
		for (var 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 result = [];
		var ri = -1;
		tagName = tagName.toLowerCase();
		var i = 0;
		for (var ci; ci = cs[i]; i++)
			if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName)
				result[++ri] = ci;
		return result
	}
	function byId(cs, id) {
		if (cs.tagName || cs == document)
			cs = [cs];
		if (!id)
			return cs;
		var result = [];
		var ri = -1;
		var i = 0;
		for (var ci; ci = cs[i]; i++)
			if (ci && ci.id == id) {
				result[++ri] = ci;
				return result
			}
		return result
	}
	function byAttribute(cs, attr, value, op, custom) {
		var result = [];
		var ri = -1;
		var useGetStyle = custom == "{";
		var fn = Ext.DomQuery.operators[op];
		var a;
		var xml;
		var hasXml;
		var i = 0;
		for (var ci; ci = cs[i]; i++) {
			if (ci.nodeType !=
				1)
				continue;
			if (!hasXml) {
				xml = Ext.DomQuery.isXml(ci);
				hasXml = true
			}
			if (!xml)
				if (useGetStyle)
					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);
			else
				a = ci.getAttribute(attr);
			if (fn && fn(a, value) || !fn && a)
				result[++ri] = ci
		}
		return result
	}
	function byPseudo(cs, name, value) {
		return Ext.DomQuery.pseudos[name](cs, value)
	}
	function nodupIEXml(cs) {
		var d = ++key;
		var r;
		cs[0].setAttribute("_nodup",
			d);
		r = [cs[0]];
		var i = 1;
		for (var len = cs.length; i < len; i++) {
			var c = cs[i];
			if (!c.getAttribute("_nodup") != d) {
				c.setAttribute("_nodup", d);
				r[r.length] = c
			}
		}
		i = 0;
		for (len = cs.length; i < len; i++)
			cs[i].removeAttribute("_nodup");
		return r
	}
	function nodup(cs) {
		if (!cs)
			return [];
		var len = cs.length;
		var c;
		var i;
		var r = cs;
		var cj;
		var 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;
		var r = [];
		var i = 0;
		for (var len = c1.length; i < len; i++)
			c1[i].setAttribute("_qdiff", d);
		i = 0;
		for (len = c2.length; i < len; i++)
			if (c2[i].getAttribute("_qdiff") != d)
				r[r.length] = c2[i];
		i = 0;
		for (len = c1.length; i < len; i++)
			c1[i].removeAttribute("_qdiff");
		return r
	}
	function quickDiff(c1, c2) {
		var len1 = c1.length;
		var d = ++key;
		var r = [];
		if (!len1)
			return c2;
		if (isIE &&
			typeof c1[0].selectSingleNode != "undefined")
			return quickDiffIEXml(c1, c2);
		for (var i = 0; i < len1; i++)
			c1[i]._qdiff = d;
		i = 0;
		for (var 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, id)
	}
	var cache = {};
	var simpleCache = {};
	var 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*)/;
	var nthRe2 = /\D/;
	var isIE = window.ActiveXObject ? true : false;
	var key = 30803;
	eval("var batch \x3d 30803;");
	return {
		getStyle : function (el, name) {
			return Ext.fly(el).getStyle(name)
		},
		compile : function (path, type) {
			type = type || "select";
			var fn = ["var f \x3d function(root){\n var mode; ++batch; var n \x3d root || document;\n"];
			var mode;
			var lastPath;
			var matchers = Ext.DomQuery.matchers;
			var matchersLn = matchers.length;
			var modeMatch;
			var lmode = path.match(modeRe);
			if (lmode && lmode[1]) {
				fn[fn.length] =
					'mode\x3d"' + lmode[1].replace(trimRe, "") + '";';
				path = path.replace(lmode[1], "")
			}
			for (; path.substr(0, 1) == "/"; )
				path = path.substr(1);
			for (; path && lastPath != path; ) {
				lastPath = path;
				var tokenMatch = path.match(tagTokenRe);
				if (type == "select")
					if (tokenMatch) {
						if (tokenMatch[1] == "#")
							fn[fn.length] = 'n \x3d quickId(n, mode, root, "' + tokenMatch[2] + '");';
						else
							fn[fn.length] = 'n \x3d getNodes(n, mode, "' + tokenMatch[2] + '");';
						path = path.replace(tokenMatch[0], "")
					} else {
						if (path.substr(0, 1) != "@")
							fn[fn.length] = 'n \x3d getNodes(n, mode, "*");'
					}
				else if (tokenMatch) {
					if (tokenMatch[1] ==
						"#")
						fn[fn.length] = 'n \x3d byId(n, "' + tokenMatch[2] + '");';
					else
						fn[fn.length] = 'n \x3d byTag(n, "' + tokenMatch[2] + '");';
					path = path.replace(tokenMatch[0], "")
				}
				for (; !(modeMatch = path.match(modeRe)); ) {
					var matched = false;
					for (var j = 0; j < matchersLn; j++) {
						var t = matchers[j];
						var m = path.match(t.re);
						if (m) {
							fn[fn.length] = t.select.replace(tplRe, function (x, i) {
									return m[i]
								});
							path = path.replace(m[0], "");
							matched = true;
							break
						}
					}
					if (!matched)
						throw 'Error parsing selector, parsing failed at "' + path + '"';
				}
				if (modeMatch[1]) {
					fn[fn.length] =
						'mode\x3d"' + modeMatch[1].replace(trimRe, "") + '";';
					path = path.replace(modeMatch[1], "")
				}
			}
			fn[fn.length] = "return nodup(n);\n}";
			eval(fn.join(""));
			return f
		},
		jsSelect : function (path, root, type) {
			root = root || document;
			if (typeof root == "string")
				root = document.getElementById(root);
			var paths = path.split(",");
			var results = [];
			var i = 0;
			for (var len = paths.length; i < len; i++) {
				var subPath = paths[i].replace(trimRe, "");
				if (!cache[subPath]) {
					cache[subPath] = Ext.DomQuery.compile(subPath);
					if (!cache[subPath])
						throw subPath + " is not a valid selector";
				}
				var result = cache[subPath](root);
				if (result && result != document)
					results = results.concat(result)
			}
			if (paths.length > 1)
				return nodup(results);
			return results
		},
		isXml : function (el) {
			var docEl = (el ? el.ownerDocument || el : 0).documentElement;
			return docEl ? docEl.nodeName !== "HTML" : false
		},
		select : document.querySelectorAll ? function (path, root, type) {
			root = root || document;
			if (!Ext.DomQuery.isXml(root))
				try {
					var cs = root.querySelectorAll(path);
					return Ext.toArray(cs)
				} catch (ex) {}

			return Ext.DomQuery.jsSelect.call(this, path, root, type)
		}
		 :
		function (path, root, type) {
			return Ext.DomQuery.jsSelect.call(this, path, root, type)
		},
		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);
			var v;
			n = n[0] ? n[0] : n;
			if (typeof n.normalize == "function")
				n.normalize();
			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 \x3d byClassName(n, " {1} ");'
			}, {
				re : /^\:([\w\-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
				select : 'n \x3d byPseudo(n, "{1}", "{2}");'
			}, {
				re : /^(?:([\[\{])(?:@)?([\w\-]+)\s?(?:(=|.=)\s?(["']?)(.*?)\4)?[\]\}])/,
				select : 'n \x3d byAttribute(n, "{2}", "{5}", "{3}", "{1}");'
			}, {
				re : /^#([\w\-]+)/,
				select : 'n \x3d byId(n, "{1}");'
			}, {
				re : /^@([\w\-]+)/,
				select : 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
			}
		],
		operators : {
			"\x3d" : function (a, v) {
				return a == v
			},
			"!\x3d" : function (a,
				v) {
				return a != v
			},
			"^\x3d" : function (a, v) {
				return a && a.substr(0, v.length) == v
			},
			"$\x3d" : function (a, v) {
				return a && a.substr(a.length - v.length) == v
			},
			"*\x3d" : function (a, v) {
				return a && a.indexOf(v) !== -1
			},
			"%\x3d" : function (a, v) {
				return a % v == 0
			},
			"|\x3d" : function (a, v) {
				return a && (a == v || a.substr(0, v.length + 1) == v + "-")
			},
			"~\x3d" : function (a, v) {
				return a && (" " + a + " ").indexOf(" " + v + " ") != -1
			}
		},
		pseudos : {
			"first-child" : function (c) {
				var r = [];
				var ri = -1;
				var n;
				var i = 0;
				for (var ci; ci = n = c[i]; i++) {
					for (; (n = n.previousSibling) && n.nodeType != 1; );
					if (!n)
						r[++ri] = ci
				}
				return r
			},
			"last-child" : function (c) {
				var r = [];
				var ri = -1;
				var n;
				var i = 0;
				for (var ci; ci = n = c[i]; i++) {
					for (; (n = n.nextSibling) && n.nodeType != 1; );
					if (!n)
						r[++ri] = ci
				}
				return r
			},
			"nth-child" : function (c, a) {
				var r = [];
				var 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;
				var l = m[2] - 0;
				var i = 0;
				for (var 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 = [];
				var ri = -1;
				var i = 0;
				for (var ci; ci = c[i]; i++)
					if (!prev(ci) && !next(ci))
						r[++ri] = ci;
				return r
			},
			"empty" : function (c) {
				var r = [];
				var ri = -1;
				var i = 0;
				for (var ci; ci = c[i]; i++) {
					var cns = ci.childNodes;
					var j = 0;
					var cn;
					for (var empty = true; 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 = [];
				var ri = -1;
				var i = 0;
				for (var ci; ci =
						c[i]; i++)
					if ((ci.textContent || ci.innerText || "").indexOf(v) != -1)
						r[++ri] = ci;
				return r
			},
			"nodeValue" : function (c, v) {
				var r = [];
				var ri = -1;
				var i = 0;
				for (var ci; ci = c[i]; i++)
					if (ci.firstChild && ci.firstChild.nodeValue == v)
						r[++ri] = ci;
				return r
			},
			"checked" : function (c) {
				var r = [];
				var ri = -1;
				var i = 0;
				for (var 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 = [];
				var ri = -1;
				var s;
				var i = 0;
				for (var 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 = [];
				var ri = -1;
				var i = 0;
				for (var 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 =
					[];
				var ri = -1;
				var i = 0;
				for (var 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 = [];
				var ri = -1;
				var i = 0;
				for (var 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.DelayedTask = function (fn, scope, args) {
	var me = this;
	var id;
	var call = function () {
		clearInterval(id);
		id = null;
		fn.apply(scope, args || [])
	};
	me.delay = function (delay, newFn, newScope, newArgs) {
		me.cancel();
		fn = newFn || fn;
		scope = newScope || scope;
		args = newArgs || args;
		id = setInterval(call, delay)
	};
	me.cancel = function () {
		if (id) {
			clearInterval(id);
			id = null
		}
	}
};
(function () {
	function garbageCollect() {
		if (!Ext.enableGarbageCollector)
			clearInterval(El.collectorThreadId);
		else {
			var eid;
			var el;
			var d;
			var o;
			for (eid in EC) {
				o = EC[eid];
				if (o.skipGC)
					continue;
				el = o.el;
				d = el.dom;
				if (!d || !d.parentNode || !d.offsetParent && !DOC.getElementById(eid)) {
					if (Ext.enableListenerCollection)
						Ext.EventManager.removeAll(d);
					delete EC[eid]
				}
			}
			if (Ext.isIE) {
				var t = {};
				for (eid in EC)
					t[eid] = EC[eid];
				EC = Ext.elCache = t
			}
		}
	}
	var DOC = document;
	Ext.Element = function (element, forceNew) {
		var dom = typeof element == "string" ?
			DOC.getElementById(element) : element;
		var id;
		if (!dom)
			return null;
		id = dom.id;
		if (!forceNew && id && Ext.elCache[id])
			return Ext.elCache[id].el;
		this.dom = dom;
		this.id = id || Ext.id(dom)
	};
	var DH = Ext.DomHelper;
	var El = Ext.Element;
	var EC = Ext.elCache;
	El.prototype = {
		set : function (o, useSet) {
			var el = this.dom;
			var attr;
			var val;
			useSet = useSet !== false && !!el.setAttribute;
			for (attr in o)
				if (o.hasOwnProperty(attr)) {
					val = o[attr];
					if (attr == "style")
						DH.applyStyles(el, val);
					else if (attr == "cls")
						el.className = val;
					else if (useSet)
						el.setAttribute(attr,
							val);
					else
						el[attr] = val
				}
			return this
		},
		defaultUnit : "px",
		is : function (simpleSelector) {
			return Ext.DomQuery.is(this.dom, simpleSelector)
		},
		focus : function (defer, dom) {
			var me = this;
			dom = dom || me.dom;
			try {
				if (Number(defer))
					me.focus.defer(defer, null, [null, dom]);
				else
					dom.focus()
			} catch (e) {}

			return me
		},
		blur : function () {
			try {
				this.dom.blur()
			} catch (e) {}

			return this
		},
		getValue : function (asNumber) {
			var val = this.dom.value;
			return asNumber ? parseInt(val, 10) : val
		},
		addListener : function (eventName, fn, scope, options) {
			Ext.EventManager.on(this.dom,
				eventName, fn, scope || this, options);
			return this
		},
		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
		},
		purgeAllListeners : function () {
			Ext.EventManager.purgeElement(this, true);
			return this
		},
		addUnits : function (size) {
			if (size === "" || size == "auto" || size === undefined)
				size = size || "";
			else if (!isNaN(size) || !unitPattern.test(size))
				size = size + (this.defaultUnit || "px");
			return size
		},
		load : function (url, params, cb) {
			Ext.Ajax.request(Ext.apply({
					params : params,
					url : url.url || url,
					callback : cb,
					el : this.dom,
					indicatorText : url.indicatorText || ""
				}, Ext.isObject(url) ? url : {}));
			return this
		},
		isBorderBox : function () {
			return Ext.isBorderBox || Ext.isForcedBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()]
		},
		remove : function () {
			var me = this;
			var dom = me.dom;
			if (dom) {
				delete me.dom;
				Ext.removeNode(dom)
			}
		},
		hover : function (overFn, outFn, scope, options) {
			var me = this;
			me.on("mouseenter", overFn, scope || me.dom, options);
			me.on("mouseleave", outFn, scope || me.dom, options);
			return me
		},
		contains : function (el) {
			return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el)
		},
		getAttributeNS : function (ns, name) {
			return this.getAttribute(name, ns)
		},
		getAttribute : function () {
			var test = document.createElement("table");
			var isBrokenOnTable = false;
			var hasGetAttribute = "getAttribute" in test;
			var unknownRe = /undefined|unknown/;
			if (hasGetAttribute) {
				try {
					test.getAttribute("ext:qtip")
				} catch (e$$0) {
					isBrokenOnTable = true
				}
				return function (name, ns) {
					var el =
						this.dom;
					var value;
					if (el.getAttributeNS)
						value = el.getAttributeNS(ns, name) || null;
					if (value == null)
						if (ns)
							if (isBrokenOnTable && el.tagName.toUpperCase() == "TABLE")
								try {
									value = el.getAttribute(ns + ":" + name)
								} catch (e) {
									value = ""
								}
							else
								value = el.getAttribute(ns + ":" + name);
						else
							value = el.getAttribute(name) || el[name];
					return value || ""
				}
			} else
				return function (name, ns) {
					var el = this.om;
					var value;
					var attribute;
					if (ns) {
						attribute = el[ns + ":" + name];
						value = unknownRe.test(typeof attribute) ? undefined : attribute
					} else
						value = el[name];
					return value ||
					""
				};
			test = null
		}
		(),
		update : function (html) {
			if (this.dom)
				this.dom.innerHTML = html;
			return this
		}
	};
	var ep = El.prototype;
	El.addMethods = function (o) {
		Ext.apply(ep, o)
	};
	ep.on = ep.addListener;
	ep.un = ep.removeListener;
	ep.autoBoxAdjust = true;
	var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
	var docEl;
	El.get = function (el) {
		var ex;
		var elm;
		var id;
		if (!el)
			return null;
		if (typeof el == "string") {
			if (!(elm = DOC.getElementById(el)))
				return null;
			if (EC[el] && EC[el].el) {
				ex = EC[el].el;
				ex.dom = elm
			} else
				ex = El.addToCache(new El(elm));
			return ex
		} else if (el.tagName) {
			if (!(id =
						el.id))
				id = Ext.id(el);
			if (EC[id] && EC[id].el) {
				ex = EC[id].el;
				ex.dom = el
			} else
				ex = El.addToCache(new El(el));
			return ex
		} else if (el instanceof El) {
			if (el != docEl)
				if (Ext.isIE && (el.id == undefined || el.id == ""))
					el.dom = el.dom;
				else
					el.dom = DOC.getElementById(el.id) || el.dom;
			return el
		} else if (el.isComposite)
			return el;
		else if (Ext.isArray(el))
			return El.select(el);
		else if (el == DOC) {
			if (!docEl) {
				var f = function () {};
				f.prototype = El.prototype;
				docEl = new f;
				docEl.dom = DOC
			}
			return docEl
		}
		return null
	};
	El.addToCache = function (el, id) {
		id = id ||
			el.id;
		EC[id] = {
			el : el,
			data : {},
			events : {}

		};
		return el
	};
	El.data = function (el, key, value) {
		el = El.get(el);
		if (!el)
			return null;
		var c = EC[el.id].data;
		if (arguments.length == 2)
			return c[key];
		else
			return c[key] = value
	};
	El.collectorThreadId = setInterval(garbageCollect, 3E4);
	var flyFn = function () {};
	flyFn.prototype = El.prototype;
	El.Flyweight = function (dom) {
		this.dom = dom
	};
	El.Flyweight.prototype = new flyFn;
	El.Flyweight.prototype.isFlyweight = true;
	El._flyweights = {};
	El.fly = function (el, named) {
		var ret = null;
		named = named || "_global";
		if (el =
				Ext.getDom(el)) {
			(El._flyweights[named] = El._flyweights[named] || new El.Flyweight).dom = el;
			ret = El._flyweights[named]
		}
		return ret
	};
	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.Element.addMethods(function () {
	var PARENTNODE = "parentNode";
	var NEXTSIBLING = "nextSibling";
	var PREVIOUSSIBLING = "previousSibling";
	var DQ = Ext.DomQuery;
	var GET = Ext.get;
	return {
		findParent : function (simpleSelector, maxDepth, returnEl) {
			var p = this.dom;
			var b = document.body;
			var depth = 0;
			var stopEl;
			if (Ext.isGecko && Object.prototype.toString.call(p) == "[object XULElement]")
				return null;
			maxDepth = maxDepth || 50;
			if (isNaN(maxDepth)) {
				stopEl = Ext.getDom(maxDepth);
				maxDepth = Number.MAX_VALUE
			}
			for (; p && p.nodeType == 1 && depth < maxDepth &&
				p != b && p != stopEl; ) {
				if (DQ.is(p, simpleSelector))
					return returnEl ? 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)
		},
		select : function (selector) {
			return Ext.Element.select(selector, this.dom)
		},
		query : function (selector) {
			return DQ.select(selector, this.dom)
		},
		child : function (selector, returnDom) {
			var n = DQ.selectNode(selector, this.dom);
			return returnDom ? n : GET(n)
		},
		down : function (selector, returnDom) {
			var n = DQ.selectNode(" \x3e " + selector, this.dom);
			return returnDom ? n : GET(n)
		},
		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) {
			for (var n = this.dom[start]; n; ) {
				if (n.nodeType == 1 && (!selector || DQ.is(n, selector)))
					return !returnDom ? GET(n) : n;
				n = n[dir]
			}
			return null
		}
	}
}
	());
Ext.Element.addMethods(function () {
	var GETDOM = Ext.getDom;
	var GET = Ext.get;
	var DH = Ext.DomHelper;
	return {
		appendChild : function (el) {
			return GET(el).appendTo(this)
		},
		appendTo : function (el) {
			GETDOM(el).appendChild(this.dom);
			return this
		},
		insertBefore : function (el) {
			(el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
			return this
		},
		insertAfter : function (el) {
			(el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
			return this
		},
		insertFirst : function (el, returnDom) {
			el = el || {};
			if (el.nodeType || el.dom || typeof el == "string") {
				el =
					GETDOM(el);
				this.dom.insertBefore(el, this.dom.firstChild);
				return !returnDom ? GET(el) : el
			} else
				return this.createChild(el, this.dom.firstChild, returnDom)
		},
		replace : function (el) {
			el = GET(el);
			this.insertBefore(el);
			el.remove();
			return this
		},
		replaceWith : function (el) {
			var me = this;
			if (el.nodeType || el.dom || typeof el == "string") {
				el = GETDOM(el);
				me.dom.parentNode.insertBefore(el, me.dom)
			} else
				el = DH.insertBefore(me.dom, el);
			delete Ext.elCache[me.id];
			Ext.removeNode(me.dom);
			me.id = Ext.id(me.dom = el);
			Ext.Element.addToCache(me.isFlyweight ?
				new Ext.Element(me.dom) : me);
			return me
		},
		createChild : function (config, insertBefore, returnDom) {
			config = config || {
				tag : "div"
			};
			return insertBefore ? DH.insertBefore(insertBefore, config, returnDom !== true) : DH[!this.dom.firstChild ? "overwrite" : "append"](this.dom, config, returnDom !== true)
		},
		wrap : function (config, returnDom) {
			var newEl = DH.insertBefore(this.dom, config || {
					tag : "div"
				}, !returnDom);
			newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
			return newEl
		},
		insertHtml : function (where, html, returnEl) {
			var el =
				DH.insertHtml(where, this.dom, html);
			return returnEl ? Ext.get(el) : el
		}
	}
}
	());
Ext.Element.addMethods(function () {
	function camelFn(m, a) {
		return a.charAt(1).toUpperCase()
	}
	function chkCache(prop) {
		return propCache[prop] || (propCache[prop] = prop == "float" ? supports.cssFloat ? "cssFloat" : "styleFloat" : prop.replace(camelRe, camelFn))
	}
	var supports = Ext.supports;
	var propCache = {};
	var camelRe = /(-[a-z])/gi;
	var view = document.defaultView;
	var opacityRe = /alpha\(opacity=(.*)\)/i;
	var trimRe = /^\s+|\s+$/g;
	var EL = Ext.Element;
	var spacesRe = /\s+/;
	var wordsRe = /\w/g;
	var PADDING = "padding";
	var MARGIN = "margin";
	var BORDER =
		"border";
	var LEFT = "-left";
	var RIGHT = "-right";
	var TOP = "-top";
	var BOTTOM = "-bottom";
	var WIDTH = "-width";
	var MATH = Math;
	var HIDDEN = "hidden";
	var ISCLIPPED = "isClipped";
	var OVERFLOW = "overflow";
	var OVERFLOWX = "overflow-x";
	var OVERFLOWY = "overflow-y";
	var ORIGINALCLIP = "originalClip";
	var borders = {
		l : BORDER + LEFT + WIDTH,
		r : BORDER + RIGHT + WIDTH,
		t : BORDER + TOP + WIDTH,
		b : BORDER + BOTTOM + WIDTH
	};
	var paddings = {
		l : PADDING + LEFT,
		r : PADDING + RIGHT,
		t : PADDING + TOP,
		b : PADDING + BOTTOM
	};
	var margins = {
		l : MARGIN + LEFT,
		r : MARGIN + RIGHT,
		t : MARGIN + TOP,
		b : MARGIN +
		BOTTOM
	};
	var data = Ext.Element.data;
	return {
		adjustWidth : function (width) {
			var me = this;
			var isNum = typeof width == "number";
			if (isNum && me.autoBoxAdjust && !me.isBorderBox())
				width -= me.getBorderWidth("lr") + me.getPadding("lr");
			return isNum && width < 0 ? 0 : width
		},
		adjustHeight : function (height) {
			var me = this;
			var isNum = typeof height == "number";
			if (isNum && me.autoBoxAdjust && !me.isBorderBox())
				height -= me.getBorderWidth("tb") + me.getPadding("tb");
			return isNum && height < 0 ? 0 : height
		},
		addClass : function (className) {
			var me = this;
			var i;
			var len;
			var v;
			var cls = [];
			if (!Ext.isArray(className)) {
				if (typeof className == "string" && !this.hasClass(className))
					me.dom.className += " " + className
			} else {
				for (i = 0, len = className.length; i < len; i++) {
					v = className[i];
					if (typeof v == "string" && (" " + me.dom.className + " ").indexOf(" " + v + " ") == -1)
						cls.push(v)
				}
				if (cls.length)
					me.dom.className += " " + cls.join(" ")
			}
			return me
		},
		removeClass : function (className) {
			var me = this;
			var i;
			var idx;
			var len;
			var cls;
			var elClasses;
			if (!Ext.isArray(className))
				className = [className];
			if (me.dom && me.dom.className) {
				elClasses =
					me.dom.className.replace(trimRe, "").split(spacesRe);
				for (i = 0, len = className.length; i < len; i++) {
					cls = className[i];
					if (typeof cls == "string") {
						cls = cls.replace(trimRe, "");
						idx = elClasses.indexOf(cls);
						if (idx != -1)
							elClasses.splice(idx, 1)
					}
				}
				me.dom.className = elClasses.join(" ")
			}
			return me
		},
		radioClass : function (className) {
			var cn = this.dom.parentNode.childNodes;
			var v;
			var i;
			var len;
			className = Ext.isArray(className) ? className : [className];
			for (i = 0, len = cn.length; i < len; i++) {
				v = cn[i];
				if (v && v.nodeType == 1)
					Ext.fly(v, "_internal").removeClass(className)
			}
			return this.addClass(className)
		},
		toggleClass : function (className) {
			return this.hasClass(className) ? this.removeClass(className) : this.addClass(className)
		},
		hasClass : function (className) {
			return className && (" " + this.dom.className + " ").indexOf(" " + className + " ") != -1
		},
		replaceClass : function (oldClassName, newClassName) {
			return this.removeClass(oldClassName).addClass(newClassName)
		},
		isStyle : function (style, val) {
			return this.getStyle(style) == val
		},
		getStyle : function () {
			return view && view.getComputedStyle ? function (prop) {
				var el = this.dom;
				var v;
				var cs;
				var out;
				var display;
				if (el == document)
					return null;
				prop = chkCache(prop);
				out = (v = el.style[prop]) ? v : (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
				if (prop == "marginRight" && out != "0px" && !supports.correctRightMargin) {
					display = el.style.display;
					el.style.display = "inline-block";
					out = view.getComputedStyle(el, "").marginRight;
					el.style.display = display
				}
				if (prop == "backgroundColor" && out == "rgba(0, 0, 0, 0)" && !supports.correctTransparentColor)
					out = "transparent";
				return out
			}
			 : function (prop) {
				var el = this.dom;
				var m;
				var cs;
				if (el == document)
					return null;
				if (prop == "opacity") {
					if (el.style.filter.match)
						if (m = el.style.filter.match(opacityRe)) {
							var fv = parseFloat(m[1]);
							if (!isNaN(fv))
								return fv ? fv / 100 : 0
						}
					return 1
				}
				prop = chkCache(prop);
				return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null)
			}
		}
		(),
		getColor : function (attr, defaultValue, prefix) {
			var v = this.getStyle(attr);
			var color = typeof prefix != "undefined" ? prefix : "#";
			var h;
			if (!v || /transparent|inherit/.test(v))
				return defaultValue;
			if (/^r/.test(v))
				Ext.each(v.slice(4, v.length - 1).split(","), function (s) {
					h = parseInt(s, 10);
					color += (h < 16 ? "0" : "") + h.toString(16)
				});
			else {
				v = v.replace("#", "");
				color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, "$1$1$2$2$3$3") : v
			}
			return color.length > 5 ? color.toLowerCase() : defaultValue
		},
		setStyle : function (prop, value) {
			var tmp;
			var style;
			if (typeof prop != "object") {
				tmp = {};
				tmp[prop] = value;
				prop = tmp
			}
			for (style in prop) {
				value = prop[style];
				style == "opacity" ? this.setOpacity(value) : this.dom.style[chkCache(style)] = value
			}
			return this
		},
		setOpacity : function (opacity, animate) {
			var me = this;
			var s = me.dom.style;
			if (!animate || !me.anim)
				if (Ext.isIE) {
					var opac =
						opacity < 1 ? "alpha(opacity\x3d" + opacity * 100 + ")" : "";
					var val = s.filter.replace(opacityRe, "").replace(trimRe, "");
					s.zoom = 1;
					s.filter = val + (val.length > 0 ? " " : "") + opac
				} else
					s.opacity = opacity;
			else
				me.anim({
					opacity : {
						to : opacity
					}
				}, me.preanim(arguments, 1), null, 0.35, "easeIn");
			return me
		},
		clearOpacity : function () {
			var style = this.dom.style;
			if (Ext.isIE) {
				if (!Ext.isEmpty(style.filter))
					style.filter = style.filter.replace(opacityRe, "").replace(trimRe, "")
			} else
				style.opacity = style["-moz-opacity"] = style["-khtml-opacity"] = "";
			return this
		},
		getHeight : function (contentHeight) {
			var me = this;
			var dom = me.dom;
			var hidden = Ext.isIE && me.isStyle("display", "none");
			var h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
			h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
			return h < 0 ? 0 : h
		},
		getWidth : function (contentWidth) {
			var me = this;
			var dom = me.dom;
			var hidden = Ext.isIE && me.isStyle("display", "none");
			var w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
			w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
			return w < 0 ? 0 : w
		},
		setWidth : function (width, animate) {
			var me = this;
			width = me.adjustWidth(width);
			!animate || !me.anim ? me.dom.style.width = me.addUnits(width) : me.anim({
					width : {
						to : width
					}
				}, me.preanim(arguments, 1));
			return me
		},
		setHeight : function (height, animate) {
			var me = this;
			height = me.adjustHeight(height);
			!animate || !me.anim ? me.dom.style.height = me.addUnits(height) : me.anim({
					height : {
						to : height
					}
				}, me.preanim(arguments, 1));
			return me
		},
		getBorderWidth : function (side) {
			return this.addStyles(side, borders)
		},
		getPadding : function (side) {
			return this.addStyles(side,
				paddings)
		},
		clip : function () {
			var me = this;
			var dom = me.dom;
			if (!data(dom, ISCLIPPED)) {
				data(dom, ISCLIPPED, true);
				data(dom, ORIGINALCLIP, {
					o : me.getStyle(OVERFLOW),
					x : me.getStyle(OVERFLOWX),
					y : me.getStyle(OVERFLOWY)
				});
				me.setStyle(OVERFLOW, HIDDEN);
				me.setStyle(OVERFLOWX, HIDDEN);
				me.setStyle(OVERFLOWY, HIDDEN)
			}
			return me
		},
		unclip : function () {
			var me = this;
			var dom = me.dom;
			if (data(dom, ISCLIPPED)) {
				data(dom, ISCLIPPED, false);
				var o = data(dom, ORIGINALCLIP);
				if (o.o)
					me.setStyle(OVERFLOW, o.o);
				if (o.x)
					me.setStyle(OVERFLOWX, o.x);
				if (o.y)
					me.setStyle(OVERFLOWY,
						o.y)
			}
			return me
		},
		addStyles : function (sides, styles) {
			var ttlSize = 0;
			var sidesArr = sides.match(wordsRe);
			var side;
			var size;
			var i;
			var len = sidesArr.length;
			for (i = 0; i < len; i++) {
				side = sidesArr[i];
				size = side && parseInt(this.getStyle(styles[side]), 10);
				if (size)
					ttlSize += MATH.abs(size)
			}
			return ttlSize
		},
		margins : margins
	}
}
	());
(function () {
	var D = Ext.lib.Dom;
	var LEFT = "left";
	var RIGHT = "right";
	var TOP = "top";
	var BOTTOM = "bottom";
	var POSITION = "position";
	var STATIC = "static";
	var RELATIVE = "relative";
	var AUTO = "auto";
	var ZINDEX = "z-index";
	Ext.Element.addMethods({
		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) {
			return this.setXY([x,
					this.getY()], this.animTest(arguments, animate, 1))
		},
		setY : function (y, animate) {
			return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1))
		},
		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) {
			var me = this;
			if (!animate ||
				!me.anim)
				D.setXY(me.dom, pos);
			else
				me.anim({
					points : {
						to : pos
					}
				}, me.preanim(arguments, 1), "motion");
			return me
		},
		setLocation : function (x, y, animate) {
			return this.setXY([x, y], this.animTest(arguments, animate, 2))
		},
		moveTo : function (x, y, animate) {
			return this.setXY([x, y], this.animTest(arguments, animate, 2))
		},
		getLeft : function (local) {
			return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0
		},
		getRight : function (local) {
			var me = this;
			return !local ? me.getX() + me.getWidth() : me.getLeft(true) + me.getWidth() || 0
		},
		getTop : function (local) {
			return !local ?
			this.getY() : parseInt(this.getStyle(TOP), 10) || 0
		},
		getBottom : function (local) {
			var me = this;
			return !local ? me.getY() + me.getHeight() : me.getTop(true) + me.getHeight() || 0
		},
		position : function (pos, zIndex, x, y) {
			var me = this;
			if (!pos && me.isStyle(POSITION, STATIC))
				me.setStyle(POSITION, RELATIVE);
			else if (pos)
				me.setStyle(POSITION, pos);
			if (zIndex)
				me.setStyle(ZINDEX, zIndex);
			if (x || y)
				me.setXY([x || false, y || false])
		},
		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(ZINDEX)
			}
		},
		setPositioning : function (pc) {
			var me = this;
			var style = me.dom.style;
			me.setStyle(pc);
			if (pc.right == AUTO)
				style.right = "";
			if (pc.bottom == AUTO)
				style.bottom = "";
			return me
		},
		translatePoints : function (x, y) {
			y = isNaN(x[1]) ? y : x[1];
			x = isNaN(x[0]) ? x : x[0];
			var me = this;
			var relative = me.isStyle(POSITION, RELATIVE);
			var o = me.getXY();
			var l = parseInt(me.getStyle(LEFT), 10);
			var t = parseInt(me.getStyle(TOP), 10);
			l = !isNaN(l) ? l : relative ? 0 : me.dom.offsetLeft;
			t = !isNaN(t) ? t : relative ? 0 : me.dom.offsetTop;
			return {
				left : x - o[0] + l,
				top : y - o[1] + t
			}
		},
		animTest : function (args, animate, i) {
			return !!animate && this.preanim ? this.preanim(args, i) : false
		}
	})
})();
Ext.Element.addMethods({
	isScrollable : function () {
		var dom = this.dom;
		return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth
	},
	scrollTo : function (side, value) {
		this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
		return this
	},
	getScroll : function () {
		var d = this.dom;
		var doc = document;
		var body = doc.body;
		var docElement = doc.documentElement;
		var l;
		var t;
		var ret;
		if (d == doc || d == body) {
			if (Ext.isIE && Ext.isStrict) {
				l = docElement.scrollLeft;
				t = docElement.scrollTop
			} else {
				l = window.pageXOffset;
				t = window.pageYOffset
			}
			ret = {
				left : l || (body ? body.scrollLeft : 0),
				top : t || (body ? body.scrollTop : 0)
			}
		} else
			ret = {
				left : d.scrollLeft,
				top : d.scrollTop
			};
		return ret
	}
});
Ext.Element.VISIBILITY = 1;
Ext.Element.DISPLAY = 2;
Ext.Element.OFFSETS = 3;
Ext.Element.ASCLASS = 4;
Ext.Element.visibilityCls = "x-hide-nosize";
Ext.Element.addMethods(function () {
	var El = Ext.Element;
	var OPACITY = "opacity";
	var VISIBILITY = "visibility";
	var DISPLAY = "display";
	var HIDDEN = "hidden";
	var OFFSETS = "offsets";
	var ASCLASS = "asclass";
	var NONE = "none";
	var NOSIZE = "nosize";
	var ORIGINALDISPLAY = "originalDisplay";
	var VISMODE = "visibilityMode";
	var ISVISIBLE = "isVisible";
	var data = El.data;
	var getDisplay = function (dom) {
		var d = data(dom, ORIGINALDISPLAY);
		if (d === undefined)
			data(dom, ORIGINALDISPLAY, d = "");
		return d
	};
	var getVisMode = function (dom) {
		var m = data(dom, VISMODE);
		if (m === undefined)
			data(dom, VISMODE, m = 1);
		return m
	};
	return {
		originalDisplay : "",
		visibilityMode : 1,
		setVisibilityMode : function (visMode) {
			data(this.dom, VISMODE, visMode);
			return this
		},
		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 me = this;
			var anim = Ext.lib.Anim[animType](me.dom, args, opt.duration || defaultDur ||
					0.35, opt.easing || defaultEase || "easeOut", function () {
					if (cb)
						cb.call(me);
					if (opt.callback)
						opt.callback.call(opt.scope || me, me, opt)
				}, me);
			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]
			}
		},
		isVisible : function () {
			var me = this;
			var dom = me.dom;
			var visible = data(dom, ISVISIBLE);
			if (typeof visible == "boolean")
				return visible;
			visible = !me.isStyle(VISIBILITY, HIDDEN) && !me.isStyle(DISPLAY, NONE) && !(getVisMode(dom) == El.ASCLASS && me.hasClass(me.visibilityCls ||
						El.visibilityCls));
			data(dom, ISVISIBLE, visible);
			return visible
		},
		setVisible : function (visible, animate) {
			var me = this;
			var isDisplay;
			var isVisibility;
			var isOffsets;
			var isNosize;
			var dom = me.dom;
			var visMode = getVisMode(dom);
			if (typeof animate == "string") {
				switch (animate) {
				case DISPLAY:
					visMode = El.DISPLAY;
					break;
				case VISIBILITY:
					visMode = El.VISIBILITY;
					break;
				case OFFSETS:
					visMode = El.OFFSETS;
					break;
				case NOSIZE:
				case ASCLASS:
					visMode = El.ASCLASS;
					break
				}
				me.setVisibilityMode(visMode);
				animate = false
			}
			if (!animate || !me.anim)
				if (visMode ==
					El.ASCLASS)
					me[visible ? "removeClass" : "addClass"](me.visibilityCls || El.visibilityCls);
				else if (visMode == El.DISPLAY)
					return me.setDisplayed(visible);
				else if (visMode == El.OFFSETS)
					if (!visible) {
						me.hideModeStyles = {
							position : me.getStyle("position"),
							top : me.getStyle("top"),
							left : me.getStyle("left")
						};
						me.applyStyles({
							position : "absolute",
							top : "-10000px",
							left : "-10000px"
						})
					} else {
						me.applyStyles(me.hideModeStyles || {
							position : "",
							top : "",
							left : ""
						});
						delete me.hideModeStyles
					}
				else {
					me.fixDisplay();
					dom.style.visibility = visible ? "visible" :
						HIDDEN
				}
			else {
				if (visible) {
					me.setOpacity(0.01);
					me.setVisible(true)
				}
				me.anim({
					opacity : {
						to : visible ? 1 : 0
					}
				}, me.preanim(arguments, 1), null, 0.35, "easeIn", function () {
					visible || me.setVisible(false).setOpacity(1)
				})
			}
			data(dom, ISVISIBLE, visible);
			return me
		},
		hasMetrics : function () {
			var dom = this.dom;
			return this.isVisible() || getVisMode(dom) == El.VISIBILITY
		},
		toggle : function (animate) {
			var me = this;
			me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
			return me
		},
		setDisplayed : function (value) {
			if (typeof value == "boolean")
				value = value ?
					getDisplay(this.dom) : NONE;
			this.setStyle(DISPLAY, value);
			return this
		},
		fixDisplay : function () {
			var me = this;
			if (me.isStyle(DISPLAY, NONE)) {
				me.setStyle(VISIBILITY, HIDDEN);
				me.setStyle(DISPLAY, getDisplay(this.dom));
				if (me.isStyle(DISPLAY, NONE))
					me.setStyle(DISPLAY, "block")
			}
		},
		hide : function (animate) {
			if (typeof animate == "string") {
				this.setVisible(false, animate);
				return this
			}
			this.setVisible(false, this.preanim(arguments, 0));
			return this
		},
		show : function (animate) {
			if (typeof animate == "string") {
				this.setVisible(true, animate);
				return this
			}
			this.setVisible(true, this.preanim(arguments, 0));
			return this
		}
	}
}
	());
(function () {
	var NULL = null;
	var UNDEFINED = undefined;
	var TRUE = true;
	var FALSE = false;
	var SETX = "setX";
	var SETY = "setY";
	var SETXY = "setXY";
	var LEFT = "left";
	var BOTTOM = "bottom";
	var TOP = "top";
	var RIGHT = "right";
	var HEIGHT = "height";
	var WIDTH = "width";
	var POINTS = "points";
	var HIDDEN = "hidden";
	var ABSOLUTE = "absolute";
	var VISIBLE = "visible";
	var MOTION = "motion";
	var POSITION = "position";
	var EASEOUT = "easeOut";
	var flyEl = new Ext.Element.Flyweight;
	var queues = {};
	var getObject = function (o) {
		return o || {}

	};
	var fly = function (dom) {
		flyEl.dom =
			dom;
		flyEl.id = Ext.id(dom);
		return flyEl
	};
	var getQueue = function (id) {
		if (!queues[id])
			queues[id] = [];
		return queues[id]
	};
	var setQueue = function (id, value) {
		queues[id] = value
	};
	Ext.enableFx = TRUE;
	Ext.Fx = {
		switchStatements : function (key, fn, argHash) {
			return fn.apply(this, argHash[key])
		},
		slideIn : function (anchor, o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var st = dom.style;
			var xy;
			var r;
			var b;
			var wrap;
			var after;
			var args;
			var pt;
			var bw;
			var bh;
			anchor = anchor || "t";
			me.queueFx(o, function () {
				function after() {
					fly(dom).fxUnwrap(wrap,
						r.pos, o);
					st.width = r.width;
					st.height = r.height;
					fly(dom).afterFx(o)
				}
				function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p) {
					var ret = {};
					fly(wrap).setWidth(ww).setHeight(wh);
					if (fly(wrap)[sXY])
						fly(wrap)[sXY](sXYval);
					style[s1] = style[s2] = "0";
					if (w)
						ret.width = w;
					if (h)
						ret.height = h;
					if (p)
						ret.points = p;
					return ret
				}
				xy = fly(dom).getXY();
				fly(dom).fixDisplay();
				r = fly(dom).getFxRestore();
				b = {
					x : xy[0],
					y : xy[1],
					0 : xy[0],
					1 : xy[1],
					width : dom.offsetWidth,
					height : dom.offsetHeight
				};
				b.right = b.x + b.width;
				b.bottom = b.y + b.height;
				fly(dom).setWidth(b.width).setHeight(b.height);
				wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
				st.visibility = VISIBLE;
				st.position = ABSOLUTE;
				pt = {
					to : [b.x, b.y]
				};
				bw = {
					to : b.width
				};
				bh = {
					to : b.height
				};
				args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
						t : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
						l : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
						r : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
						b : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
						tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
						bl : [wrap, st, 0, 0, SETY,
							b.y + b.height, RIGHT, TOP, bw, bh, pt],
						br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
						tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
					});
				st.visibility = VISIBLE;
				fly(wrap).show();
				arguments.callee.anim = fly(wrap).fxanim(args, o, MOTION, 0.5, EASEOUT, after)
			});
			return me
		},
		slideOut : function (anchor, o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var st = dom.style;
			var xy = me.getXY();
			var wrap;
			var r;
			var b;
			var a;
			var zero = {
				to : 0
			};
			anchor = anchor || "t";
			me.queueFx(o, function () {
				function after() {
					o.useDisplay ? fly(dom).setDisplayed(FALSE) :
					fly(dom).hide();
					fly(dom).fxUnwrap(wrap, r.pos, o);
					st.width = r.width;
					st.height = r.height;
					fly(dom).afterFx(o)
				}
				function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3) {
					var ret = {};
					style[s1] = style[s2] = "0";
					ret[p1] = v1;
					if (p2)
						ret[p2] = v2;
					if (p3)
						ret[p3] = v3;
					return ret
				}
				r = fly(dom).getFxRestore();
				b = {
					x : xy[0],
					y : xy[1],
					0 : xy[0],
					1 : xy[1],
					width : dom.offsetWidth,
					height : dom.offsetHeight
				};
				b.right = b.x + b.width;
				b.bottom = b.y + b.height;
				fly(dom).setWidth(b.width).setHeight(b.height);
				wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
				st.visibility = VISIBLE;
				st.position =
					ABSOLUTE;
				fly(wrap).setWidth(b.width).setHeight(b.height);
				a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
						t : [st, LEFT, BOTTOM, HEIGHT, zero],
						l : [st, RIGHT, TOP, WIDTH, zero],
						r : [st, LEFT, TOP, WIDTH, zero, POINTS, {
								to : [b.right, b.y]
							}
						],
						b : [st, LEFT, TOP, HEIGHT, zero, POINTS, {
								to : [b.x, b.bottom]
							}
						],
						tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
						bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {
								to : [b.x, b.bottom]
							}
						],
						br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {
								to : [b.x + b.width, b.bottom]
							}
						],
						tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT,
							zero, POINTS, {
								to : [b.right, b.y]
							}
						]
					});
				arguments.callee.anim = fly(wrap).fxanim(a, o, MOTION, 0.5, EASEOUT, after)
			});
			return me
		},
		puff : function (o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var st = dom.style;
			var width;
			var height;
			var r;
			me.queueFx(o, function () {
				function after() {
					o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();
					fly(dom).clearOpacity();
					fly(dom).setPositioning(r.pos);
					st.width = r.width;
					st.height = r.height;
					st.fontSize = "";
					fly(dom).afterFx(o)
				}
				width = fly(dom).getWidth();
				height = fly(dom).getHeight();
				fly(dom).clearOpacity();
				fly(dom).show();
				r = fly(dom).getFxRestore();
				arguments.callee.anim = fly(dom).fxanim({
						width : {
							to : fly(dom).adjustWidth(width * 2)
						},
						height : {
							to : fly(dom).adjustHeight(height * 2)
						},
						points : {
							by : [-width * 0.5, -height * 0.5]
						},
						opacity : {
							to : 0
						},
						fontSize : {
							to : 200,
							unit : "%"
						}
					}, o, MOTION, 0.5, EASEOUT, after)
			});
			return me
		},
		switchOff : function (o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var st = dom.style;
			var r;
			me.queueFx(o, function () {
				function after() {
					o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();
					fly(dom).clearOpacity();
					fly(dom).setPositioning(r.pos);
					st.width = r.width;
					st.height = r.height;
					fly(dom).afterFx(o)
				}
				fly(dom).clearOpacity();
				fly(dom).clip();
				r = fly(dom).getFxRestore();
				fly(dom).fxanim({
					opacity : {
						to : 0.3
					}
				}, NULL, NULL, 0.1, NULL, function () {
					fly(dom).clearOpacity();
					(function () {
						fly(dom).fxanim({
							height : {
								to : 1
							},
							points : {
								by : [0, fly(dom).getHeight() * 0.5]
							}
						}, o, MOTION, 0.3, "easeIn", after)
					}).defer(100)
				})
			});
			return me
		},
		highlight : function (color, o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var attr = o.attr || "backgroundColor";
			var a = {};
			var restore;
			me.queueFx(o, function () {
				function after() {
					dom.style[attr] =
						restore;
					fly(dom).afterFx(o)
				}
				fly(dom).clearOpacity();
				fly(dom).show();
				restore = dom.style[attr];
				a[attr] = {
					from : color || "ffff9c",
					to : o.endColor || fly(dom).getColor(attr) || "ffffff"
				};
				arguments.callee.anim = fly(dom).fxanim(a, o, "color", 1, "easeIn", after)
			});
			return me
		},
		frame : function (color, count, o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var proxy;
			var active;
			me.queueFx(o, function () {
				function animFn() {
					var scale = Ext.isBorderBox ? 2 : 1;
					active = proxy.anim({
							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 : o.duration || 1,
							callback : function () {
								proxy.remove();
								--count > 0 ? queue() : fly(dom).afterFx(o)
							}
						});
					arguments.callee.anim = {
						isAnimated : true,
						stop : function () {
							active.stop()
						}
					}
				}
				color = color || "#C3DAF9";
				if (color.length == 6)
					color = "#" + color;
				count = count || 1;
				fly(dom).show();
				var xy = fly(dom).getXY();
				var b = {
					x : xy[0],
					y : xy[1],
					0 : xy[0],
					1 : xy[1],
					width : dom.offsetWidth,
					height : dom.offsetHeight
				};
				var queue = function () {
					proxy =
						fly(document.body || document.documentElement).createChild({
							style : {
								position : ABSOLUTE,
								"z-index" : 35E3,
								border : "0px solid " + color
							}
						});
					return proxy.queueFx({}, animFn)
				};
				arguments.callee.anim = {
					isAnimated : true,
					stop : function () {
						count = 0;
						proxy.stopFx()
					}
				};
				queue()
			});
			return me
		},
		pause : function (seconds) {
			var dom = this.dom;
			var t;
			this.queueFx({}, function () {
				t = setTimeout(function () {
						fly(dom).afterFx({})
					}, seconds * 1E3);
				arguments.callee.anim = {
					isAnimated : true,
					stop : function () {
						clearTimeout(t);
						fly(dom).afterFx({})
					}
				}
			});
			return this
		},
		fadeIn : function (o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var to = o.endOpacity || 1;
			me.queueFx(o, function () {
				fly(dom).setOpacity(0);
				fly(dom).fixDisplay();
				dom.style.visibility = VISIBLE;
				arguments.callee.anim = fly(dom).fxanim({
						opacity : {
							to : to
						}
					}, o, NULL, 0.5, EASEOUT, function () {
						if (to == 1)
							fly(dom).clearOpacity();
						fly(dom).afterFx(o)
					})
			});
			return me
		},
		fadeOut : function (o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var style = dom.style;
			var to = o.endOpacity || 0;
			me.queueFx(o, function () {
				arguments.callee.anim = fly(dom).fxanim({
						opacity : {
							to : to
						}
					},
						o, NULL, 0.5, EASEOUT, function () {
						if (to == 0) {
							Ext.Element.data(dom, "visibilityMode") == Ext.Element.DISPLAY || o.useDisplay ? style.display = "none" : style.visibility = HIDDEN;
							fly(dom).clearOpacity()
						}
						fly(dom).afterFx(o)
					})
			});
			return me
		},
		scale : function (w, h, o) {
			this.shift(Ext.apply({}, o, {
					width : w,
					height : h
				}));
			return this
		},
		shift : function (o) {
			o = getObject(o);
			var dom = this.dom;
			var a = {};
			this.queueFx(o, function () {
				for (var prop in o)
					if (o[prop] != UNDEFINED)
						a[prop] = {
							to : o[prop]
						};
				a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
				a.height ?
				a.height.to = fly(dom).adjustWidth(o.height) : a;
				if (a.x || a.y || a.xy)
					a.points = a.xy || {
						to : [a.x ? a.x.to : fly(dom).getX(), a.y ? a.y.to : fly(dom).getY()]
					};
				arguments.callee.anim = fly(dom).fxanim(a, o, MOTION, 0.35, EASEOUT, function () {
						fly(dom).afterFx(o)
					})
			});
			return this
		},
		ghost : function (anchor, o) {
			o = getObject(o);
			var me = this;
			var dom = me.dom;
			var st = dom.style;
			var a = {
				opacity : {
					to : 0
				},
				points : {}

			};
			var pt = a.points;
			var r;
			var w;
			var h;
			anchor = anchor || "b";
			me.queueFx(o, function () {
				function after() {
					o.useDisplay ? fly(dom).setDisplayed(FALSE) :
					fly(dom).hide();
					fly(dom).clearOpacity();
					fly(dom).setPositioning(r.pos);
					st.width = r.width;
					st.height = r.height;
					fly(dom).afterFx(o)
				}
				r = fly(dom).getFxRestore();
				w = fly(dom).getWidth();
				h = fly(dom).getHeight();
				pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function (v1, v2) {
						return [v1, v2]
					}, {
						t : [0, -h],
						l : [-w, 0],
						r : [w, 0],
						b : [0, h],
						tl : [-w, -h],
						bl : [-w, h],
						br : [w, h],
						tr : [w, -h]
					});
				arguments.callee.anim = fly(dom).fxanim(a, o, MOTION, 0.5, EASEOUT, after)
			});
			return me
		},
		syncFx : function () {
			var me = this;
			me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
					block : FALSE,
					concurrent : TRUE,
					stopFx : FALSE
				});
			return me
		},
		sequenceFx : function () {
			var me = this;
			me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
					block : FALSE,
					concurrent : FALSE,
					stopFx : FALSE
				});
			return me
		},
		nextFx : function () {
			var ef = getQueue(this.dom.id)[0];
			if (ef)
				ef.call(this)
		},
		hasActiveFx : function () {
			return getQueue(this.dom.id)[0]
		},
		stopFx : function (finish) {
			var me = this;
			var id = me.dom.id;
			if (me.hasActiveFx()) {
				var cur = getQueue(id)[0];
				if (cur && cur.anim)
					if (cur.anim.isAnimated) {
						setQueue(id, [cur]);
						cur.anim.stop(finish !== undefined ?
							finish : TRUE)
					} else
						setQueue(id, [])
			}
			return me
		},
		beforeFx : function (o) {
			if (this.hasActiveFx() && !o.concurrent) {
				if (o.stopFx) {
					this.stopFx();
					return TRUE
				}
				return FALSE
			}
			return TRUE
		},
		hasFxBlock : function () {
			var q = getQueue(this.dom.id);
			return q && q[0] && q[0].block
		},
		queueFx : function (o, fn) {
			var me = fly(this.dom);
			if (!me.hasFxBlock()) {
				Ext.applyIf(o, me.fxDefaults);
				if (!o.concurrent) {
					var run = me.beforeFx(o);
					fn.block = o.block;
					getQueue(me.dom.id).push(fn);
					if (run)
						me.nextFx()
				} else
					fn.call(me)
			}
			return me
		},
		fxWrap : function (pos, o, vis) {
			var dom =
				this.dom;
			var wrap;
			var wrapXY;
			if (!o.wrap || !(wrap = Ext.getDom(o.wrap))) {
				if (o.fixPosition)
					wrapXY = fly(dom).getXY();
				var div = document.createElement("div");
				div.style.visibility = vis;
				wrap = dom.parentNode.insertBefore(div, dom);
				fly(wrap).setPositioning(pos);
				if (fly(wrap).isStyle(POSITION, "static"))
					fly(wrap).position("relative");
				fly(dom).clearPositioning("auto");
				fly(wrap).clip();
				wrap.appendChild(dom);
				if (wrapXY)
					fly(wrap).setXY(wrapXY)
			}
			return wrap
		},
		fxUnwrap : function (wrap, pos, o) {
			var dom = this.dom;
			fly(dom).clearPositioning();
			fly(dom).setPositioning(pos);
			if (!o.wrap) {
				var pn = fly(wrap).dom.parentNode;
				pn.insertBefore(dom, wrap);
				fly(wrap).remove()
			}
		},
		getFxRestore : function () {
			var st = this.dom.style;
			return {
				pos : this.getPositioning(),
				width : st.width,
				height : st.height
			}
		},
		afterFx : function (o) {
			var dom = this.dom;
			var id = dom.id;
			if (o.afterStyle)
				fly(dom).setStyle(o.afterStyle);
			if (o.afterCls)
				fly(dom).addClass(o.afterCls);
			if (o.remove == TRUE)
				fly(dom).remove();
			if (o.callback)
				o.callback.call(o.scope, fly(dom));
			if (!o.concurrent) {
				getQueue(id).shift();
				fly(dom).nextFx()
			}
		},
		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 || 0.35, opt.easing || defaultEase || EASEOUT, cb, this);
			opt.anim = anim;
			return anim
		}
	};
	Ext.Fx.resize = Ext.Fx.scale;
	Ext.Element.addMethods(Ext.Fx)
})();
Ext.CompositeElementLite = function (els, root) {
	this.elements = [];
	this.add(els, root);
	this.el = new Ext.Element.Flyweight
};
Ext.CompositeElementLite.prototype = {
	isComposite : true,
	getElement : function (el) {
		var e = this.el;
		e.dom = el;
		e.id = el.id;
		return e
	},
	transformElement : function (el) {
		return Ext.getDom(el)
	},
	getCount : function () {
		return this.elements.length
	},
	add : function (els, root) {
		var me = this;
		var elements = me.elements;
		if (!els)
			return this;
		if (typeof els == "string")
			els = Ext.Element.selectorFunction(els, root);
		else if (els.isComposite)
			els = els.elements;
		else if (!Ext.isIterable(els))
			els = [els];
		var i = 0;
		for (var len = els.length; i < len; ++i)
			elements.push(me.transformElement(els[i]));
		return me
	},
	invoke : function (fn, args) {
		var me = this;
		var els = me.elements;
		var len = els.length;
		var e;
		var i;
		for (i = 0; i < len; i++) {
			e = els[i];
			if (e)
				Ext.Element.prototype[fn].apply(me.getElement(e), args)
		}
		return me
	},
	item : function (index) {
		var me = this;
		var el = me.elements[index];
		var out = null;
		if (el)
			out = me.getElement(el);
		return out
	},
	addListener : function (eventName, handler, scope, opt) {
		var els = this.elements;
		var len = els.length;
		var i;
		var e;
		for (i = 0; i < len; i++) {
			e = els[i];
			if (e)
				Ext.EventManager.on(e, eventName, handler, scope || e, opt)
		}
		return this
	},
	each : function (fn, scope) {
		var me = this;
		var els = me.elements;
		var len = els.length;
		var i;
		var e;
		for (i = 0; i < len; i++) {
			e = els[i];
			if (e) {
				e = this.getElement(e);
				if (fn.call(scope || e, e, me, i) === false)
					break
			}
		}
		return me
	},
	fill : function (els) {
		var me = this;
		me.elements = [];
		me.add(els);
		return me
	},
	filter : function (selector) {
		var els = [];
		var me = this;
		var fn = Ext.isFunction(selector) ? selector : function (el) {
			return el.is(selector)
		};
		me.each(function (el, self, i) {
			if (fn(el, i) !== false)
				els[els.length] = me.transformElement(el)
		});
		me.elements = els;
		return me
	},
	indexOf : function (el) {
		return this.elements.indexOf(this.transformElement(el))
	},
	replaceElement : function (el, replacement, domReplace) {
		var index = !isNaN(el) ? el : this.indexOf(el);
		var d;
		if (index > -1) {
			replacement = Ext.getDom(replacement);
			if (domReplace) {
				d = this.elements[index];
				d.parentNode.insertBefore(replacement, d);
				Ext.removeNode(d)
			}
			this.elements.splice(index, 1, replacement)
		}
		return this
	},
	clear : function () {
		this.elements = []
	}
};
Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
Ext.CompositeElementLite.importElementMethods = function () {
	var fnName;
	var ElProto = Ext.Element.prototype;
	var CelProto = Ext.CompositeElementLite.prototype;
	for (fnName in ElProto)
		if (typeof ElProto[fnName] == "function")
			(function (fnName) {
				CelProto[fnName] = CelProto[fnName] || function () {
					return this.invoke(fnName, arguments)
				}
			}).call(CelProto, fnName)
};
Ext.CompositeElementLite.importElementMethods();
if (Ext.DomQuery)
	Ext.Element.selectorFunction = Ext.DomQuery.select;
Ext.Element.select = function (selector, root) {
	var els;
	if (typeof selector == "string")
		els = Ext.Element.selectorFunction(selector, root);
	else if (selector.length !== undefined)
		els = selector;
	else
		throw "Invalid selector";
	return new Ext.CompositeElementLite(els)
};
Ext.select = Ext.Element.select;
(function () {
	var BEFOREREQUEST = "beforerequest";
	var REQUESTCOMPLETE = "requestcomplete";
	var REQUESTEXCEPTION = "requestexception";
	var UNDEFINED = undefined;
	var LOAD = "load";
	var POST = "POST";
	var GET = "GET";
	var WINDOW = window;
	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 : 3E4,
		autoAbort : false,
		disableCaching : true,
		disableCachingParam : "_dc",
		request : function (o) {
			var me = this;
			if (me.fireEvent(BEFOREREQUEST, me, o)) {
				if (o.el) {
					if (!Ext.isEmpty(o.indicatorText))
						me.indicatorText = '\x3cdiv class\x3d"loading-indicator"\x3e' + o.indicatorText + "\x3c/div\x3e";
					if (me.indicatorText)
						Ext.getDom(o.el).innerHTML = me.indicatorText;
					o.success = (Ext.isFunction(o.success) ? o.success : function () {}).createInterceptor(function (response) {
						Ext.getDom(o.el).innerHTML = response.responseText
					})
				}
				var p = o.params;
				var url = o.url || me.url;
				var method;
				var cb = {
					success : me.handleResponse,
					failure : me.handleFailure,
					scope : me,
					argument : {
						options : o
					},
					timeout : Ext.num(o.timeout, me.timeout)
				};
				var form;
				var serForm;
				if (Ext.isFunction(p))
					p = p.call(o.scope || WINDOW, o);
				p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
				if (Ext.isFunction(url))
					url = url.call(o.scope || WINDOW, o);
				if (form = Ext.getDom(o.form)) {
					url = url || form.action;
					if (o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype")))
						return me.doFormUpload.call(me, o, p, url);
					serForm = Ext.lib.Ajax.serializeForm(form);
					p = p ? p + "\x26" + serForm : serForm
				}
				method =
					o.method || me.method || (p || o.xmlData || o.jsonData ? POST : GET);
				if (method === GET && me.disableCaching && o.disableCaching !== false || o.disableCaching === true) {
					var dcp = o.disableCachingParam || me.disableCachingParam;
					url = Ext.urlAppend(url, dcp + "\x3d" + (new Date).getTime())
				}
				o.headers = Ext.applyIf(o.headers || {}, me.defaultHeaders || {});
				if (o.autoAbort === true || me.autoAbort)
					me.abort();
				if ((method == GET || o.xmlData || o.jsonData) && p) {
					url = Ext.urlAppend(url, p);
					p = ""
				}
				return me.transId = Ext.lib.Ajax.request(method, url, cb, p, o)
			} else
				return o.callback ?
				o.callback.apply(o.scope, [o, UNDEFINED, UNDEFINED]) : null
		},
		isLoading : function (transId) {
			return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !!this.transId
		},
		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);
			if (options.success)
				options.success.call(options.scope, response,
					options);
			if (options.callback)
				options.callback.call(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);
			if (options.failure)
				options.failure.call(options.scope, response, options);
			if (options.callback)
				options.callback.call(options.scope, options, false, response)
		},
		doFormUpload : function (o, ps, url) {
			function cb() {
				function runCallback(fn,
					scope, args) {
					if (Ext.isFunction(fn))
						fn.apply(scope, args)
				}
				var me = this;
				var r = {
					responseText : "",
					responseXML : null,
					argument : o.argument
				};
				var doc;
				var firstChild;
				try {
					doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
					if (doc) {
						if (doc.body)
							if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName))
								r.responseText = firstChild.value;
							else
								r.responseText = doc.body.innerHTML;
						r.responseXML = doc.XMLDocument || doc
					}
				} catch (e) {}

				Ext.EventManager.removeListener(frame, LOAD, cb, me);
				me.fireEvent(REQUESTCOMPLETE,
					me, r, o);
				runCallback(o.success, o.scope, [r, o]);
				runCallback(o.callback, o.scope, [o, true, r]);
				if (!me.debugUploads)
					setTimeout(function () {
						Ext.removeNode(frame)
					}, 100)
			}
			var id = Ext.id();
			var doc$$0 = document;
			var frame = doc$$0.createElement("iframe");
			var form = Ext.getDom(o.form);
			var hiddens = [];
			var hd;
			var encoding = "multipart/form-data";
			var buf = {
				target : form.target,
				method : form.method,
				encoding : form.encoding,
				enctype : form.enctype,
				action : form.action
			};
			Ext.fly(frame).set({
				id : id,
				name : id,
				cls : "x-hidden",
				src : Ext.SSL_SECURE_URL
			});
			doc$$0.body.appendChild(frame);
			if (Ext.isIE)
				document.frames[id].name = id;
			Ext.fly(form).set({
				target : id,
				method : POST,
				enctype : encoding,
				encoding : encoding,
				action : url || buf.action
			});
			Ext.iterate(Ext.urlDecode(ps, false), function (k, v) {
				hd = doc$$0.createElement("input");
				Ext.fly(hd).set({
					type : "hidden",
					value : v,
					name : k
				});
				form.appendChild(hd);
				hiddens.push(hd)
			});
			Ext.EventManager.on(frame, LOAD, cb, this);
			form.submit();
			Ext.fly(form).set(buf);
			Ext.each(hiddens, function (h) {
				Ext.removeNode(h)
			})
		}
	})
})();
Ext.Ajax = new Ext.data.Connection({
		autoAbort : false,
		serializeForm : function (form) {
			return Ext.lib.Ajax.serializeForm(form)
		}
	});
Ext.util.JSON = new function () {
	var useHasOwn = !!{}

	.hasOwnProperty;
	var isNative = function () {
		var useNative = null;
		return function () {
			if (useNative === null)
				useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == "[object JSON]";
			return useNative
		}
	}
	();
	var pad = function (n) {
		return n < 10 ? "0" + n : n
	};
	var doDecode = function (json) {
		return json ? eval("(" + json + ")") : ""
	};
	var doEncode = function (o) {
		if (!Ext.isDefined(o) || 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 (Ext.isString(o))
			return encodeString(o);
		else if (typeof o == "number")
			return isFinite(o) ? String(o) : "null";
		else if (Ext.isBoolean(o))
			return String(o);
		else {
			var a = ["{"];
			var b;
			var i;
			var v;
			for (i in o)
				if (!o.getElementsByTagName)
					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(doEncode(i), ":", v === null ? "null" : doEncode(v));
							b = true
						}
					}
			a.push("}");
			return a.join("")
		}
	};
	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 = ["["];
		var b;
		var i;
		var l = o.length;
		var 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 () {
		var ec;
		return function (o) {
			if (!ec)
				ec = isNative() ? JSON.stringify : doEncode;
			return ec(o)
		}
	}
	();
	this.decode = function () {
		var dc;
		return function (json) {
			if (!dc)
				dc = isNative() ? JSON.parse : doDecode;
			return dc(json)
		}
	}
	()
};
Ext.encode = Ext.util.JSON.encode;
Ext.decode = Ext.util.JSON.decode;
Ext.EventManager = function () {
	function getId(el) {
		var id = false;
		var i = 0;
		var len = specialElCache.length;
		var skip = false;
		var o;
		if (el) {
			if (el.getElementById || el.navigator) {
				for (; i < len; ++i) {
					o = specialElCache[i];
					if (o.el === el) {
						id = o.id;
						break
					}
				}
				if (!id) {
					id = Ext.id(el);
					specialElCache.push({
						id : id,
						el : el
					});
					skip = true
				}
			} else
				id = Ext.id(el);
			if (!Ext.elCache[id]) {
				Ext.Element.addToCache(new Ext.Element(el), id);
				if (skip)
					Ext.elCache[id].skipGC = true
			}
		}
		return id
	}
	function addListener(el, ename, fn, task, wrap, scope) {
		el = Ext.getDom(el);
		var id =
			getId(el);
		var es = Ext.elCache[id].events;
		var wfn;
		wfn = E.on(el, ename, wrap);
		es[ename] = es[ename] || [];
		es[ename].push([fn, wrap, scope, wfn, task]);
		if (el.addEventListener && ename == "mousewheel") {
			var args = ["DOMMouseScroll", wrap, false];
			el.addEventListener.apply(el, args);
			Ext.EventManager.addListener(WINDOW, "unload", function () {
				el.removeEventListener.apply(el, args)
			})
		}
		if (el == DOC && ename == "mousedown")
			Ext.EventManager.stoppedMouseDownEvent.addListener(wrap)
	}
	function doScrollChk() {
		if (window != top)
			return false;
		try {
			DOC.documentElement.doScroll("left")
		} catch (e) {
			return false
		}
		fireDocReady();
		return true
	}
	function checkReadyState(e) {
		if (Ext.isIE && doScrollChk())
			return true;
		if (DOC.readyState == COMPLETE) {
			fireDocReady();
			return true
		}
		docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
		return false
	}
	function checkStyleSheets(e) {
		styles || (styles = Ext.query("style, link[rel\x3dstylesheet]"));
		if (styles.length == DOC.styleSheets.length) {
			fireDocReady();
			return true
		}
		docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
		return false
	}
	function OperaDOMContentLoaded(e) {
		DOC.removeEventListener(DOMCONTENTLOADED,
			arguments.callee, false);
		checkStyleSheets()
	}
	function fireDocReady(e) {
		if (!docReadyState) {
			docReadyState = true;
			if (docReadyProcId)
				clearTimeout(docReadyProcId);
			if (DETECT_NATIVE)
				DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
			if (Ext.isIE && checkReadyState.bindIE)
				DOC.detachEvent("onreadystatechange", checkReadyState);
			E.un(WINDOW, "load", arguments.callee)
		}
		if (docReadyEvent && !Ext.isReady) {
			Ext.isReady = true;
			docReadyEvent.fire();
			docReadyEvent.listeners = []
		}
	}
	function initDocReady() {
		docReadyEvent || (docReadyEvent =
				new Ext.util.Event);
		if (DETECT_NATIVE)
			DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
		if (Ext.isIE) {
			if (!checkReadyState()) {
				checkReadyState.bindIE = true;
				DOC.attachEvent("onreadystatechange", checkReadyState)
			}
		} else if (Ext.isOpera)
			DOC.readyState == COMPLETE && checkStyleSheets() || DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
		else if (Ext.isWebKit)
			checkReadyState();
		E.on(WINDOW, "load", fireDocReady)
	}
	function createTargeted(h, o) {
		return function () {
			var args = Ext.toArray(arguments);
			if (o.target ==
				Ext.EventObject.setEvent(args[0]).target)
				h.apply(this, args)
		}
	}
	function createBuffered(h, o, task) {
		return function (e) {
			task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)])
		}
	}
	function createSingle(h, el, ename, fn, scope) {
		return function (e) {
			Ext.EventManager.removeListener(el, ename, fn, scope);
			h(e)
		}
	}
	function createDelayed(h, o, fn) {
		return function (e) {
			var task = new Ext.util.DelayedTask(h);
			if (!fn.tasks)
				fn.tasks = [];
			fn.tasks.push(task);
			task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)])
		}
	}
	function listen(element,
		ename, opt, fn, scope) {
		function h(e) {
			if (!Ext)
				return;
			e = Ext.EventObject.setEvent(e);
			var t;
			if (o.delegate) {
				if (!(t = e.getTarget(o.delegate, el)))
					return
			} else
				t = e.target;
			if (o.stopEvent)
				e.stopEvent();
			if (o.preventDefault)
				e.preventDefault();
			if (o.stopPropagation)
				e.stopPropagation();
			if (o.normalized === false)
				e = e.browserEvent;
			fn.call(scope || el, e, t, o)
		}
		var o = !opt || typeof opt == "boolean" ? {}

		 : opt;
		var el = Ext.getDom(element);
		var task;
		fn = fn || o.fn;
		scope = scope || o.scope;
		if (!el)
			throw 'Error listening for "' + ename + '". Element "' + element +
			"\" doesn't exist.";
		if (o.target)
			h = createTargeted(h, o);
		if (o.delay)
			h = createDelayed(h, o, fn);
		if (o.single)
			h = createSingle(h, el, ename, fn, scope);
		if (o.buffer) {
			task = new Ext.util.DelayedTask(h);
			h = createBuffered(h, o, task)
		}
		addListener(el, ename, fn, task, h, scope);
		return h
	}
	var docReadyEvent;
	var docReadyProcId;
	var docReadyState = false;
	var DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari;
	var E = Ext.lib.Event;
	var D = Ext.lib.Dom;
	var DOC = document;
	var WINDOW = window;
	var DOMCONTENTLOADED = "DOMContentLoaded";
	var COMPLETE =
		"complete";
	var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
	var specialElCache = [];
	var styles;
	var pub = {
		addListener : function (element, eventName, fn, scope, options) {
			if (typeof eventName == "object") {
				var o = eventName;
				var e;
				var val;
				for (e in o) {
					val = o[e];
					if (!propRe.test(e))
						if (Ext.isFunction(val))
							listen(element, e, o, val, o.scope);
						else
							listen(element, e, val)
				}
			} else
				listen(element, eventName, options, fn, scope)
		},
		removeListener : function (el, eventName, fn, scope) {
			el =
				Ext.getDom(el);
			var id = getId(el);
			var f = el && Ext.elCache[id].events[eventName] || [];
			var wrap;
			var i;
			var l;
			var k;
			var len;
			var fnc;
			for (i = 0, len = f.length; i < len; i++)
				if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
					if (fnc[4])
						fnc[4].cancel();
					k = fn.tasks && fn.tasks.length;
					if (k) {
						for (; k--; )
							fn.tasks[k].cancel();
						delete fn.tasks
					}
					wrap = fnc[1];
					E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
					if (wrap && el.addEventListener && eventName == "mousewheel")
						el.removeEventListener("DOMMouseScroll", wrap, false);
					if (wrap && el == DOC &&
						eventName == "mousedown")
						Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
					f.splice(i, 1);
					if (f.length === 0)
						delete Ext.elCache[id].events[eventName];
					for (k in Ext.elCache[id].events)
						return false;
					Ext.elCache[id].events = {};
					return false
				}
		},
		removeAll : function (el) {
			el = Ext.getDom(el);
			var id = getId(el);
			var ec = Ext.elCache[id] || {};
			var es = ec.events || {};
			var f;
			var i;
			var len;
			var ename;
			var fn;
			var k;
			var wrap;
			for (ename in es)
				if (es.hasOwnProperty(ename)) {
					f = es[ename];
					for (i = 0, len = f.length; i < len; i++) {
						fn = f[i];
						if (fn[4])
							fn[4].cancel();
						if (fn[0].tasks && (k = fn[0].tasks.length)) {
							for (; k--; )
								fn[0].tasks[k].cancel();
							delete fn.tasks
						}
						wrap = fn[1];
						E.un(el, ename, E.extAdapter ? fn[3] : wrap);
						if (el.addEventListener && wrap && ename == "mousewheel")
							el.removeEventListener("DOMMouseScroll", wrap, false);
						if (wrap && el == DOC && ename == "mousedown")
							Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap)
					}
				}
			if (Ext.elCache[id])
				Ext.elCache[id].events = {}

		},
		getListeners : function (el, eventName) {
			el = Ext.getDom(el);
			var id = getId(el);
			var ec = Ext.elCache[id] || {};
			var es = ec.events || {};
			var results = [];
			if (es && es[eventName])
				return es[eventName];
			else
				return null
		},
		purgeElement : function (el, recurse, eventName) {
			el = Ext.getDom(el);
			var id = getId(el);
			var ec = Ext.elCache[id] || {};
			var es = ec.events || {};
			var i;
			var f;
			var len;
			if (eventName) {
				if (es && es.hasOwnProperty(eventName)) {
					f = es[eventName];
					for (i = 0, len = f.length; i < len; i++)
						Ext.EventManager.removeListener(el, eventName, f[i][0])
				}
			} else
				Ext.EventManager.removeAll(el);
			if (recurse && el && el.childNodes)
				for (i = 0, len = el.childNodes.length; i < len; i++)
					Ext.EventManager.purgeElement(el.childNodes[i],
						recurse, eventName)
		},
		_unload : function () {
			for (var el in Ext.elCache)
				Ext.EventManager.removeAll(el);
			delete Ext.elCache;
			delete Ext.Element._flyweights;
			var c;
			var conn;
			var tid;
			var ajax = Ext.lib.Ajax;
			typeof ajax.conn == "object" ? conn = ajax.conn : conn = {};
			for (tid in conn) {
				c = conn[tid];
				if (c)
					ajax.abort({
						conn : c,
						tId : tid
					})
			}
		},
		onDocumentReady : function (fn, scope, options) {
			if (Ext.isReady) {
				docReadyEvent || (docReadyEvent = new Ext.util.Event);
				docReadyEvent.addListener(fn, scope, options);
				docReadyEvent.fire();
				docReadyEvent.listeners =
					[]
			} else {
				if (!docReadyEvent)
					initDocReady();
				options = options || {};
				options.delay = options.delay || 1;
				docReadyEvent.addListener(fn, scope, options)
			}
		},
		fireDocReady : fireDocReady
	};
	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.isIE7 ? "ext-ie7" : Ext.isIE8 ? "ext-ie8" : "ext-ie9") : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? "ext-gecko2" : "ext-gecko3") : Ext.isOpera ? "ext-opera" : Ext.isWebKit ? "ext-webkit" : ""];
		if (Ext.isSafari)
			cls.push("ext-safari " + (Ext.isSafari2 ? "ext-safari2" : Ext.isSafari3 ? "ext-safari3" : "ext-safari4"));
		else if (Ext.isChrome)
			cls.push("ext-chrome");
		if (Ext.isMac)
			cls.push("ext-mac");
		if (Ext.isLinux)
			cls.push("ext-linux");
		if (Ext.isStrict || Ext.isBorderBox) {
			var p = bd.parentNode;
			if (p) {
				if (!Ext.isStrict) {
					Ext.fly(p, "_internal").addClass("x-quirks");
					if (Ext.isIE && !Ext.isStrict)
						Ext.isIEQuirks = true
				}
				Ext.fly(p, "_internal").addClass(Ext.isStrict && Ext.isIE || !Ext.enableForcedBoxModel && !Ext.isIE ? " ext-strict" : " ext-border-box")
			}
		}
		if (Ext.enableForcedBoxModel && !Ext.isIE) {
			Ext.isForcedBorderBox = true;
			cls.push("ext-forced-border-box")
		}
		Ext.fly(bd, "_internal").addClass(cls);
		return true
	};
	if (!initExtCss())
		Ext.onReady(initExtCss)
})();
(function () {
	var supports = Ext.apply(Ext.supports, {
			correctRightMargin : true,
			correctTransparentColor : true,
			cssFloat : true
		});
	var supportTests = function () {
		var div = document.createElement("div");
		var doc = document;
		var view;
		var last;
		div.innerHTML = '\x3cdiv style\x3d"height:30px;width:50px;"\x3e\x3cdiv style\x3d"height:20px;width:20px;"\x3e\x3c/div\x3e\x3c/div\x3e\x3cdiv style\x3d"float:left;background-color:transparent;"\x3e';
		doc.body.appendChild(div);
		last = div.lastChild;
		if (view = doc.defaultView) {
			if (view.getComputedStyle(div.firstChild.firstChild,
					null).marginRight != "0px")
				supports.correctRightMargin = false;
			if (view.getComputedStyle(last, null).backgroundColor != "transparent")
				supports.correctTransparentColor = false
		}
		supports.cssFloat = !!last.style.cssFloat;
		doc.body.removeChild(div)
	};
	if (Ext.isReady)
		supportTests();
	else
		Ext.onReady(supportTests)
})();
Ext.EventObject = function () {
	var E = Ext.lib.Event;
	var clickRe = /(dbl)?click/;
	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
	}
	 : {
		0 : 0,
		1 : 1,
		2 : 2
	};
	Ext.EventObjectImpl = function (e) {
		if (e)
			this.setEvent(e.browserEvent || e)
	};
	Ext.EventObjectImpl.prototype = {
		setEvent : function (e) {
			var me = this;
			if (e == me || e && e.browserEvent)
				return e;
			me.browserEvent = e;
			if (e) {
				me.button = e.button ? btnMap[e.button] : e.which ? e.which - 1 : -1;
				if (clickRe.test(e.type) &&
					me.button == -1)
					me.button = 0;
				me.type = e.type;
				me.shiftKey = e.shiftKey;
				me.ctrlKey = e.ctrlKey || e.metaKey || false;
				me.altKey = e.altKey;
				me.keyCode = e.keyCode;
				me.charCode = e.charCode;
				me.target = E.getTarget(e);
				me.xy = E.getXY(e)
			} else {
				me.button = -1;
				me.shiftKey = false;
				me.ctrlKey = false;
				me.altKey = false;
				me.keyCode = 0;
				me.charCode = 0;
				me.target = null;
				me.xy = [0, 0]
			}
			return me
		},
		stopEvent : function () {
			var me = this;
			if (me.browserEvent) {
				if (me.browserEvent.type == "mousedown")
					Ext.EventManager.stoppedMouseDownEvent.fire(me);
				E.stopEvent(me.browserEvent)
			}
		},
		preventDefault : function () {
			if (this.browserEvent)
				E.preventDefault(this.browserEvent)
		},
		stopPropagation : function () {
			var me = this;
			if (me.browserEvent) {
				if (me.browserEvent.type == "mousedown")
					Ext.EventManager.stoppedMouseDownEvent.fire(me);
				E.stopPropagation(me.browserEvent)
			}
		},
		getCharCode : function () {
			return this.charCode || this.keyCode
		},
		getKey : function () {
			return this.normalizeKey(this.keyCode || this.charCode)
		},
		normalizeKey : function (k) {
			return Ext.isSafari ? safariKeys[k] || k : k
		},
		getPageX : function () {
			return this.xy[0]
		},
		getPageY : function () {
			return this.xy[1]
		},
		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 () {
			return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : 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
		},
		within : function (el,
			related, allowEl) {
			if (el) {
				var t = this[related ? "getRelatedTarget" : "getTarget"]();
				return t && ((allowEl ? t == Ext.getDom(el) : false) || Ext.fly(el).contains(t))
			}
			return false
		}
	};
	return new Ext.EventObjectImpl
}
();
Ext.Loader = Ext.apply({}, {
		load : function (fileList, callback, scope, preserveOrder) {
			scope = scope || this;
			var head = document.getElementsByTagName("head")[0];
			var fragment = document.createDocumentFragment();
			var numFiles = fileList.length;
			var loadedFiles = 0;
			var me = this;
			var loadFileIndex = function (index) {
				head.appendChild(me.buildScriptTag(fileList[index], onFileLoaded))
			};
			var onFileLoaded = function () {
				loadedFiles++;
				if (numFiles == loadedFiles && typeof callback == "function")
					callback.call(scope);
				else if (preserveOrder === true)
					loadFileIndex(loadedFiles)
			};
			if (preserveOrder === true)
				loadFileIndex.call(this, 0);
			else {
				Ext.each(fileList, function (file, index) {
					fragment.appendChild(this.buildScriptTag(file, onFileLoaded))
				}, this);
				head.appendChild(fragment)
			}
		},
		buildScriptTag : function (filename, callback) {
			var script = document.createElement("script");
			script.type = "text/javascript";
			script.src = filename;
			if (script.readyState)
				script.onreadystatechange = function () {
					if (script.readyState == "loaded" || script.readyState == "complete") {
						script.onreadystatechange = null;
						callback()
					}
				};
			else
				script.onload =
					callback;
			return script
		}
	});
Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu", "Ext.state", "Ext.layout.boxOverflow", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct", "Ext.slider");
Ext.apply(Ext, function () {
	var E = Ext;
	var idSeed = 0;
	var scrollWidth = null;
	return {
		emptyFn : function () {},
		BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ? "http:/" + "/www.extjs.com/s.gif" : "data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw\x3d\x3d",
		extendX : function (supr, fn) {
			return Ext.extend(supr, fn(supr.prototype))
		},
		getDoc : function () {
			return Ext.get(document)
		},
		num : function (v, defaultValue) {
			v = Number(Ext.isEmpty(v) || Ext.isArray(v) || typeof v == "boolean" || typeof v == "string" && v.trim().length ==
					0 ? NaN : v);
			return isNaN(v) ? defaultValue : v
		},
		value : function (v, defaultValue, allowBlank) {
			return Ext.isEmpty(v, allowBlank) ? defaultValue : v
		},
		escapeRe : function (s) {
			return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1")
		},
		sequence : function (o, name, fn, scope) {
			o[name] = o[name].createSequence(fn, scope)
		},
		addBehaviors : function (o) {
			if (!Ext.isReady)
				Ext.onReady(function () {
					Ext.addBehaviors(o)
				});
			else {
				var cache = {};
				var parts;
				var b;
				var s;
				for (b in o)
					if ((parts = b.split("@"))[1]) {
						s = parts[0];
						if (!cache[s])
							cache[s] = Ext.select(s);
						cache[s].on(parts[1],
							o[b])
					}
				cache = null
			}
		},
		getScrollBarWidth : function (force) {
			if (!Ext.isReady)
				return 0;
			if (force === true || scrollWidth === null) {
				var div = Ext.getBody().createChild('\x3cdiv class\x3d"x-hide-offsets" style\x3d"width:100px;height:50px;overflow:hidden;"\x3e\x3cdiv style\x3d"height:200px;"\x3e\x3c/div\x3e\x3c/div\x3e');
				var child = div.child("div", true);
				var w1 = child.offsetWidth;
				div.setStyle("overflow", Ext.isWebKit || Ext.isGecko ? "auto" : "scroll");
				var w2 = child.offsetWidth;
				div.remove();
				scrollWidth = w1 - w2 + 2
			}
			return scrollWidth
		},
		combine : function () {
			var as = arguments;
			var l = as.length;
			var 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
		},
		copyTo : function (dest, source, names) {
			if (typeof names == "string")
				names = names.split(/[,;\s]/);
			Ext.each(names, function (name) {
				if (source.hasOwnProperty(name))
					dest[name] = source[name]
			}, this);
			return dest
		},
		destroy : function () {
			Ext.each(arguments, function (arg) {
				if (arg)
					if (Ext.isArray(arg))
						this.destroy.apply(this,
							arg);
					else if (typeof arg.destroy == "function")
						arg.destroy();
					else if (arg.dom)
						arg.remove()
			}, this)
		},
		destroyMembers : function (o, arg1, arg2, etc) {
			var i = 1;
			var a = arguments;
			for (var len = a.length; i < len; i++) {
				Ext.destroy(o[a[i]]);
				delete o[a[i]]
			}
		},
		clean : function (arr) {
			var ret = [];
			Ext.each(arr, function (v) {
				if (!!v)
					ret.push(v)
			});
			return ret
		},
		unique : function (arr) {
			var ret = [];
			var collect = {};
			Ext.each(arr, function (v) {
				if (!collect[v])
					ret.push(v);
				collect[v] = true
			});
			return ret
		},
		flatten : function (arr) {
			function rFlatten(a) {
				Ext.each(a,
					function (v) {
					if (Ext.isArray(v))
						rFlatten(v);
					else
						worker.push(v)
				});
				return worker
			}
			var worker = [];
			return rFlatten(arr)
		},
		min : function (arr, comp) {
			var ret = arr[0];
			comp = comp || function (a, b) {
				return a < b ? -1 : 1
			};
			Ext.each(arr, function (v) {
				ret = comp(ret, v) == -1 ? ret : v
			});
			return ret
		},
		max : function (arr, comp) {
			var ret = arr[0];
			comp = comp || function (a, b) {
				return a > b ? 1 : -1
			};
			Ext.each(arr, function (v) {
				ret = comp(ret, v) == 1 ? ret : v
			});
			return ret
		},
		mean : function (arr) {
			return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined
		},
		sum : function (arr) {
			var ret =
				0;
			Ext.each(arr, function (v) {
				ret += v
			});
			return ret
		},
		partition : function (arr, truth) {
			var ret = [[], []];
			Ext.each(arr, function (v, i, a) {
				ret[truth && truth(v, i, a) || !truth && v ? 0 : 1].push(v)
			});
			return ret
		},
		invoke : function (arr, methodName) {
			var ret = [];
			var args = Array.prototype.slice.call(arguments, 2);
			Ext.each(arr, function (v, i) {
				if (v && typeof v[methodName] == "function")
					ret.push(v[methodName].apply(v, args));
				else
					ret.push(undefined)
			});
			return ret
		},
		pluck : function (arr, prop) {
			var ret = [];
			Ext.each(arr, function (v) {
				ret.push(v[prop])
			});
			return ret
		},
		zip : function () {
			var parts = Ext.partition(arguments, function (val) {
					return typeof val != "function"
				});
			var arrs = parts[0];
			var fn = parts[1][0];
			var len = Ext.max(Ext.pluck(arrs, "length"));
			var ret = [];
			for (var i = 0; i < len; i++) {
				ret[i] = [];
				if (fn)
					ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
				else {
					var j = 0;
					for (var aLen = arrs.length; j < aLen; j++)
						ret[i].push(arrs[j][i])
				}
			}
			return ret
		},
		getCmp : function (id) {
			return Ext.ComponentMgr.get(id)
		},
		useShims : E.isIE6 || E.isMac && E.isGecko2,
		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";
				case Date:
					return "date"
				}
				if (typeof o.length == "number" && typeof o.item == "function")
					return "nodelist"
			}
			return t
		},
		intercept : function (o, name, fn, scope) {
			o[name] = o[name].createInterceptor(fn, scope)
		},
		callback : function (cb, scope, args,
			delay) {
			if (typeof cb == "function")
				if (delay)
					cb.defer(delay, scope, args || []);
				else
					cb.apply(scope, args || [])
		}
	}
}
	());
Ext.apply(Function.prototype, {
	createSequence : function (fcn, scope) {
		var method = this;
		return typeof fcn != "function" ? this : function () {
			var retval = method.apply(this || window, arguments);
			fcn.apply(scope || this || window, arguments);
			return retval
		}
	}
});
Ext.applyIf(String, {
	escape : function (string) {
		return string.replace(/('|\\)/g, "\\$1")
	},
	leftPad : function (val, size, ch) {
		var result = String(val);
		if (!ch)
			ch = " ";
		for (; result.length < size; )
			result = ch + result;
		return result
	}
});
String.prototype.toggle = function (value, other) {
	return this == value ? other : value
};
String.prototype.trim = function () {
	var re = /^\s+|\s+$/g;
	return function () {
		return this.replace(re, "")
	}
}
();
Date.prototype.getElapsed = function (date) {
	return Math.abs((date || new Date).getTime() - this.getTime())
};
Ext.applyIf(Number.prototype, {
	constrain : function (min, max) {
		return Math.min(Math.max(this, min), max)
	}
});
Ext.lib.Dom.getRegion = function (el) {
	return Ext.lib.Region.getRegion(el)
};
Ext.lib.Region = function (t, r, b, l) {
	var me = this;
	me.top = t;
	me[1] = t;
	me.right = r;
	me.bottom = b;
	me.left = l;
	me[0] = l
};
Ext.lib.Region.prototype = {
	contains : function (region) {
		var me = this;
		return region.left >= me.left && region.right <= me.right && region.top >= me.top && region.bottom <= me.bottom
	},
	getArea : function () {
		var me = this;
		return (me.bottom - me.top) * (me.right - me.left)
	},
	intersect : function (region) {
		var me = this;
		var t = Math.max(me.top, region.top);
		var r = Math.min(me.right, region.right);
		var b = Math.min(me.bottom, region.bottom);
		var l = Math.max(me.left, region.left);
		if (b >= t && r >= l)
			return new Ext.lib.Region(t, r, b, l)
	},
	union : function (region) {
		var me =
			this;
		var t = Math.min(me.top, region.top);
		var r = Math.max(me.right, region.right);
		var b = Math.max(me.bottom, region.bottom);
		var l = Math.min(me.left, region.left);
		return new Ext.lib.Region(t, r, b, l)
	},
	constrainTo : function (r) {
		var me = this;
		me.top = me.top.constrain(r.top, r.bottom);
		me.bottom = me.bottom.constrain(r.top, r.bottom);
		me.left = me.left.constrain(r.left, r.right);
		me.right = me.right.constrain(r.left, r.right);
		return me
	},
	adjust : function (t, l, b, r) {
		var me = this;
		me.top += t;
		me.left += l;
		me.right += r;
		me.bottom += b;
		return me
	}
};
Ext.lib.Region.getRegion = function (el) {
	var p = Ext.lib.Dom.getXY(el);
	var t = p[1];
	var r = p[0] + el.offsetWidth;
	var b = p[1] + el.offsetHeight;
	var l = p[0];
	return new Ext.lib.Region(t, r, b, l)
};
Ext.lib.Point = function (x, y) {
	if (Ext.isArray(x)) {
		y = x[1];
		x = x[0]
	}
	var me = this;
	me.x = me.right = me.left = me[0] = x;
	me.y = me.top = me.bottom = me[1] = y
};
Ext.lib.Point.prototype = new Ext.lib.Region;
Ext.apply(Ext.DomHelper, function () {
	function doInsert(el, o, returnElement, pos, sibling, append) {
		el = Ext.getDom(el);
		var newNode;
		if (pub.useDom) {
			newNode = createDom(o, null);
			if (append)
				el.appendChild(newNode);
			else (sibling == "firstChild" ? el : el.parentNode).insertBefore(newNode, el[sibling] || el)
		} else
			newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
		return returnElement ? Ext.get(newNode, true) : newNode
	}
	function createDom(o, parentNode) {
		var el;
		var doc = document;
		var useSet;
		var attr;
		var val;
		var cn;
		if (Ext.isArray(o)) {
			el =
				doc.createDocumentFragment();
			var i = 0;
			for (var l = o.length; i < l; i++)
				createDom(o[i], el)
		} else if (typeof o == "string")
			el = doc.createTextNode(o);
		else {
			el = doc.createElement(o.tag || "div");
			useSet = !!el.setAttribute;
			for (attr in o)
				if (!confRe.test(attr)) {
					val = o[attr];
					if (attr == "cls")
						el.className = val;
					else if (useSet)
						el.setAttribute(attr, val);
					else
						el[attr] = val
				}
			Ext.DomHelper.applyStyles(el, o.style);
			if (cn = o.children || o.cn)
				createDom(cn, el);
			else if (o.html)
				el.innerHTML = o.html
		}
		if (parentNode)
			parentNode.appendChild(el);
		return el
	}
	var pub;
	var afterbegin = "afterbegin";
	var afterend = "afterend";
	var beforebegin = "beforebegin";
	var beforeend = "beforeend";
	var confRe = /tag|children|cn|html$/i;
	pub = {
		createTemplate : function (o) {
			var html = Ext.DomHelper.createHtml(o);
			return new Ext.Template(html)
		},
		useDom : false,
		insertBefore : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, beforebegin)
		},
		insertAfter : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, afterend, "nextSibling")
		},
		insertFirst : function (el, o, returnElement) {
			return doInsert(el,
				o, returnElement, afterbegin, "firstChild")
		},
		append : function (el, o, returnElement) {
			return doInsert(el, o, returnElement, beforeend, "", true)
		},
		createDom : createDom
	};
	return pub
}
	());
Ext.apply(Ext.Template.prototype, {
	disableFormats : false,
	re : /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
	argsRe : /^\s*['"](.*)["']\s*$/,
	compileARe : /\\/g,
	compileBRe : /(\r\n|\n)/g,
	compileCRe : /'/g,
	applyTemplate : function (values) {
		function fn(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 = me.argsRe;
						args = args.split(",");
						var i = 0;
						for (var 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] : ""
		}
		var me = this;
		var useF = me.disableFormats !== true;
		var fm = Ext.util.Format;
		var tpl = me;
		if (me.compiled)
			return me.compiled(values);
		return me.html.replace(me.re, fn)
	},
	compile : function () {
		function fn(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 +
					"'] \x3d\x3d undefined ? '' : "
			}
			return "'" + sep + format + "values['" + name + "']" + args + ")" + sep + "'"
		}
		var me = this;
		var fm = Ext.util.Format;
		var useF = me.disableFormats !== true;
		var sep = Ext.isGecko ? "+" : ",";
		var body;
		if (Ext.isGecko)
			body = "this.compiled \x3d function(values){ return '" + me.html.replace(me.compileARe, "\\\\").replace(me.compileBRe, "\\n").replace(me.compileCRe, "\\'").replace(me.re, fn) + "';};";
		else {
			body = ["this.compiled \x3d function(values){ return ['"];
			body.push(me.html.replace(me.compileARe, "\\\\").replace(me.compileBRe,
					"\\n").replace(me.compileCRe, "\\'").replace(me.re, fn));
			body.push("'].join('');};");
			body = body.join("")
		}
		eval(body);
		return me
	},
	call : function (fnName, value, allValues) {
		return this[fnName](value, allValues)
	}
});
Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
Ext.util.Functions = {
	createInterceptor : function (origFn, newFn, scope) {
		var method = origFn;
		if (!Ext.isFunction(newFn))
			return origFn;
		else
			return function () {
				var me = this;
				var args = arguments;
				newFn.target = me;
				newFn.method = origFn;
				return newFn.apply(scope || me || window, args) !== false ? origFn.apply(me || window, args) : null
			}
	},
	createDelegate : function (fn, obj, args, appendArgs) {
		if (!Ext.isFunction(fn))
			return fn;
		return function () {
			var callArgs = args || arguments;
			if (appendArgs === true) {
				callArgs = Array.prototype.slice.call(arguments, 0);
				callArgs = callArgs.concat(args)
			} else if (Ext.isNumber(appendArgs)) {
				callArgs = Array.prototype.slice.call(arguments, 0);
				var applyArgs = [appendArgs, 0].concat(args);
				Array.prototype.splice.apply(callArgs, applyArgs)
			}
			return fn.apply(obj || window, callArgs)
		}
	},
	defer : function (fn, millis, obj, args, appendArgs) {
		fn = Ext.util.Functions.createDelegate(fn, obj, args, appendArgs);
		if (millis > 0)
			return setTimeout(fn, millis);
		fn();
		return 0
	},
	createSequence : function (origFn, newFn, scope) {
		if (!Ext.isFunction(newFn))
			return origFn;
		else
			return function () {
				var retval =
					origFn.apply(this || window, arguments);
				newFn.apply(scope || this || window, arguments);
				return retval
			}
	}
};
Ext.defer = Ext.util.Functions.defer;
Ext.createInterceptor = Ext.util.Functions.createInterceptor;
Ext.createSequence = Ext.util.Functions.createSequence;
Ext.createDelegate = Ext.util.Functions.createDelegate;
Ext.apply(Ext.util.Observable.prototype, function () {
	function getMethodEvent(method) {
		var e = (this.methodEvents = this.methodEvents || {})[method];
		var returnValue;
		var v;
		var cancel;
		var obj = this;
		if (!e) {
			this.methodEvents[method] = e = {};
			e.originalFn = this[method];
			e.methodName = method;
			e.before = [];
			e.after = [];
			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;
						cancel = !!v.cancel
					} else if (v ===
						false)
						cancel = true;
					else
						returnValue = v
			};
			this[method] = function () {
				var args = Array.prototype.slice.call(arguments, 0);
				var b;
				returnValue = v = undefined;
				cancel = false;
				var i = 0;
				for (var len = e.before.length; i < len; i++) {
					b = e.before[i];
					makeCall(b.fn, b.scope, args);
					if (cancel)
						return returnValue
				}
				if ((v = e.originalFn.apply(obj, args)) !== undefined)
					returnValue = v;
				i = 0;
				for (len = e.after.length; i < len; i++) {
					b = e.after[i];
					makeCall(b.fn, b.scope, args);
					if (cancel)
						return returnValue
				}
				return returnValue
			}
		}
		return e
	}
	return {
		beforeMethod : function (method,
			fn, scope) {
			getMethodEvent.call(this, method).before.push({
				fn : fn,
				scope : scope
			})
		},
		afterMethod : function (method, fn, scope) {
			getMethodEvent.call(this, method).after.push({
				fn : fn,
				scope : scope
			})
		},
		removeMethodListener : function (method, fn, scope) {
			var e = this.getMethodEvent(method);
			var i = 0;
			for (var len = e.before.length; i < len; i++)
				if (e.before[i].fn == fn && e.before[i].scope == scope) {
					e.before.splice(i, 1);
					return
				}
			i = 0;
			for (len = e.after.length; i < len; i++)
				if (e.after[i].fn == fn && e.after[i].scope == scope) {
					e.after.splice(i, 1);
					return
				}
		},
		relayEvents : function (o,
			events) {
			function createHandler(ename) {
				return function () {
					return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)))
				}
			}
			var me = this;
			var i = 0;
			for (var len = events.length; i < len; i++) {
				var ename$$0 = events[i];
				me.events[ename$$0] = me.events[ename$$0] || true;
				o.on(ename$$0, createHandler(ename$$0), me)
			}
		},
		enableBubble : function (events) {
			var me = this;
			if (!Ext.isEmpty(events)) {
				events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
				var i = 0;
				for (var len = events.length; i < len; i++) {
					var ename =
						events[i];
					ename = ename.toLowerCase();
					var ce = me.events[ename] || true;
					if (typeof ce == "boolean") {
						ce = new Ext.util.Event(me, ename);
						me.events[ename] = ce
					}
					ce.bubble = true
				}
			}
		}
	}
}
	());
Ext.util.Observable.capture = function (o, fn, scope) {
	o.fireEvent = o.fireEvent.createInterceptor(fn, scope)
};
Ext.util.Observable.observeClass = function (c, listeners) {
	if (c) {
		if (!c.fireEvent) {
			Ext.apply(c, new Ext.util.Observable);
			Ext.util.Observable.capture(c.prototype, c.fireEvent, c)
		}
		if (typeof listeners == "object")
			c.on(listeners);
		return c
	}
};
Ext.apply(Ext.EventManager, function () {
	var resizeEvent;
	var resizeTask;
	var textEvent;
	var textSize;
	var D = Ext.lib.Dom;
	var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
	var unload = Ext.EventManager._unload;
	var curWidth = 0;
	var curHeight = 0;
	var useKeydown = Ext.isWebKit ? Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 : !(Ext.isGecko && !Ext.isWindows || Ext.isOpera);
	return {
		_unload : function () {
			Ext.EventManager.un(window, "resize", this.fireWindowResize,
				this);
			unload.call(Ext.EventManager)
		},
		doResizeEvent : function () {
			var h = D.getViewHeight();
			var w = D.getViewWidth();
			if (curHeight != h || curWidth != w)
				resizeEvent.fire(curWidth = w, curHeight = h)
		},
		onWindowResize : function (fn, scope, options) {
			if (!resizeEvent) {
				resizeEvent = new Ext.util.Event;
				resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
				Ext.EventManager.on(window, "resize", this.fireWindowResize, this)
			}
			resizeEvent.addListener(fn, scope, options)
		},
		fireWindowResize : function () {
			if (resizeEvent)
				resizeTask.delay(100)
		},
		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())
		},
		textResizeInterval : 50,
		ieDeferSrc : false,
		getKeyEvent : function () {
			return useKeydown ? "keydown" : "keypress"
		},
		useKeydown : useKeydown
	}
}
	());
Ext.EventManager.on = Ext.EventManager.addListener;
Ext.apply(Ext.EventObjectImpl.prototype, {
	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,
	isNavKeyPress : function () {
		var me = this;
		var k = this.normalizeKey(me.keyCode);
		return k >= 33 && k <= 40 || k == me.RETURN || k == me.TAB || k == me.ESC
	},
	isSpecialKey : function () {
		var k = this.normalizeKey(this.keyCode);
		return this.type ==
		"keypress" && this.ctrlKey || this.isNavKeyPress() || k == this.BACKSPACE || k >= 16 && k <= 20 || k >= 44 && k <= 46
	},
	getPoint : function () {
		return new Ext.lib.Point(this.xy[0], this.xy[1])
	},
	hasModifier : function () {
		return this.ctrlKey || this.altKey || this.shiftKey
	}
});
Ext.Element.addMethods({
	swallowEvent : function (eventName, preventDefault) {
		function fn(e) {
			e.stopPropagation();
			if (preventDefault)
				e.preventDefault()
		}
		var me = this;
		if (Ext.isArray(eventName)) {
			Ext.each(eventName, function (e) {
				me.on(e, fn)
			});
			return me
		}
		me.on(eventName, fn);
		return me
	},
	relayEvent : function (eventName, observable) {
		this.on(eventName, function (e) {
			observable.fireEvent(eventName, e)
		})
	},
	clean : function (forceReclean) {
		var me = this;
		var dom = me.dom;
		var n = dom.firstChild;
		var ni = -1;
		if (Ext.Element.data(dom, "isCleaned") &&
			forceReclean !== true)
			return me;
		for (; n; ) {
			var nx = n.nextSibling;
			if (n.nodeType == 3 && !/\S/.test(n.nodeValue))
				dom.removeChild(n);
			else
				n.nodeIndex = ++ni;
			n = nx
		}
		Ext.Element.data(dom, "isCleaned", true);
		return me
	},
	load : function () {
		var updateManager = this.getUpdater();
		updateManager.update.apply(updateManager, arguments);
		return this
	},
	getUpdater : function () {
		return this.updateManager || (this.updateManager = new Ext.Updater(this))
	},
	update : function (html, loadScripts, callback) {
		if (!this.dom)
			return this;
		html = html || "";
		if (loadScripts !==
			true) {
			this.dom.innerHTML = html;
			if (typeof callback == "function")
				callback();
			return this
		}
		var id = Ext.id();
		var dom = this.dom;
		html += '\x3cspan id\x3d"' + id + '"\x3e\x3c/span\x3e';
		Ext.lib.Event.onAvailable(id, function () {
			var DOC = document;
			var hd = DOC.getElementsByTagName("head")[0];
			var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
			var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
			var typeRe = /\stype=([\'\"])(.*?)\1/i;
			var match;
			var attrs;
			var srcMatch;
			var typeMatch;
			var el;
			for (var s; match = re.exec(html); ) {
				attrs = match[1];
				srcMatch =
					attrs ? attrs.match(srcRe) : false;
				if (srcMatch && srcMatch[2]) {
					s = DOC.createElement("script");
					s.src = srcMatch[2];
					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])
			}
			el = DOC.getElementById(id);
			if (el)
				Ext.removeNode(el);
			if (typeof callback == "function")
				callback()
		});
		dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
		return this
	},
	removeAllListeners : function () {
		this.removeAnchor();
		Ext.EventManager.removeAll(this.dom);
		return this
	},
	createProxy : function (config, renderTo, matchBox) {
		config = typeof config == "object" ? config : {
			tag : "div",
			cls : config
		};
		var me = this;
		var proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) : Ext.DomHelper.insertBefore(me.dom, config, true);
		if (matchBox && me.setBox && me.getBox)
			proxy.setBox(me.getBox());
		return proxy
	}
});
Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
Ext.Element.addMethods({
	getAnchorXY : function (anchor, local, s) {
		anchor = (anchor || "tl").toLowerCase();
		s = s || {};
		var me = this;
		var vp = me.dom == document.body || me.dom == document;
		var w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth();
		var h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight();
		var xy;
		var r = Math.round;
		var o = me.getXY();
		var scroll = me.getScroll();
		var extraX = vp ? scroll.left : !local ? o[0] : 0;
		var extraY = vp ? scroll.top : !local ? o[1] : 0;
		var hash = {
			c : [r(w * 0.5), r(h * 0.5)],
			t : [r(w * 0.5), 0],
			l : [0, r(h * 0.5)],
			r : [w, r(h *
					0.5)],
			b : [r(w * 0.5), h],
			tl : [0, 0],
			bl : [0, h],
			br : [w, h],
			tr : [w, 0]
		};
		xy = hash[anchor];
		return [xy[0] + extraX, xy[1] + extraY]
	},
	anchorTo : function (el, alignment, offsets, animate, monitorScroll, callback) {
		var me = this;
		var dom = me.dom;
		var scroll = !Ext.isEmpty(monitorScroll);
		var action = function () {
			Ext.fly(dom).alignTo(el, alignment, offsets, animate);
			Ext.callback(callback, Ext.fly(dom))
		};
		var anchor = this.getAnchor();
		this.removeAnchor();
		Ext.apply(anchor, {
			fn : action,
			scroll : scroll
		});
		Ext.EventManager.onWindowResize(action, null);
		if (scroll)
			Ext.EventManager.on(window,
				"scroll", action, null, {
				buffer : !isNaN(monitorScroll) ? monitorScroll : 50
			});
		action.call(me);
		return me
	},
	removeAnchor : function () {
		var me = this;
		var anchor = this.getAnchor();
		if (anchor && anchor.fn) {
			Ext.EventManager.removeResizeListener(anchor.fn);
			if (anchor.scroll)
				Ext.EventManager.un(window, "scroll", anchor.fn);
			delete anchor.fn
		}
		return me
	},
	getAnchor : function () {
		var data = Ext.Element.data;
		var dom = this.dom;
		if (!dom)
			return;
		var anchor = data(dom, "_anchor");
		if (!anchor)
			anchor = data(dom, "_anchor", {});
		return anchor
	},
	getAlignToXY : function (el,
		p, o) {
		el = Ext.get(el);
		if (!el || !el.dom)
			throw "Element.alignToXY with an element that doesn't exist";
		o = o || [0, 0];
		p = (!p || p == "?" ? "tl-bl?" : !/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl").toLowerCase();
		var me = this;
		var d = me.dom;
		var a1;
		var a2;
		var x;
		var y;
		var w;
		var h;
		var r;
		var dw = Ext.lib.Dom.getViewWidth() - 10;
		var dh = Ext.lib.Dom.getViewHeight() - 10;
		var p1y;
		var p1x;
		var p2y;
		var p2x;
		var swapY;
		var swapX;
		var doc = document;
		var docElement = doc.documentElement;
		var docBody = doc.body;
		var scrollX = (docElement.scrollLeft || docBody.scrollLeft ||
			0) + 5;
		var scrollY = (docElement.scrollTop || docBody.scrollTop || 0) + 5;
		var c = false;
		var p1 = "";
		var p2 = "";
		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];
		a1 = me.getAnchorXY(p1, true);
		a2 = el.getAnchorXY(p2, false);
		x = a2[0] - a1[0] + o[0];
		y = a2[1] - a1[1] + o[1];
		if (c) {
			w = me.getWidth();
			h = me.getHeight();
			r = el.getRegion();
			p1y = p1.charAt(0);
			p1x = p1.charAt(p1.length - 1);
			p2y = p2.charAt(0);
			p2x = p2.charAt(p2.length - 1);
			swapY = p1y == "t" && p2y == "b" || p1y == "b" && p2y == "t";
			swapX = p1x == "r" && p2x == "l" || p1x == "l" && p2x == "r";
			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]
	},
	alignTo : function (element, position, offsets, animate) {
		var me = this;
		return me.setXY(me.getAlignToXY(element, position, offsets), me.preanim && !!animate ? me.preanim(arguments, 3) : false)
	},
	adjustForConstraints : function (xy, parent, offsets) {
		return this.getConstrainToXY(parent || document, false,
			offsets, xy) || xy
	},
	getConstrainToXY : function (el$$0, local$$0, offsets$$0, proposedXY) {
		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;
			var vh;
			var vx = 0;
			var 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];
			var y = xy[1];
			var offset = this.getConstrainOffset();
			var w = this.dom.offsetWidth + offset;
			var h = this.dom.offsetHeight + offset;
			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
		}
	}
	(),
	getConstrainOffset : function () {
		return 0
	},
	getCenterXY : function () {
		return this.getAlignToXY(document,
			"c-c")
	},
	center : function (centerIn) {
		return this.alignTo(centerIn || document, "c-c")
	}
});
Ext.Element.addMethods({
	select : function (selector, unique) {
		return Ext.Element.select(selector, unique, this.dom)
	}
});
Ext.apply(Ext.Element.prototype, function () {
	var GETDOM = Ext.getDom;
	var GET = Ext.get;
	var DH = Ext.DomHelper;
	return {
		insertSibling : function (el, where, returnDom) {
			var me = this;
			var rt;
			var isAfter = (where || "before").toLowerCase() == "after";
			var insertEl;
			if (Ext.isArray(el)) {
				insertEl = me;
				Ext.each(el, function (e) {
					rt = Ext.fly(insertEl, "_internal").insertSibling(e, where, returnDom);
					if (isAfter)
						insertEl = rt
				});
				return rt
			}
			el = el || {};
			if (el.nodeType || el.dom) {
				rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
				if (!returnDom)
					rt = GET(rt)
			} else if (isAfter && !me.dom.nextSibling)
				rt = DH.append(me.dom.parentNode, el, !returnDom);
			else
				rt = DH[isAfter ? "insertAfter" : "insertBefore"](me.dom, el, !returnDom);
			return rt
		}
	}
}
	());
Ext.Element.boxMarkup = '\x3cdiv class\x3d"{0}-tl"\x3e\x3cdiv class\x3d"{0}-tr"\x3e\x3cdiv class\x3d"{0}-tc"\x3e\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e\x3cdiv class\x3d"{0}-ml"\x3e\x3cdiv class\x3d"{0}-mr"\x3e\x3cdiv class\x3d"{0}-mc"\x3e\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e\x3cdiv class\x3d"{0}-bl"\x3e\x3cdiv class\x3d"{0}-br"\x3e\x3cdiv class\x3d"{0}-bc"\x3e\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e';
Ext.Element.addMethods(function () {
	var INTERNAL = "_internal";
	var pxMatch = /(\d+\.?\d+)px/;
	return {
		applyStyles : function (style) {
			Ext.DomHelper.applyStyles(this.dom, style);
			return this
		},
		getStyles : function () {
			var ret = {};
			Ext.each(arguments, function (v) {
				ret[v] = this.getStyle(v)
			}, this);
			return ret
		},
		setOverflow : function (v) {
			var dom = this.dom;
			if (v == "auto" && Ext.isMac && Ext.isGecko2) {
				dom.style.overflow = "hidden";
				(function () {
					dom.style.overflow = "auto"
				}).defer(1)
			} else
				dom.style.overflow = v
		},
		boxWrap : function (cls) {
			cls = cls || "x-box";
			var el = Ext.get(this.insertHtml("beforeBegin", "\x3cdiv class\x3d'" + cls + "'\x3e" + String.format(Ext.Element.boxMarkup, cls) + "\x3c/div\x3e"));
			Ext.DomQuery.selectNode("." + cls + "-mc", el.dom).appendChild(this.dom);
			return el
		},
		setSize : function (width, height, animate) {
			var me = this;
			if (typeof width == "object") {
				height = width.height;
				width = width.width
			}
			width = me.adjustWidth(width);
			height = me.adjustHeight(height);
			if (!animate || !me.anim) {
				me.dom.style.width = me.addUnits(width);
				me.dom.style.height = me.addUnits(height)
			} else
				me.anim({
					width : {
						to : width
					},
					height : {
						to : height
					}
				}, me.preanim(arguments, 2));
			return me
		},
		getComputedHeight : function () {
			var me = this;
			var h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
			if (!h) {
				h = parseFloat(me.getStyle("height")) || 0;
				if (!me.isBorderBox())
					h += me.getFrameWidth("tb")
			}
			return h
		},
		getComputedWidth : function () {
			var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
			if (!w) {
				w = parseFloat(this.getStyle("width")) || 0;
				if (!this.isBorderBox())
					w += this.getFrameWidth("lr")
			}
			return w
		},
		getFrameWidth : function (sides, onlyContentBox) {
			return onlyContentBox &&
			this.isBorderBox() ? 0 : this.getPadding(sides) + this.getBorderWidth(sides)
		},
		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
		},
		getViewSize : function () {
			var doc = document;
			var d = this.dom;
			var isDoc = d == doc || d == doc.body;
			if (isDoc) {
				var extdom = Ext.lib.Dom;
				return {
					width : extdom.getViewWidth(),
					height : extdom.getViewHeight()
				}
			} else
				return {
					width : d.clientWidth,
					height : d.clientHeight
				}
		},
		getStyleSize : function () {
			var me =
				this;
			var w;
			var h;
			var doc = document;
			var d = this.dom;
			var isDoc = d == doc || d == doc.body;
			var s = d.style;
			if (isDoc) {
				var extdom = Ext.lib.Dom;
				return {
					width : extdom.getViewWidth(),
					height : extdom.getViewHeight()
				}
			}
			if (s.width && s.width != "auto") {
				w = parseFloat(s.width);
				if (me.isBorderBox())
					w -= me.getFrameWidth("lr")
			}
			if (s.height && s.height != "auto") {
				h = parseFloat(s.height);
				if (me.isBorderBox())
					h -= me.getFrameWidth("tb")
			}
			return {
				width : w || me.getWidth(true),
				height : h || me.getHeight(true)
			}
		},
		getSize : function (contentSize) {
			return {
				width : this.getWidth(contentSize),
				height : this.getHeight(contentSize)
			}
		},
		repaint : function () {
			var dom = this.dom;
			this.addClass("x-repaint");
			setTimeout(function () {
				Ext.fly(dom).removeClass("x-repaint")
			}, 1);
			return this
		},
		unselectable : function () {
			this.dom.unselectable = "on";
			return this.swallowEvent("selectstart", true).applyStyles("-moz-user-select:none;-khtml-user-select:none;").addClass("x-unselectable")
		},
		getMargins : function (side) {
			var me = this;
			var key;
			var hash = {
				t : "top",
				l : "left",
				r : "right",
				b : "bottom"
			};
			var o = {};
			if (!side) {
				for (key in me.margins)
					o[hash[key]] =
						parseFloat(me.getStyle(me.margins[key])) || 0;
				return o
			} else
				return me.addStyles.call(me, side, me.margins)
		}
	}
}
	());
Ext.Element.addMethods({
	setBox : function (box, adjust, animate) {
		var me = this;
		var w = box.width;
		var h = box.height;
		if (adjust && !me.autoBoxAdjust && !me.isBorderBox()) {
			w -= me.getBorderWidth("lr") + me.getPadding("lr");
			h -= me.getBorderWidth("tb") + me.getPadding("tb")
		}
		me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
		return me
	},
	getBox : function (contentBox, local) {
		var me = this;
		var xy;
		var left;
		var top;
		var getBorderWidth = me.getBorderWidth;
		var getPadding = me.getPadding;
		var l;
		var r;
		var t;
		var b;
		if (!local)
			xy =
				me.getXY();
		else {
			left = parseInt(me.getStyle("left"), 10) || 0;
			top = parseInt(me.getStyle("top"), 10) || 0;
			xy = [left, top]
		}
		var el = me.dom;
		var w = el.offsetWidth;
		var h = el.offsetHeight;
		var bx;
		if (!contentBox)
			bx = {
				x : xy[0],
				y : xy[1],
				0 : xy[0],
				1 : xy[1],
				width : w,
				height : h
			};
		else {
			l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
			r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
			t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
			b = getBorderWidth.call(me, "b") + getPadding.call(me, "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
	},
	move : function (direction, distance, animate) {
		var me = this;
		var xy = me.getXY();
		var x = xy[0];
		var y = xy[1];
		var left = [x - distance, y];
		var right = [x + distance, y];
		var top = [x, y - distance];
		var bottom = [x, y + distance];
		var hash = {
			l : left,
			left : left,
			r : right,
			right : right,
			t : top,
			top : top,
			up : top,
			b : bottom,
			bottom : bottom,
			down : bottom
		};
		direction = direction.toLowerCase();
		me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments,
				animate, 2))
	},
	setLeftTop : function (left, top) {
		var me = this;
		var style = me.dom.style;
		style.left = me.addUnits(left);
		style.top = me.addUnits(top);
		return me
	},
	getRegion : function () {
		return Ext.lib.Dom.getRegion(this.dom)
	},
	setBounds : function (x, y, width, height, animate) {
		var me = this;
		if (!animate || !me.anim) {
			me.setSize(width, height);
			me.setLocation(x, y)
		} else
			me.anim({
				points : {
					to : [x, y]
				},
				width : {
					to : me.adjustWidth(width)
				},
				height : {
					to : me.adjustHeight(height)
				}
			}, me.preanim(arguments, 4), "motion");
		return me
	},
	setRegion : function (region,
		animate) {
		return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, this.animTest.call(this, arguments, animate, 1))
	}
});
Ext.Element.addMethods({
	scrollTo : function (side, value, animate) {
		var top = /top/i.test(side);
		var me = this;
		var dom = me.dom;
		var prop;
		if (!animate || !me.anim) {
			prop = "scroll" + (top ? "Top" : "Left");
			dom[prop] = value
		} else {
			prop = "scroll" + (top ? "Left" : "Top");
			me.anim({
				scroll : {
					to : top ? [dom[prop], value] : [value, dom[prop]]
				}
			}, me.preanim(arguments, 2), "scroll")
		}
		return me
	},
	scrollIntoView : function (container, hscroll) {
		var c = Ext.getDom(container) || Ext.getBody().dom;
		var el = this.dom;
		var o = this.getOffsetsTo(c);
		var l = o[0] + c.scrollLeft;
		var t =
			o[1] + c.scrollTop;
		var b = t + el.offsetHeight;
		var 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)
	},
	scroll : function (direction, distance, animate) {
		if (!this.isScrollable())
			return false;
		var el = this.dom;
		var l = el.scrollLeft;
		var t = el.scrollTop;
		var w = el.scrollWidth;
		var h = el.scrollHeight;
		var cw = el.clientWidth;
		var ch = el.clientHeight;
		var scrolled = false;
		var v;
		var hash = {
			l : Math.min(l + distance, w - cw),
			r : v = Math.max(l - distance, 0),
			t : Math.max(t - distance, 0),
			b : Math.min(t + distance, h - ch)
		};
		hash.d = hash.b;
		hash.u = hash.t;
		direction = direction.substr(0, 1);
		if ((v = hash[direction]) > -1) {
			scrolled = true;
			this.scrollTo(direction ==
				"l" || direction == "r" ? "left" : "top", v, this.preanim(arguments, 2))
		}
		return scrolled
	}
});
Ext.Element.addMethods(function () {
	var VISIBILITY = "visibility";
	var DISPLAY = "display";
	var HIDDEN = "hidden";
	var NONE = "none";
	var XMASKED = "x-masked";
	var XMASKEDRELATIVE = "x-masked-relative";
	var data = Ext.Element.data;
	return {
		isVisible : function (deep) {
			var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE);
			var p = this.dom.parentNode;
			if (deep !== true || !vis)
				return vis;
			for (; p && !/^body/i.test(p.tagName); ) {
				if (!Ext.fly(p, "_isVisible").isVisible())
					return false;
				p = p.parentNode
			}
			return true
		},
		isDisplayed : function () {
			return !this.isStyle(DISPLAY,
				NONE)
		},
		enableDisplayMode : function (display) {
			this.setVisibilityMode(Ext.Element.DISPLAY);
			if (!Ext.isEmpty(display))
				data(this.dom, "originalDisplay", display);
			return this
		},
		mask : function (msg, msgCls) {
			var me = this;
			var dom = me.dom;
			var dh = Ext.DomHelper;
			var EXTELMASKMSG = "ext-el-mask-msg";
			var el;
			var mask;
			if (!/^body/i.test(dom.tagName) && me.getStyle("position") == "static")
				me.addClass(XMASKEDRELATIVE);
			if (el = data(dom, "maskMsg"))
				el.remove();
			if (el = data(dom, "mask"))
				el.remove();
			mask = dh.append(dom, {
					cls : "ext-el-mask"
				}, true);
			data(dom, "mask", mask);
			me.addClass(XMASKED);
			mask.setDisplayed(true);
			if (typeof msg == "string") {
				var mm = dh.append(dom, {
						cls : EXTELMASKMSG,
						cn : {
							tag : "div"
						}
					}, true);
				data(dom, "maskMsg", mm);
				mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
				mm.dom.firstChild.innerHTML = msg;
				mm.setDisplayed(true);
				mm.center(me)
			}
			if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle("height") == "auto")
				mask.setSize(undefined, me.getHeight());
			return mask
		},
		unmask : function () {
			var me = this;
			var dom = me.dom;
			var mask = data(dom, "mask");
			var maskMsg =
				data(dom, "maskMsg");
			if (mask) {
				if (maskMsg) {
					maskMsg.remove();
					data(dom, "maskMsg", undefined)
				}
				mask.remove();
				data(dom, "mask", undefined);
				me.removeClass([XMASKED, XMASKEDRELATIVE])
			}
		},
		isMasked : function () {
			var m = data(this.dom, "mask");
			return m && m.isVisible()
		},
		createShim : function () {
			var el = document.createElement("iframe");
			var shim;
			el.frameBorder = "0";
			el.className = "ext-shim";
			el.src = Ext.SSL_SECURE_URL;
			shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
			shim.autoBoxAdjust = false;
			return shim
		}
	}
}
	());
Ext.Element.addMethods({
	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)
	}
});
Ext.CompositeElementLite.importElementMethods();
Ext.apply(Ext.CompositeElementLite.prototype, {
	addElements : function (els, root) {
		if (!els)
			return this;
		if (typeof els == "string")
			els = Ext.Element.selectorFunction(els, root);
		var yels = this.elements;
		Ext.each(els, function (e) {
			yels.push(Ext.get(e))
		});
		return this
	},
	first : function () {
		return this.item(0)
	},
	last : function () {
		return this.item(this.getCount() - 1)
	},
	contains : function (el) {
		return this.indexOf(el) != -1
	},
	removeElement : function (keys, removeDom) {
		var me = this;
		var els = this.elements;
		var el;
		Ext.each(keys, function (val) {
			if (el =
					els[val] || els[val = me.indexOf(val)]) {
				if (removeDom)
					if (el.dom)
						el.remove();
					else
						Ext.removeNode(el);
				els.splice(val, 1)
			}
		});
		return this
	}
});
Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
		constructor : function (els, root) {
			this.elements = [];
			this.add(els, root)
		},
		getElement : function (el) {
			return el
		},
		transformElement : function (el) {
			return Ext.get(el)
		}
	});
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";
	return unique === true ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els)
};
Ext.select = Ext.Element.select;
Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable, function () {
		function processSuccess(response) {
			var me = this;
			me.transaction = null;
			if (response.argument.form && response.argument.reset)
				try {
					response.argument.form.reset()
				} catch (e) {}

			if (me.loadScripts)
				me.renderer.render(me.el, response, me, updateComplete.createDelegate(me, [response]));
			else {
				me.renderer.render(me.el, response, me);
				updateComplete.call(me, response)
			}
		}
		function updateComplete(response, type, success) {
			this.fireEvent(type || UPDATE, this.el, response);
			if (Ext.isFunction(response.argument.callback))
				response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options)
		}
		function processFailure(response) {
			updateComplete.call(this, response, FAILURE, !!(this.transaction = null))
		}
		var BEFOREUPDATE = "beforeupdate";
		var UPDATE = "update";
		var FAILURE = "failure";
		return {
			constructor : function (el, forceNew) {
				var me = this;
				el = Ext.get(el);
				if (!forceNew && el.updateManager)
					return el.updateManager;
				me.el = el;
				me.defaultUrl =
					null;
				me.addEvents(BEFOREUPDATE, UPDATE, FAILURE);
				Ext.apply(me, Ext.Updater.defaults);
				me.transaction = null;
				me.refreshDelegate = me.refresh.createDelegate(me);
				me.updateDelegate = me.update.createDelegate(me);
				me.formUpdateDelegate = (me.formUpdate || function () {}).createDelegate(me);
				me.renderer = me.renderer || me.getDefaultRenderer();
				Ext.Updater.superclass.constructor.call(me)
			},
			setRenderer : function (renderer) {
				this.renderer = renderer
			},
			getRenderer : function () {
				return this.renderer
			},
			getDefaultRenderer : function () {
				return new Ext.Updater.BasicRenderer
			},
			setDefaultUrl : function (defaultUrl) {
				this.defaultUrl = defaultUrl
			},
			getEl : function () {
				return this.el
			},
			update : function (url, params, callback, discardUrl) {
				var me = this;
				var cfg;
				var callerScope;
				if (me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false) {
					if (Ext.isObject(url)) {
						cfg = url;
						url = cfg.url;
						params = params || cfg.params;
						callback = callback || cfg.callback;
						discardUrl = discardUrl || cfg.discardUrl;
						callerScope = cfg.scope;
						if (!Ext.isEmpty(cfg.nocache))
							me.disableCaching = cfg.nocache;
						if (!Ext.isEmpty(cfg.text))
							me.indicatorText = '\x3cdiv class\x3d"loading-indicator"\x3e' +
								cfg.text + "\x3c/div\x3e";
						if (!Ext.isEmpty(cfg.scripts))
							me.loadScripts = cfg.scripts;
						if (!Ext.isEmpty(cfg.timeout))
							me.timeout = cfg.timeout
					}
					me.showLoading();
					if (!discardUrl)
						me.defaultUrl = url;
					if (Ext.isFunction(url))
						url = url.call(me);
					var o = Ext.apply({}, {
							url : url,
							params : Ext.isFunction(params) && callerScope ? params.createDelegate(callerScope) : params,
							success : processSuccess,
							failure : processFailure,
							scope : me,
							callback : undefined,
							timeout : me.timeout * 1E3,
							disableCaching : me.disableCaching,
							argument : {
								"options" : cfg,
								"url" : url,
								"form" : null,
								"callback" : callback,
								"scope" : callerScope || window,
								"params" : params
							}
						}, cfg);
					me.transaction = Ext.Ajax.request(o)
				}
			},
			formUpdate : function (form, url, reset, callback) {
				var me = this;
				if (me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false) {
					if (Ext.isFunction(url))
						url = url.call(me);
					form = Ext.getDom(form);
					me.transaction = Ext.Ajax.request({
							form : form,
							url : url,
							success : processSuccess,
							failure : processFailure,
							scope : me,
							timeout : me.timeout * 1E3,
							argument : {
								"url" : url,
								"form" : form,
								"callback" : callback,
								"reset" : reset
							}
						});
					me.showLoading.defer(1,
						me)
				}
			},
			startAutoRefresh : function (interval, url, params, callback, refreshNow) {
				var me = this;
				if (refreshNow)
					me.update(url || me.defaultUrl, params, callback, true);
				if (me.autoRefreshProcId)
					clearInterval(me.autoRefreshProcId);
				me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1E3)
			},
			stopAutoRefresh : function () {
				if (this.autoRefreshProcId) {
					clearInterval(this.autoRefreshProcId);
					delete this.autoRefreshProcId
				}
			},
			isAutoRefreshing : function () {
				return !!this.autoRefreshProcId
			},
			showLoading : function () {
				if (this.showLoadIndicator)
					this.el.dom.innerHTML = this.indicatorText
			},
			abort : function () {
				if (this.transaction)
					Ext.Ajax.abort(this.transaction)
			},
			isUpdating : function () {
				return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false
			},
			refresh : function (callback) {
				if (this.defaultUrl)
					this.update(this.defaultUrl, null, callback, true)
			}
		}
	}
		());
Ext.Updater.defaults = {
	timeout : 30,
	disableCaching : false,
	showLoadIndicator : true,
	indicatorText : '\x3cdiv class\x3d"loading-indicator"\x3eLoading...\x3c/div\x3e',
	loadScripts : false,
	sslBlankUrl : Ext.SSL_SECURE_URL
};
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)
	}
};
(function () {
	function xf(format) {
		var args = Array.prototype.slice.call(arguments, 1);
		return format.replace(/\{(\d+)\}/g, function (m, i) {
			return args[i]
		})
	}
	Date.useStrict = false;
	Date.formatCodeToRegex = function (character, currentGroup) {
		var p = Date.parseCodes[character];
		if (p) {
			p = typeof p == "function" ? p() : p;
			Date.parseCodes[character] = p
		}
		return p ? Ext.applyIf({
			c : p.c ? xf(p.c, currentGroup || "{0}") : p.c
		}, p) : {
			g : 0,
			c : null,
			s : Ext.escapeRe(character)
		}
	};
	var $f = Date.formatCodeToRegex;
	Ext.apply(Date, {
		parseFunctions : {
			"M$" : function (input,
				strict) {
				var re = new RegExp("\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/");
				var r = (input || "").match(re);
				return r ? new Date(((r[1] || "") + r[2]) * 1) : null
			}
		},
		parseRegexes : [],
		formatFunctions : {
			"M$" : function () {
				return "\\/Date(" + this.getTime() + ")\\/"
			}
		},
		y2kYear : 50,
		MILLI : "ms",
		SECOND : "s",
		MINUTE : "mi",
		HOUR : "h",
		DAY : "d",
		MONTH : "mo",
		YEAR : "y",
		defaults : {},
		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()]
		},
		formatContainsHourInfo : function () {
			var stripEscapeRe = /(\\.)/g;
			var hourInfoRe = /([gGhHisucUOPZ]|M\$)/;
			return function (format) {
				return hourInfoRe.test(format.replace(stripEscapeRe,
						""))
			}
		}
		(),
		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() \x3d\x3d 1 \x26\x26 this.getMonth() \x3e 0 ? +1 : (this.getWeekOfYear() \x3e\x3d 52 \x26\x26 this.getMonth() \x3c 11 ? -1 : 0)))",
			Y : "String.leftPad(this.getFullYear(), 4, '0')",
			y : "('' + this.getFullYear()).substring(2, 4)",
			a : "(this.getHours() \x3c 12 ? 'am' : 'pm')",
			A : "(this.getHours() \x3c 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 () {
				var c = "Y-m-dTH:i:sP";
				var code = [];
				var i = 0;
				for (var 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)"
		},
		isValid : function (y, m, d, h, i, s, ms) {
			h = h || 0;
			i = i || 0;
			s = s || 0;
			ms = ms || 0;
			var dt = (new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms)).add(Date.YEAR, y < 100 ? y - 100 : 0);
			return y == dt.getFullYear() && m == dt.getMonth() + 1 && d == dt.getDate() && h == dt.getHours() && i == dt.getMinutes() && s == dt.getSeconds() && ms == dt.getMilliseconds()
		},
		parseDate : function (input, format, strict) {
			var p = Date.parseFunctions;
			if (p[format] == null)
				Date.createParser(format);
			return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict)
		},
		getFormatCode : function (character) {
			var f =
				Date.formatCodes[character];
			if (f) {
				f = typeof f == "function" ? f() : f;
				Date.formatCodes[character] = f
			}
			return f || "'" + String.escape(character) + "'"
		},
		createFormat : function (format) {
			var code = [];
			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.push("'" + String.escape(ch) + "'")
				} else
					code.push(Date.getFormatCode(ch))
			}
			Date.formatFunctions[format] = new Function("return " + code.join("+"))
		},
		createParser : function () {
			var code =
				["var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,", "def \x3d Date.defaults,", "results \x3d String(input).match(Date.parseRegexes[{0}]);", "if(results){", "{1}", "if(u !\x3d null){", "v \x3d new Date(u * 1000);", "}else{", "dt \x3d (new Date()).clearTime();", "y \x3d Ext.num(y, Ext.num(def.y, dt.getFullYear()));", "m \x3d Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));", "d \x3d Ext.num(d, Ext.num(def.d, dt.getDate()));", "h  \x3d Ext.num(h, Ext.num(def.h, dt.getHours()));", "i  \x3d Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
				"s  \x3d Ext.num(s, Ext.num(def.s, dt.getSeconds()));", "ms \x3d Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));", "if(z \x3e\x3d 0 \x26\x26 y \x3e\x3d 0){", "v \x3d new Date(y \x3c 100 ? 100 : y, 0, 1, h, i, s, ms).add(Date.YEAR, y \x3c 100 ? y - 100 : 0);", "v \x3d !strict? v : (strict \x3d\x3d\x3d true \x26\x26 (z \x3c\x3d 364 || (v.isLeapYear() \x26\x26 z \x3c\x3d 365))? v.add(Date.DAY, z) : null);", "}else if(strict \x3d\x3d\x3d true \x26\x26 !Date.isValid(y, m + 1, d, h, i, s, ms)){", "v \x3d null;",
				"}else{", "v \x3d new Date(y \x3c 100 ? 100 : y, m, d, h, i, s, ms).add(Date.YEAR, y \x3c 100 ? y - 100 : 0);", "}", "}", "}", "if(v){", "if(zz !\x3d null){", "v \x3d v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);", "}else if(o){", "v \x3d v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn \x3d\x3d '+'? -1 : 1) * (hr * 60 + mn));", "}", "}", "return v;"].join("\n");
			return function (format) {
				var regexNum = Date.parseRegexes.length;
				var currentGroup = 1;
				var calc = [];
				var regex = [];
				var special = false;
				var ch = "";
				var i = 0;
				var obj;
				for (var last; i < format.length; ++i) {
					ch = format.charAt(i);
					if (!special && ch == "\\")
						special = true;
					else if (special) {
						special = false;
						regex.push(String.escape(ch))
					} else {
						obj = $f(ch, currentGroup);
						currentGroup += obj.g;
						regex.push(obj.s);
						if (obj.g && obj.c)
							if (obj.calcLast)
								last = obj.c;
							else
								calc.push(obj.c)
					}
				}
				if (last)
					calc.push(last);
				Date.parseRegexes[regexNum] = new RegExp("^" + regex.join("") + "$", "i");
				Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join("")))
			}
		}
		(),
		parseCodes : {
			d : {
				g : 1,
				c : "d \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{2})"
			},
			j : {
				g : 1,
				c : "d \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{1,2})"
			},
			D : function () {
				var a = [];
				for (var 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 : 1,
				c : "z \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{1,3})"
			},
			W : {
				g : 0,
				c : null,
				s : "(?:\\d{2})"
			},
			F : function () {
				return {
					g : 1,
					c : "m \x3d parseInt(Date.getMonthNumber(results[{0}]), 10);\n",
					s : "(" + Date.monthNames.join("|") + ")"
				}
			},
			M : function () {
				var a = [];
				for (var i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i);
				return Ext.applyIf({
					s : "(" + a.join("|") + ")"
				}, $f("F"))
			},
			m : {
				g : 1,
				c : "m \x3d parseInt(results[{0}], 10) - 1;\n",
				s : "(\\d{2})"
			},
			n : {
				g : 1,
				c : "m \x3d 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 \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{4})"
			},
			y : {
				g : 1,
				c : "var ty \x3d parseInt(results[{0}], 10);\n" +
				"y \x3d ty \x3e Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
				s : "(\\d{1,2})"
			},
			a : function () {
				return $f("A")
			},
			A : {
				calcLast : true,
				g : 1,
				c : "if (/(am)/i.test(results[{0}])) {\n" + "if (!h || h \x3d\x3d 12) { h \x3d 0; }\n" + "} else { if (!h || h \x3c 12) { h \x3d (h || 0) + 12; }}",
				s : "(AM|PM|am|pm)"
			},
			g : function () {
				return $f("G")
			},
			G : {
				g : 1,
				c : "h \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{1,2})"
			},
			h : function () {
				return $f("H")
			},
			H : {
				g : 1,
				c : "h \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{2})"
			},
			i : {
				g : 1,
				c : "i \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{2})"
			},
			s : {
				g : 1,
				c : "s \x3d parseInt(results[{0}], 10);\n",
				s : "(\\d{2})"
			},
			u : {
				g : 1,
				c : "ms \x3d results[{0}]; ms \x3d parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
				s : "(\\d+)"
			},
			O : {
				g : 1,
				c : ["o \x3d results[{0}];", "var sn \x3d o.substring(0,1),", "hr \x3d o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", "mn \x3d o.substring(3,5) % 60;", "o \x3d ((-12 \x3c\x3d (hr*60 + mn)/60) \x26\x26 ((hr*60 + mn)/60 \x3c\x3d 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),
				s : "([+-]\\d{4})"
			},
			P : {
				g : 1,
				c : ["o \x3d results[{0}];", "var sn \x3d o.substring(0,1),", "hr \x3d o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", "mn \x3d o.substring(4,6) % 60;", "o \x3d ((-12 \x3c\x3d (hr*60 + mn)/60) \x26\x26 ((hr*60 + mn)/60 \x3c\x3d 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 : "zz \x3d results[{0}] * 1;\n" + "zz \x3d (-43200 \x3c\x3d zz \x26\x26 zz \x3c\x3d 50400)? zz : 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 \x3d results[7] || '0'; ms \x3d parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"
					}, {
						c : ["if(results[8]) {", "if(results[8] \x3d\x3d 'Z'){", "zz \x3d 0;", "}else if (results[8].indexOf(':') \x3e -1){", $f("P", 8).c, "}else{", $f("O", 8).c, "}", "}"].join("\n")
					}
				];
				var i = 0;
				for (var 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+))?", "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", ")?", ")?", ")?"].join("")
				}
			},
			U : {
				g : 1,
				c : "u \x3d parseInt(results[{0}], 10);\n",
				s : "(-?\\d+)"
			}
		}
	})
})();
Ext.apply(Date.prototype, {
	dateFormat : function (format) {
		if (Date.formatFunctions[format] == null)
			Date.createFormat(format);
		return Date.formatFunctions[format].call(this)
	},
	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.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0") + (colon ? ":" : "") + String.leftPad(Math.abs(this.getTimezoneOffset() %
				60), 2, "0")
	},
	getDayOfYear : function () {
		var num = 0;
		var d = this.clone();
		var m = this.getMonth();
		var i;
		for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i))
			num += d.getDaysInMonth();
		return num + this.getDate() - 1
	},
	getWeekOfYear : function () {
		var ms1d = 864E5;
		var ms7d = 7 * ms1d;
		return function () {
			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 () {
		return this.getLastDateOfMonth().getDay()
	},
	getFirstDateOfMonth : function () {
		return new Date(this.getFullYear(), this.getMonth(), 1)
	},
	getLastDateOfMonth : function () {
		return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth())
	},
	getDaysInMonth : function () {
		var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31,
			30, 31, 30, 31];
		return function () {
			var m = this.getMonth();
			return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m]
		}
	}
	(),
	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())
	},
	isDST : function () {
		return (new Date(this.getFullYear(), 0, 1)).getTimezoneOffset() != this.getTimezoneOffset()
	},
	clearTime : function (clone) {
		if (clone)
			return this.clone().clearTime();
		var d = this.getDate();
		this.setHours(0);
		this.setMinutes(0);
		this.setSeconds(0);
		this.setMilliseconds(0);
		if (this.getDate() != d) {
			var hr = 1;
			for (var c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
			this.setDate(d);
			this.setHours(c.getHours())
		}
		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 && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420)
	Ext.apply(Date.prototype, {
		_xMonth : Date.prototype.setMonth,
		_xDate : Date.prototype.setDate,
		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 this._xMonth(month)
			} else
				return this._xMonth(num)
		},
		setDate : function (d) {
			return this.setTime(this.getTime() - (this.getDate() - d) * 864E5)
		}
	});
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) {
			var old = this.map[key];
			if (typeof old != "undefined")
				return this.replace(key, o);
			this.map[key] = o
		}
		this.length++;
		this.items.push(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.map[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;
			var i = 0;
			for (var 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);
		var i = 0;
		for (var len = items.length; i < len; i++)
			if (fn.call(scope || items[i], items[i], i, len) === false)
				break
	},
	eachKey : function (fn, scope) {
		var i = 0;
		for (var len = this.keys.length; i < len; i++)
			fn.call(scope || window, this.keys[i], this.items[i], i, len)
	},
	find : function (fn, scope) {
		var i = 0;
		for (var 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 (this.containsKey(key)) {
			this.suspendEvents();
			this.removeKey(key);
			this.resumeEvents()
		}
		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 mk = this.map[key];
		var item = mk !== undefined ? mk : typeof key == "number" ? this.items[key] : undefined;
		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 i;
		var len;
		var dsc = String(dir).toUpperCase() ==
			"DESC" ? -1 : 1;
		var c = [];
		var keys = this.keys;
		var items = this.items;
		fn = fn || function (a, b) {
			return a - b
		};
		for (i = 0, len = items.length; i < len; i++)
			c[c.length] = {
				key : keys[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 (i = 0, len = c.length; i < len; i++) {
			items[i] = c[i].value;
			keys[i] = c[i].key
		}
		this.fireEvent("sort", this)
	},
	sort : function (dir, fn) {
		this._sort("value", dir, fn)
	},
	reorder : function (mapping) {
		this.suspendEvents();
		var items = this.items;
		var index =
			0;
		var length = items.length;
		var order = [];
		var remaining = [];
		for (var oldIndex in mapping)
			order[mapping[oldIndex]] = items[oldIndex];
		for (index = 0; index < length; index++)
			if (mapping[index] == undefined)
				remaining.push(items[index]);
		for (index = 0; index < length; index++)
			if (order[index] == undefined)
				order[index] = remaining.shift();
		this.clear();
		this.addAll(order);
		this.resumeEvents();
		this.fireEvent("sort", this)
	},
	keySort : function (dir, fn) {
		this._sort("key", dir, fn || function (a, b) {
			var v1 = String(a).toUpperCase();
			var v2 = String(b).toUpperCase();
			return v1 > v2 ? 1 : v1 < v2 ? -1 : 0
		})
	},
	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 i;
		var r = [];
		if (start <= end)
			for (i = start; i <= end; i++)
				r[r.length] = items[i];
		else
			for (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;
		var it = this.items;
		var i = 0;
		for (var 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;
		var it = this.items;
		var i = start || 0;
		for (var len = it.length; i < len; i++)
			if (fn.call(scope || this, it[i], k[i]))
				return i;
		return -1
	},
	createValueMatcher : function (value, anyMatch, caseSensitive, exactMatch) {
		if (!value.exec) {
			var er = Ext.escapeRe;
			value = String(value);
			if (anyMatch === true)
				value = er(value);
			else {
				value = "^" + er(value);
				if (exactMatch === true)
					value += "$"
			}
			value = new RegExp(value, caseSensitive ? "" : "i")
		}
		return value
	},
	clone : function () {
		var r = new Ext.util.MixedCollection;
		var k = this.keys;
		var it = this.items;
		var i = 0;
		for (var 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.AbstractManager = Ext.extend(Object, {
		typeName : "type",
		constructor : function (config) {
			Ext.apply(this, config || {});
			this.all = new Ext.util.MixedCollection;
			this.types = {}

		},
		get : function (id) {
			return this.all.get(id)
		},
		register : function (item) {
			this.all.add(item)
		},
		unregister : function (item) {
			this.all.remove(item)
		},
		registerType : function (type, cls) {
			this.types[type] = cls;
			cls[this.typeName] = type
		},
		isRegistered : function (type) {
			return this.types[type] !== undefined
		},
		create : function (config, defaultType) {
			var type = config[this.typeName] ||
				config.type || defaultType;
			var Constructor = this.types[type];
			if (Constructor == undefined)
				throw new Error(String.format("The '{0}' type has not been registered with this manager", type));
			return new Constructor(config)
		},
		onAvailable : function (id, fn, scope) {
			var all = this.all;
			all.on("add", function (index, o) {
				if (o.id == id) {
					fn.call(scope || o, o);
					all.un("add", fn, scope)
				}
			})
		}
	});
Ext.util.Format = function () {
	var trimRe = /^\s+|\s+$/g;
	var stripTagsRE = /<\/?[^>]+>/gi;
	var stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig;
	var nl2brRe = /\r?\n/g;
	return {
		ellipsis : function (value, len, word) {
			if (value && value.length > len)
				if (word) {
					var vs = value.substr(0, len - 2);
					var index = Math.max(vs.lastIndexOf(" "), vs.lastIndexOf("."), vs.lastIndexOf("!"), vs.lastIndexOf("?"));
					if (index == -1 || index < len - 15)
						return value.substr(0, len - 3) + "...";
					else
						return vs.substr(0, index) + "..."
				} else
					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, "\x26amp;").replace(/>/g, "\x26gt;").replace(/</g, "\x26lt;").replace(/"/g, "\x26quot;")
		},
		htmlDecode : function (value) {
			return !value ? value : String(value).replace(/&gt;/g, "\x3e").replace(/&lt;/g, "\x3c").replace(/&quot;/g, '"').replace(/&amp;/g, "\x26")
		},
		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";
			for (var r = /(\d+)(\d{3})/; 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)
			}
		},
		stripTags : function (v) {
			return !v ? v : String(v).replace(stripTagsRE, "")
		},
		stripScripts : function (v) {
			return !v ? v : String(v).replace(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)
			}
		}
		(),
		round : function (value, precision) {
			var result = Number(value);
			if (typeof precision == "number") {
				precision = Math.pow(10, precision);
				result = Math.round(value * precision) / precision
			}
			return result
		},
		number : function (v, format) {
			if (!format)
				return v;
			v = Ext.num(v, NaN);
			if (isNaN(v))
				return "";
			var comma = ",";
			var dec = ".";
			var i18n = false;
			var neg = v < 0;
			v = Math.abs(v);
			if (format.substr(format.length - 2) == "/i") {
				format = format.substr(0, format.length - 2);
				i18n = true;
				comma = ".";
				dec = ","
			}
			var hasComma = format.indexOf(comma) != -1;
			var psplit = (i18n ? format.replace(/[^\d\,]/g, "") : format.replace(/[^\d\.]/g, "")).split(dec);
			if (1 < psplit.length)
				v = v.toFixed(psplit[1].length);
			else if (2 < psplit.length)
				throw "NumberFormatException: invalid format, formats should have no more than 1 period: " + format;
			else
				v = v.toFixed(0);
			var fnum = v.toString();
			psplit = fnum.split(".");
			if (hasComma) {
				var cnum = psplit[0];
				var parr = [];
				var j = cnum.length;
				var m = Math.floor(j / 3);
				var n = cnum.length % 3 || 3;
				var i;
				for (i = 0; i < j; i += n) {
					if (i != 0)
						n = 3;
					parr[parr.length] = cnum.substr(i, n);
					m -= 1
				}
				fnum = parr.join(comma);
				if (psplit[1])
					fnum += dec + psplit[1]
			} else if (psplit[1])
				fnum = psplit[0] +
					dec + psplit[1];
			return (neg ? "-" : "") + format.replace(/[\d,?\.?]+/, fnum)
		},
		numberRenderer : function (format) {
			return function (v) {
				return Ext.util.Format.number(v, format)
			}
		},
		plural : function (v, s, p) {
			return v + " " + (v == 1 ? s : p ? p : s + "s")
		},
		nl2br : function (v) {
			return Ext.isEmpty(v) ? "" : v.replace(nl2brRe, "\x3cbr/\x3e")
		}
	}
}
();
Ext.XTemplate = function () {
	Ext.XTemplate.superclass.constructor.apply(this, arguments);
	var me = this;
	var s = me.html;
	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;
	var id = 0;
	var tpls = [];
	var VALUES = "values";
	var PARENT = "parent";
	var XINDEX = "xindex";
	var XCOUNT = "xcount";
	var RETURN = "return ";
	var WITHVALUES = "with(values){ ";
	for (s = ["\x3ctpl\x3e", s, "\x3c/tpl\x3e"].join(""); 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;
		var fn = null;
		var 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, WITHVALUES + RETURN + Ext.util.Format.htmlDecode(exp) + "; }")
		}
		if (m4) {
			exp = m4 && m4[1] ? m4[1] : null;
			if (exp)
				exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.util.Format.htmlDecode(exp) + "; }")
		}
		if (name)
			switch (name) {
			case ".":
				name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + "; }");
				break;
			case "..":
				name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + "; }");
				break;
			default:
				name = new Function(VALUES, PARENT, WITHVALUES + 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)
		me.compileTpl(tpls[i]);
	me.master = tpls[tpls.length - 1];
	me.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 me = this;
		var len;
		var t = me.tpls[id];
		var vs;
		var buf = [];
		if (t.test && !t.test.call(me, values, parent, xindex, xcount) || t.exec && t.exec.call(me, values, parent, xindex, xcount))
			return "";
		vs = t.target ? t.target.call(me, values, parent) : values;
		len = vs.length;
		parent = t.target ? values : parent;
		if (t.target &&
			Ext.isArray(vs)) {
			var i = 0;
			for (len = vs.length; i < len; i++)
				buf[buf.length] = t.compiled.call(me, vs[i], parent, i + 1, len);
			return buf.join("")
		}
		return t.compiled.call(me, vs, parent, xindex, xcount)
	},
	compileTpl : function (tpl) {
		function fn(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 + " \x3d\x3d\x3d undefined ? '' : "
			}
			return "'" + sep + format + v + args + ")" + sep + "'"
		}
		function codeFn(m, code) {
			return "'" + sep + "(" + code.replace(/\\'/g, "'") + ")" + sep + "'"
		}
		var fm = Ext.util.Format;
		var useF = this.disableFormats !== true;
		var sep = Ext.isGecko ? "+" : ",";
		var body;
		if (Ext.isGecko)
			body = "tpl.compiled \x3d 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 \x3d 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.toLowerCase()] = ssRules[j]
			} catch (e) {}

		},
		getRules : function (refreshCache) {
			if (rules === null || refreshCache) {
				rules = {};
				var ds = doc.styleSheets;
				var i = 0;
				for (var 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.toLowerCase()];
			for (var i = 0; i < selector.length; i++)
				if (rs[selector[i]])
					return rs[selector[i].toLowerCase()];
			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 = Ext.extend(Ext.util.Observable, {
		constructor : function (el, config) {
			this.el = Ext.get(el);
			this.el.unselectable();
			Ext.apply(this, config);
			this.addEvents("mousedown", "click", "mouseup");
			if (!this.disabled) {
				this.disabled = true;
				this.enable()
			}
			if (this.handler)
				this.on("click", this.handler, this.scope || this);
			Ext.util.ClickRepeater.superclass.constructor.call(this)
		},
		interval : 20,
		delay : 250,
		preventDefault : true,
		stopDefault : false,
		timer : 0,
		enable : function () {
			if (this.disabled) {
				this.el.on("mousedown", this.handleMouseDown,
					this);
				if (Ext.isIE)
					this.el.on("dblclick", this.handleDblClick, this);
				if (this.preventDefault || this.stopDefault)
					this.el.on("click", this.eventOptions, this)
			}
			this.disabled = false
		},
		disable : function (force) {
			if (force || !this.disabled) {
				clearTimeout(this.timer);
				if (this.pressClass)
					this.el.removeClass(this.pressClass);
				Ext.getDoc().un("mouseup", this.handleMouseUp, this);
				this.el.removeAllListeners()
			}
			this.disabled = true
		},
		setDisabled : function (disabled) {
			this[disabled ? "disable" : "enable"]()
		},
		eventOptions : function (e) {
			if (this.preventDefault)
				e.preventDefault();
			if (this.stopDefault)
				e.stopEvent()
		},
		destroy : function () {
			this.disable(true);
			Ext.destroy(this.el);
			this.purgeListeners()
		},
		handleDblClick : function (e) {
			clearTimeout(this.timer);
			this.el.blur();
			this.fireEvent("mousedown", this, e);
			this.fireEvent("click", this, e)
		},
		handleMouseDown : function (e) {
			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, e);
			this.fireEvent("click", this, e);
			if (this.accelerate)
				this.delay = 400;
			this.timer = this.click.defer(this.delay || this.interval, this, [e])
		},
		click : function (e) {
			this.fireEvent("click", this, e);
			this.timer = this.click.defer(this.accelerate ? this.easeOutExpo(this.mousedownTime.getElapsed(), 400, -390, 12E3) : this.interval, this, [e])
		},
		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 (e) {
			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, e)
		}
	});
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,
	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, hname)
	},
	enter : false,
	left : false,
	right : false,
	up : false,
	down : false,
	tab : false,
	esc : false,
	pageUp : false,
	pageDown : false,
	del : false,
	home : false,
	end : false,
	space : 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",
		32 : "space"
	},
	stopKeyUp : function (e) {
		var k = e.getKey();
		if (k >= 37 && k <= 40)
			e.stopEvent()
	},
	destroy : function () {
		this.disable()
	},
	enable : function () {
		if (this.disabled) {
			if (Ext.isSafari2)
				this.el.on("keyup", this.stopKeyUp, this);
			this.el.on(this.isKeydown() ? "keydown" : "keypress", this.relay, this);
			this.disabled = false
		}
	},
	disable : function () {
		if (!this.disabled) {
			if (Ext.isSafari2)
				this.el.un("keyup", this.stopKeyUp, this);
			this.el.un(this.isKeydown() ? "keydown" :
				"keypress", this.relay, this);
			this.disabled = true
		}
	},
	setDisabled : function (disabled) {
		this[disabled ? "disable" : "enable"]()
	},
	isKeydown : function () {
		return this.forceKeyDown || Ext.EventManager.useKeydown
	}
};
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)) {
			Ext.each(config, function (c) {
				this.addBinding(c)
			}, this);
			return
		}
		var keyCode = config.key;
		var fn = config.fn || config.handler;
		var scope = config.scope;
		if (config.stopEvent)
			this.stopEvent = config.stopEvent;
		if (typeof keyCode == "string") {
			var ks = [];
			var keyString = keyCode.toUpperCase();
			var j = 0;
			for (var len$$0 = keyString.length; j < len$$0; j++)
				ks.push(keyString.charCodeAt(j));
			keyCode = ks
		}
		var keyArray = Ext.isArray(keyCode);
		var handler = function (e) {
			if (this.checkModifiers(config,
					e)) {
				var k = e.getKey();
				if (keyArray) {
					var i = 0;
					for (var 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)
	},
	checkModifiers : function (config, e) {
		var val;
		var key;
		var keys = ["shift", "ctrl", "alt"];
		var i = 0;
		for (var len = keys.length; i < len; ++i) {
			key = keys[i];
			val = config[key];
			if (!(val === undefined || val === e[key + "Key"]))
				return false
		}
		return true
	},
	on : function (key,
		fn, scope) {
		var keyCode;
		var shift;
		var ctrl;
		var 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;
			var i = 0;
			for (var 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
		}
	},
	setDisabled : function (disabled) {
		this[disabled ? "disable" : "enable"]()
	}
};
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(-1E3, -1E3);
	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.addMethods({
	getTextWidth : function (text, min, max) {
		return Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width.constrain(min || 0, max || 1E6)
	}
});
Ext.util.Cookies = {
	set : function (name, value) {
		var argv = arguments;
		var argc = arguments.length;
		var expires = argc > 2 ? argv[2] : null;
		var path = argc > 3 ? argv[3] : "/";
		var domain = argc > 4 ? argv[4] : null;
		var secure = argc > 5 ? argv[5] : false;
		document.cookie = name + "\x3d" + escape(value) + (expires === null ? "" : "; expires\x3d" + expires.toGMTString()) + (path === null ? "" : "; path\x3d" + path) + (domain === null ? "" : "; domain\x3d" + domain) + (secure === true ? "; secure" : "")
	},
	get : function (name) {
		var arg = name + "\x3d";
		var alen = arg.length;
		var clen = document.cookie.length;
		var i = 0;
		for (var j = 0; i < clen; ) {
			j = i + alen;
			if (document.cookie.substring(i, j) == arg)
				return Ext.util.Cookies.getCookieVal(j);
			i = document.cookie.indexOf(" ", i) + 1;
			if (i === 0)
				break
		}
		return null
	},
	clear : function (name) {
		if (Ext.util.Cookies.get(name))
			document.cookie = name + "\x3d" + "; expires\x3dThu, 01-Jan-70 00:00:01 GMT"
	},
	getCookieVal : function (offset) {
		var endstr = document.cookie.indexOf(";", offset);
		if (endstr == -1)
			endstr = document.cookie.length;
		return unescape(document.cookie.substring(offset, endstr))
	}
};
Ext.handleError = function (e) {
	throw e;
};
Ext.Error = function (message) {
	this.message = this.lang[message] ? this.lang[message] : message
};
Ext.Error.prototype = new Error;
Ext.apply(Ext.Error.prototype, {
	lang : {},
	name : "Ext.Error",
	getName : function () {
		return this.name
	},
	getMessage : function () {
		return this.message
	},
	toJson : function () {
		return Ext.encode(this)
	}
});
Ext.ComponentMgr = function () {
	var all = new Ext.util.MixedCollection;
	var types = {};
	var ptypes = {};
	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,
		types : types,
		ptypes : ptypes,
		isRegistered : function (xtype) {
			return types[xtype] !== undefined
		},
		isPluginRegistered : function (ptype) {
			return ptypes[ptype] !== undefined
		},
		registerType : function (xtype,
			cls) {
			types[xtype] = cls;
			cls.xtype = xtype
		},
		create : function (config, defaultType) {
			return config.render ? config : new types[config.xtype || defaultType](config)
		},
		registerPlugin : function (ptype, cls) {
			ptypes[ptype] = cls;
			cls.ptype = ptype
		},
		createPlugin : function (config, defaultType) {
			var PluginCls = ptypes[config.ptype || defaultType];
			if (PluginCls.init)
				return PluginCls;
			else
				return new PluginCls(config)
		}
	}
}
();
Ext.reg = Ext.ComponentMgr.registerType;
Ext.preg = Ext.ComponentMgr.registerPlugin;
Ext.create = Ext.ComponentMgr.create;
Ext.Component = function (config) {
	config = config || {};
	if (config.initialConfig) {
		if (config.isAction)
			this.baseAction = config;
		config = config.initialConfig
	} else if (config.tagName || config.dom || Ext.isString(config))
		config = {
			applyTo : config,
			id : config.id || config
		};
	this.initialConfig = config;
	Ext.apply(this, config);
	this.addEvents("added", "disable", "enable", "beforeshow", "show", "beforehide", "hide", "removed", "beforerender", "render", "afterrender", "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)) {
			var i = 0;
			for (var 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();
	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 = 1E3;
Ext.extend(Ext.Component, Ext.util.Observable, {
	disabled : false,
	hidden : false,
	autoEl : "div",
	disabledClass : "x-item-disabled",
	allowDomMove : true,
	autoShow : false,
	hideMode : "display",
	hideParent : false,
	rendered : false,
	tplWriteMode : "overwrite",
	bubbleEvents : [],
	ctype : "Ext.Component",
	actionMode : "el",
	getActionEl : function () {
		return this[this.actionMode]
	},
	initPlugin : function (p) {
		if (p.ptype && !Ext.isFunction(p.init))
			p = Ext.ComponentMgr.createPlugin(p);
		else if (Ext.isString(p))
			p = Ext.ComponentMgr.createPlugin({
					ptype : p
				});
		p.init(this);
		return p
	},
	initComponent : function () {
		if (this.listeners) {
			this.on(this.listeners);
			delete this.listeners
		}
		this.enableBubble(this.bubbleEvents)
	},
	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 (Ext.isNumber(position))
					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
			}
			if (this.overCls)
				this.el.addClassOnOver(this.overCls);
			this.fireEvent("render", this);
			var contentTarget = this.getContentTarget();
			if (this.html) {
				contentTarget.update(Ext.DomHelper.markup(this.html));
				delete this.html
			}
			if (this.contentEl) {
				var ce = Ext.getDom(this.contentEl);
				Ext.fly(ce).removeClass(["x-hidden", "x-hide-display"]);
				contentTarget.appendChild(ce)
			}
			if (this.tpl) {
				if (!this.tpl.compile)
					this.tpl = new Ext.XTemplate(this.tpl);
				if (this.data) {
					this.tpl[this.tplWriteMode](contentTarget, this.data);
					delete this.data
				}
			}
			this.afterRender(this.container);
			if (this.hidden)
				this.doHide();
			if (this.disabled)
				this.disable(true);
			if (this.stateful !== false)
				this.initStateEvents();
			this.fireEvent("afterrender", this)
		}
		return this
	},
	update : function (htmlOrData, loadScripts, cb) {
		var contentTarget = this.getContentTarget();
		if (this.tpl && typeof htmlOrData !== "string")
			this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
		else {
			var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
			contentTarget.update(html, loadScripts, cb)
		}
	},
	onAdded : function (container, pos) {
		this.ownerCt = container;
		this.initRef();
		this.fireEvent("added", this, container, pos)
	},
	onRemoved : function () {
		this.removeRef();
		this.fireEvent("removed", this, this.ownerCt);
		delete this.ownerCt
	},
	initRef : function () {
		if (this.ref && !this.refOwner) {
			var levels = this.ref.split("/");
			var last = levels.length;
			var i = 0;
			for (var t = this; t && i < last; ) {
				t = t.ownerCt;
				++i
			}
			if (t) {
				t[this.refName = levels[--i]] = this;
				this.refOwner = t
			}
		}
	},
	removeRef : function () {
		if (this.refOwner && this.refName) {
			delete this.refOwner[this.refName];
			delete this.refOwner
		}
	},
	initState : function () {
		if (Ext.state.Manager) {
			var id = this.getStateId();
			if (id) {
				var state = Ext.state.Manager.get(id);
				if (state)
					if (this.fireEvent("beforestaterestore",
							this, state) !== false) {
						this.applyState(Ext.apply({}, state));
						this.fireEvent("staterestore", this, state)
					}
			}
		}
	},
	getStateId : function () {
		return this.stateId || (/^(ext-comp-|ext-gen)/.test(String(this.id)) ? null : this.id)
	},
	initStateEvents : function () {
		if (this.stateEvents) {
			var i = 0;
			for (var e; e = this.stateEvents[i]; i++)
				this.on(e, this.saveState, this, {
					delay : 100
				})
		}
	},
	applyState : function (state) {
		if (state)
			Ext.apply(this, state)
	},
	getState : function () {
		return null
	},
	saveState : function () {
		if (Ext.state.Manager && this.stateful !== false) {
			var id =
				this.getStateId();
			if (id) {
				var state = this.getState();
				if (this.fireEvent("beforestatesave", this, state) !== false) {
					Ext.state.Manager.set(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;
		return this
	},
	removeClass : function (cls) {
		if (this.el)
			this.el.removeClass(cls);
		else if (this.cls)
			this.cls = this.cls.split(" ").remove(cls).join(" ");
		return this
	},
	onRender : function (ct, position) {
		if (!this.el && this.autoEl) {
			if (Ext.isString(this.autoEl))
				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 (div) {
					Ext.removeNode(div);
					div = null
				}
			}
		}
	},
	getAutoCreate : function () {
		var cfg = Ext.isObject(this.autoCreate) ?
			this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
		if (this.id && !cfg.id)
			cfg.id = this.id;
		return cfg
	},
	afterRender : Ext.emptyFn,
	destroy : function () {
		if (!this.isDestroyed)
			if (this.fireEvent("beforedestroy", this) !== false) {
				this.destroying = true;
				this.beforeDestroy();
				if (this.ownerCt && this.ownerCt.remove)
					this.ownerCt.remove(this, false);
				if (this.rendered) {
					this.el.remove();
					if (this.actionMode == "container" || this.removeMode == "container")
						this.container.remove()
				}
				if (this.focusTask && this.focusTask.cancel)
					this.focusTask.cancel();
				this.onDestroy();
				Ext.ComponentMgr.unregister(this);
				this.fireEvent("destroy", this);
				this.purgeListeners();
				this.destroying = false;
				this.isDestroyed = true
			}
	},
	deleteMembers : function () {
		var args = arguments;
		var i = 0;
		for (var len = args.length; i < len; ++i)
			delete this[args[i]]
	},
	beforeDestroy : Ext.emptyFn,
	onDestroy : Ext.emptyFn,
	getEl : function () {
		return this.el
	},
	getContentTarget : 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.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
			this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
			return this
		}
		if (this.rendered && !this.isDestroyed) {
			this.el.focus();
			if (selectText === true)
				this.el.dom.select()
		}
		return this
	},
	blur : function () {
		if (this.rendered)
			this.el.blur();
		return this
	},
	disable : function (silent) {
		if (this.rendered)
			this.onDisable();
		this.disabled = true;
		if (silent !== 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) {
		return this[disabled ? "disable" : "enable"]()
	},
	show : function () {
		if (this.fireEvent("beforeshow", this) !== false) {
			this.hidden = false;
			if (this.autoRender)
				this.render(Ext.isBoolean(this.autoRender) ?
					Ext.getBody() : this.autoRender);
			if (this.rendered)
				this.onShow();
			this.fireEvent("show", this)
		}
		return this
	},
	onShow : function () {
		this.getVisibilityEl().removeClass("x-hide-" + this.hideMode)
	},
	hide : function () {
		if (this.fireEvent("beforehide", this) !== false) {
			this.doHide();
			this.fireEvent("hide", this)
		}
		return this
	},
	doHide : function () {
		this.hidden = true;
		if (this.rendered)
			this.onHide()
	},
	onHide : function () {
		this.getVisibilityEl().addClass("x-hide-" + this.hideMode)
	},
	getVisibilityEl : function () {
		return this.hideParent ? this.container :
		this.getActionEl()
	},
	setVisible : function (visible) {
		return this[visible ? "show" : "hide"]()
	},
	isVisible : function () {
		return this.rendered && this.getVisibilityEl().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) {
		if (Ext.isFunction(xtype))
			xtype = xtype.xtype;
		else if (Ext.isObject(xtype))
			xtype =
				xtype.constructor.xtype;
		return !shallow ? ("/" + this.getXTypes() + "/").indexOf("/" + xtype + "/") != -1 : this.constructor.xtype == xtype
	},
	getXTypes : function () {
		var tc = this.constructor;
		if (!tc.xtypes) {
			var c = [];
			for (var sc = this; 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, shallow) {
		return this.findParentBy(function (c) {
			return c.isXType(xtype,
				shallow)
		})
	},
	bubble : function (fn, scope, args) {
		for (var p = this; p; ) {
			if (fn.apply(scope || p, args || [p]) === false)
				break;
			p = p.ownerCt
		}
		return this
	},
	getPositionEl : function () {
		return this.positionEl || this.el
	},
	purgeListeners : function () {
		Ext.Component.superclass.purgeListeners.call(this);
		if (this.mons)
			this.on("beforedestroy", this.clearMons, this, {
				single : true
			})
	},
	clearMons : function () {
		Ext.each(this.mons, function (m) {
			m.item.un(m.ename, m.fn, m.scope)
		}, this);
		this.mons = []
	},
	createMons : function () {
		if (!this.mons) {
			this.mons = [];
			this.on("beforedestroy",
				this.clearMons, this, {
				single : true
			})
		}
	},
	mon : function (item, ename, fn, scope, opt) {
		this.createMons();
		if (Ext.isObject(ename)) {
			var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
			var o = ename;
			for (var e in o) {
				if (propRe.test(e))
					continue;
				if (Ext.isFunction(o[e])) {
					this.mons.push({
						item : item,
						ename : e,
						fn : o[e],
						scope : o.scope
					});
					item.on(e, o[e], o.scope, o)
				} else {
					this.mons.push({
						item : item,
						ename : e,
						fn : o[e],
						scope : o.scope
					});
					item.on(e, o[e])
				}
			}
			return
		}
		this.mons.push({
			item : item,
			ename : ename,
			fn : fn,
			scope : scope
		});
		item.on(ename, fn, scope, opt)
	},
	mun : function (item, ename, fn, scope) {
		var found;
		var mon;
		this.createMons();
		var i = 0;
		for (var len = this.mons.length; i < len; ++i) {
			mon = this.mons[i];
			if (item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope) {
				this.mons.splice(i, 1);
				item.un(ename, fn, scope);
				found = true;
				break
			}
		}
		return found
	},
	nextSibling : function () {
		if (this.ownerCt) {
			var index = this.ownerCt.items.indexOf(this);
			if (index != -1 && index + 1 < this.ownerCt.items.getCount())
				return this.ownerCt.items.itemAt(index +
					1)
		}
		return null
	},
	previousSibling : function () {
		if (this.ownerCt) {
			var index = this.ownerCt.items.indexOf(this);
			if (index > 0)
				return this.ownerCt.items.itemAt(index - 1)
		}
		return null
	},
	getBubbleTarget : function () {
		return this.ownerCt
	}
});
Ext.reg("component", Ext.Component);
Ext.Action = Ext.extend(Object, {
		constructor : function (config) {
			this.initialConfig = config;
			this.itemId = config.itemId = config.itemId || config.id || Ext.id();
			this.items = []
		},
		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;
			var i = 0;
			for (var 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;
		var 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.setVisibilityMode(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.getShim() || this).getStyle("z-index"), 10) || 11E3
		},
		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;
				if (Ext.isDefined(this.lastShadowOffset)) {
					this.shadowOffset = this.lastShadowOffset;
					delete this.lastShadowOffset
				}
				if (show)
					this.sync(true)
			}
		},
		sync : function (doShow) {
			var shadow = this.shadow;
			if (!this.updating && this.isVisible() && (shadow || this.useShim)) {
				var shim = this.getShim();
				var w = this.getWidth();
				var h = this.getHeight();
				var l = this.getLeft(true);
				var t = this.getTop(true);
				if (shadow && !this.shadowDisabled) {
					if (doShow && !shadow.isVisible())
						shadow.show(this);
					else
						shadow.realign(l, t, w, h);
					if (shim) {
						if (doShow)
							shim.show();
						var shadowAdj = shadow.el.getXY();
						var shimStyle = shim.dom.style;
						var shadowSize = shadow.el.getSize();
						shimStyle.left = shadowAdj[0] + "px";
						shimStyle.top = shadowAdj[1] + "px";
						shimStyle.width = shadowSize.width + "px";
						shimStyle.height = shadowSize.height + "px"
					}
				} else if (shim) {
					if (doShow)
						shim.show();
					shim.setSize(w, h);
					shim.setLeftTop(l, t)
				}
			}
		},
		destroy : function () {
			this.hideShim();
			if (this.shadow)
				this.shadow.hide();
			this.removeAllListeners();
			Ext.removeNode(this.dom);
			delete this.dom
		},
		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();
				var vh = Ext.lib.Dom.getViewHeight();
				var s = Ext.getDoc().getScroll();
				var xy = this.getXY();
				var x = xy[0];
				var y = xy[1];
				var so = this.shadowOffset;
				var w =
					this.dom.offsetWidth + so;
				var h = this.dom.offsetHeight + so;
				var moved = false;
				if (x + w > vw + s.left) {
					x = vw - w - so;
					moved = true
				}
				if (y + h > vh + s.top) {
					y = vh - h - so;
					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()
				}
			}
			return this
		},
		getConstrainOffset : function () {
			return this.shadowOffset
		},
		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(-1E4, -1E4)
		},
		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);
				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()
			}
			return this
		},
		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();
			return this
		},
		setTop : function (top) {
			this.storeLeftTop(this.getLeft(true), top);
			supr.setTop.apply(this, arguments);
			this.sync();
			return this
		},
		setLeftTop : function (left, top) {
			this.storeLeftTop(left, top);
			supr.setLeftTop.apply(this, arguments);
			this.sync();
			return this
		},
		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();
			return this
		},
		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);
			return this
		},
		setY : function (y, a, d, c, e) {
			this.setXY([this.getX(), y], a, d, c, e);
			return this
		},
		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();
			return this
		},
		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();
			return this
		},
		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();
			return this
		},
		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);
			return this
		}
	})
})();
Ext.Shadow = function (config) {
	Ext.apply(this, config);
	if (typeof this.mode != "string")
		this.mode = this.defaultMode;
	var o = this.offset;
	var 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\x3d50) progid:DXImageTransform.Microsoft.Blur(pixelradius\x3d" + 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;
		var d = this.el.dom;
		var s = d.style;
		var iea = 0;
		var sw = w + a.w;
		var sh = h + a.h;
		var sws = sw + "px";
		var shs = sh + "px";
		var cn;
		var sww;
		s.left = l + a.l + "px";
		s.top = t + a.t + "px";
		if (s.width != sws || s.height != shs) {
			s.width = sws;
			s.height = shs;
			if (!Ext.isIE) {
				cn = d.childNodes;
				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 ? '\x3cdiv class\x3d"x-ie-shadow"\x3e\x3c/div\x3e' : '\x3cdiv class\x3d"x-shadow"\x3e\x3cdiv class\x3d"xst"\x3e\x3cdiv class\x3d"xstl"\x3e\x3c/div\x3e\x3cdiv class\x3d"xstc"\x3e\x3c/div\x3e\x3cdiv class\x3d"xstr"\x3e\x3c/div\x3e\x3c/div\x3e\x3cdiv class\x3d"xsc"\x3e\x3cdiv class\x3d"xsml"\x3e\x3c/div\x3e\x3cdiv class\x3d"xsmc"\x3e\x3c/div\x3e\x3cdiv class\x3d"xsmr"\x3e\x3c/div\x3e\x3c/div\x3e\x3cdiv class\x3d"xsb"\x3e\x3cdiv class\x3d"xsbl"\x3e\x3c/div\x3e\x3cdiv class\x3d"xsbc"\x3e\x3c/div\x3e\x3cdiv class\x3d"xsbr"\x3e\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e';
	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 (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && w < this.boxMinWidth)
				w = this.boxMinWidth;
			if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && h < this.boxMinHeight)
				h = this.boxMinHeight;
			if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && w > this.boxMaxWidth)
				w =
					this.boxMaxWidth;
			if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && h > this.boxMaxHeight)
				h = this.boxMaxHeight;
			if (!this.boxReady) {
				this.width = w;
				this.height = h;
				return this
			}
			if (this.cacheSizes !== false && 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;
			var ah = adj.height;
			var rz;
			if (aw !== undefined || ah !== undefined) {
				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.getResizeEl().getSize()
		},
		getWidth : function () {
			return this.getResizeEl().getWidth()
		},
		getHeight : function () {
			return this.getResizeEl().getHeight()
		},
		getOuterSize : function () {
			var el =
				this.getResizeEl();
			return {
				width : el.getWidth() + el.getMargins("lr"),
				height : el.getHeight() + el.getMargins("tb")
			}
		},
		getPosition : function (local) {
			var el = this.getPositionEl();
			if (local === true)
				return [el.getLeft(true), el.getTop(true)];
			return this.xy || el.getXY()
		},
		getBox : function (local) {
			var pos = this.getPosition(local);
			var s = this.getSize();
			s.x = pos[0];
			s.y = pos[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
		},
		setAutoScroll : function (scroll) {
			if (this.rendered)
				this.getContentTarget().setOverflow(scroll ? "auto" : "");
			this.autoScroll = scroll;
			return this
		},
		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;
			var 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.getPositionEl().translatePoints(x, y);
			this.setPosition(p.left, p.top);
			return this
		},
		afterRender : function () {
			Ext.BoxComponent.superclass.afterRender.call(this);
			if (this.resizeEl)
				this.resizeEl = Ext.get(this.resizeEl);
			if (this.positionEl)
				this.positionEl = Ext.get(this.positionEl);
			this.boxReady = true;
			Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
			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.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().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.Spacer = Ext.extend(Ext.BoxComponent, {
		autoEl : "div"
	});
Ext.reg("spacer", Ext.Spacer);
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 = 2E3;
	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 : "\x26#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.tickSize);
			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.tickSize)
		}
		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) {
			Ext.destroy(this.overlay);
			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) {
		Ext.destroy(this.shim, Ext.get(this.proxy));
		this.dd.unreg();
		if (removeEl)
			this.el.remove();
		this.purgeListeners()
	}
});
Ext.SplitBar.createProxy = function (dir) {
	var proxy = new Ext.Element(document.createElement("div"));
	document.body.appendChild(proxy.dom);
	proxy.unselectable();
	var cls = "x-splitbar-proxy";
	proxy.addClass(cls + " " + (dir == Ext.SplitBar.HORIZONTAL ? cls + "-h" : cls + "-v"));
	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, 0.1, onComplete, "easeOut");
		else if (!s.animate) {
			s.resizingEl.setHeight(newSize);
			if (onComplete)
				onComplete(s,
					newSize)
		} else
			s.resizingEl.setHeight(newSize, true, 0.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, {
		bufferResize : 50,
		autoDestroy : true,
		forceLayout : false,
		defaultType : "panel",
		resizeEvent : "resize",
		bubbleEvents : ["add", "remove"],
		initComponent : function () {
			Ext.Container.superclass.initComponent.call(this);
			this.addEvents("afterlayout", "beforeadd", "beforeremove", "add", "remove");
			var items = this.items;
			if (items) {
				delete this.items;
				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.layout = layout;
			this.initItems();
			layout.setContainer(this)
		},
		afterRender : function () {
			Ext.Container.superclass.afterRender.call(this);
			if (!this.layout)
				this.layout = "auto";
			if (Ext.isObject(this.layout) && !this.layout.layout) {
				this.layoutConfig = this.layout;
				this.layout = this.layoutConfig.type
			}
			if (Ext.isString(this.layout))
				this.layout = new(Ext.Container.LAYOUTS[this.layout.toLowerCase()])(this.layoutConfig);
			this.setLayout(this.layout);
			if (this.activeItem !== undefined && this.layout.setActiveItem) {
				var item = this.activeItem;
				delete this.activeItem;
				this.layout.setActiveItem(item)
			}
			if (!this.ownerCt)
				this.doLayout(false, true);
			if (this.monitorResize === true)
				Ext.EventManager.onWindowResize(this.doLayout, this, [false])
		},
		getLayoutTarget : function () {
			return this.el
		},
		getComponentId : function (comp) {
			return comp.getItemId()
		},
		add : function (comp) {
			this.initItems();
			var args = arguments.length > 1;
			if (args || Ext.isArray(comp)) {
				var result = [];
				Ext.each(args ? arguments : comp,
					function (c) {
					result.push(this.add(c))
				}, this);
				return result
			}
			var c$$0 = this.lookupComponent(this.applyDefaults(comp));
			var index = this.items.length;
			if (this.fireEvent("beforeadd", this, c$$0, index) !== false && this.onBeforeAdd(c$$0) !== false) {
				this.items.add(c$$0);
				c$$0.onAdded(this, index);
				this.onAdd(c$$0);
				this.fireEvent("add", this, c$$0, index)
			}
			return c$$0
		},
		onAdd : function (c) {},
		onAdded : function (container, pos) {
			this.ownerCt = container;
			this.initRef();
			this.cascade(function (c) {
				c.initRef()
			});
			this.fireEvent("added", this,
				container, pos)
		},
		insert : function (index, comp) {
			var args = arguments;
			var length = args.length;
			var result = [];
			var i;
			var c;
			this.initItems();
			if (length > 2) {
				for (i = length - 1; i >= 1; --i)
					result.push(this.insert(index, args[i]));
				return result
			}
			c = this.lookupComponent(this.applyDefaults(comp));
			index = Math.min(index, this.items.length);
			if (this.fireEvent("beforeadd", this, c, index) !== false && this.onBeforeAdd(c) !== false) {
				if (c.ownerCt == this)
					this.items.remove(c);
				this.items.insert(index, c);
				c.onAdded(this, index);
				this.onAdd(c);
				this.fireEvent("add",
					this, c, index)
			}
			return c
		},
		applyDefaults : function (c) {
			var d = this.defaults;
			if (d) {
				if (Ext.isFunction(d))
					d = d.call(this, c);
				if (Ext.isString(c)) {
					c = Ext.ComponentMgr.get(c);
					Ext.apply(c, d)
				} else if (!c.events)
					Ext.applyIf(c.isAction ? c.initialConfig : c, d);
				else
					Ext.apply(c, d)
			}
			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) {
			this.initItems();
			var c = this.getComponent(comp);
			if (c && this.fireEvent("beforeremove",
					this, c) !== false) {
				this.doRemove(c, autoDestroy);
				this.fireEvent("remove", this, c)
			}
			return c
		},
		onRemove : function (c) {},
		doRemove : function (c, autoDestroy) {
			var l = this.layout;
			var hasLayout = l && this.rendered;
			if (hasLayout)
				l.onRemove(c);
			this.items.remove(c);
			c.onRemoved();
			this.onRemove(c);
			if (autoDestroy === true || autoDestroy !== false && this.autoDestroy)
				c.destroy();
			if (hasLayout)
				l.afterRemove(c)
		},
		removeAll : function (autoDestroy) {
			this.initItems();
			var item;
			var rem = [];
			var items = [];
			this.items.each(function (i) {
				rem.push(i)
			});
			var i$$0 =
				0;
			for (var len = rem.length; i$$0 < len; ++i$$0) {
				item = rem[i$$0];
				this.remove(item, autoDestroy);
				if (item.ownerCt !== this)
					items.push(item)
			}
			return items
		},
		getComponent : function (comp) {
			if (Ext.isObject(comp))
				comp = comp.getItemId();
			return this.items.get(comp)
		},
		lookupComponent : function (comp) {
			if (Ext.isString(comp))
				return Ext.ComponentMgr.get(comp);
			else if (!comp.events)
				return this.createComponent(comp);
			return comp
		},
		createComponent : function (config, defaultType) {
			if (config.render)
				return config;
			var c = Ext.create(Ext.apply({
						ownerCt : this
					},
						config), defaultType || this.defaultType);
			delete c.initialConfig.ownerCt;
			delete c.ownerCt;
			return c
		},
		canLayout : function () {
			var el = this.getVisibilityEl();
			return el && el.dom && !el.isStyle("display", "none")
		},
		doLayout : function (shallow, force) {
			var rendered = this.rendered;
			var forceLayout = force || this.forceLayout;
			if (this.collapsed || !this.canLayout()) {
				this.deferLayout = this.deferLayout || !shallow;
				if (!forceLayout)
					return;
				shallow = shallow && !this.deferLayout
			} else
				delete this.deferLayout;
			if (rendered && this.layout)
				this.layout.layout();
			if (shallow !== true && this.items) {
				var cs = this.items.items;
				var i = 0;
				for (var len = cs.length; i < len; i++) {
					var c = cs[i];
					if (c.doLayout)
						c.doLayout(false, forceLayout)
				}
			}
			if (rendered)
				this.onLayout(shallow, forceLayout);
			this.hasLayout = true;
			delete this.forceLayout
		},
		onLayout : Ext.emptyFn,
		shouldBufferLayout : function () {
			var hl = this.hasLayout;
			if (this.ownerCt)
				return hl ? !this.hasLayoutPending() : false;
			return hl
		},
		hasLayoutPending : function () {
			var pending = false;
			this.ownerCt.bubble(function (c) {
				if (c.layoutPending) {
					pending = true;
					return false
				}
			});
			return pending
		},
		onShow : function () {
			Ext.Container.superclass.onShow.call(this);
			if (Ext.isDefined(this.deferLayout)) {
				delete this.deferLayout;
				this.doLayout(true)
			}
		},
		getLayout : function () {
			if (!this.layout) {
				var layout = new Ext.layout.AutoLayout(this.layoutConfig);
				this.setLayout(layout)
			}
			return this.layout
		},
		beforeDestroy : function () {
			var c;
			if (this.items)
				for (; c = this.items.first(); )
					this.doRemove(c, true);
			if (this.monitorResize)
				Ext.EventManager.removeResizeListener(this.doLayout, this);
			Ext.destroy(this.layout);
			Ext.Container.superclass.beforeDestroy.call(this)
		},
		cascade : function (fn, scope, args) {
			if (fn.apply(scope || this, args || [this]) !== false)
				if (this.items) {
					var cs = this.items.items;
					var i = 0;
					for (var 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]])
				}
			return this
		},
		findById : function (id) {
			var m = null;
			var ct = this;
			this.cascade(function (c) {
				if (ct != c && c.id === id) {
					m = c;
					return false
				}
			});
			return m
		},
		findByType : function (xtype, shallow) {
			return this.findBy(function (c) {
				return c.isXType(xtype, shallow)
			})
		},
		find : function (prop, value) {
			return this.findBy(function (c) {
				return c[prop] ===
				value
			})
		},
		findBy : function (fn, scope) {
			var m = [];
			var ct = this;
			this.cascade(function (c) {
				if (ct != c && fn.call(scope || c, c, ct) === true)
					m.push(c)
			});
			return m
		},
		get : function (key) {
			return this.getComponent(key)
		}
	});
Ext.Container.LAYOUTS = {};
Ext.reg("container", Ext.Container);
Ext.layout.ContainerLayout = Ext.extend(Object, {
		monitorResize : false,
		activeItem : null,
		constructor : function (config) {
			this.id = Ext.id(null, "ext-layout-");
			Ext.apply(this, config)
		},
		type : "container",
		IEMeasureHack : function (target, viewFlag) {
			var tChildren = target.dom.childNodes;
			var tLen = tChildren.length;
			var c;
			var d = [];
			var e;
			var i;
			var ret;
			for (i = 0; i < tLen; i++) {
				c = tChildren[i];
				e = Ext.get(c);
				if (e) {
					d[i] = e.getStyle("display");
					e.setStyle({
						display : "none"
					})
				}
			}
			ret = target ? target.getViewSize(viewFlag) : {};
			for (i = 0; i < tLen; i++) {
				c = tChildren[i];
				e = Ext.get(c);
				if (e)
					e.setStyle({
						display : d[i]
					})
			}
			return ret
		},
		getLayoutTargetSize : Ext.EmptyFn,
		layout : function () {
			var ct = this.container;
			var target = ct.getLayoutTarget();
			if (!(this.hasLayout || Ext.isEmpty(this.targetCls)))
				target.addClass(this.targetCls);
			this.onLayout(ct, target);
			ct.fireEvent("afterlayout", ct, this)
		},
		onLayout : function (ct, target) {
			this.renderAll(ct, target)
		},
		isValidParent : function (c, target) {
			return target && c.getPositionEl().dom.parentNode == (target.dom || target)
		},
		renderAll : function (ct, target) {
			var items =
				ct.items.items;
			var i;
			var c;
			var len = items.length;
			for (i = 0; i < len; i++) {
				c = items[i];
				if (c && (!c.rendered || !this.isValidParent(c, target)))
					this.renderItem(c, i, target)
			}
		},
		renderItem : function (c, position, target) {
			if (c)
				if (!c.rendered) {
					c.render(target, position);
					this.configureItem(c)
				} else if (!this.isValidParent(c, target)) {
					if (Ext.isNumber(position))
						position = target.dom.childNodes[position];
					target.dom.insertBefore(c.getPositionEl().dom, position || null);
					c.container = target;
					this.configureItem(c)
				}
		},
		getRenderedItems : function (ct) {
			var t =
				ct.getLayoutTarget();
			var cti = ct.items.items;
			var len = cti.length;
			var i;
			var c;
			var items = [];
			for (i = 0; i < len; i++)
				if ((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false)
					items.push(c);
			return items
		},
		configureItem : function (c) {
			if (this.extraCls) {
				var t = c.getPositionEl ? c.getPositionEl() : c;
				t.addClass(this.extraCls)
			}
			if (c.doLayout && this.forceLayout)
				c.doLayout();
			if (this.renderHidden && c != this.activeItem)
				c.hide()
		},
		onRemove : function (c) {
			if (this.activeItem == c)
				delete this.activeItem;
			if (c.rendered && this.extraCls) {
				var t =
					c.getPositionEl ? c.getPositionEl() : c;
				t.removeClass(this.extraCls)
			}
		},
		afterRemove : function (c) {
			if (c.removeRestore) {
				c.removeMode = "container";
				delete c.removeRestore
			}
		},
		onResize : function () {
			var ct = this.container;
			var b;
			if (ct.collapsed)
				return;
			if (b = ct.bufferResize && ct.shouldBufferLayout()) {
				if (!this.resizeTask) {
					this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
					this.resizeBuffer = Ext.isNumber(b) ? b : 50
				}
				ct.layoutPending = true;
				this.resizeTask.delay(this.resizeBuffer)
			} else
				this.runLayout()
		},
		runLayout : function () {
			var ct =
				this.container;
			this.layout();
			ct.onLayout();
			delete ct.layoutPending
		},
		setContainer : function (ct) {
			if (this.monitorResize && ct != this.container) {
				var old = this.container;
				if (old)
					old.un(old.resizeEvent, this.onResize, this);
				if (ct)
					ct.on(ct.resizeEvent, this.onResize, this)
			}
			this.container = ct
		},
		parseMargins : function (v) {
			if (Ext.isNumber(v))
				v = v.toString();
			var ms = v.split(" ");
			var len = ms.length;
			if (len == 1)
				ms[1] = ms[2] = ms[3] = ms[0];
			else if (len == 2) {
				ms[2] = ms[0];
				ms[3] = ms[1]
			} else if (len == 3)
				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
			}
		},
		fieldTpl : function () {
			var t = new Ext.Template('\x3cdiv class\x3d"x-form-item {itemCls}" tabIndex\x3d"-1"\x3e', '\x3clabel for\x3d"{id}" style\x3d"{labelStyle}" class\x3d"x-form-item-label"\x3e{label}{labelSeparator}\x3c/label\x3e', '\x3cdiv class\x3d"x-form-element" id\x3d"x-form-el-{id}" style\x3d"{elementStyle}"\x3e', '\x3c/div\x3e\x3cdiv class\x3d"{clearCls}"\x3e\x3c/div\x3e', "\x3c/div\x3e");
			t.disableFormats = true;
			return t.compile()
		}
		(),
		destroy : function () {
			if (this.resizeTask && this.resizeTask.cancel)
				this.resizeTask.cancel();
			if (this.container)
				this.container.un(this.container.resizeEvent, this.onResize, this);
			if (!Ext.isEmpty(this.targetCls)) {
				var target = this.container.getLayoutTarget();
				if (target)
					target.removeClass(this.targetCls)
			}
		}
	});
Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
		type : "auto",
		monitorResize : true,
		onLayout : function (ct, target) {
			Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
			var cs = this.getRenderedItems(ct);
			var len = cs.length;
			var i;
			var c;
			for (i = 0; i < len; i++) {
				c = cs[i];
				if (c.doLayout)
					c.doLayout(true)
			}
		}
	});
Ext.Container.LAYOUTS["auto"] = Ext.layout.AutoLayout;
Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
		monitorResize : true,
		type : "fit",
		getLayoutTargetSize : function () {
			var target = this.container.getLayoutTarget();
			if (!target)
				return {};
			return target.getStyleSize()
		},
		onLayout : function (ct, target) {
			Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
			if (!ct.collapsed)
				this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize())
		},
		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,
		layoutOnCardChange : false,
		renderHidden : true,
		type : "card",
		setActiveItem : function (item) {
			var ai = this.activeItem;
			var ct = this.container;
			item = ct.getComponent(item);
			if (item && ai != item) {
				if (ai) {
					ai.hide();
					if (ai.hidden !== true)
						return false;
					ai.fireEvent("deactivate", ai)
				}
				var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
				this.activeItem = item;
				delete item.deferLayout;
				item.show();
				this.layout();
				if (layout)
					item.doLayout();
				item.fireEvent("activate",
					item)
			}
		},
		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,
		type : "anchor",
		defaultAnchor : "100%",
		parseAnchorRE : /^(r|right|b|bottom)$/i,
		getLayoutTargetSize : function () {
			var target = this.container.getLayoutTarget();
			var ret = {};
			if (target) {
				ret = target.getViewSize();
				if (Ext.isIE && Ext.isStrict && ret.width == 0)
					ret = target.getStyleSize();
				ret.width -= target.getPadding("lr");
				ret.height -= target.getPadding("tb")
			}
			return ret
		},
		onLayout : function (container, target) {
			Ext.layout.AnchorLayout.superclass.onLayout.call(this,
				container, target);
			var size = this.getLayoutTargetSize();
			var containerWidth = size.width;
			var containerHeight = size.height;
			var overflow = target.getStyle("overflow");
			var components = this.getRenderedItems(container);
			var len = components.length;
			var boxes = [];
			var box;
			var anchorWidth;
			var anchorHeight;
			var component;
			var anchorSpec;
			var calcWidth;
			var calcHeight;
			var anchorsArray;
			var totalHeight = 0;
			var i;
			var el;
			if (containerWidth < 20 && containerHeight < 20)
				return;
			if (container.anchorSize)
				if (typeof container.anchorSize == "number")
					anchorWidth =
						container.anchorSize;
				else {
					anchorWidth = container.anchorSize.width;
					anchorHeight = container.anchorSize.height
				}
			else {
				anchorWidth = container.initialConfig.width;
				anchorHeight = container.initialConfig.height
			}
			for (i = 0; i < len; i++) {
				component = components[i];
				el = component.getPositionEl();
				if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict))
					component.anchor = this.defaultAnchor;
				if (component.anchor) {
					anchorSpec = component.anchorSpec;
					if (!anchorSpec) {
						anchorsArray = component.anchor.split(" ");
						component.anchorSpec = anchorSpec = {
							right : this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
							bottom : this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
						}
					}
					calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins("lr"), component) : undefined;
					calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins("tb"), component) : undefined;
					if (calcWidth || calcHeight)
						boxes.push({
							component : component,
							width : calcWidth || undefined,
							height : calcHeight || undefined
						})
				}
			}
			for (i = 0, len = boxes.length; i < len; i++) {
				box = boxes[i];
				box.component.setSize(box.width, box.height)
			}
			if (overflow && overflow != "hidden" && !this.adjustmentPass) {
				var newTargetSize = this.getLayoutTargetSize();
				if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
					this.adjustmentPass = true;
					this.onLayout(container, target)
				}
			}
			delete this.adjustmentPass
		},
		parseAnchor : function (a, start, cstart) {
			if (a && a != "none") {
				var last;
				if (this.parseAnchorRE.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("%", "")) * 0.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,
		type : "column",
		extraCls : "x-column",
		scrollOffset : 0,
		targetCls : "x-column-layout-ct",
		isValidParent : function (c, target) {
			return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom
		},
		getLayoutTargetSize : function () {
			var target = this.container.getLayoutTarget();
			var ret;
			if (target) {
				ret = target.getViewSize();
				if (Ext.isIE && Ext.isStrict && ret.width == 0)
					ret = target.getStyleSize();
				ret.width -= target.getPadding("lr");
				ret.height -= target.getPadding("tb")
			}
			return ret
		},
		renderAll : function (ct, target) {
			if (!this.innerCt) {
				this.innerCt = target.createChild({
						cls : "x-column-inner"
					});
				this.innerCt.createChild({
					cls : "x-clear"
				})
			}
			Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt)
		},
		onLayout : function (ct, target) {
			var cs = ct.items.items;
			var len = cs.length;
			var c;
			var i;
			var m;
			var margins = [];
			this.renderAll(ct, target);
			var size = this.getLayoutTargetSize();
			if (size.width < 1 && size.height < 1)
				return;
			var w = size.width - this.scrollOffset;
			var h = size.height;
			var pw = w;
			this.innerCt.setWidth(w);
			for (i = 0; i < len; i++) {
				c = cs[i];
				m = c.getPositionEl().getMargins("lr");
				margins[i] = m;
				if (!c.columnWidth)
					pw -= c.getWidth() + m
			}
			pw = pw < 0 ? 0 : pw;
			for (i = 0; i < len; i++) {
				c = cs[i];
				m = margins[i];
				if (c.columnWidth)
					c.setSize(Math.floor(c.columnWidth * pw) - m)
			}
			if (Ext.isIE)
				if (i = target.getStyle("overflow") && i != "hidden" && !this.adjustmentPass) {
					var ts = this.getLayoutTargetSize();
					if (ts.width != size.width) {
						this.adjustmentPass = true;
						this.onLayout(ct, target)
					}
				}
			delete this.adjustmentPass
		}
	});
Ext.Container.LAYOUTS["column"] = Ext.layout.ColumnLayout;
Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
		monitorResize : true,
		rendered : false,
		type : "border",
		targetCls : "x-border-layout-ct",
		getLayoutTargetSize : function () {
			var target = this.container.getLayoutTarget();
			return target ? target.getViewSize() : {}

		},
		onLayout : function (ct, target) {
			var collapsed;
			var i;
			var c;
			var pos;
			var items = ct.items.items;
			var len = items.length;
			if (!this.rendered) {
				collapsed = [];
				for (i = 0; i < len; i++) {
					c = items[i];
					pos = c.region;
					if (c.collapsed)
						collapsed.push(c);
					c.collapsed = false;
					if (!c.rendered) {
						c.render(target,
							i);
						c.getPositionEl().addClass("x-border-panel")
					}
					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 = this.getLayoutTargetSize();
			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;
			var h = size.height;
			var centerW = w;
			var centerH = h;
			var centerY = 0;
			var centerX = 0;
			var n = this.north;
			var s = this.south;
			var west = this.west;
			var e = this.east;
			c = this.center;
			var b;
			var m;
			var totalWidth;
			var totalHeight;
			if (!c && Ext.layout.BorderLayout.WARN !== false)
				throw "No center region defined in BorderLayout " + ct.id;
			if (n && n.isVisible()) {
				b = n.getSize();
				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()) {
				b = s.getSize();
				m = s.getMargins();
				b.width =
					w - (m.left + m.right);
				b.x = m.left;
				totalHeight = b.height + m.top + m.bottom;
				b.y = h - totalHeight + m.top;
				centerH -= totalHeight;
				s.applyLayout(b)
			}
			if (west && west.isVisible()) {
				b = west.getSize();
				m = west.getMargins();
				b.height = centerH - (m.top + m.bottom);
				b.x = m.left;
				b.y = centerY + m.top;
				totalWidth = b.width + m.left + m.right;
				centerX += totalWidth;
				centerW -= totalWidth;
				west.applyLayout(b)
			}
			if (e && e.isVisible()) {
				b = e.getSize();
				m = e.getMargins();
				b.height = centerH - (m.top + m.bottom);
				totalWidth = b.width + m.left + m.right;
				b.x = w - totalWidth + m.left;
				b.y = centerY +
					m.top;
				centerW -= totalWidth;
				e.applyLayout(b)
			}
			if (c) {
				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 (i = 0, len = collapsed.length; i < len; i++)
					collapsed[i].collapse(false);
			if (Ext.isIE && Ext.isStrict)
				target.repaint();
			if (i = target.getStyle("overflow") && i != "hidden" && !this.adjustmentPass) {
				var ts = this.getLayoutTargetSize();
				if (ts.width != size.width || ts.height != size.height) {
					this.adjustmentPass = true;
					this.onLayout(ct, target)
				}
			}
			delete this.adjustmentPass
		},
		destroy : function () {
			var r = ["north", "south", "east", "west"];
			var i;
			var region;
			for (i = 0; i < r.length; i++) {
				region = this[r[i]];
				if (region)
					if (region.destroy)
						region.destroy();
					else if (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
	},
	floatingZIndex : 100,
	isCollapsed : false,
	render : function (ct, p) {
		this.panel = p;
		p.el.enableDisplayMode();
		this.targetEl = ct;
		this.el = p.el;
		var gs = p.getState;
		var 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 || 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")
			}
		}
	},
	getCollapsedEl : function () {
		if (!this.collapsedEl) {
			if (!this.toolTemplate) {
				var tt =
					new Ext.Template('\x3cdiv class\x3d"x-tool x-tool-{id}"\x3e\x26#160;\x3c/div\x3e');
				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 : "\x26#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) {
					var t = this.expandToolEl = 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.titleCollapse) {
					this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
					this.collapsedEl.on("click", this[this.floatable ? "collapseClick" : "onExpandClick"], this)
				}
			}
		}
		return this.collapsedEl
	},
	onExpandClick : function (e) {
		if (this.isSlid)
			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();
		var el = this.panel.getEl();
		this.originalZIndex =
			el.getStyle("z-index");
		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 : 0.2
			});
		this.state.collapsed = true;
		this.panel.saveState()
	},
	beforeExpand : function (animate) {
		if (this.isSlid)
			this.afterSlideIn();
		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", this.floatingZIndex)
	},
	onExpand : function () {
		this.isCollapsed = false;
		if (this.splitEl)
			this.splitEl.show();
		this.layout.layout();
		this.panel.el.setStyle("z-index", this.originalZIndex);
		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) {
				this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
				this.autoHideHd = {
					"mouseout" : function (e) {
						if (!e.within(this.el, true))
							this.autoHideSlideTask.delay(500)
					},
					"mouseover" : function (e) {
						this.autoHideSlideTask.cancel()
					},
					scope : this
				}
			}
			this.el.on(this.autoHideHd);
			this.collapsedEl.on(this.autoHideHd)
		}
	},
	clearAutoHide : function () {
		if (this.autoHide !== false) {
			this.el.un("mouseout", this.autoHideHd.mouseout);
			this.el.un("mouseover", this.autoHideHd.mouseover);
			this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
			this.collapsedEl.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;
		var dh;
		var pc;
		if (ts && ts.toggle)
			ts.toggle.hide();
		this.el.show();
		pc = this.panel.collapsed;
		this.panel.collapsed = false;
		if (this.position == "east" || this.position == "west") {
			dh = this.panel.deferHeight;
			this.panel.deferHeight =
				false;
			this.panel.setSize(undefined, this.collapsedEl.getHeight());
			this.panel.deferHeight = dh
		} else
			this.panel.setSize(this.collapsedEl.getWidth(), undefined);
		this.panel.collapsed = pc;
		this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
		this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
		this.el.setStyle("z-index", this.floatingZIndex + 2);
		this.panel.el.replaceClass("x-panel-collapsed", "x-panel-floating");
		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.panel.el.replaceClass("x-panel-floating", "x-panel-collapsed");
		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;
		var 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
		}
	},
	destroy : function () {
		if (this.autoHideSlideTask && this.autoHideSlideTask.cancel)
			this.autoHideSlideTask.cancel();
		Ext.destroyMembers(this, "miniCollapsedEl", "collapsedEl", "expandToolEl")
	}
};
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;
			var 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;
			var 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;
			var 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;
			var 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 : "\x26#160;",
				id : this.panel.id + "-xsplit"
			});
		if (this.collapseMode == "mini") {
			this.miniSplitEl = this.splitEl.createChild({
					cls : "x-layout-mini x-layout-mini-" + ps,
					html : "\x26#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.tickSize = this.tickSize;
		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 || 1E4;
		var center = this.layout.center;
		return Math.min(cmax, this.el.getWidth() + center.el.getWidth() - center.getMinWidth())
	},
	getVMaxSize : function () {
		var cmax = this.maxSize || 1E4;
		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
	},
	destroy : function () {
		Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
		Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this)
	}
});
Ext.Container.LAYOUTS["border"] = Ext.layout.BorderLayout;
Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
		labelSeparator : ":",
		trackLabels : true,
		type : "form",
		onRemove : function (c) {
			Ext.layout.FormLayout.superclass.onRemove.call(this, c);
			if (this.trackLabels) {
				c.un("show", this.onFieldShow, this);
				c.un("hide", this.onFieldHide, this)
			}
			var el = c.getPositionEl();
			var ct = c.getItemCt && c.getItemCt();
			if (c.rendered && ct) {
				if (el && el.dom)
					el.insertAfter(ct);
				Ext.destroy(ct);
				Ext.destroyMembers(c, "label", "itemCt");
				if (c.customItemCt)
					Ext.destroyMembers(c, "getItemCt", "customItemCt")
			}
		},
		setContainer : function (ct) {
			Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
			if (ct.labelAlign)
				ct.addClass("x-form-label-" + ct.labelAlign);
			if (ct.hideLabels)
				Ext.apply(this, {
					labelStyle : "display:none",
					elementStyle : "padding-left:0;",
					labelAdjust : 0
				});
			else {
				this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
				ct.labelWidth = ct.labelWidth || 100;
				if (Ext.isNumber(ct.labelWidth)) {
					var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
					Ext.apply(this, {
						labelAdjust : ct.labelWidth +
						pad,
						labelStyle : "width:" + ct.labelWidth + "px;",
						elementStyle : "padding-left:" + (ct.labelWidth + pad) + "px"
					})
				}
				if (ct.labelAlign == "top")
					Ext.apply(this, {
						labelStyle : "width:auto;",
						labelAdjust : 0,
						elementStyle : "padding-left:0;"
					})
			}
		},
		isHide : function (c) {
			return c.hideLabel || this.container.hideLabels
		},
		onFieldShow : function (c) {
			c.getItemCt().removeClass("x-hide-" + c.hideMode);
			if (c.isComposite)
				c.doLayout()
		},
		onFieldHide : function (c) {
			c.getItemCt().addClass("x-hide-" + c.hideMode)
		},
		getLabelStyle : function (s) {
			var ls = "";
			var items = [this.labelStyle,
				s];
			var i = 0;
			for (var len = items.length; i < len; ++i)
				if (items[i]) {
					ls += items[i];
					if (ls.substr(-1, 1) != ";")
						ls += ";"
				}
			return ls
		},
		renderItem : function (c, position, target) {
			if (c && (c.isFormField || c.fieldLabel) && c.inputType != "hidden") {
				var args = this.getTemplateArgs(c);
				if (Ext.isNumber(position))
					position = target.dom.childNodes[position] || null;
				if (position)
					c.itemCt = this.fieldTpl.insertBefore(position, args, true);
				else
					c.itemCt = this.fieldTpl.append(target, args, true);
				if (!c.getItemCt)
					Ext.apply(c, {
						getItemCt : function () {
							return c.itemCt
						},
						customItemCt : true
					});
				c.label = c.getItemCt().child("label.x-form-item-label");
				if (!c.rendered)
					c.render("x-form-el-" + c.id);
				else if (!this.isValidParent(c, target))
					Ext.fly("x-form-el-" + c.id).appendChild(c.getPositionEl());
				if (this.trackLabels) {
					if (c.hidden)
						this.onFieldHide(c);
					c.on({
						scope : this,
						show : this.onFieldShow,
						hide : this.onFieldHide
					})
				}
				this.configureItem(c)
			} else
				Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments)
		},
		getTemplateArgs : function (field) {
			var noLabelSep = !field.fieldLabel || field.hideLabel;
			var itemCls = (field.itemCls || this.container.itemCls || "") + (field.hideLabel ? " x-hide-label" : "");
			if (Ext.isIE9 && Ext.isIEQuirks && field instanceof Ext.form.TextField)
				itemCls += " x-input-wrapper";
			return {
				id : field.id,
				label : field.fieldLabel,
				itemCls : itemCls,
				clearCls : field.clearCls || "x-form-clear-left",
				labelStyle : this.getLabelStyle(field.labelStyle),
				elementStyle : this.elementStyle || "",
				labelSeparator : noLabelSep ? "" : Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator
			}
		},
		adjustWidthAnchor : function (value,
			c) {
			if (c.label && !this.isHide(c) && this.container.labelAlign != "top") {
				var adjust = Ext.isIE6 || Ext.isIE && !Ext.isStrict;
				return value - this.labelAdjust + (adjust ? -3 : 0)
			}
			return value
		},
		adjustHeightAnchor : function (value, c) {
			if (c.label && !this.isHide(c) && this.container.labelAlign == "top")
				return value - c.label.getHeight();
			return value
		},
		isValidParent : function (c, target) {
			return target && this.container.getEl().contains(c.getPositionEl())
		}
	});
Ext.Container.LAYOUTS["form"] = Ext.layout.FormLayout;
Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
		fill : true,
		autoWidth : true,
		titleCollapse : true,
		hideCollapseTool : false,
		collapseFirst : false,
		animate : false,
		sequence : false,
		activeOnTop : false,
		type : "accordion",
		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.setActiveItem(c, true);
			else if (this.activeItem && this.activeItem != c)
				c.collapsed = true;
			Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
			c.header.addClass("x-accordion-hd");
			c.on("beforeexpand", this.beforeExpand, this)
		},
		onRemove : function (c) {
			Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
			if (c.rendered)
				c.header.removeClass("x-accordion-hd");
			c.un("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.setActive(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 hh = 0;
				var i;
				var ct = this.getRenderedItems(this.container);
				var len = ct.length;
				var p;
				for (i = 0; i < len; i++)
					if ((p = ct[i]) != item && !p.hidden)
						hh += p.header.getHeight();
				size.height -= hh;
				item.setSize(size)
			}
		},
		setActiveItem : function (item) {
			this.setActive(item, true)
		},
		setActive : function (item, expand) {
			var ai = this.activeItem;
			item = this.container.getComponent(item);
			if (ai != item)
				if (item.rendered && item.collapsed && expand)
					item.expand();
				else {
					if (ai)
						ai.fireEvent("deactivate", ai);
					this.activeItem = item;
					item.fireEvent("activate", item)
				}
		}
	});
Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
Ext.layout.Accordion = Ext.layout.AccordionLayout;
Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
		monitorResize : false,
		type : "table",
		targetCls : "x-table-layout-ct",
		tableAttrs : null,
		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;
			var len = cs.length;
			var c;
			var i;
			if (!this.table) {
				target.addClass("x-table-layout-ct");
				this.table = target.createChild(Ext.apply({
							tag : "table",
							cls : "x-table-layout",
							cellspacing : 0,
							cn : {
								tag : "tbody"
							}
						}, this.tableAttrs), 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];
			var 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) {
			for (var cols = this.columns; 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 (!this.table)
				this.table = target.createChild(Ext.apply({
							tag : "table",
							cls : "x-table-layout",
							cellspacing : 0,
							cn : {
								tag : "tbody"
							}
						}, this.tableAttrs), null, true);
			if (c && !c.rendered) {
				c.render(this.getNextCell(c));
				this.configureItem(c)
			} else if (c && !this.isValidParent(c, target)) {
				var container = this.getNextCell(c);
				container.insertBefore(c.getPositionEl().dom, null);
				c.container = Ext.get(container);
				this.configureItem(c)
			}
		},
		isValidParent : function (c, target) {
			return c.getPositionEl().up("table", 5).dom.parentNode === (target.dom || target)
		},
		destroy : function () {
			delete this.table;
			Ext.layout.TableLayout.superclass.destroy.call(this)
		}
	});
Ext.Container.LAYOUTS["table"] = Ext.layout.TableLayout;
Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
		extraCls : "x-abs-layout-item",
		type : "absolute",
		onLayout : function (ct, target) {
			target.position();
			this.paddingLeft = target.getPadding("l");
			this.paddingTop = target.getPadding("t");
			Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target)
		},
		adjustWidthAnchor : function (value, comp) {
			return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value
		},
		adjustHeightAnchor : function (value, comp) {
			return value ? value - comp.getPosition(true)[1] + this.paddingTop :
			value
		}
	});
Ext.Container.LAYOUTS["absolute"] = Ext.layout.AbsoluteLayout;
Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
		defaultMargins : {
			left : 0,
			top : 0,
			right : 0,
			bottom : 0
		},
		padding : "0",
		pack : "start",
		monitorResize : true,
		type : "box",
		scrollOffset : 0,
		extraCls : "x-box-item",
		targetCls : "x-box-layout-ct",
		innerCls : "x-box-inner",
		constructor : function (config) {
			Ext.layout.BoxLayout.superclass.constructor.call(this, config);
			if (Ext.isString(this.defaultMargins))
				this.defaultMargins = this.parseMargins(this.defaultMargins);
			var handler = this.overflowHandler;
			if (typeof handler == "string")
				handler = {
					type : handler
				};
			var handlerType = "none";
			if (handler && handler.type != undefined)
				handlerType = handler.type;
			var constructor = Ext.layout.boxOverflow[handlerType];
			if (constructor[this.type])
				constructor = constructor[this.type];
			this.overflowHandler = new constructor(this, handler)
		},
		onLayout : function (container, target) {
			Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
			var tSize = this.getLayoutTargetSize();
			var items = this.getVisibleItems(container);
			var calcs = this.calculateChildBoxes(items, tSize);
			var boxes =
				calcs.boxes;
			var meta = calcs.meta;
			if (tSize.width > 0) {
				var handler = this.overflowHandler;
				var method = meta.tooNarrow ? "handleOverflow" : "clearOverflow";
				var results = handler[method](calcs, tSize);
				if (results) {
					if (results.targetSize)
						tSize = results.targetSize;
					if (results.recalculate) {
						items = this.getVisibleItems(container);
						calcs = this.calculateChildBoxes(items, tSize);
						boxes = calcs.boxes
					}
				}
			}
			this.layoutTargetLastSize = tSize;
			this.childBoxCache = calcs;
			this.updateInnerCtSize(tSize, calcs);
			this.updateChildBoxes(boxes);
			this.handleTargetOverflow(tSize,
				container, target)
		},
		updateChildBoxes : function (boxes) {
			var i = 0;
			for (var length = boxes.length; i < length; i++) {
				var box = boxes[i];
				var comp = box.component;
				if (box.dirtySize)
					comp.setSize(box.width, box.height);
				if (isNaN(box.left) || isNaN(box.top))
					continue;
				comp.setPosition(box.left, box.top)
			}
		},
		updateInnerCtSize : function (tSize, calcs) {
			var align = this.align;
			var padding = this.padding;
			var width = tSize.width;
			var height = tSize.height;
			if (this.type == "hbox") {
				var innerCtWidth = width;
				var innerCtHeight = calcs.meta.maxHeight + padding.top +
					padding.bottom;
				if (align == "stretch")
					innerCtHeight = height;
				else if (align == "middle")
					innerCtHeight = Math.max(height, innerCtHeight)
			} else {
				innerCtHeight = height;
				innerCtWidth = calcs.meta.maxWidth + padding.left + padding.right;
				if (align == "stretch")
					innerCtWidth = width;
				else if (align == "center")
					innerCtWidth = Math.max(width, innerCtWidth)
			}
			this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined)
		},
		handleTargetOverflow : function (previousTargetSize, container, target) {
			var overflow = target.getStyle("overflow");
			if (overflow &&
				overflow != "hidden" && !this.adjustmentPass) {
				var newTargetSize = this.getLayoutTargetSize();
				if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
					this.adjustmentPass = true;
					this.onLayout(container, target)
				}
			}
			delete this.adjustmentPass
		},
		isValidParent : function (c, target) {
			return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom
		},
		getVisibleItems : function (ct) {
			ct = ct || this.container;
			var t = ct.getLayoutTarget();
			var cti = ct.items.items;
			var len = cti.length;
			var i;
			var c;
			var items = [];
			for (i = 0; i < len; i++)
				if ((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true && c.collapsed !== true && c.shouldLayout !== false)
					items.push(c);
			return items
		},
		renderAll : function (ct, target) {
			if (!this.innerCt) {
				this.innerCt = target.createChild({
						cls : this.innerCls
					});
				this.padding = this.parseMargins(this.padding)
			}
			Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt)
		},
		getLayoutTargetSize : function () {
			var target = this.container.getLayoutTarget();
			var ret;
			if (target) {
				ret = target.getViewSize();
				if (Ext.isIE && Ext.isStrict && ret.width == 0)
					ret = target.getStyleSize();
				ret.width -= target.getPadding("lr");
				ret.height -= target.getPadding("tb")
			}
			return ret
		},
		renderItem : function (c) {
			if (Ext.isString(c.margins))
				c.margins = this.parseMargins(c.margins);
			else if (!c.margins)
				c.margins = this.defaultMargins;
			Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments)
		},
		destroy : function () {
			Ext.destroy(this.overflowHandler);
			Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments)
		}
	});
Ext.layout.boxOverflow.None = Ext.extend(Object, {
		constructor : function (layout, config) {
			this.layout = layout;
			Ext.apply(this, config || {})
		},
		handleOverflow : Ext.emptyFn,
		clearOverflow : Ext.emptyFn
	});
Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
		afterCls : "x-strip-right",
		noItemsMenuText : '\x3cdiv class\x3d"x-toolbar-no-items"\x3e(None)\x3c/div\x3e',
		constructor : function (layout) {
			Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
			this.menuItems = []
		},
		createInnerElements : function () {
			if (!this.afterCt)
				this.afterCt = this.layout.innerCt.insertSibling({
						cls : this.afterCls
					}, "before")
		},
		clearOverflow : function (calculations, targetSize) {
			var newWidth = targetSize.width + (this.afterCt ?
					this.afterCt.getWidth() : 0);
			var items = this.menuItems;
			this.hideTrigger();
			var index = 0;
			for (var length = items.length; index < length; index++)
				items.pop().component.show();
			return {
				targetSize : {
					height : targetSize.height,
					width : newWidth
				}
			}
		},
		showTrigger : function () {
			this.createMenu();
			this.menuTrigger.show()
		},
		hideTrigger : function () {
			if (this.menuTrigger != undefined)
				this.menuTrigger.hide()
		},
		beforeMenuShow : function (menu) {
			var items = this.menuItems;
			var len = items.length;
			var item$$0;
			var prev;
			var needsSep = function (group, item) {
				return group.isXType("buttongroup") &&
				!(item instanceof Ext.Toolbar.Separator)
			};
			this.clearMenu();
			menu.removeAll();
			for (var i = 0; i < len; i++) {
				item$$0 = items[i].component;
				if (prev && (needsSep(item$$0, prev) || needsSep(prev, item$$0)))
					menu.add("-");
				this.addComponentToMenu(menu, item$$0);
				prev = item$$0
			}
			if (menu.items.length < 1)
				menu.add(this.noItemsMenuText)
		},
		createMenuConfig : function (component, hideOnClick) {
			var config = Ext.apply({}, component.initialConfig);
			var group = component.toggleGroup;
			Ext.copyTo(config, component, ["iconCls", "icon", "itemId", "disabled", "handler",
					"scope", "menu"]);
			Ext.apply(config, {
				text : component.overflowText || component.text,
				hideOnClick : hideOnClick
			});
			if (group || component.enableToggle)
				Ext.apply(config, {
					group : group,
					checked : component.pressed,
					listeners : {
						checkchange : function (item, checked) {
							component.toggle(checked)
						}
					}
				});
			delete config.ownerCt;
			delete config.xtype;
			delete config.id;
			return config
		},
		addComponentToMenu : function (menu, component) {
			if (component instanceof Ext.Toolbar.Separator)
				menu.add("-");
			else if (Ext.isFunction(component.isXType))
				if (component.isXType("splitbutton"))
					menu.add(this.createMenuConfig(component,
							true));
				else if (component.isXType("button"))
					menu.add(this.createMenuConfig(component, !component.menu));
				else if (component.isXType("buttongroup"))
					component.items.each(function (item) {
						this.addComponentToMenu(menu, item)
					}, this)
		},
		clearMenu : function () {
			var menu = this.moreMenu;
			if (menu && menu.items)
				menu.items.each(function (item) {
					delete item.menu
				})
		},
		createMenu : function () {
			if (!this.menuTrigger) {
				this.createInnerElements();
				this.menu = new Ext.menu.Menu({
						ownerCt : this.layout.container,
						listeners : {
							scope : this,
							beforeshow : this.beforeMenuShow
						}
					});
				this.menuTrigger = new Ext.Button({
						iconCls : "x-toolbar-more-icon",
						cls : "x-toolbar-more",
						menu : this.menu,
						renderTo : this.afterCt
					})
			}
		},
		destroy : function () {
			Ext.destroy(this.menu, this.menuTrigger)
		}
	});
Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
		constructor : function () {
			Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
			var me = this;
			var layout = me.layout;
			var origFunction = layout.calculateChildBoxes;
			layout.calculateChildBoxes = function (visibleItems, targetSize) {
				var calcs = origFunction.apply(layout, arguments);
				var meta = calcs.meta;
				var items = me.menuItems;
				var hiddenWidth = 0;
				var index = 0;
				for (var length = items.length; index < length; index++)
					hiddenWidth +=
					items[index].width;
				meta.minimumWidth += hiddenWidth;
				meta.tooNarrow = meta.minimumWidth > targetSize.width;
				return calcs
			}
		},
		handleOverflow : function (calculations, targetSize) {
			this.showTrigger();
			var newWidth = targetSize.width - this.afterCt.getWidth();
			var boxes = calculations.boxes;
			var usedWidth = 0;
			var recalculate = false;
			var index = 0;
			for (var length = boxes.length; index < length; index++)
				usedWidth += boxes[index].width;
			var spareWidth = newWidth - usedWidth;
			var showCount = 0;
			index = 0;
			for (length = this.menuItems.length; index < length; index++) {
				var hidden =
					this.menuItems[index];
				var comp = hidden.component;
				var width = hidden.width;
				if (width < spareWidth) {
					comp.show();
					spareWidth -= width;
					showCount++;
					recalculate = true
				} else
					break
			}
			if (recalculate)
				this.menuItems = this.menuItems.slice(showCount);
			else
				for (var i = boxes.length - 1; i >= 0; i--) {
					var item = boxes[i].component;
					var right = boxes[i].left + boxes[i].width;
					if (right >= newWidth) {
						this.menuItems.unshift({
							component : item,
							width : boxes[i].width
						});
						item.hide()
					} else
						break
				}
			if (this.menuItems.length == 0)
				this.hideTrigger();
			return {
				targetSize : {
					height : targetSize.height,
					width : newWidth
				},
				recalculate : recalculate
			}
		}
	});
Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;
Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
		animateScroll : true,
		scrollIncrement : 100,
		wheelIncrement : 3,
		scrollRepeatInterval : 400,
		scrollDuration : 0.4,
		beforeCls : "x-strip-left",
		afterCls : "x-strip-right",
		scrollerCls : "x-strip-scroller",
		beforeScrollerCls : "x-strip-scroller-left",
		afterScrollerCls : "x-strip-scroller-right",
		createWheelListener : function () {
			this.layout.innerCt.on({
				scope : this,
				mousewheel : function (e) {
					e.stopEvent();
					this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false)
				}
			})
		},
		handleOverflow : function (calculations, targetSize) {
			this.createInnerElements();
			this.showScrollers()
		},
		clearOverflow : function () {
			this.hideScrollers()
		},
		showScrollers : function () {
			this.createScrollers();
			this.beforeScroller.show();
			this.afterScroller.show();
			this.updateScrollButtons()
		},
		hideScrollers : function () {
			if (this.beforeScroller != undefined) {
				this.beforeScroller.hide();
				this.afterScroller.hide()
			}
		},
		createScrollers : function () {
			if (!this.beforeScroller && !this.afterScroller) {
				var before = this.beforeCt.createChild({
						cls : String.format("{0} {1} ",
							this.scrollerCls, this.beforeScrollerCls)
					});
				var after = this.afterCt.createChild({
						cls : String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
					});
				before.addClassOnOver(this.beforeScrollerCls + "-hover");
				after.addClassOnOver(this.afterScrollerCls + "-hover");
				before.setVisibilityMode(Ext.Element.DISPLAY);
				after.setVisibilityMode(Ext.Element.DISPLAY);
				this.beforeRepeater = new Ext.util.ClickRepeater(before, {
						interval : this.scrollRepeatInterval,
						handler : this.scrollLeft,
						scope : this
					});
				this.afterRepeater = new Ext.util.ClickRepeater(after, {
						interval : this.scrollRepeatInterval,
						handler : this.scrollRight,
						scope : this
					});
				this.beforeScroller = before;
				this.afterScroller = after
			}
		},
		destroy : function () {
			Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt)
		},
		scrollBy : function (delta, animate) {
			this.scrollTo(this.getScrollPosition() + delta, animate)
		},
		getItem : function (item) {
			if (Ext.isString(item))
				item = Ext.getCmp(item);
			else if (Ext.isNumber(item))
				item = this.items[item];
			return item
		},
		getScrollAnim : function () {
			return {
				duration : this.scrollDuration,
				callback : this.updateScrollButtons,
				scope : this
			}
		},
		updateScrollButtons : function () {
			if (this.beforeScroller == undefined || this.afterScroller == undefined)
				return;
			var beforeMeth = this.atExtremeBefore() ? "addClass" : "removeClass";
			var afterMeth = this.atExtremeAfter() ? "addClass" : "removeClass";
			var beforeCls = this.beforeScrollerCls + "-disabled";
			var afterCls = this.afterScrollerCls + "-disabled";
			this.beforeScroller[beforeMeth](beforeCls);
			this.afterScroller[afterMeth](afterCls);
			this.scrolling = false
		},
		atExtremeBefore : function () {
			return this.getScrollPosition() ===
			0
		},
		scrollLeft : function (animate) {
			this.scrollBy(-this.scrollIncrement, animate)
		},
		scrollRight : function (animate) {
			this.scrollBy(this.scrollIncrement, animate)
		},
		scrollToItem : function (item, animate) {
			item = this.getItem(item);
			if (item != undefined) {
				var visibility = this.getItemVisibility(item);
				if (!visibility.fullyVisible) {
					var box = item.getBox(true, true);
					var newX = box.x;
					if (visibility.hiddenRight)
						newX -= this.layout.innerCt.getWidth() - box.width;
					this.scrollTo(newX, animate)
				}
			}
		},
		getItemVisibility : function (item) {
			var box = this.getItem(item).getBox(true,
					true);
			var itemLeft = box.x;
			var itemRight = box.x + box.width;
			var scrollLeft = this.getScrollPosition();
			var scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
			return {
				hiddenLeft : itemLeft < scrollLeft,
				hiddenRight : itemRight > scrollRight,
				fullyVisible : itemLeft > scrollLeft && itemRight < scrollRight
			}
		}
	});
Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
		scrollIncrement : 75,
		wheelIncrement : 2,
		handleOverflow : function (calculations, targetSize) {
			Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
			return {
				targetSize : {
					height : targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
					width : targetSize.width
				}
			}
		},
		createInnerElements : function () {
			var target = this.layout.innerCt;
			if (!this.beforeCt) {
				this.beforeCt = target.insertSibling({
						cls : this.beforeCls
					},
						"before");
				this.afterCt = target.insertSibling({
						cls : this.afterCls
					}, "after");
				this.createWheelListener()
			}
		},
		scrollTo : function (position, animate) {
			var oldPosition = this.getScrollPosition();
			var newPosition = position.constrain(0, this.getMaxScrollBottom());
			if (newPosition != oldPosition && !this.scrolling) {
				if (animate == undefined)
					animate = this.animateScroll;
				this.layout.innerCt.scrollTo("top", newPosition, animate ? this.getScrollAnim() : false);
				if (animate)
					this.scrolling = true;
				else {
					this.scrolling = false;
					this.updateScrollButtons()
				}
			}
		},
		getScrollPosition : function () {
			return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0
		},
		getMaxScrollBottom : function () {
			return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight()
		},
		atExtremeAfter : function () {
			return this.getScrollPosition() >= this.getMaxScrollBottom()
		}
	});
Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
		handleOverflow : function (calculations, targetSize) {
			Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
			return {
				targetSize : {
					height : targetSize.height,
					width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
				}
			}
		},
		createInnerElements : function () {
			var target = this.layout.innerCt;
			if (!this.beforeCt) {
				this.afterCt = target.insertSibling({
						cls : this.afterCls
					}, "before");
				this.beforeCt =
					target.insertSibling({
						cls : this.beforeCls
					}, "before");
				this.createWheelListener()
			}
		},
		scrollTo : function (position, animate) {
			var oldPosition = this.getScrollPosition();
			var newPosition = position.constrain(0, this.getMaxScrollRight());
			if (newPosition != oldPosition && !this.scrolling) {
				if (animate == undefined)
					animate = this.animateScroll;
				this.layout.innerCt.scrollTo("left", newPosition, animate ? this.getScrollAnim() : false);
				if (animate)
					this.scrolling = true;
				else {
					this.scrolling = false;
					this.updateScrollButtons()
				}
			}
		},
		getScrollPosition : function () {
			return parseInt(this.layout.innerCt.dom.scrollLeft,
				10) || 0
		},
		getMaxScrollRight : function () {
			return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth()
		},
		atExtremeAfter : function () {
			return this.getScrollPosition() >= this.getMaxScrollRight()
		}
	});
Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;
Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
		align : "top",
		type : "hbox",
		calculateChildBoxes : function (visibleItems, targetSize) {
			var visibleCount = visibleItems.length;
			var padding = this.padding;
			var topOffset = padding.top;
			var leftOffset = padding.left;
			var paddingVert = topOffset + padding.bottom;
			var paddingHoriz = leftOffset + padding.right;
			var width = targetSize.width - this.scrollOffset;
			var height = targetSize.height;
			var availHeight = Math.max(0, height - paddingVert);
			var isStart = this.pack == "start";
			var isCenter = this.pack ==
				"center";
			var isEnd = this.pack == "end";
			var nonFlexWidth = 0;
			var maxHeight = 0;
			var totalFlex = 0;
			var desiredWidth = 0;
			var minimumWidth = 0;
			var boxes = [];
			var child;
			var childWidth;
			var childHeight;
			var childSize;
			var childMargins;
			var canLayout;
			var i;
			var calcs;
			var flexedWidth;
			var horizMargins;
			var vertMargins;
			var stretchHeight;
			for (i = 0; i < visibleCount; i++) {
				child = visibleItems[i];
				childHeight = child.height;
				childWidth = child.width;
				canLayout = !child.hasLayout && typeof child.doLayout == "function";
				if (typeof childWidth != "number")
					if (child.flex &&
						!childWidth)
						totalFlex += child.flex;
					else {
						if (!childWidth && canLayout)
							child.doLayout();
						childSize = child.getSize();
						childWidth = childSize.width;
						childHeight = childSize.height
					}
				childMargins = child.margins;
				horizMargins = childMargins.left + childMargins.right;
				nonFlexWidth += horizMargins + (childWidth || 0);
				desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
				minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
				if (typeof childHeight != "number") {
					if (canLayout)
						child.doLayout();
					childHeight = child.getHeight()
				}
				maxHeight =
					Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
				boxes.push({
					component : child,
					height : childHeight || undefined,
					width : childWidth || undefined
				})
			}
			var shortfall = desiredWidth - width;
			var tooNarrow = minimumWidth > width;
			var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
			if (tooNarrow)
				for (i = 0; i < visibleCount; i++)
					boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
			else if (shortfall > 0) {
				var minWidths = [];
				var index = 0;
				for (var length = visibleCount; index < length; index++) {
					var item =
						visibleItems[index];
					var minWidth = item.minWidth || 0;
					if (item.flex)
						boxes[index].width = minWidth;
					else
						minWidths.push({
							minWidth : minWidth,
							available : boxes[index].width - minWidth,
							index : index
						})
				}
				minWidths.sort(function (a, b) {
					return a.available > b.available ? 1 : -1
				});
				i = 0;
				for (length = minWidths.length; i < length; i++) {
					var itemIndex = minWidths[i].index;
					if (itemIndex == undefined)
						continue;
					item = visibleItems[itemIndex];
					var box = boxes[itemIndex];
					var oldWidth = box.width;
					minWidth = item.minWidth;
					var newWidth = Math.max(minWidth, oldWidth -
							Math.ceil(shortfall / (length - i)));
					var reduction = oldWidth - newWidth;
					boxes[itemIndex].width = newWidth;
					shortfall -= reduction
				}
			} else {
				var remainingWidth = availableWidth;
				var remainingFlex = totalFlex;
				for (i = 0; i < visibleCount; i++) {
					child = visibleItems[i];
					calcs = boxes[i];
					childMargins = child.margins;
					vertMargins = childMargins.top + childMargins.bottom;
					if (isStart && child.flex && !child.width) {
						flexedWidth = Math.ceil(child.flex / remainingFlex * remainingWidth);
						remainingWidth -= flexedWidth;
						remainingFlex -= child.flex;
						calcs.width = flexedWidth;
						calcs.dirtySize = true
					}
				}
			}
			if (isCenter)
				leftOffset += availableWidth / 2;
			else if (isEnd)
				leftOffset += availableWidth;
			for (i = 0; i < visibleCount; i++) {
				child = visibleItems[i];
				calcs = boxes[i];
				childMargins = child.margins;
				leftOffset += childMargins.left;
				vertMargins = childMargins.top + childMargins.bottom;
				calcs.left = leftOffset;
				calcs.top = topOffset + childMargins.top;
				switch (this.align) {
				case "stretch":
					stretchHeight = availHeight - vertMargins;
					calcs.height = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1E6);
					calcs.dirtySize =
						true;
					break;
				case "stretchmax":
					stretchHeight = maxHeight - vertMargins;
					calcs.height = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1E6);
					calcs.dirtySize = true;
					break;
				case "middle":
					var diff = availHeight - calcs.height - vertMargins;
					if (diff > 0)
						calcs.top = topOffset + vertMargins + diff / 2
				}
				leftOffset += calcs.width + childMargins.right
			}
			return {
				boxes : boxes,
				meta : {
					maxHeight : maxHeight,
					nonFlexWidth : nonFlexWidth,
					desiredWidth : desiredWidth,
					minimumWidth : minimumWidth,
					shortfall : desiredWidth - width,
					tooNarrow : tooNarrow
				}
			}
		}
	});
Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
		align : "left",
		type : "vbox",
		calculateChildBoxes : function (visibleItems, targetSize) {
			var visibleCount = visibleItems.length;
			var padding = this.padding;
			var topOffset = padding.top;
			var leftOffset = padding.left;
			var paddingVert = topOffset + padding.bottom;
			var paddingHoriz = leftOffset + padding.right;
			var width = targetSize.width - this.scrollOffset;
			var height = targetSize.height;
			var availWidth = Math.max(0, width - paddingHoriz);
			var isStart = this.pack == "start";
			var isCenter = this.pack ==
				"center";
			var isEnd = this.pack == "end";
			var nonFlexHeight = 0;
			var maxWidth = 0;
			var totalFlex = 0;
			var desiredHeight = 0;
			var minimumHeight = 0;
			var boxes = [];
			var child;
			var childWidth;
			var childHeight;
			var childSize;
			var childMargins;
			var canLayout;
			var i;
			var calcs;
			var flexedHeight;
			var horizMargins;
			var vertMargins;
			var stretchWidth;
			var length;
			for (i = 0; i < visibleCount; i++) {
				child = visibleItems[i];
				childHeight = child.height;
				childWidth = child.width;
				canLayout = !child.hasLayout && typeof child.doLayout == "function";
				if (typeof childHeight !=
					"number")
					if (child.flex && !childHeight)
						totalFlex += child.flex;
					else {
						if (!childHeight && canLayout)
							child.doLayout();
						childSize = child.getSize();
						childWidth = childSize.width;
						childHeight = childSize.height
					}
				childMargins = child.margins;
				vertMargins = childMargins.top + childMargins.bottom;
				nonFlexHeight += vertMargins + (childHeight || 0);
				desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
				minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
				if (typeof childWidth != "number") {
					if (canLayout)
						child.doLayout();
					childWidth = child.getWidth()
				}
				maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
				boxes.push({
					component : child,
					height : childHeight || undefined,
					width : childWidth || undefined
				})
			}
			var shortfall = desiredHeight - height;
			var tooNarrow = minimumHeight > height;
			var availableHeight = Math.max(0, height - nonFlexHeight - paddingVert);
			if (tooNarrow)
				for (i = 0, length = visibleCount; i < length; i++)
					boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
			else if (shortfall > 0) {
				var minHeights = [];
				var index = 0;
				for (length = visibleCount; index < length; index++) {
					var item = visibleItems[index];
					var minHeight = item.minHeight || 0;
					if (item.flex)
						boxes[index].height = minHeight;
					else
						minHeights.push({
							minHeight : minHeight,
							available : boxes[index].height - minHeight,
							index : index
						})
				}
				minHeights.sort(function (a, b) {
					return a.available > b.available ? 1 : -1
				});
				i = 0;
				for (length = minHeights.length; i < length; i++) {
					var itemIndex = minHeights[i].index;
					if (itemIndex == undefined)
						continue;
					item = visibleItems[itemIndex];
					var box = boxes[itemIndex];
					var oldHeight =
						box.height;
					minHeight = item.minHeight;
					var newHeight = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i)));
					var reduction = oldHeight - newHeight;
					boxes[itemIndex].height = newHeight;
					shortfall -= reduction
				}
			} else {
				var remainingHeight = availableHeight;
				var remainingFlex = totalFlex;
				for (i = 0; i < visibleCount; i++) {
					child = visibleItems[i];
					calcs = boxes[i];
					childMargins = child.margins;
					horizMargins = childMargins.left + childMargins.right;
					if (isStart && child.flex && !child.height) {
						flexedHeight = Math.ceil(child.flex / remainingFlex * remainingHeight);
						remainingHeight -= flexedHeight;
						remainingFlex -= child.flex;
						calcs.height = flexedHeight;
						calcs.dirtySize = true
					}
				}
			}
			if (isCenter)
				topOffset += availableHeight / 2;
			else if (isEnd)
				topOffset += availableHeight;
			for (i = 0; i < visibleCount; i++) {
				child = visibleItems[i];
				calcs = boxes[i];
				childMargins = child.margins;
				topOffset += childMargins.top;
				horizMargins = childMargins.left + childMargins.right;
				calcs.left = leftOffset + childMargins.left;
				calcs.top = topOffset;
				switch (this.align) {
				case "stretch":
					stretchWidth = availWidth - horizMargins;
					calcs.width = stretchWidth.constrain(child.minWidth ||
							0, child.maxWidth || 1E6);
					calcs.dirtySize = true;
					break;
				case "stretchmax":
					stretchWidth = maxWidth - horizMargins;
					calcs.width = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1E6);
					calcs.dirtySize = true;
					break;
				case "center":
					var diff = availWidth - calcs.width - horizMargins;
					if (diff > 0)
						calcs.left = leftOffset + horizMargins + diff / 2
				}
				topOffset += calcs.height + childMargins.bottom
			}
			return {
				boxes : boxes,
				meta : {
					maxWidth : maxWidth,
					nonFlexHeight : nonFlexHeight,
					desiredHeight : desiredHeight,
					minimumHeight : minimumHeight,
					shortfall : desiredHeight -
					height,
					tooNarrow : tooNarrow
				}
			}
		}
	});
Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
		monitorResize : true,
		type : "toolbar",
		triggerWidth : 18,
		noItemsMenuText : '\x3cdiv class\x3d"x-toolbar-no-items"\x3e(None)\x3c/div\x3e',
		lastOverflow : false,
		tableHTML : ['\x3ctable cellspacing\x3d"0" class\x3d"x-toolbar-ct"\x3e', "\x3ctbody\x3e", "\x3ctr\x3e", '\x3ctd class\x3d"x-toolbar-left" align\x3d"{0}"\x3e', '\x3ctable cellspacing\x3d"0"\x3e', "\x3ctbody\x3e", '\x3ctr class\x3d"x-toolbar-left-row"\x3e\x3c/tr\x3e', "\x3c/tbody\x3e", "\x3c/table\x3e",
			"\x3c/td\x3e", '\x3ctd class\x3d"x-toolbar-right" align\x3d"right"\x3e', '\x3ctable cellspacing\x3d"0" class\x3d"x-toolbar-right-ct"\x3e', "\x3ctbody\x3e", "\x3ctr\x3e", "\x3ctd\x3e", '\x3ctable cellspacing\x3d"0"\x3e', "\x3ctbody\x3e", '\x3ctr class\x3d"x-toolbar-right-row"\x3e\x3c/tr\x3e', "\x3c/tbody\x3e", "\x3c/table\x3e", "\x3c/td\x3e", "\x3ctd\x3e", '\x3ctable cellspacing\x3d"0"\x3e', "\x3ctbody\x3e", '\x3ctr class\x3d"x-toolbar-extras-row"\x3e\x3c/tr\x3e', "\x3c/tbody\x3e", "\x3c/table\x3e", "\x3c/td\x3e", "\x3c/tr\x3e",
			"\x3c/tbody\x3e", "\x3c/table\x3e", "\x3c/td\x3e", "\x3c/tr\x3e", "\x3c/tbody\x3e", "\x3c/table\x3e"].join(""),
		onLayout : function (ct, target) {
			if (!this.leftTr) {
				var align = ct.buttonAlign == "center" ? "center" : "left";
				target.addClass("x-toolbar-layout-ct");
				target.insertHtml("beforeEnd", String.format(this.tableHTML, align));
				this.leftTr = target.child("tr.x-toolbar-left-row", true);
				this.rightTr = target.child("tr.x-toolbar-right-row", true);
				this.extrasTr = target.child("tr.x-toolbar-extras-row", true);
				if (this.hiddenItem == undefined)
					this.hiddenItems =
						[]
			}
			var side = ct.buttonAlign == "right" ? this.rightTr : this.leftTr;
			var items = ct.items.items;
			var position = 0;
			var i = 0;
			var len = items.length;
			for (var c; i < len; i++, position++) {
				c = items[i];
				if (c.isFill) {
					side = this.rightTr;
					position = -1
				} else if (!c.rendered) {
					c.render(this.insertCell(c, side, position));
					this.configureItem(c)
				} else if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
					var td = this.insertCell(c, side, position);
					td.appendChild(c.getPositionEl().dom);
					c.container = Ext.get(td)
				}
			}
			this.cleanup(this.leftTr);
			this.cleanup(this.rightTr);
			this.cleanup(this.extrasTr);
			this.fitToSize(target)
		},
		cleanup : function (el) {
			var cn = el.childNodes;
			var i;
			var c;
			for (i = cn.length - 1; i >= 0 && (c = cn[i]); i--)
				if (!c.firstChild)
					el.removeChild(c)
		},
		insertCell : function (c, target, position) {
			var td = document.createElement("td");
			td.className = "x-toolbar-cell";
			target.insertBefore(td, target.childNodes[position] || null);
			return td
		},
		hideItem : function (item) {
			this.hiddenItems.push(item);
			item.xtbHidden = true;
			item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
			item.hide()
		},
		unhideItem : function (item) {
			item.show();
			item.xtbHidden = false;
			this.hiddenItems.remove(item)
		},
		getItemWidth : function (c) {
			return c.hidden ? c.xtbWidth || 0 : c.getPositionEl().dom.parentNode.offsetWidth
		},
		fitToSize : function (target) {
			if (this.container.enableOverflow === false)
				return;
			var width = target.dom.clientWidth;
			var tableWidth = target.dom.firstChild.offsetWidth;
			var clipWidth = width - this.triggerWidth;
			var lastWidth = this.lastWidth || 0;
			var hiddenItems = this.hiddenItems;
			var hasHiddens = hiddenItems.length != 0;
			var isLarger = width >= lastWidth;
			this.lastWidth = width;
			if (tableWidth > width || hasHiddens && isLarger) {
				var items = this.container.items.items;
				var len = items.length;
				var loopWidth = 0;
				var item;
				for (var i = 0; i < len; i++) {
					item = items[i];
					if (!item.isFill) {
						loopWidth += this.getItemWidth(item);
						if (loopWidth > clipWidth) {
							if (!(item.hidden || item.xtbHidden))
								this.hideItem(item)
						} else if (item.xtbHidden)
							this.unhideItem(item)
					}
				}
			}
			hasHiddens = hiddenItems.length != 0;
			if (hasHiddens) {
				this.initMore();
				if (!this.lastOverflow) {
					this.container.fireEvent("overflowchange",
						this.container, true);
					this.lastOverflow = true
				}
			} else if (this.more) {
				this.clearMenu();
				this.more.destroy();
				delete this.more;
				if (this.lastOverflow) {
					this.container.fireEvent("overflowchange", this.container, false);
					this.lastOverflow = false
				}
			}
		},
		createMenuConfig : function (component, hideOnClick) {
			var config = Ext.apply({}, component.initialConfig);
			var group = component.toggleGroup;
			Ext.copyTo(config, component, ["iconCls", "icon", "itemId", "disabled", "handler", "scope", "menu"]);
			Ext.apply(config, {
				text : component.overflowText ||
				component.text,
				hideOnClick : hideOnClick
			});
			if (group || component.enableToggle)
				Ext.apply(config, {
					group : group,
					checked : component.pressed,
					listeners : {
						checkchange : function (item, checked) {
							component.toggle(checked)
						}
					}
				});
			delete config.ownerCt;
			delete config.xtype;
			delete config.id;
			return config
		},
		addComponentToMenu : function (menu, component) {
			if (component instanceof Ext.Toolbar.Separator)
				menu.add("-");
			else if (Ext.isFunction(component.isXType))
				if (component.isXType("splitbutton"))
					menu.add(this.createMenuConfig(component,
							true));
				else if (component.isXType("button"))
					menu.add(this.createMenuConfig(component, !component.menu));
				else if (component.isXType("buttongroup"))
					component.items.each(function (item) {
						this.addComponentToMenu(menu, item)
					}, this)
		},
		clearMenu : function () {
			var menu = this.moreMenu;
			if (menu && menu.items)
				menu.items.each(function (item) {
					delete item.menu
				})
		},
		beforeMoreShow : function (menu) {
			var items = this.container.items.items;
			var len = items.length;
			var item$$0;
			var prev;
			var needsSep = function (group, item) {
				return group.isXType("buttongroup") &&
				!(item instanceof Ext.Toolbar.Separator)
			};
			this.clearMenu();
			menu.removeAll();
			for (var i = 0; i < len; i++) {
				item$$0 = items[i];
				if (item$$0.xtbHidden) {
					if (prev && (needsSep(item$$0, prev) || needsSep(prev, item$$0)))
						menu.add("-");
					this.addComponentToMenu(menu, item$$0);
					prev = item$$0
				}
			}
			if (menu.items.length < 1)
				menu.add(this.noItemsMenuText)
		},
		initMore : function () {
			if (!this.more) {
				this.moreMenu = new Ext.menu.Menu({
						ownerCt : this.container,
						listeners : {
							beforeshow : this.beforeMoreShow,
							scope : this
						}
					});
				this.more = new Ext.Button({
						iconCls : "x-toolbar-more-icon",
						cls : "x-toolbar-more",
						menu : this.moreMenu,
						ownerCt : this.container
					});
				var td = this.insertCell(this.more, this.extrasTr, 100);
				this.more.render(td)
			}
		},
		destroy : function () {
			Ext.destroy(this.more, this.moreMenu);
			delete this.leftTr;
			delete this.rightTr;
			delete this.extrasTr;
			Ext.layout.ToolbarLayout.superclass.destroy.call(this)
		}
	});
Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
		monitorResize : true,
		type : "menu",
		setContainer : function (ct) {
			this.monitorResize = !ct.floating;
			ct.on("autosize", this.doAutoSize, this);
			Ext.layout.MenuLayout.superclass.setContainer.call(this, ct)
		},
		renderItem : function (c, position, target) {
			if (!this.itemTpl)
				this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate('\x3cli id\x3d"{itemId}" class\x3d"{itemCls}"\x3e', '\x3ctpl if\x3d"needsIcon"\x3e', '\x3cimg alt\x3d"{altText}" src\x3d"{icon}" class\x3d"{iconCls}"/\x3e',
						"\x3c/tpl\x3e", "\x3c/li\x3e");
			if (c && !c.rendered) {
				if (Ext.isNumber(position))
					position = target.dom.childNodes[position];
				var a = this.getItemArgs(c);
				c.render(c.positionEl = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(target, a, true));
				c.positionEl.menuItemId = c.getItemId();
				if (!a.isMenuItem && a.needsIcon)
					c.positionEl.addClass("x-menu-list-item-indent");
				this.configureItem(c)
			} else if (c && !this.isValidParent(c, target)) {
				if (Ext.isNumber(position))
					position = target.dom.childNodes[position];
				target.dom.insertBefore(c.getActionEl().dom,
					position || null)
			}
		},
		getItemArgs : function (c) {
			var isMenuItem = c instanceof Ext.menu.Item;
			var canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
			return {
				isMenuItem : isMenuItem,
				needsIcon : canHaveIcon && (c.icon || c.iconCls),
				icon : c.icon || Ext.BLANK_IMAGE_URL,
				iconCls : "x-menu-item-icon " + (c.iconCls || ""),
				itemId : "x-menu-el-" + c.id,
				itemCls : "x-menu-list-item ",
				altText : c.altText || ""
			}
		},
		isValidParent : function (c, target) {
			return c.el.up("li.x-menu-list-item", 5).dom.parentNode === (target.dom || target)
		},
		onLayout : function (ct,
			target) {
			Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
			this.doAutoSize()
		},
		doAutoSize : function () {
			var ct = this.container;
			var w = ct.width;
			if (ct.floating)
				if (w)
					ct.setWidth(w);
				else if (Ext.isIE) {
					ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8 || Ext.isIE9) ? "auto" : ct.minWidth);
					var el = ct.getEl();
					var t = el.dom.offsetWidth;
					ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth("lr"))
				}
		}
	});
Ext.Container.LAYOUTS["menu"] = Ext.layout.MenuLayout;
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",
		preventBodyReset : false,
		padding : undefined,
		resizeEvent : "bodyresize",
		toolTarget : "header",
		collapseEl : "bwrap",
		slideAnchor : "t",
		disabledClass : "",
		deferHeight : true,
		expandDefaults : {
			duration : 0.25
		},
		collapseDefaults : {
			duration : 0.25
		},
		initComponent : function () {
			Ext.Panel.superclass.initComponent.call(this);
			this.addEvents("bodyresize", "titlechange", "iconchange", "collapse", "expand", "beforecollapse", "beforeexpand", "beforeclose", "close", "activate", "deactivate");
			if (this.unstyled)
				this.baseCls = "x-plain";
			this.toolbars = [];
			if (this.tbar) {
				this.elements += ",tbar";
				this.topToolbar = this.createToolbar(this.tbar);
				this.tbar = null
			}
			if (this.bbar) {
				this.elements += ",bbar";
				this.bottomToolbar = this.createToolbar(this.bbar);
				this.bbar = null
			}
			if (this.header === true) {
				this.elements += ",header";
				this.header = null
			} else if (this.headerCfg || this.title &&
				this.header !== false)
				this.elements += ",header";
			if (this.footerCfg || this.footer === true) {
				this.elements += ",footer";
				this.footer = null
			}
			if (this.buttons) {
				this.fbar = this.buttons;
				this.buttons = null
			}
			if (this.fbar)
				this.createFbar(this.fbar);
			if (this.autoLoad)
				this.on("render", this.doAutoLoad, this, {
					delay : 10
				})
		},
		createFbar : function (fbar) {
			var min = this.minButtonWidth;
			this.elements += ",footer";
			this.fbar = this.createToolbar(fbar, {
					buttonAlign : this.buttonAlign,
					toolbarCls : "x-panel-fbar",
					enableOverflow : false,
					defaults : function (c) {
						return {
							minWidth : c.minWidth ||
							min
						}
					}
				});
			this.fbar.items.each(function (c) {
				c.minWidth = c.minWidth || this.minButtonWidth
			}, this);
			this.buttons = this.fbar.items.items
		},
		createToolbar : function (tb, options) {
			var result;
			if (Ext.isArray(tb))
				tb = {
					items : tb
				};
			result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), "toolbar");
			this.toolbars.push(result);
			return result
		},
		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))
				}
				if (this[name + "CssClass"])
					this[name].addClass(this[name + "CssClass"]);
				if (this[name + "Style"])
					this[name].applyStyles(this[name + "Style"])
			}
		},
		onRender : function (ct, position) {
			Ext.Panel.superclass.onRender.call(this, ct, position);
			this.createClasses();
			var el = this.el;
			var d = el.dom;
			var bw;
			var ts;
			if (this.collapsible && !this.hideCollapseTool) {
				this.tools = this.tools ?
					this.tools.slice(0) : [];
				this.tools[this.collapseFirst ? "unshift" : "push"]({
					id : "toggle",
					handler : this.toggleCollapse,
					scope : this
				})
			}
			if (this.tools) {
				ts = this.tools;
				this.elements += this.header !== false ? ",header" : ""
			}
			this.tools = {};
			el.addClass(this.baseCls);
			if (d.firstChild) {
				this.header = el.down("." + this.headerCls);
				this.bwrap = el.down("." + this.bwrapCls);
				var cp = this.bwrap ? this.bwrap : 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
			}
			if (this.preventBodyReset === true)
				el.addClass("x-panel-reset");
			if (this.cls)
				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);
				bw = this.bwrap.dom;
				var ml = d.childNodes[1];
				var 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";
				this.ft = Ext.get(this.bwrap.dom.lastChild);
				this.mc = Ext.get(mc)
			} else {
				this.createElement("header", d);
				this.createElement("bwrap", d);
				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 (Ext.isDefined(this.padding))
				this.body.setStyle("padding", this.body.addUnits(this.padding));
			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");
			this.bwrap.enableDisplayMode("block");
			if (this.header) {
				this.header.unselectable();
				if (this.headerAsText) {
					this.header.dom.innerHTML = '\x3cspan class\x3d"' + this.headerTextCls + '"\x3e' + this.header.dom.innerHTML + "\x3c/span\x3e";
					if (this.iconCls)
						this.setIconClass(this.iconCls)
				}
			}
			if (this.floating)
				this.makeFloating(this.floating);
			if (this.collapsible && this.titleCollapse && this.header) {
				this.mon(this.header, "click", this.toggleCollapse,
					this);
				this.header.setStyle("cursor", "pointer")
			}
			if (ts)
				this.addTool.apply(this, ts);
			if (this.fbar) {
				this.footer.addClass("x-panel-btns");
				this.fbar.ownerCt = this;
				this.fbar.render(this.footer);
				this.footer.createChild({
					cls : "x-clear"
				})
			}
			if (this.tbar && this.topToolbar) {
				this.topToolbar.ownerCt = this;
				this.topToolbar.render(this.tbar)
			}
			if (this.bbar && this.bottomToolbar) {
				this.bottomToolbar.ownerCt = this;
				this.bottomToolbar.render(this.bbar)
			}
		},
		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;
					var img = hd.child("img.x-panel-inline-icon");
					if (img)
						Ext.fly(img).replaceClass(old, this.iconCls);
					else {
						var hdspan = hd.child("span." + this.headerTextCls);
						if (hdspan)
							Ext.DomHelper.insertBefore(hdspan.dom, {
								tag : "img",
								alt : "",
								src : Ext.BLANK_IMAGE_URL,
								cls : "x-panel-inline-icon " + this.iconCls
							})
					}
				}
			this.fireEvent("iconchange", this, cls, old)
		},
		makeFloating : function (cfg) {
			this.floating = true;
			this.el = new Ext.Layer(Ext.apply({}, cfg, {
						shadow : Ext.isDefined(this.shadow) ? 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
		},
		getFooterToolbar : function () {
			return this.fbar
		},
		addButton : function (config, handler, scope) {
			if (!this.fbar)
				this.createFbar([]);
			if (handler) {
				if (Ext.isString(config))
					config = {
						text : config
					};
				config = Ext.apply({
						handler : handler,
						scope : scope
					}, config)
			}
			return this.fbar.add(config)
		},
		addTool : function () {
			if (!this.rendered) {
				if (!this.tools)
					this.tools = [];
				Ext.each(arguments, function (arg) {
					this.tools.push(arg)
				}, this);
				return
			}
			if (!this[this.toolTarget])
				return;
			if (!this.toolTemplate) {
				var tt = new Ext.Template('\x3cdiv class\x3d"x-tool x-tool-{id}"\x3e\x26#160;\x3c/div\x3e');
				tt.disableFormats = true;
				tt.compile();
				Ext.Panel.prototype.toolTemplate = tt
			}
			var i = 0;
			var a = arguments;
			for (var len = a.length; i < len; i++) {
				var tc = a[i];
				if (!this.tools[tc.id]) {
					var overCls =
						"x-tool-" + tc.id + "-over";
					var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
					this.tools[tc.id] = t;
					t.enableDisplayMode("block");
					this.mon(t, "click", this.createToolHandler(t, tc, overCls, this));
					if (tc.on)
						this.mon(t, tc.on);
					if (tc.hidden)
						t.hide();
					if (tc.qtip)
						if (Ext.isObject(tc.qtip))
							Ext.QuickTips.register(Ext.apply({
									target : t.id
								}, tc.qtip));
						else
							t.dom.qtip = tc.qtip;
					t.addClassOnOver(overCls)
				}
			}
		},
		onLayout : function (shallow, force) {
			Ext.Panel.superclass.onLayout.apply(this, arguments);
			if (this.hasLayout &&
				this.toolbars.length > 0) {
				Ext.each(this.toolbars, function (tb) {
					tb.doLayout(undefined, force)
				});
				this.syncHeight()
			}
		},
		syncHeight : function () {
			var h = this.toolbarHeight;
			var bd = this.body;
			var lsh = this.lastSize.height;
			var sz;
			if (this.autoHeight || !Ext.isDefined(lsh) || lsh == "auto")
				return;
			if (h != this.getToolbarHeight()) {
				h = Math.max(0, lsh - this.getFrameHeight());
				bd.setHeight(h);
				sz = bd.getSize();
				this.toolbarHeight = this.getToolbarHeight();
				this.onBodyResize(sz.width, sz.height)
			}
		},
		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);
				if (tc.stopEvent !== false)
					e.stopEvent();
				if (tc.handler)
					tc.handler.call(tc.scope || t, e, t, panel, tc)
			}
		},
		afterRender : function () {
			if (this.floating && !this.hidden)
				this.el.show();
			if (this.title)
				this.setTitle(this.title);
			Ext.Panel.superclass.afterRender.call(this);
			if (this.collapsed) {
				this.collapsed =
					false;
				this.collapse(false)
			}
			this.initEvents()
		},
		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();
			if (this.toolbars.length > 0) {
				Ext.each(this.toolbars, function (tb) {
					tb.doLayout();
					tb.on({
						scope : this,
						afterlayout : this.syncHeight,
						remove : this.syncHeight
					})
				}, this);
				this.syncHeight()
			}
		},
		initDraggable : function () {
			this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null :
					this.draggable)
		},
		beforeEffect : function (anim) {
			if (this.floating)
				this.el.beforeAction();
			if (anim !== false)
				this.el.addClass("x-panel-animated")
		},
		afterEffect : function (anim) {
			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(doAnim);
			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.hideMode);
				this.afterCollapse(false)
			}
		},
		afterCollapse : function (anim) {
			this.collapsed =
				true;
			this.el.addClass(this.collapsedCls);
			if (anim !== false)
				this[this.collapseEl].hide(this.hideMode);
			this.afterEffect(anim);
			this.cascade(function (c) {
				if (c.lastSize)
					c.lastSize = {
						width : undefined,
						height : undefined
					}
			});
			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(doAnim);
			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.hideMode);
				this.afterExpand(false)
			}
		},
		afterExpand : function (anim) {
			this.collapsed = false;
			if (anim !== false)
				this[this.collapseEl].show(this.hideMode);
			this.afterEffect(anim);
			if (this.deferLayout) {
				delete this.deferLayout;
				this.doLayout(true)
			}
			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 (adjWidth, adjHeight, rawWidth, rawHeight) {
			var w = adjWidth;
			var h = adjHeight;
			if (Ext.isDefined(w) || Ext.isDefined(h)) {
				if (!this.collapsed) {
					if (Ext.isNumber(w))
						this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
					else if (w == "auto")
						w = this.body.setWidth("auto").dom.offsetWidth;
					else
						w = this.body.dom.offsetWidth;
					if (this.tbar) {
						this.tbar.setWidth(w);
						if (this.topToolbar)
							this.topToolbar.setSize(w)
					}
					if (this.bbar) {
						this.bbar.setWidth(w);
						if (this.bottomToolbar) {
							this.bottomToolbar.setSize(w);
							if (Ext.isIE) {
								this.bbar.setStyle("position", "static");
								this.bbar.setStyle("position", "")
							}
						}
					}
					if (this.footer) {
						this.footer.setWidth(w);
						if (this.fbar)
							this.fbar.setSize(Ext.isIE ? w - this.footer.getFrameWidth("lr") : "auto")
					}
					if (Ext.isNumber(h)) {
						h = Math.max(0,
								h - this.getFrameHeight());
						this.body.setHeight(h)
					} 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, {
							single : true
						})
					}
				}
				this.onBodyResize(w, h)
			}
			this.syncShadow();
			Ext.Panel.superclass.onResize.call(this,
				adjWidth, adjHeight, rawWidth, rawHeight)
		},
		onBodyResize : function (w, h) {
			this.fireEvent("bodyresize", this, w, h)
		},
		getToolbarHeight : function () {
			var h = 0;
			if (this.rendered)
				Ext.each(this.toolbars, function (tb) {
					h += tb.getHeight()
				}, this);
			return h
		},
		adjustBodyHeight : function (h) {
			return h
		},
		adjustBodyWidth : function (w) {
			return w
		},
		onPosition : function () {
			this.syncShadow()
		},
		getFrameWidth : function () {
			var w = this.el.getFrameWidth("lr") + this.bwrap.getFrameWidth("lr");
			if (this.frame) {
				var l = this.bwrap.dom.firstChild;
				w += Ext.fly(l).getFrameWidth("l") +
				Ext.fly(l.firstChild).getFrameWidth("r");
				w += this.mc.getFrameWidth("lr")
			}
			return w
		},
		getFrameHeight : function () {
			var h = this.el.getFrameWidth("tb") + this.bwrap.getFrameWidth("tb");
			h += (this.tbar ? this.tbar.getHeight() : 0) + (this.bbar ? this.bbar.getHeight() : 0);
			if (this.frame)
				h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.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.body.getHeight()
		},
		syncShadow : function () {
			if (this.floating)
				this.el.sync(true)
		},
		getLayoutTarget : function () {
			return this.body
		},
		getContentTarget : 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.Panel.superclass.beforeDestroy.call(this);
			if (this.header)
				this.header.removeAllListeners();
			if (this.tools)
				for (var k in this.tools)
					Ext.destroy(this.tools[k]);
			if (this.toolbars.length > 0)
				Ext.each(this.toolbars, function (tb) {
					tb.un("afterlayout", this.syncHeight, this);
					tb.un("remove", this.syncHeight, this)
				}, this);
			if (Ext.isArray(this.buttons))
				for (; this.buttons.length; )
					Ext.destroy(this.buttons[0]);
			if (this.rendered) {
				Ext.destroy(this.ft,
					this.header, this.footer, this.tbar, this.bbar, this.body, this.mc, this.bwrap, this.dd);
				if (this.fbar)
					Ext.destroy(this.fbar, this.fbar.el)
			}
			Ext.destroy(this.toolbars)
		},
		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 () {
			var u = this.body.getUpdater();
			if (this.renderer)
				u.setRenderer(this.renderer);
			u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {
				url : this.autoLoad
			})
		},
		getTool : function (id) {
			return this.tools[id]
		}
	});
Ext.reg("panel", Ext.Panel);
Ext.Editor = function (field, config) {
	if (field.field) {
		this.field = Ext.create(field.field, "textfield");
		config = Ext.apply({}, field);
		delete config.field
	} else
		this.field = field;
	Ext.Editor.superclass.constructor.call(this, config)
};
Ext.extend(Ext.Editor, Ext.Component, {
	allowBlur : true,
	value : "",
	alignment : "c-c?",
	offsets : [0, 0],
	shadow : "frame",
	constrain : false,
	swallowKeys : true,
	completeOnEnter : true,
	cancelOnEsc : true,
	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 : this.shadowOffset ||
				4,
				id : this.id,
				constrain : this.constrain
			});
		if (this.zIndex)
			this.el.setZIndex(this.zIndex);
		this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
		if (this.field.msgTarget != "title")
			this.field.msgTarget = "qtip";
		this.field.inEditor = true;
		this.mon(this.field, {
			scope : this,
			blur : this.onBlur,
			specialkey : this.onSpecialKey
		});
		if (this.field.grow)
			this.mon(this.field, "autosize", this.el.sync, this.el, {
				delay : 1
			});
		this.field.render(this.el).show();
		this.field.getEl().dom.name = "";
		if (this.swallowKeys)
			this.field.el.swallowEvent(["keypress",
					"keydown"])
	},
	onSpecialKey : function (field, e) {
		var key = e.getKey();
		var complete = this.completeOnEnter && key == e.ENTER;
		var cancel = this.cancelOnEsc && key == e.ESC;
		if (complete || cancel) {
			e.stopEvent();
			if (complete)
				this.completeEdit();
			else
				this.cancelEdit();
			if (field.triggerBlur)
				field.triggerBlur()
		}
		this.fireEvent("specialkey", field, e)
	},
	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) {
			this.startValue = v;
			this.field.reset();
			this.field.setValue(v);
			this.realign(true);
			this.editing = true;
			this.show()
		}
	},
	doAutoSize : function () {
		if (this.autoSize) {
			var sz = this.boundEl.getSize();
			var fs = this.field.getSize();
			switch (this.autoSize) {
			case "width":
				this.setSize(sz.width, fs.height);
				break;
			case "height":
				this.setSize(fs.width, sz.height);
				break;
			case "none":
				this.setSize(fs.width, fs.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 || Ext.isIE7 && Ext.isStrict)
				this.el.setSize(w, h);
			this.el.sync()
		}
	},
	realign : function (autoSize) {
		if (autoSize === true)
			this.doAutoSize();
		this.el.alignTo(this.boundEl, this.alignment, this.offsets)
	},
	completeEdit : function (remainVisible) {
		if (!this.editing)
			return;
		if (this.field.assertValue)
			this.field.assertValue();
		var v = this.getValue();
		if (!this.field.isValid()) {
			if (this.revertInvalid !== false)
				this.cancelEdit(remainVisible);
			return
		}
		if (String(v) === String(this.startValue) && this.ignoreNoChange) {
			this.hideEdit(remainVisible);
			return
		}
		if (this.fireEvent("beforecomplete", this, v, this.startValue) !== false) {
			v = this.getValue();
			if (this.updateEl && this.boundEl)
				this.boundEl.update(v);
			this.hideEdit(remainVisible);
			this.fireEvent("complete", this, v, this.startValue)
		}
	},
	onShow : function () {
		this.el.show();
		if (this.hideEl !== false)
			this.boundEl.hide();
		this.field.show().focus(false, true);
		this.fireEvent("startedit", this.boundEl, this.startValue)
	},
	cancelEdit : function (remainVisible) {
		if (this.editing) {
			var v =
				this.getValue();
			this.setValue(this.startValue);
			this.hideEdit(remainVisible);
			this.fireEvent("canceledit", this, v, this.startValue)
		}
	},
	hideEdit : function (remainVisible) {
		if (remainVisible !== true) {
			this.editing = false;
			this.hide()
		}
	},
	onBlur : function () {
		if (this.allowBlur === true && this.editing && this.selectSameEditor !== true)
			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 () {
		Ext.destroyMembers(this, "field");
		delete this.parentEl;
		delete this.boundEl
	}
});
Ext.reg("editor", Ext.Editor);
Ext.ColorPalette = Ext.extend(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"],
		initComponent : function () {
			Ext.ColorPalette.superclass.initComponent.call(this);
			this.addEvents("select");
			if (this.handler)
				this.on("select", this.handler, this.scope, true)
		},
		onRender : function (container, position) {
			this.autoEl = {
				tag : "div",
				cls : this.itemCls
			};
			Ext.ColorPalette.superclass.onRender.call(this, container, position);
			var t = this.tpl || new Ext.XTemplate('\x3ctpl for\x3d"."\x3e\x3ca href\x3d"#" class\x3d"color-{.}" hidefocus\x3d"on"\x3e\x3cem\x3e\x3cspan style\x3d"background:#{.}" unselectable\x3d"on"\x3e\x26#160;\x3c/span\x3e\x3c/em\x3e\x3c/a\x3e\x3c/tpl\x3e');
			t.overwrite(this.el, this.colors);
			this.mon(this.el, this.clickEvent, this.handleClick, this, {
				delegate : "a"
			});
			if (this.clickEvent != "click")
				this.mon(this.el, "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, true)
			}
		},
		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, suppressEvent) {
			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;
				if (suppressEvent !== true)
					this.fireEvent("select", this, color)
			}
		}
	});
Ext.reg("colorpalette", Ext.ColorPalette);
Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
		todayText : "Today",
		okText : "\x26#160;OK\x26#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",
		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,
		focusOnSelect : true,
		initHour : 12,
		initComponent : function () {
			Ext.DatePicker.superclass.initComponent.call(this);
			this.value = this.value ? this.value.clearTime(true) : (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 len = dd.length - 1;
				var re = "(?:";
				Ext.each(dd, function (d, i) {
					re += Ext.isDate(d) ? "^" + Ext.escapeRe(d.dateFormat(this.format)) +
					"$" : dd[i];
					if (i != len)
						re += "|"
				}, this);
				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) {
			this.value =
				value.clearTime(true);
			this.update(this.value)
		},
		getValue : function () {
			return this.value
		},
		focus : function () {
			this.update(this.activeDate)
		},
		onEnable : function (initial) {
			Ext.DatePicker.superclass.onEnable.call(this);
			this.doDisabled(false);
			this.update(initial ? this.value : this.activeDate);
			if (Ext.isIE)
				this.el.repaint()
		},
		onDisable : function () {
			Ext.DatePicker.superclass.onDisable.call(this);
			this.doDisabled(true);
			if (Ext.isIE && !Ext.isIE8)
				Ext.each([].concat(this.textNodes, this.el.query("th span")), function (el) {
					Ext.fly(el).repaint()
				})
		},
		doDisabled : function (disabled) {
			this.keyNav.setDisabled(disabled);
			this.prevRepeater.setDisabled(disabled);
			this.nextRepeater.setDisabled(disabled);
			if (this.showToday) {
				this.todayKeyListener.setDisabled(disabled);
				this.todayBtn.setDisabled(disabled)
			}
		},
		onRender : function (container, position) {
			var m = ['\x3ctable cellspacing\x3d"0"\x3e', '\x3ctr\x3e\x3ctd class\x3d"x-date-left"\x3e\x3ca href\x3d"#" title\x3d"', this.prevText, '"\x3e\x26#160;\x3c/a\x3e\x3c/td\x3e\x3ctd class\x3d"x-date-middle" align\x3d"center"\x3e\x3c/td\x3e\x3ctd class\x3d"x-date-right"\x3e\x3ca href\x3d"#" title\x3d"',
				this.nextText, '"\x3e\x26#160;\x3c/a\x3e\x3c/td\x3e\x3c/tr\x3e', '\x3ctr\x3e\x3ctd colspan\x3d"3"\x3e\x3ctable class\x3d"x-date-inner" cellspacing\x3d"0"\x3e\x3cthead\x3e\x3ctr\x3e'];
			var dn = this.dayNames;
			var i;
			for (i = 0; i < 7; i++) {
				var d = this.startDay + i;
				if (d > 6)
					d = d - 7;
				m.push("\x3cth\x3e\x3cspan\x3e", dn[d].substr(0, 1), "\x3c/span\x3e\x3c/th\x3e")
			}
			m[m.length] = "\x3c/tr\x3e\x3c/thead\x3e\x3ctbody\x3e\x3ctr\x3e";
			for (i = 0; i < 42; i++) {
				if (i % 7 === 0 && i !== 0)
					m[m.length] = "\x3c/tr\x3e\x3ctr\x3e";
				m[m.length] = '\x3ctd\x3e\x3ca href\x3d"#" hidefocus\x3d"on" class\x3d"x-date-date" tabIndex\x3d"1"\x3e\x3cem\x3e\x3cspan\x3e\x3c/span\x3e\x3c/em\x3e\x3c/a\x3e\x3c/td\x3e'
			}
			m.push("\x3c/tr\x3e\x3c/tbody\x3e\x3c/table\x3e\x3c/td\x3e\x3c/tr\x3e",
				this.showToday ? '\x3ctr\x3e\x3ctd colspan\x3d"3" class\x3d"x-date-bottom" align\x3d"center"\x3e\x3c/td\x3e\x3c/tr\x3e' : "", '\x3c/table\x3e\x3cdiv class\x3d"x-date-mp"\x3e\x3c/div\x3e');
			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);
			this.prevRepeater = new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
					handler : this.showPrevMonth,
					scope : this,
					preventDefault : true,
					stopDefault : true
				});
			this.nextRepeater = new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
					handler : this.showNextMonth,
					scope : this,
					preventDefault : true,
					stopDefault : true
				});
			this.monthPicker = this.el.down("div.x-date-mp");
			this.monthPicker.enableDisplayMode("block");
			this.keyNav = new Ext.KeyNav(this.eventEl, {
					"left" : function (e) {
						if (e.ctrlKey)
							this.showPrevMonth();
						else
							this.update(this.activeDate.add("d", -1))
					},
					"right" : function (e) {
						if (e.ctrlKey)
							this.showNextMonth();
						else
							this.update(this.activeDate.add("d",
									1))
					},
					"up" : function (e) {
						if (e.ctrlKey)
							this.showNextYear();
						else
							this.update(this.activeDate.add("d", -7))
					},
					"down" : function (e) {
						if (e.ctrlKey)
							this.showPrevYear();
						else
							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.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 : "\x26#160;",
					tooltip : this.monthYearText,
					renderTo : this.el.child("td.x-date-middle", true)
				});
			this.mbtn.el.child("em").addClass("x-btn-arrow");
			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
					})
			}
			this.mon(this.eventEl, "mousewheel", this.handleMouseWheel, this);
			this.mon(this.eventEl, "click", this.handleDateClick, this, {
				delegate : "a.x-date-date"
			});
			this.mon(this.mbtn, "click", this.showMonthPicker, this);
			this.onEnable(true)
		},
		createMonthPicker : function () {
			if (!this.monthPicker.dom.firstChild) {
				var buf = ['\x3ctable border\x3d"0" cellspacing\x3d"0"\x3e'];
				for (var i$$0 = 0; i$$0 < 6; i$$0++)
					buf.push('\x3ctr\x3e\x3ctd class\x3d"x-date-mp-month"\x3e\x3ca href\x3d"#"\x3e', Date.getShortMonthName(i$$0), "\x3c/a\x3e\x3c/td\x3e",
						'\x3ctd class\x3d"x-date-mp-month x-date-mp-sep"\x3e\x3ca href\x3d"#"\x3e', Date.getShortMonthName(i$$0 + 6), "\x3c/a\x3e\x3c/td\x3e", i$$0 === 0 ? '\x3ctd class\x3d"x-date-mp-ybtn" align\x3d"center"\x3e\x3ca class\x3d"x-date-mp-prev"\x3e\x3c/a\x3e\x3c/td\x3e\x3ctd class\x3d"x-date-mp-ybtn" align\x3d"center"\x3e\x3ca class\x3d"x-date-mp-next"\x3e\x3c/a\x3e\x3c/td\x3e\x3c/tr\x3e' : '\x3ctd class\x3d"x-date-mp-year"\x3e\x3ca href\x3d"#"\x3e\x3c/a\x3e\x3c/td\x3e\x3ctd class\x3d"x-date-mp-year"\x3e\x3ca href\x3d"#"\x3e\x3c/a\x3e\x3c/td\x3e\x3c/tr\x3e');
				buf.push('\x3ctr class\x3d"x-date-mp-btns"\x3e\x3ctd colspan\x3d"4"\x3e\x3cbutton type\x3d"button" class\x3d"x-date-mp-ok"\x3e', this.okText, '\x3c/button\x3e\x3cbutton type\x3d"button" class\x3d"x-date-mp-cancel"\x3e', this.cancelText, "\x3c/button\x3e\x3c/td\x3e\x3c/tr\x3e", "\x3c/table\x3e");
				this.monthPicker.update(buf.join(""));
				this.mon(this.monthPicker, "click", this.onMonthClick, this);
				this.mon(this.monthPicker, "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 * 0.5);
					else
						m.dom.xmonth = Math.round((i - 1) * 0.5)
				})
			}
		},
		showMonthPicker : function () {
			if (!this.disabled) {
				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 : 0.2
				})
			}
		},
		updateMPYear : function (y) {
			this.mpyear = y;
			var ys = this.mpYears.elements;
			for (var i = 1; i <= 10; i++) {
				var td = ys[i - 1];
				var y2;
				if (i % 2 === 0) {
					y2 = y + Math.round(i * 0.5);
					td.firstChild.innerHTML = y2;
					td.xyear = y2
				} else {
					y2 = y - (5 - Math.round(i * 0.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);
			var 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);
			var 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 : 0.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) {
			e.stopEvent();
			if (!this.disabled) {
				var delta = e.getWheelDelta();
				if (delta > 0)
					this.showPrevMonth();
				else if (delta < 0)
					this.showNextMonth()
			}
		},
		handleDateClick : function (e, t) {
			e.stopEvent();
			if (!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")) {
				this.cancelFocus = this.focusOnSelect === false;
				this.setValue(new Date(t.dateValue));
				delete this.cancelFocus;
				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) {
			if (this.rendered) {
				var vd = this.activeDate;
				var vis = this.isVisible();
				this.activeDate = date;
				if (!forceRefresh && vd && this.el) {
					var t$$0 = 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$$0) {
								c.addClass("x-date-selected");
								if (vis && !this.cancelFocus)
									Ext.fly(c.dom.firstChild).focus(50);
								return false
							}
						}, this);
						return
					}
				}
				var days = date.getDaysInMonth();
				var firstOfMonth = date.getFirstDateOfMonth();
				var startingPos = firstOfMonth.getDay() - this.startDay;
				if (startingPos < 0)
					startingPos += 7;
				days += startingPos;
				var pm = date.add("mo", -1);
				var prevStart = pm.getDaysInMonth() - startingPos;
				var cells = this.cells.elements;
				var textEls = this.textNodes;
				var d = new Date(pm.getFullYear(),
						pm.getMonth(), prevStart, this.initHour);
				var today = (new Date).clearTime().getTime();
				var sel = date.clearTime(true).getTime();
				var min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY;
				var max = this.maxDate ? this.maxDate.clearTime(true) : 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;
					if (!this.disabled) {
						this.todayBtn.setDisabled(disable);
						this.todayKeyListener[disable ? "disable" : "enable"]()
					}
				}
				var setCellClass = function (cal, cell) {
					cell.title = "";
					var t = d.clearTime(true).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";
						if (vis)
							Ext.fly(cell.firstChild).focus(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"
						}
					}
				};
				for (var i = 0; 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++) {
					var intDay = i - startingPos + 1;
					textEls[i].innerHTML = intDay;
					d.setDate(d.getDate() + 1);
					cells[i].className = "x-date-active";
					setCellClass(this, cells[i])
				}
				for (var extraDays = 0; 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.keyNav, this.monthPicker, this.eventEl, this.mbtn, this.nextRepeater, this.prevRepeater, this.cells.el, this.todayBtn);
				delete this.textNodes;
				delete this.cells.elements
			}
		}
	});
Ext.reg("datepicker", Ext.DatePicker);
Ext.LoadMask = function (el, config) {
	this.el = Ext.get(el);
	Ext.apply(this, config);
	if (this.store) {
		this.store.on({
			scope : this,
			beforeload : this.onBeforeLoad,
			load : this.onLoad,
			exception : this.onLoad
		});
		this.removeMask = Ext.value(this.removeMask, false)
	} else {
		var um = this.el.getUpdater();
		um.showLoadIndicator = false;
		um.on({
			scope : this,
			beforeupdate : this.onBeforeLoad,
			update : this.onLoad,
			failure : this.onLoad
		});
		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("exception",
				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.slider.Thumb = Ext.extend(Object, {
		dragging : false,
		constructor : function (config) {
			Ext.apply(this, config || {}, {
				cls : "x-slider-thumb",
				constrain : false
			});
			Ext.slider.Thumb.superclass.constructor.call(this, config);
			if (this.slider.vertical)
				Ext.apply(this, Ext.slider.Thumb.Vertical)
		},
		render : function () {
			this.el = this.slider.innerEl.insertFirst({
					cls : this.cls
				});
			this.initEvents()
		},
		enable : function () {
			this.disabled = false;
			this.el.removeClass(this.slider.disabledClass)
		},
		disable : function () {
			this.disabled = true;
			this.el.addClass(this.slider.disabledClass)
		},
		initEvents : function () {
			var el = this.el;
			el.addClassOnOver("x-slider-thumb-over");
			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(el)
		},
		onBeforeDragStart : function (e) {
			if (this.disabled)
				return false;
			else {
				this.slider.promoteThumb(this);
				return true
			}
		},
		onDragStart : function (e) {
			this.el.addClass("x-slider-thumb-drag");
			this.dragging = true;
			this.dragStartValue = this.value;
			this.slider.fireEvent("dragstart", this.slider, e, this)
		},
		onDrag : function (e) {
			var slider = this.slider;
			var index = this.index;
			var newValue = this.getNewValue();
			if (this.constrain) {
				var above = slider.thumbs[index + 1];
				var below = slider.thumbs[index - 1];
				if (below != undefined && newValue <= below.value)
					newValue = below.value;
				if (above != undefined && newValue >= above.value)
					newValue = above.value
			}
			slider.setValue(index, newValue, false);
			slider.fireEvent("drag", slider, e, this)
		},
		getNewValue : function () {
			var slider =
				this.slider;
			var pos = slider.innerEl.translatePoints(this.tracker.getXY());
			return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision)
		},
		onDragEnd : function (e) {
			var slider = this.slider;
			var value = this.value;
			this.el.removeClass("x-slider-thumb-drag");
			this.dragging = false;
			slider.fireEvent("dragend", slider, e);
			if (this.dragStartValue != value)
				slider.fireEvent("changecomplete", slider, value, this)
		},
		destroy : function () {
			Ext.destroyMembers(this, "tracker", "el")
		}
	});
Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
		vertical : false,
		minValue : 0,
		maxValue : 100,
		decimalPrecision : 0,
		keyIncrement : 1,
		increment : 0,
		clickRange : [5, 15],
		clickToChange : true,
		animate : true,
		constrainThumbs : true,
		topThumbZIndex : 1E4,
		initComponent : function () {
			if (!Ext.isDefined(this.value))
				this.value = this.minValue;
			this.thumbs = [];
			Ext.slider.MultiSlider.superclass.initComponent.call(this);
			this.keyIncrement = Math.max(this.increment, this.keyIncrement);
			this.addEvents("beforechange", "change", "changecomplete", "dragstart",
				"drag", "dragend");
			if (this.values == undefined || Ext.isEmpty(this.values))
				this.values = [0];
			var values = this.values;
			for (var i = 0; i < values.length; i++)
				this.addThumb(values[i]);
			if (this.vertical)
				Ext.apply(this, Ext.slider.Vertical)
		},
		addThumb : function (value) {
			var thumb = new Ext.slider.Thumb({
					value : value,
					slider : this,
					index : this.thumbs.length,
					constrain : this.constrainThumbs
				});
			this.thumbs.push(thumb);
			if (this.rendered)
				thumb.render()
		},
		promoteThumb : function (topThumb) {
			var thumbs = this.thumbs;
			var zIndex;
			var thumb;
			var i = 0;
			for (var j =
					thumbs.length; i < j; i++) {
				thumb = thumbs[i];
				if (thumb == topThumb)
					zIndex = this.topThumbZIndex;
				else
					zIndex = "";
				thumb.el.setStyle("zIndex", zIndex)
			}
		},
		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 : [{
								tag : "a",
								cls : "x-slider-focus",
								href : "#",
								tabIndex : "-1",
								hidefocus : "on"
							}
						]
					}
				}
			};
			Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
			this.endEl = this.el.first();
			this.innerEl = this.endEl.first();
			this.focusEl = this.innerEl.child(".x-slider-focus");
			for (var i = 0; i < this.thumbs.length; i++)
				this.thumbs[i].render();
			var thumb = this.innerEl.child(".x-slider-thumb");
			this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
			this.initEvents()
		},
		initEvents : function () {
			this.mon(this.el, {
				scope : this,
				mousedown : this.onMouseDown,
				keydown : this.onKeyDown
			});
			this.focusEl.swallowEvent("click", true)
		},
		onMouseDown : function (e) {
			if (this.disabled)
				return;
			var thumbClicked = false;
			for (var i = 0; i < this.thumbs.length; i++)
				thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
			if (this.clickToChange && !thumbClicked) {
				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]) {
				var thumb = this.getNearest(local, "left");
				var index = thumb.index;
				this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true)
			}
		},
		getNearest : function (local, prop) {
			var localValue = prop == "top" ? this.innerEl.getHeight() - local[prop] : local[prop];
			var clickValue = this.reverseValue(localValue);
			var nearestDistance = this.maxValue - this.minValue + 5;
			var index = 0;
			var nearest = null;
			for (var i = 0; i < this.thumbs.length; i++) {
				var thumb = this.thumbs[i];
				var value = thumb.value;
				var dist = Math.abs(value - clickValue);
				if (Math.abs(dist <= nearestDistance)) {
					nearest = thumb;
					index = i;
					nearestDistance = dist
				}
			}
			return nearest
		},
		onKeyDown : function (e) {
			if (this.disabled || this.thumbs.length !== 1) {
				e.preventDefault();
				return
			}
			var k = e.getKey();
			var val;
			switch (k) {
			case e.UP:
			case e.RIGHT:
				e.stopEvent();
				val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
				this.setValue(0, val, undefined, true);
				break;
			case e.DOWN:
			case e.LEFT:
				e.stopEvent();
				val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
				this.setValue(0, val, undefined, true);
				break;
			default:
				e.preventDefault()
			}
		},
		doSnap : function (value) {
			if (!(this.increment && value))
				return value;
			var newValue = value;
			var inc = this.increment;
			var m = value % inc;
			if (m != 0) {
				newValue -= m;
				if (m * 2 >= inc)
					newValue += inc;
				else if (m * 2 < -inc)
					newValue -= inc
			}
			return newValue.constrain(this.minValue,
				this.maxValue)
		},
		afterRender : function () {
			Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
			for (var i = 0; i < this.thumbs.length; i++) {
				var thumb = this.thumbs[i];
				if (thumb.value !== undefined) {
					var v = this.normalizeValue(thumb.value);
					if (v !== thumb.value)
						this.setValue(i, v, false);
					else
						this.moveThumb(i, 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) {
			v = this.doSnap(v);
			v = Ext.util.Format.round(v,
					this.decimalPrecision);
			v = v.constrain(this.minValue, this.maxValue);
			return v
		},
		setMinValue : function (val) {
			this.minValue = val;
			var i = 0;
			var thumbs = this.thumbs;
			var len = thumbs.length;
			for (var t; i < len; ++i) {
				t = thumbs[i];
				t.value = t.value < val ? val : t.value
			}
			this.syncThumb()
		},
		setMaxValue : function (val) {
			this.maxValue = val;
			var i = 0;
			var thumbs = this.thumbs;
			var len = thumbs.length;
			for (var t; i < len; ++i) {
				t = thumbs[i];
				t.value = t.value > val ? val : t.value
			}
			this.syncThumb()
		},
		setValue : function (index, v, animate, changeComplete) {
			var thumb = this.thumbs[index];
			var el = thumb.el;
			v = this.normalizeValue(v);
			if (v !== thumb.value && this.fireEvent("beforechange", this, v, thumb.value, thumb) !== false) {
				thumb.value = v;
				if (this.rendered) {
					this.moveThumb(index, this.translateValue(v), animate !== false);
					this.fireEvent("change", this, v, thumb);
					if (changeComplete)
						this.fireEvent("changecomplete", this, v, thumb)
				}
			}
		},
		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.minValue *
				ratio) / ratio
		},
		moveThumb : function (index, v, animate) {
			var thumb = this.thumbs[index].el;
			if (!animate || this.animate === false)
				thumb.setLeft(v);
			else
				thumb.shift({
					left : v,
					stopFx : true,
					duration : 0.35
				})
		},
		focus : function () {
			this.focusEl.focus(10)
		},
		onResize : function (w, h) {
			var thumbs = this.thumbs;
			var len = thumbs.length;
			for (var i = 0; i < len; ++i)
				thumbs[i].el.stopFx();
			if (Ext.isNumber(w))
				this.innerEl.setWidth(w - (this.el.getPadding("l") + this.endEl.getPadding("r")));
			this.syncThumb();
			Ext.slider.MultiSlider.superclass.onResize.apply(this,
				arguments)
		},
		onDisable : function () {
			Ext.slider.MultiSlider.superclass.onDisable.call(this);
			for (var i = 0; i < this.thumbs.length; i++) {
				var thumb = this.thumbs[i];
				var el = thumb.el;
				thumb.disable();
				if (Ext.isIE) {
					var xy = el.getXY();
					el.hide();
					this.innerEl.addClass(this.disabledClass).dom.disabled = true;
					if (!this.thumbHolder)
						this.thumbHolder = this.endEl.createChild({
								cls : "x-slider-thumb " + this.disabledClass
							});
					this.thumbHolder.show().setXY(xy)
				}
			}
		},
		onEnable : function () {
			Ext.slider.MultiSlider.superclass.onEnable.call(this);
			for (var i =
					0; i < this.thumbs.length; i++) {
				var thumb = this.thumbs[i];
				var el = thumb.el;
				thumb.enable();
				if (Ext.isIE) {
					this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
					if (this.thumbHolder)
						this.thumbHolder.hide();
					el.show();
					this.syncThumb()
				}
			}
		},
		syncThumb : function () {
			if (this.rendered)
				for (var i = 0; i < this.thumbs.length; i++)
					this.moveThumb(i, this.translateValue(this.thumbs[i].value))
		},
		getValue : function (index) {
			return this.thumbs[index].value
		},
		getValues : function () {
			var values = [];
			for (var i = 0; i < this.thumbs.length; i++)
				values.push(this.thumbs[i].value);
			return values
		},
		beforeDestroy : function () {
			var thumbs = this.thumbs;
			var i = 0;
			for (var len = thumbs.length; i < len; ++i) {
				thumbs[i].destroy();
				thumbs[i] = null
			}
			Ext.destroyMembers(this, "endEl", "innerEl", "focusEl", "thumbHolder");
			Ext.slider.MultiSlider.superclass.beforeDestroy.call(this)
		}
	});
Ext.reg("multislider", Ext.slider.MultiSlider);
Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
		constructor : function (config) {
			config = config || {};
			Ext.applyIf(config, {
				values : [config.value || 0]
			});
			Ext.slider.SingleSlider.superclass.constructor.call(this, config)
		},
		getValue : function () {
			return Ext.slider.SingleSlider.superclass.getValue.call(this, 0)
		},
		setValue : function (value, animate) {
			var args = Ext.toArray(arguments);
			var len = args.length;
			if (len == 1 || len <= 3 && typeof arguments[1] != "number")
				args.unshift(0);
			return Ext.slider.SingleSlider.superclass.setValue.apply(this,
				args)
		},
		syncThumb : function () {
			return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments))
		},
		getNearest : function () {
			return this.thumbs[0]
		}
	});
Ext.Slider = Ext.slider.SingleSlider;
Ext.reg("slider", Ext.slider.SingleSlider);
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 (index, v, animate) {
		var thumb = this.thumbs[index];
		var el = thumb.el;
		if (!animate || this.animate === false)
			el.setBottom(v);
		else
			el.shift({
				bottom : v,
				stopFx : true,
				duration : 0.35
			})
	},
	onClickChange : function (local) {
		if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
			var thumb =
				this.getNearest(local, "top");
			var index = thumb.index;
			var value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
			this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true)
		}
	}
};
Ext.slider.Thumb.Vertical = {
	getNewValue : function () {
		var slider = this.slider;
		var innerEl = slider.innerEl;
		var pos = innerEl.translatePoints(this.tracker.getXY());
		var bottom = innerEl.getHeight() - pos.top;
		return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision)
	}
};
Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
		baseCls : "x-progress",
		animate : false,
		waitTimer : null,
		initComponent : function () {
			Ext.ProgressBar.superclass.initComponent.call(this);
			this.addEvents("update")
		},
		onRender : function (ct, position) {
			var tpl = new Ext.Template('\x3cdiv class\x3d"{cls}-wrap"\x3e', '\x3cdiv class\x3d"{cls}-inner"\x3e', '\x3cdiv class\x3d"{cls}-bar"\x3e', '\x3cdiv class\x3d"{cls}-text"\x3e', "\x3cdiv\x3e\x26#160;\x3c/div\x3e", "\x3c/div\x3e", "\x3c/div\x3e", '\x3cdiv class\x3d"{cls}-text {cls}-text-back"\x3e',
					"\x3cdiv\x3e\x26#160;\x3c/div\x3e", "\x3c/div\x3e", "\x3c/div\x3e", "\x3c/div\x3e");
			this.el = position ? tpl.insertBefore(position, {
					cls : this.baseCls
				}, true) : 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, animate) {
			this.value = value || 0;
			if (text)
				this.updateText(text);
			if (this.rendered && !this.isDestroyed) {
				var w =
					Math.floor(value * this.el.dom.firstChild.offsetWidth);
				this.progressBar.setWidth(w, animate === true || animate !== false && this.animate);
				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;
							i -= 1;
							this.updateProgress(((i + inc) % inc + 1) * (100 / inc) * 0.01, null, o.animate)
						},
						interval : o.interval ||
						1E3,
						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 || "\x26#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");
			this.clearTimer();
			if (hide === true)
				this.hide();
			return this
		},
		clearTimer : function () {
			if (this.waitTimer) {
				this.waitTimer.onStop = null;
				Ext.TaskMgr.stop(this.waitTimer);
				this.waitTimer = null
			}
		},
		onDestroy : function () {
			this.clearTimer();
			if (this.rendered) {
				if (this.textEl.isComposite)
					this.textEl.clear();
				Ext.destroyMembers(this,
					"textEl", "progressBar", "textTopEl")
			}
			Ext.ProgressBar.superclass.onDestroy.call(this)
		}
	});
Ext.reg("progress", Ext.ProgressBar);
(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
		},
		moveOnly : false,
		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 (Ext.isNumber(pad))
				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;
			var 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],
					y : xy[1],
					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) {
			var i = 0;
			for (var 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];
			var i = 0;
			for (var 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 {
				var i = 0;
				for (var 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] && 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 (var 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);
				var i = 0;
				for (var 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.ddDisable();
				if (this.dragCurrent)
					this.handleMouseUp(e);
				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.ddEnable();
				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 || dc.ignoreSelf ===
								false))
							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();
				var pos;
				var x1;
				var x2;
				var y1;
				var y2;
				var t;
				var r;
				var b;
				var l;
				var region;
				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];
				region = new Ext.lib.Region(t, r, b, l);
				for (el = Ext.get(el.parentNode); el && region; ) {
					if (el.isScrollable())
						region =
							region.intersect(el.getRegion());
					el = el.parent()
				}
				return region
			},
			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) {
				Event.removeListener(document, "mouseup", this.handleMouseUp, this);
				Event.removeListener(document, "mousemove", this.handleMouseMove, this);
				Event.removeListener(window, "resize", this._onResize, this);
				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;
				var l;
				var dde = document.documentElement;
				var 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 > 2E3);
				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
					for (var p = node.parentNode; 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, {
	getDragEl : Ext.emptyFn,
	isValidHandleChild : Ext.emptyFn,
	startDrag : Ext.emptyFn,
	endDrag : Ext.emptyFn,
	onDrag : Ext.emptyFn,
	onDragDrop : Ext.emptyFn,
	onDragEnter : Ext.emptyFn,
	onDragOut : Ext.emptyFn,
	onDragOver : Ext.emptyFn,
	onInvalidDrop : Ext.emptyFn,
	onMouseDown : Ext.emptyFn,
	onMouseUp : Ext.emptyFn,
	setXConstraint : Ext.emptyFn,
	setYConstraint : Ext.emptyFn,
	resetConstraints : Ext.emptyFn,
	clearConstraints : Ext.emptyFn,
	clearTicks : Ext.emptyFn,
	setInitPosition : Ext.emptyFn,
	setDragElId : Ext.emptyFn,
	setHandleElId : Ext.emptyFn,
	setOuterHandleElId : Ext.emptyFn,
	addInvalidHandleClass : Ext.emptyFn,
	addInvalidHandleId : Ext.emptyFn,
	addInvalidHandleType : Ext.emptyFn,
	removeInvalidHandleClass : Ext.emptyFn,
	removeInvalidHandleId : Ext.emptyFn,
	removeInvalidHandleType : Ext.emptyFn,
	toString : function () {
		return "DDTarget " + this.id
	}
});
Ext.dd.DragTracker = Ext.extend(Ext.util.Observable, {
		active : false,
		tolerance : 5,
		autoStart : false,
		constructor : 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.dd.DragTracker.superclass.constructor.call(this, config)
		},
		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);
			delete this.el
		},
		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;
				if (this.preventDefault !== false)
					e.preventDefault();
				Ext.getDoc().on({
					scope : this,
					mouseup : this.onMouseUp,
					mousemove : this.onMouseMove,
					selectstart : this.stopSelect
				});
				if (this.autoStart)
					this.timer = this.triggerStart.defer(this.autoStart === true ? 1E3 : this.autoStart, this, [e])
			}
		},
		onMouseMove : function (e,
			target) {
			if (this.active && Ext.isIE && !e.browserEvent.button) {
				e.preventDefault();
				this.onMouseUp(e);
				return
			}
			e.preventDefault();
			var xy = e.getXY();
			var 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(e);
				else
					return;
			this.fireEvent("mousemove", this, e);
			this.onDrag(e);
			this.fireEvent("drag", this, e)
		},
		onMouseUp : function (e) {
			var doc = Ext.getDoc();
			var wasActive = this.active;
			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);
			if (wasActive) {
				this.onEnd(e);
				this.fireEvent("dragend", this, e)
			}
		},
		triggerStart : function (e) {
			this.clearStart();
			this.active = true;
			this.onStart(e);
			this.fireEvent("dragstart", this, e)
		},
		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 group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined;
		var freq = el.ddScrollConfig && el.ddScrollConfig.frequency ? el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
		if (group === undefined || ddm.dragCurrent.ddGroup == group)
			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];
			var 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)) {
				var i = 0;
				for (var 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)) {
				var i = 0;
				for (var 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 : 0.4,
		ddGroup : undefined,
		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;
				var i = 0;
				for (var 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;
					var i = 0;
					for (var 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("float", "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 || 0.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
	},
	destroy : function () {
		Ext.destroy(this.ghost, this.el)
	}
};
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)
	},
	destroy : function () {
		Ext.dd.DragSource.superclass.destroy.call(this);
		Ext.destroy(this.proxy)
	}
});
Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {
		constructor : 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
			})
		},
		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
		},
		destroy : function () {
			Ext.dd.DropTarget.superclass.destroy.call(this);
			if (this.containerScroll)
				Ext.dd.ScrollManager.unregister(this.el)
		}
	});
Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {
		constructor : function (el, config) {
			Ext.dd.DragZone.superclass.constructor.call(this, el, config);
			if (this.containerScroll)
				Ext.dd.ScrollManager.register(this.el)
		},
		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()
		},
		destroy : function () {
			Ext.dd.DragZone.superclass.destroy.call(this);
			if (this.containerScroll)
				Ext.dd.ScrollManager.unregister(this.el)
		}
	});
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.Element.addMethods({
	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)
	}
});
Ext.data.Api = function () {
	var validActions = {};
	return {
		actions : {
			create : "create",
			read : "read",
			update : "update",
			destroy : "destroy"
		},
		restActions : {
			create : "POST",
			read : "GET",
			update : "PUT",
			destroy : "DELETE"
		},
		isAction : function (action) {
			return Ext.data.Api.actions[action] ? true : false
		},
		getVerb : function (name) {
			if (validActions[name])
				return validActions[name];
			for (var verb in this.actions)
				if (this.actions[verb] === name) {
					validActions[name] = verb;
					break
				}
			return validActions[name] !== undefined ? validActions[name] : null
		},
		isValid : function (api) {
			var invalid =
				[];
			var crud = this.actions;
			for (var action in api)
				if (!(action in crud))
					invalid.push(action);
			return !invalid.length ? true : invalid
		},
		hasUniqueUrl : function (proxy, verb) {
			var url = proxy.api[verb] ? proxy.api[verb].url : null;
			var unique = true;
			for (var action in proxy.api)
				if ((unique = action === verb ? true : proxy.api[action].url != url ? true : false) === false)
					break;
			return unique
		},
		prepare : function (proxy) {
			if (!proxy.api)
				proxy.api = {};
			for (var verb in this.actions) {
				var action = this.actions[verb];
				proxy.api[action] = proxy.api[action] || proxy.url ||
					proxy.directFn;
				if (typeof proxy.api[action] == "string")
					proxy.api[action] = {
						url : proxy.api[action],
						method : proxy.restful === true ? Ext.data.Api.restActions[action] : undefined
					}
			}
		},
		restify : function (proxy) {
			proxy.restful = true;
			for (var verb in this.restActions)
				proxy.api[this.actions[verb]].method || (proxy.api[this.actions[verb]].method = this.restActions[verb]);
			proxy.onWrite = proxy.onWrite.createInterceptor(function (action, o, response, rs) {
					var reader = o.reader;
					var res = new Ext.data.Response({
							action : action,
							raw : response
						});
					switch (response.status) {
					case 200:
						return true;
						break;
					case 201:
						if (Ext.isEmpty(res.raw.responseText))
							res.success = true;
						else
							return true;
						break;
					case 204:
						res.success = true;
						res.data = null;
						break;
					default:
						return true;
						break
					}
					if (res.success === true)
						this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
					else
						this.fireEvent("exception", this, "remote", action, o, res, rs);
					o.request.callback.call(o.request.scope, res.data, res, res.success);
					return false
				}, proxy)
		}
	}
}
();
Ext.data.Response = function (params, response) {
	Ext.apply(this, params, {
		raw : response
	})
};
Ext.data.Response.prototype = {
	message : null,
	success : false,
	status : null,
	root : null,
	raw : null,
	getMessage : function () {
		return this.message
	},
	getSuccess : function () {
		return this.success
	},
	getStatus : function () {
		return this.status
	},
	getRoot : function () {
		return this.root
	},
	getRawResponse : function () {
		return this.raw
	}
};
Ext.data.Api.Error = Ext.extend(Ext.Error, {
		constructor : function (message, arg) {
			this.arg = arg;
			Ext.Error.call(this, message)
		},
		name : "Ext.data.Api"
	});
Ext.apply(Ext.data.Api.Error.prototype, {
	lang : {
		"action-url-undefined" : "No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.",
		"invalid" : "received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions",
		"invalid-url" : "Invalid url.  Please review your proxy configuration.",
		"execute" : 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
	}
});
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, ""));
		return isNaN(val) ? 0 : val
	},
	asInt : function (s) {
		var val = parseInt(String(s).replace(/,/g,
					""), 10);
		return isNaN(val) ? 0 : val
	}
};
Ext.data.Record = function (data, id) {
	this.id = id || id === 0 ? id : Ext.data.Record.id(this);
	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
		});
	var i = 0;
	for (var 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.PREFIX = "ext-record";
Ext.data.Record.AUTO_ID = 1;
Ext.data.Record.EDIT = "edit";
Ext.data.Record.REJECT = "reject";
Ext.data.Record.COMMIT = "commit";
Ext.data.Record.id = function (rec) {
	rec.phantom = true;
	return [Ext.data.Record.PREFIX, "-", Ext.data.Record.AUTO_ID++].join("")
};
Ext.data.Record.prototype = {
	dirty : false,
	editing : false,
	error : null,
	modified : null,
	phantom : false,
	join : function (store) {
		this.store = store
	},
	set : function (name, value) {
		var encode = Ext.isPrimitive(value) ? String : Ext.encode;
		if (encode(this.data[name]) == encode(value))
			return;
		this.dirty = true;
		if (!this.modified)
			this.modified = {};
		if (this.modified[name] === undefined)
			this.modified[name] = this.data[name];
		this.data[name] = value;
		if (!this.editing)
			this.afterEdit()
	},
	afterEdit : function () {
		if (this.store != undefined && typeof this.store.afterEdit ==
			"function")
			this.store.afterEdit(this)
	},
	afterReject : function () {
		if (this.store)
			this.store.afterReject(this)
	},
	afterCommit : function () {
		if (this.store)
			this.store.afterCommit(this)
	},
	get : function (name) {
		return this.data[name]
	},
	beginEdit : function () {
		this.editing = true;
		this.modified = this.modified || {}

	},
	cancelEdit : function () {
		this.editing = false;
		delete this.modified
	},
	endEdit : function () {
		this.editing = false;
		if (this.dirty)
			this.afterEdit()
	},
	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 (silent !== true)
			this.afterReject()
	},
	commit : function (silent) {
		this.dirty = false;
		delete this.modified;
		this.editing = false;
		if (silent !== true)
			this.afterCommit()
	},
	getChanges : function () {
		var m = this.modified;
		var 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))
	},
	isValid : function () {
		return this.fields.find(function (f) {
			return f.allowBlank === false && Ext.isEmpty(this.data[f.name]) ? true : false
		}, this) ? false : true
	},
	markDirty : function () {
		this.dirty = true;
		if (!this.modified)
			this.modified = {};
		this.fields.each(function (f) {
			this.modified[f.name] = this.data[f.name]
		}, this)
	}
};
Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection, {
		register : function () {
			var i = 0;
			for (var s; s = arguments[i]; i++)
				this.add(s)
		},
		unregister : function () {
			var i = 0;
			for (var s; s = arguments[i]; i++)
				this.remove(this.lookup(s))
		},
		lookup : function (id) {
			if (Ext.isArray(id)) {
				var fields = ["field1"];
				var expand = !Ext.isArray(id[0]);
				if (!expand) {
					var i = 2;
					for (var len = id[0].length; i <= len; ++i)
						fields.push("field" + i)
				}
				return new Ext.data.ArrayStore({
					fields : fields,
					data : id,
					expandData : expand,
					autoDestroy : true,
					autoCreated : true
				})
			}
			return Ext.isObject(id) ?
			id.events ? id : Ext.create(id, "store") : this.get(id)
		},
		getKey : function (o) {
			return o.storeId
		}
	});
Ext.data.Store = Ext.extend(Ext.util.Observable, {
		writer : undefined,
		remoteSort : false,
		autoDestroy : false,
		pruneModifiedRecords : false,
		lastOptions : null,
		autoSave : true,
		batch : true,
		restful : false,
		paramNames : undefined,
		defaultParamNames : {
			start : "start",
			limit : "limit",
			sort : "sort",
			dir : "dir"
		},
		isDestroyed : false,
		hasMultiSort : false,
		batchKey : "_ext_batch_",
		constructor : function (config) {
			this.data = new Ext.util.MixedCollection(false);
			this.data.getKey = function (o) {
				return o.id
			};
			this.removed = [];
			if (config && config.data) {
				this.inlineData =
					config.data;
				delete config.data
			}
			Ext.apply(this, config);
			this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
			this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
			if ((this.url || this.api) && !this.proxy)
				this.proxy = new Ext.data.HttpProxy({
						url : this.url,
						api : this.api
					});
			if (this.restful === true && this.proxy) {
				this.batch = false;
				Ext.data.Api.restify(this.proxy)
			}
			if (this.reader) {
				if (!this.recordType)
					this.recordType = this.reader.recordType;
				if (this.reader.onMetaChange)
					this.reader.onMetaChange =
						this.reader.onMetaChange.createSequence(this.onMetaChange, this);
				if (this.writer) {
					if (this.writer instanceof Ext.data.DataWriter === false)
						this.writer = this.buildWriter(this.writer);
					this.writer.meta = this.reader.meta;
					this.pruneModifiedRecords = true
				}
			}
			if (this.recordType)
				this.fields = this.recordType.prototype.fields;
			this.modified = [];
			this.addEvents("datachanged", "metachange", "add", "remove", "update", "clear", "exception", "beforeload", "load", "loadexception", "beforewrite", "write", "beforesave", "save");
			if (this.proxy)
				this.relayEvents(this.proxy,
					["loadexception", "exception"]);
			if (this.writer)
				this.on({
					scope : this,
					add : this.createRecords,
					remove : this.destroyRecord,
					update : this.updateRecord,
					clear : this.onClear
				});
			this.sortToggle = {};
			if (this.sortField)
				this.setDefaultSort(this.sortField, this.sortDir);
			else if (this.sortInfo)
				this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
			Ext.data.Store.superclass.constructor.call(this);
			if (this.id) {
				this.storeId = this.id;
				delete this.id
			}
			if (this.storeId)
				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]);
			this.batchCounter = 0;
			this.batches = {}

		},
		buildWriter : function (config) {
			var klass = undefined;
			var type = (config.format || "json").toLowerCase();
			switch (type) {
			case "json":
				klass = Ext.data.JsonWriter;
				break;
			case "xml":
				klass = Ext.data.XmlWriter;
				break;
			default:
				klass = Ext.data.JsonWriter
			}
			return new klass(config)
		},
		destroy : function () {
			if (!this.isDestroyed) {
				if (this.storeId)
					Ext.StoreMgr.unregister(this);
				this.clearData();
				this.data = null;
				Ext.destroy(this.proxy);
				this.reader = this.writer = null;
				this.purgeListeners();
				this.isDestroyed = true
			}
		},
		add : function (records) {
			var i;
			var len;
			var record;
			var index;
			records = [].concat(records);
			if (records.length < 1)
				return;
			for (i = 0, len = records.length; i < len; i++) {
				record = records[i];
				record.join(this);
				if (record.dirty || record.phantom)
					this.modified.push(record)
			}
			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)
		},
		doUpdate : function (rec) {
			var id = rec.id;
			this.getById(id).join(null);
			this.data.replace(id, rec);
			if (this.snapshot)
				this.snapshot.replace(id, rec);
			rec.join(this);
			this.fireEvent("update", this, rec, Ext.data.Record.COMMIT)
		},
		remove : function (record) {
			if (Ext.isArray(record)) {
				Ext.each(record, function (r) {
					this.remove(r)
				}, this);
				return
			}
			var index = this.data.indexOf(record);
			if (index > -1) {
				record.join(null);
				this.data.removeAt(index)
			}
			if (this.pruneModifiedRecords)
				this.modified.remove(record);
			if (this.snapshot)
				this.snapshot.remove(record);
			if (index > -1)
				this.fireEvent("remove", this, record, index)
		},
		removeAt : function (index) {
			this.remove(this.getAt(index))
		},
		removeAll : function (silent) {
			var items = [];
			this.each(function (rec) {
				items.push(rec)
			});
			this.clearData();
			if (this.snapshot)
				this.snapshot.clear();
			if (this.pruneModifiedRecords)
				this.modified = [];
			if (silent !== true)
				this.fireEvent("clear", this, items)
		},
		onClear : function (store, records) {
			Ext.each(records, function (rec, index) {
				this.destroyRecord(this, rec, index)
			},
				this)
		},
		insert : function (index, records) {
			var i;
			var len;
			var record;
			records = [].concat(records);
			for (i = 0, len = records.length; i < len; i++) {
				record = records[i];
				this.data.insert(index + i, record);
				record.join(this);
				if (record.dirty || record.phantom)
					this.modified.push(record)
			}
			if (this.snapshot)
				this.snapshot.addAll(records);
			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.snapshot ||
				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
		},
		clearData : function () {
			this.data.each(function (rec) {
				rec.join(null)
			});
			this.data.clear()
		},
		load : function (options) {
			options = Ext.apply({}, options);
			this.storeOptions(options);
			if (this.sortInfo && this.remoteSort) {
				var pn = this.paramNames;
				options.params = Ext.apply({}, options.params);
				options.params[pn.sort] = this.sortInfo.field;
				options.params[pn.dir] = this.sortInfo.direction
			}
			try {
				return this.execute("read", null, options)
			} catch (e) {
				this.handleException(e);
				return false
			}
		},
		updateRecord : function (store, record, action) {
			if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || record.phantom && record.isValid()))
				this.save()
		},
		createRecords : function (store, records, index) {
			var modified = this.modified;
			var length = records.length;
			var record;
			var i;
			for (i = 0; i < length; i++) {
				record = records[i];
				if (record.phantom && record.isValid()) {
					record.markDirty();
					if (modified.indexOf(record) == -1)
						modified.push(record)
				}
			}
			if (this.autoSave === true)
				this.save()
		},
		destroyRecord : function (store, record, index) {
			if (this.modified.indexOf(record) != -1)
				this.modified.remove(record);
			if (!record.phantom) {
				this.removed.push(record);
				record.lastIndex = index;
				if (this.autoSave === true)
					this.save()
			}
		},
		execute : function (action, rs, options, batch) {
			if (!Ext.data.Api.isAction(action))
				throw new Ext.data.Api.Error("execute", action);
			options = Ext.applyIf(options || {}, {
					params : {}

				});
			if (batch !== undefined)
				this.addToBatch(batch);
			var doRequest = true;
			if (action === "read") {
				doRequest = this.fireEvent("beforeload", this, options);
				Ext.applyIf(options.params, this.baseParams)
			} else {
				if (this.writer.listful === true && this.restful !== true)
					rs = Ext.isArray(rs) ? rs : [rs];
				else if (Ext.isArray(rs) && rs.length == 1)
					rs = rs.shift();
				if ((doRequest = this.fireEvent("beforewrite", this, action, rs, options)) !== false)
					this.writer.apply(options.params, this.baseParams, action, rs)
			}
			if (doRequest !== false) {
				if (this.writer &&
					this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action))
					options.params.xaction = action;
				this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options)
			}
			return doRequest
		},
		save : function () {
			if (!this.writer)
				throw new Ext.data.Store.Error("writer-undefined");
			var queue = [];
			var len;
			var trans;
			var batch;
			var data = {};
			var i;
			if (this.removed.length)
				queue.push(["destroy", this.removed]);
			var rs = [].concat(this.getModifiedRecords());
			if (rs.length) {
				var phantoms = [];
				for (i = rs.length - 1; i >= 0; i--)
					if (rs[i].phantom === true) {
						var rec = rs.splice(i, 1).shift();
						if (rec.isValid())
							phantoms.push(rec)
					} else if (!rs[i].isValid())
						rs.splice(i, 1);
				if (phantoms.length)
					queue.push(["create", phantoms]);
				if (rs.length)
					queue.push(["update", rs])
			}
			len = queue.length;
			if (len) {
				batch = ++this.batchCounter;
				for (i = 0; i < len; ++i) {
					trans = queue[i];
					data[trans[0]] = trans[1]
				}
				if (this.fireEvent("beforesave", this, data) !== false) {
					for (i = 0; i < len; ++i) {
						trans = queue[i];
						this.doTransaction(trans[0],
							trans[1], batch)
					}
					return batch
				}
			}
			return -1
		},
		doTransaction : function (action, rs, batch) {
			function transaction(records) {
				try {
					this.execute(action, records, undefined, batch)
				} catch (e) {
					this.handleException(e)
				}
			}
			if (this.batch === false) {
				var i = 0;
				for (var len = rs.length; i < len; i++)
					transaction.call(this, rs[i])
			} else
				transaction.call(this, rs)
		},
		addToBatch : function (batch) {
			var b = this.batches;
			var key = this.batchKey + batch;
			var o = b[key];
			if (!o)
				b[key] = o = {
					id : batch,
					count : 0,
					data : {}

				};
			++o.count
		},
		removeFromBatch : function (batch, action, data) {
			var b =
				this.batches;
			var key = this.batchKey + batch;
			var o = b[key];
			var arr;
			if (o) {
				arr = o.data[action] || [];
				o.data[action] = arr.concat(data);
				if (o.count === 1) {
					data = o.data;
					delete b[key];
					this.fireEvent("save", this, batch, data)
				} else --o.count
			}
		},
		createCallback : function (action, rs, batch) {
			var actions = Ext.data.Api.actions;
			return action == "read" ? this.loadRecords : function (data, response, success) {
				this["on" + Ext.util.Format.capitalize(action) + "Records"](success, rs, [].concat(data));
				if (success === true)
					this.fireEvent("write", this, action,
						data, response, rs);
				this.removeFromBatch(batch, action, data)
			}
		},
		clearModified : function (rs) {
			if (Ext.isArray(rs))
				for (var n = rs.length - 1; n >= 0; n--)
					this.modified.splice(this.modified.indexOf(rs[n]), 1);
			else
				this.modified.splice(this.modified.indexOf(rs), 1)
		},
		reMap : function (record) {
			if (Ext.isArray(record)) {
				var i = 0;
				for (var len = record.length; i < len; i++)
					this.reMap(record[i])
			} else {
				delete this.data.map[record._phid];
				this.data.map[record.id] = record;
				var index = this.data.keys.indexOf(record._phid);
				this.data.keys.splice(index,
					1, record.id);
				delete record._phid
			}
		},
		onCreateRecords : function (success, rs, data) {
			if (success === true)
				try {
					this.reader.realize(rs, data)
				} catch (e) {
					this.handleException(e);
					if (Ext.isArray(rs))
						this.onCreateRecords(success, rs, data)
				}
		},
		onUpdateRecords : function (success, rs, data) {
			if (success === true)
				try {
					this.reader.update(rs, data)
				} catch (e) {
					this.handleException(e);
					if (Ext.isArray(rs))
						this.onUpdateRecords(success, rs, data)
				}
		},
		onDestroyRecords : function (success, rs, data) {
			rs = rs instanceof Ext.data.Record ? [rs] : [].concat(rs);
			var i =
				0;
			for (var len = rs.length; i < len; i++)
				this.removed.splice(this.removed.indexOf(rs[i]), 1);
			if (success === false)
				for (i = rs.length - 1; i >= 0; i--)
					this.insert(rs[i].lastIndex, rs[i])
		},
		handleException : function (e) {
			Ext.handleError(e)
		},
		reload : function (options) {
			this.load(Ext.applyIf(options || {}, this.lastOptions))
		},
		loadRecords : function (o, options, success) {
			var i;
			var len;
			if (this.isDestroyed === true)
				return;
			if (!o || success === false) {
				if (success !== false)
					this.fireEvent("load", this, [], options);
				if (options.callback)
					options.callback.call(options.scope ||
						this, [], options, false, o);
				return
			}
			var r = o.records;
			var t = o.totalRecords || r.length;
			if (!options || options.add !== true) {
				if (this.pruneModifiedRecords)
					this.modified = [];
				for (i = 0, len = r.length; i < len; i++)
					r[i].join(this);
				if (this.snapshot) {
					this.data = this.snapshot;
					delete this.snapshot
				}
				this.clearData();
				this.data.addAll(r);
				this.totalLength = t;
				this.applySort();
				this.fireEvent("datachanged", this)
			} else {
				var toAdd = [];
				var rec;
				var cnt = 0;
				for (i = 0, len = r.length; i < len; ++i) {
					rec = r[i];
					if (this.indexOfId(rec.id) > -1)
						this.doUpdate(rec);
					else {
						toAdd.push(rec);
						++cnt
					}
				}
				this.totalLength = Math.max(t, this.data.length + cnt);
				this.add(toAdd)
			}
			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.multiSortInfo) &&
				!this.remoteSort)
				this.sortData()
		},
		sortData : function () {
			var sortInfo = this.hasMultiSort ? this.multiSortInfo : this.sortInfo;
			var direction = sortInfo.direction || "ASC";
			var sorters = sortInfo.sorters;
			var sortFns = [];
			if (!this.hasMultiSort)
				sorters = [{
						direction : direction,
						field : sortInfo.field
					}
				];
			var i$$0 = 0;
			for (var j$$0 = sorters.length; i$$0 < j$$0; i$$0++)
				sortFns.push(this.createSortFunction(sorters[i$$0].field, sorters[i$$0].direction));
			if (sortFns.length == 0)
				return;
			var directionModifier = direction.toUpperCase() == "DESC" ? -1 :
				1;
			var fn = function (r1, r2) {
				var result = sortFns[0].call(this, r1, r2);
				if (sortFns.length > 1) {
					var i = 1;
					for (var j = sortFns.length; i < j; i++)
						result = result || sortFns[i].call(this, r1, r2)
				}
				return directionModifier * result
			};
			this.data.sort(direction, fn);
			if (this.snapshot && this.snapshot != this.data)
				this.snapshot.sort(direction, fn)
		},
		createSortFunction : function (field, direction) {
			direction = direction || "ASC";
			var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
			var sortType = this.fields.get(field).sortType;
			return function (r1,
				r2) {
				var v1 = sortType(r1.data[field]);
				var v2 = sortType(r2.data[field]);
				return directionModifier * (v1 > v2 ? 1 : v1 < v2 ? -1 : 0)
			}
		},
		setDefaultSort : function (field, dir) {
			dir = dir ? dir.toUpperCase() : "ASC";
			this.sortInfo = {
				field : field,
				direction : dir
			};
			this.sortToggle[field] = dir
		},
		sort : function (fieldName, dir) {
			if (Ext.isArray(arguments[0]))
				return this.multiSort.call(this, fieldName, dir);
			else
				return this.singleSort(fieldName, dir)
		},
		singleSort : function (fieldName, dir) {
			var field = this.fields.get(fieldName);
			if (!field)
				return false;
			var name =
				field.name;
			var sortInfo = this.sortInfo || null;
			var sortToggle = this.sortToggle ? this.sortToggle[name] : null;
			if (!dir)
				if (sortInfo && sortInfo.field == name)
					dir = (this.sortToggle[name] || "ASC").toggle("ASC", "DESC");
				else
					dir = field.sortDir;
			this.sortToggle[name] = dir;
			this.sortInfo = {
				field : name,
				direction : dir
			};
			this.hasMultiSort = false;
			if (this.remoteSort) {
				if (!this.load(this.lastOptions)) {
					if (sortToggle)
						this.sortToggle[name] = sortToggle;
					if (sortInfo)
						this.sortInfo = sortInfo
				}
			} else {
				this.applySort();
				this.fireEvent("datachanged",
					this)
			}
			return true
		},
		multiSort : function (sorters, direction) {
			this.hasMultiSort = true;
			direction = direction || "ASC";
			if (this.multiSortInfo && direction == this.multiSortInfo.direction)
				direction = direction.toggle("ASC", "DESC");
			this.multiSortInfo = {
				sorters : sorters,
				direction : direction
			};
			if (this.remoteSort)
				this.singleSort(sorters[0].field, sorters[0].direction);
			else {
				this.applySort();
				this.fireEvent("datachanged", this)
			}
		},
		each : function (fn, scope) {
			this.data.each(fn, scope)
		},
		getModifiedRecords : function () {
			return this.modified
		},
		sum : function (property, start, end) {
			var rs = this.data.items;
			var 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
		},
		createFilterFn : function (property, value, anyMatch, caseSensitive, exactMatch) {
			if (Ext.isEmpty(value, false))
				return false;
			value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
			return function (r) {
				return value.test(r.data[property])
			}
		},
		createMultipleFilterFn : function (filters) {
			return function (record) {
				var isMatch =
					true;
				var i = 0;
				for (var j = filters.length; i < j; i++) {
					var filter = filters[i];
					var fn = filter.fn;
					var scope = filter.scope;
					isMatch = isMatch && fn.call(scope, record)
				}
				return isMatch
			}
		},
		filter : function (property, value, anyMatch, caseSensitive, exactMatch) {
			var fn;
			if (Ext.isObject(property))
				property = [property];
			if (Ext.isArray(property)) {
				var filters = [];
				var i = 0;
				for (var j = property.length; i < j; i++) {
					var filter = property[i];
					var func = filter.fn;
					var scope = filter.scope || this;
					if (!Ext.isFunction(func))
						func = this.createFilterFn(filter.property,
								filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
					filters.push({
						fn : func,
						scope : scope
					})
				}
				fn = this.createMultipleFilterFn(filters)
			} else
				fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
			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)
		},
		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
		},
		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
		},
		findExact : function (property, value, start) {
			return this.data.findIndexBy(function (rec) {
				return rec.get(property) === value
			}, this, start)
		},
		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;
			var sv;
			var r = [];
			var l = {};
			var i = 0;
			for (var 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
		},
		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 modified =
				this.modified.slice(0);
			var length = modified.length;
			var i;
			for (i = 0; i < length; i++)
				modified[i].commit();
			this.modified = [];
			this.removed = []
		},
		rejectChanges : function () {
			var modified = this.modified.slice(0);
			var removed = this.removed.slice(0).reverse();
			var mLength = modified.length;
			var rLength = removed.length;
			var i;
			for (i = 0; i < mLength; i++)
				modified[i].reject();
			for (i = 0; i < rLength; i++) {
				this.insert(removed[i].lastIndex || 0, removed[i]);
				removed[i].reject()
			}
			this.modified = [];
			this.removed = []
		},
		onMetaChange : function (meta) {
			this.recordType =
				this.reader.recordType;
			this.fields = this.recordType.prototype.fields;
			delete this.snapshot;
			if (this.reader.meta.sortInfo)
				this.sortInfo = this.reader.meta.sortInfo;
			else if (this.sortInfo && !this.fields.get(this.sortInfo.field))
				delete this.sortInfo;
			if (this.writer)
				this.writer.meta = this.reader.meta;
			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
		},
		setBaseParam : function (name, value) {
			this.baseParams = this.baseParams || {};
			this.baseParams[name] = value
		}
	});
Ext.reg("store", Ext.data.Store);
Ext.data.Store.Error = Ext.extend(Ext.Error, {
		name : "Ext.data.Store"
	});
Ext.apply(Ext.data.Store.Error.prototype, {
	lang : {
		"writer-undefined" : "Attempted to execute a write-action without a DataWriter installed."
	}
});
Ext.data.Field = Ext.extend(Object, {
		constructor : function (config) {
			if (Ext.isString(config))
				config = {
					name : config
				};
			Ext.apply(this, config);
			var types = Ext.data.Types;
			var st = this.sortType;
			var t;
			if (this.type) {
				if (Ext.isString(this.type))
					this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO
			} else
				this.type = types.AUTO;
			if (Ext.isString(st))
				this.sortType = Ext.data.SortTypes[st];
			else if (Ext.isEmpty(st))
				this.sortType = this.type.sortType;
			if (!this.convert)
				this.convert = this.type.convert
		},
		dateFormat : null,
		useNull : false,
		defaultValue : "",
		mapping : null,
		sortType : null,
		sortDir : "ASC",
		allowBlank : true
	});
Ext.data.DataReader = function (meta, recordType) {
	this.meta = meta;
	this.recordType = Ext.isArray(recordType) ? Ext.data.Record.create(recordType) : recordType;
	if (this.recordType)
		this.buildExtractors()
};
Ext.data.DataReader.prototype = {
	getTotal : Ext.emptyFn,
	getRoot : Ext.emptyFn,
	getMessage : Ext.emptyFn,
	getSuccess : Ext.emptyFn,
	getId : Ext.emptyFn,
	buildExtractors : Ext.emptyFn,
	extractValues : Ext.emptyFn,
	realize : function (rs, data) {
		if (Ext.isArray(rs))
			for (var i = rs.length - 1; i >= 0; i--)
				if (Ext.isArray(data))
					this.realize(rs.splice(i, 1).shift(), data.splice(i, 1).shift());
				else
					this.realize(rs.splice(i, 1).shift(), data);
		else {
			if (Ext.isArray(data) && data.length == 1)
				data = data.shift();
			if (!this.isData(data))
				throw new Ext.data.DataReader.Error("realize",
					rs);
			rs.phantom = false;
			rs._phid = rs.id;
			rs.id = this.getId(data);
			rs.data = data;
			rs.commit();
			rs.store.reMap(rs)
		}
	},
	update : function (rs, data) {
		if (Ext.isArray(rs))
			for (var i = rs.length - 1; i >= 0; i--)
				if (Ext.isArray(data))
					this.update(rs.splice(i, 1).shift(), data.splice(i, 1).shift());
				else
					this.update(rs.splice(i, 1).shift(), data);
		else {
			if (Ext.isArray(data) && data.length == 1)
				data = data.shift();
			if (this.isData(data))
				rs.data = Ext.apply(rs.data, data);
			rs.commit()
		}
	},
	extractData : function (root, returnRecords) {
		var rawName = this instanceof
			Ext.data.JsonReader ? "json" : "node";
		var rs = [];
		if (this.isData(root) && !(this instanceof Ext.data.XmlReader))
			root = [root];
		var f = this.recordType.prototype.fields;
		var fi = f.items;
		var fl = f.length;
		rs = [];
		if (returnRecords === true) {
			var Record = this.recordType;
			for (var i = 0; i < root.length; i++) {
				var n = root[i];
				var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
				record[rawName] = n;
				rs.push(record)
			}
		} else
			for (i = 0; i < root.length; i++) {
				var data = this.extractValues(root[i], fi, fl);
				data[this.meta.idProperty] = this.getId(root[i]);
				rs.push(data)
			}
		return rs
	},
	isData : function (data) {
		return data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data)) ? true : false
	},
	onMetaChange : function (meta) {
		delete this.ef;
		this.meta = meta;
		this.recordType = Ext.data.Record.create(meta.fields);
		this.buildExtractors()
	}
};
Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
		constructor : function (message, arg) {
			this.arg = arg;
			Ext.Error.call(this, message)
		},
		name : "Ext.data.DataReader"
	});
Ext.apply(Ext.data.DataReader.Error.prototype, {
	lang : {
		"update" : "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
		"realize" : "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
		"invalid-response" : "#readResponse received an invalid response from the server."
	}
});
Ext.data.DataWriter = function (config) {
	Ext.apply(this, config)
};
Ext.data.DataWriter.prototype = {
	writeAllFields : false,
	listful : false,
	apply : function (params, baseParams, action, rs) {
		var data = [];
		var renderer = action + "Record";
		if (Ext.isArray(rs))
			Ext.each(rs, function (rec) {
				data.push(this[renderer](rec))
			}, this);
		else if (rs instanceof Ext.data.Record)
			data = this[renderer](rs);
		this.render(params, baseParams, data)
	},
	render : Ext.emptyFn,
	updateRecord : Ext.emptyFn,
	createRecord : Ext.emptyFn,
	destroyRecord : Ext.emptyFn,
	toHash : function (rec, config) {
		var map = rec.fields.map;
		var data = {};
		var raw = this.writeAllFields ===
			false && rec.phantom === false ? rec.getChanges() : rec.data;
		var m;
		Ext.iterate(raw, function (prop, value) {
			if (m = map[prop])
				data[m.mapping ? m.mapping : m.name] = value
		});
		if (rec.phantom) {
			if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty]))
				delete data[this.meta.idProperty]
		} else
			data[this.meta.idProperty] = rec.id;
		return data
	},
	toArray : function (data) {
		var fields = [];
		Ext.iterate(data, function (k, v) {
			fields.push({
				name : k,
				value : v
			})
		}, this);
		return fields
	}
};
Ext.data.DataProxy = function (conn) {
	conn = conn || {};
	this.api = conn.api;
	this.url = conn.url;
	this.restful = conn.restful;
	this.listeners = conn.listeners;
	this.prettyUrls = conn.prettyUrls;
	this.addEvents("exception", "beforeload", "load", "loadexception", "beforewrite", "write");
	Ext.data.DataProxy.superclass.constructor.call(this);
	try {
		Ext.data.Api.prepare(this)
	} catch (e) {
		if (e instanceof Ext.data.Api.Error)
			e.toConsole()
	}
	Ext.data.DataProxy.relayEvents(this, ["beforewrite", "write", "exception"])
};
Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
	restful : false,
	setApi : function () {
		if (arguments.length == 1) {
			var valid = Ext.data.Api.isValid(arguments[0]);
			if (valid === true)
				this.api = arguments[0];
			else
				throw new Ext.data.Api.Error("invalid", valid);
		} else if (arguments.length == 2) {
			if (!Ext.data.Api.isAction(arguments[0]))
				throw new Ext.data.Api.Error("invalid", arguments[0]);
			this.api[arguments[0]] = arguments[1]
		}
		Ext.data.Api.prepare(this)
	},
	isApiAction : function (action) {
		return this.api[action] ? true : false
	},
	request : function (action,
		rs, params, reader, callback, scope, options) {
		if (!this.api[action] && !this.load)
			throw new Ext.data.DataProxy.Error("action-undefined", action);
		params = params || {};
		if (action === Ext.data.Api.actions.read ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false)
			this.doRequest.apply(this, arguments);
		else
			callback.call(scope || this, null, options, false)
	},
	load : null,
	doRequest : function (action, rs, params, reader, callback, scope, options) {
		this.load(params, reader, callback, scope, options)
	},
	onRead : Ext.emptyFn,
	onWrite : Ext.emptyFn,
	buildUrl : function (action, record) {
		record = record || null;
		var url = this.conn && this.conn.url ? this.conn.url : this.api[action] ? this.api[action].url : this.url;
		if (!url)
			throw new Ext.data.Api.Error("invalid-url", action);
		var provides = null;
		var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
		if (m) {
			provides = m[2];
			url = m[1]
		}
		if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom)
			url += "/" + record.id;
		return provides === null ? url : url + provides
	},
	destroy : function () {
		this.purgeListeners()
	}
});
Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
Ext.util.Observable.call(Ext.data.DataProxy);
Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
		constructor : function (message, arg) {
			this.arg = arg;
			Ext.Error.call(this, message)
		},
		name : "Ext.data.DataProxy"
	});
Ext.apply(Ext.data.DataProxy.Error.prototype, {
	lang : {
		"action-undefined" : "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
		"api-invalid" : "Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions."
	}
});
Ext.data.Request = function (params) {
	Ext.apply(this, params)
};
Ext.data.Request.prototype = {
	action : undefined,
	rs : undefined,
	params : undefined,
	callback : Ext.emptyFn,
	scope : undefined,
	reader : undefined
};
Ext.data.Response = function (params) {
	Ext.apply(this, params)
};
Ext.data.Response.prototype = {
	action : undefined,
	success : undefined,
	message : undefined,
	data : undefined,
	raw : undefined,
	records : undefined
};
Ext.data.ScriptTagProxy = function (config) {
	Ext.apply(this, config);
	Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
	this.head = document.getElementsByTagName("head")[0]
};
Ext.data.ScriptTagProxy.TRANS_ID = 1E3;
Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
	timeout : 3E4,
	callbackParam : "callback",
	nocache : true,
	doRequest : function (action, rs, params, reader, callback, scope, arg) {
		var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
		var url = this.buildUrl(action, rs);
		if (!url)
			throw new Ext.data.Api.Error("invalid-url", url);
		url = Ext.urlAppend(url, p);
		if (this.nocache)
			url = Ext.urlAppend(url, "_dc\x3d" + (new Date).getTime());
		var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
		var trans = {
			id : transId,
			action : action,
			cb : "stcCallback" +
			transId,
			scriptId : "stcScript" + transId,
			params : params,
			arg : arg,
			url : url,
			callback : callback,
			scope : scope,
			reader : reader
		};
		window[trans.cb] = this.createCallback(action, rs, trans);
		url += String.format("\x26{0}\x3d{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
	},
	createCallback : function (action, rs, trans) {
		var self = this;
		return function (res) {
			self.trans = false;
			self.destroyTrans(trans, true);
			if (action === Ext.data.Api.actions.read)
				self.onRead.call(self, action, trans, res);
			else
				self.onWrite.call(self, action, trans, res, rs)
		}
	},
	onRead : function (action, trans, res) {
		var result;
		try {
			result = trans.reader.readRecords(res)
		} catch (e) {
			this.fireEvent("loadexception", this, trans, res, e);
			this.fireEvent("exception", this, "response", action, trans, res, e);
			trans.callback.call(trans.scope ||
				window, null, trans.arg, false);
			return
		}
		if (result.success === false) {
			this.fireEvent("loadexception", this, trans, res);
			this.fireEvent("exception", this, "remote", action, trans, res, null)
		} else
			this.fireEvent("load", this, res, trans.arg);
		trans.callback.call(trans.scope || window, result, trans.arg, result.success)
	},
	onWrite : function (action, trans, response, rs) {
		var reader = trans.reader;
		try {
			var res = reader.readResponse(action, response)
		} catch (e) {
			this.fireEvent("exception", this, "response", action, trans, res, e);
			trans.callback.call(trans.scope ||
				window, null, res, false);
			return
		}
		if (!res.success === true) {
			this.fireEvent("exception", this, "remote", action, trans, res, rs);
			trans.callback.call(trans.scope || window, null, res, false);
			return
		}
		this.fireEvent("write", this, action, res.data, res, rs, trans.arg);
		trans.callback.call(trans.scope || window, res.data, res, true)
	},
	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$$0) {}

		} else
			window[trans.cb] = function () {
				window[trans.cb] = undefined;
				try {
					delete window[trans.cb]
				} catch (e) {}

			}
	},
	handleFailure : function (trans) {
		this.trans = false;
		this.destroyTrans(trans, false);
		if (trans.action === Ext.data.Api.actions.read)
			this.fireEvent("loadexception", this, null, trans.arg);
		this.fireEvent("exception", this, "response", trans.action, {
			response : null,
			options : trans.arg
		});
		trans.callback.call(trans.scope ||
			window, null, trans.arg, false)
	},
	destroy : function () {
		this.abort();
		Ext.data.ScriptTagProxy.superclass.destroy.call(this)
	}
});
Ext.data.HttpProxy = function (conn) {
	Ext.data.HttpProxy.superclass.constructor.call(this, conn);
	this.conn = conn;
	this.conn.url = null;
	this.useAjax = !conn || !conn.events;
	var actions = Ext.data.Api.actions;
	this.activeRequest = {};
	for (var verb in actions)
		this.activeRequest[actions[verb]] = undefined
};
Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
	getConnection : function () {
		return this.useAjax ? Ext.Ajax : this.conn
	},
	setUrl : function (url, makePermanent) {
		this.conn.url = url;
		if (makePermanent === true) {
			this.url = url;
			this.api = null;
			Ext.data.Api.prepare(this)
		}
	},
	doRequest : function (action, rs, params, reader, cb, scope, arg) {
		var o = {
			method : this.api[action] ? this.api[action]["method"] : undefined,
			request : {
				callback : cb,
				scope : scope,
				arg : arg
			},
			reader : reader,
			callback : this.createCallback(action, rs),
			scope : this
		};
		if (params.jsonData)
			o.jsonData =
				params.jsonData;
		else if (params.xmlData)
			o.xmlData = params.xmlData;
		else
			o.params = params || {};
		this.conn.url = this.buildUrl(action, rs);
		if (this.useAjax) {
			Ext.applyIf(o, this.conn);
			if (this.activeRequest[action]);
			this.activeRequest[action] = Ext.Ajax.request(o)
		} else
			this.conn.request(o);
		this.conn.url = null
	},
	createCallback : function (action, rs) {
		return function (o, success, response) {
			this.activeRequest[action] = undefined;
			if (!success) {
				if (action === Ext.data.Api.actions.read)
					this.fireEvent("loadexception", this, o, response);
				this.fireEvent("exception", this, "response", action, o, response);
				o.request.callback.call(o.request.scope, null, o.request.arg, false);
				return
			}
			if (action === Ext.data.Api.actions.read)
				this.onRead(action, o, response);
			else
				this.onWrite(action, o, response, rs)
		}
	},
	onRead : function (action, o, response) {
		var result;
		try {
			result = o.reader.read(response)
		} catch (e) {
			this.fireEvent("loadexception", this, o, response, e);
			this.fireEvent("exception", this, "response", action, o, response, e);
			o.request.callback.call(o.request.scope, null, o.request.arg,
				false);
			return
		}
		if (result.success === false) {
			this.fireEvent("loadexception", this, o, response);
			var res = o.reader.readResponse(action, response);
			this.fireEvent("exception", this, "remote", action, o, res, null)
		} else
			this.fireEvent("load", this, o, o.request.arg);
		o.request.callback.call(o.request.scope, result, o.request.arg, result.success)
	},
	onWrite : function (action, o, response, rs) {
		var reader = o.reader;
		var res;
		try {
			res = reader.readResponse(action, response)
		} catch (e) {
			this.fireEvent("exception", this, "response", action, o, response,
				e);
			o.request.callback.call(o.request.scope, null, o.request.arg, false);
			return
		}
		if (res.success === true)
			this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
		else
			this.fireEvent("exception", this, "remote", action, o, res, rs);
		o.request.callback.call(o.request.scope, res.data, res, res.success)
	},
	destroy : function () {
		if (!this.useAjax)
			this.conn.abort();
		else if (this.activeRequest) {
			var actions = Ext.data.Api.actions;
			for (var verb in actions)
				if (this.activeRequest[actions[verb]])
					Ext.Ajax.abort(this.activeRequest[actions[verb]])
		}
		Ext.data.HttpProxy.superclass.destroy.call(this)
	}
});
Ext.data.MemoryProxy = function (data) {
	var api = {};
	api[Ext.data.Api.actions.read] = true;
	Ext.data.MemoryProxy.superclass.constructor.call(this, {
		api : api
	});
	this.data = data
};
Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
	doRequest : function (action, rs, params, reader, callback, scope, arg) {
		params = params || {};
		var result;
		try {
			result = reader.readRecords(this.data)
		} catch (e) {
			this.fireEvent("loadexception", this, null, arg, e);
			this.fireEvent("exception", this, "response", action, arg, null, e);
			callback.call(scope, null, arg, false);
			return
		}
		callback.call(scope, result, arg, true)
	}
});
Ext.data.Types = new function () {
	var st = Ext.data.SortTypes;
	Ext.apply(this, {
		stripRe : /[\$,%]/g,
		AUTO : {
			convert : function (v) {
				return v
			},
			sortType : st.none,
			type : "auto"
		},
		STRING : {
			convert : function (v) {
				return v === undefined || v === null ? "" : String(v)
			},
			sortType : st.asUCString,
			type : "string"
		},
		INT : {
			convert : function (v) {
				return v !== undefined && v !== null && v !== "" ? parseInt(String(v).replace(Ext.data.Types.stripRe, ""), 10) : this.useNull ? null : 0
			},
			sortType : st.none,
			type : "int"
		},
		FLOAT : {
			convert : function (v) {
				return v !== undefined && v !== null && v !==
				"" ? parseFloat(String(v).replace(Ext.data.Types.stripRe, ""), 10) : this.useNull ? null : 0
			},
			sortType : st.none,
			type : "float"
		},
		BOOL : {
			convert : function (v) {
				return v === true || v === "true" || v == 1
			},
			sortType : st.none,
			type : "bool"
		},
		DATE : {
			convert : function (v) {
				var df = this.dateFormat;
				if (!v)
					return null;
				if (Ext.isDate(v))
					return v;
				if (df) {
					if (df == "timestamp")
						return new Date(v * 1E3);
					if (df == "time")
						return new Date(parseInt(v, 10));
					return Date.parseDate(v, df)
				}
				var parsed = Date.parse(v);
				return parsed ? new Date(parsed) : null
			},
			sortType : st.asDate,
			type : "date"
		}
	});
	Ext.apply(this, {
		BOOLEAN : this.BOOL,
		INTEGER : this.INT,
		NUMBER : this.FLOAT
	})
};
Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
		encode : true,
		encodeDelete : false,
		constructor : function (config) {
			Ext.data.JsonWriter.superclass.constructor.call(this, config)
		},
		render : function (params, baseParams, data) {
			if (this.encode === true) {
				Ext.apply(params, baseParams);
				params[this.meta.root] = Ext.encode(data)
			} else {
				var jdata = Ext.apply({}, baseParams);
				jdata[this.meta.root] = data;
				params.jsonData = jdata
			}
		},
		createRecord : function (rec) {
			return this.toHash(rec)
		},
		updateRecord : function (rec) {
			return this.toHash(rec)
		},
		destroyRecord : function (rec) {
			if (this.encodeDelete) {
				var data = {};
				data[this.meta.idProperty] = rec.id;
				return data
			} else
				return rec.id
		}
	});
Ext.data.JsonReader = function (meta, recordType) {
	meta = meta || {};
	Ext.applyIf(meta, {
		idProperty : "id",
		successProperty : "success",
		totalProperty : "total"
	});
	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 = Ext.decode(json);
		if (!o)
			throw {
				message : "JsonReader.read: Json object not found"
			};
		return this.readRecords(o)
	},
	readResponse : function (action, response) {
		var o = response.responseText !== undefined ? Ext.decode(response.responseText) : response;
		if (!o)
			throw new Ext.data.JsonReader.Error("response");
		var root = this.getRoot(o);
		var success = this.getSuccess(o);
		if (success && action === Ext.data.Api.actions.create) {
			var def =
				Ext.isDefined(root);
			if (def && Ext.isEmpty(root))
				throw new Ext.data.JsonReader.Error("root-empty", this.meta.root);
			else if (!def)
				throw new Ext.data.JsonReader.Error("root-undefined-response", this.meta.root);
		}
		var res = new Ext.data.Response({
				action : action,
				success : success,
				data : root ? this.extractData(root, false) : [],
				message : this.getMessage(o),
				raw : o
			});
		if (Ext.isEmpty(res.success))
			throw new Ext.data.JsonReader.Error("successProperty-response", this.meta.successProperty);
		return res
	},
	readRecords : function (o) {
		this.jsonData =
			o;
		if (o.metaData)
			this.onMetaChange(o.metaData);
		var s = this.meta;
		var Record = this.recordType;
		var f = Record.prototype.fields;
		var fi = f.items;
		var fl = f.length;
		var v;
		var root = this.getRoot(o);
		var c = root.length;
		var totalRecords = c;
		var success = true;
		if (s.totalProperty) {
			v = parseInt(this.getTotal(o), 10);
			if (!isNaN(v))
				totalRecords = v
		}
		if (s.successProperty) {
			v = this.getSuccess(o);
			if (v === false || v === "false")
				success = false
		}
		return {
			success : success,
			records : this.extractData(root, true),
			totalRecords : totalRecords
		}
	},
	buildExtractors : function () {
		if (this.ef)
			return;
		var s = this.meta;
		var Record = this.recordType;
		var f = Record.prototype.fields;
		var fi = f.items;
		var fl = f.length;
		if (s.totalProperty)
			this.getTotal = this.createAccessor(s.totalProperty);
		if (s.successProperty)
			this.getSuccess = this.createAccessor(s.successProperty);
		if (s.messageProperty)
			this.getMessage = this.createAccessor(s.messageProperty);
		this.getRoot = s.root ? this.createAccessor(s.root) : function (p) {
			return p
		};
		if (s.id || s.idProperty) {
			var g = this.createAccessor(s.id || s.idProperty);
			this.getId = function (rec) {
				var r = g(rec);
				return r === undefined || r === "" ? null : r
			}
		} else
			this.getId = function () {
				return null
			};
		var ef = [];
		for (var i = 0; i < fl; i++) {
			f = fi[i];
			var map = f.mapping !== undefined && f.mapping !== null ? f.mapping : f.name;
			ef.push(this.createAccessor(map))
		}
		this.ef = ef
	},
	simpleAccess : function (obj, subsc) {
		return obj[subsc]
	},
	createAccessor : function () {
		var re = /[\[\.]/;
		return function (expr) {
			if (Ext.isEmpty(expr))
				return Ext.emptyFn;
			if (Ext.isFunction(expr))
				return expr;
			var i = String(expr).search(re);
			if (i >= 0)
				return new Function("obj", "return obj" + (i > 0 ?
						"." : "") + expr);
			return function (obj) {
				return obj[expr]
			}
		}
	}
	(),
	extractValues : function (data, items, len) {
		var f;
		var values = {};
		for (var j = 0; j < len; j++) {
			f = items[j];
			var v = this.ef[j](data);
			values[f.name] = f.convert(v !== undefined ? v : f.defaultValue, data)
		}
		return values
	}
});
Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
		constructor : function (message, arg) {
			this.arg = arg;
			Ext.Error.call(this, message)
		},
		name : "Ext.data.JsonReader"
	});
Ext.apply(Ext.data.JsonReader.Error.prototype, {
	lang : {
		"response" : "An error occurred while json-decoding your server response",
		"successProperty-response" : 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
		"root-undefined-config" : 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
		"idProperty-undefined" : 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
		"root-empty" : 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
	}
});
Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
		readRecords : function (o) {
			this.arrayData = o;
			var s = this.meta;
			var sid = s ? Ext.num(s.idIndex, s.id) : null;
			var recordType = this.recordType;
			var fields = recordType.prototype.fields;
			var records = [];
			var success = true;
			var v;
			var root = this.getRoot(o);
			var i = 0;
			for (var len = root.length; i < len; i++) {
				var n = root[i];
				var values = {};
				var id = (sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null;
				var j = 0;
				for (var jlen = fields.length; j < jlen; j++) {
					var f = fields.items[j];
					var k = f.mapping !==
						undefined && f.mapping !== null ? f.mapping : j;
					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
			}
			var totalRecords = records.length;
			if (s.totalProperty) {
				v = parseInt(this.getTotal(o), 10);
				if (!isNaN(v))
					totalRecords = v
			}
			if (s.successProperty) {
				v = this.getSuccess(o);
				if (v === false || v === "false")
					success = false
			}
			return {
				success : success,
				records : records,
				totalRecords : totalRecords
			}
		}
	});
Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
		constructor : function (config) {
			Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
					reader : new Ext.data.ArrayReader(config)
				}))
		},
		loadData : function (data, append) {
			if (this.expandData === true) {
				var r = [];
				var i = 0;
				for (var len = data.length; i < len; i++)
					r[r.length] = [data[i]];
				data = r
			}
			Ext.data.ArrayStore.superclass.loadData.call(this, data, append)
		}
	});
Ext.reg("arraystore", Ext.data.ArrayStore);
Ext.data.SimpleStore = Ext.data.ArrayStore;
Ext.reg("simplestore", Ext.data.SimpleStore);
Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
		constructor : function (config) {
			Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
					reader : new Ext.data.JsonReader(config)
				}))
		}
	});
Ext.reg("jsonstore", Ext.data.JsonStore);
Ext.data.XmlWriter = function (params) {
	Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
	this.tpl = typeof this.tpl === "string" ? (new Ext.XTemplate(this.tpl)).compile() : this.tpl.compile()
};
Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
	documentRoot : "xrequest",
	forceDocumentRoot : false,
	root : "records",
	xmlVersion : "1.0",
	xmlEncoding : "ISO-8859-15",
	tpl : '\x3ctpl for\x3d"."\x3e\x3c?xml version\x3d"{version}" encoding\x3d"{encoding}"?\x3e\x3ctpl if\x3d"documentRoot"\x3e\x3c{documentRoot}\x3e\x3ctpl for\x3d"baseParams"\x3e\x3ctpl for\x3d"."\x3e\x3c{name}\x3e{value}\x3c/{name}\x3e\x3c/tpl\x3e\x3c/tpl\x3e\x3c/tpl\x3e\x3ctpl if\x3d"records.length\x26gt;1"\x3e\x3c{root}\x3e\x3c/tpl\x3e\x3ctpl for\x3d"records"\x3e\x3c{parent.record}\x3e\x3ctpl for\x3d"."\x3e\x3c{name}\x3e{value}\x3c/{name}\x3e\x3c/tpl\x3e\x3c/{parent.record}\x3e\x3c/tpl\x3e\x3ctpl if\x3d"records.length\x26gt;1"\x3e\x3c/{root}\x3e\x3c/tpl\x3e\x3ctpl if\x3d"documentRoot"\x3e\x3c/{documentRoot}\x3e\x3c/tpl\x3e\x3c/tpl\x3e',
	render : function (params, baseParams, data) {
		baseParams = this.toArray(baseParams);
		params.xmlData = this.tpl.applyTemplate({
				version : this.xmlVersion,
				encoding : this.xmlEncoding,
				documentRoot : baseParams.length > 0 || this.forceDocumentRoot === true ? this.documentRoot : false,
				record : this.meta.record,
				root : this.root,
				baseParams : baseParams,
				records : Ext.isArray(data[0]) ? data : [data]
			})
	},
	createRecord : function (rec) {
		return this.toArray(this.toHash(rec))
	},
	updateRecord : function (rec) {
		return this.toArray(this.toHash(rec))
	},
	destroyRecord : function (rec) {
		var data = {};
		data[this.meta.idProperty] = rec.id;
		return this.toArray(data)
	}
});
Ext.data.XmlReader = function (meta, recordType) {
	meta = meta || {};
	Ext.applyIf(meta, {
		idProperty : meta.idProperty || meta.idPath || meta.id,
		successProperty : meta.successProperty || meta.success
	});
	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 totalRecords = 0;
		var success = true;
		if (this.meta.totalProperty)
			totalRecords = this.getTotal(root, 0);
		if (this.meta.successProperty)
			success = this.getSuccess(root);
		var records = this.extractData(q.select(this.meta.record,
					root), true);
		return {
			success : success,
			records : records,
			totalRecords : totalRecords || records.length
		}
	},
	readResponse : function (action, response) {
		var q = Ext.DomQuery;
		var doc = response.responseXML;
		var root = doc.documentElement || doc;
		var res = new Ext.data.Response({
				action : action,
				success : this.getSuccess(root),
				message : this.getMessage(root),
				data : this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
				raw : doc
			});
		if (Ext.isEmpty(res.success))
			throw new Ext.data.DataReader.Error("successProperty-response",
				this.meta.successProperty);
		if (action === Ext.data.Api.actions.create) {
			var def = Ext.isDefined(res.data);
			if (def && Ext.isEmpty(res.data))
				throw new Ext.data.JsonReader.Error("root-empty", this.meta.root);
			else if (!def)
				throw new Ext.data.JsonReader.Error("root-undefined-response", this.meta.root);
		}
		return res
	},
	getSuccess : function () {
		return true
	},
	buildExtractors : function () {
		if (this.ef)
			return;
		var s = this.meta;
		var Record = this.recordType;
		var f = Record.prototype.fields;
		var fi = f.items;
		var fl = f.length;
		if (s.totalProperty)
			this.getTotal =
				this.createAccessor(s.totalProperty);
		if (s.successProperty)
			this.getSuccess = this.createAccessor(s.successProperty);
		if (s.messageProperty)
			this.getMessage = this.createAccessor(s.messageProperty);
		this.getRoot = function (res) {
			return !Ext.isEmpty(res[this.meta.record]) ? res[this.meta.record] : res[this.meta.root]
		};
		if (s.idPath || s.idProperty) {
			var g = this.createAccessor(s.idPath || s.idProperty);
			this.getId = function (rec) {
				var id = g(rec) || rec.id;
				return id === undefined || id === "" ? null : id
			}
		} else
			this.getId = function () {
				return null
			};
		var ef = [];
		for (var i = 0; i < fl; i++) {
			f = fi[i];
			var map = f.mapping !== undefined && f.mapping !== null ? f.mapping : f.name;
			ef.push(this.createAccessor(map))
		}
		this.ef = ef
	},
	createAccessor : function () {
		var q = Ext.DomQuery;
		return function (key) {
			if (Ext.isFunction(key))
				return key;
			switch (key) {
			case this.meta.totalProperty:
				return function (root, def) {
					return q.selectNumber(key, root, def)
				};
				break;
			case this.meta.successProperty:
				return function (root, def) {
					var sv = q.selectValue(key, root, true);
					var success = sv !== false && sv !== "false";
					return success
				};
				break;
			default:
				return function (root, def) {
					return q.selectValue(key, root, def)
				};
				break
			}
		}
	}
	(),
	extractValues : function (data, items, len) {
		var f;
		var values = {};
		for (var j = 0; j < len; j++) {
			f = items[j];
			var v = this.ef[j](data);
			values[f.name] = f.convert(v !== undefined ? v : f.defaultValue, data)
		}
		return values
	}
});
Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
		constructor : function (config) {
			Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
					reader : new Ext.data.XmlReader(config)
				}))
		}
	});
Ext.reg("xmlstore", Ext.data.XmlStore);
Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
		constructor : function (config) {
			config = config || {};
			this.hasMultiSort = true;
			this.multiSortInfo = this.multiSortInfo || {
				sorters : []
			};
			var sorters = this.multiSortInfo.sorters;
			var groupField = config.groupField || this.groupField;
			var sortInfo = config.sortInfo || this.sortInfo;
			var groupDir = config.groupDir || this.groupDir;
			if (groupField)
				sorters.push({
					field : groupField,
					direction : groupDir
				});
			if (sortInfo)
				sorters.push(sortInfo);
			Ext.data.GroupingStore.superclass.constructor.call(this,
				config);
			this.addEvents("groupchange");
			this.applyGroupField()
		},
		remoteGroup : false,
		groupOnSort : false,
		groupDir : "ASC",
		clearGrouping : function () {
			this.groupField = false;
			if (this.remoteGroup) {
				if (this.baseParams) {
					delete this.baseParams.groupBy;
					delete this.baseParams.groupDir
				}
				var lo = this.lastOptions;
				if (lo && lo.params) {
					delete lo.params.groupBy;
					delete lo.params.groupDir
				}
				this.reload()
			} else {
				this.sort();
				this.fireEvent("datachanged", this)
			}
		},
		groupBy : function (field, forceRegroup, direction) {
			direction = direction ? String(direction).toUpperCase() ==
				"DESC" ? "DESC" : "ASC" : this.groupDir;
			if (this.groupField == field && this.groupDir == direction && !forceRegroup)
				return;
			var sorters = this.multiSortInfo.sorters;
			if (sorters.length > 0 && sorters[0].field == this.groupField)
				sorters.shift();
			this.groupField = field;
			this.groupDir = direction;
			this.applyGroupField();
			var fireGroupEvent = function () {
				this.fireEvent("groupchange", this, this.getGroupState())
			};
			if (this.groupOnSort) {
				this.sort(field, direction);
				fireGroupEvent.call(this);
				return
			}
			if (this.remoteGroup) {
				this.on("load", fireGroupEvent,
					this, {
					single : true
				});
				this.reload()
			} else {
				this.sort(sorters);
				fireGroupEvent.call(this)
			}
		},
		sort : function (fieldName, dir) {
			if (this.remoteSort)
				return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
			var sorters = [];
			if (Ext.isArray(arguments[0]))
				sorters = arguments[0];
			else if (fieldName == undefined)
				sorters = this.sortInfo ? [this.sortInfo] : [];
			else {
				var field = this.fields.get(fieldName);
				if (!field)
					return false;
				var name = field.name;
				var sortInfo = this.sortInfo || null;
				var sortToggle = this.sortToggle ? this.sortToggle[name] :
					null;
				if (!dir)
					if (sortInfo && sortInfo.field == name)
						dir = (this.sortToggle[name] || "ASC").toggle("ASC", "DESC");
					else
						dir = field.sortDir;
				this.sortToggle[name] = dir;
				this.sortInfo = {
					field : name,
					direction : dir
				};
				sorters = [this.sortInfo]
			}
			if (this.groupField)
				sorters.unshift({
					direction : this.groupDir,
					field : this.groupField
				});
			return this.multiSort.call(this, sorters, dir)
		},
		applyGroupField : function () {
			if (this.remoteGroup) {
				if (!this.baseParams)
					this.baseParams = {};
				Ext.apply(this.baseParams, {
					groupBy : this.groupField,
					groupDir : this.groupDir
				});
				var lo = this.lastOptions;
				if (lo && lo.params) {
					lo.params.groupDir = this.groupDir;
					delete lo.params.groupBy
				}
			}
		},
		applyGrouping : function (alwaysFireChange) {
			if (this.groupField !== false) {
				this.groupBy(this.groupField, true, this.groupDir);
				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.reg("groupingstore", Ext.data.GroupingStore);
Ext.data.DirectProxy = function (config) {
	Ext.apply(this, config);
	if (typeof this.paramOrder == "string")
		this.paramOrder = this.paramOrder.split(/[\s,|]/);
	Ext.data.DirectProxy.superclass.constructor.call(this, config)
};
Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
	paramOrder : undefined,
	paramsAsHash : true,
	directFn : undefined,
	doRequest : function (action, rs, params, reader, callback, scope, options) {
		var args = [];
		var directFn = this.api[action] || this.directFn;
		switch (action) {
		case Ext.data.Api.actions.create:
			args.push(params.jsonData);
			break;
		case Ext.data.Api.actions.read:
			if (directFn.directCfg.method.len > 0)
				if (this.paramOrder) {
					var i = 0;
					for (var len = this.paramOrder.length; i < len; i++)
						args.push(params[this.paramOrder[i]])
				} else if (this.paramsAsHash)
					args.push(params);
			break;
		case Ext.data.Api.actions.update:
			args.push(params.jsonData);
			break;
		case Ext.data.Api.actions.destroy:
			args.push(params.jsonData);
			break
		}
		var trans = {
			params : params || {},
			request : {
				callback : callback,
				scope : scope,
				arg : options
			},
			reader : reader
		};
		args.push(this.createCallback(action, rs, trans), this);
		directFn.apply(window, args)
	},
	createCallback : function (action, rs, trans) {
		var me = this;
		return function (result, res) {
			if (!res.status) {
				if (action === Ext.data.Api.actions.read)
					me.fireEvent("loadexception", me, trans, res, null);
				me.fireEvent("exception",
					me, "remote", action, trans, res, null);
				trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
				return
			}
			if (action === Ext.data.Api.actions.read)
				me.onRead(action, trans, result, res);
			else
				me.onWrite(action, trans, result, res, rs)
		}
	},
	onRead : function (action, trans, result, res) {
		var records;
		try {
			records = trans.reader.readRecords(result)
		} catch (ex) {
			this.fireEvent("loadexception", this, trans, res, ex);
			this.fireEvent("exception", this, "response", action, trans, res, ex);
			trans.request.callback.call(trans.request.scope,
				null, trans.request.arg, false);
			return
		}
		this.fireEvent("load", this, res, trans.request.arg);
		trans.request.callback.call(trans.request.scope, records, trans.request.arg, true)
	},
	onWrite : function (action, trans, result, res, rs) {
		var data = trans.reader.extractData(trans.reader.getRoot(result), false);
		var success = trans.reader.getSuccess(result);
		success = success !== false;
		if (success)
			this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
		else
			this.fireEvent("exception", this, "remote", action, trans, result, rs);
		trans.request.callback.call(trans.request.scope,
			data, res, success)
	}
});
Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
		constructor : function (config) {
			var c = Ext.apply({}, {
					batchTransactions : false
				}, config);
			Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
					proxy : Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, "paramOrder,paramsAsHash,directFn,api")),
					reader : !Ext.isDefined(c.reader) && c.fields ? new Ext.data.JsonReader(Ext.copyTo({}, c, "totalProperty,root,idProperty"), c.fields) : c.reader
				}))
		}
	});
Ext.reg("directstore", Ext.data.DirectStore);
Ext.Direct = Ext.extend(Ext.util.Observable, {
		exceptions : {
			TRANSPORT : "xhr",
			PARSE : "parse",
			LOGIN : "login",
			SERVER : "exception"
		},
		constructor : function () {
			this.addEvents("event", "exception");
			this.transactions = {};
			this.providers = {}

		},
		addProvider : function (provider) {
			var a = arguments;
			if (a.length > 1) {
				var i = 0;
				for (var len = a.length; i < len; i++)
					this.addProvider(a[i]);
				return
			}
			if (!provider.events)
				provider = new Ext.Direct.PROVIDERS[provider.type](provider);
			provider.id = provider.id || Ext.id();
			this.providers[provider.id] = provider;
			provider.on("data",
				this.onProviderData, this);
			provider.on("exception", this.onProviderException, this);
			if (!provider.isConnected())
				provider.connect();
			return provider
		},
		getProvider : function (id) {
			return this.providers[id]
		},
		removeProvider : function (id) {
			var provider = id.id ? id : this.providers[id];
			provider.un("data", this.onProviderData, this);
			provider.un("exception", this.onProviderException, this);
			delete this.providers[provider.id];
			return provider
		},
		addTransaction : function (t) {
			this.transactions[t.tid] = t;
			return t
		},
		removeTransaction : function (t) {
			delete this.transactions[t.tid ||
				t];
			return t
		},
		getTransaction : function (tid) {
			return this.transactions[tid.tid || tid]
		},
		onProviderData : function (provider, e) {
			if (Ext.isArray(e)) {
				var i = 0;
				for (var len = e.length; i < len; i++)
					this.onProviderData(provider, e[i]);
				return
			}
			if (e.name && e.name != "event" && e.name != "exception")
				this.fireEvent(e.name, e);
			else if (e.type == "exception")
				this.fireEvent("exception", e);
			this.fireEvent("event", e, provider)
		},
		createEvent : function (response, extraProps) {
			return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps))
		}
	});
Ext.Direct = new Ext.Direct;
Ext.Direct.TID = 1;
Ext.Direct.PROVIDERS = {};
Ext.Direct.Transaction = function (config) {
	Ext.apply(this, config);
	this.tid = ++Ext.Direct.TID;
	this.retryCount = 0
};
Ext.Direct.Transaction.prototype = {
	send : function () {
		this.provider.queueTransaction(this)
	},
	retry : function () {
		this.retryCount++;
		this.send()
	},
	getProvider : function () {
		return this.provider
	}
};
Ext.Direct.Event = function (config) {
	Ext.apply(this, config)
};
Ext.Direct.Event.prototype = {
	status : true,
	getData : function () {
		return this.data
	}
};
Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
		type : "rpc",
		getTransaction : function () {
			return this.transaction || Ext.Direct.getTransaction(this.tid)
		}
	});
Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
		status : false,
		type : "exception"
	});
Ext.Direct.eventTypes = {
	"rpc" : Ext.Direct.RemotingEvent,
	"event" : Ext.Direct.Event,
	"exception" : Ext.Direct.ExceptionEvent
};
Ext.direct.Provider = Ext.extend(Ext.util.Observable, {
		priority : 1,
		constructor : function (config) {
			Ext.apply(this, config);
			this.addEvents("connect", "disconnect", "data", "exception");
			Ext.direct.Provider.superclass.constructor.call(this, config)
		},
		isConnected : function () {
			return false
		},
		connect : Ext.emptyFn,
		disconnect : Ext.emptyFn
	});
Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
		parseResponse : function (xhr) {
			if (!Ext.isEmpty(xhr.responseText)) {
				if (typeof xhr.responseText == "object")
					return xhr.responseText;
				return Ext.decode(xhr.responseText)
			}
			return null
		},
		getEvents : function (xhr) {
			var data = null;
			try {
				data = this.parseResponse(xhr)
			} catch (e) {
				var event = new Ext.Direct.ExceptionEvent({
						data : e,
						xhr : xhr,
						code : Ext.Direct.exceptions.PARSE,
						message : "Error parsing json response: \n\n " + data
					});
				return [event]
			}
			var events = [];
			if (Ext.isArray(data)) {
				var i =
					0;
				for (var len = data.length; i < len; i++)
					events.push(Ext.Direct.createEvent(data[i]))
			} else
				events.push(Ext.Direct.createEvent(data));
			return events
		}
	});
Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
		priority : 3,
		interval : 3E3,
		constructor : function (config) {
			Ext.direct.PollingProvider.superclass.constructor.call(this, config);
			this.addEvents("beforepoll", "poll")
		},
		isConnected : function () {
			return !!this.pollTask
		},
		connect : function () {
			if (this.url && !this.pollTask) {
				this.pollTask = Ext.TaskMgr.start({
						run : function () {
							if (this.fireEvent("beforepoll", this) !== false)
								if (typeof this.url == "function")
									this.url(this.baseParams);
								else
									Ext.Ajax.request({
										url : this.url,
										callback : this.onData,
										scope : this,
										params : this.baseParams
									})
						},
						interval : this.interval,
						scope : this
					});
				this.fireEvent("connect", this)
			} else if (!this.url)
				throw "Error initializing PollingProvider, no url configured.";
		},
		disconnect : function () {
			if (this.pollTask) {
				Ext.TaskMgr.stop(this.pollTask);
				delete this.pollTask;
				this.fireEvent("disconnect", this)
			}
		},
		onData : function (opt, success, xhr) {
			if (success) {
				var events = this.getEvents(xhr);
				var i = 0;
				for (var len = events.length; i < len; i++) {
					var e = events[i];
					this.fireEvent("data", this, e)
				}
			} else {
				e =
					new Ext.Direct.ExceptionEvent({
						data : e,
						code : Ext.Direct.exceptions.TRANSPORT,
						message : "Unable to connect to the server.",
						xhr : xhr
					});
				this.fireEvent("data", this, e)
			}
		}
	});
Ext.Direct.PROVIDERS["polling"] = Ext.direct.PollingProvider;
Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {
		enableBuffer : 10,
		maxRetries : 1,
		timeout : undefined,
		constructor : function (config) {
			Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
			this.addEvents("beforecall", "call");
			this.namespace = Ext.isString(this.namespace) ? Ext.ns(this.namespace) : this.namespace || window;
			this.transactions = {};
			this.callBuffer = []
		},
		initAPI : function () {
			var o = this.actions;
			for (var c in o) {
				var cls = this.namespace[c] || (this.namespace[c] = {});
				var ms = o[c];
				var i = 0;
				for (var len =
						ms.length; i < len; i++) {
					var m = ms[i];
					cls[m.name] = this.createMethod(c, m)
				}
			}
		},
		isConnected : function () {
			return !!this.connected
		},
		connect : function () {
			if (this.url) {
				this.initAPI();
				this.connected = true;
				this.fireEvent("connect", this)
			} else if (!this.url)
				throw "Error initializing RemotingProvider, no url configured.";
		},
		disconnect : function () {
			if (this.connected) {
				this.connected = false;
				this.fireEvent("disconnect", this)
			}
		},
		onData : function (opt, success, xhr) {
			if (success) {
				var events = this.getEvents(xhr);
				var i = 0;
				for (var len = events.length; i <
					len; i++) {
					var e = events[i];
					var t = this.getTransaction(e);
					this.fireEvent("data", this, e);
					if (t) {
						this.doCallback(t, e, true);
						Ext.Direct.removeTransaction(t)
					}
				}
			} else {
				var ts = [].concat(opt.ts);
				i = 0;
				for (len = ts.length; i < len; i++) {
					t = this.getTransaction(ts[i]);
					if (t && t.retryCount < this.maxRetries)
						t.retry();
					else {
						e = new Ext.Direct.ExceptionEvent({
								data : e,
								transaction : t,
								code : Ext.Direct.exceptions.TRANSPORT,
								message : "Unable to connect to the server.",
								xhr : xhr
							});
						this.fireEvent("data", this, e);
						if (t) {
							this.doCallback(t, e, false);
							Ext.Direct.removeTransaction(t)
						}
					}
				}
			}
		},
		getCallData : function (t) {
			return {
				action : t.action,
				method : t.method,
				data : t.data,
				type : "rpc",
				tid : t.tid
			}
		},
		doSend : function (data) {
			var o = {
				url : this.url,
				callback : this.onData,
				scope : this,
				ts : data,
				timeout : this.timeout
			};
			var callData;
			if (Ext.isArray(data)) {
				callData = [];
				var i = 0;
				for (var len = data.length; i < len; i++)
					callData.push(this.getCallData(data[i]))
			} else
				callData = this.getCallData(data);
			if (this.enableUrlEncode) {
				var params = {};
				params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : "data"] = Ext.encode(callData);
				o.params =
					params
			} else
				o.jsonData = callData;
			Ext.Ajax.request(o)
		},
		combineAndSend : function () {
			var len = this.callBuffer.length;
			if (len > 0) {
				this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
				this.callBuffer = []
			}
		},
		queueTransaction : function (t) {
			if (t.form) {
				this.processForm(t);
				return
			}
			this.callBuffer.push(t);
			if (this.enableBuffer) {
				if (!this.callTask)
					this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
				this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10)
			} else
				this.combineAndSend()
		},
		doCall : function (c,
			m, args) {
			var data = null;
			var hs = args[m.len];
			var scope = args[m.len + 1];
			if (m.len !== 0)
				data = args.slice(0, m.len);
			var t = new Ext.Direct.Transaction({
					provider : this,
					args : args,
					action : c,
					method : m.name,
					data : data,
					cb : scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
				});
			if (this.fireEvent("beforecall", this, t, m) !== false) {
				Ext.Direct.addTransaction(t);
				this.queueTransaction(t);
				this.fireEvent("call", this, t, m)
			}
		},
		doForm : function (c, m, form, callback, scope) {
			var t = new Ext.Direct.Transaction({
					provider : this,
					action : c,
					method : m.name,
					args : [form, callback, scope],
					cb : scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
					isForm : true
				});
			if (this.fireEvent("beforecall", this, t, m) !== false) {
				Ext.Direct.addTransaction(t);
				var isUpload = String(form.getAttribute("enctype")).toLowerCase() == "multipart/form-data";
				var params = {
					extTID : t.tid,
					extAction : c,
					extMethod : m.name,
					extType : "rpc",
					extUpload : String(isUpload)
				};
				Ext.apply(t, {
					form : Ext.getDom(form),
					isUpload : isUpload,
					params : callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) :
					params
				});
				this.fireEvent("call", this, t, m);
				this.processForm(t)
			}
		},
		processForm : function (t) {
			Ext.Ajax.request({
				url : this.url,
				params : t.params,
				callback : this.onData,
				scope : this,
				form : t.form,
				isUpload : t.isUpload,
				ts : t
			})
		},
		createMethod : function (c, m) {
			var f;
			if (!m.formHandler)
				f = function () {
					this.doCall(c, m, Array.prototype.slice.call(arguments, 0))
				}
			.createDelegate(this);
			else
				f = function (form, callback, scope) {
					this.doForm(c, m, form, callback, scope)
				}
			.createDelegate(this);
			f.directCfg = {
				action : c,
				method : m
			};
			return f
		},
		getTransaction : function (opt) {
			return opt &&
			opt.tid ? Ext.Direct.getTransaction(opt.tid) : null
		},
		doCallback : function (t, e) {
			var fn = e.status ? "success" : "failure";
			if (t && t.cb) {
				var hs = t.cb;
				var result = Ext.isDefined(e.result) ? e.result : e.data;
				if (Ext.isFunction(hs))
					hs(result, e);
				else {
					Ext.callback(hs[fn], hs.scope, [result, e]);
					Ext.callback(hs.callback, hs.scope, [result, e])
				}
			}
		}
	});
Ext.Direct.PROVIDERS["remoting"] = Ext.direct.RemotingProvider;
Ext.Resizable = Ext.extend(Ext.util.Observable, {
		constructor : 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;
			var i = 0;
			for (var 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.handleCls)
				}
			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;
				var he = this.east;
				var 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);
				if (this.constrainTo)
					this.dd.constrainTo(this.constrainTo)
			}
			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)
		},
		adjustments : [0, 0],
		animate : false,
		disableTrackOver : false,
		draggable : false,
		duration : 0.35,
		dynamic : false,
		easing : "easeOutStrong",
		enabled : true,
		handles : false,
		multiDirectional : false,
		height : null,
		width : null,
		heightIncrement : 0,
		widthIncrement : 0,
		minHeight : 5,
		minWidth : 5,
		maxHeight : 1E4,
		maxWidth : 1E4,
		minX : 0,
		minY : 0,
		pinned : false,
		preserveRatio : false,
		resizeChild : false,
		transparent : 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 : "\x26#160;"
						}, Ext.getBody());
					this.overlay.unselectable();
					this.overlay.enableDisplayMode("block");
					this.overlay.on({
						scope : this,
						mousemove : this.onMouseMove,
						mouseup : this.onMouseUp
					})
				}
				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) {
			this.activeHandle = null;
			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$$0 = el.getSize(true);
					child.setSize(b$$0.width +
						adj[0], b$$0.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();
			if (this.draggable && this.constrainTo) {
				this.dd.resetConstraints();
				this.dd.constrainTo(this.constrainTo)
			}
			return box
		},
		constrain : function (v, diff, m, mx) {
			if (v - diff < m)
				diff = v - m;
			else if (v - diff > mx)
				diff = v - mx;
			return diff
		},
		onMouseMove : function (e) {
			if (this.enabled && this.activeHandle)
				try {
					if (this.resizeRegion && !this.resizeRegion.contains(e.getPoint()))
						return;
					var curSize = this.curSize || this.startBox;
					var x =
						this.startBox.x;
					var y = this.startBox.y;
					var ox = x;
					var oy = y;
					var w = curSize.width;
					var h = curSize.height;
					var ow = w;
					var oh = h;
					var mw = this.minWidth;
					var mh = this.minHeight;
					var mxw = this.maxWidth;
					var 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;
					var tw;
					var th;
					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":
							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);
							tw = w;
							w = ow * (h / oh);
							x += tw - w;
							break;
						case "west":
							th = h;
							h = oh * (w / ow);
							h = Math.min(Math.max(mh, h), mxh);
							y += (th - h) / 2;
							tw = w;
							w = ow * (h / oh);
							x += tw - w;
							break;
						case "northwest":
							tw =
								w;
							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 (ex) {}

		},
		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) {
			Ext.destroy(this.dd, this.overlay, this.proxy);
			this.overlay = null;
			this.proxy =
				null;
			var ps = Ext.Resizable.positions;
			for (var k in ps)
				if (typeof ps[k] != "function" && this[ps[k]])
					this[ps[k]].destroy();
			if (removeEl) {
				this.el.update("");
				Ext.destroy(this.el);
				this.el = null
			}
			this.purgeListeners()
		},
		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 = Ext.extend(Object, {
		constructor : function (rz, pos, disableTrackOver, transparent, cls) {
			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);
			if (!Ext.isEmpty(cls))
				this.el.addClass(cls);
			this.el.on("mousedown", this.onMouseDown, this);
			if (!disableTrackOver)
				this.el.on({
					scope : this,
					mouseover : this.onMouseOver,
					mouseout : this.onMouseOut
				})
		},
		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)
		},
		destroy : function () {
			Ext.destroy(this.el);
			this.el = null
		}
	});
Ext.Window = Ext.extend(Ext.Panel, {
		baseCls : "x-window",
		resizable : true,
		draggable : true,
		closable : true,
		closeAction : "close",
		constrain : false,
		constrainHeader : false,
		plain : false,
		minimizable : false,
		maximizable : false,
		minHeight : 100,
		minWidth : 200,
		expandOnShow : true,
		showAnimDuration : 0.25,
		hideAnimDuration : 0.25,
		collapsible : false,
		initHidden : undefined,
		hidden : true,
		elements : "header,body",
		frame : true,
		floating : true,
		initComponent : function () {
			this.initTools();
			Ext.Window.superclass.initComponent.call(this);
			this.addEvents("resize",
				"maximize", "minimize", "restore");
			if (Ext.isDefined(this.initHidden))
				this.hidden = this.initHidden;
			if (this.hidden === false) {
				this.hidden = true;
				this.show()
			}
		},
		getState : function () {
			return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true))
		},
		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 : "\x26#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();
				this.mon(this.mask, "click", this.focus, this)
			}
			if (this.maximizable)
				this.mon(this.header, "dblclick", this.toggleMaximize, this)
		},
		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,
						handleCls : "x-window-handle"
					});
				this.resizer.window = this;
				this.mon(this.resizer, "beforeresize", this.beforeResize, this)
			}
			if (this.draggable)
				this.header.addClass("x-window-draggable");
			this.mon(this.el, "mousedown", this.toFront, this);
			this.manager = this.manager || Ext.WindowMgr;
			this.manager.register(this);
			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 (k, e) {
			if (this.activeGhost)
				this.unghost();
			e.stopEvent();
			this[this.closeAction]()
		},
		beforeDestroy : function () {
			if (this.rendered) {
				this.hide();
				this.clearAnchor();
				Ext.destroy(this.focusEl, 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
				})
			}
			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);
				if (Ext.isIE6 && Ext.isStrict)
					this.doLayout()
			}
			this.focus();
			this.updateHandles();
			this.saveState()
		},
		focus : function () {
			var f = this.focusEl;
			var db = this.defaultButton;
			var t = typeof db;
			var el;
			var ct;
			if (Ext.isDefined(db)) {
				if (Ext.isNumber(db) && this.fbar)
					f = this.fbar.items.get(db);
				else if (Ext.isString(db))
					f = Ext.getCmp(db);
				else
					f = db;
				el = f.getEl();
				ct = Ext.getDom(this.container);
				if (el && ct)
					if (ct != document.body && !Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom)))
						return
			}
			f = f || this.focusEl;
			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 this
			}
			if (this.fireEvent("beforeshow", this) === false)
				return this;
			if (cb)
				this.on("show", cb, scope, {
					single : true
				});
			this.hidden = false;
			if (Ext.isDefined(animateTarget))
				this.setAnimateTarget(animateTarget);
			this.beforeShow();
			if (this.animateTarget)
				this.animShow();
			else
				this.afterShow();
			return this
		},
		afterShow : function (isAnim) {
			if (this.isDestroyed)
				return false;
			this.proxy.hide();
			this.el.setStyle("display",
				"block");
			this.el.show();
			if (this.maximized)
				this.fitContainer();
			if (Ext.isMac && Ext.isGecko2)
				this.cascade(this.setAutoScroll);
			if (this.monitorResize || this.modal || this.constrain || this.constrainHeader)
				Ext.EventManager.onWindowResize(this.onWindowResize, this);
			this.doConstrain();
			this.doLayout();
			if (this.keyMap)
				this.keyMap.enable();
			this.toFront();
			this.updateHandles();
			if (isAnim && (Ext.isIE || Ext.isWebKit)) {
				var sz = this.getSize();
				this.onResize(sz.width, sz.height)
			}
			this.onShow();
			this.fireEvent("show", this)
		},
		animShow : function () {
			this.proxy.show();
			this.proxy.setBox(this.animateTarget.getBox());
			this.proxy.setOpacity(0);
			var b = this.getBox();
			this.el.setStyle("display", "none");
			this.proxy.shift(Ext.apply(b, {
					callback : this.afterShow.createDelegate(this, [true], false),
					scope : this,
					easing : "easeNone",
					duration : this.showAnimDuration,
					opacity : 0.5
				}))
		},
		hide : function (animateTarget, cb, scope) {
			if (this.hidden || this.fireEvent("beforehide", this) === false)
				return this;
			if (cb)
				this.on("hide", cb, scope, {
					single : true
				});
			this.hidden = true;
			if (animateTarget !== undefined)
				this.setAnimateTarget(animateTarget);
			if (this.modal) {
				this.mask.hide();
				Ext.getBody().removeClass("x-body-masked")
			}
			if (this.animateTarget)
				this.animHide();
			else {
				this.el.hide();
				this.afterHide()
			}
			return this
		},
		afterHide : function () {
			this.proxy.hide();
			if (this.monitorResize || this.modal || this.constrain || this.constrainHeader)
				Ext.EventManager.removeResizeListener(this.onWindowResize, this);
			if (this.keyMap)
				this.keyMap.disable();
			this.onHide();
			this.fireEvent("hide", this)
		},
		animHide : function () {
			this.proxy.setOpacity(0.5);
			this.proxy.show();
			var tb = this.getBox(false);
			this.proxy.setBox(tb);
			this.el.hide();
			this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
					callback : this.afterHide,
					scope : this,
					duration : this.hideAnimDuration,
					easing : "easeNone",
					opacity : 0
				}))
		},
		onShow : Ext.emptyFn,
		onHide : Ext.emptyFn,
		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 + this.el.getConstrainOffset())
					}
				}
				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 (!this.activeGhost)
				return;
			if (show !== false) {
				this.el.show();
				this.focus.defer(10, this);
				if (Ext.isMac && Ext.isGecko2)
					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);
			return this
		},
		close : function () {
			if (this.fireEvent("beforeclose", this) !==
				false)
				if (this.hidden)
					this.doClose();
				else
					this.hide(null, this.doClose, this)
		},
		doClose : function () {
			this.fireEvent("close", this);
			this.destroy()
		},
		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)
			}
			return this
		},
		restore : function () {
			if (this.maximized) {
				var t = this.tools;
				this.el.removeClass("x-window-maximized");
				if (t.restore)
					t.restore.hide();
				if (t.maximize)
					t.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 &&
					t.toggle)
					t.toggle.show();
				this.container.removeClass("x-window-maximized-ct");
				this.doConstrain();
				this.fireEvent("restore", this)
			}
			return this
		},
		toggleMaximize : function () {
			return this[this.maximized ? "restore" : "maximize"]()
		},
		fitContainer : function () {
			var vs = this.container.getViewSize(false);
			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) {
			this.clearAnchor();
			this.anchorTarget = {
				el : el,
				alignment : alignment,
				offsets : offsets
			};
			Ext.EventManager.onWindowResize(this.doAnchor, this);
			var tm = typeof monitorScroll;
			if (tm != "undefined")
				Ext.EventManager.on(window, "scroll", this.doAnchor, this, {
					buffer : tm == "number" ? monitorScroll : 50
				});
			return this.doAnchor()
		},
		doAnchor : function () {
			var o = this.anchorTarget;
			this.alignTo(o.el, o.alignment, o.offsets);
			return this
		},
		clearAnchor : function () {
			if (this.anchorTarget) {
				Ext.EventManager.removeResizeListener(this.doAnchor, this);
				Ext.EventManager.un(window, "scroll", this.doAnchor, this);
				delete this.anchorTarget
			}
			return this
		},
		toFront : function (e) {
			if (this.manager.bringToFront(this))
				if (!e || !e.getTarget().focus)
					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 = Ext.extend(Ext.dd.DD, {
		constructor : 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
		},
		moveOnly : true,
		headerOffsets : [100, 25],
		startDrag : function () {
			var w = this.win;
			this.proxy = w.ghost(w.initialConfig.cls);
			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;
		var 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 : 9E3,
		register : function (win) {
			if (win.manager)
				win.manager.unregister(win);
			win.manager = this;
			list[win.id] = win;
			accessList.push(win);
			win.on("hide", activateLast)
		},
		unregister : function (win) {
			delete win.manager;
			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.MessageBox = function () {
	var dlg;
	var opt;
	var mask;
	var waitTimer;
	var bodyEl;
	var msgEl;
	var textboxEl;
	var textareaEl;
	var progressBar;
	var pp;
	var iconEl;
	var spacerEl;
	var buttons;
	var activeTextEl;
	var bwidth;
	var bufferIcon = "";
	var iconCls = "";
	var buttonNames = ["ok", "yes", "no", "cancel"];
	var handleButton = function (button) {
		buttons[button].blur();
		if (dlg.isVisible()) {
			dlg.hide();
			handleHide();
			Ext.callback(opt.fn, opt.scope || window, [button, activeTextEl.dom.value, opt], 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();
			handleHide()
		}
		if (e)
			e.stopEvent()
	};
	var updateButtons = function (b) {
		var width = 0;
		var cfg;
		if (!b) {
			Ext.each(buttonNames, function (name) {
				buttons[name].hide()
			});
			return width
		}
		dlg.footer.dom.style.display = "";
		Ext.iterate(buttons, function (name, btn) {
			cfg = b[name];
			if (cfg) {
				btn.show();
				btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
				width += btn.getEl().getWidth() + 15
			} else
				btn.hide()
		});
		return width
	};
	return {
		getDialog : function (titleText) {
			if (!dlg) {
				var btns =
					[];
				buttons = {};
				Ext.each(buttonNames, function (name) {
					btns.push(buttons[name] = new Ext.Button({
								text : this.buttonText[name],
								handler : handleButton.createCallback(name),
								hideMode : "offsets"
							}))
				}, this);
				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")
						},
						fbar : new Ext.Toolbar({
							items : btns,
							enableOverflow : false
						})
					});
				dlg.render(document.body);
				dlg.getEl().addClass("x-window-dlg");
				mask = dlg.mask;
				bodyEl = dlg.body.createChild({
						html : '\x3cdiv class\x3d"ext-mb-icon"\x3e\x3c/div\x3e\x3cdiv class\x3d"ext-mb-content"\x3e\x3cspan class\x3d"ext-mb-text"\x3e\x3c/span\x3e\x3cbr /\x3e\x3cdiv class\x3d"ext-mb-fix-cursor"\x3e\x3cinput type\x3d"text" class\x3d"ext-mb-input" /\x3e\x3ctextarea class\x3d"ext-mb-textarea"\x3e\x3c/textarea\x3e\x3c/div\x3e\x3c/div\x3e'
					});
				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 ? text + " " : "\x26#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");
			var w;
			w = Math.max(Math.min(opt.width || iw + mw + fw + bw, opt.maxWidth || 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);
			if (Ext.isIE && w == bwidth)
				w += 4;
			msgEl.update(text || "\x26#160;");
			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 () {
			var proxy = dlg ? dlg.activeGhost : null;
			if (this.isVisible() || proxy) {
				dlg.hide();
				handleHide();
				if (proxy)
					dlg.unghost(false,
						false)
			}
			return this
		},
		show : function (options) {
			if (this.isVisible())
				this.hide();
			opt = options;
			var d = this.getDialog(opt.title || "\x26#160;");
			d.setTitle(opt.title || "\x26#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(Ext.isNumber(opt.multiline) ? 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 (Ext.isDefined(opt.iconCls))
				d.setIconClass(opt.iconCls);
			this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
			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.on("show", function () {
					if (allowClose === true)
						d.keyMap.enable();
					else
						d.keyMap.disable()
				}, this, {
					single : true
				});
				d.show(opt.animEl)
			}
			if (opt.wait === true)
				progressBar.wait(opt.waitConfig);
			return this
		},
		setIcon : function (icon) {
			if (!dlg) {
				bufferIcon =
					icon;
				return
			}
			bufferIcon = undefined;
			if (icon && icon != "") {
				iconEl.removeClass("x-hidden");
				iconEl.replaceClass(iconCls, icon);
				bodyEl.addClass("x-dlg-icon");
				iconCls = icon
			} else {
				iconEl.replaceClass(iconCls, "x-hidden");
				bodyEl.removeClass("x-dlg-icon");
				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,
				minWidth : this.minWidth
			});
			return this
		},
		confirm : function (title, msg, fn, scope) {
			this.show({
				title : title,
				msg : msg,
				buttons : this.YESNO,
				fn : fn,
				scope : scope,
				icon : this.QUESTION,
				minWidth : this.minWidth
			});
			return this
		},
		prompt : function (title, msg, fn, scope, multiline, value) {
			this.show({
				title : title,
				msg : msg,
				buttons : this.OKCANCEL,
				fn : fn,
				minWidth : this.minPromptWidth,
				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,
		minPromptWidth : 250,
		buttonText : {
			ok : "OK",
			cancel : "Cancel",
			yes : "Yes",
			no : "No"
		}
	}
}
();
Ext.Msg = Ext.MessageBox;
Ext.dd.PanelProxy = Ext.extend(Object, {
		constructor : function (panel, config) {
			this.panel = panel;
			this.id = this.panel.id + "-ddproxy";
			Ext.apply(this, config)
		},
		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(this.panel.initialConfig.cls, 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 = Ext.extend(Ext.dd.DragSource, {
		constructor : 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;
			var el = panel.body;
			if (h) {
				this.setHandleElId(h.id);
				el = panel.header
			}
			el.setStyle("cursor", "move");
			this.scroll = false
		},
		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 = Ext.extend(Ext.util.Observable, {
		constructor : function () {
			this.addEvents("statechange");
			this.state = {};
			Ext.state.Provider.superclass.constructor.call(this)
		},
		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|e)\:(.*)$/;
			var matches = re.exec(unescape(cookie));
			var all;
			var type;
			var v;
			var kv;
			if (!matches || !matches[1])
				return;
			type = matches[1];
			v = matches[2];
			switch (type) {
			case "e":
				return null;
			case "n":
				return parseFloat(v);
			case "d":
				return new Date(Date.parse(v));
			case "b":
				return v == "1";
			case "a":
				all = [];
				if (v != "")
					Ext.each(v.split("^"), function (val) {
						all.push(this.decodeValue(val))
					}, this);
				return all;
			case "o":
				all = {};
				if (v != "")
					Ext.each(v.split("^"), function (val) {
						kv = val.split("\x3d");
						all[kv[0]] = this.decodeValue(kv[1])
					},
						this);
				return all;
			default:
				return v
			}
		},
		encodeValue : function (v) {
			var enc;
			var flat = "";
			var i = 0;
			var len;
			var key;
			if (v == null)
				return "e:1";
			else 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)) {
				for (len = v.length; i < len; i++) {
					flat += this.encodeValue(v[i]);
					if (i != len - 1)
						flat += "^"
				}
				enc = "a:" + flat
			} else if (typeof v == "object") {
				for (key in v)
					if (typeof v[key] != "function" && v[key] !== undefined)
						flat += key + "\x3d" + 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 = Ext.extend(Ext.state.Provider, {
		constructor : function (config) {
			Ext.state.CookieProvider.superclass.constructor.call(this);
			this.path = "/";
			this.expires = new Date((new Date).getTime() + 1E3 * 60 * 60 * 24 * 7);
			this.domain = null;
			this.secure = false;
			Ext.apply(this, config);
			this.state = this.readCookies()
		},
		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;
			var name;
			for (var value; (matches = re.exec(c)) != null; ) {
				name = matches[1];
				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 + "\x3d" + this.encodeValue(value) + (this.expires == null ? "" : "; expires\x3d" + this.expires.toGMTString()) +
				(this.path == null ? "" : "; path\x3d" + this.path) + (this.domain == null ? "" : "; domain\x3d" + this.domain) + (this.secure == true ? "; secure" : "")
		},
		clearCookie : function (name) {
			document.cookie = "ys-" + name + "\x3dnull; expires\x3dThu, 01-Jan-70 00:00:01 GMT" + (this.path == null ? "" : "; path\x3d" + this.path) + (this.domain == null ? "" : "; domain\x3d" + this.domain) + (this.secure == true ? "; secure" : "")
		}
	});
Ext.DataView = Ext.extend(Ext.BoxComponent, {
		selectedClass : "x-view-selected",
		emptyText : "",
		deferEmptyText : true,
		trackOver : false,
		blockRefresh : false,
		last : false,
		initComponent : function () {
			Ext.DataView.superclass.initComponent.call(this);
			if (Ext.isString(this.tpl) || Ext.isArray(this.tpl))
				this.tpl = new Ext.XTemplate(this.tpl);
			this.addEvents("beforeclick", "click", "mouseenter", "mouseleave", "containerclick", "dblclick", "contextmenu", "containercontextmenu", "selectionchange", "beforeselect");
			this.store = Ext.StoreMgr.lookup(this.store);
			this.all = new Ext.CompositeElementLite;
			this.selected = new Ext.CompositeElementLite
		},
		afterRender : function () {
			Ext.DataView.superclass.afterRender.call(this);
			this.mon(this.getTemplateTarget(), {
				"click" : this.onClick,
				"dblclick" : this.onDblClick,
				"contextmenu" : this.onContextMenu,
				scope : this
			});
			if (this.overClass || this.trackOver)
				this.mon(this.getTemplateTarget(), {
					"mouseover" : this.onMouseOver,
					"mouseout" : this.onMouseOut,
					scope : this
				});
			if (this.store)
				this.bindStore(this.store, true)
		},
		refresh : function () {
			this.clearSelections(false,
				true);
			var el = this.getTemplateTarget();
			var records = this.store.getRange();
			el.update("");
			if (records.length < 1) {
				if (!this.deferEmptyText || this.hasSkippedEmptyText)
					el.update(this.emptyText);
				this.all.clear()
			} else {
				this.tpl.overwrite(el, this.collectData(records, 0));
				this.all.fill(Ext.query(this.itemSelector, el.dom));
				this.updateIndexes(0)
			}
			this.hasSkippedEmptyText = true
		},
		getTemplateTarget : function () {
			return this.el
		},
		prepareData : function (data) {
			return data
		},
		collectData : function (records, startIndex) {
			var r = [];
			var i =
				0;
			for (var len = records.length; i < len; i++)
				r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
			return r
		},
		bufferRender : function (records, index) {
			var div = document.createElement("div");
			this.tpl.overwrite(div, this.collectData(records, index));
			return Ext.query(this.itemSelector, div)
		},
		onUpdate : function (ds, record) {
			var index = this.store.indexOf(record);
			if (index > -1) {
				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);
			var n;
			var 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);
			if (this.store.getCount() === 0)
				this.refresh()
		},
		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
		},
		getStore : function () {
			return this.store
		},
		bindStore : function (store, initial) {
			if (!initial && this.store) {
				if (store !== this.store && this.store.autoDestroy)
					this.store.destroy();
				else {
					this.store.un("beforeload", this.onBeforeLoad, this);
					this.store.un("datachanged", this.onDataChanged, 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)
					this.store = null
			}
			if (store) {
				store = Ext.StoreMgr.lookup(store);
				store.on({
					scope : this,
					beforeload : this.onBeforeLoad,
					datachanged : this.onDataChanged,
					add : this.onAdd,
					remove : this.onRemove,
					update : this.onUpdate,
					clear : this.refresh
				})
			}
			this.store = store;
			if (store)
				this.refresh()
		},
		onDataChanged : function () {
			if (this.blockRefresh !== true)
				this.refresh.apply(this, arguments)
		},
		findItemFromChild : function (node) {
			return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget())
		},
		onClick : function (e) {
			var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
			var index;
			if (item) {
				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.onContainerClick(e)
		},
		onContainerClick : function (e) {
			this.clearSelections()
		},
		onContextMenu : function (e) {
			var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
			if (item)
				this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
			else
				this.fireEvent("containercontextmenu", this, e)
		},
		onDblClick : function (e) {
			var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
			if (item)
				this.fireEvent("dblclick",
					this, this.indexOf(item), item, e)
		},
		onMouseOver : function (e) {
			var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
			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, 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 = [];
			var selected = this.selected.elements;
			var i = 0;
			for (var len = selected.length; i < len; i++)
				indexes.push(selected[i].viewIndex);
			return indexes
		},
		getSelectedRecords : function () {
			return this.getRecords(this.selected.elements)
		},
		getRecords : function (nodes) {
			var records = [];
			var i = 0;
			for (var len = nodes.length; i < len; i++)
				records[records.length] = this.store.getAt(nodes[i].viewIndex);
			return records
		},
		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);
				var i = 0;
				for (var 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 (Ext.isString(nodeInfo))
				return document.getElementById(nodeInfo);
			else if (Ext.isNumber(nodeInfo))
				return this.all.elements[nodeInfo];
			else if (nodeInfo instanceof Ext.data.Record) {
				var idx = this.store.indexOf(nodeInfo);
				return this.all.elements[idx]
			}
			return nodeInfo
		},
		getNodes : function (start, end) {
			var ns = this.all.elements;
			var nodes = [];
			var i;
			start =
				start || 0;
			end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
			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 (Ext.isNumber(node.viewIndex))
				return node.viewIndex;
			return this.all.indexOf(node)
		},
		onBeforeLoad : function () {
			if (this.loadingText) {
				this.clearSelections(false, true);
				this.getTemplateTarget().update('\x3cdiv class\x3d"loading-indicator"\x3e' + this.loadingText + "\x3c/div\x3e");
				this.all.clear()
			}
		},
		onDestroy : function () {
			this.all.clear();
			this.selected.clear();
			Ext.DataView.superclass.onDestroy.call(this);
			this.bindStore(null)
		}
	});
Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
Ext.reg("dataview", Ext.DataView);
Ext.list.ListView = Ext.extend(Ext.DataView, {
		itemSelector : "dl",
		selectedClass : "x-list-selected",
		overClass : "x-list-over",
		scrollOffset : undefined,
		columnResize : true,
		columnSort : true,
		maxColumnWidth : Ext.isIE ? 99 : 100,
		initComponent : function () {
			if (this.columnResize) {
				this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
				this.colResizer.init(this)
			}
			if (this.columnSort) {
				this.colSorter = new Ext.list.Sorter(this.columnSort);
				this.colSorter.init(this)
			}
			if (!this.internalTpl)
				this.internalTpl = new Ext.XTemplate('\x3cdiv class\x3d"x-list-header"\x3e\x3cdiv class\x3d"x-list-header-inner"\x3e',
						'\x3ctpl for\x3d"columns"\x3e', '\x3cdiv style\x3d"width:{[values.width*100]}%;text-align:{align};"\x3e\x3cem unselectable\x3d"on" id\x3d"', this.id, '-xlhd-{#}"\x3e', "{header}", "\x3c/em\x3e\x3c/div\x3e", "\x3c/tpl\x3e", '\x3cdiv class\x3d"x-clear"\x3e\x3c/div\x3e', "\x3c/div\x3e\x3c/div\x3e", '\x3cdiv class\x3d"x-list-body"\x3e\x3cdiv class\x3d"x-list-body-inner"\x3e', "\x3c/div\x3e\x3c/div\x3e");
			if (!this.tpl)
				this.tpl = new Ext.XTemplate('\x3ctpl for\x3d"rows"\x3e', "\x3cdl\x3e", '\x3ctpl for\x3d"parent.columns"\x3e',
						'\x3cdt style\x3d"width:{[values.width*100]}%;text-align:{align};"\x3e', '\x3cem unselectable\x3d"on"\x3ctpl if\x3d"cls"\x3e class\x3d"{cls}\x3c/tpl\x3e"\x3e', "{[values.tpl.apply(parent)]}", "\x3c/em\x3e\x3c/dt\x3e", "\x3c/tpl\x3e", '\x3cdiv class\x3d"x-clear"\x3e\x3c/div\x3e', "\x3c/dl\x3e", "\x3c/tpl\x3e");
			var cs = this.columns;
			var allocatedWidth = 0;
			var colsWithWidth = 0;
			var len = cs.length;
			var columns = [];
			for (var i = 0; i < len; i++) {
				var c = cs[i];
				if (!c.isColumn) {
					c.xtype = c.xtype ? /^lv/.test(c.xtype) ? c.xtype : "lv" + c.xtype :
						"lvcolumn";
					c = Ext.create(c)
				}
				if (c.width) {
					allocatedWidth += c.width * 100;
					if (allocatedWidth > this.maxColumnWidth)
						c.width -= (allocatedWidth - this.maxColumnWidth) / 100;
					colsWithWidth++
				}
				columns.push(c)
			}
			cs = this.columns = columns;
			if (colsWithWidth < len) {
				var remaining = len - colsWithWidth;
				if (allocatedWidth < this.maxColumnWidth) {
					var perCol = (this.maxColumnWidth - allocatedWidth) / remaining / 100;
					for (var j = 0; j < len; j++) {
						c = cs[j];
						if (!c.width)
							c.width = perCol
					}
				}
			}
			Ext.list.ListView.superclass.initComponent.call(this)
		},
		onRender : function () {
			this.autoEl = {
				cls : "x-list-wrap"
			};
			Ext.list.ListView.superclass.onRender.apply(this, arguments);
			this.internalTpl.overwrite(this.el, {
				columns : this.columns
			});
			this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
			this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
			if (this.hideHeaders)
				this.el.dom.firstChild.style.display = "none"
		},
		getTemplateTarget : function () {
			return this.innerBody
		},
		collectData : function () {
			var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
			return {
				columns : this.columns,
				rows : rs
			}
		},
		verifyInternalSize : function () {
			if (this.lastSize)
				this.onResize(this.lastSize.width, this.lastSize.height)
		},
		onResize : function (w, h) {
			var body = this.innerBody.dom;
			var header = this.innerHd.dom;
			var scrollWidth = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth()) + "px";
			var parentNode;
			if (!body)
				return;
			parentNode = body.parentNode;
			if (Ext.isNumber(w))
				if (this.reserveScrollOffset || parentNode.offsetWidth - parentNode.clientWidth > 10) {
					body.style.width = scrollWidth;
					header.style.width = scrollWidth
				} else {
					body.style.width = w + "px";
					header.style.width = w + "px";
					setTimeout(function () {
						if (parentNode.offsetWidth - parentNode.clientWidth > 10) {
							body.style.width = scrollWidth;
							header.style.width = scrollWidth
						}
					}, 10)
				}
			if (Ext.isNumber(h))
				parentNode.style.height = Math.max(0, h - header.parentNode.offsetHeight) + "px"
		},
		updateIndexes : function () {
			Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
			this.verifyInternalSize()
		},
		findHeaderIndex : function (header) {
			header = header.dom || header;
			var parentNode = header.parentNode;
			var children = parentNode.parentNode.childNodes;
			var i = 0;
			for (var c; c = children[i]; i++)
				if (c == parentNode)
					return i;
			return -1
		},
		setHdWidths : function () {
			var els = this.innerHd.dom.getElementsByTagName("div");
			var i = 0;
			var columns = this.columns;
			for (var len = columns.length; i < len; i++)
				els[i].style.width = columns[i].width * 100 + "%"
		}
	});
Ext.reg("listview", Ext.list.ListView);
Ext.ListView = Ext.list.ListView;
Ext.list.Column = Ext.extend(Object, {
		isColumn : true,
		align : "left",
		header : "",
		width : null,
		cls : "",
		constructor : function (c) {
			if (!c.tpl)
				c.tpl = new Ext.XTemplate("{" + c.dataIndex + "}");
			else if (Ext.isString(c.tpl))
				c.tpl = new Ext.XTemplate(c.tpl);
			Ext.apply(this, c)
		}
	});
Ext.reg("lvcolumn", Ext.list.Column);
Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
		format : "0,000.00",
		constructor : function (c) {
			c.tpl = c.tpl || new Ext.XTemplate("{" + c.dataIndex + ':number("' + (c.format || this.format) + '")}');
			Ext.list.NumberColumn.superclass.constructor.call(this, c)
		}
	});
Ext.reg("lvnumbercolumn", Ext.list.NumberColumn);
Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
		format : "m/d/Y",
		constructor : function (c) {
			c.tpl = c.tpl || new Ext.XTemplate("{" + c.dataIndex + ':date("' + (c.format || this.format) + '")}');
			Ext.list.DateColumn.superclass.constructor.call(this, c)
		}
	});
Ext.reg("lvdatecolumn", Ext.list.DateColumn);
Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
		trueText : "true",
		falseText : "false",
		undefinedText : "\x26#160;",
		constructor : function (c) {
			c.tpl = c.tpl || new Ext.XTemplate("{" + c.dataIndex + ":this.format}");
			var t = this.trueText;
			var f = this.falseText;
			var u = this.undefinedText;
			c.tpl.format = function (v) {
				if (v === undefined)
					return u;
				if (!v || v === "false")
					return f;
				return t
			};
			Ext.list.DateColumn.superclass.constructor.call(this, c)
		}
	});
Ext.reg("lvbooleancolumn", Ext.list.BooleanColumn);
Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
		minPct : 0.05,
		constructor : function (config) {
			Ext.apply(this, config);
			Ext.list.ColumnResizer.superclass.constructor.call(this)
		},
		init : function (listView) {
			this.view = listView;
			listView.on("render", this.initEvents, this)
		},
		initEvents : function (view) {
			view.mon(view.innerHd, "mousemove", this.handleHdMove, this);
			this.tracker = new Ext.dd.DragTracker({
					onBeforeStart : this.onBeforeStart.createDelegate(this),
					onStart : this.onStart.createDelegate(this),
					onDrag : this.onDrag.createDelegate(this),
					onEnd : this.onEnd.createDelegate(this),
					tolerance : 3,
					autoStart : 300
				});
			this.tracker.initEl(view.innerHd);
			view.on("beforedestroy", this.tracker.destroy, this.tracker)
		},
		handleHdMove : function (e, t) {
			var handleWidth = 5;
			var x = e.getPageX();
			var header = e.getTarget("em", 3, true);
			if (header) {
				var region = header.getRegion();
				var style = header.dom.style;
				var parentNode = header.dom.parentNode;
				if (x - region.left <= handleWidth && parentNode != parentNode.parentNode.firstChild) {
					this.activeHd = Ext.get(parentNode.previousSibling.firstChild);
					style.cursor = Ext.isWebKit ? "e-resize" : "col-resize"
				} else if (region.right - x <= handleWidth && parentNode != parentNode.parentNode.lastChild.previousSibling) {
					this.activeHd = header;
					style.cursor = Ext.isWebKit ? "w-resize" : "col-resize"
				} else {
					delete this.activeHd;
					style.cursor = ""
				}
			}
		},
		onBeforeStart : function (e) {
			this.dragHd = this.activeHd;
			return !!this.dragHd
		},
		onStart : function (e) {
			var me = this;
			var view = me.view;
			var dragHeader = me.dragHd;
			var x = me.tracker.getXY()[0];
			me.proxy = view.el.createChild({
					cls : "x-list-resizer"
				});
			me.dragX =
				dragHeader.getX();
			me.headerIndex = view.findHeaderIndex(dragHeader);
			me.headersDisabled = view.disableHeaders;
			view.disableHeaders = true;
			me.proxy.setHeight(view.el.getHeight());
			me.proxy.setX(me.dragX);
			me.proxy.setWidth(x - me.dragX);
			this.setBoundaries()
		},
		setBoundaries : function (relativeX) {
			var view = this.view;
			var headerIndex = this.headerIndex;
			var width = view.innerHd.getWidth();
			relativeX = view.innerHd.getX();
			var minWidth = Math.ceil(width * this.minPct);
			var maxWidth = width - minWidth;
			var numColumns = view.columns.length;
			var headers = view.innerHd.select("em", true);
			var minX = minWidth + relativeX;
			var maxX = maxWidth + relativeX;
			var header;
			if (numColumns == 2) {
				this.minX = minX;
				this.maxX = maxX
			} else {
				header = headers.item(headerIndex + 2);
				this.minX = headers.item(headerIndex).getX() + minWidth;
				this.maxX = header ? header.getX() - minWidth : maxX;
				if (headerIndex == 0)
					this.minX = minX;
				else if (headerIndex == numColumns - 2)
					this.maxX = maxX
			}
		},
		onDrag : function (e) {
			var me = this;
			var cursorX = me.tracker.getXY()[0].constrain(me.minX, me.maxX);
			me.proxy.setWidth(cursorX - this.dragX)
		},
		onEnd : function (e) {
			var newWidth = this.proxy.getWidth();
			var index = this.headerIndex;
			var view = this.view;
			var columns = view.columns;
			var width = view.innerHd.getWidth();
			var newPercent = Math.ceil(newWidth * view.maxColumnWidth / width) / 100;
			var disabled = this.headersDisabled;
			var headerCol = columns[index];
			var otherCol = columns[index + 1];
			var totalPercent = headerCol.width + otherCol.width;
			this.proxy.remove();
			headerCol.width = newPercent;
			otherCol.width = totalPercent - newPercent;
			delete this.dragHd;
			view.setHdWidths();
			view.refresh();
			setTimeout(function () {
				view.disableHeaders = disabled
			}, 100)
		}
	});
Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
		sortClasses : ["sort-asc", "sort-desc"],
		constructor : function (config) {
			Ext.apply(this, config);
			Ext.list.Sorter.superclass.constructor.call(this)
		},
		init : function (listView) {
			this.view = listView;
			listView.on("render", this.initEvents, this)
		},
		initEvents : function (view) {
			view.mon(view.innerHd, "click", this.onHdClick, this);
			view.innerHd.setStyle("cursor", "pointer");
			view.mon(view.store, "datachanged", this.updateSortState, this);
			this.updateSortState.defer(10, this, [view.store])
		},
		updateSortState : function (store) {
			var state = store.getSortState();
			if (!state)
				return;
			this.sortState = state;
			var cs = this.view.columns;
			var sortColumn = -1;
			var i = 0;
			for (var len = cs.length; i < len; i++)
				if (cs[i].dataIndex == state.field) {
					sortColumn = i;
					break
				}
			if (sortColumn != -1) {
				var sortDir = state.direction;
				this.updateSortIcon(sortColumn, sortDir)
			}
		},
		updateSortIcon : function (col, dir) {
			var sc = this.sortClasses;
			var hds = this.view.innerHd.select("em").removeClass(sc);
			hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0])
		},
		onHdClick : function (e) {
			var hd =
				e.getTarget("em", 3);
			if (hd && !this.view.disableHeaders) {
				var index = this.view.findHeaderIndex(hd);
				this.view.store.sort(this.view.columns[index].dataIndex)
			}
		}
	});
Ext.ListView.Sorter = Ext.list.Sorter;
Ext.TabPanel = Ext.extend(Ext.Panel, {
		deferredRender : true,
		tabWidth : 120,
		minTabWidth : 30,
		resizeTabs : false,
		enableTabScroll : false,
		scrollIncrement : 0,
		scrollRepeatInterval : 400,
		scrollDuration : 0.35,
		animScroll : true,
		tabPosition : "top",
		baseCls : "x-tab-panel",
		autoTabs : false,
		autoTabSelector : "div.x-tab",
		activeTab : undefined,
		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(Ext.apply({
						layoutOnCardChange : this.layoutOnTabChange,
						deferredRender : this.deferredRender
					}, this.layoutConfig)));
			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()
		},
		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;
			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",
					cn : [{
							tag : "span",
							cls : "x-tab-strip-text",
							cn : "\x26#160;"
						}
					]
				});
			this.strip.createChild({
				cls : "x-clear"
			});
			this.body.addClass("x-tab-panel-body-" + this.tabPosition);
			if (!this.itemTpl) {
				var tt = new Ext.Template('\x3cli class\x3d"{cls}" id\x3d"{id}"\x3e\x3ca class\x3d"x-tab-strip-close"\x3e\x3c/a\x3e', '\x3ca class\x3d"x-tab-right" href\x3d"#"\x3e\x3cem class\x3d"x-tab-left"\x3e', '\x3cspan class\x3d"x-tab-strip-inner"\x3e\x3cspan class\x3d"x-tab-strip-text {iconCls}"\x3e{text}\x3c/span\x3e\x3c/span\x3e', "\x3c/em\x3e\x3c/a\x3e\x3c/li\x3e");
				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);
			if (this.activeTab !== undefined) {
				var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
				delete this.activeTab;
				this.setActiveTab(item)
			}
		},
		initEvents : function () {
			Ext.TabPanel.superclass.initEvents.call(this);
			this.mon(this.strip, {
				scope : this,
				mousedown : this.onStripMouseDown,
				contextmenu : this.onStripContextMenu
			});
			if (this.enableTabScroll)
				this.mon(this.strip, "mousewheel", this.onWheel, this)
		},
		findTargets : function (e) {
			var item = null;
			var itemEl = e.getTarget("li:not(.x-tab-edge)", 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) {
				if (t.item.fireEvent("beforeclose", t.item) !== false) {
					t.item.fireEvent("close", t.item);
					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);
			var i = 0;
			for (var len = tabs.length; i <
				len; i++) {
				var tab = tabs[i];
				var title = tab.getAttribute("title");
				tab.removeAttribute("title");
				this.add({
					title : title,
					contentEl : tab
				})
			}
		},
		initTab : function (item, index) {
			var before = this.strip.dom.childNodes[index];
			var p = this.getTemplateArgs(item);
			var el = before ? this.itemTpl.insertBefore(before, p) : this.itemTpl.append(this.strip, p);
			var cls = "x-tab-strip-over";
			var tabEl = Ext.get(el);
			tabEl.hover(function () {
				if (!item.disabled)
					tabEl.addClass(cls)
			}, function () {
				tabEl.removeClass(cls)
			});
			if (item.tabTip)
				tabEl.child("span.x-tab-strip-text",
					true).qtip = item.tabTip;
			item.tabEl = el;
			tabEl.select("a").on("click", function (e) {
				if (!e.getPageX())
					this.onStripMouseDown(e)
			}, this, {
				preventDefault : true
			});
			item.on({
				scope : this,
				disable : this.onItemDisabled,
				enable : this.onItemEnabled,
				titlechange : this.onItemTitleChanged,
				iconchange : this.onItemIconChanged,
				beforeshow : this.onBeforeShowItem
			})
		},
		getTemplateArgs : function (item) {
			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;
			return {
				id : this.id + this.idDelimiter + item.getItemId(),
				text : item.title,
				cls : cls,
				iconCls : item.iconCls || ""
			}
		},
		onAdd : function (c) {
			Ext.TabPanel.superclass.onAdd.call(this, c);
			if (this.rendered) {
				var items = this.items;
				this.initTab(c, items.indexOf(c));
				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 (c) {
			var te = Ext.get(c.tabEl);
			if (te) {
				te.select("a").removeAllListeners();
				Ext.destroy(te)
			}
			Ext.TabPanel.superclass.onRemove.call(this, c);
			this.stack.remove(c);
			delete c.tabEl;
			c.un("disable", this.onItemDisabled, this);
			c.un("enable", this.onItemEnabled, this);
			c.un("titlechange", this.onItemTitleChanged, this);
			c.un("iconchange", this.onItemIconChanged, this);
			c.un("beforeshow", this.onBeforeShowItem, this);
			if (c == this.activeTab) {
				var next = this.stack.next();
				if (next)
					this.setActiveTab(next);
				else if (this.items.getCount() > 0)
					this.setActiveTab(0);
				else
					this.setActiveTab(null)
			}
			if (!this.destroying)
				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
		},
		onItemIconChanged : function (item, iconCls, oldCls) {
			var el = this.getTabEl(item);
			if (el) {
				el = Ext.get(el);
				el.child("span.x-tab-strip-text").replaceClass(oldCls, iconCls);
				el[Ext.isEmpty(iconCls) ? "removeClass" : "addClass"]("x-tab-with-icon")
			}
		},
		getTabEl : function (item) {
			var c = this.getComponent(item);
			return c ? c.tabEl : null
		},
		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 () {
			var rendered =
				this.rendered;
			if (this.suspendUpdates)
				return;
			if (this.resizeTabs && rendered)
				this.autoSizeTabs();
			if (this.enableTabScroll && 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.strip.query("li:not(.x-tab-edge)");
			var i = 0;
			for (var len = lis.length; i < len; i++) {
				var li = lis[i];
				var inner = Ext.fly(li).child(".x-tab-strip-inner", true);
				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 (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 = item;
				if (item) {
					var el = this.getTabEl(item);
					Ext.fly(el).addClass("x-tab-strip-active");
					this.stack.add(item);
					this.layout.setActiveItem(item);
					this.delegateUpdates();
					if (this.scrolling)
						this.scrollToTab(item, this.animScroll)
				}
				this.fireEvent("tabchange", this, item)
			}
		},
		getActiveTab : function () {
			return this.activeTab || null
		},
		getItem : function (item) {
			return this.getComponent(item)
		},
		autoScrollTabs : function () {
			this.pos = this.tabPosition == "bottom" ? this.footer : this.header;
			var count = this.items.length;
			var ow = this.pos.dom.offsetWidth;
			var tw = this.pos.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 || cw < 20)
				return;
			if (count == 0 || l <= tw) {
				wd.scrollLeft = 0;
				wrap.setWidth(tw);
				if (this.scrolling) {
					this.scrolling = false;
					this.pos.removeClass("x-tab-scrolling");
					this.scrollLeft.hide();
					this.scrollRight.hide();
					if (Ext.isAir || Ext.isWebKit) {
						wd.style.marginLeft = "";
						wd.style.marginRight = ""
					}
				}
			} else {
				if (!this.scrolling) {
					this.pos.addClass("x-tab-scrolling");
					if (Ext.isAir || Ext.isWebKit) {
						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 () {
			this.pos.addClass("x-tab-scrolling-" + this.tabPosition);
			var h = this.stripWrap.dom.offsetHeight;
			var sl = this.pos.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.pos.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();
			var 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")
		},
		beforeDestroy : function () {
			Ext.destroy(this.leftRepeater, this.rightRepeater);
			this.deleteMembers("strip", "edge", "scrollLeft", "scrollRight",
				"stripWrap");
			this.activeTab = null;
			Ext.TabPanel.superclass.beforeDestroy.apply(this)
		}
	});
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 = [];
			var i = 0;
			for (var 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.BoxComponent, {
		hidden : false,
		disabled : false,
		pressed : false,
		enableToggle : false,
		menuAlign : "tl-bl?",
		type : "button",
		menuClassTarget : "tr:nth(2)",
		clickEvent : "click",
		handleMouseEvents : true,
		tooltipType : "qtip",
		buttonSelector : "button:first-child",
		scale : "small",
		iconAlign : "left",
		arrowAlign : "right",
		initComponent : function () {
			if (this.menu) {
				if (Ext.isArray(this.menu))
					this.menu = {
						items : this.menu
					};
				if (Ext.isObject(this.menu))
					this.menu.ownerCt = this;
				this.menu = Ext.menu.MenuMgr.get(this.menu);
				this.menu.ownerCt =
					undefined
			}
			Ext.Button.superclass.initComponent.call(this);
			this.addEvents("click", "toggle", "mouseover", "mouseout", "menushow", "menuhide", "menutriggerover", "menutriggerout");
			if (Ext.isString(this.toggleGroup))
				this.enableToggle = true
		},
		getTemplateArgs : function () {
			return [this.type, "x-btn-" + this.scale + " x-btn-icon-" + this.scale + "-" + this.iconAlign, this.getMenuClass(), this.cls, this.id]
		},
		setButtonClass : function () {
			if (this.useSetClass) {
				if (!Ext.isEmpty(this.oldCls))
					this.el.removeClass([this.oldCls, "x-btn-pressed"]);
				this.oldCls = this.iconCls || this.icon ? this.text ? "x-btn-text-icon" : "x-btn-icon" : "x-btn-noicon";
				this.el.addClass([this.oldCls, this.pressed ? "x-btn-pressed" : null])
			}
		},
		getMenuClass : function () {
			return this.menu ? this.arrowAlign != "bottom" ? "x-btn-arrow" : "x-btn-arrow-bottom" : ""
		},
		onRender : function (ct, position) {
			if (!this.template) {
				if (!Ext.Button.buttonTemplate) {
					Ext.Button.buttonTemplate = new Ext.Template('\x3ctable id\x3d"{4}" cellspacing\x3d"0" class\x3d"x-btn {3}"\x3e\x3ctbody class\x3d"{1}"\x3e', '\x3ctr\x3e\x3ctd class\x3d"x-btn-tl"\x3e\x3ci\x3e\x26#160;\x3c/i\x3e\x3c/td\x3e\x3ctd class\x3d"x-btn-tc"\x3e\x3c/td\x3e\x3ctd class\x3d"x-btn-tr"\x3e\x3ci\x3e\x26#160;\x3c/i\x3e\x3c/td\x3e\x3c/tr\x3e',
							'\x3ctr\x3e\x3ctd class\x3d"x-btn-ml"\x3e\x3ci\x3e\x26#160;\x3c/i\x3e\x3c/td\x3e\x3ctd class\x3d"x-btn-mc"\x3e\x3cem class\x3d"{2}" unselectable\x3d"on"\x3e\x3cbutton type\x3d"{0}"\x3e\x3c/button\x3e\x3c/em\x3e\x3c/td\x3e\x3ctd class\x3d"x-btn-mr"\x3e\x3ci\x3e\x26#160;\x3c/i\x3e\x3c/td\x3e\x3c/tr\x3e', '\x3ctr\x3e\x3ctd class\x3d"x-btn-bl"\x3e\x3ci\x3e\x26#160;\x3c/i\x3e\x3c/td\x3e\x3ctd class\x3d"x-btn-bc"\x3e\x3c/td\x3e\x3ctd class\x3d"x-btn-br"\x3e\x3ci\x3e\x26#160;\x3c/i\x3e\x3c/td\x3e\x3c/tr\x3e',
							"\x3c/tbody\x3e\x3c/table\x3e");
					Ext.Button.buttonTemplate.compile()
				}
				this.template = Ext.Button.buttonTemplate
			}
			var btn;
			var targs = this.getTemplateArgs();
			if (position)
				btn = this.template.insertBefore(position, targs, true);
			else
				btn = this.template.append(ct, targs, true);
			this.btnEl = btn.child(this.buttonSelector);
			this.mon(this.btnEl, {
				scope : this,
				focus : this.onFocus,
				blur : this.onBlur
			});
			this.initButtonEl(btn, this.btnEl);
			Ext.ButtonToggleMgr.register(this)
		},
		initButtonEl : function (btn, btnEl) {
			this.el = btn;
			this.setIcon(this.icon);
			this.setText(this.text);
			this.setIconClass(this.iconCls);
			if (Ext.isDefined(this.tabIndex))
				btnEl.dom.tabIndex = this.tabIndex;
			if (this.tooltip)
				this.setTooltip(this.tooltip, true);
			if (this.handleMouseEvents)
				this.mon(btn, {
					scope : this,
					mouseover : this.onMouseOver,
					mousedown : this.onMouseDown
				});
			if (this.menu)
				this.mon(this.menu, {
					scope : this,
					show : this.onMenuShow,
					hide : this.onMenuHide
				});
			if (this.repeat) {
				var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
				this.mon(repeater, "click", this.onRepeatClick,
					this)
			} else
				this.mon(btn, this.clickEvent, this.onClick, this)
		},
		afterRender : function () {
			Ext.Button.superclass.afterRender.call(this);
			this.useSetClass = true;
			this.setButtonClass();
			this.doc = Ext.getDoc();
			this.doAutoWidth()
		},
		setIconClass : function (cls) {
			this.iconCls = cls;
			if (this.el) {
				this.btnEl.dom.className = "";
				this.btnEl.addClass(["x-btn-text", cls || ""]);
				this.setButtonClass()
			}
			return this
		},
		setTooltip : function (tooltip, initial) {
			if (this.rendered) {
				if (!initial)
					this.clearTip();
				if (Ext.isObject(tooltip)) {
					Ext.QuickTips.register(Ext.apply({
							target : this.btnEl.id
						},
							tooltip));
					this.tooltip = tooltip
				} else
					this.btnEl.dom[this.tooltipType] = tooltip
			} else
				this.tooltip = tooltip;
			return this
		},
		clearTip : function () {
			if (Ext.isObject(this.tooltip))
				Ext.QuickTips.unregister(this.btnEl)
		},
		beforeDestroy : function () {
			if (this.rendered)
				this.clearTip();
			if (this.menu && this.destroyMenu !== false)
				Ext.destroy(this.btnEl, this.menu);
			Ext.destroy(this.repeater)
		},
		onDestroy : function () {
			if (this.rendered) {
				this.doc.un("mouseover", this.monitorMouseOver, this);
				this.doc.un("mouseup", this.onMouseUp, this);
				delete this.doc;
				delete this.btnEl;
				Ext.ButtonToggleMgr.unregister(this)
			}
			Ext.Button.superclass.onDestroy.call(this)
		},
		doAutoWidth : function () {
			if (this.autoWidth !== false && this.el && this.text && this.width === undefined) {
				this.el.setWidth("auto");
				if (Ext.isIE7 && Ext.isStrict) {
					var ib = this.btnEl;
					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;
			return this
		},
		setText : function (text) {
			this.text = text;
			if (this.el) {
				this.btnEl.update(text || "\x26#160;");
				this.setButtonClass()
			}
			this.doAutoWidth();
			return this
		},
		setIcon : function (icon) {
			this.icon = icon;
			if (this.el) {
				this.btnEl.setStyle("background-image", icon ? "url(" + icon + ")" : "");
				this.setButtonClass()
			}
			return this
		},
		getText : function () {
			return this.text
		},
		toggle : function (state, suppressEvent) {
			state = state === undefined ? !this.pressed : !!state;
			if (state != this.pressed) {
				if (this.rendered)
					this.el[state ?
						"addClass" : "removeClass"]("x-btn-pressed");
				this.pressed = state;
				if (!suppressEvent) {
					this.fireEvent("toggle", this, state);
					if (this.toggleHandler)
						this.toggleHandler.call(this.scope || this, this, state)
				}
			}
			return this
		},
		onDisable : function () {
			this.onDisableChange(true)
		},
		onEnable : function () {
			this.onDisableChange(false)
		},
		onDisableChange : function (disabled) {
			if (this.el) {
				if (!Ext.isIE6 || !this.text)
					this.el[disabled ? "addClass" : "removeClass"](this.disabledClass);
				this.el.dom.disabled = disabled
			}
			this.disabled = disabled
		},
		showMenu : function () {
			if (this.rendered &&
				this.menu) {
				if (this.tooltip)
					Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
				if (this.menu.isVisible())
					this.menu.hide();
				this.menu.ownerCt = this;
				this.menu.show(this.el, this.menuAlign)
			}
			return this
		},
		hideMenu : function () {
			if (this.hasVisibleMenu())
				this.menu.hide();
			return this
		},
		hasVisibleMenu : function () {
			return this.menu && this.menu.ownerCt == this && this.menu.isVisible()
		},
		onRepeatClick : function (repeat, e) {
			this.onClick(e)
		},
		onClick : function (e) {
			if (e)
				e.preventDefault();
			if (e.button !== 0)
				return;
			if (!this.disabled) {
				this.doToggle();
				if (this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick)
					this.showMenu();
				this.fireEvent("click", this, e);
				if (this.handler)
					this.handler.call(this.scope || this, this, e)
			}
		},
		doToggle : function () {
			if (this.enableToggle && (this.allowDepress !== false || !this.pressed))
				this.toggle()
		},
		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) {
						this.doc.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) {
					this.doc.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)
		},
		focus : function () {
			this.btnEl.focus()
		},
		blur : function () {
			this.btnEl.blur()
		},
		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");
				this.doc.on("mouseup", this.onMouseUp, this)
			}
		},
		onMouseUp : function (e) {
			if (e.button === 0) {
				this.getClickEl(e, true).removeClass("x-btn-click");
				this.doc.un("mouseup", this.onMouseUp, this)
			}
		},
		onMenuShow : function (e) {
			if (this.menu.ownerCt == this) {
				this.menu.ownerCt = this;
				this.ignoreNextClick = 0;
				this.el.addClass("x-btn-menu-active");
				this.fireEvent("menushow", this, this.menu)
			}
		},
		onMenuHide : function (e) {
			if (this.menu.ownerCt == this) {
				this.el.removeClass("x-btn-menu-active");
				this.ignoreNextClick = this.restoreClick.defer(250, this);
				this.fireEvent("menuhide", this, this.menu);
				delete this.menu.ownerCt
			}
		},
		restoreClick : function () {
			this.ignoreNextClick = 0
		}
	});
Ext.reg("button", Ext.Button);
Ext.ButtonToggleMgr = function () {
	function toggleGroup(btn, state) {
		if (state) {
			var g = groups[btn.toggleGroup];
			var i = 0;
			for (var l = g.length; i < l; i++)
				if (g[i] != btn)
					g[i].toggle(false)
		}
	}
	var groups = {};
	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)
			}
		},
		getPressed : function (group) {
			var g =
				groups[group];
			if (g) {
				var i = 0;
				for (var len = g.length; i < len; i++)
					if (g[i].pressed === true)
						return g[i]
			}
			return null
		}
	}
}
();
Ext.SplitButton = Ext.extend(Ext.Button, {
		arrowSelector : "em",
		split : true,
		initComponent : function () {
			Ext.SplitButton.superclass.initComponent.call(this);
			this.addEvents("arrowclick")
		},
		onRender : function () {
			Ext.SplitButton.superclass.onRender.apply(this, arguments);
			if (this.arrowTooltip)
				this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip
		},
		setArrowHandler : function (handler, scope) {
			this.arrowHandler = handler;
			this.scope = scope
		},
		getMenuClass : function () {
			return "x-btn-split" + (this.arrowAlign == "bottom" ?
				"-bottom" : "")
		},
		isClickOnArrow : function (e) {
			if (this.arrowAlign != "bottom") {
				var visBtn = this.el.child("em.x-btn-split");
				var right = visBtn.getRegion().right - visBtn.getPadding("r");
				return e.getPageX() > right
			} else
				return e.getPageY() > this.btnEl.getRegion().bottom
		},
		onClick : function (e, t) {
			e.preventDefault();
			if (!this.disabled)
				if (this.isClickOnArrow(e)) {
					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 {
					this.doToggle();
					this.fireEvent("click", this, e);
					if (this.handler)
						this.handler.call(this.scope || this, this, e)
				}
		},
		isMenuTriggerOver : function (e) {
			return this.menu && e.target.tagName == this.arrowSelector
		},
		isMenuTriggerOut : function (e, internal) {
			return this.menu && e.target.tagName != this.arrowSelector
		}
	});
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 (!Ext.isObject(item))
				item = this.menu.getComponent(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,
						suppressEvent);
				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 = 0;
			Ext.each(this.items, function (item, i) {
				Ext.apply(item, {
					group : item.group || this.id,
					itemIndex : i,
					checkHandler : this.checkHandler,
					scope : this,
					checked : item.checked || false
				});
				this.menu.items.push(item);
				if (item.checked)
					checked = i
			}, this);
			Ext.CycleButton.superclass.initComponent.call(this);
			this.on("click", this.toggleSelected, this);
			this.setActiveItem(checked, true)
		},
		checkHandler : function (item, pressed) {
			if (pressed)
				this.setActiveItem(item)
		},
		toggleSelected : function () {
			var m = this.menu;
			m.render();
			if (!m.hasLayout)
				m.doLayout();
			var nextIdx;
			var checkItem;
			for (var i = 1; i < this.itemCount; i++) {
				nextIdx = (this.activeItem.itemIndex +
					i) % this.itemCount;
				checkItem = m.items.itemAt(nextIdx);
				if (!checkItem.disabled) {
					checkItem.setChecked(true);
					break
				}
			}
		}
	});
Ext.reg("cycle", Ext.CycleButton);
Ext.Toolbar = function (config) {
	if (Ext.isArray(config))
		config = {
			items : config,
			layout : "toolbar"
		};
	else {
		config = Ext.apply({
				layout : "toolbar"
			}, config);
		if (config.buttons)
			config.items = config.buttons
	}
	Ext.Toolbar.superclass.constructor.call(this, config)
};
(function () {
	var T = Ext.Toolbar;
	Ext.extend(T, Ext.Container, {
		defaultType : "button",
		enableOverflow : false,
		trackMenus : true,
		internalDefaults : {
			removeMode : "container",
			hideParent : true
		},
		toolbarCls : "x-toolbar",
		initComponent : function () {
			T.superclass.initComponent.call(this);
			this.addEvents("overflowchange")
		},
		onRender : function (ct, position) {
			if (!this.el) {
				if (!this.autoCreate)
					this.autoCreate = {
						cls : this.toolbarCls + " x-small-editor"
					};
				this.el = ct.createChild(Ext.apply({
							id : this.id
						}, this.autoCreate), position);
				Ext.Toolbar.superclass.onRender.apply(this,
					arguments)
			}
		},
		lookupComponent : function (c) {
			if (Ext.isString(c)) {
				if (c == "-")
					c = new T.Separator;
				else if (c == " ")
					c = new T.Spacer;
				else if (c == "-\x3e")
					c = new T.Fill;
				else
					c = new T.TextItem(c);
				this.applyDefaults(c)
			} else if (c.isFormField || c.render)
				c = this.createComponent(c);
			else if (c.tag)
				c = new T.Item({
						autoEl : c
					});
			else if (c.tagName)
				c = new T.Item({
						el : c
					});
			else if (Ext.isObject(c))
				c = c.xtype ? this.createComponent(c) : this.constructButton(c);
			return c
		},
		applyDefaults : function (c) {
			if (!Ext.isString(c)) {
				c = Ext.Toolbar.superclass.applyDefaults.call(this,
						c);
				var d = this.internalDefaults;
				if (c.events) {
					Ext.applyIf(c.initialConfig, d);
					Ext.apply(c, d)
				} else
					Ext.applyIf(c, d)
			}
			return c
		},
		addSeparator : function () {
			return this.add(new T.Separator)
		},
		addSpacer : function () {
			return this.add(new T.Spacer)
		},
		addFill : function () {
			this.add(new T.Fill)
		},
		addElement : function (el) {
			return this.addItem(new T.Item({
					el : el
				}))
		},
		addItem : function (item) {
			return this.add.apply(this, arguments)
		},
		addButton : function (config) {
			if (Ext.isArray(config)) {
				var buttons = [];
				var i = 0;
				for (var len = config.length; i <
					len; i++)
					buttons.push(this.addButton(config[i]));
				return buttons
			}
			return this.add(this.constructButton(config))
		},
		addText : function (text) {
			return this.addItem(new T.TextItem(text))
		},
		addDom : function (config) {
			return this.add(new T.Item({
					autoEl : config
				}))
		},
		addField : function (field) {
			return this.add(field)
		},
		insertButton : function (index, item) {
			if (Ext.isArray(item)) {
				var buttons = [];
				var i = 0;
				for (var len = item.length; i < len; i++)
					buttons.push(this.insertButton(index + i, item[i]));
				return buttons
			}
			return Ext.Toolbar.superclass.insert.call(this,
				index, item)
		},
		trackMenu : function (item, remove) {
			if (this.trackMenus && item.menu) {
				var method = remove ? "mun" : "mon";
				this[method](item, "menutriggerover", this.onButtonTriggerOver, this);
				this[method](item, "menushow", this.onButtonMenuShow, this);
				this[method](item, "menuhide", this.onButtonMenuHide, this)
			}
		},
		constructButton : function (item) {
			var b = item.events ? item : this.createComponent(item, item.split ? "splitbutton" : this.defaultType);
			return b
		},
		onAdd : function (c) {
			Ext.Toolbar.superclass.onAdd.call(this);
			this.trackMenu(c);
			if (this.disabled)
				c.disable()
		},
		onRemove : function (c) {
			Ext.Toolbar.superclass.onRemove.call(this);
			if (c == this.activeMenuBtn)
				delete this.activeMenuBtn;
			this.trackMenu(c, true)
		},
		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 = Ext.extend(Ext.BoxComponent, {
			hideParent : true,
			enable : Ext.emptyFn,
			disable : Ext.emptyFn,
			focus : Ext.emptyFn
		});
	Ext.reg("tbitem", T.Item);
	T.Separator = Ext.extend(T.Item, {
			onRender : function (ct, position) {
				this.el = ct.createChild({
						tag : "span",
						cls : "xtb-sep"
					}, position)
			}
		});
	Ext.reg("tbseparator", T.Separator);
	T.Spacer = Ext.extend(T.Item, {
			onRender : function (ct, position) {
				this.el = ct.createChild({
						tag : "div",
						cls : "xtb-spacer",
						style : this.width ? "width:" + this.width + "px" : ""
					}, position)
			}
		});
	Ext.reg("tbspacer", T.Spacer);
	T.Fill = Ext.extend(T.Item, {
			render : Ext.emptyFn,
			isFill : true
		});
	Ext.reg("tbfill", T.Fill);
	T.TextItem = Ext.extend(T.Item, {
			constructor : function (config) {
				T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {
					text : config
				}
					 : config)
			},
			onRender : function (ct, position) {
				this.autoEl = {
					cls : "xtb-text",
					html : this.text || ""
				};
				T.TextItem.superclass.onRender.call(this, ct, position)
			},
			setText : function (t) {
				if (this.rendered)
					this.el.update(t);
				else
					this.text = t
			}
		});
	Ext.reg("tbtext", T.TextItem);
	T.Button = Ext.extend(Ext.Button, {});
	T.SplitButton = Ext.extend(Ext.SplitButton, {});
	Ext.reg("tbbutton", T.Button);
	Ext.reg("tbsplit", T.SplitButton)
})();
Ext.ButtonGroup = Ext.extend(Ext.Panel, {
		baseCls : "x-btn-group",
		layout : "table",
		defaultType : "button",
		frame : true,
		internalDefaults : {
			removeMode : "container",
			hideParent : true
		},
		initComponent : function () {
			this.layoutConfig = this.layoutConfig || {};
			Ext.applyIf(this.layoutConfig, {
				columns : this.columns
			});
			if (!this.title)
				this.addClass("x-btn-group-notitle");
			this.on("afterlayout", this.onAfterLayout, this);
			Ext.ButtonGroup.superclass.initComponent.call(this)
		},
		applyDefaults : function (c) {
			c = Ext.ButtonGroup.superclass.applyDefaults.call(this,
					c);
			var d = this.internalDefaults;
			if (c.events) {
				Ext.applyIf(c.initialConfig, d);
				Ext.apply(c, d)
			} else
				Ext.applyIf(c, d);
			return c
		},
		onAfterLayout : function () {
			var bodyWidth = this.body.getFrameWidth("lr") + this.body.dom.firstChild.offsetWidth;
			this.body.setWidth(bodyWidth);
			this.el.setWidth(bodyWidth + this.getFrameWidth())
		}
	});
Ext.reg("buttongroup", Ext.ButtonGroup);
(function () {
	var T = Ext.Toolbar;
	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",
			initComponent : function () {
				var pagingItems = [this.first = new T.Button({
							tooltip : this.firstText,
							overflowText : this.firstText,
							iconCls : "x-tbar-page-first",
							disabled : true,
							handler : this.moveFirst,
							scope : this
						}),
					this.prev = new T.Button({
							tooltip : this.prevText,
							overflowText : this.prevText,
							iconCls : "x-tbar-page-prev",
							disabled : true,
							handler : this.movePrevious,
							scope : this
						}), "-", this.beforePageText, this.inputItem = new Ext.form.NumberField({
							cls : "x-tbar-page-number",
							allowDecimals : false,
							allowNegative : false,
							enableKeyEvents : true,
							selectOnFocus : true,
							submitValue : false,
							listeners : {
								scope : this,
								keydown : this.onPagingKeyDown,
								blur : this.onPagingBlur
							}
						}), this.afterTextItem = new T.TextItem({
							text : String.format(this.afterPageText, 1)
						}), "-", this.next =
						new T.Button({
							tooltip : this.nextText,
							overflowText : this.nextText,
							iconCls : "x-tbar-page-next",
							disabled : true,
							handler : this.moveNext,
							scope : this
						}), this.last = new T.Button({
							tooltip : this.lastText,
							overflowText : this.lastText,
							iconCls : "x-tbar-page-last",
							disabled : true,
							handler : this.moveLast,
							scope : this
						}), "-", this.refresh = new T.Button({
							tooltip : this.refreshText,
							overflowText : this.refreshText,
							iconCls : "x-tbar-loading",
							handler : this.doRefresh,
							scope : this
						})];
				var userItems = this.items || this.buttons || [];
				if (this.prependButtons)
					this.items =
						userItems.concat(pagingItems);
				else
					this.items = pagingItems.concat(userItems);
				delete this.buttons;
				if (this.displayInfo) {
					this.items.push("-\x3e");
					this.items.push(this.displayItem = new T.TextItem({}))
				}
				Ext.PagingToolbar.superclass.initComponent.call(this);
				this.addEvents("change", "beforechange");
				this.on("afterlayout", this.onFirstLayout, this, {
					single : true
				});
				this.cursor = 0;
				this.bindStore(this.store, true)
			},
			onFirstLayout : function () {
				if (this.dsLoaded)
					this.onLoad.apply(this, this.dsLoaded)
			},
			updateInfo : function () {
				if (this.displayItem) {
					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.displayItem.setText(msg)
				}
			},
			onLoad : function (store, r, o) {
				if (!this.rendered) {
					this.dsLoaded = [store, r, o];
					return
				}
				var p = this.getParams();
				this.cursor = o.params && o.params[p.start] ? o.params[p.start] : 0;
				var d = this.getPageData();
				var ap = d.activePage;
				var ps = d.pages;
				this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
				this.inputItem.setValue(ap);
				this.first.setDisabled(ap ==
					1);
				this.prev.setDisabled(ap == 1);
				this.next.setDisabled(ap == ps);
				this.last.setDisabled(ap == ps);
				this.refresh.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)
				}
			},
			changePage : function (page) {
				this.doLoad(((page - 1) * this.pageSize).constrain(0, this.store.getTotalCount()))
			},
			onLoadError : function () {
				if (!this.rendered)
					return;
				this.refresh.enable()
			},
			readPage : function (d) {
				var v = this.inputItem.getValue();
				var pageNum;
				if (!v || isNaN(pageNum = parseInt(v, 10))) {
					this.inputItem.setValue(d.activePage);
					return false
				}
				return pageNum
			},
			onPagingFocus : function () {
				this.inputItem.select()
			},
			onPagingBlur : function (e) {
				this.inputItem.setValue(this.getPageData().activePage)
			},
			onPagingKeyDown : function (field, e) {
				var k = e.getKey();
				var d = this.getPageData();
				var 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;
					field.setValue(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)
							field.setValue(pageNum)
					}
				}
			},
			getParams : function () {
				return this.paramNames || this.store.paramNames
			},
			beforeLoad : function () {
				if (this.rendered &&
					this.refresh)
					this.refresh.disable()
			},
			doLoad : function (start) {
				var o = {};
				var pn = this.getParams();
				o[pn.start] = start;
				o[pn.limit] = this.pageSize;
				if (this.fireEvent("beforechange", this, o) !== false)
					this.store.load({
						params : o
					})
			},
			moveFirst : function () {
				this.doLoad(0)
			},
			movePrevious : function () {
				this.doLoad(Math.max(0, this.cursor - this.pageSize))
			},
			moveNext : function () {
				this.doLoad(this.cursor + this.pageSize)
			},
			moveLast : function () {
				var total = this.store.getTotalCount();
				var extra = total % this.pageSize;
				this.doLoad(extra ? total - extra :
					total - this.pageSize)
			},
			doRefresh : function () {
				this.doLoad(this.cursor)
			},
			bindStore : function (store, initial) {
				var doLoad;
				if (!initial && this.store) {
					if (store !== this.store && this.store.autoDestroy)
						this.store.destroy();
					else {
						this.store.un("beforeload", this.beforeLoad, this);
						this.store.un("load", this.onLoad, this);
						this.store.un("exception", this.onLoadError, this)
					}
					if (!store)
						this.store = null
				}
				if (store) {
					store = Ext.StoreMgr.lookup(store);
					store.on({
						scope : this,
						beforeload : this.beforeLoad,
						load : this.onLoad,
						exception : this.onLoadError
					});
					doLoad = true
				}
				this.store = store;
				if (doLoad)
					this.onLoad(store, null, {})
			},
			unbind : function (store) {
				this.bindStore(null)
			},
			bind : function (store) {
				this.bindStore(store)
			},
			onDestroy : function () {
				this.bindStore(null);
				Ext.PagingToolbar.superclass.onDestroy.call(this)
			}
		})
})();
Ext.reg("paging", Ext.PagingToolbar);
Ext.History = function () {
	function getHash() {
		var href = location.href;
		var i = href.indexOf("#");
		var hash = i >= 0 ? href.substr(i + 1) : null;
		if (Ext.isGecko)
			hash = decodeURIComponent(hash);
		return hash
	}
	function doSave() {
		hiddenField.value = currentToken
	}
	function handleStateChange(token) {
		currentToken = token;
		Ext.History.fireEvent("change", token)
	}
	function updateIFrame(token) {
		var html = ['\x3chtml\x3e\x3cbody\x3e\x3cdiv id\x3d"state"\x3e', Ext.util.Format.htmlEncode(token), "\x3c/div\x3e\x3c/body\x3e\x3c/html\x3e"].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);
				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 ? hiddenField.value : getHash();
		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)
		}
	}
	var iframe;
	var hiddenField;
	var ready = false;
	var currentToken;
	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 {
				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.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,
		closeAction : "hide",
		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[this.closeAction],
					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 (adjust) {
			adjust = adjust || 0;
			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") + adjust;
			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.reg("tip", Ext.Tip);
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 : 5E3,
		trackMouse : false,
		anchorToTarget : true,
		anchorOffset : 0,
		targetCounter : 0,
		constrainPosition : false,
		initComponent : function () {
			Ext.ToolTip.superclass.initComponent.call(this);
			this.lastActive = new Date;
			this.initTarget(this.target);
			this.origAnchor = this.anchor
		},
		onRender : function (ct, position) {
			Ext.ToolTip.superclass.onRender.call(this, ct, position);
			this.anchorCls = "x-tip-anchor-" + this.getAnchorPosition();
			this.anchorEl = this.el.createChild({
					cls : "x-tip-anchor " +
					this.anchorCls
				})
		},
		afterRender : function () {
			Ext.ToolTip.superclass.afterRender.call(this);
			this.anchorEl.setStyle("z-index", this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY)
		},
		initTarget : function (target) {
			var t;
			if (t = Ext.get(target)) {
				if (this.target) {
					var tg = Ext.get(this.target);
					this.mun(tg, "mouseover", this.onTargetOver, this);
					this.mun(tg, "mouseout", this.onTargetOut, this);
					this.mun(tg, "mousemove", this.onMouseMove, this)
				}
				this.mon(t, {
					mouseover : this.onTargetOver,
					mouseout : this.onTargetOut,
					mousemove : this.onMouseMove,
					scope : this
				});
				this.target = t
			}
			if (this.anchor)
				this.anchorTarget = this.target
		},
		onMouseMove : function (e) {
			var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
			if (t) {
				this.targetXY = e.getXY();
				if (t === this.triggerElement) {
					if (!this.hidden && this.trackMouse)
						this.setPagePosition(this.getTargetXY())
				} else {
					this.hide();
					this.lastActive = new Date(0);
					this.onTargetOver(e)
				}
			} else if (!this.closable && this.isVisible())
				this.hide()
		},
		getTargetXY : function () {
			if (this.delegate)
				this.anchorTarget = this.triggerElement;
			if (this.anchor) {
				this.targetCounter++;
				var offsets = this.getOffsets();
				var xy = this.anchorToTarget && !this.trackMouse ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY;
				var dw = Ext.lib.Dom.getViewWidth() - 5;
				var dh = Ext.lib.Dom.getViewHeight() - 5;
				var de = document.documentElement;
				var bd = document.body;
				var scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5;
				var scrollY = (de.scrollTop || bd.scrollTop || 0) + 5;
				var axy = [xy[0] + offsets[0], xy[1] + offsets[1]];
				var sz = this.getSize();
				this.anchorEl.removeClass(this.anchorCls);
				if (this.targetCounter <
					2) {
					if (axy[0] < scrollX) {
						if (this.anchorToTarget) {
							this.defaultAlign = "l-r";
							if (this.mouseOffset)
								this.mouseOffset[0] *= -1
						}
						this.anchor = "left";
						return this.getTargetXY()
					}
					if (axy[0] + sz.width > dw) {
						if (this.anchorToTarget) {
							this.defaultAlign = "r-l";
							if (this.mouseOffset)
								this.mouseOffset[0] *= -1
						}
						this.anchor = "right";
						return this.getTargetXY()
					}
					if (axy[1] < scrollY) {
						if (this.anchorToTarget) {
							this.defaultAlign = "t-b";
							if (this.mouseOffset)
								this.mouseOffset[1] *= -1
						}
						this.anchor = "top";
						return this.getTargetXY()
					}
					if (axy[1] + sz.height > dh) {
						if (this.anchorToTarget) {
							this.defaultAlign =
								"b-t";
							if (this.mouseOffset)
								this.mouseOffset[1] *= -1
						}
						this.anchor = "bottom";
						return this.getTargetXY()
					}
				}
				this.anchorCls = "x-tip-anchor-" + this.getAnchorPosition();
				this.anchorEl.addClass(this.anchorCls);
				this.targetCounter = 0;
				return axy
			} else {
				var mouseOffset = this.getMouseOffset();
				return [this.targetXY[0] + mouseOffset[0], this.targetXY[1] + mouseOffset[1]]
			}
		},
		getMouseOffset : function () {
			var offset = this.anchor ? [0, 0] : [15, 18];
			if (this.mouseOffset) {
				offset[0] += this.mouseOffset[0];
				offset[1] += this.mouseOffset[1]
			}
			return offset
		},
		getAnchorPosition : function () {
			if (this.anchor)
				this.tipAnchor = this.anchor.charAt(0);
			else {
				var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
				if (!m)
					throw "AnchorTip.defaultAlign is invalid";
				this.tipAnchor = m[1].charAt(0)
			}
			switch (this.tipAnchor) {
			case "t":
				return "top";
			case "b":
				return "bottom";
			case "r":
				return "right"
			}
			return "left"
		},
		getAnchorAlign : function () {
			switch (this.anchor) {
			case "top":
				return "tl-bl";
			case "left":
				return "tl-tr";
			case "right":
				return "tr-tl";
			default:
				return "bl-tl"
			}
		},
		getOffsets : function () {
			var offsets;
			var ap = this.getAnchorPosition().charAt(0);
			if (this.anchorToTarget && !this.trackMouse)
				switch (ap) {
				case "t":
					offsets = [0, 9];
					break;
				case "b":
					offsets = [0, -13];
					break;
				case "r":
					offsets = [-13, 0];
					break;
				default:
					offsets = [9, 0];
					break
				}
			else
				switch (ap) {
				case "t":
					offsets = [-15 - this.anchorOffset, 30];
					break;
				case "b":
					offsets = [-19 - this.anchorOffset, -13 - this.el.dom.offsetHeight];
					break;
				case "r":
					offsets = [-15 - this.el.dom.offsetWidth, -13 - this.anchorOffset];
					break;
				default:
					offsets = [25, -13 - this.anchorOffset];
					break
				}
			var mouseOffset = this.getMouseOffset();
			offsets[0] += mouseOffset[0];
			offsets[1] += mouseOffset[1];
			return offsets
		},
		onTargetOver : function (e) {
			if (this.disabled || e.within(this.target.dom, true))
				return;
			var t = e.getTarget(this.delegate);
			if (t) {
				this.triggerElement = t;
				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;
			if (this.anchorEl)
				this.anchorEl.hide();
			Ext.ToolTip.superclass.hide.call(this);
			delete this.triggerElement
		},
		show : function () {
			if (this.anchor) {
				this.showAt([-1E3, -1E3]);
				this.origConstrainPosition =
					this.constrainPosition;
				this.constrainPosition = false;
				this.anchor = this.origAnchor
			}
			this.showAt(this.getTargetXY());
			if (this.anchor) {
				this.anchorEl.show();
				this.syncAnchor();
				this.constrainPosition = this.origConstrainPosition
			} else
				this.anchorEl.hide()
		},
		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);
			if (this.anchor && !this.anchorEl.isVisible()) {
				this.syncAnchor();
				this.anchorEl.show()
			} else
				this.anchorEl.hide()
		},
		syncAnchor : function () {
			var anchorPos;
			var targetPos;
			var offset;
			switch (this.tipAnchor.charAt(0)) {
			case "t":
				anchorPos = "b";
				targetPos = "tl";
				offset = [20 + this.anchorOffset, 2];
				break;
			case "r":
				anchorPos = "l";
				targetPos = "tr";
				offset = [-2, 11 + this.anchorOffset];
				break;
			case "b":
				anchorPos = "t";
				targetPos = "bl";
				offset = [20 + this.anchorOffset, -2];
				break;
			default:
				anchorPos = "r";
				targetPos = "tl";
				offset = [2, 11 + this.anchorOffset];
				break
			}
			this.anchorEl.alignTo(this.el, anchorPos + "-" + targetPos,
				offset)
		},
		setPagePosition : function (x, y) {
			Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
			if (this.anchor)
				this.syncAnchor()
		},
		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 !== true && !this.closable && !e.within(this.el.dom)) {
				this.disable();
				this.doEnable.defer(100, this)
			}
		},
		doEnable : function () {
			if (!this.isDestroyed)
				this.enable()
		},
		onDisable : function () {
			this.clearTimers();
			this.hide()
		},
		adjustPosition : function (x, y) {
			if (this.constrainPosition) {
				var ay = this.targetXY[1];
				var h = this.getSize().height;
				if (y <= ay && y + h >= ay)
					y = ay - h - 5
			}
			return {
				x : x,
				y : y
			}
		},
		beforeDestroy : function () {
			this.clearTimers();
			Ext.destroy(this.anchorEl);
			delete this.anchorEl;
			delete this.target;
			delete this.anchorTarget;
			delete this.triggerElement;
			Ext.ToolTip.superclass.beforeDestroy.call(this)
		},
		onDestroy : function () {
			Ext.getDoc().un("mousedown", this.onDocMouseDown, this);
			Ext.ToolTip.superclass.onDestroy.call(this)
		}
	});
Ext.reg("tooltip", Ext.ToolTip);
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",
			anchor : "anchor"
		},
		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;
			var i = 0;
			for (var len = cs.length; i < len; i++) {
				var c = cs[i];
				var target = c.target;
				if (target)
					if (Ext.isArray(target)) {
						var j =
							0;
						for (var 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)]
		},
		cancelShow : function (el) {
			var at = this.activeTarget;
			el = Ext.get(el).dom;
			if (this.isVisible()) {
				if (at && at.el == el)
					this.hide()
			} else if (at && at.el == el)
				this.clearTimer("show")
		},
		getTipCfg : function (e) {
			var t = e.getTarget();
			var ttp;
			var cfg;
			if (this.interceptTitles && t.title && Ext.isString(t.title)) {
				ttp = t.title;
				t.qtip = ttp;
				t.removeAttribute("title");
				e.preventDefault()
			} else {
				cfg =
					this.tagConfig;
				ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace)
			}
			return ttp
		},
		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 || Ext.fly(this.activeTarget.el).contains(t))) {
				this.clearTimer("hide");
				this.show();
				return
			}
			if (t && this.targets[t.id]) {
				this.activeTarget = this.targets[t.id];
				this.activeTarget.el = t;
				this.anchor = this.activeTarget.anchor;
				if (this.anchor)
					this.anchorTarget = t;
				this.delayShow();
				return
			}
			var ttp;
			var et = Ext.fly(t);
			var cfg = this.tagConfig;
			var ns = cfg.namespace;
			if (ttp = this.getTipCfg(e)) {
				var autoHide = et.getAttribute(cfg.hide, ns);
				this.activeTarget = {
					el : t,
					text : ttp,
					width : et.getAttribute(cfg.width, ns),
					autoHide : autoHide != "user" && autoHide !== "false",
					title : et.getAttribute(cfg.title, ns),
					cls : et.getAttribute(cfg.cls, ns),
					align : et.getAttribute(cfg.align, ns)
				};
				this.anchor = et.getAttribute(cfg.anchor, ns);
				if (this.anchor)
					this.anchorTarget = t;
				this.delayShow()
			}
		},
		onTargetOut : function (e) {
			if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e))
				return;
			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 (this.anchor)
					this.constrainPosition = false;
				else 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.reg("quicktip", Ext.QuickTip);
Ext.QuickTips = function () {
	var tip;
	var disabled = false;
	return {
		init : function (autoRender) {
			if (!tip) {
				if (!Ext.isReady) {
					Ext.onReady(function () {
						Ext.QuickTips.init(autoRender)
					});
					return
				}
				tip = new Ext.QuickTip({
						elements : "header,body",
						disabled : disabled
					});
				if (autoRender !== false)
					tip.render(Ext.getBody())
			}
		},
		ddDisable : function () {
			if (tip && !disabled)
				tip.disable()
		},
		ddEnable : function () {
			if (tip && !disabled)
				tip.enable()
		},
		enable : function () {
			if (tip)
				tip.enable();
			disabled = false
		},
		disable : function () {
			if (tip)
				tip.disable();
			disabled = true
		},
		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.slider.Tip = Ext.extend(Ext.Tip, {
		minWidth : 10,
		offsets : [0, -10],
		init : function (slider) {
			slider.on({
				scope : this,
				dragstart : this.onSlide,
				drag : this.onSlide,
				dragend : this.hide,
				destroy : this.destroy
			})
		},
		onSlide : function (slider, e, thumb) {
			this.show();
			this.body.update(this.getText(thumb));
			this.doAutoWidth();
			this.el.alignTo(thumb.el, "b-t?", this.offsets)
		},
		getText : function (thumb) {
			return String(thumb.value)
		}
	});
Ext.ux.SliderTip = Ext.slider.Tip;
Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
		rootVisible : true,
		animate : Ext.enableFx,
		lines : true,
		enableDD : false,
		hlDrop : Ext.enableFx,
		pathSeparator : "/",
		bubbleEvents : [],
		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,
						requestMethod : this.requestMethod
					});
			else if (Ext.isObject(l) && !l.load)
				l = new Ext.tree.TreeLoader(l);
			this.loader = l;
			this.nodeHash = {};
			if (this.root) {
				var r = this.root;
				delete this.root;
				this.setRootNode(r)
			}
			this.addEvents("append", "remove", "movenode", "insert", "beforeappend", "beforeremove", "beforemovenode", "beforeinsert", "beforeload", "load", "textchange", "beforeexpandnode", "beforecollapsenode", "expandnode", "disabledchange", "collapsenode", "beforeclick", "click", "containerclick", "checkchange", "beforedblclick", "dblclick", "containerdblclick", "contextmenu", "containercontextmenu", "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) {
			this.destroyRoot();
			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)
			}
			if (this.innerCt) {
				this.clearInnerCt();
				this.renderRoot()
			}
			return node
		},
		clearInnerCt : function () {
			this.innerCt.update("")
		},
		renderRoot : function () {
			this.root.render();
			if (!this.rootVisible)
				this.root.renderChildren()
		},
		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
		},
		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) {
			if (Ext.isEmpty(path)) {
				if (callback)
					callback(false, undefined);
				return
			}
			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) {
			if (Ext.isEmpty(path)) {
				if (callback)
					callback(false, undefined);
				return
			}
			attr = attr || "id";
			var keys = path.split(this.pathSeparator);
			var v = keys.pop();
			if (keys.length > 1) {
				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.renderRoot()
		},
		beforeDestroy : function () {
			if (this.rendered) {
				Ext.dd.ScrollManager.unregister(this.body);
				Ext.destroy(this.dropZone, this.dragZone)
			}
			this.destroyRoot();
			Ext.destroy(this.loader);
			this.nodeHash = this.root = this.loader = null;
			Ext.tree.TreePanel.superclass.beforeDestroy.call(this)
		},
		destroyRoot : function () {
			if (this.root && this.root.destroy)
				this.root.destroy(true)
		}
	});
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 t = this.tree;
		if (t.trackMouseOver !== false)
			t.mon(t.innerCt, {
				scope : this,
				mouseover : this.delegateOver,
				mouseout : this.delegateOut
			});
		t.mon(t.getTreeEl(), {
			scope : this,
			click : this.delegateClick,
			dblclick : this.delegateDblClick,
			contextmenu : this.delegateContextMenu
		})
	},
	getNode : function (e) {
		var t;
		if (t = e.getTarget(".x-tree-node-el", 10)) {
			var id = Ext.fly(t, "_treeEvents").getAttribute("tree-node-id", "ext");
			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 (Ext.isGecko && !this.trackingDoc) {
			Ext.getBody().on("mouseover", this.trackExit, this);
			this.trackingDoc =
				true
		}
		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))
	},
	trackExit : function (e) {
		if (this.lastOverNode) {
			if (this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl()))
				this.onNodeOut(e, this.lastOverNode);
			delete this.lastOverNode;
			Ext.getBody().un("mouseover", this.trackExit, this);
			this.trackingDoc = false
		}
	},
	delegateClick : function (e,
		t) {
		if (this.beforeEvent(e))
			if (e.getTarget("input[type\x3dcheckbox]", 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))
			}
		else
			this.checkContainerEvent(e, "click")
	},
	delegateDblClick : function (e, t) {
		if (this.beforeEvent(e)) {
			if (this.getNodeTarget(e))
				this.onNodeDblClick(e, this.getNode(e))
		} else
			this.checkContainerEvent(e, "dblclick")
	},
	delegateContextMenu : function (e, t) {
		if (this.beforeEvent(e)) {
			if (this.getNodeTarget(e))
				this.onNodeContextMenu(e,
					this.getNode(e))
		} else
			this.checkContainerEvent(e, "contextmenu")
	},
	checkContainerEvent : function (e, type) {
		if (this.disabled) {
			e.stopEvent();
			return false
		}
		this.onContainerEvent(e, type)
	},
	onContainerEvent : function (e, type) {
		this.tree.fireEvent("container" + type, this.tree, e)
	},
	onNodeClick : function (e, node) {
		node.ui.onClick(e)
	},
	onNodeOver : function (e, node) {
		this.lastOverNode = 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) {
		var node = this.getNode(e);
		if (this.disabled || !node || !node.ui) {
			e.stopEvent();
			return false
		}
		return true
	},
	disable : function () {
		this.disabled = true
	},
	enable : function () {
		this.disabled = false
	}
};
Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
		constructor : function (config) {
			this.selNode = null;
			this.addEvents("selectionchange", "beforeselect");
			Ext.apply(this, config);
			Ext.tree.DefaultSelectionModel.superclass.constructor.call(this)
		},
		init : function (tree) {
			this.tree = tree;
			tree.mon(tree.getTreeEl(), "keydown", this.onKeyDown, this);
			tree.on("click", this.onNodeClick, this)
		},
		onNodeClick : function (node, e) {
			this.select(node)
		},
		select : function (node, selectNextNode) {
			if (!Ext.fly(node.ui.wrap).isVisible() &&
				selectNextNode)
				return selectNextNode.call(this, node);
			var last = this.selNode;
			if (node == last)
				node.ui.onSelectedChange(true);
			else if (this.fireEvent("beforeselect", this, node, last) !== false) {
				if (last && last.ui)
					last.ui.onSelectedChange(false);
				this.selNode = node;
				node.ui.onSelectedChange(true);
				this.fireEvent("selectionchange", this, node, last)
			}
			return node
		},
		unselect : function (node, silent) {
			if (this.selNode == node)
				this.clearSelections(silent)
		},
		clearSelections : function (silent) {
			var n = this.selNode;
			if (n) {
				n.ui.onSelectedChange(false);
				this.selNode = null;
				if (silent !== true)
					this.fireEvent("selectionchange", this, null)
			}
			return n
		},
		getSelectedNode : function () {
			return this.selNode
		},
		isSelected : function (node) {
			return this.selNode == node
		},
		selectPrevious : function (s) {
			if (!(s = s || this.selNode || this.lastSelNode))
				return null;
			var ps = s.previousSibling;
			if (ps)
				if (!ps.isExpanded() || ps.childNodes.length < 1)
					return this.select(ps, this.selectPrevious);
				else {
					for (var lc = ps.lastChild; lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0; )
						lc = lc.lastChild;
					return this.select(lc, this.selectPrevious)
				}
			else if (s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot))
				return this.select(s.parentNode, this.selectPrevious);
			return null
		},
		selectNext : function (s) {
			if (!(s = s || this.selNode || this.lastSelNode))
				return null;
			if (s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible())
				return this.select(s.firstChild, this.selectNext);
			else if (s.nextSibling)
				return this.select(s.nextSibling, this.selectNext);
			else if (s.parentNode) {
				var newS = null;
				s.parentNode.bubble(function () {
					if (this.nextSibling) {
						newS =
							this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
						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 = Ext.extend(Ext.util.Observable, {
		constructor : function (config) {
			this.selNodes = [];
			this.selMap = {};
			this.addEvents("selectionchange");
			Ext.apply(this, config);
			Ext.tree.MultiSelectionModel.superclass.constructor.call(this)
		},
		init : function (tree) {
			this.tree = tree;
			tree.mon(tree.getTreeEl(), "keydown", this.onKeyDown, this);
			tree.on("click", this.onNodeClick, this)
		},
		onNodeClick : function (node, e) {
			if (e.ctrlKey && this.isSelected(node))
				this.unselect(node);
			else
				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) {
				var i = 0;
				for (var 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.concat([])
		},
		onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
		selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
		selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
	});
Ext.data.Tree = Ext.extend(Ext.util.Observable, {
		constructor : 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)
		},
		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 = Ext.extend(Ext.util.Observable, {
		constructor : function (attributes) {
			this.attributes = attributes || {};
			this.leaf = this.attributes.leaf;
			this.id = this.attributes.id;
			if (!this.id) {
				this.id = Ext.id(null, "xnode-");
				this.attributes.id = this.id
			}
			this.childNodes = [];
			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)
		},
		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) {
				var i = 0;
				for (var 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, destroy) {
			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);
			this.fireEvent("remove", this.ownerTree, this, node);
			if (destroy)
				node.destroy(true);
			else
				node.clear();
			return node
		},
		clear : function (destroy) {
			this.setOwnerTree(null, destroy);
			this.parentNode = this.previousSibling = this.nextSibling = null;
			if (destroy)
				this.firstChild = this.lastChild = null
		},
		destroy : function (silent) {
			if (silent === true) {
				this.purgeListeners();
				this.clear(true);
				Ext.each(this.childNodes,
					function (n) {
					n.destroy(true)
				});
				this.childNodes = null
			} else
				this.remove(true)
		},
		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 (destroy) {
			if (this.parentNode)
				this.parentNode.removeChild(this, destroy);
			return this
		},
		removeAll : function (destroy) {
			var cn = this.childNodes;
			for (var n; n = cn[0]; )
				this.removeChild(n, destroy);
			return this
		},
		item : function (index) {
			return this.childNodes[index]
		},
		replaceChild : function (newChild, oldChild) {
			var s = oldChild ? oldChild.nextSibling : null;
			this.removeChild(oldChild);
			this.insertBefore(newChild, s);
			return oldChild
		},
		indexOf : function (child) {
			return this.childNodes.indexOf(child)
		},
		getOwnerTree : function () {
			if (!this.ownerTree)
				for (var p = this; p; ) {
					if (p.ownerTree) {
						this.ownerTree = p.ownerTree;
						break
					}
					p = p.parentNode
				}
			return this.ownerTree
		},
		getDepth : function () {
			var depth = 0;
			for (var p = this; p.parentNode; ) {
				++depth;
				p = p.parentNode
			}
			return depth
		},
		setOwnerTree : function (tree, destroy) {
			if (tree != this.ownerTree) {
				if (this.ownerTree)
					this.ownerTree.unregisterNode(this);
				this.ownerTree = tree;
				if (destroy !== true)
					Ext.each(this.childNodes, function (n) {
						n.setOwnerTree(tree)
					});
				if (tree)
					tree.registerNode(this)
			}
		},
		setId : function (id) {
			if (id !==
				this.id) {
				var t = this.ownerTree;
				if (t)
					t.unregisterNode(this);
				this.id = this.attributes.id = id;
				if (t)
					t.registerNode(this);
				this.onIdChange(id)
			}
		},
		onIdChange : Ext.emptyFn,
		getPath : function (attr) {
			attr = attr || "id";
			var p = this.parentNode;
			for (var b = [this.attributes[attr]]; p; ) {
				b.unshift(p.attributes[attr]);
				p = p.parentNode
			}
			var sep = this.getOwnerTree().pathSeparator;
			return sep + b.join(sep)
		},
		bubble : function (fn, scope, args) {
			for (var p = this; 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;
				var i = 0;
				for (var len = cs.length; i < len; i++)
					cs[i].cascade(fn, scope, args)
			}
		},
		eachChild : function (fn, scope, args) {
			var cs = this.childNodes;
			var i = 0;
			for (var len = cs.length; i < len; i++)
				if (fn.apply(scope || cs[i], args || [cs[i]]) === false)
					break
		},
		findChild : function (attribute, value, deep) {
			return this.findChildBy(function () {
				return this.attributes[attribute] == value
			}, null, deep)
		},
		findChildBy : function (fn, scope, deep) {
			var cs = this.childNodes;
			var len =
				cs.length;
			var i = 0;
			var n;
			for (var res; i < len; i++) {
				n = cs[i];
				if (fn.call(scope || n, n) === true)
					return n;
				else if (deep) {
					res = n.findChildBy(fn, scope, deep);
					if (res != null)
						return res
				}
			}
			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) {
			for (var p = this.parentNode; p; ) {
				if (p == node)
					return true;
				p = p.parentNode
			}
			return false
		},
		toString : function () {
			return "[Node" + (this.id ? " " + this.id : "") + "]"
		}
	});
Ext.tree.TreeNode = Ext.extend(Ext.data.Node, {
		constructor : function (attributes) {
			attributes = attributes || {};
			if (Ext.isString(attributes))
				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.hidden = attributes.hidden === true;
			this.addEvents("textchange", "beforeexpand", "beforecollapse", "expand", "disabledchange", "collapse", "beforeclick", "click", "checkchange", "beforedblclick", "dblclick", "contextmenu", "beforechildrenrendered");
			var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
			this.ui = new uiClass(this)
		},
		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 : this.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, destroy) {
			this.ownerTree.getSelectionModel().unselect(node);
			Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
			if (!destroy) {
				var rendered = node.ui.rendered;
				if (rendered)
					node.ui.remove();
				if (rendered && 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.call(this, node, refNode);
			if (newNode && refNode && this.childrenRendered)
				node.render();
			this.ui.updateExpandIcon();
			return newNode
		},
		setText : function (text) {
			var oldText =
				this.text;
			this.text = this.attributes.text = text;
			if (this.rendered)
				this.ui.onTextChange(this, text, oldText);
			this.fireEvent("textchange", this, text, oldText)
		},
		setIconCls : function (cls) {
			var old = this.attributes.iconCls;
			this.attributes.iconCls = cls;
			if (this.rendered)
				this.ui.onIconClsChange(this, cls, old)
		},
		setTooltip : function (tip, title) {
			this.attributes.qtip = tip;
			this.attributes.qtipTitle = title;
			if (this.rendered)
				this.ui.onTipChange(this, tip, title)
		},
		setIcon : function (icon) {
			this.attributes.icon = icon;
			if (this.rendered)
				this.ui.onIconChange(this,
					icon)
		},
		setHref : function (href, target) {
			this.attributes.href = href;
			this.attributes.hrefTarget = target;
			if (this.rendered)
				this.ui.onHrefChange(this, href, target)
		},
		setCls : function (cls) {
			var old = this.attributes.cls;
			this.attributes.cls = cls;
			if (this.rendered)
				this.ui.onClsChange(this, cls, old)
		},
		select : function () {
			var t = this.getOwnerTree();
			if (t)
				t.getSelectionModel().select(this)
		},
		unselect : function (silent) {
			var t = this.getOwnerTree();
			if (t)
				t.getSelectionModel().unselect(this, silent)
		},
		isSelected : function () {
			var t = this.getOwnerTree();
			return t ? t.getSelectionModel().isSelected(this) : false
		},
		expand : function (deep, anim, callback, scope) {
			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);
						this.runCallback(callback, scope || this, [this]);
						if (deep === true)
							this.expandChildNodes(true, true)
					}
						.createDelegate(this));
					return
				} else {
					this.ui.expand();
					this.fireEvent("expand", this);
					this.runCallback(callback, scope || this, [this])
				}
			} else
				this.runCallback(callback, scope || this, [this]);
			if (deep === true)
				this.expandChildNodes(true)
		},
		runCallback : function (cb, scope, args) {
			if (Ext.isFunction(cb))
				cb.apply(scope, args)
		},
		isHiddenRoot : function () {
			return this.isRoot && !this.getOwnerTree().rootVisible
		},
		collapse : function (deep, anim, callback, scope) {
			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);
						this.runCallback(callback, scope || this, [this]);
						if (deep === true)
							this.collapseChildNodes(true)
					}
						.createDelegate(this));
					return
				} else {
					this.ui.collapse();
					this.fireEvent("collapse", this);
					this.runCallback(callback, scope || this, [this])
				}
			} else if (!this.expanded)
				this.runCallback(callback, scope || this, [this]);
			if (deep === true) {
				var cs = this.childNodes;
				var i = 0;
				for (var 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, scope) {
			var tree = this.getOwnerTree();
			tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function () {
				var node = tree.getNodeById(this.id);
				tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
				this.runCallback(callback, scope || this, [this])
			}
				.createDelegate(this))
		},
		expandChildNodes : function (deep, anim) {
			var cs = this.childNodes;
			var i;
			var len = cs.length;
			for (i = 0; i < len; i++)
				cs[i].expand(deep, anim)
		},
		collapseChildNodes : function (deep) {
			var cs = this.childNodes;
			var i = 0;
			for (var 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;
			var i = 0;
			for (var 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;
				var i = 0;
				for (var 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;
				var i = 0;
				for (var 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 (silent) {
			if (silent === true)
				this.unselect(true);
			Ext.tree.TreeNode.superclass.destroy.call(this, silent);
			Ext.destroy(this.ui, this.loader);
			this.ui = this.loader = null
		},
		onIdChange : function (id) {
			this.ui.onIdChange(id)
		}
	});
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, scope) {
		if (this.loading) {
			var timer;
			var f = function () {
				if (!this.loading) {
					clearInterval(timer);
					this.expand(deep, anim, callback, scope)
				}
			}
			.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, scope]), this);
				return
			}
		}
		Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope)
	},
	isLoading : function () {
		return this.loading
	},
	loadComplete : function (deep, anim, callback, scope) {
		this.loading = false;
		this.loaded = true;
		this.ui.afterLoad(this);
		this.fireEvent("load", this);
		this.expand(deep, anim, callback, scope)
	},
	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, scope) {
		for (this.collapse(false, false); this.firstChild; )
			this.removeChild(this.firstChild).destroy();
		this.childrenRendered = false;
		this.loaded = false;
		if (this.isHiddenRoot())
			this.expanded = false;
		this.expand(false, false, callback, scope)
	}
});
Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
Ext.tree.TreeNodeUI = Ext.extend(Object, {
		constructor : function (node) {
			Ext.apply(this, {
				node : node,
				rendered : false,
				animating : false,
				wasLeaf : true,
				ecc : "x-tree-ec-icon x-tree-elbow",
				emptyIcon : Ext.BLANK_IMAGE_URL
			})
		},
		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
		},
		onIconClsChange : function (node,
			cls, oldCls) {
			if (this.rendered)
				Ext.fly(this.iconNode).replaceClass(oldCls, cls)
		},
		onIconChange : function (node, icon) {
			if (this.rendered) {
				var empty = Ext.isEmpty(icon);
				this.iconNode.src = empty ? this.emptyIcon : icon;
				Ext.fly(this.iconNode)[empty ? "removeClass" : "addClass"]("x-tree-node-inline-icon")
			}
		},
		onTipChange : function (node, tip, title) {
			if (this.rendered) {
				var hasTitle = Ext.isDefined(title);
				if (this.textNode.setAttributeNS) {
					this.textNode.setAttributeNS("ext", "qtip", tip);
					if (hasTitle)
						this.textNode.setAttributeNS("ext",
							"qtitle", title)
				} else {
					this.textNode.setAttribute("ext:qtip", tip);
					if (hasTitle)
						this.textNode.setAttribute("ext:qtitle", title)
				}
			}
		},
		onHrefChange : function (node, href, target) {
			if (this.rendered) {
				this.anchor.href = this.getHref(href);
				if (Ext.isDefined(target))
					this.anchor.target = target
			}
		},
		onClsChange : function (node, cls, oldCls) {
			if (this.rendered)
				Ext.fly(this.elNode).replaceClass(oldCls, cls)
		},
		onDisableChange : function (node, state) {
			this.disabled = state;
			if (this.checkbox)
				this.checkbox.disabled = state;
			this[state ? "addClass" : "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, oldParent != newParent)
			}
		},
		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.onDisableChange(this.node,
					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.fireEvent("beforedblclick", this.node, e) !== false) {
				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
				try {
					var noscroll = this.node.getOwnerTree().getTreeEl().dom;
					var l = noscroll.scrollLeft;
					this.anchor.focus();
					noscroll.scrollLeft = l
				} catch (e$$0) {}

		},
		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 || 0.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 || 0.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;
			var 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)
					this.onTipChange(n, a.qtip, 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 =
				Ext.isBoolean(a.checked);
			var nel;
			var href = this.getHref(a.href);
			var buf = ['\x3cli class\x3d"x-tree-node"\x3e\x3cdiv ext:tree-node-id\x3d"', n.id, '" class\x3d"x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls, '" unselectable\x3d"on"\x3e', '\x3cspan class\x3d"x-tree-node-indent"\x3e', this.indentMarkup, "\x3c/span\x3e", '\x3cimg alt\x3d"" src\x3d"', this.emptyIcon, '" class\x3d"x-tree-ec-icon x-tree-elbow" /\x3e', '\x3cimg alt\x3d"" src\x3d"', a.icon || this.emptyIcon, '" class\x3d"x-tree-node-icon', a.icon ?
				" x-tree-node-inline-icon" : "", a.iconCls ? " " + a.iconCls : "", '" unselectable\x3d"on" /\x3e', cb ? '\x3cinput class\x3d"x-tree-node-cb" type\x3d"checkbox" ' + (a.checked ? 'checked\x3d"checked" /\x3e' : "/\x3e") : "", '\x3ca hidefocus\x3d"on" class\x3d"x-tree-node-anchor" href\x3d"', href, '" tabIndex\x3d"1" ', a.hrefTarget ? ' target\x3d"' + a.hrefTarget + '"' : "", '\x3e\x3cspan unselectable\x3d"on"\x3e', n.text, "\x3c/span\x3e\x3c/a\x3e\x3c/div\x3e", '\x3cul class\x3d"x-tree-node-ct" style\x3d"display:none;"\x3e\x3c/ul\x3e',
				"\x3c/li\x3e"].join("");
			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
		},
		getHref : function (href) {
			return Ext.isEmpty(href) ? Ext.isGecko ? "" : "#" : href
		},
		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;
				var c1;
				var c2;
				var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
				var hasChild = n.hasChildNodes();
				if (hasChild || n.attributes.expandable) {
					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-collapsed");
					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
				}
			}
		},
		onIdChange : function (id) {
			if (this.rendered)
				this.elNode.setAttribute("ext:tree-node-id", id)
		},
		getChildIndent : function () {
			if (!this.childIndent) {
				var buf = [];
				for (var p = this.node; p; ) {
					if (!p.isRoot || p.isRoot && p.ownerTree.rootVisible)
						if (!p.isLast())
							buf.unshift('\x3cimg alt\x3d"" src\x3d"' + this.emptyIcon + '" class\x3d"x-tree-elbow-line" /\x3e');
						else
							buf.unshift('\x3cimg alt\x3d"" src\x3d"' + this.emptyIcon + '" class\x3d"x-tree-icon" /\x3e');
					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);
			Ext.each(["textnode", "anchor", "checkbox", "indentNode", "ecNode", "iconNode", "elNode", "ctNode", "wrap", "holder"], function (el) {
				if (this[el]) {
					Ext.fly(this[el]).remove();
					delete this[el]
				}
			}, this);
			delete this.node
		}
	});
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 = '\x3cdiv class\x3d"x-tree-root-node"\x3e\x3c/div\x3e';
				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);
	if (Ext.isString(this.paramOrder))
		this.paramOrder = this.paramOrder.split(/[\s,|]/)
};
Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
	uiProviders : {},
	clearOnLoad : true,
	paramOrder : undefined,
	paramsAsHash : false,
	nodeParameter : "node",
	directFn : undefined,
	load : function (node, callback, scope) {
		if (this.clearOnLoad)
			for (; node.firstChild; )
				node.removeChild(node.firstChild);
		if (this.doPreload(node))
			this.runCallback(callback, scope || node, [node]);
		else if (this.directFn || this.dataUrl || this.url)
			this.requestData(node, callback, scope || node)
	},
	doPreload : function (node) {
		if (node.attributes.children) {
			if (node.childNodes.length <
				1) {
				var cs = node.attributes.children;
				node.beginUpdate();
				var i = 0;
				for (var len = cs.length; i < len; i++) {
					var cn = node.appendChild(this.createNode(cs[i]));
					if (this.preloadChildren)
						this.doPreload(cn)
				}
				node.endUpdate()
			}
			return true
		}
		return false
	},
	getParams : function (node) {
		var bp = Ext.apply({}, this.baseParams);
		var np = this.nodeParameter;
		var po = this.paramOrder;
		np && (bp[np] = node.id);
		if (this.directFn) {
			var buf = [node.id];
			if (po) {
				if (np && po.indexOf(np) > -1)
					buf = [];
				var i = 0;
				for (var len = po.length; i < len; i++)
					buf.push(bp[po[i]])
			} else if (this.paramsAsHash)
				buf =
					[bp];
			return buf
		} else
			return bp
	},
	requestData : function (node, callback, scope) {
		if (this.fireEvent("beforeload", this, node, callback) !== false)
			if (this.directFn) {
				var args = this.getParams(node);
				args.push(this.processDirectResponse.createDelegate(this, [{
								callback : callback,
								node : node,
								scope : scope
							}
						], true));
				this.directFn.apply(window, args)
			} else
				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,
							scope : scope
						},
						params : this.getParams(node)
					});
		else
			this.runCallback(callback, scope || node, [])
	},
	processDirectResponse : function (result, response, args) {
		if (response.status)
			this.handleResponse({
				responseData : Ext.isArray(result) ? result : null,
				responseText : result,
				argument : args
			});
		else
			this.handleFailure({
				argument : args
			})
	},
	runCallback : function (cb, scope, args) {
		if (Ext.isFunction(cb))
			cb.apply(scope, args)
	},
	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)
			attr.loader = this;
		if (Ext.isString(attr.uiProvider))
			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, scope) {
		var json = response.responseText;
		try {
			var o = response.responseData ||
				Ext.decode(json);
			node.beginUpdate();
			var i = 0;
			for (var len = o.length; i < len; i++) {
				var n = this.createNode(o[i]);
				if (n)
					node.appendChild(n)
			}
			node.endUpdate();
			this.runCallback(callback, scope || node, [node])
		} catch (e) {
			this.handleFailure(response)
		}
	},
	handleResponse : function (response) {
		this.transId = false;
		var a = response.argument;
		this.processResponse(response, a.node, a.callback, a.scope);
		this.fireEvent("load", this, a.node, response)
	},
	handleFailure : function (response) {
		this.transId = false;
		var a = response.argument;
		this.fireEvent("loadexception",
			this, a.node, response);
		this.runCallback(a.callback, a.scope || a.node, [a.node])
	},
	destroy : function () {
		this.abort();
		this.purgeListeners()
	}
});
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;
		var 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$$0 = af[id];
					if (n$$0 && n$$0.parentNode)
						n$$0.parentNode.removeChild(n$$0)
				}
	},
	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 = Ext.extend(Object, {
		constructor : function (tree, config) {
			Ext.apply(this, config);
			tree.on({
				scope : this,
				beforechildrenrendered : this.doSort,
				append : this.updateSort,
				insert : this.updateSort,
				textchange : this.updateSortParent
			});
			var desc = this.dir && this.dir.toLowerCase() == "desc";
			var prop = this.property || "text";
			var sortType = this.sortType;
			var folderSort = this.folderSort;
			var caseSensitive = this.caseSensitive === true;
			var leafAttr = this.leafAttr || "leaf";
			if (Ext.isString(sortType))
				sortType = Ext.data.SortTypes[sortType];
			this.sortFn = function (n1, n2) {
				var attr1 = n1.attributes;
				var attr2 = n2.attributes;
				if (folderSort) {
					if (attr1[leafAttr] && !attr2[leafAttr])
						return 1;
					if (!attr1[leafAttr] && attr2[leafAttr])
						return -1
				}
				var prop1 = attr1[prop];
				var prop2 = attr2[prop];
				var v1 = sortType ? sortType(prop1) : caseSensitive ? prop1 : prop1.toUpperCase();
				var v2 = sortType ? sortType(prop2) : caseSensitive ? prop2 : prop2.toUpperCase();
				if (v1 < v2)
					return desc ? 1 : -1;
				else if (v1 > v2)
					return desc ? -1 : 1;
				return 0
			}
		},
		doSort : function (node) {
			node.sort(this.sortFn)
		},
		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 = config.allowParentInsert || false;
		this.allowContainerDrop = config.allowContainerDrop || false;
		this.appendOnly = config.appendOnly || false;
		Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
		this.tree = tree;
		this.dragOverData = {};
		this.lastInsertClass = "x-tree-no-status"
	};
	Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
		ddGroup : "TreeDD",
		expandDelay : 1E3,
		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);
			var 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()
		},
		onContainerOver : function (dd, e, data) {
			if (this.allowContainerDrop && this.isValidDropPoint({
					ddel : this.tree.getRootNode().ui.elNode,
					node : this.tree.getRootNode()
				}, "append", dd, e, data))
				return this.dropAllowed;
			return this.dropNotAllowed
		},
		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);
			return this.processDrop(targetNode,
				data, point, dd, e, dropNode)
		},
		onContainerDrop : function (dd, e, data) {
			if (this.allowContainerDrop && this.isValidDropPoint({
					ddel : this.tree.getRootNode().ui.elNode,
					node : this.tree.getRootNode()
				}, "append", dd, e, data)) {
				var targetNode = this.tree.getRootNode();
				targetNode.ui.startDrop();
				var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, "append", e) : null);
				return this.processDrop(targetNode, data, "append", dd, e, dropNode)
			}
			return false
		},
		processDrop : function (target, data, point, dd, e, dropNode) {
			var dropEvent = {
				tree : this.tree,
				target : target,
				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) {
				target.ui.endDrop();
				return dropEvent.dropStatus
			}
			target = dropEvent.target;
			if (point == "append" && !target.isExpanded())
				target.expand(false, null, function () {
					this.completeDrop(dropEvent)
				}
					.createDelegate(this));
			else
				this.completeDrop(dropEvent);
			return true
		},
		completeDrop : function (de) {
			var ns =
				de.dropNode;
			var p = de.point;
			var t = de.target;
			if (!Ext.isArray(ns))
				ns = [ns];
			var n;
			var i = 0;
			for (var 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.innerCt, 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({
			scope : this,
			beforeclick : this.beforeNodeClick,
			dblclick : this.onNodeDblClick
		});
		this.on({
			scope : this,
			complete : this.updateNode,
			beforestartedit : this.fitToTree,
			specialkey : this.onSpecialKey
		});
		this.on("startedit", this.bindScroll, this, {
			delay : 10
		})
	},
	fitToTree : function (ed, el) {
		var td = this.tree.getTreeEl().dom;
		var 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)
				Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
			var value = node.text || "";
			if (!Ext.isGecko && Ext.isEmpty(node.text))
				node.setText("\x26#160;");
			this.autoEditTimer =
				this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
			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()
		}
	},
	onDestroy : function () {
		clearTimeout(this.autoEditTimer);
		Ext.tree.TreeEditor.superclass.onDestroy.call(this);
		var tree = this.tree;
		tree.un("beforeclick", this.beforeNodeClick, this);
		tree.un("dblclick", this.onNodeDblClick,
			this)
	}
});
var swfobject = function () {
	function callDomLoadFunctions() {
		if (isDomLoaded)
			return;
		try {
			var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
			t.parentNode.removeChild(t)
		} catch (e) {
			return
		}
		isDomLoaded = true;
		var dl = domLoadFnArr.length;
		for (var i = 0; i < dl; i++)
			domLoadFnArr[i]()
	}
	function addDomLoadEvent(fn) {
		if (isDomLoaded)
			fn();
		else
			domLoadFnArr[domLoadFnArr.length] = fn
	}
	function addLoadEvent(fn) {
		if (typeof win.addEventListener != UNDEF)
			win.addEventListener("load", fn, false);
		else if (typeof doc.addEventListener != UNDEF)
			doc.addEventListener("load",
				fn, false);
		else if (typeof win.attachEvent != UNDEF)
			addListener(win, "onload", fn);
		else if (typeof win.onload == "function") {
			var fnOld = win.onload;
			win.onload = function () {
				fnOld();
				fn()
			}
		} else
			win.onload = fn
	}
	function main() {
		if (plugin)
			testPlayerVersion();
		else
			matchVersions()
	}
	function testPlayerVersion() {
		var b = doc.getElementsByTagName("body")[0];
		var o = createElement(OBJECT);
		o.setAttribute("type", FLASH_MIME_TYPE);
		var t = b.appendChild(o);
		if (t) {
			var counter = 0;
			(function () {
				if (typeof t.GetVariable != UNDEF) {
					var d = t.GetVariable("$version");
					if (d) {
						d = d.split(" ")[1].split(",");
						ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]
					}
				} else if (counter < 10) {
					counter++;
					setTimeout(arguments.callee, 10);
					return
				}
				b.removeChild(o);
				t = null;
				matchVersions()
			})()
		} else
			matchVersions()
	}
	function matchVersions() {
		var rl = regObjArr.length;
		if (rl > 0)
			for (var i = 0; i < rl; i++) {
				var id = regObjArr[i].id;
				var cb = regObjArr[i].callbackFn;
				var cbObj = {
					success : false,
					id : id
				};
				if (ua.pv[0] > 0) {
					var obj = getElementById(id);
					if (obj)
						if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk &&
								ua.wk < 312)) {
							setVisibility(id, true);
							if (cb) {
								cbObj.success = true;
								cbObj.ref = getObjectById(id);
								cb(cbObj)
							}
						} else if (regObjArr[i].expressInstall && canExpressInstall()) {
							var att = {};
							att.data = regObjArr[i].expressInstall;
							att.width = obj.getAttribute("width") || "0";
							att.height = obj.getAttribute("height") || "0";
							if (obj.getAttribute("class"))
								att.styleclass = obj.getAttribute("class");
							if (obj.getAttribute("align"))
								att.align = obj.getAttribute("align");
							var par = {};
							var p = obj.getElementsByTagName("param");
							var pl = p.length;
							for (var j =
									0; j < pl; j++)
								if (p[j].getAttribute("name").toLowerCase() != "movie")
									par[p[j].getAttribute("name")] = p[j].getAttribute("value");
							showExpressInstall(att, par, id, cb)
						} else {
							displayAltContent(obj);
							if (cb)
								cb(cbObj)
						}
				} else {
					setVisibility(id, true);
					if (cb) {
						var o = getObjectById(id);
						if (o && typeof o.SetVariable != UNDEF) {
							cbObj.success = true;
							cbObj.ref = o
						}
						cb(cbObj)
					}
				}
			}
	}
	function getObjectById(objectIdStr) {
		var r = null;
		var o = getElementById(objectIdStr);
		if (o && o.nodeName == "OBJECT")
			if (typeof o.SetVariable != UNDEF)
				r = o;
			else {
				var n = o.getElementsByTagName(OBJECT)[0];
				if (n)
					r = n
			}
		return r
	}
	function canExpressInstall() {
		return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312)
	}
	function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
		isExpressInstallActive = true;
		storedCallbackFn = callbackFn || null;
		storedCallbackObj = {
			success : false,
			id : replaceElemIdStr
		};
		var obj = getElementById(replaceElemIdStr);
		if (obj) {
			if (obj.nodeName == "OBJECT") {
				storedAltContent = abstractAltContent(obj);
				storedAltContentId = null
			} else {
				storedAltContent = obj;
				storedAltContentId =
					replaceElemIdStr
			}
			att.id = EXPRESS_INSTALL_ID;
			if (typeof att.width == UNDEF || !/%$/.test(att.width) && parseInt(att.width, 10) < 310)
				att.width = "310";
			if (typeof att.height == UNDEF || !/%$/.test(att.height) && parseInt(att.height, 10) < 137)
				att.height = "137";
			doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
			var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn";
			var fv = "MMredirectURL\x3d" + win.location.toString().replace(/&/g, "%26") + "\x26MMplayerType\x3d" + pt + "\x26MMdoctitle\x3d" + doc.title;
			if (typeof par.flashvars != UNDEF)
				par.flashvars +=
				"\x26" + fv;
			else
				par.flashvars = fv;
			if (ua.ie && ua.win && obj.readyState != 4) {
				var newObj = createElement("div");
				replaceElemIdStr += "SWFObjectNew";
				newObj.setAttribute("id", replaceElemIdStr);
				obj.parentNode.insertBefore(newObj, obj);
				obj.style.display = "none";
				(function () {
					if (obj.readyState == 4)
						obj.parentNode.removeChild(obj);
					else
						setTimeout(arguments.callee, 10)
				})()
			}
			createSWF(att, par, replaceElemIdStr)
		}
	}
	function displayAltContent(obj) {
		if (ua.ie && ua.win && obj.readyState != 4) {
			var el = createElement("div");
			obj.parentNode.insertBefore(el,
				obj);
			el.parentNode.replaceChild(abstractAltContent(obj), el);
			obj.style.display = "none";
			(function () {
				if (obj.readyState == 4)
					obj.parentNode.removeChild(obj);
				else
					setTimeout(arguments.callee, 10)
			})()
		} else
			obj.parentNode.replaceChild(abstractAltContent(obj), obj)
	}
	function abstractAltContent(obj) {
		var ac = createElement("div");
		if (ua.win && ua.ie)
			ac.innerHTML = obj.innerHTML;
		else {
			var nestedObj = obj.getElementsByTagName(OBJECT)[0];
			if (nestedObj) {
				var c = nestedObj.childNodes;
				if (c) {
					var cl = c.length;
					for (var i = 0; i < cl; i++)
						if (!(c[i].nodeType ==
								1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8))
							ac.appendChild(c[i].cloneNode(true))
				}
			}
		}
		return ac
	}
	function createSWF(attObj, parObj, id) {
		var r;
		var el = getElementById(id);
		if (ua.wk && ua.wk < 312)
			return r;
		if (el) {
			if (typeof attObj.id == UNDEF)
				attObj.id = id;
			if (ua.ie && ua.win) {
				var att = "";
				for (var i in attObj)
					if (attObj[i] != Object.prototype[i])
						if (i.toLowerCase() == "data")
							parObj.movie = attObj[i];
						else if (i.toLowerCase() == "styleclass")
							att += ' class\x3d"' + attObj[i] + '"';
						else if (i.toLowerCase() != "classid")
							att += " " + i + '\x3d"' + attObj[i] +
							'"';
				var par = "";
				for (var j in parObj)
					if (parObj[j] != Object.prototype[j])
						par += '\x3cparam name\x3d"' + j + '" value\x3d"' + parObj[j] + '" /\x3e';
				el.outerHTML = '\x3cobject classid\x3d"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + "\x3e" + par + "\x3c/object\x3e";
				objIdArr[objIdArr.length] = attObj.id;
				r = getElementById(attObj.id)
			} else {
				var o = createElement(OBJECT);
				o.setAttribute("type", FLASH_MIME_TYPE);
				for (var m in attObj)
					if (attObj[m] != Object.prototype[m])
						if (m.toLowerCase() == "styleclass")
							o.setAttribute("class", attObj[m]);
						else if (m.toLowerCase() != "classid")
							o.setAttribute(m, attObj[m]);
				for (var n in parObj)
					if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie")
						createObjParam(o, n, parObj[n]);
				el.parentNode.replaceChild(o, el);
				r = o
			}
		}
		return r
	}
	function createObjParam(el, pName, pValue) {
		var p = createElement("param");
		p.setAttribute("name", pName);
		p.setAttribute("value", pValue);
		el.appendChild(p)
	}
	function removeSWF(id) {
		var obj = getElementById(id);
		if (obj && obj.nodeName == "OBJECT")
			if (ua.ie && ua.win) {
				obj.style.display = "none";
				(function () {
					if (obj.readyState ==
						4)
						removeObjectInIE(id);
					else
						setTimeout(arguments.callee, 10)
				})()
			} else
				obj.parentNode.removeChild(obj)
	}
	function removeObjectInIE(id) {
		var obj = getElementById(id);
		if (obj) {
			for (var i in obj)
				if (typeof obj[i] == "function")
					obj[i] = null;
			obj.parentNode.removeChild(obj)
		}
	}
	function getElementById(id) {
		var el = null;
		try {
			el = doc.getElementById(id)
		} catch (e) {}

		return el
	}
	function createElement(el) {
		return doc.createElement(el)
	}
	function addListener(target, eventType, fn) {
		target.attachEvent(eventType, fn);
		listenersArr[listenersArr.length] =
			[target, eventType, fn]
	}
	function hasPlayerVersion(rv) {
		var pv = ua.pv;
		var v = rv.split(".");
		v[0] = parseInt(v[0], 10);
		v[1] = parseInt(v[1], 10) || 0;
		v[2] = parseInt(v[2], 10) || 0;
		return pv[0] > v[0] || pv[0] == v[0] && pv[1] > v[1] || pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2] ? true : false
	}
	function createCSS(sel, decl, media, newStyle) {
		if (ua.ie && ua.mac)
			return;
		var h = doc.getElementsByTagName("head")[0];
		if (!h)
			return;
		var m = media && typeof media == "string" ? media : "screen";
		if (newStyle) {
			dynamicStylesheet = null;
			dynamicStylesheetMedia = null
		}
		if (!dynamicStylesheet ||
			dynamicStylesheetMedia != m) {
			var s = createElement("style");
			s.setAttribute("type", "text/css");
			s.setAttribute("media", m);
			dynamicStylesheet = h.appendChild(s);
			if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0)
				dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
			dynamicStylesheetMedia = m
		}
		if (ua.ie && ua.win) {
			if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT)
				dynamicStylesheet.addRule(sel, decl)
		} else if (dynamicStylesheet && typeof doc.createTextNode != UNDEF)
			dynamicStylesheet.appendChild(doc.createTextNode(sel +
					" {" + decl + "}"))
	}
	function setVisibility(id, isVisible) {
		if (!autoHideShow)
			return;
		var v = isVisible ? "visible" : "hidden";
		if (isDomLoaded && getElementById(id))
			getElementById(id).style.visibility = v;
		else
			createCSS("#" + id, "visibility:" + v)
	}
	function urlEncodeIfNecessary(s) {
		var regex = /[\\\"<>\.;]/;
		var hasBadChars = regex.exec(s) != null;
		return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s
	}
	var UNDEF = "undefined";
	var OBJECT = "object";
	var SHOCKWAVE_FLASH = "Shockwave Flash";
	var SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash";
	var FLASH_MIME_TYPE = "application/x-shockwave-flash";
	var EXPRESS_INSTALL_ID = "SWFObjectExprInst";
	var ON_READY_STATE_CHANGE = "onreadystatechange";
	var win = window;
	var doc = document;
	var nav = navigator;
	var plugin = false;
	var domLoadFnArr = [main];
	var regObjArr = [];
	var objIdArr = [];
	var listenersArr = [];
	var storedAltContent;
	var storedAltContentId;
	var storedCallbackFn;
	var storedCallbackObj;
	var isDomLoaded = false;
	var isExpressInstallActive = false;
	var dynamicStylesheet;
	var dynamicStylesheetMedia;
	var autoHideShow = true;
	var ua =
	function () {
		var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF;
		var u = nav.userAgent.toLowerCase();
		var p = nav.platform.toLowerCase();
		var windows = p ? /win/.test(p) : /win/.test(u);
		var mac = p ? /mac/.test(p) : /mac/.test(u);
		var webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false;
		var ie = ! + "\v1";
		var playerVersion = [0, 0, 0];
		var d = null;
		if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
			d = nav.plugins[SHOCKWAVE_FLASH].description;
			if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {
				plugin = true;
				ie = false;
				d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
				playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
				playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
				playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0
			}
		} else if (typeof win.ActiveXObject != UNDEF)
			try {
				var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
				if (a) {
					d = a.GetVariable("$version");
					if (d) {
						ie = true;
						d = d.split(" ")[1].split(",");
						playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]
					}
				}
			} catch (e) {}

		return {
			w3 : w3cdom,
			pv : playerVersion,
			wk : webkit,
			ie : ie,
			win : windows,
			mac : mac
		}
	}
	();
	var onDomLoad = function () {
		if (!ua.w3)
			return;
		if (typeof doc.readyState != UNDEF && doc.readyState == "complete" || typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))
			callDomLoadFunctions();
		if (!isDomLoaded) {
			if (typeof doc.addEventListener != UNDEF)
				doc.addEventListener("DOMContentLoaded", callDomLoadFunctions,
					false);
			if (ua.ie && ua.win) {
				doc.attachEvent(ON_READY_STATE_CHANGE, function () {
					if (doc.readyState == "complete") {
						doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
						callDomLoadFunctions()
					}
				});
				if (win == top)
					(function () {
						if (isDomLoaded)
							return;
						try {
							doc.documentElement.doScroll("left")
						} catch (e) {
							setTimeout(arguments.callee, 0);
							return
						}
						callDomLoadFunctions()
					})()
			}
			if (ua.wk)
				(function () {
					if (isDomLoaded)
						return;
					if (!/loaded|complete/.test(doc.readyState)) {
						setTimeout(arguments.callee, 0);
						return
					}
					callDomLoadFunctions()
				})();
			addLoadEvent(callDomLoadFunctions)
		}
	}
	();
	var cleanup = function () {
		if (ua.ie && ua.win)
			window.attachEvent("onunload", function () {
				var ll = listenersArr.length;
				for (var i = 0; i < ll; i++)
					listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
				var il = objIdArr.length;
				for (var j = 0; j < il; j++)
					removeSWF(objIdArr[j]);
				for (var k in ua)
					ua[k] = null;
				ua = null;
				for (var l in swfobject)
					swfobject[l] = null;
				swfobject = null;
				window.detachEvent("onunload", arguments.callee)
			})
	}
	();
	return {
		registerObject : function (objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
			if (ua.w3 &&
				objectIdStr && swfVersionStr) {
				var regObj = {};
				regObj.id = objectIdStr;
				regObj.swfVersion = swfVersionStr;
				regObj.expressInstall = xiSwfUrlStr;
				regObj.callbackFn = callbackFn;
				regObjArr[regObjArr.length] = regObj;
				setVisibility(objectIdStr, false)
			} else if (callbackFn)
				callbackFn({
					success : false,
					id : objectIdStr
				})
		},
		getObjectById : function (objectIdStr) {
			if (ua.w3)
				return getObjectById(objectIdStr)
		},
		embedSWF : function (swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
			var callbackObj = {
				success : false,
				id : replaceElemIdStr
			};
			if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
				setVisibility(replaceElemIdStr, false);
				addDomLoadEvent(function () {
					widthStr += "";
					heightStr += "";
					var att = {};
					if (attObj && typeof attObj === OBJECT)
						for (var i in attObj)
							att[i] = attObj[i];
					att.data = swfUrlStr;
					att.width = widthStr;
					att.height = heightStr;
					var par = {};
					if (parObj && typeof parObj === OBJECT)
						for (var j in parObj)
							par[j] = parObj[j];
					if (flashvarsObj && typeof flashvarsObj === OBJECT)
						for (var k in flashvarsObj)
							if (typeof par.flashvars !=
								UNDEF)
								par.flashvars += "\x26" + k + "\x3d" + flashvarsObj[k];
							else
								par.flashvars = k + "\x3d" + flashvarsObj[k];
					if (hasPlayerVersion(swfVersionStr)) {
						var obj = createSWF(att, par, replaceElemIdStr);
						if (att.id == replaceElemIdStr)
							setVisibility(replaceElemIdStr, true);
						callbackObj.success = true;
						callbackObj.ref = obj
					} else if (xiSwfUrlStr && canExpressInstall()) {
						att.data = xiSwfUrlStr;
						showExpressInstall(att, par, replaceElemIdStr, callbackFn);
						return
					} else
						setVisibility(replaceElemIdStr, true);
					if (callbackFn)
						callbackFn(callbackObj)
				})
			} else if (callbackFn)
				callbackFn(callbackObj)
		},
		switchOffAutoHideShow : function () {
			autoHideShow = false
		},
		ua : ua,
		getFlashPlayerVersion : function () {
			return {
				major : ua.pv[0],
				minor : ua.pv[1],
				release : ua.pv[2]
			}
		},
		hasFlashPlayerVersion : hasPlayerVersion,
		createSWF : function (attObj, parObj, replaceElemIdStr) {
			if (ua.w3)
				return createSWF(attObj, parObj, replaceElemIdStr);
			else
				return undefined
		},
		showExpressInstall : function (att, par, replaceElemIdStr, callbackFn) {
			if (ua.w3 && canExpressInstall())
				showExpressInstall(att, par, replaceElemIdStr, callbackFn)
		},
		removeSWF : function (objElemIdStr) {
			if (ua.w3)
				removeSWF(objElemIdStr)
		},
		createCSS : function (selStr, declStr, mediaStr, newStyleBoolean) {
			if (ua.w3)
				createCSS(selStr, declStr, mediaStr, newStyleBoolean)
		},
		addDomLoadEvent : addDomLoadEvent,
		addLoadEvent : addLoadEvent,
		getQueryParamValue : function (param) {
			var q = doc.location.search || doc.location.hash;
			if (q) {
				if (/\?/.test(q))
					q = q.split("?")[1];
				if (param == null)
					return urlEncodeIfNecessary(q);
				var pairs = q.split("\x26");
				for (var i = 0; i < pairs.length; i++)
					if (pairs[i].substring(0, pairs[i].indexOf("\x3d")) == param)
						return urlEncodeIfNecessary(pairs[i].substring(pairs[i].indexOf("\x3d") +
								1))
			}
			return ""
		},
		expressInstallCallback : function () {
			if (isExpressInstallActive) {
				var obj = getElementById(EXPRESS_INSTALL_ID);
				if (obj && storedAltContent) {
					obj.parentNode.replaceChild(storedAltContent, obj);
					if (storedAltContentId) {
						setVisibility(storedAltContentId, true);
						if (ua.ie && ua.win)
							storedAltContent.style.display = "block"
					}
					if (storedCallbackFn)
						storedCallbackFn(storedCallbackObj)
				}
				isExpressInstallActive = false
			}
		}
	}
}
();
Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
		flashVersion : "9.0.115",
		backgroundColor : "#ffffff",
		wmode : "opaque",
		flashVars : undefined,
		flashParams : undefined,
		url : undefined,
		swfId : undefined,
		swfWidth : "100%",
		swfHeight : "100%",
		expressInstall : false,
		initComponent : function () {
			Ext.FlashComponent.superclass.initComponent.call(this);
			this.addEvents("initialize")
		},
		onRender : function () {
			Ext.FlashComponent.superclass.onRender.apply(this, arguments);
			var params = Ext.apply({
					allowScriptAccess : "always",
					bgcolor : this.backgroundColor,
					wmode : this.wmode
				}, this.flashParams);
			var vars = Ext.apply({
					allowedDomain : document.location.hostname,
					YUISwfId : this.getId(),
					YUIBridgeCallback : "Ext.FlashEventProxy.onEvent"
				}, this.flashVars);
			new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion, this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
			this.swf = Ext.getDom(this.id);
			this.el = Ext.get(this.swf)
		},
		getSwfId : function () {
			return this.swfId || (this.swfId = "extswf" + ++Ext.Component.AUTO_ID)
		},
		getId : function () {
			return this.id ||
			(this.id = "extflashcmp" + ++Ext.Component.AUTO_ID)
		},
		onFlashEvent : function (e) {
			switch (e.type) {
			case "swfReady":
				this.initSwf();
				return;
			case "log":
				return
			}
			e.component = this;
			this.fireEvent(e.type.toLowerCase().replace(/event$/, ""), e)
		},
		initSwf : function () {
			this.onSwfReady(!!this.isInitialized);
			this.isInitialized = true;
			this.fireEvent("initialize", this)
		},
		beforeDestroy : function () {
			if (this.rendered)
				swfobject.removeSWF(this.swf.id);
			Ext.FlashComponent.superclass.beforeDestroy.call(this)
		},
		onSwfReady : Ext.emptyFn
	});
Ext.FlashComponent.EXPRESS_INSTALL_URL = "http:/" + "/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf";
Ext.reg("flash", Ext.FlashComponent);
Ext.FlashEventProxy = {
	onEvent : function (id, e) {
		var fp = Ext.getCmp(id);
		if (fp)
			fp.onFlashEvent(e);
		else
			arguments.callee.defer(10, this, [id, e])
	}
};
Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
		refreshBuffer : 100,
		chartStyle : {
			padding : 10,
			animationEnabled : true,
			font : {
				name : "Tahoma",
				color : 4473924,
				size : 11
			},
			dataTip : {
				padding : 5,
				border : {
					color : 10075112,
					size : 1
				},
				background : {
					color : 14346230,
					alpha : 0.9
				},
				font : {
					name : "Tahoma",
					color : 1393291,
					size : 10,
					bold : true
				}
			}
		},
		extraStyle : null,
		seriesStyles : null,
		disableCaching : Ext.isIE || Ext.isOpera,
		disableCacheParam : "_dc",
		initComponent : function () {
			Ext.chart.Chart.superclass.initComponent.call(this);
			if (!this.url)
				this.url = Ext.chart.Chart.CHART_URL;
			if (this.disableCaching)
				this.url = Ext.urlAppend(this.url, String.format("{0}\x3d{1}", this.disableCacheParam, (new Date).getTime()));
			this.addEvents("itemmouseover", "itemmouseout", "itemclick", "itemdoubleclick", "itemdragstart", "itemdrag", "itemdragend", "beforerefresh", "refresh");
			this.store = Ext.StoreMgr.lookup(this.store)
		},
		setStyle : function (name, value) {
			this.swf.setStyle(name, Ext.encode(value))
		},
		setStyles : function (styles) {
			this.swf.setStyles(Ext.encode(styles))
		},
		setSeriesStyles : function (styles) {
			this.seriesStyles =
				styles;
			var s = [];
			Ext.each(styles, function (style) {
				s.push(Ext.encode(style))
			});
			this.swf.setSeriesStyles(s)
		},
		setCategoryNames : function (names) {
			this.swf.setCategoryNames(names)
		},
		setLegendRenderer : function (fn, scope) {
			var chart = this;
			scope = scope || chart;
			chart.removeFnProxy(chart.legendFnName);
			chart.legendFnName = chart.createFnProxy(function (name) {
					return fn.call(scope, name)
				});
			chart.swf.setLegendLabelFunction(chart.legendFnName)
		},
		setTipRenderer : function (fn, scope) {
			var chart = this;
			scope = scope || chart;
			chart.removeFnProxy(chart.tipFnName);
			chart.tipFnName = chart.createFnProxy(function (item, index, series) {
					var record = chart.store.getAt(index);
					return fn.call(scope, chart, record, index, series)
				});
			chart.swf.setDataTipFunction(chart.tipFnName)
		},
		setSeries : function (series) {
			this.series = series;
			this.refresh()
		},
		bindStore : function (store, initial) {
			if (!initial && this.store)
				if (store !== this.store && this.store.autoDestroy)
					this.store.destroy();
				else {
					this.store.un("datachanged", this.refresh, this);
					this.store.un("add", this.delayRefresh, this);
					this.store.un("remove",
						this.delayRefresh, this);
					this.store.un("update", this.delayRefresh, this);
					this.store.un("clear", this.refresh, this)
				}
			if (store) {
				store = Ext.StoreMgr.lookup(store);
				store.on({
					scope : this,
					datachanged : this.refresh,
					add : this.delayRefresh,
					remove : this.delayRefresh,
					update : this.delayRefresh,
					clear : this.refresh
				})
			}
			this.store = store;
			if (store && !initial)
				this.refresh()
		},
		onSwfReady : function (isReset) {
			Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
			var ref;
			this.swf.setType(this.type);
			if (this.chartStyle)
				this.setStyles(Ext.apply({},
						this.extraStyle, this.chartStyle));
			if (this.categoryNames)
				this.setCategoryNames(this.categoryNames);
			if (this.tipRenderer) {
				ref = this.getFunctionRef(this.tipRenderer);
				this.setTipRenderer(ref.fn, ref.scope)
			}
			if (this.legendRenderer) {
				ref = this.getFunctionRef(this.legendRenderer);
				this.setLegendRenderer(ref.fn, ref.scope)
			}
			if (!isReset)
				this.bindStore(this.store, true);
			this.refresh.defer(10, this)
		},
		delayRefresh : function () {
			if (!this.refreshTask)
				this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
			this.refreshTask.delay(this.refreshBuffer)
		},
		refresh : function () {
			if (this.fireEvent("beforerefresh", this) !== false) {
				var styleChanged = false;
				var data = [];
				var rs = this.store.data.items;
				var j = 0;
				for (var len = rs.length; j < len; j++)
					data[j] = rs[j].data;
				var dataProvider = [];
				var seriesCount = 0;
				var currentSeries = null;
				var i = 0;
				if (this.series) {
					seriesCount = this.series.length;
					for (i = 0; i < seriesCount; i++) {
						currentSeries = this.series[i];
						var clonedSeries = {};
						for (var prop in currentSeries)
							if (prop == "style" && currentSeries.style !== null) {
								clonedSeries.style = Ext.encode(currentSeries.style);
								styleChanged = true
							} else
								clonedSeries[prop] = currentSeries[prop];
						dataProvider.push(clonedSeries)
					}
				}
				if (seriesCount > 0)
					for (i = 0; i < seriesCount; i++) {
						currentSeries = dataProvider[i];
						if (!currentSeries.type)
							currentSeries.type = this.type;
						currentSeries.dataProvider = data
					}
				else
					dataProvider.push({
						type : this.type,
						dataProvider : data
					});
				this.swf.setDataProvider(dataProvider);
				if (this.seriesStyles)
					this.setSeriesStyles(this.seriesStyles);
				this.fireEvent("refresh", this)
			}
		},
		createFnProxy : function (fn) {
			var fnName = "extFnProxy" + ++Ext.chart.Chart.PROXY_FN_ID;
			Ext.chart.Chart.proxyFunction[fnName] = fn;
			return "Ext.chart.Chart.proxyFunction." + fnName
		},
		removeFnProxy : function (fn) {
			if (!Ext.isEmpty(fn)) {
				fn = fn.replace("Ext.chart.Chart.proxyFunction.", "");
				delete Ext.chart.Chart.proxyFunction[fn]
			}
		},
		getFunctionRef : function (val) {
			if (Ext.isFunction(val))
				return {
					fn : val,
					scope : this
				};
			else
				return {
					fn : val.fn,
					scope : val.scope || this
				}
		},
		onDestroy : function () {
			if (this.refreshTask && this.refreshTask.cancel)
				this.refreshTask.cancel();
			Ext.chart.Chart.superclass.onDestroy.call(this);
			this.bindStore(null);
			this.removeFnProxy(this.tipFnName);
			this.removeFnProxy(this.legendFnName)
		}
	});
Ext.reg("chart", Ext.chart.Chart);
Ext.chart.Chart.PROXY_FN_ID = 0;
Ext.chart.Chart.proxyFunction = {};
Ext.chart.Chart.CHART_URL = "http:/" + "/yui.yahooapis.com/2.8.2/build/charts/assets/charts.swf";
Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
		type : "pie",
		onSwfReady : function (isReset) {
			Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
			this.setDataField(this.dataField);
			this.setCategoryField(this.categoryField)
		},
		setDataField : function (field) {
			this.dataField = field;
			this.swf.setDataField(field)
		},
		setCategoryField : function (field) {
			this.categoryField = field;
			this.swf.setCategoryField(field)
		}
	});
Ext.reg("piechart", Ext.chart.PieChart);
Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
		onSwfReady : function (isReset) {
			Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
			this.labelFn = [];
			if (this.xField)
				this.setXField(this.xField);
			if (this.yField)
				this.setYField(this.yField);
			if (this.xAxis)
				this.setXAxis(this.xAxis);
			if (this.xAxes)
				this.setXAxes(this.xAxes);
			if (this.yAxis)
				this.setYAxis(this.yAxis);
			if (this.yAxes)
				this.setYAxes(this.yAxes);
			if (Ext.isDefined(this.constrainViewport))
				this.swf.setConstrainViewport(this.constrainViewport)
		},
		setXField : function (value) {
			this.xField = value;
			this.swf.setHorizontalField(value)
		},
		setYField : function (value) {
			this.yField = value;
			this.swf.setVerticalField(value)
		},
		setXAxis : function (value) {
			this.xAxis = this.createAxis("xAxis", value);
			this.swf.setHorizontalAxis(this.xAxis)
		},
		setXAxes : function (value) {
			var axis;
			for (var i = 0; i < value.length; i++) {
				axis = this.createAxis("xAxis" + i, value[i]);
				this.swf.setHorizontalAxis(axis)
			}
		},
		setYAxis : function (value) {
			this.yAxis = this.createAxis("yAxis", value);
			this.swf.setVerticalAxis(this.yAxis)
		},
		setYAxes : function (value) {
			var axis;
			for (var i = 0; i < value.length; i++) {
				axis = this.createAxis("yAxis" + i, value[i]);
				this.swf.setVerticalAxis(axis)
			}
		},
		createAxis : function (axis, value) {
			var o = Ext.apply({}, value);
			var ref;
			var old;
			if (this[axis]) {
				old = this[axis].labelFunction;
				this.removeFnProxy(old);
				this.labelFn.remove(old)
			}
			if (o.labelRenderer) {
				ref = this.getFunctionRef(o.labelRenderer);
				o.labelFunction = this.createFnProxy(function (v) {
						return ref.fn.call(ref.scope, v)
					});
				delete o.labelRenderer;
				this.labelFn.push(o.labelFunction)
			}
			if (axis.indexOf("xAxis") >
				-1 && o.position == "left")
				o.position = "bottom";
			return o
		},
		onDestroy : function () {
			Ext.chart.CartesianChart.superclass.onDestroy.call(this);
			Ext.each(this.labelFn, function (fn) {
				this.removeFnProxy(fn)
			}, this)
		}
	});
Ext.reg("cartesianchart", Ext.chart.CartesianChart);
Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
		type : "line"
	});
Ext.reg("linechart", Ext.chart.LineChart);
Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
		type : "column"
	});
Ext.reg("columnchart", Ext.chart.ColumnChart);
Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
		type : "stackcolumn"
	});
Ext.reg("stackedcolumnchart", Ext.chart.StackedColumnChart);
Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
		type : "bar"
	});
Ext.reg("barchart", Ext.chart.BarChart);
Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
		type : "stackbar"
	});
Ext.reg("stackedbarchart", Ext.chart.StackedBarChart);
Ext.chart.Axis = function (config) {
	Ext.apply(this, config)
};
Ext.chart.Axis.prototype = {
	type : null,
	orientation : "horizontal",
	reverse : false,
	labelFunction : null,
	hideOverlappingLabels : true,
	labelSpacing : 2
};
Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
		type : "numeric",
		minimum : NaN,
		maximum : NaN,
		majorUnit : NaN,
		minorUnit : NaN,
		snapToUnits : true,
		alwaysShowZero : true,
		scale : "linear",
		roundMajorUnit : true,
		calculateByLabelSize : true,
		position : "left",
		adjustMaximumByMajorUnit : true,
		adjustMinimumByMajorUnit : true
	});
Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
		type : "time",
		minimum : null,
		maximum : null,
		majorUnit : NaN,
		majorTimeUnit : null,
		minorUnit : NaN,
		minorTimeUnit : null,
		snapToUnits : true,
		stackingEnabled : false,
		calculateByLabelSize : true
	});
Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
		type : "category",
		categoryNames : null,
		calculateCategoryCount : false
	});
Ext.chart.Series = function (config) {
	Ext.apply(this, config)
};
Ext.chart.Series.prototype = {
	type : null,
	displayName : null
};
Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
		xField : null,
		yField : null,
		showInLegend : true,
		axis : "primary"
	});
Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
		type : "column"
	});
Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
		type : "line"
	});
Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
		type : "bar"
	});
Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
		type : "pie",
		dataField : null,
		categoryField : null
	});
Ext.menu.Menu = Ext.extend(Ext.Container, {
		minWidth : 120,
		shadow : "sides",
		subMenuAlign : "tl-tr?",
		defaultAlign : "tl-bl?",
		allowOtherMenus : false,
		ignoreParentClicks : false,
		enableScrolling : true,
		maxHeight : null,
		scrollIncrement : 24,
		showSeparator : true,
		defaultOffsets : [0, 0],
		plain : false,
		floating : true,
		zIndex : 15E3,
		hidden : true,
		layout : "menu",
		hideMode : "offsets",
		scrollerHeight : 8,
		autoLayout : true,
		defaultType : "menuitem",
		bufferResize : false,
		initComponent : function () {
			if (Ext.isArray(this.initialConfig))
				Ext.apply(this, {
					items : this.initialConfig
				});
			this.addEvents("click", "mouseover", "mouseout", "itemclick");
			Ext.menu.MenuMgr.register(this);
			if (this.floating)
				Ext.EventManager.onWindowResize(this.hide, this);
			else {
				if (this.initialConfig.hidden !== false)
					this.hidden = false;
				this.internalDefaults = {
					hideOnClick : false
				}
			}
			Ext.menu.Menu.superclass.initComponent.call(this);
			if (this.autoLayout) {
				var fn = this.doLayout.createDelegate(this, []);
				this.on({
					add : fn,
					remove : fn
				})
			}
		},
		getLayoutTarget : function () {
			return this.ul
		},
		onRender : function (ct, position) {
			if (!ct)
				ct = Ext.getBody();
			var dh = {
				id : this.getId(),
				cls : "x-menu " + (this.floating ? "x-menu-floating x-layer " : "") + (this.cls || "") + (this.plain ? " x-menu-plain" : "") + (this.showSeparator ? "" : " x-menu-nosep"),
				style : this.style,
				cn : [{
						tag : "a",
						cls : "x-menu-focus",
						href : "#",
						onclick : "return false;",
						tabIndex : "-1"
					}, {
						tag : "ul",
						cls : "x-menu-list"
					}
				]
			};
			if (this.floating)
				this.el = new Ext.Layer({
						shadow : this.shadow,
						dh : dh,
						constrain : false,
						parentEl : ct,
						zindex : this.zIndex
					});
			else
				this.el = ct.createChild(dh);
			Ext.menu.Menu.superclass.onRender.call(this, ct, position);
			if (!this.keyNav)
				this.keyNav = new Ext.menu.MenuNav(this);
			this.focusEl = this.el.child("a.x-menu-focus");
			this.ul = this.el.child("ul.x-menu-list");
			this.mon(this.ul, {
				scope : this,
				click : this.onClick,
				mouseover : this.onMouseOver,
				mouseout : this.onMouseOut
			});
			if (this.enableScrolling)
				this.mon(this.el, {
					scope : this,
					delegate : ".x-menu-scroller",
					click : this.onScroll,
					mouseover : this.deactivateActive
				})
		},
		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 = this.findTargetItem(e);
			if (t)
				if (t.isFormField)
					this.setActiveItem(t);
				else if (t instanceof Ext.menu.BaseItem)
					if (t.menu && this.ignoreParentClicks) {
						t.expandMenu();
						e.preventDefault()
					} else if (t.onClick) {
						t.onClick(e);
						this.fireEvent("click", this, t, e)
					}
		},
		setActiveItem : function (item, autoExpand) {
			if (item != this.activeItem) {
				this.deactivateActive();
				if ((this.activeItem = item).isFormField)
					item.focus();
				else
					item.activate(autoExpand)
			} else if (autoExpand)
				item.expandMenu()
		},
		deactivateActive : function () {
			var a =
				this.activeItem;
			if (a) {
				if (a.isFormField) {
					if (a.collapse)
						a.collapse()
				} else
					a.deactivate();
				delete this.activeItem
			}
		},
		tryActivate : function (start, step) {
			var items = this.items;
			var i = start;
			for (var len = items.length; i >= 0 && i < len; i += step) {
				var item = items.get(i);
				if (item.isVisible() && !item.disabled && (item.canActivate || item.isFormField)) {
					this.setActiveItem(item, false);
					return item
				}
			}
			return false
		},
		onMouseOver : function (e) {
			var t = this.findTargetItem(e);
			if (t)
				if (t.canActivate && !t.disabled)
					this.setActiveItem(t, true);
			this.over =
				true;
			this.fireEvent("mouseover", this, e, t)
		},
		onMouseOut : function (e) {
			var t = this.findTargetItem(e);
			if (t)
				if (t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)) {
					this.activeItem.deactivate();
					delete this.activeItem
				}
			this.over = false;
			this.fireEvent("mouseout", this, e, t)
		},
		onScroll : function (e, t) {
			if (e)
				e.stopEvent();
			var ul = this.ul.dom;
			var top = Ext.fly(t).is(".x-menu-scroller-top");
			ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
			if (top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight)
				this.onScrollerOut(null,
					t)
		},
		onScrollerIn : function (e, t) {
			var ul = this.ul.dom;
			var top = Ext.fly(t).is(".x-menu-scroller-top");
			if (top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight)
				Ext.fly(t).addClass(["x-menu-item-active", "x-menu-scroller-active"])
		},
		onScrollerOut : function (e, t) {
			Ext.fly(t).removeClass(["x-menu-item-active", "x-menu-scroller-active"])
		},
		show : function (el, pos, parentMenu) {
			if (this.floating) {
				this.parentMenu = parentMenu;
				if (!this.el) {
					this.render();
					this.doLayout(false, true)
				}
				this.showAt(this.el.getAlignToXY(el, pos ||
						this.defaultAlign, this.defaultOffsets), parentMenu)
			} else
				Ext.menu.Menu.superclass.show.call(this)
		},
		showAt : function (xy, parentMenu) {
			if (this.fireEvent("beforeshow", this) !== false) {
				this.parentMenu = parentMenu;
				if (!this.el)
					this.render();
				if (this.enableScrolling) {
					this.el.setXY(xy);
					xy[1] = this.constrainScroll(xy[1]);
					xy = [this.el.adjustForConstraints(xy)[0], xy[1]]
				} else
					xy = this.el.adjustForConstraints(xy);
				this.el.setXY(xy);
				this.el.show();
				Ext.menu.Menu.superclass.onShow.call(this);
				if (Ext.isIE) {
					this.fireEvent("autosize",
						this);
					if (!Ext.isIE8)
						this.el.repaint()
				}
				this.hidden = false;
				this.focus();
				this.fireEvent("show", this)
			}
		},
		constrainScroll : function (y) {
			var max;
			var full = this.ul.setHeight("auto").getHeight();
			var returnY = y;
			var normalY;
			var parentEl;
			var scrollTop;
			var viewHeight;
			if (this.floating) {
				parentEl = Ext.fly(this.el.dom.parentNode);
				scrollTop = parentEl.getScroll().top;
				viewHeight = parentEl.getViewSize().height;
				normalY = y - scrollTop;
				max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
				if (full > viewHeight) {
					max = viewHeight;
					returnY =
						y - normalY
				} else if (max < full) {
					returnY = y - (full - max);
					max = full
				}
			} else
				max = this.getHeight();
			if (this.maxHeight)
				max = Math.min(this.maxHeight, max);
			if (full > max && max > 0) {
				this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth("tb") - Ext.num(this.el.shadowOffset, 0);
				this.ul.setHeight(this.activeMax);
				this.createScrollers();
				this.el.select(".x-menu-scroller").setDisplayed("")
			} else {
				this.ul.setHeight(full);
				this.el.select(".x-menu-scroller").setDisplayed("none")
			}
			this.ul.dom.scrollTop = 0;
			return returnY
		},
		createScrollers : function () {
			if (!this.scroller) {
				this.scroller = {
					pos : 0,
					top : this.el.insertFirst({
						tag : "div",
						cls : "x-menu-scroller x-menu-scroller-top",
						html : "\x26#160;"
					}),
					bottom : this.el.createChild({
						tag : "div",
						cls : "x-menu-scroller x-menu-scroller-bottom",
						html : "\x26#160;"
					})
				};
				this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
				this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
						listeners : {
							click : this.onScroll.createDelegate(this, [null, this.scroller.top], false)
						}
					});
				this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
				this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
						listeners : {
							click : this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
						}
					})
			}
		},
		onLayout : function () {
			if (this.isVisible()) {
				if (this.enableScrolling)
					this.constrainScroll(this.el.getTop());
				if (this.floating)
					this.el.sync()
			}
		},
		focus : function () {
			if (!this.hidden)
				this.doFocus.defer(50, this)
		},
		doFocus : function () {
			if (!this.hidden)
				this.focusEl.focus()
		},
		hide : function (deep) {
			if (!this.isDestroyed) {
				this.deepHide = deep;
				Ext.menu.Menu.superclass.hide.call(this);
				delete this.deepHide
			}
		},
		onHide : function () {
			Ext.menu.Menu.superclass.onHide.call(this);
			this.deactivateActive();
			if (this.el && this.floating)
				this.el.hide();
			var pm = this.parentMenu;
			if (this.deepHide === true && pm)
				if (pm.floating)
					pm.hide(true);
				else
					pm.deactivateActive()
		},
		lookupComponent : function (c) {
			if (Ext.isString(c)) {
				c = c == "separator" || c == "-" ? new Ext.menu.Separator : new Ext.menu.TextItem(c);
				this.applyDefaults(c)
			} else if (Ext.isObject(c))
				c = this.getMenuItem(c);
			else if (c.tagName || c.el)
				c = new Ext.BoxComponent({
						el : c
					});
			return c
		},
		applyDefaults : function (c) {
			if (!Ext.isString(c)) {
				c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
				var d = this.internalDefaults;
				if (d)
					if (c.events) {
						Ext.applyIf(c.initialConfig, d);
						Ext.apply(c, d)
					} else
						Ext.applyIf(c, d)
			}
			return c
		},
		getMenuItem : function (config) {
			config.ownerCt = this;
			if (!config.isXType) {
				if (!config.xtype && Ext.isBoolean(config.checked))
					return new Ext.menu.CheckItem(config);
				return Ext.create(config, this.defaultType)
			}
			return config
		},
		addSeparator : function () {
			return this.add(new Ext.menu.Separator)
		},
		addElement : function (el) {
			return this.add(new Ext.menu.BaseItem({
					el : el
				}))
		},
		addItem : function (item) {
			return this.add(item)
		},
		addMenuItem : function (config) {
			return this.add(this.getMenuItem(config))
		},
		addText : function (text) {
			return this.add(new Ext.menu.TextItem(text))
		},
		onDestroy : function () {
			Ext.EventManager.removeResizeListener(this.hide, this);
			var pm = this.parentMenu;
			if (pm && pm.activeChild == this)
				delete pm.activeChild;
			delete this.parentMenu;
			Ext.menu.Menu.superclass.onDestroy.call(this);
			Ext.menu.MenuMgr.unregister(this);
			if (this.keyNav)
				this.keyNav.disable();
			var s = this.scroller;
			if (s)
				Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
			Ext.destroy(this.el, this.focusEl, this.ul)
		}
	});
Ext.reg("menu", Ext.menu.Menu);
Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function () {
		function up(e, m) {
			if (!m.tryActivate(m.items.indexOf(m.activeItem) - 1, -1))
				m.tryActivate(m.items.length - 1, -1)
		}
		function down(e, m) {
			if (!m.tryActivate(m.items.indexOf(m.activeItem) + 1, 1))
				m.tryActivate(0, 1)
		}
		return {
			constructor : function (menu) {
				Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
				this.scope = this.menu = menu
			},
			doRelay : function (e, h) {
				var k = e.getKey();
				if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB)
					return false;
				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)
			},
			tab : function (e, m) {
				e.stopEvent();
				if (e.shiftKey)
					up(e, m);
				else
					down(e, m)
			},
			up : up,
			down : down,
			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 () {
	function init() {
		menus = {};
		active = new Ext.util.MixedCollection;
		map = Ext.getDoc().addKeyListener(27, hideAll);
		map.disable()
	}
	function hideAll() {
		if (active && active.length > 0) {
			var c = active.clone();
			c.each(function (m) {
				m.hide()
			});
			return true
		}
		return false
	}
	function onHide(m) {
		active.remove(m);
		if (active.length < 1) {
			map.disable();
			Ext.getDoc().un("mousedown", onMouseDown);
			attached = false
		}
	}
	function onShow(m) {
		var last = active.last();
		lastShow = new Date;
		active.add(m);
		if (!attached) {
			map.enable();
			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.isDestroyed && 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()
	}
	var menus;
	var active;
	var map;
	var groups = {};
	var attached = false;
	var lastShow = new Date;
	return {
		hideAll : function () {
			return hideAll()
		},
		register : function (menu) {
			if (!menus)
				init();
			menus[menu.id] = menu;
			menu.on({
				beforehide : onBeforeHide,
				hide : onHide,
				beforeshow : onBeforeShow,
				show : onShow
			})
		},
		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 Ext.create(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)
		},
		registerCheckable : function (menuItem) {
			var g = menuItem.group;
			if (g) {
				if (!groups[g])
					groups[g] = [];
				groups[g].push(menuItem)
			}
		},
		unregisterCheckable : function (menuItem) {
			var g = menuItem.group;
			if (g)
				groups[g].remove(menuItem)
		},
		onCheckChange : function (item, state) {
			if (item.group &&
				state) {
				var group = groups[item.group];
				var i = 0;
				var len = group.length;
				for (var current; i < len; i++) {
					current = group[i];
					if (current != item)
						current.setChecked(false)
				}
			}
		},
		getCheckedItem : function (groupId) {
			var g = groups[groupId];
			if (g) {
				var i = 0;
				for (var 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) {
				var i = 0;
				for (var l = g.length; i < l; i++)
					if (g[i].id == itemId)
						g[i].setChecked(true)
			}
			return null
		}
	}
}
();
Ext.menu.BaseItem = Ext.extend(Ext.Component, {
		canActivate : false,
		activeClass : "x-menu-item-active",
		hideOnClick : true,
		clickHideDelay : 1,
		ctype : "Ext.menu.BaseItem",
		actionMode : "container",
		initComponent : function () {
			Ext.menu.BaseItem.superclass.initComponent.call(this);
			this.addEvents("click", "activate", "deactivate");
			if (this.handler)
				this.on("click", this.handler, this.scope)
		},
		onRender : function (container, position) {
			Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
			if (this.ownerCt && this.ownerCt instanceof
				Ext.menu.Menu)
				this.parentMenu = this.ownerCt;
			else {
				this.container.addClass("x-menu-list-item");
				this.mon(this.el, {
					scope : this,
					click : this.onClick,
					mouseenter : this.activate,
					mouseleave : this.deactivate
				})
			}
		},
		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 && 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) {
			var pm = this.parentMenu;
			if (this.hideOnClick)
				if (pm.floating)
					this.clickHideDelayTimer =
						pm.hide.defer(this.clickHideDelay, pm, [true]);
				else
					pm.deactivateActive()
		},
		beforeDestroy : function () {
			clearTimeout(this.clickHideDelayTimer);
			Ext.menu.BaseItem.superclass.beforeDestroy.call(this)
		},
		expandMenu : Ext.emptyFn,
		hideMenu : Ext.emptyFn
	});
Ext.reg("menubaseitem", Ext.menu.BaseItem);
Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
		hideOnClick : false,
		itemCls : "x-menu-text",
		constructor : function (config) {
			if (typeof config == "string")
				config = {
					text : config
				};
			Ext.menu.TextItem.superclass.constructor.call(this, config)
		},
		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.reg("menutextitem", Ext.menu.TextItem);
Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
		itemCls : "x-menu-sep",
		hideOnClick : false,
		activeClass : "",
		onRender : function (li) {
			var s = document.createElement("span");
			s.className = this.itemCls;
			s.innerHTML = "\x26#160;";
			this.el = s;
			li.addClass("x-menu-sep-li");
			Ext.menu.Separator.superclass.onRender.apply(this, arguments)
		}
	});
Ext.reg("menuseparator", Ext.menu.Separator);
Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
		itemCls : "x-menu-item",
		canActivate : true,
		showDelay : 200,
		altText : "",
		hideDelay : 200,
		ctype : "Ext.menu.Item",
		initComponent : function () {
			Ext.menu.Item.superclass.initComponent.call(this);
			if (this.menu) {
				if (Ext.isArray(this.menu))
					this.menu = {
						items : this.menu
					};
				if (Ext.isObject(this.menu))
					this.menu.ownerCt = this;
				this.menu = Ext.menu.MenuMgr.get(this.menu);
				this.menu.ownerCt = undefined
			}
		},
		onRender : function (container, position) {
			if (!this.itemTpl)
				this.itemTpl = Ext.menu.Item.prototype.itemTpl =
					new Ext.XTemplate('\x3ca id\x3d"{id}" class\x3d"{cls}" hidefocus\x3d"true" unselectable\x3d"on" href\x3d"{href}"', '\x3ctpl if\x3d"hrefTarget"\x3e', ' target\x3d"{hrefTarget}"', "\x3c/tpl\x3e", "\x3e", '\x3cimg alt\x3d"{altText}" src\x3d"{icon}" class\x3d"x-menu-item-icon {iconCls}"/\x3e', '\x3cspan class\x3d"x-menu-item-text"\x3e{text}\x3c/span\x3e', "\x3c/a\x3e");
			var a = this.getTemplateArgs();
			this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
			this.iconEl = this.el.child("img.x-menu-item-icon");
			this.textEl = this.el.child(".x-menu-item-text");
			if (!this.href)
				this.mon(this.el, "click", Ext.emptyFn, null, {
					preventDefault : true
				});
			Ext.menu.Item.superclass.onRender.call(this, container, position)
		},
		getTemplateArgs : function () {
			return {
				id : this.id,
				cls : this.itemCls + (this.menu ? " x-menu-item-arrow" : "") + (this.cls ? " " + this.cls : ""),
				href : this.href || "#",
				hrefTarget : this.hrefTarget,
				icon : this.icon || Ext.BLANK_IMAGE_URL,
				iconCls : this.iconCls || "",
				text : this.itemText || this.text || "\x26#160;",
				altText : this.altText || ""
			}
		},
		setText : function (text) {
			this.text =
				text || "\x26#160;";
			if (this.rendered) {
				this.textEl.update(this.text);
				this.parentMenu.layout.doAutoSize()
			}
		},
		setIconClass : function (cls) {
			var oldCls = this.iconCls;
			this.iconCls = cls;
			if (this.rendered)
				this.iconEl.replaceClass(oldCls, this.iconCls)
		},
		beforeDestroy : function () {
			clearTimeout(this.showTimer);
			clearTimeout(this.hideTimer);
			if (this.menu) {
				delete this.menu.ownerCt;
				this.menu.destroy()
			}
			Ext.menu.Item.superclass.beforeDestroy.call(this)
		},
		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.reg("menuitem", Ext.menu.Item);
Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
		itemCls : "x-menu-item x-menu-check-item",
		groupClass : "x-menu-group-item",
		checked : false,
		ctype : "Ext.menu.CheckItem",
		initComponent : function () {
			Ext.menu.CheckItem.superclass.initComponent.call(this);
			this.addEvents("beforecheckchange", "checkchange");
			if (this.checkHandler)
				this.on("checkchange", this.checkHandler, this.scope);
			Ext.menu.MenuMgr.registerCheckable(this)
		},
		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) {
			var suppress = suppressEvent === true;
			if (this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)) {
				Ext.menu.MenuMgr.onCheckChange(this, state);
				if (this.container)
					this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
				this.checked = state;
				if (!suppress)
					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.reg("menucheckitem", Ext.menu.CheckItem);
Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
		enableScrolling : false,
		hideOnClick : true,
		pickerId : null,
		cls : "x-date-menu",
		initComponent : function () {
			this.on("beforeshow", this.onBeforeShow, this);
			if (this.strict = Ext.isIE7 && Ext.isStrict)
				this.on("show", this.onShow, this, {
					single : true,
					delay : 20
				});
			Ext.apply(this, {
				plain : true,
				showSeparator : false,
				items : this.picker = new Ext.DatePicker(Ext.applyIf({
							internalRender : this.strict || !Ext.isIE,
							ctCls : "x-menu-date-item",
							id : this.pickerId
						}, this.initialConfig))
			});
			this.picker.purgeListeners();
			Ext.menu.DateMenu.superclass.initComponent.call(this);
			this.relayEvents(this.picker, ["select"]);
			this.on("show", this.picker.focus, this.picker);
			this.on("select", this.menuHide, this);
			if (this.handler)
				this.on("select", this.handler, this.scope || this)
		},
		menuHide : function () {
			if (this.hideOnClick)
				this.hide(true)
		},
		onBeforeShow : function () {
			if (this.picker)
				this.picker.hideMonthPicker(true)
		},
		onShow : function () {
			var el = this.picker.getEl();
			el.setWidth(el.getWidth())
		}
	});
Ext.reg("datemenu", Ext.menu.DateMenu);
Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
		enableScrolling : false,
		hideOnClick : true,
		cls : "x-color-menu",
		paletteId : null,
		initComponent : function () {
			Ext.apply(this, {
				plain : true,
				showSeparator : false,
				items : this.palette = new Ext.ColorPalette(Ext.applyIf({
							id : this.paletteId
						}, this.initialConfig))
			});
			this.palette.purgeListeners();
			Ext.menu.ColorMenu.superclass.initComponent.call(this);
			this.relayEvents(this.palette, ["select"]);
			this.on("select", this.menuHide, this);
			if (this.handler)
				this.on("select", this.handler, this.scope ||
					this)
		},
		menuHide : function () {
			if (this.hideOnClick)
				this.hide(true)
		}
	});
Ext.reg("colormenu", Ext.menu.ColorMenu);
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,
		submitValue : true,
		isFormField : true,
		msgDisplay : "",
		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.name || this.id || ""
		},
		onRender : function (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.autoEl = cfg
			}
			Ext.form.Field.superclass.onRender.call(this, ct, position);
			if (this.submitValue === false)
				this.el.dom.removeAttribute("name");
			var type = this.el.dom.type;
			if (type) {
				if (type ==
					"password")
					type = "text";
				this.el.addClass("x-form-" + type)
			}
			if (this.readOnly)
				this.setReadOnly(true);
			if (this.tabIndex !== undefined)
				this.el.dom.setAttribute("tabIndex", this.tabIndex);
			this.el.addClass([this.fieldClass, this.cls])
		},
		getItemCt : function () {
			return this.itemCt
		},
		initValue : function () {
			if (this.value !== undefined)
				this.setValue(this.value);
			else if (!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText)
				this.setValue(this.el.dom.value);
			this.originalValue = this.getValue()
		},
		isDirty : function () {
			if (this.disabled ||
				!this.rendered)
				return false;
			return String(this.getValue()) !== String(this.originalValue)
		},
		setReadOnly : function (readOnly) {
			if (this.rendered)
				this.el.dom.readOnly = readOnly;
			this.readOnly = readOnly
		},
		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.mon(this.el, Ext.EventManager.getKeyEvent(),
				this.fireKey, this);
			this.mon(this.el, "focus", this.onFocus, this);
			this.mon(this.el, "blur", this.onBlur, this, this.inEditor ? {
				buffer : 10
			}
				 : null)
		},
		preFocus : Ext.emptyFn,
		onFocus : function () {
			this.preFocus();
			if (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 (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);
			this.postBlur()
		},
		postBlur : Ext.emptyFn,
		isValid : function (preventMark) {
			if (this.disabled)
				return true;
			var restore = this.preventMark;
			this.preventMark = preventMark === true;
			var v = this.validateValue(this.processValue(this.getRawValue()), preventMark);
			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) {
			var error = this.getErrors(value)[0];
			if (error == undefined)
				return true;
			else {
				this.markInvalid(error);
				return false
			}
		},
		getErrors : function () {
			return []
		},
		getActiveError : function () {
			return this.activeError || ""
		},
		markInvalid : function (msg) {
			if (this.rendered && !this.preventMark) {
				msg = msg || this.invalidText;
				var mt = this.getMessageHandler();
				if (mt)
					mt.mark(this,
						msg);
				else if (this.msgTarget) {
					this.el.addClass(this.invalidClass);
					var t = Ext.getDom(this.msgTarget);
					if (t) {
						t.innerHTML = msg;
						t.style.display = this.msgDisplay
					}
				}
			}
			this.setActiveError(msg)
		},
		clearInvalid : function () {
			if (this.rendered && !this.preventMark) {
				this.el.removeClass(this.invalidClass);
				var mt = this.getMessageHandler();
				if (mt)
					mt.clear(this);
				else if (this.msgTarget) {
					this.el.removeClass(this.invalidClass);
					var t = Ext.getDom(this.msgTarget);
					if (t) {
						t.innerHTML = "";
						t.style.display = "none"
					}
				}
			}
			this.unsetActiveError()
		},
		setActiveError : function (msg,
			suppressEvent) {
			this.activeError = msg;
			if (suppressEvent !== true)
				this.fireEvent("invalid", this, msg)
		},
		unsetActiveError : function (suppressEvent) {
			delete this.activeError;
			if (suppressEvent !== true)
				this.fireEvent("valid", this)
		},
		getMessageHandler : function () {
			return Ext.form.MessageTargets[this.msgTarget]
		},
		getErrorCt : function () {
			return this.el.findParent(".x-form-element", 5, true) || this.el.findParent(".x-form-field-wrap", 5, true)
		},
		alignErrorEl : function () {
			this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20)
		},
		alignErrorIcon : function () {
			this.errorIcon.alignTo(this.el,
				"tl-tr", [2, 0])
		},
		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.rendered ? this.el.dom.value = Ext.isEmpty(v) ? "" : v : ""
		},
		setValue : function (v) {
			this.value = v;
			if (this.rendered) {
				this.el.dom.value = Ext.isEmpty(v) ? "" : v;
				this.validate()
			}
			return this
		},
		append : function (v) {
			this.setValue([this.getValue(),
					v].join(""))
		}
	});
Ext.form.MessageTargets = {
	"qtip" : {
		mark : function (field, msg) {
			field.el.addClass(field.invalidClass);
			field.el.dom.qtip = msg;
			field.el.dom.qclass = "x-form-invalid-tip";
			if (Ext.QuickTips)
				Ext.QuickTips.enable()
		},
		clear : function (field) {
			field.el.removeClass(field.invalidClass);
			field.el.dom.qtip = ""
		}
	},
	"title" : {
		mark : function (field, msg) {
			field.el.addClass(field.invalidClass);
			field.el.dom.title = msg
		},
		clear : function (field) {
			field.el.dom.title = ""
		}
	},
	"under" : {
		mark : function (field, msg) {
			field.el.addClass(field.invalidClass);
			if (!field.errorEl) {
				var elp =
					field.getErrorCt();
				if (!elp) {
					field.el.dom.title = msg;
					return
				}
				field.errorEl = elp.createChild({
						cls : "x-form-invalid-msg"
					});
				field.on("resize", field.alignErrorEl, field);
				field.on("destroy", function () {
					Ext.destroy(this.errorEl)
				}, field)
			}
			field.alignErrorEl();
			field.errorEl.update(msg);
			Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field)
		},
		clear : function (field) {
			field.el.removeClass(field.invalidClass);
			if (field.errorEl)
				Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
			else
				field.el.dom.title = ""
		}
	},
	"side" : {
		mark : function (field, msg) {
			field.el.addClass(field.invalidClass);
			if (!field.errorIcon) {
				var elp = field.getErrorCt();
				if (!elp) {
					field.el.dom.title = msg;
					return
				}
				field.errorIcon = elp.createChild({
						cls : "x-form-invalid-icon"
					});
				if (field.ownerCt) {
					field.ownerCt.on("afterlayout", field.alignErrorIcon, field);
					field.ownerCt.on("expand", field.alignErrorIcon, field)
				}
				field.on("resize", field.alignErrorIcon, field);
				field.on("destroy", function () {
					Ext.destroy(this.errorIcon)
				}, field)
			}
			field.alignErrorIcon();
			field.errorIcon.dom.qtip =
				msg;
			field.errorIcon.dom.qclass = "x-form-invalid-tip";
			field.errorIcon.show()
		},
		clear : function (field) {
			field.el.removeClass(field.invalidClass);
			if (field.errorIcon) {
				field.errorIcon.dom.qtip = "";
				field.errorIcon.hide()
			} else
				field.el.dom.title = ""
		}
	}
};
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.mon(this.el, "keyup", this.filterValidation, this)
			} else if (this.validationEvent !== false && this.validationEvent != "blur")
				this.mon(this.el, this.validationEvent, this.validate, this, {
					buffer : this.validationDelay
				});
			if (this.selectOnFocus || this.emptyText) {
				this.mon(this.el, "mousedown",
					this.onMouseDown, this);
				if (this.emptyText)
					this.applyEmptyText()
			}
			if (this.maskRe || this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype + "Mask"]))
				this.mon(this.el, "keypress", this.filterKeys, this);
			if (this.grow) {
				this.mon(this.el, "keyup", this.onKeyUpBuffered, this, {
					buffer : 50
				});
				this.mon(this.el, "click", this.autoSize, this)
			}
			if (this.enableKeyEvents)
				this.mon(this.el, {
					scope : this,
					keyup : this.onKeyUp,
					keydown : this.onKeyDown,
					keypress : this.onKeyPress
				})
		},
		onMouseDown : function (e) {
			if (!this.hasFocus)
				this.mon(this.el,
					"mouseup", Ext.emptyFn, this, {
					single : true,
					preventDefault : true
				})
		},
		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)
		},
		onDisable : function () {
			Ext.form.TextField.superclass.onDisable.call(this);
			if (Ext.isIE)
				this.el.dom.unselectable = "on"
		},
		onEnable : function () {
			Ext.form.TextField.superclass.onEnable.call(this);
			if (Ext.isIE)
				this.el.dom.unselectable = ""
		},
		onKeyUpBuffered : function (e) {
			if (this.doAutoSize(e))
				this.autoSize()
		},
		doAutoSize : function (e) {
			return !e.isNavKeyPress()
		},
		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.hasFocus) {
				this.setRawValue(this.emptyText);
				this.el.addClass(this.emptyClass)
			}
		},
		preFocus : function () {
			var el = this.el;
			var isEmpty;
			if (this.emptyText) {
				if (el.dom.value == this.emptyText) {
					this.setRawValue("");
					isEmpty = true
				}
				el.removeClass(this.emptyClass)
			}
			if (this.selectOnFocus || isEmpty)
				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 cc = String.fromCharCode(e.getCharCode());
			if (!Ext.isGecko && e.isSpecialKey() &&
				!cc)
				return;
			if (!this.maskRe.test(cc))
				e.stopEvent()
		},
		setValue : function (v) {
			if (this.emptyText && this.el && !Ext.isEmpty(v))
				this.el.removeClass(this.emptyClass);
			Ext.form.TextField.superclass.setValue.apply(this, arguments);
			this.applyEmptyText();
			this.autoSize();
			return this
		},
		getErrors : function (value) {
			var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
			value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
			if (Ext.isFunction(this.validator)) {
				var msg = this.validator(value);
				if (msg !==
					true)
					errors.push(msg)
			}
			if (value.length < 1 || value === this.emptyText)
				if (this.allowBlank)
					return errors;
				else
					errors.push(this.blankText);
			if (!this.allowBlank && (value.length < 1 || value === this.emptyText))
				errors.push(this.blankText);
			if (value.length < this.minLength)
				errors.push(String.format(this.minLengthText, this.minLength));
			if (value.length > this.maxLength)
				errors.push(String.format(this.maxLengthText, this.maxLength));
			if (this.vtype) {
				var vt = Ext.form.VTypes;
				if (!vt[this.vtype](value, this))
					errors.push(this.vtypeText ||
						vt[this.vtype + "Text"])
			}
			if (this.regex && !this.regex.test(value))
				errors.push(this.regexText);
			return errors
		},
		selectText : function (start, end) {
			var v = this.getRawValue();
			var doFocus = false;
			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()
				}
				doFocus = Ext.isGecko || Ext.isOpera
			} else
				doFocus =
					true;
			if (doFocus)
				this.focus()
		},
		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;
			Ext.removeNode(d);
			d = null;
			v += "\x26#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)
		},
		onDestroy : function () {
			if (this.validationTask) {
				this.validationTask.cancel();
				this.validationTask = null
			}
			Ext.form.TextField.superclass.onDestroy.call(this)
		}
	});
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,
		editable : true,
		readOnly : false,
		wrapFocusClass : "x-trigger-wrap-focus",
		autoSize : Ext.emptyFn,
		monitorTab : true,
		deferHeight : true,
		mimicing : false,
		actionMode : "wrap",
		defaultTriggerWidth : 17,
		onResize : function (w, h) {
			Ext.form.TriggerField.superclass.onResize.call(this, w, h);
			var tw = this.getTriggerWidth();
			if (Ext.isNumber(w))
				this.el.setWidth(w - tw);
			this.wrap.setWidth(this.el.getWidth() +
				tw)
		},
		getTriggerWidth : function () {
			var tw = this.trigger.getWidth();
			if (!this.hideTrigger && !this.readOnly && tw === 0)
				tw = this.defaultTriggerWidth;
			return tw
		},
		alignErrorIcon : function () {
			if (this.wrap)
				this.errorIcon.alignTo(this.wrap, "tl-tr", [2, 0])
		},
		onRender : function (ct, position) {
			this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
			Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
			this.wrap = this.el.wrap({
					cls : "x-form-field-wrap x-form-field-trigger-wrap"
				});
			this.trigger = this.wrap.createChild(this.triggerConfig || {
					tag : "img",
					src : Ext.BLANK_IMAGE_URL,
					alt : "",
					cls : "x-form-trigger " + this.triggerClass
				});
			this.initTrigger();
			if (!this.width)
				this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth());
			this.resizeEl = this.positionEl = this.wrap
		},
		getWidth : function () {
			return this.el.getWidth() + this.trigger.getWidth()
		},
		updateEditState : function () {
			if (this.rendered) {
				if (this.readOnly) {
					this.el.dom.readOnly = true;
					this.el.addClass("x-trigger-noedit");
					this.mun(this.el, "click", this.onTriggerClick, this);
					this.trigger.setDisplayed(false)
				} else {
					if (!this.editable) {
						this.el.dom.readOnly =
							true;
						this.el.addClass("x-trigger-noedit");
						this.mon(this.el, "click", this.onTriggerClick, this)
					} else {
						this.el.dom.readOnly = false;
						this.el.removeClass("x-trigger-noedit");
						this.mun(this.el, "click", this.onTriggerClick, this)
					}
					this.trigger.setDisplayed(!this.hideTrigger)
				}
				this.onResize(this.width || this.wrap.getWidth())
			}
		},
		setHideTrigger : function (hideTrigger) {
			if (hideTrigger != this.hideTrigger) {
				this.hideTrigger = hideTrigger;
				this.updateEditState()
			}
		},
		setEditable : function (editable) {
			if (editable != this.editable) {
				this.editable =
					editable;
				this.updateEditState()
			}
		},
		setReadOnly : function (readOnly) {
			if (readOnly != this.readOnly) {
				this.readOnly = readOnly;
				this.updateEditState()
			}
		},
		afterRender : function () {
			Ext.form.TriggerField.superclass.afterRender.call(this);
			this.updateEditState()
		},
		initTrigger : function () {
			this.mon(this.trigger, "click", this.onTriggerClick, this, {
				preventDefault : true
			});
			this.trigger.addClassOnOver("x-form-trigger-over");
			this.trigger.addClassOnClick("x-form-trigger-click")
		},
		onDestroy : function () {
			Ext.destroy(this.trigger, this.wrap);
			if (this.mimicing)
				this.doc.un("mousedown", this.mimicBlur, this);
			delete this.doc;
			Ext.form.TriggerField.superclass.onDestroy.call(this)
		},
		onFocus : function () {
			Ext.form.TriggerField.superclass.onFocus.call(this);
			if (!this.mimicing) {
				this.wrap.addClass(this.wrapFocusClass);
				this.mimicing = true;
				this.doc.on("mousedown", this.mimicBlur, this, {
					delay : 10
				});
				if (this.monitorTab)
					this.on("specialkey", this.checkTab, this)
			}
		},
		checkTab : function (me, e) {
			if (e.getKey() == e.TAB)
				this.triggerBlur()
		},
		onBlur : Ext.emptyFn,
		mimicBlur : function (e) {
			if (!this.isDestroyed &&
				!this.wrap.contains(e.target) && this.validateBlur(e))
				this.triggerBlur()
		},
		triggerBlur : function () {
			this.mimicing = false;
			this.doc.un("mousedown", this.mimicBlur, this);
			if (this.monitorTab && this.el)
				this.un("specialkey", this.checkTab, this);
			Ext.form.TriggerField.superclass.onBlur.call(this);
			if (this.wrap)
				this.wrap.removeClass(this.wrapFocusClass)
		},
		beforeBlur : Ext.emptyFn,
		validateBlur : function (e) {
			return true
		},
		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,
						alt : "",
						cls : "x-form-trigger " + this.trigger1Class
					}, {
						tag : "img",
						src : Ext.BLANK_IMAGE_URL,
						alt : "",
						cls : "x-form-trigger " + this.trigger2Class
					}
				]
			}
		},
		getTrigger : function (index) {
			return this.triggers[index]
		},
		afterRender : function () {
			Ext.form.TwinTriggerField.superclass.afterRender.call(this);
			var triggers = this.triggers;
			var i = 0;
			for (var len = triggers.length; i < len; ++i)
				if (this["hideTrigger" + (i + 1)])
					triggers[i].hide()
		},
		initTrigger : function () {
			var ts = this.trigger.select(".x-form-trigger", true);
			var triggerField = this;
			ts.each(function (t, all, index) {
				var triggerIndex = "Trigger" + (index + 1);
				t.hide = function () {
					var w = triggerField.wrap.getWidth();
					this.dom.style.display = "none";
					triggerField.el.setWidth(w - triggerField.trigger.getWidth());
					triggerField["hidden" + triggerIndex] = true
				};
				t.show = function () {
					var w = triggerField.wrap.getWidth();
					this.dom.style.display = "";
					triggerField.el.setWidth(w - triggerField.trigger.getWidth());
					triggerField["hidden" + triggerIndex] = false
				};
				this.mon(t, "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
		},
		getTriggerWidth : function () {
			var tw = 0;
			Ext.each(this.triggers, function (t, index) {
				var triggerIndex = "Trigger" + (index + 1);
				var w = t.getWidth();
				if (w === 0 && !this["hidden" + triggerIndex])
					tw += this.defaultTriggerWidth;
				else
					tw += w
			}, this);
			return tw
		},
		onDestroy : function () {
			Ext.destroy(this.triggers);
			Ext.form.TwinTriggerField.superclass.onDestroy.call(this)
		},
		onTrigger1Click : Ext.emptyFn,
		onTrigger2Click : Ext.emptyFn
	});
Ext.reg("trigger", Ext.form.TriggerField);
Ext.form.TextArea = Ext.extend(Ext.form.TextField, {
		growMin : 60,
		growMax : 1E3,
		growAppend : "\x26#160;\n\x26#160;",
		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 () {
			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)
		},
		doAutoSize : function (e) {
			return !e.isNavKeyPress() || e.getKey() == e.ENTER
		},
		filterValidation : function (e) {
			if (!e.isNavKeyPress() || !this.enterIsSpecial && e.keyCode == e.ENTER)
				this.validationTask.delay(this.validationDelay)
		},
		autoSize : function () {
			if (!this.grow ||
				!this.textSizeEl)
				return;
			var el = this.el;
			var v = Ext.util.Format.htmlEncode(el.dom.value);
			var ts = this.textSizeEl;
			var h;
			Ext.fly(ts).setWidth(this.el.getWidth());
			if (v.length < 1)
				v = "\x26#160;\x26#160;";
			else {
				v += this.growAppend;
				if (Ext.isIE)
					v = v.replace(/\n/g, "\x26#160;\x3cbr /\x3e")
			}
			ts.innerHTML = v;
			h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
			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",
		autoStripChars : false,
		initEvents : function () {
			var allowed = this.baseChars + "";
			if (this.allowDecimals)
				allowed += this.decimalSeparator;
			if (this.allowNegative)
				allowed += "-";
			allowed = Ext.escapeRe(allowed);
			this.maskRe = new RegExp("[" + allowed + "]");
			if (this.autoStripChars)
				this.stripCharsRe = new RegExp("[^" + allowed + "]", "gi");
			Ext.form.NumberField.superclass.initEvents.call(this)
		},
		getErrors : function (value) {
			var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
			value = Ext.isDefined(value) ? value : this.processValue(this.getRawValue());
			if (value.length < 1)
				return errors;
			value = String(value).replace(this.decimalSeparator, ".");
			if (isNaN(value))
				errors.push(String.format(this.nanText,
						value));
			var num = this.parseValue(value);
			if (num < this.minValue)
				errors.push(String.format(this.minText, this.minValue));
			if (num > this.maxValue)
				errors.push(String.format(this.maxText, this.maxValue));
			return errors
		},
		getValue : function () {
			return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)))
		},
		setValue : function (v) {
			v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
			v = this.fixPrecision(v);
			v = isNaN(v) ? "" : String(v).replace(".", this.decimalSeparator);
			return Ext.form.NumberField.superclass.setValue.call(this, v)
		},
		setMinValue : function (value) {
			this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY)
		},
		setMaxValue : function (value) {
			this.maxValue = Ext.num(value, Number.MAX_VALUE)
		},
		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 (!Ext.isEmpty(v))
				this.setValue(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|n-j|n/j",
		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,
		startDay : 0,
		defaultAutoCreate : {
			tag : "input",
			type : "text",
			size : "10",
			autocomplete : "off"
		},
		initTime : "12",
		initTimeFormat : "H",
		safeParse : function (value, format) {
			if (Date.formatContainsHourInfo(format))
				return Date.parseDate(value, format);
			else {
				var parsedDate = Date.parseDate(value + " " + this.initTime, format + " " + this.initTimeFormat);
				if (parsedDate)
					return parsedDate.clearTime()
			}
		},
		initComponent : function () {
			Ext.form.DateField.superclass.initComponent.call(this);
			this.addEvents("select");
			if (Ext.isString(this.minValue))
				this.minValue = this.parseDate(this.minValue);
			if (Ext.isString(this.maxValue))
				this.maxValue =
					this.parseDate(this.maxValue);
			this.disabledDatesRE = null;
			this.initDisabledDays()
		},
		initEvents : function () {
			Ext.form.DateField.superclass.initEvents.call(this);
			this.keyNav = new Ext.KeyNav(this.el, {
					"down" : function (e) {
						this.onTriggerClick()
					},
					scope : this,
					forceKeyDown : true
				})
		},
		initDisabledDays : function () {
			if (this.disabledDates) {
				var dd = this.disabledDates;
				var len = dd.length - 1;
				var re = "(?:";
				Ext.each(dd, function (d, i) {
					re += Ext.isDate(d) ? "^" + Ext.escapeRe(d.dateFormat(this.format)) + "$" : dd[i];
					if (i != len)
						re += "|"
				}, this);
				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 = Ext.isString(dt) ? this.parseDate(dt) : dt;
			if (this.menu)
				this.menu.picker.setMinDate(this.minValue)
		},
		setMaxValue : function (dt) {
			this.maxValue = Ext.isString(dt) ? this.parseDate(dt) : dt;
			if (this.menu)
				this.menu.picker.setMaxDate(this.maxValue)
		},
		getErrors : function (value) {
			var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
			value = this.formatDate(value || this.processValue(this.getRawValue()));
			if (value.length < 1)
				return errors;
			var svalue = value;
			value = this.parseDate(value);
			if (!value) {
				errors.push(String.format(this.invalidText, svalue, this.format));
				return errors
			}
			var time = value.getTime();
			if (this.minValue && time < this.minValue.clearTime().getTime())
				errors.push(String.format(this.minText, this.formatDate(this.minValue)));
			if (this.maxValue &&
				time > this.maxValue.clearTime().getTime())
				errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
			if (this.disabledDays) {
				var day = value.getDay();
				for (var i = 0; i < this.disabledDays.length; i++)
					if (day === this.disabledDays[i]) {
						errors.push(this.disabledDaysText);
						break
					}
			}
			var fvalue = this.formatDate(value);
			if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue))
				errors.push(String.format(this.disabledDatesText, fvalue));
			return errors
		},
		validateBlur : function () {
			return !this.menu || !this.menu.isVisible()
		},
		getValue : function () {
			return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || ""
		},
		setValue : function (date) {
			return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)))
		},
		parseDate : function (value) {
			if (!value || Ext.isDate(value))
				return value;
			var v = this.safeParse(value, this.format);
			var af = this.altFormats;
			var afa = this.altFormatsArray;
			if (!v && af) {
				afa = afa || af.split("|");
				var i = 0;
				for (var len = afa.length; i < len && !v; i++)
					v = this.safeParse(value, afa[i])
			}
			return v
		},
		onDestroy : function () {
			Ext.destroy(this.menu,
				this.keyNav);
			Ext.form.DateField.superclass.onDestroy.call(this)
		},
		formatDate : function (date) {
			return Ext.isDate(date) ? date.dateFormat(this.format) : date
		},
		onTriggerClick : function () {
			if (this.disabled)
				return;
			if (this.menu == null)
				this.menu = new Ext.menu.DateMenu({
						hideOnClick : false,
						focusOnSelect : false
					});
			this.onFocus();
			Ext.apply(this.menu.picker, {
				minDate : this.minValue,
				maxDate : this.maxValue,
				disabledDatesRE : this.disabledDatesRE,
				disabledDatesText : this.disabledDatesText,
				disabledDays : this.disabledDays,
				disabledDaysText : this.disabledDaysText,
				format : this.format,
				showToday : this.showToday,
				startDay : this.startDay,
				minText : String.format(this.minText, this.formatDate(this.minValue)),
				maxText : String.format(this.maxText, this.formatDate(this.maxValue))
			});
			this.menu.picker.setValue(this.getValue() || new Date);
			this.menu.show(this.el, "tl-bl?");
			this.menuEvents("on")
		},
		menuEvents : function (method) {
			this.menu[method]("select", this.onSelect, this);
			this.menu[method]("hide", this.onMenuHide, this);
			this.menu[method]("show", this.onFocus, this)
		},
		onSelect : function (m, d) {
			this.setValue(d);
			this.fireEvent("select", this, d);
			this.menu.hide()
		},
		onMenuHide : function () {
			this.focus(false, 60);
			this.menuEvents("un")
		},
		beforeBlur : function () {
			var v = this.parseDate(this.getRawValue());
			if (v)
				this.setValue(v)
		}
	});
Ext.reg("datefield", Ext.form.DateField);
Ext.form.DisplayField = Ext.extend(Ext.form.Field, {
		validationEvent : false,
		validateOnBlur : false,
		defaultAutoCreate : {
			tag : "div"
		},
		fieldClass : "x-form-display-field",
		htmlEncode : false,
		initEvents : Ext.emptyFn,
		isValid : function () {
			return true
		},
		validate : function () {
			return true
		},
		getRawValue : function () {
			var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, "");
			if (v === this.emptyText)
				v = "";
			if (this.htmlEncode)
				v = Ext.util.Format.htmlDecode(v);
			return v
		},
		getValue : function () {
			return this.getRawValue()
		},
		getName : function () {
			return this.name
		},
		setRawValue : function (v) {
			if (this.htmlEncode)
				v = Ext.util.Format.htmlEncode(v);
			return this.rendered ? this.el.dom.innerHTML = Ext.isEmpty(v) ? "" : v : this.value = v
		},
		setValue : function (v) {
			this.setRawValue(v);
			return this
		}
	});
Ext.reg("displayfield", Ext.form.DisplayField);
Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
		defaultAutoCreate : {
			tag : "input",
			type : "text",
			size : "24",
			autocomplete : "off"
		},
		listClass : "",
		selectedClass : "x-combo-selected",
		listEmptyText : "",
		triggerClass : "x-form-arrow-trigger",
		shadow : "sides",
		listAlign : "tl-bl?",
		maxHeight : 300,
		minHeight : 90,
		triggerAction : "query",
		minChars : 4,
		autoSelect : true,
		typeAhead : false,
		queryDelay : 500,
		pageSize : 0,
		selectOnFocus : false,
		queryParam : "query",
		loadingText : "Loading...",
		resizable : false,
		handleHeight : 8,
		allQuery : "",
		mode : "remote",
		minListWidth : 70,
		forceSelection : false,
		typeAheadDelay : 250,
		lazyInit : true,
		clearFilterOnReset : true,
		submitValue : undefined,
		initComponent : function () {
			Ext.form.ComboBox.superclass.initComponent.call(this);
			this.addEvents("expand", "collapse", "beforeselect", "select", "beforequery");
			if (this.transform) {
				var s = Ext.getDom(this.transform);
				if (!this.hiddenName)
					this.hiddenName = s.name;
				if (!this.store) {
					this.mode = "local";
					var d = [];
					var opts = s.options;
					var i = 0;
					for (var len = opts.length; i < len; i++) {
						var o = opts[i];
						var value = (o.hasAttribute ? o.hasAttribute("value") :
							o.getAttributeNode("value").specified) ? o.value : o.text;
						if (o.selected && Ext.isEmpty(this.value, true))
							this.value = value;
						d.push([value, o.text])
					}
					this.store = new Ext.data.ArrayStore({
							idIndex : 0,
							fields : ["value", "text"],
							data : d,
							autoDestroy : true
						});
					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);
					this.render(this.el.parentNode, s)
				}
				Ext.removeNode(s)
			} else if (this.store) {
				this.store = Ext.StoreMgr.lookup(this.store);
				if (this.store.autoCreated) {
					this.displayField = this.valueField = "field1";
					if (!this.store.expandData)
						this.displayField = "field2";
					this.mode = "local"
				}
			}
			this.selectedIndex = -1;
			if (this.mode == "local") {
				if (!Ext.isDefined(this.initialConfig.queryDelay))
					this.queryDelay = 10;
				if (!Ext.isDefined(this.initialConfig.minChars))
					this.minChars = 0
			}
		},
		onRender : function (ct, position) {
			if (this.hiddenName && !Ext.isDefined(this.submitValue))
				this.submitValue = false;
			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 || Ext.id()
					}, "before", true);
			if (Ext.isGecko)
				this.el.dom.setAttribute("autocomplete", "off");
			if (!this.lazyInit)
				this.initList();
			else
				this.on("focus", this.initList, this, {
					single : true
				})
		},
		initValue : function () {
			Ext.form.ComboBox.superclass.initValue.call(this);
			if (this.hiddenField)
				this.hiddenField.value = Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, "")
		},
		getParentZIndex : function () {
			var zindex;
			if (this.ownerCt)
				this.findParentBy(function (ct) {
					zindex =
						parseInt(ct.getPositionEl().getStyle("z-index"), 10);
					return !!zindex
				});
			return zindex
		},
		getZIndex : function (listParent) {
			listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
			var zindex = parseInt(Ext.fly(listParent).getStyle("z-index"), 10);
			if (!zindex)
				zindex = this.getParentZIndex();
			return (zindex || 12E3) + 5
		},
		initList : function () {
			if (!this.list) {
				var cls = "x-combo-list";
				var listParent = Ext.getDom(this.getListParent() || Ext.getBody());
				this.list = new Ext.Layer({
						parentEl : listParent,
						shadow : this.shadow,
						cls : [cls,
							this.listClass].join(" "),
						constrain : false,
						zindex : this.getZIndex(listParent)
					});
				var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
				this.list.setSize(lw, 0);
				this.list.swallowEvent("mousewheel");
				this.assetHeight = 0;
				if (this.syncFont !== false)
					this.list.setStyle("font-size", this.el.getStyle("font-size"));
				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.mon(this.innerList,
					"mouseover", this.onViewOver, this);
				this.mon(this.innerList, "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 = '\x3ctpl for\x3d"."\x3e\x3cdiv class\x3d"' + cls + '-item"\x3e{' + this.displayField + "}\x3c/div\x3e\x3c/tpl\x3e";
				this.view = new Ext.DataView({
						applyTo : this.innerList,
						tpl : this.tpl,
						singleSelect : true,
						selectedClass : this.selectedClass,
						itemSelector : this.itemSelector || "." + cls + "-item",
						emptyText : this.listEmptyText,
						deferEmptyText : false
					});
				this.mon(this.view, {
					containerclick : this.onViewClick,
					click : this.onViewClick,
					scope : this
				});
				this.bindStore(this.store, true);
				if (this.resizable) {
					this.resizer = new Ext.Resizable(this.list, {
							pinned : true,
							handles : "se"
						});
					this.mon(this.resizer, "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")
				}
			}
		},
		getListParent : function () {
			return document.body
		},
		getStore : function () {
			return this.store
		},
		bindStore : function (store, initial) {
			if (this.store && !initial) {
				if (this.store !== store && this.store.autoDestroy)
					this.store.destroy();
				else {
					this.store.un("beforeload", this.onBeforeLoad, this);
					this.store.un("load", this.onLoad, this);
					this.store.un("exception", this.collapse, this)
				}
				if (!store) {
					this.store = null;
					if (this.view)
						this.view.bindStore(null);
					if (this.pageTb)
						this.pageTb.bindStore(null)
				}
			}
			if (store) {
				if (!initial) {
					this.lastQuery = null;
					if (this.pageTb)
						this.pageTb.bindStore(store)
				}
				this.store = Ext.StoreMgr.lookup(store);
				this.store.on({
					scope : this,
					beforeload : this.onBeforeLoad,
					load : this.onLoad,
					exception : this.collapse
				});
				if (this.view)
					this.view.bindStore(store)
			}
		},
		reset : function () {
			if (this.clearFilterOnReset && this.mode == "local")
				this.store.clearFilter();
			Ext.form.ComboBox.superclass.reset.call(this)
		},
		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()
					},
					"esc" : function (e) {
						this.collapse()
					},
					"tab" : function (e) {
						if (this.forceSelection === true)
							this.collapse();
						else
							this.onViewClick(false);
						return true
					},
					scope : this,
					doRelay : function (e, h, hname) {
						if (hname == "down" || this.scope.isExpanded()) {
							var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
							if (!Ext.isIE && Ext.EventManager.useKeydown)
								this.scope.fireKey(e);
							return relay
						}
						return true
					},
					forceKeyDown : true,
					defaultEventAction : "stopEvent"
				});
			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.enableKeyEvents)
				this.mon(this.el,
					"keyup", this.onKeyUp, this)
		},
		onDestroy : function () {
			if (this.dqTask) {
				this.dqTask.cancel();
				this.dqTask = null
			}
			this.bindStore(null);
			Ext.destroy(this.resizer, this.view, this.pageTb, this.list);
			Ext.destroyMembers(this, "hiddenField");
			Ext.form.ComboBox.superclass.onDestroy.call(this)
		},
		fireKey : function (e) {
			if (!this.isExpanded())
				Ext.form.ComboBox.superclass.fireKey.call(this, e)
		},
		onResize : function (w, h) {
			Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
			if (!isNaN(w) && this.isVisible() && this.list)
				this.doResize(w);
			else
				this.bufferSize = w
		},
		doResize : function (w) {
			if (!Ext.isDefined(this.listWidth)) {
				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
		},
		onBeforeLoad : function () {
			if (!this.hasFocus)
				return;
			this.innerList.update(this.loadingText ? '\x3cdiv class\x3d"loading-indicator"\x3e' + this.loadingText + "\x3c/div\x3e" : "");
			this.restrictHeight();
			this.selectedIndex = -1
		},
		onLoad : function () {
			if (!this.hasFocus)
				return;
			if (this.store.getCount() > 0 || this.listEmptyText) {
				this.expand();
				this.restrictHeight();
				if (this.lastQuery == this.allQuery) {
					if (this.editable)
						this.el.dom.select();
					if (this.autoSelect !== false && !this.selectByValue(this.value, true))
						this.select(0, true)
				} else {
					if (this.autoSelect !== false)
						this.selectNext();
					if (this.typeAhead &&
						this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE)
						this.taTask.delay(this.typeAheadDelay)
				}
			} else
				this.collapse()
		},
		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)
				}
			}
		},
		assertValue : function () {
			var val = this.getRawValue();
			var rec;
			if (this.valueField && Ext.isDefined(this.value))
				rec =
					this.findRecord(this.valueField, this.value);
			if (!rec || rec.get(this.displayField) != val)
				rec = this.findRecord(this.displayField, val);
			if (!rec && this.forceSelection)
				if (val.length > 0 && val != this.emptyText) {
					this.el.dom.value = Ext.value(this.lastSelectionText, "");
					this.applyEmptyText()
				} else
					this.clearValue();
			else {
				if (rec && this.valueField) {
					if (this.value == val)
						return;
					val = rec.get(this.valueField || this.displayField)
				}
				this.setValue(val)
			}
		},
		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)
			}
		},
		getName : function () {
			var hf = this.hiddenField;
			return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this)
		},
		getValue : function () {
			if (this.valueField)
				return Ext.isDefined(this.value) ? 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 (Ext.isDefined(this.valueNotFoundText))
					text = this.valueNotFoundText
			}
			this.lastSelectionText = text;
			if (this.hiddenField)
				this.hiddenField.value = Ext.value(v, "");
			Ext.form.ComboBox.superclass.setValue.call(this, text);
			this.value = v;
			return this
		},
		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 s = this.store;
			var r = s.getAt(index);
			if (r)
				this.onSelect(r, index);
			else
				this.collapse();
			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.apply(this.list, [this.el].concat(this.listAlign));
			this.list.endUpdate()
		},
		isExpanded : function () {
			return this.list && this.list.isVisible()
		},
		selectByValue : function (v, scrollIntoView) {
			if (!Ext.isEmpty(v, true)) {
				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) {
			var k = e.getKey();
			if (this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())) {
				this.lastKey =
					k;
				this.dqTask.delay(this.queryDelay)
			}
			Ext.form.ComboBox.superclass.onKeyUp.call(this, e)
		},
		validateBlur : function () {
			return !this.list || !this.list.isVisible()
		},
		initQuery : function () {
			this.doQuery(this.getRawValue())
		},
		beforeBlur : function () {
			this.assertValue()
		},
		postBlur : function () {
			Ext.form.ComboBox.superclass.postBlur.call(this);
			this.collapse();
			this.inKeyMode = false
		},
		doQuery : function (q, forceAll) {
			q = Ext.isEmpty(q) ? "" : 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 params = {};
			var paramNames = this.store.paramNames;
			if (this.pageSize) {
				params[paramNames.start] = 0;
				params[paramNames.limit] = this.pageSize
			}
			return params
		},
		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 (!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list))
				this.collapse()
		},
		expand : function () {
			if (this.isExpanded() || !this.hasFocus)
				return;
			if (this.title || this.pageSize) {
				this.assetHeight =
					0;
				if (this.title)
					this.assetHeight += this.header.getHeight();
				if (this.pageSize)
					this.assetHeight += this.footer.getHeight()
			}
			if (this.bufferSize) {
				this.doResize(this.bufferSize);
				delete this.bufferSize
			}
			this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
			this.list.setZIndex(this.getZIndex());
			this.list.show();
			if (Ext.isGecko2)
				this.innerList.setOverflow("auto");
			this.mon(Ext.getDoc(), {
				scope : this,
				mousewheel : this.collapseIf,
				mousedown : this.collapseIf
			});
			this.fireEvent("expand", this)
		},
		onTriggerClick : function () {
			if (this.readOnly ||
				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, {
		focusClass : undefined,
		fieldClass : "x-form-field",
		checked : false,
		boxLabel : "\x26#160;",
		defaultAutoCreate : {
			tag : "input",
			type : "checkbox",
			autocomplete : "off"
		},
		actionMode : "wrap",
		initComponent : function () {
			Ext.form.Checkbox.superclass.initComponent.call(this);
			this.addEvents("check")
		},
		onResize : function () {
			Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
			if (!this.boxLabel && !this.fieldLabel)
				this.el.alignTo(this.wrap, "c-c")
		},
		initEvents : function () {
			Ext.form.Checkbox.superclass.initEvents.call(this);
			this.mon(this.el, {
				scope : this,
				click : this.onClick,
				change : this.onClick
			})
		},
		markInvalid : Ext.emptyFn,
		clearInvalid : Ext.emptyFn,
		onRender : function (ct, position) {
			Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
			if (this.inputValue !== undefined)
				this.el.dom.value = this.inputValue;
			this.wrap = this.el.wrap({
					cls : "x-form-check-wrap"
				});
			if (this.boxLabel)
				this.wrap.createChild({
					tag : "label",
					htmlFor : this.el.id,
					cls : "x-form-cb-label",
					html : this.boxLabel
				});
			if (this.checked)
				this.setValue(true);
			else
				this.checked = this.el.dom.checked;
			if (Ext.isIE && !Ext.isStrict)
				this.wrap.repaint();
			this.resizeEl = this.positionEl = this.wrap
		},
		onDestroy : function () {
			Ext.destroy(this.wrap);
			Ext.form.Checkbox.superclass.onDestroy.call(this)
		},
		initValue : function () {
			this.originalValue = this.getValue()
		},
		getValue : function () {
			if (this.rendered)
				return this.el.dom.checked;
			return this.checked
		},
		onClick : function () {
			if (this.el.dom.checked != this.checked)
				this.setValue(this.el.dom.checked)
		},
		setValue : function (v) {
			var checked = this.checked;
			var inputVal = this.inputValue;
			if (v === false)
				this.checked =
					false;
			else
				this.checked = v === true || v === "true" || v == "1" || (inputVal ? v == inputVal : String(v).toLowerCase() == "on");
			if (this.rendered) {
				this.el.dom.checked = this.checked;
				this.el.dom.defaultChecked = this.checked
			}
			if (checked != this.checked) {
				this.fireEvent("check", this, this.checked);
				if (this.handler)
					this.handler.call(this.scope || this, this, this.checked)
			}
			return this
		}
	});
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",
		initComponent : function () {
			this.addEvents("change");
			this.on("change", this.validate, this);
			Ext.form.CheckboxGroup.superclass.initComponent.call(this)
		},
		onRender : function (ct, position) {
			if (!this.el) {
				var panelCfg = {
					autoEl : {
						id : this.id
					},
					cls : this.groupCls,
					layout : "column",
					renderTo : ct,
					bufferResize : false
				};
				var colCfg = {
					xtype : "container",
					defaultType : this.defaultType,
					layout : "form",
					defaults : {
						hideLabel : true,
						anchor : "100%"
					}
				};
				if (this.items[0].items) {
					Ext.apply(panelCfg, {
						layoutConfig : {
							columns : this.items.length
						},
						defaults : this.defaults,
						items : this.items
					});
					var i = 0;
					for (var len = this.items.length; i < len; i++)
						Ext.applyIf(this.items[i], colCfg)
				} else {
					var numCols;
					var cols = [];
					if (typeof this.columns == "string")
						this.columns = this.items.length;
					if (!Ext.isArray(this.columns)) {
						var cs = [];
						for (i = 0; i < this.columns; i++)
							cs.push(100 / this.columns * 0.01);
						this.columns = cs
					}
					numCols = this.columns.length;
					for (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);
						var ri = 0;
						i = 0;
						for (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 {
						i = 0;
						for (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.Container(panelCfg);
				this.panel.ownerCt = this;
				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)
		},
		initValue : function () {
			if (this.value) {
				this.setValue.apply(this, this.buffered ? this.value : [this.value]);
				delete this.buffered;
				delete this.value
			}
		},
		afterRender : function () {
			Ext.form.CheckboxGroup.superclass.afterRender.call(this);
			this.eachItem(function (item) {
				item.on("check", this.fireChecked, this);
				item.inGroup = true
			})
		},
		doLayout : function () {
			if (this.rendered) {
				this.panel.forceLayout = this.ownerCt.forceLayout;
				this.panel.doLayout()
			}
		},
		fireChecked : function () {
			var arr = [];
			this.eachItem(function (item) {
				if (item.checked)
					arr.push(item)
			});
			this.fireEvent("change", this, arr)
		},
		getErrors : function () {
			var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
			if (!this.allowBlank) {
				var blank = true;
				this.eachItem(function (f) {
					if (f.checked)
						return blank = false
				});
				if (blank)
					errors.push(this.blankText)
			}
			return errors
		},
		isDirty : function () {
			if (this.disabled || !this.rendered)
				return false;
			var dirty = false;
			this.eachItem(function (item) {
				if (item.isDirty()) {
					dirty =
						true;
					return false
				}
			});
			return dirty
		},
		setReadOnly : function (readOnly) {
			if (this.rendered)
				this.eachItem(function (item) {
					item.setReadOnly(readOnly)
				});
			this.readOnly = readOnly
		},
		onDisable : function () {
			this.eachItem(function (item) {
				item.disable()
			})
		},
		onEnable : function () {
			this.eachItem(function (item) {
				item.enable()
			})
		},
		onResize : function (w, h) {
			this.panel.setSize(w, h);
			this.panel.doLayout()
		},
		reset : function () {
			if (this.originalValue) {
				this.eachItem(function (c) {
					if (c.setValue) {
						c.setValue(false);
						c.originalValue = c.getValue()
					}
				});
				this.resetOriginal =
					true;
				this.setValue(this.originalValue);
				delete this.resetOriginal
			} else
				this.eachItem(function (c) {
					if (c.reset)
						c.reset()
				});
			(function () {
				this.clearInvalid()
			}).defer(50, this)
		},
		setValue : function () {
			if (this.rendered)
				this.onSetValue.apply(this, arguments);
			else {
				this.buffered = true;
				this.value = arguments
			}
			return this
		},
		onSetValue : function (id, value) {
			if (arguments.length == 1)
				if (Ext.isArray(id))
					Ext.each(id, function (val, idx) {
						if (Ext.isObject(val) && val.setValue) {
							val.setValue(true);
							if (this.resetOriginal === true)
								val.originalValue =
									val.getValue()
						} else {
							var item = this.items.itemAt(idx);
							if (item)
								item.setValue(val)
						}
					}, this);
				else if (Ext.isObject(id))
					for (var i in id) {
						var f = this.getBox(i);
						if (f)
							f.setValue(id[i])
					}
				else
					this.setValueForItem(id);
			else {
				f = this.getBox(id);
				if (f)
					f.setValue(value)
			}
		},
		beforeDestroy : function () {
			Ext.destroy(this.panel);
			if (!this.rendered)
				Ext.destroy(this.items);
			Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this)
		},
		setValueForItem : function (val) {
			val = String(val).split(",");
			this.eachItem(function (item) {
				if (val.indexOf(item.inputValue) >
					-1)
					item.setValue(true)
			})
		},
		getBox : function (id) {
			var box = null;
			this.eachItem(function (f) {
				if (id == f || f.dataIndex == id || f.id == id || f.getName() == id) {
					box = f;
					return false
				}
			});
			return box
		},
		getValue : function () {
			var out = [];
			this.eachItem(function (item) {
				if (item.checked)
					out.push(item)
			});
			return out
		},
		eachItem : function (fn, scope) {
			if (this.items && this.items.each)
				this.items.each(fn, scope || this)
		},
		getRawValue : Ext.emptyFn,
		setRawValue : Ext.emptyFn
	});
Ext.reg("checkboxgroup", Ext.form.CheckboxGroup);
Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
		defaultMargins : "0 5 0 0",
		skipLastItemMargin : true,
		isComposite : true,
		combineErrors : true,
		labelConnector : ", ",
		initComponent : function () {
			var labels = [];
			var items = this.items;
			var item$$0;
			var i = 0;
			for (var j = items.length; i < j; i++) {
				item$$0 = items[i];
				if (!Ext.isEmpty(item$$0.ref))
					item$$0.ref = "../" + item$$0.ref;
				labels.push(item$$0.fieldLabel);
				Ext.applyIf(item$$0, this.defaults);
				if (!(i == j - 1 && this.skipLastItemMargin))
					Ext.applyIf(item$$0, {
						margins : this.defaultMargins
					})
			}
			this.fieldLabel =
				this.fieldLabel || this.buildLabel(labels);
			this.fieldErrors = new Ext.util.MixedCollection(true, function (item) {
					return item.field
				});
			this.fieldErrors.on({
				scope : this,
				add : this.updateInvalidMark,
				remove : this.updateInvalidMark,
				replace : this.updateInvalidMark
			});
			Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
			this.innerCt = new Ext.Container({
					layout : "hbox",
					items : this.items,
					cls : "x-form-composite",
					defaultMargins : "0 3 0 0",
					ownerCt : this
				});
			this.innerCt.ownerCt = undefined;
			var fields = this.innerCt.findBy(function (c) {
					return c.isFormField
				},
					this);
			this.items = new Ext.util.MixedCollection;
			this.items.addAll(fields)
		},
		onRender : function (ct, position) {
			if (!this.el) {
				var innerCt = this.innerCt;
				innerCt.render(ct);
				this.el = innerCt.getEl();
				if (this.combineErrors)
					this.eachItem(function (field) {
						Ext.apply(field, {
							markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
							clearInvalid : this.onFieldClearInvalid.createDelegate(this, [field], 0)
						})
					});
				var l = this.el.parent().parent().child("label", true);
				if (l)
					l.setAttribute("for", this.items.items[0].id)
			}
			Ext.form.CompositeField.superclass.onRender.apply(this,
				arguments)
		},
		onFieldMarkInvalid : function (field, message) {
			var name = field.getName();
			var error = {
				field : name,
				errorName : field.fieldLabel || name,
				error : message
			};
			this.fieldErrors.replace(name, error);
			if (!field.preventMark)
				field.el.addClass(field.invalidClass)
		},
		onFieldClearInvalid : function (field) {
			this.fieldErrors.removeKey(field.getName());
			field.el.removeClass(field.invalidClass)
		},
		updateInvalidMark : function () {
			var ieStrict = Ext.isIE6 && Ext.isStrict;
			if (this.fieldErrors.length == 0) {
				this.clearInvalid();
				if (ieStrict)
					this.clearInvalid.defer(50,
						this)
			} else {
				var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
				this.sortErrors();
				this.markInvalid(message);
				if (ieStrict)
					this.markInvalid(message)
			}
		},
		validateValue : function (value, preventMark) {
			var valid = true;
			this.eachItem(function (field) {
				if (!field.isValid(preventMark))
					valid = false
			});
			return valid
		},
		buildCombinedErrorMessage : function (errors) {
			var combined = [];
			var error;
			var i = 0;
			for (var j = errors.length; i < j; i++) {
				error = errors[i];
				combined.push(String.format("{0}: {1}", error.errorName, error.error))
			}
			return combined.join("\x3cbr /\x3e")
		},
		sortErrors : function () {
			var fields = this.items;
			this.fieldErrors.sort("ASC", function (a, b) {
				var findByName = function (key) {
					return function (field) {
						return field.getName() == key
					}
				};
				var aIndex = fields.findIndexBy(findByName(a.field));
				var bIndex = fields.findIndexBy(findByName(b.field));
				return aIndex < bIndex ? -1 : 1
			})
		},
		reset : function () {
			this.eachItem(function (item) {
				item.reset()
			});
			(function () {
				this.clearInvalid()
			}).defer(50, this)
		},
		clearInvalidChildren : function () {
			this.eachItem(function (item) {
				item.clearInvalid()
			})
		},
		buildLabel : function (segments) {
			return Ext.clean(segments).join(this.labelConnector)
		},
		isDirty : function () {
			if (this.disabled || !this.rendered)
				return false;
			var dirty = false;
			this.eachItem(function (item) {
				if (item.isDirty()) {
					dirty = true;
					return false
				}
			});
			return dirty
		},
		eachItem : function (fn, scope) {
			if (this.items && this.items.each)
				this.items.each(fn, scope || this)
		},
		onResize : function (adjWidth, adjHeight, rawWidth, rawHeight) {
			var innerCt = this.innerCt;
			if (this.rendered && innerCt.rendered)
				innerCt.setSize(adjWidth, adjHeight);
			Ext.form.CompositeField.superclass.onResize.apply(this, arguments)
		},
		doLayout : function (shallow,
			force) {
			if (this.rendered) {
				var innerCt = this.innerCt;
				innerCt.forceLayout = this.ownerCt.forceLayout;
				innerCt.doLayout(shallow, force)
			}
		},
		beforeDestroy : function () {
			Ext.destroy(this.innerCt);
			Ext.form.CompositeField.superclass.beforeDestroy.call(this)
		},
		setReadOnly : function (readOnly) {
			if (readOnly == undefined)
				readOnly = true;
			readOnly = !!readOnly;
			if (this.rendered)
				this.eachItem(function (item) {
					item.setReadOnly(readOnly)
				});
			this.readOnly = readOnly
		},
		onShow : function () {
			Ext.form.CompositeField.superclass.onShow.call(this);
			this.doLayout()
		},
		onDisable : function () {
			this.eachItem(function (item) {
				item.disable()
			})
		},
		onEnable : function () {
			this.eachItem(function (item) {
				item.enable()
			})
		}
	});
Ext.reg("compositefield", Ext.form.CompositeField);
Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
		inputType : "radio",
		markInvalid : Ext.emptyFn,
		clearInvalid : Ext.emptyFn,
		getGroupValue : function () {
			var p = this.el.up("form") || Ext.getBody();
			var c = p.child('input[name\x3d"' + this.el.dom.name + '"]:checked', true);
			return c ? c.value : null
		},
		setValue : function (v) {
			var checkEl;
			var els;
			var radio;
			if (typeof v == "boolean")
				Ext.form.Radio.superclass.setValue.call(this, v);
			else if (this.rendered) {
				checkEl = this.getCheckEl();
				radio = checkEl.child('input[name\x3d"' + this.el.dom.name + '"][value\x3d"' +
						v + '"]', true);
				if (radio)
					Ext.getCmp(radio.id).setValue(true)
			}
			if (this.rendered && this.checked) {
				checkEl = checkEl || this.getCheckEl();
				els = this.getCheckEl().select('input[name\x3d"' + this.el.dom.name + '"]');
				els.each(function (el) {
					if (el.dom.id != this.id)
						Ext.getCmp(el.dom.id).setValue(false)
				}, this)
			}
			return this
		},
		getCheckEl : function () {
			if (this.inGroup)
				return this.el.up(".x-form-radio-group");
			return this.el.up("form") || Ext.getBody()
		}
	});
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",
		getValue : function () {
			var out = null;
			this.eachItem(function (item) {
				if (item.checked) {
					out = item;
					return false
				}
			});
			return out
		},
		onSetValue : function (id, value) {
			if (arguments.length > 1) {
				var f = this.getBox(id);
				if (f) {
					f.setValue(value);
					if (f.checked)
						this.eachItem(function (item) {
							if (item !== f)
								item.setValue(false)
						})
				}
			} else
				this.setValueForItem(id)
		},
		setValueForItem : function (val) {
			val =
				String(val).split(",")[0];
			this.eachItem(function (item) {
				item.setValue(val == item.inputValue)
			})
		},
		fireChecked : function () {
			if (!this.checkTask)
				this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
			this.checkTask.delay(10)
		},
		bufferChecked : function () {
			var out = null;
			this.eachItem(function (item) {
				if (item.checked) {
					out = item;
					return false
				}
			});
			this.fireEvent("change", this, out)
		},
		onDestroy : function () {
			if (this.checkTask) {
				this.checkTask.cancel();
				this.checkTask = null
			}
			Ext.form.RadioGroup.superclass.onDestroy.call(this)
		}
	});
Ext.reg("radiogroup", Ext.form.RadioGroup);
Ext.form.Hidden = Ext.extend(Ext.form.Field, {
		inputType : "hidden",
		shouldLayout : false,
		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 = Ext.extend(Ext.util.Observable, {
		constructor : function (el, config) {
			Ext.apply(this, config);
			if (Ext.isString(this.paramOrder))
				this.paramOrder = this.paramOrder.split(/[\s,|]/);
			this.items = new Ext.util.MixedCollection(false, function (o) {
					return o.getItemId()
				});
			this.addEvents("beforeaction", "actionfailed", "actioncomplete");
			if (el)
				this.initEl(el);
			Ext.form.BasicForm.superclass.constructor.call(this)
		},
		timeout : 30,
		paramOrder : undefined,
		paramsAsHash : false,
		waitTitle : "Please Wait...",
		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 (bound) {
			if (bound !== true) {
				this.items.each(function (f) {
					Ext.destroy(f)
				});
				Ext.destroy(this.el)
			}
			this.items.clear();
			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 (Ext.isString(action))
				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) {
			options = options || {};
			if (this.standardSubmit) {
				var v = options.clientValidation === false || this.isValid();
				if (v) {
					var el = this.el.dom;
					if (this.url && Ext.isEmpty(el.action))
						el.action = this.url;
					el.submit()
				}
				return v
			}
			var submitAction = String.format("{0}submit", this.api ? "direct" : "");
			this.doAction(submitAction, options);
			return this
		},
		load : function (options) {
			var loadAction = String.format("{0}load", this.api ? "direct" : "");
			this.doAction(loadAction, options);
			return this
		},
		updateRecord : function (record) {
			record.beginEdit();
			var fs = record.fields;
			var field;
			var value;
			fs.each(function (f) {
				field = this.findField(f.name);
				if (field) {
					value = field.getValue();
					if (Ext.type(value) !==
						false && value.getGroupValue)
						value = value.getGroupValue();
					else if (field.eachItem) {
						value = [];
						field.eachItem(function (item) {
							value.push(item.getValue())
						})
					}
					record.set(f.name, value)
				}
			}, this);
			record.endEdit();
			return this
		},
		loadRecord : function (record) {
			this.setValues(record.data);
			return this
		},
		beforeAction : function (action) {
			this.items.each(function (f) {
				if (f.isFormField && f.syncValue)
					f.syncValue()
			});
			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)
		},
		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 (!Ext.isObject(field)) {
				var findMatchingField = function (f) {
					if (f.isFormField)
						if (f.dataIndex == id || f.id == id || f.getName() == id) {
							field = f;
							return false
						} else if (f.isComposite)
							return f.items.each(findMatchingField);
						else if (f instanceof Ext.form.CheckboxGroup && f.rendered)
							return f.eachItem(findMatchingField)
				};
				this.items.each(findMatchingField)
			}
			return field ||
			null
		},
		markInvalid : function (errors) {
			if (Ext.isArray(errors)) {
				var i = 0;
				for (var 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;
				for (var id in errors)
					if (!Ext.isFunction(errors[id]) && (field = this.findField(id)))
						field.markInvalid(errors[id])
			}
			return this
		},
		setValues : function (values) {
			if (Ext.isArray(values)) {
				var i = 0;
				for (var 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;
				for (var id in values)
					if (!Ext.isFunction(values[id]) && (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)
		},
		getFieldValues : function (dirtyOnly) {
			var o = {};
			var n;
			var key;
			var val;
			this.items.each(function (f) {
				if (!f.disabled && (dirtyOnly !==
						true || f.isDirty())) {
					n = f.getName();
					key = o[n];
					val = f.getValue();
					if (Ext.isDefined(key))
						if (Ext.isArray(key))
							o[n].push(val);
						else
							o[n] = [key, val];
					else
						o[n] = val
				}
			});
			return o
		},
		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
		},
		cleanDestroyed : function () {
			this.items.filterBy(function (o) {
				return !!o.isDestroyed
			}).each(this.remove,
				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
		},
		callFieldMethod : function (fnName, args) {
			args = args || [];
			this.items.each(function (f) {
				if (Ext.isFunction(f[fnName]))
					f[fnName].apply(f, args)
			});
			return this
		}
	});
Ext.BasicForm = Ext.form.BasicForm;
Ext.FormPanel = Ext.extend(Ext.Panel, {
		minButtonWidth : 75,
		labelAlign : "left",
		monitorValid : false,
		monitorPoll : 200,
		layout : "form",
		initComponent : function () {
			this.form = this.createForm();
			Ext.FormPanel.superclass.initComponent.call(this);
			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";
			this.initItems();
			this.addEvents("clientvalidation");
			this.relayEvents(this.form, ["beforeaction", "actionfailed", "actioncomplete"])
		},
		createForm : function () {
			var config = Ext.applyIf({
					listeners : {}

				}, this.initialConfig);
			return new Ext.form.BasicForm(null, config)
		},
		initFields : function () {
			var f = this.form;
			var formPanel = this;
			var fn = function (c) {
				if (formPanel.isField(c))
					f.add(c);
				else if (c.findBy && c != formPanel) {
					formPanel.applySettings(c);
					if (c.items && c.items.each)
						c.items.each(fn, this)
				}
			};
			this.items.each(fn, this)
		},
		applySettings : function (c) {
			var ct = c.ownerCt;
			Ext.applyIf(c, {
				labelAlign : ct.labelAlign,
				labelWidth : ct.labelWidth,
				itemCls : ct.itemCls
			})
		},
		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 () {
			this.stopMonitoring();
			this.form.destroy(true);
			Ext.FormPanel.superclass.beforeDestroy.call(this)
		},
		isField : function (c) {
			return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid
		},
		initEvents : function () {
			Ext.FormPanel.superclass.initEvents.call(this);
			this.on({
				scope : this,
				add : this.onAddEvent,
				remove : this.onRemoveEvent
			});
			if (this.monitorValid)
				this.startMonitoring()
		},
		onAdd : function (c) {
			Ext.FormPanel.superclass.onAdd.call(this, c);
			this.processAdd(c)
		},
		onAddEvent : function (ct, c) {
			if (ct !== this)
				this.processAdd(c)
		},
		processAdd : function (c) {
			if (this.isField(c))
				this.form.add(c);
			else if (c.findBy) {
				this.applySettings(c);
				this.form.add.apply(this.form, c.findBy(this.isField))
			}
		},
		onRemove : function (c) {
			Ext.FormPanel.superclass.onRemove.call(this, c);
			this.processRemove(c)
		},
		onRemoveEvent : function (ct, c) {
			if (ct !== this)
				this.processRemove(c)
		},
		processRemove : function (c) {
			if (!this.destroying)
				if (this.isField(c))
					this.form.remove(c);
				else if (c.findBy) {
					Ext.each(c.findBy(this.isField), this.form.remove, this.form);
					this.form.cleanDestroyed()
				}
		},
		startMonitoring : function () {
			if (!this.validTask) {
				this.validTask = new Ext.util.TaskRunner;
				this.validTask.start({
					run : this.bindHandler,
					interval : this.monitorPoll || 200,
					scope : this
				})
			}
		},
		stopMonitoring : function () {
			if (this.validTask) {
				this.validTask.stopAll();
				this.validTask = null
			}
		},
		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 () {
			var valid = true;
			this.form.items.each(function (f) {
				if (!f.isValid(true)) {
					valid = false;
					return false
				}
			});
			if (this.fbar) {
				var fitems = this.fbar.items.items;
				var i = 0;
				for (var len = fitems.length; i < len; i++) {
					var btn = fitems[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",
		animCollapse : false,
		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 = this.baseCls + "-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.mon(this.checkbox, "click", this.onCheckClick, this)
			}
		},
		onCollapse : function (doAnim, animArg) {
			if (this.checkbox)
				this.checkbox.dom.checked = false;
			Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg)
		},
		onExpand : function (doAnim, animArg) {
			if (this.checkbox)
				this.checkbox.dom.checked = true;
			Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg)
		},
		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",
		defaultValue : Ext.isOpera || Ext.isIE6 ? "\x26#160;" : "\x26#8203;",
		actionMode : "wrap",
		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");
			Ext.form.HtmlEditor.superclass.initComponent.call(this)
		},
		createFontOptions : function () {
			var buf = [];
			var fs = this.fontFamilies;
			var ff;
			var lc;
			var i = 0;
			for (var len = fs.length; i < len; i++) {
				ff = fs[i];
				lc = ff.toLowerCase();
				buf.push('\x3coption value\x3d"', lc, '" style\x3d"font-family:', ff, ';"', this.defaultFont == lc ? ' selected\x3d"true"\x3e' : "\x3e", ff, "\x3c/option\x3e")
			}
			return buf.join("")
		},
		createToolbar : function (editor) {
			function btn$$0(id, toggle, handler) {
				return {
					itemId : id,
					cls : "x-btn-icon",
					iconCls : "x-edit-" + id,
					enableToggle : toggle !== false,
					scope : editor,
					handler : handler || editor.relayBtnCmd,
					clickEvent : "mousedown",
					tooltip : tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
					overflowText : editor.buttonTips[id].title || undefined,
					tabIndex : -1
				}
			}
			var items = [];
			var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
			if (this.enableFont && !Ext.isSafari2) {
				var fontSelectItem = new Ext.Toolbar.Item({
						autoEl : {
							tag : "select",
							cls : "x-font-select",
							html : this.createFontOptions()
						}
					});
				items.push(fontSelectItem, "-")
			}
			if (this.enableFormat)
				items.push(btn$$0("bold"), btn$$0("italic"), btn$$0("underline"));
			if (this.enableFontSize)
				items.push("-", btn$$0("increasefontsize", false, this.adjustFont), btn$$0("decreasefontsize", false, this.adjustFont));
			if (this.enableColors)
				items.push("-", {
					itemId : "forecolor",
					cls : "x-btn-icon",
					iconCls : "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,
						listeners : {
							scope : this,
							select : function (cp, color) {
								this.execCmd("forecolor", Ext.isWebKit || Ext.isIE ? "#" + color : color);
								this.deferFocus()
							}
						},
						clickEvent : "mousedown"
					})
				}, {
					itemId : "backcolor",
					cls : "x-btn-icon",
					iconCls : "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,
						listeners : {
							scope : this,
							select : 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.isWebKit || Ext.isIE ? "#" + color : color);
									this.deferFocus()
								}
							}
						},
						clickEvent : "mousedown"
					})
				});
			if (this.enableAlignments)
				items.push("-",
					btn$$0("justifyleft"), btn$$0("justifycenter"), btn$$0("justifyright"));
			if (!Ext.isSafari2) {
				if (this.enableLinks)
					items.push("-", btn$$0("createlink", false, this.createLink));
				if (this.enableLists)
					items.push("-", btn$$0("insertorderedlist"), btn$$0("insertunorderedlist"));
				if (this.enableSourceEdit)
					items.push("-", btn$$0("sourceedit", true, function (btn) {
							this.toggleSourceEdit(!this.sourceEditMode)
						}))
			}
			var tb = new Ext.Toolbar({
					renderTo : this.wrap.dom.firstChild,
					items : items
				});
			if (fontSelectItem) {
				this.fontSelect = fontSelectItem.el;
				this.mon(this.fontSelect, "change", function () {
					var font = this.fontSelect.dom.value;
					this.relayCmd("fontname", font);
					this.deferFocus()
				}, this)
			}
			this.mon(tb.el, "click", function (e) {
				e.preventDefault()
			});
			this.tb = tb;
			this.tb.doLayout()
		},
		onDisable : function () {
			this.wrap.mask();
			Ext.form.HtmlEditor.superclass.onDisable.call(this)
		},
		onEnable : function () {
			this.wrap.unmask();
			Ext.form.HtmlEditor.superclass.onEnable.call(this)
		},
		setReadOnly : function (readOnly) {
			Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
			if (this.initialized) {
				if (Ext.isIE)
					this.getEditorBody().contentEditable =
						!readOnly;
				else
					this.setDesignMode(!readOnly);
				var bd = this.getEditorBody();
				if (bd)
					bd.style.cursor = this.readOnly ? "default" : "text";
				this.disableItems(readOnly)
			}
		},
		getDocMarkup : function () {
			var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
			return String.format('\x3chtml\x3e\x3chead\x3e\x3cstyle type\x3d"text/css"\x3ebody{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}\x3c/style\x3e\x3c/head\x3e\x3cbody\x3e\x3c/body\x3e\x3c/html\x3e', this.iframePad, h)
		},
		getEditorBody : function () {
			var doc =
				this.getDoc();
			return doc.body || 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.disableItems(true);
			this.tb.doLayout();
			this.createIFrame();
			if (!this.width) {
				var sz = this.el.getSize();
				this.setSize(sz.width, this.height || sz.height)
			}
			this.resizeEl = this.positionEl = this.wrap
		},
		createIFrame : function () {
			var iframe = document.createElement("iframe");
			iframe.name = Ext.id();
			iframe.frameBorder = "0";
			iframe.style.overflow = "auto";
			iframe.src = Ext.SSL_SECURE_URL;
			this.wrap.dom.appendChild(iframe);
			this.iframe =
				iframe;
			this.monitorTask = Ext.TaskMgr.start({
					run : this.checkDesignMode,
					scope : this,
					interval : 100
				})
		},
		initFrame : function () {
			Ext.TaskMgr.stop(this.monitorTask);
			var doc$$0 = this.getDoc();
			this.win = this.getWin();
			doc$$0.open();
			doc$$0.write(this.getDocMarkup());
			doc$$0.close();
			var task = {
				run : function () {
					var doc = this.getDoc();
					if (doc.body || doc.readyState == "complete") {
						Ext.TaskMgr.stop(task);
						this.setDesignMode(true);
						this.initEditor.defer(10, this)
					}
				},
				interval : 10,
				duration : 1E4,
				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 || this.getDesignMode() != "on")
					this.initFrame()
			}
		},
		setDesignMode : function (mode) {
			var doc = this.getDoc();
			if (doc) {
				if (this.readOnly)
					mode = false;
				doc.designMode = /on|true/i.test(String(mode).toLowerCase()) ? "on" : "off"
			}
		},
		getDesignMode : function () {
			var doc = this.getDoc();
			if (!doc)
				return "";
			return String(doc.designMode).toLowerCase()
		},
		disableItems : function (disabled) {
			if (this.fontSelect)
				this.fontSelect.dom.disabled = disabled;
			this.tb.items.each(function (item) {
				if (item.getItemId() !=
					"sourceedit")
					item.setDisabled(disabled)
			})
		},
		onResize : function (w, h) {
			Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
			if (this.el && this.iframe) {
				if (Ext.isNumber(w)) {
					var aw = w - this.wrap.getFrameWidth("lr");
					this.el.setWidth(aw);
					this.tb.setWidth(aw);
					this.iframe.style.width = Math.max(aw, 0) + "px"
				}
				if (Ext.isNumber(h)) {
					var ah = h - this.wrap.getFrameWidth("tb") - this.tb.el.getHeight();
					this.el.setHeight(ah);
					this.iframe.style.height = Math.max(ah, 0) + "px";
					var bd = this.getEditorBody();
					if (bd)
						bd.style.height = Math.max(ah -
								this.iframePad * 2, 0) + "px"
				}
			}
		},
		toggleSourceEdit : function (sourceEditMode) {
			var iframeHeight;
			var elHeight;
			if (sourceEditMode === undefined)
				sourceEditMode = !this.sourceEditMode;
			this.sourceEditMode = sourceEditMode === true;
			var btn = this.tb.getComponent("sourceedit");
			if (btn.pressed !== this.sourceEditMode) {
				btn.toggle(this.sourceEditMode);
				if (!btn.xtbHidden)
					return
			}
			if (this.sourceEditMode) {
				this.previousSize = this.getSize();
				iframeHeight = Ext.get(this.iframe).getHeight();
				this.disableItems(true);
				this.syncValue();
				this.iframe.className =
					"x-hidden";
				this.el.removeClass("x-hidden");
				this.el.dom.removeAttribute("tabIndex");
				this.el.focus();
				this.el.dom.style.height = iframeHeight + "px"
			} else {
				elHeight = parseInt(this.el.dom.style.height, 10);
				if (this.initialized)
					this.disableItems(this.readOnly);
				this.pushValue();
				this.iframe.className = "";
				this.el.addClass("x-hidden");
				this.el.dom.setAttribute("tabIndex", -1);
				this.deferFocus();
				this.setSize(this.previousSize);
				delete this.previousSize;
				this.iframe.style.height = elHeight + "px"
			}
			this.fireEvent("editmodechange",
				this, this.sourceEditMode)
		},
		createLink : function () {
			var url = prompt(this.createLinkText, this.defaultLinkValue);
			if (url && url != "http:/" + "/")
				this.relayCmd("createlink", url)
		},
		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();
			return this
		},
		cleanHtml : function (html) {
			html = String(html);
			if (Ext.isWebKit)
				html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi,
						"");
			if (html.charCodeAt(0) == this.defaultValue.replace(/\D/g, ""))
				html = html.substring(1);
			return html
		},
		syncValue : function () {
			if (this.initialized) {
				var bd = this.getEditorBody();
				var html = bd.innerHTML;
				if (Ext.isWebKit) {
					var bs = bd.getAttribute("style");
					var m = bs.match(/text-align:(.*?);/i);
					if (m && m[1])
						html = '\x3cdiv style\x3d"' + m[0] + '"\x3e' + html + "\x3c/div\x3e"
				}
				html = this.cleanHtml(html);
				if (this.fireEvent("beforesync", this, html) !== false) {
					this.el.dom.value = html;
					this.fireEvent("sync", this, html)
				}
			}
		},
		getValue : function () {
			this[this.sourceEditMode ?
				"pushValue" : "syncValue"]();
			return Ext.form.HtmlEditor.superclass.getValue.call(this)
		},
		pushValue : function () {
			if (this.initialized) {
				var v = this.el.dom.value;
				if (!this.activated && v.length < 1)
					v = this.defaultValue;
				if (this.fireEvent("beforepush", this, v) !== false) {
					this.getEditorBody().innerHTML = v;
					if (Ext.isGecko) {
						this.setDesignMode(false);
						this.setDesignMode(true)
					}
					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 () {
			try {
				var dbody = this.getEditorBody();
				var ss = this.el.getStyles("font-size", "font-family", "background-image", "background-repeat", "background-color", "color");
				var doc;
				var fn;
				ss["background-attachment"] = "fixed";
				dbody.bgProperties = "fixed";
				Ext.DomHelper.applyStyles(dbody, ss);
				doc = this.getDoc();
				if (doc)
					try {
						Ext.EventManager.removeAll(doc)
					} catch (e) {}

				fn = this.onEditorEvent.createDelegate(this);
				Ext.EventManager.on(doc, {
					mousedown : fn,
					dblclick : fn,
					click : fn,
					keyup : fn,
					buffer : 100
				});
				if (Ext.isGecko)
					Ext.EventManager.on(doc, "keypress", this.applyCommand, this);
				if (Ext.isIE || Ext.isWebKit || Ext.isOpera)
					Ext.EventManager.on(doc, "keydown", this.fixKeys, this);
				doc.editorInitialized = true;
				this.initialized = true;
				this.pushValue();
				this.setReadOnly(this.readOnly);
				this.fireEvent("initialize", this)
			} catch (e$$0) {}

		},
		beforeDestroy : function () {
			if (this.monitorTask)
				Ext.TaskMgr.stop(this.monitorTask);
			if (this.rendered) {
				Ext.destroy(this.tb);
				var doc = this.getDoc();
				if (doc)
					try {
						Ext.EventManager.removeAll(doc);
						for (var prop in doc)
							delete doc[prop]
					} catch (e) {}

				if (this.wrap) {
					this.wrap.dom.innerHTML =
						"";
					this.wrap.remove()
				}
			}
			Ext.form.HtmlEditor.superclass.beforeDestroy.call(this)
		},
		onFirstFocus : function () {
			this.activated = true;
			this.disableItems(this.readOnly);
			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.getItemId() == "increasefontsize" ? 1 : -1;
			var doc = this.getDoc();
			var v = parseInt(doc.queryCommandValue("FontSize") || 2, 10);
			if (Ext.isSafari && !Ext.isSafari2 || Ext.isChrome || 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.readOnly)
				return;
			if (!this.activated) {
				this.onFirstFocus();
				return
			}
			var btns = this.tb.items.map;
			var doc = this.getDoc();
			if (this.enableFont && !Ext.isSafari2) {
				var name = (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.getItemId())
		},
		relayCmd : function (cmd, value) {
			(function () {
				this.focus();
				this.execCmd(cmd, value);
				this.updateToolbar()
			}).defer(10,
				this)
		},
		execCmd : function (cmd, value) {
			var doc = this.getDoc();
			doc.execCommand(cmd, false, value === undefined ? null : value);
			this.syncValue()
		},
		applyCommand : function (e) {
			if (e.ctrlKey) {
				var c = e.getCharCode();
				var 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 doc =
					this.getDoc();
				var r = doc.selection.createRange();
				if (r) {
					r.pasteHTML(text);
					this.syncValue();
					this.deferFocus()
				}
			} else {
				this.win.focus();
				this.execCmd("InsertHTML", text);
				this.deferFocus()
			}
		},
		fixKeys : function () {
			if (Ext.isIE)
				return function (e) {
					var k = e.getKey();
					var doc = this.getDoc();
					var r;
					if (k == e.TAB) {
						e.stopEvent();
						r = doc.selection.createRange();
						if (r) {
							r.collapse(true);
							r.pasteHTML("\x26nbsp;\x26nbsp;\x26nbsp;\x26nbsp;");
							this.deferFocus()
						}
					} else if (k == e.ENTER) {
						r = doc.selection.createRange();
						if (r) {
							var target = r.parentElement();
							if (!target || target.tagName.toLowerCase() != "li") {
								e.stopEvent();
								r.pasteHTML("\x3cbr /\x3e");
								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", "\x26nbsp;\x26nbsp;\x26nbsp;\x26nbsp;");
						this.deferFocus()
					}
				};
			else if (Ext.isWebKit)
				return function (e) {
					var k = e.getKey();
					if (k == e.TAB) {
						e.stopEvent();
						this.execCmd("InsertText", "\t");
						this.deferFocus()
					} else if (k == e.ENTER) {
						e.stopEvent();
						this.execCmd("InsertHtml",
							"\x3cbr /\x3e\x3cbr /\x3e");
						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 : undefined,
		maxValue : undefined,
		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|gi a|hi a|giA|hiA|gi A|hi A",
		increment : 15,
		mode : "local",
		triggerAction : "all",
		typeAhead : false,
		initDate : "1/1/2008",
		initDateFormat : "j/n/Y",
		initComponent : function () {
			if (Ext.isDefined(this.minValue))
				this.setMinValue(this.minValue,
					true);
			if (Ext.isDefined(this.maxValue))
				this.setMaxValue(this.maxValue, true);
			if (!this.store)
				this.generateStore(true);
			Ext.form.TimeField.superclass.initComponent.call(this)
		},
		setMinValue : function (value, initial) {
			this.setLimit(value, true, initial);
			return this
		},
		setMaxValue : function (value, initial) {
			this.setLimit(value, false, initial);
			return this
		},
		generateStore : function (initial) {
			var min = this.minValue || (new Date(this.initDate)).clearTime();
			var max = this.maxValue || (new Date(this.initDate)).clearTime().add("mi",
					24 * 60 - 1);
			for (var times = []; min <= max; ) {
				times.push(min.dateFormat(this.format));
				min = min.add("mi", this.increment)
			}
			this.bindStore(times, initial)
		},
		setLimit : function (value, isMin, initial) {
			var d;
			if (Ext.isString(value))
				d = this.parseDate(value);
			else if (Ext.isDate(value))
				d = value;
			if (d) {
				var val = (new Date(this.initDate)).clearTime();
				val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
				this[isMin ? "minValue" : "maxValue"] = val;
				if (!initial)
					this.generateStore()
			}
		},
		getValue : function () {
			var v = Ext.form.TimeField.superclass.getValue.call(this);
			return this.formatDate(this.parseDate(v)) || ""
		},
		setValue : function (value) {
			return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)))
		},
		validateValue : Ext.form.DateField.prototype.validateValue,
		formatDate : Ext.form.DateField.prototype.formatDate,
		parseDate : function (value) {
			if (!value || Ext.isDate(value))
				return value;
			var id = this.initDate + " ";
			var idf = this.initDateFormat + " ";
			var v = Date.parseDate(id + value, idf + this.format);
			var af = this.altFormats;
			if (!v && af) {
				if (!this.altFormatsArray)
					this.altFormatsArray =
						af.split("|");
				var i = 0;
				var afa = this.altFormatsArray;
				for (var len = afa.length; i < len && !v; i++)
					v = Date.parseDate(id + value, idf + afa[i])
			}
			return v
		}
	});
Ext.reg("timefield", Ext.form.TimeField);
Ext.form.SliderField = Ext.extend(Ext.form.Field, {
		useTips : true,
		tipText : null,
		actionMode : "wrap",
		initComponent : function () {
			var cfg = Ext.copyTo({
					id : this.id + "-slider"
				}, this.initialConfig, ["vertical", "minValue", "maxValue", "decimalPrecision", "keyIncrement", "increment", "clickToChange", "animate"]);
			if (this.useTips) {
				var plug = this.tipText ? {
					getText : this.tipText
				}
				 : {};
				cfg.plugins = [new Ext.slider.Tip(plug)]
			}
			this.slider = new Ext.Slider(cfg);
			Ext.form.SliderField.superclass.initComponent.call(this)
		},
		onRender : function (ct,
			position) {
			this.autoCreate = {
				id : this.id,
				name : this.name,
				type : "hidden",
				tag : "input"
			};
			Ext.form.SliderField.superclass.onRender.call(this, ct, position);
			this.wrap = this.el.wrap({
					cls : "x-form-field-wrap"
				});
			this.resizeEl = this.positionEl = this.wrap;
			this.slider.render(this.wrap)
		},
		onResize : function (w, h, aw, ah) {
			Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
			this.slider.setSize(w, h)
		},
		initEvents : function () {
			Ext.form.SliderField.superclass.initEvents.call(this);
			this.slider.on("change", this.onChange, this)
		},
		onChange : function (slider, v) {
			this.setValue(v, undefined, true)
		},
		onEnable : function () {
			Ext.form.SliderField.superclass.onEnable.call(this);
			this.slider.enable()
		},
		onDisable : function () {
			Ext.form.SliderField.superclass.onDisable.call(this);
			this.slider.disable()
		},
		beforeDestroy : function () {
			Ext.destroy(this.slider);
			Ext.form.SliderField.superclass.beforeDestroy.call(this)
		},
		alignErrorIcon : function () {
			this.errorIcon.alignTo(this.slider.el, "tl-tr", [2, 0])
		},
		setMinValue : function (v) {
			this.slider.setMinValue(v);
			return this
		},
		setMaxValue : function (v) {
			this.slider.setMaxValue(v);
			return this
		},
		setValue : function (v, animate, silent) {
			if (!silent)
				this.slider.setValue(v, animate);
			return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue())
		},
		getValue : function () {
			return this.slider.getValue()
		}
	});
Ext.reg("sliderfield", Ext.form.SliderField);
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("for", this.forId)
			}
			Ext.form.Label.superclass.onRender.call(this, ct, position)
		},
		setText : function (t, encode) {
			var e = encode === false;
			this[!e ? "text" : "html"] = t;
			delete this[e ? "text" : "html"];
			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 && !response.responseXML)
			return true;
		this.result = this.handleResponse(response);
		return this.result
	},
	decodeResponse : function (response) {
		try {
			return Ext.decode(response.responseText)
		} catch (e) {
			return false
		}
	},
	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 = Ext.urlAppend(url, 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 += "\x26" + Ext.urlEncode(bp)
			}
		else if (bp)
			p =
				Ext.urlEncode(bp);
		return p
	},
	createCallback : function (opts) {
		opts = opts || {};
		return {
			success : this.success,
			failure : this.failure,
			scope : this,
			timeout : opts.timeout * 1E3 || this.form.timeout * 1E3,
			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()) {
			if (o.submitEmptyText === false) {
				var fields = this.form.items;
				var emptyFields = [];
				var setupEmptyFields = function (f) {
					if (f.el.getValue() == f.emptyText) {
						emptyFields.push(f);
						f.el.dom.value = ""
					}
					if (f.isComposite && f.rendered)
						f.items.each(setupEmptyFields)
				};
				fields.each(setupEmptyFields)
			}
			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
				}));
			if (o.submitEmptyText === false)
				Ext.each(emptyFields, function (f) {
					if (f.applyEmptyText)
						f.applyEmptyText()
				})
		} 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) {
				var i = 0;
				for (var 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 this.decodeResponse(response)
	}
});
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 this.decodeResponse(response)
	}
});
Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
		constructor : function (form, opts) {
			Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts)
		},
		type : "directload",
		run : function () {
			var args = this.getParams();
			args.push(this.success, this);
			this.form.api.load.apply(window, args)
		},
		getParams : function () {
			var buf = [];
			var o = {};
			var bp = this.form.baseParams;
			var p = this.options.params;
			Ext.apply(o, p, bp);
			var paramOrder = this.form.paramOrder;
			if (paramOrder) {
				var i = 0;
				for (var len = paramOrder.length; i < len; i++)
					buf.push(o[paramOrder[i]])
			} else if (this.form.paramsAsHash)
				buf.push(o);
			return buf
		},
		processResponse : function (result) {
			this.result = result;
			return result
		},
		success : function (response, trans) {
			if (trans.type == Ext.Direct.exceptions.SERVER)
				response = {};
			Ext.form.Action.DirectLoad.superclass.success.call(this, response)
		}
	});
Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
		constructor : function (form, opts) {
			Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts)
		},
		type : "directsubmit",
		run : function () {
			var o = this.options;
			if (o.clientValidation === false || this.form.isValid()) {
				this.success.params = this.getParams();
				this.form.api.submit(this.form.el.dom, this.success, this)
			} else if (o.clientValidation !== false) {
				this.failureType = Ext.form.Action.CLIENT_INVALID;
				this.form.afterAction(this, false)
			}
		},
		getParams : function () {
			var o = {};
			var bp = this.form.baseParams;
			var p = this.options.params;
			Ext.apply(o, p, bp);
			return o
		},
		processResponse : function (result) {
			this.result = result;
			return result
		},
		success : function (response, trans) {
			if (trans.type == Ext.Direct.exceptions.SERVER)
				response = {};
			Ext.form.Action.DirectSubmit.superclass.success.call(this, response)
		}
	});
Ext.form.Action.ACTION_TYPES = {
	"load" : Ext.form.Action.Load,
	"submit" : Ext.form.Action.Submit,
	"directload" : Ext.form.Action.DirectLoad,
	"directsubmit" : Ext.form.Action.DirectSubmit
};
Ext.form.VTypes = function () {
	var alpha = /^[a-zA-Z_]+$/;
	var alphanum = /^[a-zA-Z0-9_]+$/;
	var email = /^(\w+)([\-+.\'][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/;
	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@example.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.example.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, {
		autoExpandColumn : false,
		autoExpandMax : 1E3,
		autoExpandMin : 50,
		columnLines : false,
		ddText : "{0} selected row{1}",
		deferRowRender : true,
		enableColumnHide : true,
		enableColumnMove : true,
		enableDragDrop : false,
		enableHdMenu : true,
		loadMask : false,
		minColumnWidth : 25,
		stripeRows : false,
		trackMouseOver : true,
		stateEvents : ["columnmove", "columnresize", "sortchange", "groupchange"],
		view : null,
		bubbleEvents : [],
		rendered : false,
		viewReady : false,
		initComponent : function () {
			Ext.grid.GridPanel.superclass.initComponent.call(this);
			if (this.columnLines)
				this.cls = (this.cls || "") + " x-grid-with-col-lines";
			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", "groupmousedown", "rowbodymousedown", "containermousedown", "cellclick", "celldblclick", "rowclick", "rowdblclick", "headerclick", "headerdblclick", "groupclick", "groupdblclick", "containerclick", "containerdblclick", "rowbodyclick", "rowbodydblclick", "rowcontextmenu", "cellcontextmenu", "headercontextmenu", "groupcontextmenu", "containercontextmenu", "rowbodycontextmenu", "bodyscroll", "columnresize", "columnmove", "sortchange", "groupchange", "reconfigure", "viewready")
		},
		onRender : function (ct, position) {
			Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
			var c = this.getGridEl();
			this.el.addClass("x-grid-panel");
			this.mon(c, {
				scope : this,
				mousedown : this.onMouseDown,
				click : this.onClick,
				dblclick : this.onDblClick,
				contextmenu : this.onContextMenu
			});
			this.relayEvents(c, ["mousedown", "mouseup", "mouseover", "mouseout", "keypress", "keydown"]);
			var view = this.getView();
			view.init(this);
			view.render();
			this.getSelectionModel().init(this)
		},
		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.mon(this.colModel, "hiddenchange", this.saveState, this, {
				delay : 100
			})
		},
		applyState : function (state) {
			var cm = this.colModel;
			var cs = state.columns;
			var store = this.store;
			var s;
			var c;
			var colIndex;
			if (cs) {
				var i = 0;
				for (var len = cs.length; i < len; i++) {
					s = cs[i];
					c = cm.getColumnById(s.id);
					if (c) {
						colIndex = cm.getIndexById(s.id);
						cm.setState(colIndex, {
							hidden : s.hidden,
							width : s.width,
							sortable : s.sortable
						});
						if (colIndex != i)
							cm.moveColumn(colIndex, i)
					}
				}
			}
			if (store) {
				s = state.sort;
				if (s)
					store[store.remoteSort ? "setDefaultSort" : "sort"](s.field, s.direction);
				s = state.group;
				if (store.groupBy)
					if (s)
						store.groupBy(s);
					else
						store.clearGrouping()
			}
			var o = Ext.apply({}, state);
			delete o.columns;
			delete o.sort;
			Ext.grid.GridPanel.superclass.applyState.call(this, o)
		},
		getState : function () {
			var o = {
				columns : []
			};
			var store = this.store;
			var ss;
			var gs;
			var i = 0;
			for (var c; c = this.colModel.config[i]; i++) {
				o.columns[i] = {
					id : c.id,
					width : c.width
				};
				if (c.hidden)
					o.columns[i].hidden = true;
				if (c.sortable)
					o.columns[i].sortable = true
			}
			if (store) {
				ss = store.getSortState();
				if (ss)
					o.sort = ss;
				if (store.getGroupState) {
					gs = store.getGroupState();
					if (gs)
						o.group = gs
				}
			}
			return o
		},
		afterRender : function () {
			Ext.grid.GridPanel.superclass.afterRender.call(this);
			var v = this.view;
			this.on("bodyresize", v.layout, v);
			v.layout(true);
			if (this.deferRowRender) {
				if (!this.deferRowRenderTask)
					this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
				this.deferRowRenderTask.delay(10)
			} else
				v.afterRender();
			this.viewReady = true
		},
		reconfigure : function (store, colModel) {
			var rendered = this.rendered;
			if (rendered)
				if (this.loadMask) {
					this.loadMask.destroy();
					this.loadMask = new Ext.LoadMask(this.bwrap, Ext.apply({}, {
								store : store
							}, this.initialConfig.loadMask))
				}
			if (this.view)
				this.view.initData(store, colModel);
			this.store = store;
			this.colModel = colModel;
			if (rendered)
				this.view.refresh(true);
			this.fireEvent("reconfigure", this, store, colModel)
		},
		onDestroy : function () {
			if (this.deferRowRenderTask && this.deferRowRenderTask.cancel)
				this.deferRowRenderTask.cancel();
			if (this.rendered)
				Ext.destroy(this.view, this.loadMask);
			else if (this.store && this.store.autoDestroy)
				this.store.destroy();
			Ext.destroy(this.colModel, this.selModel);
			this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
			Ext.grid.GridPanel.superclass.onDestroy.call(this)
		},
		processEvent : function (name, e) {
			this.view.processEvent(name, 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;
			var clen = cm.getColumnCount();
			var ds = this.store;
			var rlen = ds.getCount();
			var first = true;
			if (step < 0) {
				if (col < 0) {
					row--;
					first = false
				}
				for (; row >= 0; ) {
					if (!first)
						col = clen - 1;
					for (first = false; col >= 0; ) {
						if (fn.call(scope || this, row, col, cm) === true)
							return [row, col];
						col--
					}
					row--
				}
			} else {
				if (col >= clen) {
					row++;
					first = false
				}
				for (; row < rlen; ) {
					if (!first)
						col = 0;
					for (first = false; col < clen; ) {
						if (fn.call(scope || this, row,
								col, cm) === true)
							return [row, col];
						col++
					}
					row++
				}
			}
			return null
		},
		getGridEl : function () {
			return this.body
		},
		stopEditing : Ext.emptyFn,
		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.PivotGrid = Ext.extend(Ext.grid.GridPanel, {
		aggregator : "sum",
		renderer : undefined,
		initComponent : function () {
			Ext.grid.PivotGrid.superclass.initComponent.apply(this, arguments);
			this.initAxes();
			this.enableColumnResize = false;
			this.viewConfig = Ext.apply(this.viewConfig || {}, {
					forceFit : true
				});
			this.colModel = new Ext.grid.ColumnModel({})
		},
		getAggregator : function () {
			if (typeof this.aggregator == "string")
				return Ext.grid.PivotAggregatorMgr.types[this.aggregator];
			else
				return this.aggregator
		},
		setAggregator : function (aggregator) {
			this.aggregator =
				aggregator
		},
		setMeasure : function (measure) {
			this.measure = measure
		},
		setLeftAxis : function (axis, refresh) {
			this.leftAxis = axis;
			if (refresh)
				this.view.refresh()
		},
		setTopAxis : function (axis, refresh) {
			this.topAxis = axis;
			if (refresh)
				this.view.refresh()
		},
		initAxes : function () {
			var PivotAxis = Ext.grid.PivotAxis;
			if (!(this.leftAxis instanceof PivotAxis))
				this.setLeftAxis(new PivotAxis({
						orientation : "vertical",
						dimensions : this.leftAxis || [],
						store : this.store
					}));
			if (!(this.topAxis instanceof PivotAxis))
				this.setTopAxis(new PivotAxis({
						orientation : "horizontal",
						dimensions : this.topAxis || [],
						store : this.store
					}))
		},
		extractData : function () {
			var records = this.store.data.items;
			var recCount = records.length;
			var cells = [];
			var record;
			var i;
			var j;
			var k;
			if (recCount == 0)
				return [];
			var leftTuples = this.leftAxis.getTuples();
			var leftCount = leftTuples.length;
			var topTuples = this.topAxis.getTuples();
			var topCount = topTuples.length;
			var aggregator = this.getAggregator();
			for (i = 0; i < recCount; i++) {
				record = records[i];
				for (j = 0; j < leftCount; j++) {
					cells[j] = cells[j] || [];
					if (leftTuples[j].matcher(record) ===
						true)
						for (k = 0; k < topCount; k++) {
							cells[j][k] = cells[j][k] || [];
							if (topTuples[k].matcher(record))
								cells[j][k].push(record)
						}
				}
			}
			var rowCount = cells.length;
			var colCount;
			var row;
			for (i = 0; i < rowCount; i++) {
				row = cells[i];
				colCount = row.length;
				for (j = 0; j < colCount; j++)
					cells[i][j] = aggregator(cells[i][j], this.measure)
			}
			return cells
		},
		getView : function () {
			if (!this.view)
				this.view = new Ext.grid.PivotGridView(this.viewConfig);
			return this.view
		}
	});
Ext.reg("pivotgrid", Ext.grid.PivotGrid);
Ext.grid.PivotAggregatorMgr = new Ext.AbstractManager;
Ext.grid.PivotAggregatorMgr.registerType("sum", function (records, measure) {
	var length = records.length;
	var total = 0;
	var i;
	for (i = 0; i < length; i++)
		total += records[i].get(measure);
	return total
});
Ext.grid.PivotAggregatorMgr.registerType("avg", function (records, measure) {
	var length = records.length;
	var total = 0;
	var i;
	for (i = 0; i < length; i++)
		total += records[i].get(measure);
	return total / length || "n/a"
});
Ext.grid.PivotAggregatorMgr.registerType("min", function (records, measure) {
	var data = [];
	var length = records.length;
	var i;
	for (i = 0; i < length; i++)
		data.push(records[i].get(measure));
	return Math.min.apply(this, data) || "n/a"
});
Ext.grid.PivotAggregatorMgr.registerType("max", function (records, measure) {
	var data = [];
	var length = records.length;
	var i;
	for (i = 0; i < length; i++)
		data.push(records[i].get(measure));
	return Math.max.apply(this, data) || "n/a"
});
Ext.grid.PivotAggregatorMgr.registerType("count", function (records, measure) {
	return records.length
});
Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
		deferEmptyText : true,
		scrollOffset : undefined,
		autoFill : false,
		forceFit : false,
		sortClasses : ["sort-asc", "sort-desc"],
		sortAscText : "Sort Ascending",
		sortDescText : "Sort Descending",
		columnsText : "Columns",
		selectedRowClass : "x-grid3-row-selected",
		borderWidth : 2,
		tdClass : "x-grid3-cell",
		hdCls : "x-grid3-hd",
		markDirty : true,
		cellSelectorDepth : 4,
		rowSelectorDepth : 10,
		rowBodySelectorDepth : 10,
		cellSelector : "td.x-grid3-cell",
		rowSelector : "div.x-grid3-row",
		rowBodySelector : "div.x-grid3-row-body",
		firstRowCls : "x-grid3-row-first",
		lastRowCls : "x-grid3-row-last",
		rowClsRe : /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
		headerMenuOpenCls : "x-grid3-hd-menu-open",
		rowOverCls : "x-grid3-row-over",
		constructor : function (config) {
			Ext.apply(this, config);
			this.addEvents("beforerowremoved", "beforerowsinserted", "beforerefresh", "rowremoved", "rowsinserted", "rowupdated", "refresh");
			Ext.grid.GridView.superclass.constructor.call(this)
		},
		masterTpl : new Ext.Template('\x3cdiv class\x3d"x-grid3" hidefocus\x3d"true"\x3e', '\x3cdiv class\x3d"x-grid3-viewport"\x3e',
			'\x3cdiv class\x3d"x-grid3-header"\x3e', '\x3cdiv class\x3d"x-grid3-header-inner"\x3e', '\x3cdiv class\x3d"x-grid3-header-offset" style\x3d"{ostyle}"\x3e{header}\x3c/div\x3e', "\x3c/div\x3e", '\x3cdiv class\x3d"x-clear"\x3e\x3c/div\x3e', "\x3c/div\x3e", '\x3cdiv class\x3d"x-grid3-scroller"\x3e', '\x3cdiv class\x3d"x-grid3-body" style\x3d"{bstyle}"\x3e{body}\x3c/div\x3e', '\x3ca href\x3d"#" class\x3d"x-grid3-focus" tabIndex\x3d"-1"\x3e\x3c/a\x3e', "\x3c/div\x3e", "\x3c/div\x3e", '\x3cdiv class\x3d"x-grid3-resize-marker"\x3e\x26#160;\x3c/div\x3e',
			'\x3cdiv class\x3d"x-grid3-resize-proxy"\x3e\x26#160;\x3c/div\x3e', "\x3c/div\x3e"),
		headerTpl : new Ext.Template('\x3ctable border\x3d"0" cellspacing\x3d"0" cellpadding\x3d"0" style\x3d"{tstyle}"\x3e', "\x3cthead\x3e", '\x3ctr class\x3d"x-grid3-hd-row"\x3e{cells}\x3c/tr\x3e', "\x3c/thead\x3e", "\x3c/table\x3e"),
		bodyTpl : new Ext.Template("{rows}"),
		cellTpl : new Ext.Template('\x3ctd class\x3d"x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style\x3d"{style}" tabIndex\x3d"0" {cellAttr}\x3e', '\x3cdiv class\x3d"x-grid3-cell-inner x-grid3-col-{id}" unselectable\x3d"on" {attr}\x3e{value}\x3c/div\x3e',
			"\x3c/td\x3e"),
		initTemplates : function () {
			var templates = this.templates || {};
			var template;
			var name;
			var headerCellTpl = new Ext.Template('\x3ctd class\x3d"x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style\x3d"{style}"\x3e', '\x3cdiv {tooltip} {attr} class\x3d"x-grid3-hd-inner x-grid3-hd-{id}" unselectable\x3d"on" style\x3d"{istyle}"\x3e', this.grid.enableHdMenu ? '\x3ca class\x3d"x-grid3-hd-btn" href\x3d"#"\x3e\x3c/a\x3e' : "", "{value}", '\x3cimg alt\x3d"" class\x3d"x-grid3-sort-icon" src\x3d"', Ext.BLANK_IMAGE_URL,
					'" /\x3e', "\x3c/div\x3e", "\x3c/td\x3e");
			var rowBodyText = ['\x3ctr class\x3d"x-grid3-row-body-tr" style\x3d"{bodyStyle}"\x3e', '\x3ctd colspan\x3d"{cols}" class\x3d"x-grid3-body-cell" tabIndex\x3d"0" hidefocus\x3d"on"\x3e', '\x3cdiv class\x3d"x-grid3-row-body"\x3e{body}\x3c/div\x3e', "\x3c/td\x3e", "\x3c/tr\x3e"].join("");
			var innerText = ['\x3ctable class\x3d"x-grid3-row-table" border\x3d"0" cellspacing\x3d"0" cellpadding\x3d"0" style\x3d"{tstyle}"\x3e', "\x3ctbody\x3e", "\x3ctr\x3e{cells}\x3c/tr\x3e", this.enableRowBody ?
				rowBodyText : "", "\x3c/tbody\x3e", "\x3c/table\x3e"].join("");
			Ext.applyIf(templates, {
				hcell : headerCellTpl,
				cell : this.cellTpl,
				body : this.bodyTpl,
				header : this.headerTpl,
				master : this.masterTpl,
				row : new Ext.Template('\x3cdiv class\x3d"x-grid3-row {alt}" style\x3d"{tstyle}"\x3e' + innerText + "\x3c/div\x3e"),
				rowInner : new Ext.Template(innerText)
			});
			for (name in templates) {
				template = templates[name];
				if (template && Ext.isFunction(template.compile) && !template.compiled) {
					template.disableFormats = true;
					template.compile()
				}
			}
			this.templates =
				templates;
			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 () {
			return this.scroller.dom
		},
		initElements : function () {
			var Element = Ext.Element;
			var el = Ext.get(this.grid.getGridEl().dom.firstChild);
			var mainWrap = new Element(el.child("div.x-grid3-viewport"));
			var mainHd = new Element(mainWrap.child("div.x-grid3-header"));
			var scroller = new Element(mainWrap.child("div.x-grid3-scroller"));
			if (this.grid.hideHeaders)
				mainHd.setDisplayed(false);
			if (this.forceFit)
				scroller.setStyle("overflow-x", "hidden");
			Ext.apply(this, {
				el : el,
				mainWrap : mainWrap,
				scroller : scroller,
				mainHd : mainHd,
				innerHd : mainHd.child("div.x-grid3-header-inner").dom,
				mainBody : new Element(Element.fly(scroller).child("div.x-grid3-body")),
				focusEl : new Element(Element.fly(scroller).child("a")),
				resizeMarker : new Element(el.child("div.x-grid3-resize-marker")),
				resizeProxy : new Element(el.child("div.x-grid3-resize-proxy"))
			});
			this.focusEl.swallowEvent("click",
				true)
		},
		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);
			var hasCls;
			if (cell) {
				hasCls = this.fly(cell).hasClass(requiredCls);
				if (!requiredCls || hasCls)
					return this.getCellIndex(cell)
			}
			return false
		},
		getCellIndex : function (el) {
			if (el) {
				var match = el.className.match(this.colRe);
				if (match && match[1])
					return this.cm.getIndexById(match[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 row = this.findRow(el);
			return row ? row.rowIndex : false
		},
		findRowBody : function (el) {
			if (!el)
				return false;
			return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth)
		},
		getRow : function (row) {
			return this.getRows()[row]
		},
		getCell : function (row, col) {
			return Ext.fly(this.getRow(row)).query(this.cellSelector)[col]
		},
		getHeaderCell : function (index) {
			return this.mainHd.dom.getElementsByTagName("td")[index]
		},
		addRowClass : function (rowId, cls) {
			var row = this.getRow(rowId);
			if (row)
				this.fly(row).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.syncFocusEl(row)
		},
		removeRows : function (firstRow,
			lastRow) {
			var bd = this.mainBody.dom;
			var rowIndex;
			for (rowIndex = firstRow; rowIndex <= lastRow; rowIndex++)
				Ext.removeNode(bd.childNodes[firstRow]);
			this.syncFocusEl(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 () {
			var dom = this.scroller.dom;
			dom.scrollTop = 0;
			dom.scrollLeft = 0
		},
		syncScroll : function () {
			this.syncHeaderScroll();
			var mb =
				this.scroller.dom;
			this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop)
		},
		syncHeaderScroll : function () {
			var innerHd = this.innerHd;
			var scrollLeft = this.scroller.dom.scrollLeft;
			innerHd.scrollLeft = scrollLeft;
			innerHd.scrollLeft = scrollLeft
		},
		updateSortIcon : function (col, dir) {
			var sortClasses = this.sortClasses;
			var sortClass = sortClasses[dir == "DESC" ? 1 : 0];
			var headers = this.mainHd.select("td").removeClass(sortClasses);
			headers.item(col).addClass(sortClass)
		},
		updateAllColumnWidths : function () {
			var totalWidth = this.getTotalWidth();
			var colCount = this.cm.getColumnCount();
			var rows = this.getRows();
			var rowCount = rows.length;
			var widths = [];
			var row;
			var rowFirstChild;
			var trow;
			var i;
			var j;
			for (i = 0; i < colCount; i++) {
				widths[i] = this.getColumnWidth(i);
				this.getHeaderCell(i).style.width = widths[i]
			}
			this.updateHeaderWidth();
			for (i = 0; i < rowCount; i++) {
				row = rows[i];
				row.style.width = totalWidth;
				rowFirstChild = row.firstChild;
				if (rowFirstChild) {
					rowFirstChild.style.width = totalWidth;
					trow = rowFirstChild.rows[0];
					for (j = 0; j < colCount; j++)
						trow.childNodes[j].style.width =
							widths[j]
				}
			}
			this.onAllColumnWidthsUpdated(widths, totalWidth)
		},
		updateColumnWidth : function (column, width) {
			var columnWidth = this.getColumnWidth(column);
			var totalWidth = this.getTotalWidth();
			var headerCell = this.getHeaderCell(column);
			var nodes = this.getRows();
			var nodeCount = nodes.length;
			var row;
			var i;
			var firstChild;
			this.updateHeaderWidth();
			headerCell.style.width = columnWidth;
			for (i = 0; i < nodeCount; i++) {
				row = nodes[i];
				firstChild = row.firstChild;
				row.style.width = totalWidth;
				if (firstChild) {
					firstChild.style.width = totalWidth;
					firstChild.rows[0].childNodes[column].style.width = columnWidth
				}
			}
			this.onColumnWidthUpdated(column, columnWidth, totalWidth)
		},
		updateColumnHidden : function (col, hidden) {
			var totalWidth = this.getTotalWidth();
			var display = hidden ? "none" : "";
			var headerCell = this.getHeaderCell(col);
			var nodes = this.getRows();
			var nodeCount = nodes.length;
			var row;
			var rowFirstChild;
			var i;
			this.updateHeaderWidth();
			headerCell.style.display = display;
			for (i = 0; i < nodeCount; i++) {
				row = nodes[i];
				row.style.width = totalWidth;
				rowFirstChild = row.firstChild;
				if (rowFirstChild) {
					rowFirstChild.style.width = totalWidth;
					rowFirstChild.rows[0].childNodes[col].style.display = display
				}
			}
			this.onColumnHiddenUpdated(col, hidden, totalWidth);
			delete this.lastViewWidth;
			this.layout()
		},
		doRender : function (columns, records, store, startRow, colCount, stripe) {
			var templates = this.templates;
			var cellTemplate = templates.cell;
			var rowTemplate = templates.row;
			var last = colCount - 1;
			var tstyle = "width:" + this.getTotalWidth() + ";";
			var rowBuffer = [];
			var colBuffer = [];
			var rowParams = {
				tstyle : tstyle
			};
			var meta = {};
			var len = records.length;
			var alt;
			var column;
			var record;
			var i;
			var j;
			var rowIndex;
			for (j = 0; j < len; j++) {
				record = records[j];
				colBuffer = [];
				rowIndex = j + startRow;
				for (i = 0; i < colCount; i++) {
					column = columns[i];
					meta.id = column.id;
					meta.css = i === 0 ? "x-grid3-cell-first " : i == last ? "x-grid3-cell-last " : "";
					meta.attr = meta.cellAttr = "";
					meta.style = column.style;
					meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
					if (Ext.isEmpty(meta.value))
						meta.value = "\x26#160;";
					if (this.markDirty && record.dirty &&
						typeof record.modified[column.name] != "undefined")
						meta.css += " x-grid3-dirty-cell";
					colBuffer[colBuffer.length] = cellTemplate.apply(meta)
				}
				alt = [];
				if (stripe && (rowIndex + 1) % 2 === 0)
					alt[0] = "x-grid3-row-alt";
				if (record.dirty)
					alt[1] = " x-grid3-dirty-row";
				rowParams.cols = colCount;
				if (this.getRowClass)
					alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
				rowParams.alt = alt.join(" ");
				rowParams.cells = colBuffer.join("");
				rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams)
			}
			return rowBuffer.join("")
		},
		processRows : function (startRow,
			skipStripe) {
			if (!this.ds || this.ds.getCount() < 1)
				return;
			var rows = this.getRows();
			var length = rows.length;
			var row;
			var i;
			skipStripe = skipStripe || !this.grid.stripeRows;
			startRow = startRow || 0;
			for (i = 0; i < length; i++) {
				row = rows[i];
				if (row) {
					row.rowIndex = i;
					if (!skipStripe) {
						row.className = row.className.replace(this.rowClsRe, " ");
						if ((i + 1) % 2 === 0)
							row.className += " x-grid3-row-alt"
					}
				}
			}
			if (startRow === 0)
				Ext.fly(rows[0]).addClass(this.firstRowCls);
			Ext.fly(rows[length - 1]).addClass(this.lastRowCls)
		},
		afterRender : function () {
			if (!this.ds ||
				!this.cm)
				return;
			this.mainBody.dom.innerHTML = this.renderBody() || "\x26#160;";
			this.processRows(0, true);
			if (this.deferEmptyText !== true)
				this.applyEmptyText();
			this.grid.fireEvent("viewready", this.grid)
		},
		afterRenderUI : function () {
			var grid = this.grid;
			this.initElements();
			Ext.fly(this.innerHd).on("click", this.handleHdDown, this);
			this.mainHd.on({
				scope : this,
				mouseover : this.handleHdOver,
				mouseout : this.handleHdOut,
				mousemove : this.handleHdMove
			});
			this.scroller.on("scroll", this.syncScroll, this);
			if (grid.enableColumnResize !==
				false)
				this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
			if (grid.enableColumnMove) {
				this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
				this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom)
			}
			if (grid.enableHdMenu !== false) {
				this.hmenu = new Ext.menu.Menu({
						id : grid.id + "-hctx"
					});
				this.hmenu.add({
					itemId : "asc",
					text : this.sortAscText,
					cls : "xg-hmenu-sort-asc"
				}, {
					itemId : "desc",
					text : this.sortDescText,
					cls : "xg-hmenu-sort-desc"
				});
				if (grid.enableColumnHide !== false) {
					this.colMenu =
						new Ext.menu.Menu({
							id : grid.id + "-hcols-menu"
						});
					this.colMenu.on({
						scope : this,
						beforeshow : this.beforeColMenuShow,
						itemclick : this.handleHdMenuClick
					});
					this.hmenu.add("-", {
						itemId : "columns",
						hideOnClick : false,
						text : this.columnsText,
						menu : this.colMenu,
						iconCls : "x-cols-icon"
					})
				}
				this.hmenu.on("itemclick", this.handleHdMenuClick, this)
			}
			if (grid.trackMouseOver)
				this.mainBody.on({
					scope : this,
					mouseover : this.onRowOver,
					mouseout : this.onRowOut
				});
			if (grid.enableDragDrop || grid.enableDrag)
				this.dragZone = new Ext.grid.GridDragZone(grid, {
						ddGroup : grid.ddGroup || "GridDD"
					});
			this.updateHeaderSortState()
		},
		renderUI : function () {
			var templates = this.templates;
			return templates.master.apply({
				body : templates.body.apply({
					rows : "\x26#160;"
				}),
				header : this.renderHeaders(),
				ostyle : "width:" + this.getOffsetWidth() + ";",
				bstyle : "width:" + this.getTotalWidth() + ";"
			})
		},
		processEvent : function (name, e) {
			var target = e.getTarget();
			var grid = this.grid;
			var header = this.findHeaderIndex(target);
			var row;
			var cell;
			var col;
			var body;
			grid.fireEvent(name, e);
			if (header !== false)
				grid.fireEvent("header" +
					name, grid, header, e);
			else {
				row = this.findRowIndex(target);
				if (row !== false) {
					cell = this.findCellIndex(target);
					if (cell !== false) {
						col = grid.colModel.getColumnAt(cell);
						if (grid.fireEvent("cell" + name, grid, row, cell, e) !== false)
							if (!col || col.processEvent && col.processEvent(name, e, grid, row, cell) !== false)
								grid.fireEvent("row" + name, grid, row, e)
					} else if (grid.fireEvent("row" + name, grid, row, e) !== false)
						(body = this.findRowBody(target)) && grid.fireEvent("rowbody" + name, grid, row, e)
				} else
					grid.fireEvent("container" + name, grid, e)
			}
		},
		layout : function (initial) {
			if (!this.mainBody)
				return;
			var grid = this.grid;
			var gridEl = grid.getGridEl();
			var gridSize = gridEl.getSize(true);
			var gridWidth = gridSize.width;
			var gridHeight = gridSize.height;
			var scroller = this.scroller;
			var scrollStyle;
			var headerHeight;
			var scrollHeight;
			if (gridWidth < 20 || gridHeight < 20)
				return;
			if (grid.autoHeight) {
				scrollStyle = scroller.dom.style;
				scrollStyle.overflow = "visible";
				if (Ext.isWebKit)
					scrollStyle.position = "static"
			} else {
				this.el.setSize(gridWidth, gridHeight);
				headerHeight = this.mainHd.getHeight();
				scrollHeight = gridHeight - headerHeight;
				scroller.setSize(gridWidth, scrollHeight);
				if (this.innerHd)
					this.innerHd.style.width = gridWidth + "px"
			}
			if (this.forceFit || initial === true && this.autoFill) {
				if (this.lastViewWidth != gridWidth) {
					this.fitColumns(false, false);
					this.lastViewWidth = gridWidth
				}
			} else {
				this.autoExpand();
				this.syncHeaderScroll()
			}
			this.onLayout(gridWidth, scrollHeight)
		},
		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)
		},
		getOffsetWidth : function () {
			return this.cm.getTotalWidth() + this.getScrollOffset() + "px"
		},
		getScrollOffset : function () {
			return Ext.num(this.scrollOffset, Ext.getScrollBarWidth())
		},
		renderHeaders : function () {
			var colModel = this.cm;
			var templates = this.templates;
			var headerTpl = templates.hcell;
			var properties = {};
			var colCount = colModel.getColumnCount();
			var last = colCount - 1;
			var cells = [];
			var i;
			var cssCls;
			for (i = 0; i < colCount; i++) {
				if (i == 0)
					cssCls = "x-grid3-cell-first ";
				else
					cssCls = i == last ? "x-grid3-cell-last " : "";
				properties = {
					id : colModel.getColumnId(i),
					value : colModel.getColumnHeader(i) || "",
					style : this.getColumnStyle(i, true),
					css : cssCls,
					tooltip : this.getColumnTooltip(i)
				};
				if (colModel.config[i].align == "right")
					properties.istyle = "padding-right: 16px;";
				else
					delete properties.istyle;
				cells[i] = headerTpl.apply(properties)
			}
			return templates.header.apply({
				cells : cells.join(""),
				tstyle : String.format("width: {0};", this.getTotalWidth())
			})
		},
		getColumnTooltip : function (i) {
			var tooltip = this.cm.getColumnTooltip(i);
			if (tooltip)
				if (Ext.QuickTips.isEnabled())
					return 'ext:qtip\x3d"' + tooltip + '"';
				else
					return 'title\x3d"' + tooltip + '"';
			return ""
		},
		beforeUpdate : function () {
			this.grid.stopEditing(true)
		},
		updateHeaders : function () {
			this.innerHd.firstChild.innerHTML = this.renderHeaders();
			this.updateHeaderWidth(false)
		},
		updateHeaderWidth : function (updateMain) {
			var innerHdChild = this.innerHd.firstChild;
			var totalWidth =
				this.getTotalWidth();
			innerHdChild.style.width = this.getOffsetWidth();
			innerHdChild.firstChild.style.width = totalWidth;
			if (updateMain !== false)
				this.mainBody.dom.style.width = totalWidth
		},
		focusRow : function (row) {
			this.focusCell(row, 0, false)
		},
		focusCell : function (row, col, hscroll) {
			this.syncFocusEl(this.ensureVisible(row, col, hscroll));
			var focusEl = this.focusEl;
			if (Ext.isGecko)
				focusEl.focus();
			else
				focusEl.focus.defer(1, focusEl)
		},
		resolveCell : function (row, col, hscroll) {
			if (!Ext.isNumber(row))
				row = row.rowIndex;
			if (!this.ds)
				return null;
			if (row < 0 || row >= this.ds.getCount())
				return null;
			col = col !== undefined ? col : 0;
			var rowEl = this.getRow(row);
			var colModel = this.cm;
			var colCount = colModel.getColumnCount();
			var cellEl;
			if (!(hscroll === false && col === 0)) {
				for (; col < colCount && colModel.isHidden(col); )
					col++;
				cellEl = this.getCell(row, col)
			}
			return {
				row : rowEl,
				cell : cellEl
			}
		},
		getResolvedXY : function (resolved) {
			if (!resolved)
				return null;
			var cell = resolved.cell;
			var row = resolved.row;
			if (cell)
				return Ext.fly(cell).getXY();
			else
				return [this.el.getX(), Ext.fly(row).getY()]
		},
		syncFocusEl : function (row,
			col, hscroll) {
			var xy = row;
			if (!Ext.isArray(xy)) {
				row = Math.min(row, Math.max(0, this.getRows().length - 1));
				if (isNaN(row))
					return;
				xy = this.getResolvedXY(this.resolveCell(row, col, hscroll))
			}
			this.focusEl.setXY(xy || this.scroller.getXY())
		},
		ensureVisible : function (row, col, hscroll) {
			var resolved = this.resolveCell(row, col, hscroll);
			if (!resolved || !resolved.row)
				return null;
			var rowEl = resolved.row;
			var cellEl = resolved.cell;
			var c = this.scroller.dom;
			var p = rowEl;
			var ctop = 0;
			for (var stop = this.el.dom; p && p != stop; ) {
				ctop += p.offsetTop;
				p = p.offsetParent
			}
			ctop -= this.mainHd.dom.offsetHeight;
			stop = parseInt(c.scrollTop, 10);
			var cbot = ctop + rowEl.offsetHeight;
			var ch = c.clientHeight;
			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 this.getResolvedXY(resolved)
		},
		insertRows : function (dm, firstRow, lastRow, isUpdate) {
			var last = dm.getCount() - 1;
			if (!isUpdate && firstRow === 0 && lastRow >= last) {
				this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
				this.refresh();
				this.fireEvent("rowsinserted", this, firstRow, lastRow)
			} else {
				if (!isUpdate)
					this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
				var html = this.renderRows(firstRow, lastRow);
				var before = this.getRow(firstRow);
				if (before) {
					if (firstRow === 0)
						Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
					Ext.DomHelper.insertHtml("beforeBegin",
						before, html)
				} else {
					var r = this.getRow(last - 1);
					if (r)
						Ext.fly(r).removeClass(this.lastRowCls);
					Ext.DomHelper.insertHtml("beforeEnd", this.mainBody.dom, html)
				}
				if (!isUpdate) {
					this.processRows(firstRow);
					this.fireEvent("rowsinserted", this, firstRow, lastRow)
				} else if (firstRow === 0 || firstRow >= last)
					Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls)
			}
			this.syncFocusEl(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 (colIndex, isHeader) {
			var colModel = this.cm;
			var colConfig = colModel.config;
			var style = isHeader ? "" : colConfig[colIndex].css || "";
			var align = colConfig[colIndex].align;
			style += String.format("width: {0};", this.getColumnWidth(colIndex));
			if (colModel.isHidden(colIndex))
				style += "display: none; ";
			if (align)
				style += String.format("text-align: {0};", align);
			return style
		},
		getColumnWidth : function (column) {
			var columnWidth = this.cm.getColumnWidth(column);
			var borderWidth = this.borderWidth;
			if (Ext.isNumber(columnWidth))
				if (Ext.isBorderBox || Ext.isWebKit && !Ext.isSafari2)
					return columnWidth + "px";
				else
					return Math.max(columnWidth - borderWidth, 0) + "px";
			else
				return columnWidth
		},
		getTotalWidth : function () {
			return this.cm.getTotalWidth() + "px"
		},
		fitColumns : function (preventRefresh, onlyExpand, omitColumn) {
			var grid = this.grid;
			var colModel = this.cm;
			var totalColWidth = colModel.getTotalWidth(false);
			var gridWidth =
				this.getGridInnerWidth();
			var extraWidth = gridWidth - totalColWidth;
			var columns = [];
			var extraCol = 0;
			var width = 0;
			var colWidth;
			var fraction;
			var i;
			if (gridWidth < 20 || extraWidth === 0)
				return false;
			var visibleColCount = colModel.getColumnCount(true);
			var totalColCount = colModel.getColumnCount(false);
			var adjCount = visibleColCount - (Ext.isNumber(omitColumn) ? 1 : 0);
			if (adjCount === 0) {
				adjCount = 1;
				omitColumn = undefined
			}
			for (i = 0; i < totalColCount; i++)
				if (!colModel.isFixed(i) && i !== omitColumn) {
					colWidth = colModel.getColumnWidth(i);
					columns.push(i,
						colWidth);
					if (!colModel.isHidden(i)) {
						extraCol = i;
						width += colWidth
					}
				}
			for (fraction = (gridWidth - colModel.getTotalWidth()) / width; columns.length; ) {
				colWidth = columns.pop();
				i = columns.pop();
				colModel.setColumnWidth(i, Math.max(grid.minColumnWidth, Math.floor(colWidth + colWidth * fraction)), true)
			}
			totalColWidth = colModel.getTotalWidth(false);
			if (totalColWidth > gridWidth) {
				var adjustCol = adjCount == visibleColCount ? extraCol : omitColumn;
				var newWidth = Math.max(1, colModel.getColumnWidth(adjustCol) - (totalColWidth - gridWidth));
				colModel.setColumnWidth(adjustCol,
					newWidth, true)
			}
			if (preventRefresh !== true)
				this.updateAllColumnWidths();
			return true
		},
		autoExpand : function (preventUpdate) {
			var grid = this.grid;
			var colModel = this.cm;
			var gridWidth = this.getGridInnerWidth();
			var totalColumnWidth = colModel.getTotalWidth(false);
			var autoExpandColumn = grid.autoExpandColumn;
			if (!this.userResized && autoExpandColumn)
				if (gridWidth != totalColumnWidth) {
					var colIndex = colModel.getIndexById(autoExpandColumn);
					var currentWidth = colModel.getColumnWidth(colIndex);
					var desiredWidth = gridWidth - totalColumnWidth +
						currentWidth;
					var newWidth = Math.min(Math.max(desiredWidth, grid.autoExpandMin), grid.autoExpandMax);
					if (currentWidth != newWidth) {
						colModel.setColumnWidth(colIndex, newWidth, true);
						if (preventUpdate !== true)
							this.updateColumnWidth(colIndex, newWidth)
					}
				}
		},
		getGridInnerWidth : function () {
			return this.grid.getGridEl().getWidth(true) - this.getScrollOffset()
		},
		getColumnData : function () {
			var columns = [];
			var colModel = this.cm;
			var colCount = colModel.getColumnCount();
			var fields = this.ds.fields;
			var i;
			var name;
			for (i = 0; i < colCount; i++) {
				name =
					colModel.getDataIndex(i);
				columns[i] = {
					name : Ext.isDefined(name) ? name : fields.get(i) ? fields.get(i).name : undefined,
					renderer : colModel.getRenderer(i),
					scope : colModel.getRendererScope(i),
					id : colModel.getColumnId(i),
					style : this.getColumnStyle(i)
				}
			}
			return columns
		},
		renderRows : function (startRow, endRow) {
			var grid = this.grid;
			var store = grid.store;
			var stripe = grid.stripeRows;
			var colModel = grid.colModel;
			var colCount = colModel.getColumnCount();
			var rowCount = store.getCount();
			var records;
			if (rowCount < 1)
				return "";
			startRow = startRow ||
				0;
			endRow = Ext.isDefined(endRow) ? endRow : rowCount - 1;
			records = store.getRange(startRow, endRow);
			return this.doRender(this.getColumnData(), records, store, startRow, colCount, stripe)
		},
		renderBody : function () {
			var markup = this.renderRows() || "\x26#160;";
			return this.templates.body.apply({
				rows : markup
			})
		},
		refreshRow : function (record) {
			var store = this.ds;
			var colCount = this.cm.getColumnCount();
			var columns = this.getColumnData();
			var last = colCount - 1;
			var cls = ["x-grid3-row"];
			var rowParams = {
				tstyle : String.format("width: {0};", this.getTotalWidth())
			};
			var colBuffer = [];
			var cellTpl = this.templates.cell;
			var rowIndex;
			var row;
			var column;
			var meta;
			var css;
			var i;
			if (Ext.isNumber(record)) {
				rowIndex = record;
				record = store.getAt(rowIndex)
			} else
				rowIndex = store.indexOf(record);
			if (!record || rowIndex < 0)
				return;
			for (i = 0; i < colCount; i++) {
				column = columns[i];
				if (i == 0)
					css = "x-grid3-cell-first";
				else
					css = i == last ? "x-grid3-cell-last " : "";
				meta = {
					id : column.id,
					style : column.style,
					css : css,
					attr : "",
					cellAttr : ""
				};
				meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record,
						rowIndex, i, store);
				if (Ext.isEmpty(meta.value))
					meta.value = "\x26#160;";
				if (this.markDirty && record.dirty && typeof record.modified[column.name] != "undefined")
					meta.css += " x-grid3-dirty-cell";
				colBuffer[i] = cellTpl.apply(meta)
			}
			row = this.getRow(rowIndex);
			row.className = "";
			if (this.grid.stripeRows && (rowIndex + 1) % 2 === 0)
				cls.push("x-grid3-row-alt");
			if (this.getRowClass) {
				rowParams.cols = colCount;
				cls.push(this.getRowClass(record, rowIndex, rowParams, store))
			}
			this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
			rowParams.cells =
				colBuffer.join("");
			row.innerHTML = this.templates.rowInner.apply(rowParams);
			this.fireEvent("rowupdated", this, rowIndex, record)
		},
		refresh : function (headersToo) {
			this.fireEvent("beforerefresh", this);
			this.grid.stopEditing(true);
			var result = this.renderBody();
			this.mainBody.update(result).setWidth(this.getTotalWidth());
			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('\x3cdiv class\x3d"x-grid-empty"\x3e' + this.emptyText + "\x3c/div\x3e")
		},
		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)
			}
		},
		clearHeaderSortState : function () {
			if (!this.sortState)
				return;
			this.grid.fireEvent("sortchange", this.grid, null);
			this.mainHd.select("td").removeClass(this.sortClasses);
			delete this.sortState
		},
		destroy : function () {
			var me = this;
			var grid = me.grid;
			var gridEl = grid.getGridEl();
			var dragZone = me.dragZone;
			var splitZone = me.splitZone;
			var columnDrag = me.columnDrag;
			var columnDrop = me.columnDrop;
			var scrollToTopTask = me.scrollToTopTask;
			var columnDragData;
			var columnDragProxy;
			if (scrollToTopTask && scrollToTopTask.cancel)
				scrollToTopTask.cancel();
			Ext.destroyMembers(me, "colMenu", "hmenu");
			me.initData(null,
				null);
			me.purgeListeners();
			Ext.fly(me.innerHd).un("click", me.handleHdDown, me);
			if (grid.enableColumnMove) {
				columnDragData = columnDrag.dragData;
				columnDragProxy = columnDrag.proxy;
				Ext.destroy(columnDrag.el, columnDragProxy.ghost, columnDragProxy.el, columnDrop.el, columnDrop.proxyTop, columnDrop.proxyBottom, columnDragData.ddel, columnDragData.header);
				if (columnDragProxy.anim)
					Ext.destroy(columnDragProxy.anim);
				delete columnDragProxy.ghost;
				delete columnDragData.ddel;
				delete columnDragData.header;
				columnDrag.destroy();
				delete Ext.dd.DDM.locationCache[columnDrag.id];
				delete columnDrag._domRef;
				delete columnDrop.proxyTop;
				delete columnDrop.proxyBottom;
				columnDrop.destroy();
				delete Ext.dd.DDM.locationCache["gridHeader" + gridEl.id];
				delete columnDrop._domRef;
				delete Ext.dd.DDM.ids[columnDrop.ddGroup]
			}
			if (splitZone) {
				splitZone.destroy();
				delete splitZone._domRef;
				delete Ext.dd.DDM.ids["gridSplitters" + gridEl.id]
			}
			Ext.fly(me.innerHd).removeAllListeners();
			Ext.removeNode(me.innerHd);
			delete me.innerHd;
			Ext.destroy(me.el, me.mainWrap, me.mainHd,
				me.scroller, me.mainBody, me.focusEl, me.resizeMarker, me.resizeProxy, me.activeHdBtn, me._flyweight, dragZone, splitZone);
			delete grid.container;
			if (dragZone)
				dragZone.destroy();
			Ext.dd.DDM.currentTarget = null;
			delete Ext.dd.DDM.locationCache[gridEl.id];
			Ext.EventManager.removeResizeListener(me.onWindowResize, me)
		},
		onDenyColumnHide : function () {},
		render : function () {
			if (this.autoFill) {
				var ct = this.grid.ownerCt;
				if (ct && ct.getLayout())
					ct.on("afterlayout", function () {
						this.fitColumns(true, true);
						this.updateHeaders();
						this.updateHeaderSortState()
					},
						this, {
						single : true
					})
			} else if (this.forceFit)
				this.fitColumns(true, false);
			else if (this.grid.autoExpandColumn)
				this.autoExpand(true);
			this.grid.getGridEl().dom.innerHTML = this.renderUI();
			this.afterRenderUI()
		},
		initData : function (newStore, newColModel) {
			var me = this;
			if (me.ds) {
				var oldStore = me.ds;
				oldStore.un("add", me.onAdd, me);
				oldStore.un("load", me.onLoad, me);
				oldStore.un("clear", me.onClear, me);
				oldStore.un("remove", me.onRemove, me);
				oldStore.un("update", me.onUpdate, me);
				oldStore.un("datachanged", me.onDataChange, me);
				if (oldStore !== newStore && oldStore.autoDestroy)
					oldStore.destroy()
			}
			if (newStore)
				newStore.on({
					scope : me,
					load : me.onLoad,
					add : me.onAdd,
					remove : me.onRemove,
					update : me.onUpdate,
					clear : me.onClear,
					datachanged : me.onDataChange
				});
			if (me.cm) {
				var oldColModel = me.cm;
				oldColModel.un("configchange", me.onColConfigChange, me);
				oldColModel.un("widthchange", me.onColWidthChange, me);
				oldColModel.un("headerchange", me.onHeaderChange, me);
				oldColModel.un("hiddenchange", me.onHiddenChange, me);
				oldColModel.un("columnmoved", me.onColumnMove, me)
			}
			if (newColModel) {
				delete me.lastViewWidth;
				newColModel.on({
					scope : me,
					configchange : me.onColConfigChange,
					widthchange : me.onColWidthChange,
					headerchange : me.onHeaderChange,
					hiddenchange : me.onHiddenChange,
					columnmoved : me.onColumnMove
				})
			}
			me.ds = newStore;
			me.cm = newColModel
		},
		onDataChange : function () {
			this.refresh(true);
			this.updateHeaderSortState();
			this.syncFocusEl(0)
		},
		onClear : function () {
			this.refresh();
			this.syncFocusEl(0)
		},
		onUpdate : function (store, record) {
			this.refreshRow(record)
		},
		onAdd : function (store, records, index) {
			this.insertRows(store, index, index + (records.length -
					1))
		},
		onRemove : function (store, 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 () {
			if (Ext.isGecko) {
				if (!this.scrollToTopTask)
					this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
				this.scrollToTopTask.delay(1)
			} else
				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;
			this.refresh(true);
			this.restoreScroll(this.getScrollState());
			this.afterMove(newIndex);
			this.grid.fireEvent("columnmove", oldIndex, newIndex)
		},
		onColConfigChange : function () {
			delete this.lastViewWidth;
			this.indexMap = null;
			this.refresh(true)
		},
		initUI : function (grid) {
			grid.on("headerclick", this.onHeaderClick,
				this)
		},
		initEvents : Ext.emptyFn,
		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, target) {
			var row = this.findRowIndex(target);
			if (row !== false)
				this.addRowClass(row, this.rowOverCls)
		},
		onRowOut : function (e, target) {
			var row = this.findRowIndex(target);
			if (row !== false && !e.within(this.getRow(row), true))
				this.removeRowClass(row, this.rowOverCls)
		},
		onRowSelect : function (row) {
			this.addRowClass(row,
				this.selectedRowClass)
		},
		onRowDeselect : function (row) {
			this.removeRowClass(row, this.selectedRowClass)
		},
		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")
		},
		handleWheel : function (e) {
			e.stopPropagation()
		},
		onColumnSplitterMoved : function (cellIndex, width) {
			this.userResized = true;
			this.grid.colModel.setColumnWidth(cellIndex,
				width, true);
			if (this.forceFit) {
				this.fitColumns(true, false, cellIndex);
				this.updateAllColumnWidths()
			} else {
				this.updateColumnWidth(cellIndex, width);
				this.syncHeaderScroll()
			}
			this.grid.fireEvent("columnresize", cellIndex, width)
		},
		beforeColMenuShow : function () {
			var colModel = this.cm;
			var colCount = colModel.getColumnCount();
			var colMenu = this.colMenu;
			var i;
			colMenu.removeAll();
			for (i = 0; i < colCount; i++)
				if (colModel.config[i].hideable !== false)
					colMenu.add(new Ext.menu.CheckItem({
							text : colModel.getColumnHeader(i),
							itemId : "col-" +
							colModel.getColumnId(i),
							checked : !colModel.isHidden(i),
							disabled : colModel.config[i].hideable === false,
							hideOnClick : false
						}))
		},
		handleHdMenuClick : function (item) {
			var store = this.ds;
			var dataIndex = this.cm.getDataIndex(this.hdCtxIndex);
			switch (item.getItemId()) {
			case "asc":
				store.sort(dataIndex, "ASC");
				break;
			case "desc":
				store.sort(dataIndex, "DESC");
				break;
			default:
				this.handleHdMenuClickDefault(item)
			}
			return true
		},
		handleHdMenuClickDefault : function (item) {
			var colModel = this.cm;
			var itemId = item.getItemId();
			var index = colModel.getIndexById(itemId.substr(4));
			if (index != -1) {
				if (item.checked && colModel.getColumnsBy(this.isHideableColumn, this).length <= 1) {
					this.onDenyColumnHide();
					return
				}
				colModel.setHidden(index, item.checked)
			}
		},
		handleHdDown : function (e, target) {
			if (Ext.fly(target).hasClass("x-grid3-hd-btn")) {
				e.stopEvent();
				var colModel = this.cm;
				var header = this.findHeaderCell(target);
				var index = this.getCellIndex(header);
				var sortable = colModel.isSortable(index);
				var menu = this.hmenu;
				var menuItems = menu.items;
				var menuCls = this.headerMenuOpenCls;
				this.hdCtxIndex = index;
				Ext.fly(header).addClass(menuCls);
				menuItems.get("asc").setDisabled(!sortable);
				menuItems.get("desc").setDisabled(!sortable);
				menu.on("hide", function () {
					Ext.fly(header).removeClass(menuCls)
				}, this, {
					single : true
				});
				menu.show(target, "tl-bl?")
			}
		},
		handleHdMove : function (e) {
			var header = this.findHeaderCell(this.activeHdRef);
			if (header && !this.headersDisabled) {
				var handleWidth = this.splitHandleWidth || 5;
				var activeRegion = this.activeHdRegion;
				var headerStyle = header.style;
				var colModel = this.cm;
				var cursor = "";
				var pageX = e.getPageX();
				if (this.grid.enableColumnResize !==
					false) {
					var activeHeaderIndex = this.activeHdIndex;
					var previousVisible = this.getPreviousVisible(activeHeaderIndex);
					var currentResizable = colModel.isResizable(activeHeaderIndex);
					var previousResizable = previousVisible && colModel.isResizable(previousVisible);
					var inLeftResizer = pageX - activeRegion.left <= handleWidth;
					var inRightResizer = activeRegion.right - pageX <= (!this.activeHdBtn ? handleWidth : 2);
					if (inLeftResizer && previousResizable)
						cursor = Ext.isAir ? "move" : Ext.isWebKit ? "e-resize" : "col-resize";
					else if (inRightResizer &&
						currentResizable)
						cursor = Ext.isAir ? "move" : Ext.isWebKit ? "w-resize" : "col-resize"
				}
				headerStyle.cursor = cursor
			}
		},
		getPreviousVisible : function (index) {
			for (; index > 0; ) {
				if (!this.cm.isHidden(index - 1))
					return index;
				index--
			}
			return undefined
		},
		handleHdOver : function (e, target) {
			var header = this.findHeaderCell(target);
			if (header && !this.headersDisabled) {
				var fly = this.fly(header);
				this.activeHdRef = target;
				this.activeHdIndex = this.getCellIndex(header);
				this.activeHdRegion = fly.getRegion();
				if (!this.isMenuDisabled(this.activeHdIndex,
						fly)) {
					fly.addClass("x-grid3-hd-over");
					this.activeHdBtn = fly.child(".x-grid3-hd-btn");
					if (this.activeHdBtn)
						this.activeHdBtn.dom.style.height = header.firstChild.offsetHeight - 1 + "px"
				}
			}
		},
		handleHdOut : function (e, target) {
			var header = this.findHeaderCell(target);
			if (header && (!Ext.isIE || !e.within(header, true))) {
				this.activeHdRef = null;
				this.fly(header).removeClass("x-grid3-hd-over");
				header.style.cursor = ""
			}
		},
		isMenuDisabled : function (cellIndex, el) {
			return this.cm.isMenuDisabled(cellIndex)
		},
		hasRows : function () {
			var fc = this.mainBody.dom.firstChild;
			return fc && fc.nodeType == 1 && fc.className != "x-grid-empty"
		},
		isHideableColumn : function (c) {
			return !c.hidden
		},
		bind : function (d, c) {
			this.initData(d, c)
		}
	});
Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
		constructor : 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
		},
		b4StartDrag : function (x, y) {
			this.dragHeadersDisabled = this.view.headersDisabled;
			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, 1E3);
			this.setYConstraint(0, 0);
			this.minX = x - minw;
			this.maxX = x + 1E3;
			this.startPos = x;
			Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y)
		},
		allowHeaderDrag : function (e) {
			return true
		},
		handleMouseDown : function (e) {
			var t = this.view.findHeaderCell(e.getTarget());
			if (t && this.allowHeaderDrag(e)) {
				var xy = this.view.fly(t).getXY();
				var x = xy[0];
				var exy = e.getXY();
				var ex = exy[0];
				var w = t.offsetWidth;
				var 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;
						for (; 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;
			var disabled = this.dragHeadersDisabled;
			v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex) + diff);
			setTimeout(function () {
				v.headersDisabled =
					disabled
			}, 50)
		},
		autoOffset : function () {
			this.setDelta(0, 0)
		}
	});
Ext.grid.PivotGridView = Ext.extend(Ext.grid.GridView, {
		colHeaderCellCls : "grid-hd-group-cell",
		title : "",
		getColumnHeaders : function () {
			return this.grid.topAxis.buildHeaders()
		},
		getRowHeaders : function () {
			return this.grid.leftAxis.buildHeaders()
		},
		renderRows : function (startRow, endRow) {
			var grid = this.grid;
			var rows = grid.extractData();
			var rowCount = rows.length;
			var templates = this.templates;
			var renderer = grid.renderer;
			var hasRenderer = typeof renderer == "function";
			var getCellCls = this.getCellCls;
			var hasGetCellCls = typeof getCellCls ==
				"function";
			var cellTemplate = templates.cell;
			var rowTemplate = templates.row;
			var rowBuffer = [];
			var meta = {};
			var tstyle = "width:" + this.getGridInnerWidth() + "px;";
			var colBuffer;
			var colCount;
			var column;
			var i;
			var row;
			startRow = startRow || 0;
			endRow = Ext.isDefined(endRow) ? endRow : rowCount - 1;
			for (i = 0; i < rowCount; i++) {
				row = rows[i];
				colCount = row.length;
				colBuffer = [];
				for (var j = 0; j < colCount; j++) {
					meta.id = i + "-" + j;
					meta.css = j === 0 ? "x-grid3-cell-first " : j == colCount - 1 ? "x-grid3-cell-last " : "";
					meta.attr = meta.cellAttr = "";
					meta.value = row[j];
					if (Ext.isEmpty(meta.value))
						meta.value = "\x26#160;";
					if (hasRenderer)
						meta.value = renderer(meta.value);
					if (hasGetCellCls)
						meta.css += getCellCls(meta.value) + " ";
					colBuffer[colBuffer.length] = cellTemplate.apply(meta)
				}
				rowBuffer[rowBuffer.length] = rowTemplate.apply({
						tstyle : tstyle,
						cols : colCount,
						cells : colBuffer.join(""),
						alt : ""
					})
			}
			return rowBuffer.join("")
		},
		masterTpl : new Ext.Template('\x3cdiv class\x3d"x-grid3 x-pivotgrid" hidefocus\x3d"true"\x3e', '\x3cdiv class\x3d"x-grid3-viewport"\x3e', '\x3cdiv class\x3d"x-grid3-header"\x3e',
			'\x3cdiv class\x3d"x-grid3-header-title"\x3e\x3cspan\x3e{title}\x3c/span\x3e\x3c/div\x3e', '\x3cdiv class\x3d"x-grid3-header-inner"\x3e', '\x3cdiv class\x3d"x-grid3-header-offset" style\x3d"{ostyle}"\x3e\x3c/div\x3e', "\x3c/div\x3e", '\x3cdiv class\x3d"x-clear"\x3e\x3c/div\x3e', "\x3c/div\x3e", '\x3cdiv class\x3d"x-grid3-scroller"\x3e', '\x3cdiv class\x3d"x-grid3-row-headers"\x3e\x3c/div\x3e', '\x3cdiv class\x3d"x-grid3-body" style\x3d"{bstyle}"\x3e{body}\x3c/div\x3e', '\x3ca href\x3d"#" class\x3d"x-grid3-focus" tabIndex\x3d"-1"\x3e\x3c/a\x3e',
			"\x3c/div\x3e", "\x3c/div\x3e", '\x3cdiv class\x3d"x-grid3-resize-marker"\x3e\x26#160;\x3c/div\x3e', '\x3cdiv class\x3d"x-grid3-resize-proxy"\x3e\x26#160;\x3c/div\x3e', "\x3c/div\x3e"),
		initTemplates : function () {
			Ext.grid.PivotGridView.superclass.initTemplates.apply(this, arguments);
			var templates = this.templates || {};
			if (!templates.gcell)
				templates.gcell = new Ext.XTemplate('\x3ctd class\x3d"x-grid3-hd x-grid3-gcell x-grid3-td-{id} ux-grid-hd-group-row-{row} ' + this.colHeaderCellCls + '" style\x3d"{style}"\x3e', '\x3cdiv {tooltip} class\x3d"x-grid3-hd-inner x-grid3-hd-{id}" unselectable\x3d"on" style\x3d"{istyle}"\x3e',
						this.grid.enableHdMenu ? '\x3ca class\x3d"x-grid3-hd-btn" href\x3d"#"\x3e\x3c/a\x3e' : "", "{value}", "\x3c/div\x3e", "\x3c/td\x3e");
			this.templates = templates;
			this.hrowRe = new RegExp("ux-grid-hd-group-row-(\\d+)", "")
		},
		initElements : function () {
			Ext.grid.PivotGridView.superclass.initElements.apply(this, arguments);
			this.rowHeadersEl = new Ext.Element(this.scroller.child("div.x-grid3-row-headers"));
			this.headerTitleEl = new Ext.Element(this.mainHd.child("div.x-grid3-header-title"))
		},
		getGridInnerWidth : function () {
			var previousWidth =
				Ext.grid.PivotGridView.superclass.getGridInnerWidth.apply(this, arguments);
			return previousWidth - this.getTotalRowHeaderWidth()
		},
		getTotalRowHeaderWidth : function () {
			var headers = this.getRowHeaders();
			var length = headers.length;
			var total = 0;
			var i;
			for (i = 0; i < length; i++)
				total += headers[i].width;
			return total
		},
		getTotalColumnHeaderHeight : function () {
			return this.getColumnHeaders().length * 21
		},
		getCellIndex : function (el) {
			if (el) {
				var match = el.className.match(this.colRe);
				var data;
				if (match && (data = match[1]))
					return parseInt(data.split("-")[1],
						10)
			}
			return false
		},
		renderUI : function () {
			var templates = this.templates;
			var innerWidth = this.getGridInnerWidth();
			return templates.master.apply({
				body : templates.body.apply({
					rows : "\x26#160;"
				}),
				ostyle : "width:" + innerWidth + "px",
				bstyle : "width:" + innerWidth + "px"
			})
		},
		onLayout : function (width, height) {
			Ext.grid.PivotGridView.superclass.onLayout.apply(this, arguments);
			width = this.getGridInnerWidth();
			this.resizeColumnHeaders(width);
			this.resizeAllRows(width)
		},
		refresh : function (headersToo) {
			this.fireEvent("beforerefresh", this);
			this.grid.stopEditing(true);
			var result = this.renderBody();
			this.mainBody.update(result).setWidth(this.getGridInnerWidth());
			if (headersToo === true) {
				this.updateHeaders();
				this.updateHeaderSortState()
			}
			this.processRows(0, true);
			this.layout();
			this.applyEmptyText();
			this.fireEvent("refresh", this)
		},
		renderHeaders : Ext.emptyFn,
		fitColumns : Ext.emptyFn,
		resizeColumnHeaders : function (width) {
			var topAxis = this.grid.topAxis;
			if (topAxis.rendered)
				topAxis.el.setWidth(width)
		},
		resizeRowHeaders : function () {
			var rowHeaderWidth = this.getTotalRowHeaderWidth();
			var marginStyle = String.format("margin-left: {0}px;", rowHeaderWidth);
			this.rowHeadersEl.setWidth(rowHeaderWidth);
			this.mainBody.applyStyles(marginStyle);
			Ext.fly(this.innerHd).applyStyles(marginStyle);
			this.headerTitleEl.setWidth(rowHeaderWidth);
			this.headerTitleEl.setHeight(this.getTotalColumnHeaderHeight())
		},
		resizeAllRows : function (width) {
			var rows = this.getRows();
			var length = rows.length;
			var i;
			for (i = 0; i < length; i++) {
				Ext.fly(rows[i]).setWidth(width);
				Ext.fly(rows[i]).child("table").setWidth(width)
			}
		},
		updateHeaders : function () {
			this.renderGroupRowHeaders();
			this.renderGroupColumnHeaders()
		},
		renderGroupRowHeaders : function () {
			var leftAxis = this.grid.leftAxis;
			this.resizeRowHeaders();
			leftAxis.rendered = false;
			leftAxis.render(this.rowHeadersEl);
			this.setTitle(this.title)
		},
		setTitle : function (title) {
			this.headerTitleEl.child("span").dom.innerHTML = title
		},
		renderGroupColumnHeaders : function () {
			var topAxis = this.grid.topAxis;
			topAxis.rendered = false;
			topAxis.render(this.innerHd.firstChild)
		},
		isMenuDisabled : function (cellIndex, el) {
			return true
		}
	});
Ext.grid.PivotAxis = Ext.extend(Ext.Component, {
		orientation : "horizontal",
		defaultHeaderWidth : 80,
		paddingWidth : 7,
		setDimensions : function (dimensions) {
			this.dimensions = dimensions
		},
		onRender : function (ct, position) {
			var rows = this.orientation == "horizontal" ? this.renderHorizontalRows() : this.renderVerticalRows();
			this.el = Ext.DomHelper.overwrite(ct.dom, {
					tag : "table",
					cn : rows
				}, true)
		},
		renderHorizontalRows : function () {
			var headers = this.buildHeaders();
			var rowCount = headers.length;
			var rows = [];
			var cells;
			var cols;
			var colCount;
			var i;
			var j;
			for (i = 0; i < rowCount; i++) {
				cells = [];
				cols = headers[i].items;
				colCount = cols.length;
				for (j = 0; j < colCount; j++)
					cells.push({
						tag : "td",
						html : cols[j].header,
						colspan : cols[j].span
					});
				rows[i] = {
					tag : "tr",
					cn : cells
				}
			}
			return rows
		},
		renderVerticalRows : function () {
			var headers = this.buildHeaders();
			var colCount = headers.length;
			var rowCells = [];
			var rows = [];
			var rowCount;
			var col;
			var row;
			var colWidth;
			var i;
			var j;
			for (i = 0; i < colCount; i++) {
				col = headers[i];
				colWidth = col.width || 80;
				rowCount = col.items.length;
				for (j = 0; j < rowCount; j++) {
					row = col.items[j];
					rowCells[row.start] = rowCells[row.start] || [];
					rowCells[row.start].push({
						tag : "td",
						html : row.header,
						rowspan : row.span,
						width : Ext.isBorderBox ? colWidth : colWidth - this.paddingWidth
					})
				}
			}
			rowCount = rowCells.length;
			for (i = 0; i < rowCount; i++)
				rows[i] = {
					tag : "tr",
					cn : rowCells[i]
				};
			return rows
		},
		getTuples : function () {
			var newStore = new Ext.data.Store({});
			newStore.data = this.store.data.clone();
			newStore.fields = this.store.fields;
			var sorters = [];
			var dimensions = this.dimensions;
			var length = dimensions.length;
			var i;
			for (i = 0; i < length; i++)
				sorters.push({
					field : dimensions[i].dataIndex,
					direction : dimensions[i].direction || "ASC"
				});
			newStore.sort(sorters);
			var records = newStore.data.items;
			var hashes = [];
			var tuples = [];
			var recData;
			var hash;
			var info;
			var data;
			var key;
			length = records.length;
			for (i = 0; i < length; i++) {
				info = this.getRecordInfo(records[i]);
				data = info.data;
				hash = "";
				for (key in data)
					hash += data[key] + "---";
				if (hashes.indexOf(hash) == -1) {
					hashes.push(hash);
					tuples.push(info)
				}
			}
			newStore.destroy();
			return tuples
		},
		getRecordInfo : function (record$$0) {
			var dimensions = this.dimensions;
			var length = dimensions.length;
			var data$$0 = {};
			var dimension;
			var dataIndex$$0;
			var i;
			for (i = 0; i < length; i++) {
				dimension = dimensions[i];
				dataIndex$$0 = dimension.dataIndex;
				data$$0[dataIndex$$0] = record$$0.get(dataIndex$$0)
			}
			var createMatcherFunction = function (data) {
				return function (record) {
					for (var dataIndex in data)
						if (record.get(dataIndex) != data[dataIndex])
							return false;
					return true
				}
			};
			return {
				data : data$$0,
				matcher : createMatcherFunction(data$$0)
			}
		},
		buildHeaders : function () {
			var tuples = this.getTuples();
			var rowCount = tuples.length;
			var dimensions = this.dimensions;
			var dimension;
			var colCount = dimensions.length;
			var headers = [];
			var tuple;
			var rows;
			var currentHeader;
			var previousHeader;
			var span;
			var start;
			var isLast;
			var changed;
			var i;
			var j;
			for (i = 0; i < colCount; i++) {
				dimension = dimensions[i];
				rows = [];
				span = 0;
				start = 0;
				for (j = 0; j < rowCount; j++) {
					tuple = tuples[j];
					isLast = j == rowCount - 1;
					currentHeader = tuple.data[dimension.dataIndex];
					changed = previousHeader != undefined && previousHeader != currentHeader;
					if (i > 0 && j > 0)
						changed = changed || tuple.data[dimensions[i - 1].dataIndex] != tuples[j - 1].data[dimensions[i -
									1].dataIndex];
					if (changed) {
						rows.push({
							header : previousHeader,
							span : span,
							start : start
						});
						start += span;
						span = 0
					}
					if (isLast) {
						rows.push({
							header : currentHeader,
							span : span + 1,
							start : start
						});
						start += span;
						span = 0
					}
					previousHeader = currentHeader;
					span++
				}
				headers.push({
					items : rows,
					width : dimension.width || this.defaultHeaderWidth
				});
				previousHeader = undefined
			}
			return headers
		}
	});
Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
		maxDragWidth : 120,
		constructor : 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
		},
		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.dragHeadersDisabled =
				this.view.headersDisabled;
			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 () {
			this.completeDrop()
		},
		afterInvalidDrop : function () {
			this.completeDrop()
		},
		completeDrop : function () {
			var v = this.view;
			var disabled = this.dragHeadersDisabled;
			setTimeout(function () {
				v.headersDisabled = disabled
			}, 50)
		}
	});
Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
		proxyOffsets : [-4, -9],
		fly : Ext.Element.fly,
		constructor : function (grid, hd, hd2) {
			this.grid = grid;
			this.view = grid.getView();
			this.proxyTop = Ext.DomHelper.append(document.body, {
					cls : "col-move-top",
					html : "\x26#160;"
				}, true);
			this.proxyBottom = Ext.DomHelper.append(document.body, {
					cls : "col-move-bottom",
					html : "\x26#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)
		},
		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;
			var cm = this.grid.colModel;
			for (h = h.nextSibling; h; ) {
				if (!cm.isHidden(v.getCellIndex(h)))
					return h;
				h = h.nextSibling
			}
			return null
		},
		prevVisible : function (h) {
			var v = this.view;
			var cm = this.grid.colModel;
			for (h = h.prevSibling; 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;
			var pt;
			var 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"
			}
			if (this.grid.colModel.isFixed(this.view.getCellIndex(n)))
				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);
				if (pt == "after")
					newIndex++;
				if (oldIndex < newIndex)
					newIndex--;
				cm.moveColumn(oldIndex, newIndex);
				return true
			}
			return false
		}
	});
Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
		constructor : function (grid, hd) {
			Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
			this.proxy.el.addClass("x-grid3-col-dd")
		},
		handleMouseDown : function (e) {},
		callHandleMouseDown : function (e) {
			Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e)
		}
	});
Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
		fly : Ext.Element.fly,
		constructor : 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
		},
		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, 1E3);
			this.setYConstraint(0, 0);
			this.minX = x - minw;
			this.maxX = x + 1E3;
			this.startPos = x;
			Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y)
		},
		handleMouseDown : function (e) {
			var 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);
	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 = Ext.extend(Ext.util.Observable, {
		defaultWidth : 100,
		defaultSortable : false,
		constructor : function (config) {
			if (config.columns) {
				Ext.apply(this, config);
				this.setConfig(config.columns, true)
			} else
				this.setConfig(config, true);
			this.addEvents("widthchange", "headerchange", "hiddenchange", "columnmoved", "configchange");
			Ext.grid.ColumnModel.superclass.constructor.call(this)
		},
		getColumnId : function (index) {
			return this.config[index].id
		},
		getColumnAt : function (index) {
			return this.config[index]
		},
		setConfig : function (config,
			initial) {
			var i;
			var c;
			var len;
			if (!initial) {
				delete this.totalWidth;
				for (i = 0, len = this.config.length; i < len; i++) {
					c = this.config[i];
					if (c.setEditor)
						c.setEditor(null)
				}
			}
			this.defaults = Ext.apply({
					width : this.defaultWidth,
					sortable : this.defaultSortable
				}, this.defaults);
			this.config = config;
			this.lookup = {};
			for (i = 0, len = config.length; i < len; i++) {
				c = Ext.applyIf(config[i], this.defaults);
				if (Ext.isEmpty(c.id))
					c.id = i;
				if (!c.isColumn) {
					var Cls = Ext.grid.Column.types[c.xtype || "gridcolumn"];
					c = new Cls(c);
					config[i] = c
				}
				this.lookup[c.id] =
					c
			}
			if (!initial)
				this.fireEvent("configchange", this)
		},
		getColumnById : function (id) {
			return this.lookup[id]
		},
		getIndexById : function (id) {
			var i = 0;
			for (var len = this.config.length; i < len; i++)
				if (this.config[i].id == id)
					return i;
			return -1
		},
		moveColumn : function (oldIndex, newIndex) {
			var config = this.config;
			var c = config[oldIndex];
			config.splice(oldIndex, 1);
			config.splice(newIndex, 0, c);
			this.dataMap = null;
			this.fireEvent("columnmoved", this, oldIndex, newIndex)
		},
		getColumnCount : function (visibleOnly) {
			var length = this.config.length;
			var c =
				0;
			var i;
			if (visibleOnly === true) {
				for (i = 0; i < length; i++)
					if (!this.isHidden(i))
						c++;
				return c
			}
			return length
		},
		getColumnsBy : function (fn, scope) {
			var config = this.config;
			var length = config.length;
			var result = [];
			var i;
			var c;
			for (i = 0; i < length; i++) {
				c = config[i];
				if (fn.call(scope || this, c, i) === true)
					result[result.length] = c
			}
			return result
		},
		isSortable : function (col) {
			return !!this.config[col].sortable
		},
		isMenuDisabled : function (col) {
			return !!this.config[col].menuDisabled
		},
		getRenderer : function (col) {
			return this.config[col].renderer ||
			Ext.grid.ColumnModel.defaultRenderer
		},
		getRendererScope : function (col) {
			return this.config[col].scope
		},
		setRenderer : function (col, fn) {
			this.config[col].renderer = fn
		},
		getColumnWidth : function (col) {
			var width = this.config[col].width;
			if (typeof width != "number")
				width = this.defaultWidth;
			return width
		},
		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;
				var i = 0;
				for (var 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;
			var i = 0;
			for (var len = c.length; i < len; i++)
				if (c[i].dataIndex == dataIndex)
					return i;
			return -1
		},
		isCellEditable : function (colIndex, rowIndex) {
			var c = this.config[colIndex];
			var ed = c.editable;
			return !!(ed || !Ext.isDefined(ed) && c.editor)
		},
		getCellEditor : function (colIndex, rowIndex) {
			return this.config[colIndex].getCellEditor(rowIndex)
		},
		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].setEditor(editor)
		},
		destroy : function () {
			var length = this.config.length;
			for (var i = 0; i < length; i++)
				this.config[i].destroy();
			delete this.config;
			delete this.lookup;
			this.purgeListeners()
		},
		setState : function (col, state) {
			state = Ext.applyIf(state, this.defaults);
			Ext.apply(this.config[col], state)
		}
	});
Ext.grid.ColumnModel.defaultRenderer = function (value) {
	if (typeof value == "string" && value.length < 1)
		return "\x26#160;";
	return value
};
Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable, {
		constructor : function () {
			this.locked = false;
			Ext.grid.AbstractSelectionModel.superclass.constructor.call(this)
		},
		init : function (grid) {
			this.grid = grid;
			if (this.lockOnInit) {
				delete this.lockOnInit;
				this.locked = false;
				this.lock()
			}
			this.initEvents()
		},
		lock : function () {
			if (!this.locked) {
				this.locked = true;
				var g = this.grid;
				if (g)
					g.getView().on({
						scope : this,
						beforerefresh : this.sortUnLock,
						refresh : this.sortLock
					});
				else
					this.lockOnInit = true
			}
		},
		sortLock : function () {
			this.locked =
				true
		},
		sortUnLock : function () {
			this.locked = false
		},
		unlock : function () {
			if (this.locked) {
				this.locked = false;
				var g = this.grid;
				var gv;
				if (g) {
					gv = g.getView();
					gv.un("beforerefresh", this.sortUnLock, this);
					gv.un("refresh", this.sortLock, this)
				} else
					delete this.lockOnInit
			}
		},
		isLocked : function () {
			return this.locked
		},
		destroy : function () {
			this.unlock();
			this.purgeListeners()
		}
	});
Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, {
		singleSelect : false,
		constructor : 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)
		},
		initEvents : function () {
			if (!this.grid.enableDragDrop && !this.grid.enableDrag)
				this.grid.on("rowmousedown", this.handleMouseDown,
					this);
			this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
					up : this.onKeyPress,
					down : this.onKeyPress,
					scope : this
				});
			this.grid.getView().on({
				scope : this,
				refresh : this.onRefresh,
				rowupdated : this.onRowUpdated,
				rowremoved : this.onRemove
			})
		},
		onKeyPress : function (e, name) {
			var up = name == "up";
			var method = up ? "selectPrevious" : "selectNext";
			var add = up ? -1 : 1;
			var last;
			if (!e.shiftKey || this.singleSelect)
				this[method](false);
			else if (this.last !== false && this.lastActive !== false) {
				last = this.last;
				this.selectRange(this.last, this.lastActive +
					add);
				this.grid.getView().focusRow(this.lastActive);
				if (last !== false)
					this.last = last
			} else
				this.selectFirstRow()
		},
		onRefresh : function () {
			var ds = this.grid.store;
			var s = this.getSelections();
			var i = 0;
			var len = s.length;
			var index;
			var r;
			this.silent = true;
			for (this.clearSelections(true); i < len; i++) {
				r = s[i];
				if ((index = ds.indexOfId(r.id)) != -1)
					this.selectRow(index, true)
			}
			if (s.length != this.selections.getCount())
				this.fireEvent("selectionchange", this);
			this.silent = false
		},
		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;
			var i = 0;
			for (var 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();
			var i = 0;
			for (var len = s.length; i < len; i++)
				if (fn.call(scope || this, s[i], i) === false)
					return false;
			return true
		},
		clearSelections : function (fast) {
			if (this.isLocked())
				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.isLocked())
				return;
			this.selections.clear();
			var i = 0;
			for (var len = this.grid.store.getCount(); i < len; i++)
				this.selectRow(i, true)
		},
		hasSelection : function () {
			return this.selections.length > 0
		},
		isSelected : function (index) {
			var r = Ext.isNumber(index) ? 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.singleSelect && 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();
			var i = 0;
			for (var len = rows.length; i < len; i++)
				this.selectRow(rows[i], true)
		},
		selectRange : function (startRow, endRow, keepExisting) {
			var i;
			if (this.isLocked())
				return;
			if (!keepExisting)
				this.clearSelections();
			if (startRow <= endRow)
				for (i = startRow; i <= endRow; i++)
					this.selectRow(i, true);
			else
				for (i = startRow; i >= endRow; i--)
					this.selectRow(i, true)
		},
		deselectRange : function (startRow, endRow, preventViewNotify) {
			if (this.isLocked())
				return;
			for (var i = startRow; i <= endRow; i++)
				this.deselectRow(i, preventViewNotify)
		},
		selectRow : function (index, keepExisting, preventViewNotify) {
			if (this.isLocked() || index < 0 || index >= this.grid.store.getCount() || keepExisting && 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);
				if (!this.silent) {
					this.fireEvent("rowselect", this, index, r);
					this.fireEvent("selectionchange", this)
				}
			}
		},
		deselectRow : function (index, preventViewNotify) {
			if (this.isLocked())
				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)
			}
		},
		acceptsNav : function (row, col, cm) {
			return !cm.isHidden(col) && cm.isCellEditable(col, row)
		},
		onEditorKey : function (field, e) {
			var k = e.getKey();
			var newCell;
			var g = this.grid;
			var last = g.lastEdit;
			var ed = g.activeEditor;
			var shift = e.shiftKey;
			var ae;
			var r;
			var c;
			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)
				if (this.moveEditorOnEnter !== false)
					if (shift)
						newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
					else
						newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
			if (newCell) {
				r = newCell[0];
				c = newCell[1];
				this.onEditorSelect(r, last.row);
				if (g.isEditor && g.editing) {
					ae = g.activeEditor;
					if (ae && ae.field.triggerBlur)
						ae.field.triggerBlur()
				}
				g.startEditing(r,
					c)
			}
		},
		onEditorSelect : function (row, lastRow) {
			if (lastRow != row)
				this.selectRow(row)
		},
		destroy : function () {
			Ext.destroy(this.rowNav);
			this.rowNav = null;
			Ext.grid.RowSelectionModel.superclass.destroy.call(this)
		}
	});
Ext.grid.Column = Ext.extend(Ext.util.Observable, {
		isColumn : true,
		constructor : function (config) {
			Ext.apply(this, config);
			if (Ext.isString(this.renderer))
				this.renderer = Ext.util.Format[this.renderer];
			else if (Ext.isObject(this.renderer)) {
				this.scope = this.renderer.scope;
				this.renderer = this.renderer.fn
			}
			if (!this.scope)
				this.scope = this;
			var ed = this.editor;
			delete this.editor;
			this.setEditor(ed);
			this.addEvents("click", "contextmenu", "dblclick", "mousedown");
			Ext.grid.Column.superclass.constructor.call(this)
		},
		processEvent : function (name,
			e, grid, rowIndex, colIndex) {
			return this.fireEvent(name, this, grid, rowIndex, e)
		},
		destroy : function () {
			if (this.setEditor)
				this.setEditor(null);
			this.purgeListeners()
		},
		renderer : function (value) {
			return value
		},
		getEditor : function (rowIndex) {
			return this.editable !== false ? this.editor : null
		},
		setEditor : function (editor) {
			var ed = this.editor;
			if (ed)
				if (ed.gridEditor) {
					ed.gridEditor.destroy();
					delete ed.gridEditor
				} else
					ed.destroy();
			this.editor = null;
			if (editor) {
				if (!editor.isXType)
					editor = Ext.create(editor, "textfield");
				this.editor =
					editor
			}
		},
		getCellEditor : function (rowIndex) {
			var ed = this.getEditor(rowIndex);
			if (ed)
				if (!ed.startEdit) {
					if (!ed.gridEditor)
						ed.gridEditor = new Ext.grid.GridEditor(ed);
					ed = ed.gridEditor
				}
			return ed
		}
	});
Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
		trueText : "true",
		falseText : "false",
		undefinedText : "\x26#160;",
		constructor : function (cfg) {
			Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
			var t = this.trueText;
			var f = this.falseText;
			var u = this.undefinedText;
			this.renderer = function (v) {
				if (v === undefined)
					return u;
				if (!v || v === "false")
					return f;
				return t
			}
		}
	});
Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
		format : "0,000.00",
		constructor : function (cfg) {
			Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
			this.renderer = Ext.util.Format.numberRenderer(this.format)
		}
	});
Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
		format : "m/d/Y",
		constructor : function (cfg) {
			Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
			this.renderer = Ext.util.Format.dateRenderer(this.format)
		}
	});
Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
		constructor : function (cfg) {
			Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
			var tpl = !Ext.isPrimitive(this.tpl) && this.tpl.compile ? this.tpl : new Ext.XTemplate(this.tpl);
			this.renderer = function (value, p, r) {
				return tpl.apply(r.data)
			};
			this.tpl = tpl
		}
	});
Ext.grid.ActionColumn = Ext.extend(Ext.grid.Column, {
		header : "\x26#160;",
		actionIdRe : /x-action-col-(\d+)/,
		altText : "",
		constructor : function (cfg) {
			var me = this;
			var items = cfg.items || (me.items = [me]);
			var l = items.length;
			var i;
			var item;
			Ext.grid.ActionColumn.superclass.constructor.call(me, cfg);
			me.renderer = function (v, meta) {
				v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments) || "" : "";
				meta.css += " x-action-col-cell";
				for (i = 0; i < l; i++) {
					item = items[i];
					v += '\x3cimg alt\x3d"' + (item.altText || me.altText) + '" src\x3d"' +
					(item.icon || Ext.BLANK_IMAGE_URL) + '" class\x3d"x-action-col-icon x-action-col-' + String(i) + " " + (item.iconCls || "") + " " + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope || this.scope || this, arguments) : "") + '"' + (item.tooltip ? ' ext:qtip\x3d"' + item.tooltip + '"' : "") + " /\x3e"
				}
				return v
			}
		},
		destroy : function () {
			delete this.items;
			delete this.renderer;
			return Ext.grid.ActionColumn.superclass.destroy.apply(this, arguments)
		},
		processEvent : function (name, e, grid, rowIndex, colIndex) {
			var m = e.getTarget().className.match(this.actionIdRe);
			var item;
			var fn;
			if (m && (item = this.items[parseInt(m[1], 10)]))
				if (name == "click")
					(fn = item.handler || this.handler) && fn.call(item.scope || this.scope || this, grid, rowIndex, colIndex, item, e);
				else if (name == "mousedown" && item.stopSelection !== false)
					return false;
			return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments)
		}
	});
Ext.grid.Column.types = {
	gridcolumn : Ext.grid.Column,
	booleancolumn : Ext.grid.BooleanColumn,
	numbercolumn : Ext.grid.NumberColumn,
	datecolumn : Ext.grid.DateColumn,
	templatecolumn : Ext.grid.TemplateColumn,
	actioncolumn : Ext.grid.ActionColumn
};
Ext.grid.RowNumberer = Ext.extend(Object, {
		header : "",
		width : 23,
		sortable : false,
		constructor : function (config) {
			Ext.apply(this, config);
			if (this.rowspan)
				this.renderer = this.renderer.createDelegate(this)
		},
		fixed : true,
		hideable : false,
		menuDisabled : true,
		dataIndex : "",
		id : "numberer",
		rowspan : undefined,
		renderer : function (v, p, record, rowIndex) {
			if (this.rowspan)
				p.cellAttr = 'rowspan\x3d"' + this.rowspan + '"';
			return rowIndex + 1
		}
	});
Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
		header : '\x3cdiv class\x3d"x-grid3-hd-checker"\x3e\x26#160;\x3c/div\x3e',
		width : 20,
		sortable : false,
		menuDisabled : true,
		fixed : true,
		hideable : false,
		dataIndex : "",
		id : "checker",
		isColumn : true,
		constructor : function () {
			Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
			if (this.checkOnly)
				this.handleMouseDown = Ext.emptyFn
		},
		initEvents : function () {
			Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
			this.grid.on("render",
				function () {
				Ext.fly(this.grid.getView().innerHd).on("mousedown", this.onHdMouseDown, this)
			}, this)
		},
		processEvent : function (name, e, grid, rowIndex, colIndex) {
			if (name == "mousedown") {
				this.onMouseDown(e, e.getTarget());
				return false
			} else
				return Ext.grid.Column.prototype.processEvent.apply(this, arguments)
		},
		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);
						this.grid.getView().focusRow(index)
					}
				}
			}
		},
		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 '\x3cdiv class\x3d"x-grid3-row-checker"\x3e\x26#160;\x3c/div\x3e'
		},
		onEditorSelect : function (row,
			lastRow) {
			if (lastRow != row && !this.checkOnly)
				this.selectRow(row)
		}
	});
Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel, {
		constructor : function (config) {
			Ext.apply(this, config);
			this.selection = null;
			this.addEvents("beforecellselect", "cellselect", "selectionchange");
			Ext.grid.CellSelectionModel.superclass.constructor.call(this)
		},
		initEvents : function () {
			this.grid.on("cellmousedown", this.handleMouseDown, this);
			this.grid.on(Ext.EventManager.getKeyEvent(), this.handleKeyDown, this);
			this.grid.getView().on({
				scope : this,
				refresh : this.onViewChange,
				rowupdated : this.onRowUpdated,
				beforerowremoved : this.clearSelections,
				beforerowsinserted : this.clearSelections
			});
			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)
		},
		onEditorKey : function (field, e) {
			if (e.getKey() == e.TAB)
				this.handleKeyDown(e)
		},
		handleKeyDown : function (e) {
			if (!e.isNavKeyPress())
				return;
			var k =
				e.getKey();
			var g = this.grid;
			var s = this.selection;
			var sm = this;
			var walk = function (row, col, step) {
				return g.walkCells(row, col, step, g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, sm)
			};
			var cell;
			var newCell;
			var r;
			var c;
			var ae;
			switch (k) {
			case e.ESC:
			case e.PAGE_UP:
			case e.PAGE_DOWN:
				break;
			default:
				e.stopEvent();
				break
			}
			if (!s) {
				cell = walk(0, 0, 1);
				if (cell)
					this.select(cell[0], cell[1]);
				return
			}
			cell = s.cell;
			r = cell[0];
			c = cell[1];
			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);
					return
				}
				break
			}
			if (newCell) {
				r = newCell[0];
				c = newCell[1];
				this.select(r, c);
				if (g.isEditor && g.editing) {
					ae = g.activeEditor;
					if (ae && ae.field.triggerBlur)
						ae.field.triggerBlur();
					g.startEditing(r, c)
				}
			}
		},
		acceptsNav : function (row, col, cm) {
			return !cm.isHidden(col) && cm.isCellEditable(col, row)
		}
	});
Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
		clicksToEdit : 2,
		forceValidation : false,
		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.getGridEl().on("mousewheel",
				this.stopEditing.createDelegate(this, [true]), this);
			this.on("columnresize", this.stopEditing, this, [true]);
			if (this.clicksToEdit == 1)
				this.on("cellclick", this.onCellDblClick, this);
			else {
				var view = this.getView();
				if (this.clicksToEdit == "auto" && view.mainBody)
					view.mainBody.on("mousedown", this.onAutoEditClick, this);
				this.on("celldblclick", this.onCellDblClick, this)
			}
		},
		onResize : function () {
			Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
			var ae = this.activeEditor;
			if (this.editing && ae)
				ae.realign(true)
		},
		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[0] === row && sc[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.lastActiveEditor =
				this.activeEditor;
			this.activeEditor = null;
			var r = ed.record;
			var field = this.colModel.getDataIndex(ed.col);
			value = this.postEditValue(value, startValue, r, field);
			if (this.forceValidation === true || 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 && String(value) !== String(startValue)) {
					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$$0 = this.colModel.getDataIndex(col);
				var e$$0 = {
					grid : this,
					record : r,
					field : field$$0,
					value : r.data[field$$0],
					row : row,
					column : col,
					cancel : false
				};
				if (this.fireEvent("beforeedit", e$$0) !== false && !e$$0.cancel) {
					this.editing = true;
					var ed = this.colModel.getCellEditor(col, row);
					if (!ed)
						return;
					if (!ed.rendered) {
						ed.parentEl = this.view.getEditorParent(ed);
						ed.on({
							scope : this,
							render : {
								fn : function (c) {
									c.field.focus(false, true)
								},
								single : true,
								scope : this
							},
							specialkey : function (field, e) {
								this.getSelectionModel().onEditorKey(field, e)
							},
							complete : this.onEditComplete,
							canceledit : this.stopEditing.createDelegate(this, [true])
						})
					}
					Ext.apply(ed, {
						row : row,
						col : col,
						record : r
					});
					this.lastEdit = {
						row : row,
						col : col
					};
					this.activeEditor = ed;
					ed.selectSameEditor = this.activeEditor == this.lastActiveEditor;
					var v = this.preEditValue(r, field$$0);
					ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ?
						v : "");
					(function () {
						delete ed.selectSameEditor
					}).defer(50)
				}
			}
		},
		preEditValue : function (r, field) {
			var value = r.data[field];
			return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value
		},
		postEditValue : function (value, originalValue, r, field) {
			return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value
		},
		stopEditing : function (cancel) {
			if (this.editing) {
				var ae = this.lastActiveEditor = this.activeEditor;
				if (ae) {
					ae[cancel === true ? "cancelEdit" : "completeEdit"]();
					this.view.focusCell(ae.row,
						ae.col)
				}
				this.activeEditor = null
			}
			this.editing = false
		}
	});
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 = Ext.extend(Ext.util.Observable, {
		constructor : 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)
		},
		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) {
			return Ext.isPrimitive(val) || Ext.isDate(val)
		},
		setValue : function (prop,
			value, create) {
			var r = this.getRec(prop);
			if (r) {
				r.set("value", value);
				this.source[prop] = value
			} else if (create) {
				this.source[prop] = value;
				r = new Ext.grid.PropertyRecord({
						name : prop,
						value : value
					}, prop);
				this.store.add(r)
			}
		},
		remove : function (prop) {
			var r = this.getRec(prop);
			if (r) {
				this.store.remove(r);
				delete this.source[prop]
			}
		},
		getRec : function (prop) {
			return this.store.getById(prop)
		},
		getSource : function () {
			return this.source
		}
	});
Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
		nameText : "Name",
		valueText : "Value",
		dateFormat : "m/j/Y",
		trueText : "true",
		falseText : "false",
		constructor : function (grid, store) {
			var g = Ext.grid;
			var f = Ext.form;
			this.grid = 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;
			var bfield = new f.Field({
					autoCreate : {
						tag : "select",
						children : [{
								tag : "option",
								value : "true",
								html : this.trueText
							}, {
								tag : "option",
								value : "false",
								html : this.falseText
							}
						]
					},
					getValue : function () {
						return this.el.dom.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, {
					autoSize : "both"
				})
			};
			this.renderCellDelegate = this.renderCell.createDelegate(this);
			this.renderPropDelegate = this.renderProp.createDelegate(this)
		},
		renderDate : function (dateVal) {
			return dateVal.dateFormat(this.dateFormat)
		},
		renderBool : function (bVal) {
			return this[bVal ? "trueText" : "falseText"]
		},
		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, meta, rec) {
			var renderer = this.grid.customRenderers[rec.get("name")];
			if (renderer)
				return renderer.apply(this,
					arguments);
			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;
			var 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
		},
		destroy : function () {
			Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
			this.destroyEditors(this.editors);
			this.destroyEditors(this.grid.customEditors)
		},
		destroyEditors : function (editors) {
			for (var ed in editors)
				Ext.destroy(editors[ed])
		}
	});
Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
		enableColumnMove : false,
		stripeRows : false,
		trackMouseOver : false,
		clicksToEdit : 1,
		enableHdMenu : false,
		viewConfig : {
			forceFit : true
		},
		initComponent : function () {
			this.customRenderers = this.customRenderers || {};
			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.mon(this.selModel, "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()
		},
		setProperty : function (prop, value, create) {
			this.propStore.setValue(prop, value, create)
		},
		removeProperty : function (prop) {
			this.propStore.remove(prop)
		}
	});
Ext.reg("propertygrid", Ext.grid.PropertyGrid);
Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
		groupByText : "Group By This Field",
		showGroupsText : "Show in Groups",
		hideGroupedColumn : false,
		showGroupName : true,
		startCollapsed : false,
		enableGrouping : true,
		enableGroupingMenu : true,
		enableNoGroups : true,
		emptyGroupText : "(None)",
		ignoreAdd : false,
		groupTextTpl : "{text}",
		groupMode : "value",
		cancelEditOnToggle : true,
		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('\x3cdiv id\x3d"{groupId}" class\x3d"x-grid-group {cls}"\x3e', '\x3cdiv id\x3d"{groupId}-hd" class\x3d"x-grid-group-hd" style\x3d"{style}"\x3e\x3cdiv class\x3d"x-grid-group-title"\x3e', this.groupTextTpl, "\x3c/div\x3e\x3c/div\x3e", '\x3cdiv id\x3d"{groupId}-bd" class\x3d"x-grid-group-body"\x3e');
			this.startGroup.compile();
			if (!this.endGroup)
				this.endGroup = "\x3c/div\x3e\x3c/div\x3e"
		},
		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 (ds, records, index) {
			if (this.canGroup() && !this.ignoreAdd) {
				var ss = this.getScrollState();
				this.fireEvent("beforerowsinserted", ds, index, index + (records.length - 1));
				this.refresh();
				this.restoreScroll(ss);
				this.fireEvent("rowsinserted", ds, index, index + (records.length - 1))
			} else if (!this.canGroup())
				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 item;
			var items = this.hmenu.items;
			var disabled = this.cm.config[this.hdCtxIndex].groupable === false;
			if (item = items.get("groupBy"))
				item.setDisabled(disabled);
			if (item = items.get("showGroups")) {
				item.setDisabled(disabled);
				item.setChecked(this.canGroup(), true)
			}
		},
		renderUI : function () {
			var markup = Ext.grid.GroupingView.superclass.renderUI.call(this);
			if (this.enableGroupingMenu && this.hmenu) {
				this.hmenu.add("-", {
					itemId : "groupBy",
					text : this.groupByText,
					handler : this.onGroupByClick,
					scope : this,
					iconCls : "x-group-by-icon"
				});
				if (this.enableNoGroups)
					this.hmenu.add({
						itemId : "showGroups",
						text : this.showGroupsText,
						checked : true,
						checkHandler : this.onShowGroupsClick,
						scope : this
					});
				this.hmenu.on("beforeshow",
					this.beforeMenuShow, this)
			}
			return markup
		},
		processEvent : function (name, e) {
			Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
			var hd = e.getTarget(".x-grid-group-hd", this.mainBody);
			if (hd) {
				var field = this.getGroupField();
				var prefix = this.getPrefix(field);
				var groupValue = hd.id.substring(prefix.length);
				var emptyRe = new RegExp("gp-" + Ext.escapeRe(field) + "--hd");
				groupValue = groupValue.substr(0, groupValue.length - 3);
				if (groupValue || emptyRe.test(hd.id))
					this.grid.fireEvent("group" + name, this.grid, field, groupValue,
						e);
				if (name == "mousedown" && e.button == 0)
					this.toggleGroup(hd.parentNode)
			}
		},
		onGroupByClick : function () {
			var grid = this.grid;
			this.enableGrouping = true;
			grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
			grid.fireEvent("groupchange", grid, grid.store.getGroupState());
			this.beforeMenuShow();
			this.refresh()
		},
		onShowGroupsClick : function (mi, checked) {
			this.enableGrouping = checked;
			if (checked)
				this.onGroupByClick();
			else {
				this.grid.store.clearGrouping();
				this.grid.fireEvent("groupchange", this, null)
			}
		},
		toggleRowIndex : function (rowIndex,
			expanded) {
			if (!this.canGroup())
				return;
			var row = this.getRow(rowIndex);
			if (row)
				this.toggleGroup(this.findGroup(row), expanded)
		},
		toggleGroup : function (group, expanded) {
			var gel = Ext.get(group);
			var id = Ext.util.Format.htmlEncode(gel.id);
			expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass("x-grid-group-collapsed");
			if (this.state[id] !== expanded) {
				if (this.cancelEditOnToggle !== false)
					this.grid.stopEditing(true);
				this.state[id] = expanded;
				gel[expanded ? "removeClass" : "addClass"]("x-grid-group-collapsed")
			}
		},
		toggleAllGroups : function (expanded) {
			var groups =
				this.getGroups();
			var i = 0;
			for (var len = groups.length; i < len; i++)
				this.toggleGroup(groups[i], expanded)
		},
		expandAllGroups : function () {
			this.toggleAllGroups(true)
		},
		collapseAllGroups : function () {
			this.toggleAllGroups(false)
		},
		getGroup : function (v, r, groupRenderer, rowIndex, colIndex, ds) {
			var column = this.cm.config[colIndex];
			var g = groupRenderer ? groupRenderer.call(column.scope, v, {}, r, rowIndex, colIndex, ds) : String(v);
			if (g === "" || g === "\x26#160;")
				g = column.emptyGroupText || this.emptyGroupText;
			return g
		},
		getGroupField : function () {
			return this.grid.store.getGroupState()
		},
		afterRender : function () {
			if (!this.ds || !this.cm)
				return;
			Ext.grid.GroupingView.superclass.afterRender.call(this);
			if (this.grid.deferRowRender)
				this.updateGroupWidths()
		},
		afterRenderUI : function () {
			Ext.grid.GroupingView.superclass.afterRenderUI.call(this);
			if (this.enableGroupingMenu && this.hmenu) {
				this.hmenu.add("-", {
					itemId : "groupBy",
					text : this.groupByText,
					handler : this.onGroupByClick,
					scope : this,
					iconCls : "x-group-by-icon"
				});
				if (this.enableNoGroups)
					this.hmenu.add({
						itemId : "showGroups",
						text : this.showGroupsText,
						checked : true,
						checkHandler : this.onShowGroupsClick,
						scope : this
					});
				this.hmenu.on("beforeshow", this.beforeMenuShow, this)
			}
		},
		renderRows : function () {
			var groupField = this.getGroupField();
			var eg = !!groupField;
			if (this.hideGroupedColumn) {
				var colIndex = this.cm.findColumnIndex(groupField);
				var hasLastGroupField = Ext.isDefined(this.lastGroupField);
				if (!eg && hasLastGroupField) {
					this.mainBody.update("");
					this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
					delete this.lastGroupField
				} else if (eg && !hasLastGroupField) {
					this.lastGroupField =
						groupField;
					this.cm.setHidden(colIndex, true)
				} else if (eg && hasLastGroupField && 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 "";
			if (!this.canGroup() || this.isUpdating)
				return Ext.grid.GroupingView.superclass.doRender.apply(this,
					arguments);
			var groupField = this.getGroupField();
			var colIndex = this.cm.findColumnIndex(groupField);
			var g;
			var gstyle = "width:" + this.getTotalWidth() + ";";
			var cfg = this.cm.config[colIndex];
			var groupRenderer = cfg.groupRenderer || cfg.renderer;
			var prefix = this.showGroupName ? (cfg.groupName || cfg.header) + ": " : "";
			var groups = [];
			var curGroup;
			var i;
			var len;
			var gid;
			for (i = 0, len = rs.length; i < len; i++) {
				var rowIndex = startRow + i;
				var r = rs[i];
				var gvalue = r.data[groupField];
				g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex,
						ds);
				if (!curGroup || curGroup.group != g) {
					gid = this.constructId(gvalue, groupField, colIndex);
					this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
					curGroup = {
						group : g,
						gvalue : gvalue,
						text : prefix + g,
						groupId : gid,
						startRow : rowIndex,
						rs : [r],
						cls : this.state[gid] ? "" : "x-grid-group-collapsed",
						style : gstyle
					};
					groups.push(curGroup)
				} else
					curGroup.rs.push(r);
				r._groupId = gid
			}
			var buf = [];
			for (i = 0, len = groups.length; i < len; i++) {
				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 field = this.getGroupField();
			return this.constructId(value, field, this.cm.findColumnIndex(field))
		},
		constructId : function (value, field, idx) {
			var cfg = this.cm.config[idx];
			var groupRenderer = cfg.groupRenderer || cfg.renderer;
			var val = this.groupMode == "value" ? value : this.getGroup(value, {
					data : {}

				}, groupRenderer, 0, idx, this.ds);
			return this.getPrefix(field) + Ext.util.Format.htmlEncode(val)
		},
		canGroup : function () {
			return this.enableGrouping &&
			!!this.getGroupField()
		},
		getPrefix : function (field) {
			return this.grid.getGridEl().id + "-gp-" + field + "-"
		},
		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.canGroup())
				return Ext.grid.GroupingView.superclass.getRows.call(this);
			var r = [];
			var gs = this.getGroups();
			var g;
			var i = 0;
			var len = gs.length;
			var j;
			for (var jlen; i < len; ++i) {
				g = gs[i].childNodes[1];
				if (g) {
					g = g.childNodes;
					for (j =
							0, jlen = g.length; j < jlen; ++j)
						r[r.length] = g[j]
				}
			}
			return r
		},
		updateGroupWidths : function () {
			if (!this.canGroup() || !this.hasRows())
				return;
			var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth - this.getScrollOffset()) + "px";
			var gs = this.getGroups();
			var i = 0;
			for (var len = gs.length; i < len; i++)
				gs[i].firstChild.style.width = tw
		},
		onColumnWidthUpdated : function (col, w, tw) {
			Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
			this.updateGroupWidths()
		},
		onAllColumnWidthsUpdated : function (ws, tw) {
			Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this,
				ws, tw);
			this.updateGroupWidths()
		},
		onColumnHiddenUpdated : function (col, hidden, tw) {
			Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
			this.updateGroupWidths()
		},
		onLayout : function () {
			this.updateGroupWidths()
		},
		onBeforeRowSelect : function (sm, rowIndex) {
			this.toggleRowIndex(rowIndex, true)
		}
	});
Ext.grid.GroupingView.GROUP_ID = 1E3;
Ext.ns("Ext.ux.grid");
Ext.ux.grid.CheckColumn = Ext.extend(Ext.grid.Column, {
		processEvent : function (name, e, grid, rowIndex, colIndex) {
			if (name == "mousedown") {
				var record = grid.store.getAt(rowIndex);
				record.set(this.dataIndex, !record.data[this.dataIndex]);
				return false
			} else
				return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments)
		},
		renderer : function (v, p, record) {
			p.css += " x-grid3-check-col-td";
			return String.format('\x3cdiv class\x3d"x-grid3-check-col{0}"\x3e\x26#160;\x3c/div\x3e', v ? "-on" : "")
		},
		init : Ext.emptyFn
	});
Ext.preg("checkcolumn", Ext.ux.grid.CheckColumn);
Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn;
Ext.grid.Column.types.checkcolumn = Ext.ux.grid.CheckColumn;
Ext.ns("Ext.ux.form");
Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField, {
		buttonText : "Browse...",
		buttonOnly : false,
		buttonOffset : 3,
		readOnly : true,
		autoSize : Ext.emptyFn,
		initComponent : function () {
			Ext.ux.form.FileUploadField.superclass.initComponent.call(this);
			this.addEvents("fileselected")
		},
		onRender : function (ct, position) {
			Ext.ux.form.FileUploadField.superclass.onRender.call(this, ct, position);
			this.wrap = this.el.wrap({
					cls : "x-form-field-wrap x-form-file-wrap"
				});
			this.el.addClass("x-form-file-text");
			this.el.dom.removeAttribute("name");
			this.createFileInput();
			var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
					text : this.buttonText
				});
			this.button = new Ext.Button(Ext.apply(btnCfg, {
						renderTo : this.wrap,
						cls : "x-form-file-btn" + (btnCfg.iconCls ? " x-btn-icon" : "")
					}));
			if (this.buttonOnly) {
				this.el.hide();
				this.wrap.setWidth(this.button.getEl().getWidth())
			}
			this.bindListeners();
			this.resizeEl = this.positionEl = this.wrap
		},
		bindListeners : function () {
			this.fileInput.on({
				scope : this,
				mouseenter : function () {
					this.button.addClass(["x-btn-over", "x-btn-focus"])
				},
				mouseleave : function () {
					this.button.removeClass(["x-btn-over",
							"x-btn-focus", "x-btn-click"])
				},
				mousedown : function () {
					this.button.addClass("x-btn-click")
				},
				mouseup : function () {
					this.button.removeClass(["x-btn-over", "x-btn-focus", "x-btn-click"])
				},
				change : function () {
					var v = this.fileInput.dom.value;
					this.setValue(v);
					this.fireEvent("fileselected", this, v)
				}
			})
		},
		createFileInput : function () {
			this.fileInput = this.wrap.createChild({
					id : this.getFileInputId(),
					name : this.name || this.getId(),
					cls : "x-form-file",
					tag : "input",
					type : "file",
					size : 1
				})
		},
		reset : function () {
			if (this.rendered) {
				this.fileInput.remove();
				this.createFileInput();
				this.bindListeners()
			}
			Ext.ux.form.FileUploadField.superclass.reset.call(this)
		},
		getFileInputId : function () {
			return this.id + "-file"
		},
		onResize : function (w, h) {
			Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h);
			this.wrap.setWidth(w);
			if (!this.buttonOnly) {
				w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
				this.el.setWidth(w)
			}
		},
		onDestroy : function () {
			Ext.ux.form.FileUploadField.superclass.onDestroy.call(this);
			Ext.destroy(this.fileInput, this.button, this.wrap)
		},
		onDisable : function () {
			Ext.ux.form.FileUploadField.superclass.onDisable.call(this);
			this.doDisable(true)
		},
		onEnable : function () {
			Ext.ux.form.FileUploadField.superclass.onEnable.call(this);
			this.doDisable(false)
		},
		doDisable : function (disabled) {
			this.fileInput.dom.disabled = disabled;
			this.button.setDisabled(disabled)
		},
		preFocus : Ext.emptyFn,
		alignErrorIcon : function () {
			this.errorIcon.alignTo(this.wrap, "tl-tr", [2, 0])
		}
	});
Ext.reg("fileuploadfield", Ext.ux.form.FileUploadField);
Ext.form.FileUploadField = Ext.ux.form.FileUploadField;
var debug = typeof console !== "undefined" && typeof console.debug !== "undefined";
Ext.Ajax.defaultHeaders = {
	"X-SCM-Client" : "WUI"
};
var state = null;
var admin = false;
var dummyPassword = "__dummypassword__";
var loginCallbacks = [];
var logoutCallbacks = [];
var initCallbacks = [];
var restUrl = "api/rest/";
var userSearchStore = new Ext.data.JsonStore({
		root : "results",
		idProperty : "value",
		fields : ["value", "label"],
		proxy : new Ext.data.HttpProxy({
			url : restUrl + "search/users.json",
			method : "GET"
		})
	});
var groupSearchStore = new Ext.data.JsonStore({
		root : "results",
		idProperty : "value",
		fields : ["value", "label"],
		proxy : new Ext.data.HttpProxy({
			url : restUrl + "search/groups.json",
			method : "GET"
		})
	});
Sonia = {
	idSeparator : ";",
	idNoneObject : "-",
	id : function () {
		var id = "";
		for (var i = 0; i < arguments.length; i++) {
			id += arguments[i];
			if (i + 1 < arguments.length)
				id += this.idSeparator
		}
		if (id.length() === 0)
			id = Ext.id();
		return id
	}
};
var main = null;
Ext.QuickTips.init();
Ext.ns("Sonia");
Sonia.History = {
	initialized : false,
	historyElements : [],
	recentlyAdded : [],
	recentlyChanged : [],
	add : function (token) {
		if (this.initialized)
			if (token !== Ext.History.getToken())
				if (this.isInvokeable(this.recentlyChanged, token)) {
					if (debug)
						console.debug("add history element " + token);
					this.recentlyAdded.push(token);
					Ext.History.add(token, true)
				}
	},
	createToken : function () {
		var token = "";
		for (var i = 0; i < arguments.length; i++) {
			token += arguments[i];
			if (i + 1 < arguments.length)
				token += ";"
		}
		return token
	},
	append : function (item) {
		return this.appendWithDepth(item,
			1)
	},
	appendWithDepth : function (item, depth) {
		var token = Ext.History.getToken();
		if (token) {
			var tokenSuffix = "";
			if (Ext.isArray(item))
				for (var i = 0; i < item.length; i++) {
					tokenSuffix += item[i];
					if (i + 1 < item.length)
						tokenSuffix += ";"
				}
			else
				tokenSuffix = item;
			var parts = token.split(";");
			var newToken = "";
			for (var j = 0; j < depth; j++)
				newToken += parts[j] + ";";
			newToken += tokenSuffix;
			this.add(newToken);
			token = newToken
		}
		return token
	},
	register : function (id, fn, scope) {
		if (scope)
			this.historyElements[id] = {
				"fn" : fn,
				"scope" : scope
			};
		else
			this.historyElements[id] =
				fn
	},
	isInvokeable : function (lockList, item) {
		var invokeable = true;
		var index = lockList.indexOf(item);
		if (index >= 0) {
			invokeable = false;
			lockList.splice(index)
		}
		return invokeable
	},
	onActivate : function (tab) {
		if (tab) {
			var el = this.historyElements[tab.xtype];
			if (el) {
				var token = Sonia.util.apply({
						fn : el.onActivate,
						scope : el
					}, tab);
				if (token)
					this.add(token)
			} else {
				if (debug)
					console.debug("could not find xtype " + tab.xtype + " set xtype as id");
				this.add(tab.xtype)
			}
		}
	},
	onChange : function (token) {
		if (token) {
			if (this.isInvokeable(this.recentlyAdded,
					token)) {
				var parts = token.split(";");
				var id = parts[0];
				this.recentlyChanged.push(token);
				Sonia.History.handleChange(id, parts.splice(1, parts.length - 1))
			}
		} else if (debug)
			console.debug("history token is empty")
	},
	handleChange : function (id, p) {
		var el = this.historyElements[id];
		if (el) {
			if (debug)
				console.debug("handle history event for " + id + ' with "' + p + '"');
			Sonia.util.apply({
				fn : el.onChange,
				scope : el
			}, p)
		} else if (Ext.ComponentMgr.isRegistered(id))
			try {
				main.addTabPanel(id)
			} catch (e) {
				if (debug)
					console.debug("could not handle history event: " +
						e)
			}
		else if (debug)
			console.debug("could not find xtype " + id)
	}
};
Ext.History.on("ready", function (history) {
	var token = history.getToken();
	if (token && token !== "null")
		Sonia.History.onChange(token);
	Sonia.History.initialized = true
});
Ext.History.on("change", function (token) {
	Sonia.History.onChange(token)
});
Ext.ns("Sonia.util");
Sonia.util.getServername = function (url) {
	var i = url.indexOf("://");
	if (i > 0) {
		url = url.substring(i + 3);
		i = url.indexOf(":");
		if (i <= 0)
			i = url.indexOf("/");
		if (i > 0)
			url = url.substring(0, i)
	}
	return url
};
Sonia.util.getContextPath = function () {
	var path = window.location.pathname;
	if (path.indexOf(".html") > 0) {
		var i = path.lastIndexOf("/");
		if (i > 0)
			path = path.substring(0, i)
	}
	return path
};
Sonia.util.getBaseUrl = function () {
	var url = location.href;
	var i = url.indexOf("#");
	if (i > 0)
		url = url.substring(0, i);
	i = url.indexOf("?");
	if (i > 0)
		url = url.substring(0, i);
	if (url.endsWith("/index.html"))
		url = url.substring(0, url.length - "/index.html".length);
	else if (url.endsWith("/"))
		url = url.substring(0, url.length - 1);
	return url
};
Sonia.util.getName = function (path) {
	var name = path;
	var index = path.lastIndexOf("/");
	if (index > 0)
		name = path.substr(index + 1);
	return name
};
Sonia.util.getExtension = function (path) {
	var ext = null;
	var index = path.lastIndexOf(".");
	if (index > 0)
		ext = path.substr(index + 1, path.length);
	return ext
};
Sonia.util.clone = function (obj) {
	var newObj = this instanceof Array ? [] : {};
	for (i in obj) {
		if (i === "clone")
			continue;
		if (obj[i] && typeof obj[i] === "object")
			newObj[i] = Sonia.util.clone(obj[i]);
		else
			newObj[i] = obj[i]
	}
	return newObj
};
Sonia.util.parseInt = function (string, defaultValue) {
	var result = defaultValue;
	try {
		result = parseInt(string)
	} catch (e) {
		if (debug)
			console.debug(e)
	}
	if (isNaN(result))
		result = defaultValue;
	return result
};
Sonia.util.getStringFromArray = function (array) {
	var value = "";
	if (Ext.isArray(array))
		for (var i = 0; i < array.length; i++) {
			value += array[i];
			if (i + 1 < array.length)
				value += ", "
		}
	return value
};
Sonia.util.applySub = function (obj, name, p) {
	if (name)
		obj = obj[name];
	return Sonia.util.call(obj, p)
};
Sonia.util.apply = function (obj, p) {
	var result = null;
	if (Ext.isFunction(obj))
		if (p)
			if (Ext.isArray(p))
				result = obj(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
			else
				result = obj(p);
		else
			result = obj();
	else if (p)
		if (Ext.isArray(p))
			result = obj.fn.call(obj.scope, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
		else
			result = obj.fn.call(obj.scope, p);
	else
		result = obj.fn.call(obj.scope);
	return result
};
if (!Array.prototype.filter)
	Array.prototype.filter = function (fn, scope) {
		var results = [];
		for (var i = 0; i < this.length; i++)
			if (fn.call(scope, this[i], i, this))
				results.push(this[i]);
		return results
	};
Sonia.util.getProperty = function (properties, key) {
	var value = null;
	if (properties)
		for (var i = 0; i < properties.length; i++) {
			var property = properties[i];
			if (property.key === key) {
				value = property.value;
				break
			}
		}
	return value
};
Sonia.util.Link = Ext.extend(Ext.BoxComponent, {
		handler : null,
		scope : null,
		constructor : function (config) {
			config = config || {};
			var cl = "scm-link";
			if (config["class"])
				cl += " " + config["class"];
			config.xtype = "box";
			config.autoEl = {
				tag : "a",
				html : config.text,
				style : config.style,
				"class" : cl
			};
			config.listeners = {
				render : function (c) {
					c.getEl().on("click", function () {
						if (this.handler)
							this.scope ? this.handler.call(this.scope) : this.handler()
					}, this)
				}
			};
			Sonia.util.Link.superclass.constructor.apply(this, arguments);
			this.text = config.text
		}
	});
Ext.reg("link", Sonia.util.Link);
Sonia.util.Tip = Ext.extend(Ext.BoxComponent, {
		tpl : new Ext.XTemplate('    \x3cdiv id\x3d"" class\x3d"x-tip" style\x3d"position: inherit; visibility: visible;"\x3e      \x3cdiv class\x3d"x-tip-tl"\x3e        \x3cdiv class\x3d"x-tip-tr"\x3e          \x3cdiv class\x3d"x-tip-tc"\x3e            \x3cdiv class\x3d"x-tip-header x-unselectable"\x3e              \x3cspan class\x3d"x-tip-header-text"\x3e\x3c/span\x3e            \x3c/div\x3e          \x3c/div\x3e        \x3c/div\x3e      \x3c/div\x3e      \x3cdiv class\x3d"x-tip-bwrap"\x3e        \x3cdiv class\x3d"x-tip-ml"\x3e          \x3cdiv class\x3d"x-tip-mr"\x3e            \x3cdiv class\x3d"x-tip-mc"\x3e              \x3cdiv class\x3d"x-tip-body" style\x3d"height: auto; width: auto;"\x3e                {content}              \x3c/div\x3e            \x3c/div\x3e          \x3c/div\x3e        \x3c/div\x3e        \x3cdiv class\x3d"x-tip-bl x-panel-nofooter"\x3e          \x3cdiv class\x3d"x-tip-br"\x3e            \x3cdiv class\x3d"x-tip-bc"\x3e\x3c/div\x3e          \x3c/div\x3e        \x3c/div\x3e      \x3c/div\x3e    \x3c/div\x3e'),
		constructor : function (config) {
			config =
				config || {};
			var cl = "scm-tip";
			if (config["class"])
				cl += " " + config["class"];
			config.xtype = "box";
			this.html = this.tpl.apply({
					content : config.content
				});
			Sonia.util.Tip.superclass.constructor.apply(this, arguments)
		}
	});
Ext.reg("scmTip", Sonia.util.Tip);
Ext.apply(Ext.form.VTypes, {
	password : function (val, field) {
		if (field.initialPassField) {
			var pwd = Ext.getCmp(field.initialPassField);
			return val === pwd.getValue()
		}
		return true
	},
	passwordText : "The passwords entered do not match!",
	name : function (val) {
		return val.match(/^[^ ][A-z0-9\.\-_@ ]*[^ ]$/)
	},
	nameText : "The name is invalid.",
	repositoryNameRegex : /(?!^\.\.$)(?!^\.$)(?!.*[\[\]])^[A-z0-9\.][A-z0-9\.\-_/]*$/,
	repositoryName : function (val) {
		var result = true;
		if (val) {
			var p = val.split("/");
			for (var i = 0; i < p.length; i++)
				if (!this.repositoryNameRegex.test(p[i])) {
					result =
						false;
					break
				}
		} else
			result = false;
		return result
	},
	repositoryNameText : "The name of the repository is invalid.",
	username : function (val) {
		return this.name(val)
	},
	usernameText : "The username is invalid."
});
Ext.form.Field.prototype.afterRenderExt = Ext.form.Field.prototype.afterRender;
Ext.override(Ext.form.Field, {
	afterRender : function () {
		if (this.helpText)
			this.renderHelp(this.helpText);
		this.afterRenderExt.apply(this, arguments)
	},
	renderHelp : function (text) {
		var div = this.el.up("div");
		var cls = this.getHelpButtonClass();
		var helpButton = div.createChild({
				tag : "img",
				width : 16,
				height : 16,
				src : "resources/images/help.png",
				cls : cls
			});
		var quickTip = {
			target : helpButton,
			title : "",
			text : text,
			enabled : true
		};
		if (this.helpDisableAutoHide)
			quickTip.autoHide = !this.helpDisableAutoHide;
		Ext.QuickTips.register(quickTip)
	},
	getHelpButtonClass : function () {
		var cls = null;
		switch (this.getXType()) {
		case "combo":
			if (this.readOnly)
				cls = "scm-form-help-button";
			else
				cls = "scm-form-combo-help-button";
			break;
		case "fileuploadfield":
			cls = "scm-form-fileupload-help-button";
			break;
		case "textarea":
			cls = "scm-form-textarea-help-button";
			break;
		default:
			cls = "scm-form-help-button"
		}
		return cls
	}
});
Ext.apply(Ext.util.Format, {
	formatTimestamp : function (value) {
		var result = "";
		if (value && (value > 0 || value.length > 0)) {
			var df = state.clientConfig.dateFormat;
			if (!df || df.length === 0 || !Ext.isDefined(value))
				df = "YYYY-MM-DD HH:mm:ss";
			result = moment(value).format(df)
		}
		if (result.indexOf("{0}") >= 0)
			result = String.format(result, Ext.util.Format.timeAgo(value));
		return result
	},
	timeAgo : function (value) {
		return moment(value).fromNow()
	},
	id : function (value) {
		return this.substr(value, 0, 12)
	},
	convertLineBreaks : function (value) {
		if (value)
			value =
				value.replace(/(\r\n|\n|\r)/gm, "\x3cbr /\x3e");
		return value
	}
});
Ext.override(Ext.data.Store, {
	addField : function (field) {
		field = new Ext.data.Field(field);
		this.recordType.prototype.fields.replace(field);
		if (typeof field.defaultValue !== "undefined")
			this.each(function (r) {
				if (typeof r.data[field.name] === "undefined")
					r.data[field.name] = field.defaultValue
			})
	},
	removeField : function (name) {
		this.recordType.prototype.fields.removeKey(name);
		this.each(function (r) {
			delete r.data[name];
			if (r.modified)
				delete r.modified[name]
		})
	}
});
Ext.override(Ext.grid.ColumnModel, {
	addColumn : function (column, colIndex) {
		if (typeof column === "string")
			column = {
				header : column,
				dataIndex : column
			};
		var config = this.config;
		this.config = [];
		if (typeof colIndex === "number")
			config.splice(colIndex, 0, column);
		else
			colIndex = config.push(column);
		this.setConfig(config);
		return colIndex
	},
	removeColumn : function (colIndex) {
		var config = this.config;
		this.config = [config[colIndex]];
		config.splice(colIndex, 1);
		this.setConfig(config)
	}
});
Ext.grid.GridPanel.prototype.applyStateExt = Ext.grid.GridPanel.prototype.applyState;
Ext.grid.GridPanel.prototype.getStateExt = Ext.grid.GridPanel.prototype.getState;
Ext.override(Ext.grid.GridPanel, {
	stateEvents : ["columnmove", "columnresize", "sortchange", "groupchange", "toggleGroup"],
	addColumn : function (field, column, colIndex) {
		if (!column)
			if (field.dataIndex) {
				column = field;
				field = field.dataIndex
			} else
				column = field.name || field;
		this.store.addField(field);
		return this.colModel.addColumn(column, colIndex)
	},
	removeColumn : function (name, colIndex) {
		this.store.removeField(name);
		if (typeof colIndex !== "number")
			colIndex = this.colModel.findColumnIndex(name);
		if (colIndex >= 0)
			this.colModel.removeColumn(colIndex)
	},
	applyState : function (state) {
		var view = this.getView();
		if (view && view.applyState) {
			var groups = state.groups;
			if (groups)
				view.applyState(groups)
		}
		this.applyStateExt(state)
	},
	getState : function () {
		var state = this.getStateExt();
		var view = this.getView();
		if (view && view.getState)
			state.groups = view.getState();
		return state
	}
});
Ext.grid.GroupingView.prototype.initTemplatesExt = Ext.grid.GroupingView.prototype.initTemplates;
Ext.grid.GroupingView.prototype.toggleGroupExt = Ext.grid.GroupingView.prototype.toggleGroup;
Ext.override(Ext.grid.GroupingView, {
	storedState : null,
	idPrefix : "{grid.el.id}",
	initTemplates : function () {
		this.initTemplatesExt();
		if (this.storedState)
			this.state = this.storedState
	},
	toggleGroup : function (group, expanded) {
		this.toggleGroupExt(group, expanded);
		this.grid.fireEvent("toggleGroup", group, expanded)
	},
	getState : function () {
		return this.state
	},
	applyState : function (state) {
		this.storedState = state
	},
	getPrefix : function (field) {
		var prefix;
		if (this.idPrefix === "{grid.id}")
			prefix = this.grid.getId();
		else if (this.idPrefix ===
			"{grid.el.id}")
			prefix = this.grid.getGridEl().id;
		else
			prefix = this.idPrefix;
		prefix += "-gp-" + field + "-";
		return prefix
	}
});
Ext.ns("Sonia.uistate");
Sonia.uistate.WebStorageProvider = Ext.extend(Ext.state.Provider, {
		constructor : function (config) {
			Ext.apply(this, config)
		},
		get : function (name, defaultValue) {
			var value = localStorage.getItem(name);
			if (value)
				value = this.decodeValue(value);
			else
				value = defaultValue;
			return value
		},
		set : function (name, value) {
			if (typeof value === "undefined" || value === null)
				this.clear(name);
			else
				localStorage.setItem(name, this.encodeValue(value))
		},
		clear : function (name) {
			localStorage.removeItem(name)
		}
	});
Ext.ns("Sonia.navigation");
Sonia.navigation.NavSection = Ext.extend(Ext.Panel, {
		links : null,
		tpl : new Ext.XTemplate('\x3cul class\x3d"scm-nav-list"\x3e', '\x3ctpl for\x3d"links"\x3e', '\x3cli class\x3d"scm-nav-item"\x3e', '\x3ca id\x3d"{id}" class\x3d"scm-nav-item"\x3e{label}\x3c/a\x3e', "\x3c/li\x3e", "\x3c/tpl\x3e", "\x3c/ul\x3e"),
		initComponent : function () {
			if (!this.links)
				this.links = this.items;
			if (!this.links)
				this.links = [];
			Ext.each(this.links, function (link) {
				Ext.id(link)
			});
			var config = {
				frame : true,
				collapsible : true,
				style : "margin: 5px"
			};
			Ext.apply(this,
				Ext.apply(this.initialConfig, config));
			Sonia.navigation.NavSection.superclass.initComponent.apply(this, arguments)
		},
		doAction : function (e, t) {
			e.stopEvent();
			Ext.each(this.links, function (navItem) {
				if (navItem.id === t.id && Ext.isFunction(navItem.fn)) {
					var scope = navItem.scope;
					if (Ext.isObject(scope))
						navItem.fn.call(scope);
					else
						navItem.fn()
				}
			})
		},
		afterRender : function () {
			Sonia.navigation.NavSection.superclass.afterRender.apply(this, arguments);
			this.tpl.overwrite(this.body, {
				links : this.links
			});
			this.body.on("mousedown",
				this.doAction, this, {
				delegate : "a"
			});
			this.body.on("click", Ext.emptyFn, null, {
				delegate : "a",
				preventDefault : true
			})
		},
		addLink : function (link) {
			Ext.id(link);
			this.links.push(link)
		},
		addLinks : function (links) {
			if (Ext.isArray(links) && links.length > 0)
				for (var i = 0; i < links.length; i++)
					this.addLink(links[i]);
			else
				this.addLink(links)
		},
		insertLink : function (pos, link) {
			this.links.splice(pos, 0, link)
		},
		count : function () {
			return this.links.length
		}
	});
Ext.reg("navSection", Sonia.navigation.NavSection);
Sonia.navigation.NavPanel = Ext.extend(Ext.Panel, {
		sections : null,
		initComponent : function () {
			var config = {
				listeners : {
					afterrender : {
						fn : this.renderSections,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.navigation.NavSection.superclass.initComponent.apply(this, arguments)
		},
		renderSections : function () {
			if (this.sections)
				this.addSections(this.sections)
		},
		insertSection : function (pos, section) {
			if (debug)
				console.debug("insert navsection " + section.title + " at " + pos);
			section.xtype = "navSection";
			this.insert(pos,
				section);
			this.doLayout()
		},
		addSections : function (sections) {
			if (Ext.isArray(sections) && sections.length > 0)
				for (var i = 0; i < sections.length; i++)
					this.addSection(sections[i]);
			else
				this.addSection(sections);
			this.doLayout()
		},
		addSection : function (section) {
			if (debug)
				console.debug("add navsection " + section.title);
			section.xtype = "navSection";
			this.add(section)
		},
		count : function () {
			return this.items.length
		}
	});
Ext.reg("navPanel", Sonia.navigation.NavPanel);
Ext.ns("Sonia.login");
Sonia.login.Form = Ext.extend(Ext.FormPanel, {
		usernameText : "Username",
		passwordText : "Password",
		loginText : "Login",
		cancelText : "Cancel",
		waitTitleText : "Connecting",
		WaitMsgText : "Sending data...",
		failedMsgText : "Login failed!",
		failedDescriptionText : "Incorrect username, password or not enough permission. Please Try again.",
		accountLockedText : "Account is locked.",
		accountTemporaryLockedText : "Account is temporary locked. Please try again later.",
		rememberMeText : "Remember me",
		initComponent : function () {
			var buttons = [];
			if (scmGlobalConfiguration.anonymousAccessEnabled)
				buttons.push({
					text : this.cancelText,
					scope : this,
					handler : this.cancel
				});
			buttons.push({
				id : "loginButton",
				text : this.loginText,
				formBind : true,
				scope : this,
				handler : this.authenticate
			});
			var config = {
				labelWidth : 120,
				url : restUrl + "authentication/login.json",
				frame : true,
				title : this.titleText,
				defaultType : "textfield",
				monitorValid : true,
				listeners : {
					afterrender : function () {
						Ext.getCmp("username").focus(true, 500)
					}
				},
				items : [{
						id : "username",
						fieldLabel : this.usernameText,
						name : "username",
						allowBlank : false,
						listeners : {
							specialkey : {
								fn : this.specialKeyPressed,
								scope : this
							}
						}
					}, {
						fieldLabel : this.passwordText,
						name : "password",
						inputType : "password",
						allowBlank : false,
						listeners : {
							specialkey : {
								fn : this.specialKeyPressed,
								scope : this
							}
						}
					}, {
						xtype : "checkbox",
						fieldLabel : this.rememberMeText,
						name : "rememberMe",
						inputValue : "true"
					}
				],
				buttons : buttons
			};
			this.addEvents("cancel", "failure");
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.login.Form.superclass.initComponent.apply(this, arguments)
		},
		cancel : function () {
			this.fireEvent("cancel");
			main.checkLogin()
		},
		authenticate : function () {
			var form$$0 = this.getForm();
			form$$0.submit({
				scope : this,
				method : "POST",
				waitTitle : this.waitTitleText,
				waitMsg : this.WaitMsgText,
				success : function (form, action) {
					if (debug)
						console.debug("login success");
					main.loadState(action.result)
				},
				failure : function (form, action) {
					if (debug)
						console.debug("login failed with " + action.result.failure);
					this.fireEvent("failure");
					var msg = this.failedDescriptionText;
					switch (action.result.failure) {
					case "LOCKED":
						msg = this.accountLockedText;
						break;
					case "TEMPORARY_LOCKED":
						msg = this.accountTemporaryLockedText;
						break
					}
					Ext.Msg.show({
						title : this.failedMsgText,
						msg : msg,
						buttons : Ext.Msg.OK,
						icon : Ext.MessageBox.WARNING
					});
					form.reset()
				}
			})
		},
		specialKeyPressed : function (field, e) {
			if (e.getKey() === e.ENTER) {
				var form = this.getForm();
				if (form.isValid())
					this.authenticate()
			}
		}
	});
Ext.reg("soniaLoginForm", Sonia.login.Form);
Sonia.login.Window = Ext.extend(Ext.Window, {
		titleText : "Please Login",
		initComponent : function () {
			var form = new Sonia.login.Form;
			form.on("actioncomplete", function () {
				this.fireEvent("success");
				this.close()
			}, this);
			form.on("cancel", function () {
				this.close()
			}, this);
			var config = {
				layout : "fit",
				width : 320,
				height : 150,
				closable : false,
				resizable : false,
				plain : true,
				border : false,
				modal : true,
				title : this.titleText,
				items : [form]
			};
			this.addEvents("success");
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.login.Window.superclass.initComponent.apply(this,
				arguments)
		}
	});
Ext.ns("Sonia.panel");
Sonia.panel.SyntaxHighlighterPanel = Ext.extend(Ext.Panel, {
		syntaxes : [{
				name : "ActionScript3",
				aliases : ["as", "as3", "actionscript3"],
				fileName : "shBrushAS3.js"
			}, {
				name : "AppleScript",
				aliases : ["applescript", "scpt"],
				fileName : "shBrushAppleScript.js"
			}, {
				name : "Bash/shell",
				aliases : ["sh", "bash", "shell"],
				fileName : "shBrushBash.js"
			}, {
				name : "ColdFusion",
				aliases : ["cf", "coldfusion"],
				fileName : "shBrushColdFusion.js"
			}, {
				name : "C#",
				brush : "csharp",
				aliases : ["cs", "c-sharp", "csharp"],
				fileName : "shBrushCSharp.js"
			}, {
				name : "C++",
				aliases : ["cpp",
					"c", "h", "hh", "cc"],
				fileName : "shBrushCpp.js"
			}, {
				name : "CSS",
				aliases : ["css"],
				fileName : "shBrushCss.js"
			}, {
				name : "Delphi",
				aliases : ["delphi", "pas", "pascal"],
				fileName : "shBrushDelphi.js"
			}, {
				name : "Diff",
				aliases : ["diff", "patch"],
				fileName : "shBrushDiff.js"
			}, {
				name : "Erlang",
				aliases : ["erl", "erlang"],
				fileName : "shBrushErlang.js"
			}, {
				name : "Groovy",
				aliases : ["groovy"],
				fileName : "shBrushGroovy.js"
			}, {
				name : "JavaScript",
				aliases : ["js", "jscript", "javascript"],
				fileName : "shBrushJScript.js"
			}, {
				name : "Java",
				aliases : ["java", "idl"],
				fileName : "shBrushJava.js"
			}, {
				name : "JavaFX",
				aliases : ["jfx", "javafx"],
				fileName : "shBrushJavaFX.js"
			}, {
				name : "Perl",
				aliases : ["perl", "pl"],
				fileName : "shBrushPerl.js"
			}, {
				name : "PHP",
				aliases : ["php"],
				fileName : "shBrushPhp.js"
			}, {
				name : "Plain Text",
				brush : "plain",
				aliases : ["plain", "text", "txt", "log"],
				fileName : "shBrushPlain.js"
			}, {
				name : "PowerShell",
				aliases : ["ps", "powershell"],
				fileName : "shBrushPowerShell.js"
			}, {
				name : "Python",
				aliases : ["py", "python"],
				fileName : "shBrushPython.js"
			}, {
				name : "Ruby",
				aliases : ["rails", "ror", "ruby", "rb"],
				fileName : "shBrushRuby.js"
			}, {
				name : "Sass",
				aliases : ["sass", "scss"],
				fileName : "shBrushSass.js"
			}, {
				name : "Scala",
				aliases : ["scala"],
				fileName : "shBrushScala.js"
			}, {
				name : "SQL",
				aliases : ["sql"],
				fileName : "shBrushSql.js"
			}, {
				name : "Visual Basic",
				aliases : ["vb", "vbnet"],
				fileName : "shBrushVb.js"
			}, {
				name : "XML",
				aliases : ["xml", "xhtml", "xslt", "html", "xhtml"],
				fileName : "shBrushXml.js"
			}
		],
		syntax : "plain",
		brush : "plain",
		brushUrl : "shBrushPlain.js",
		theme : "Netbeans",
		shPath : "resources/syntaxhighlighter",
		contentUrl : null,
		loadErrorTitleText : "Error",
		loadErrorMsgText : "Could not load file",
		contentLoaded : false,
		scriptsLoaded : false,
		initComponent : function () {
			if (debug)
				console.debug("try to find brush for " + this.syntax);
			if (this.syntax !== "plain") {
				var s = null;
				var found = false;
				for (var i = 0; i < this.syntaxes.length; i++) {
					s = this.syntaxes[i];
					for (var j = 0; j < s.aliases.length; j++)
						if (this.syntax === s.aliases[j]) {
							found = true;
							if (s.brush)
								this.syntax = s.brush;
							this.brushUrl = s.fileName;
							if (debug)
								console.debug("found brush " + this.syntax + " at " + this.brushUrl);
							break
						}
					if (found)
						break
				}
				if (!found) {
					if (debug)
						console.debug("could not find syntax for " +
							this.syntax);
					this.syntax = "plain"
				}
			}
			this.brush = this.syntax;
			main.loadStylesheet(this.shPath + "/styles/shCore.css");
			if (debug)
				console.debug("load theme " + this.theme);
			main.loadStylesheet(this.shPath + "/styles/shCore" + this.theme + ".css");
			var config = {
				autoScroll : true,
				listeners : {
					afterrender : {
						fn : this.loadBodyContent,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.panel.SyntaxHighlighterPanel.superclass.initComponent.apply(this, arguments)
		},
		loadBodyContent : function () {
			main.loadScript(this.shPath +
				"/scripts/shCore.js", this.loadBrush, this);
			Ext.Ajax.request({
				url : this.contentUrl,
				scope : this,
				success : function (response) {
					if (debug)
						console.debug("load content for brush: " + this.brush);
					this.update('\x3cpre class\x3d"brush: ' + this.brush + "; class-name: " + this.brush + '"\x3e' + Ext.util.Format.htmlEncode(response.responseText) + "\x3c/pre\x3e");
					this.contentLoaded = true;
					this.highlight()
				},
				failure : function (result) {
					main.handleRestFailure(result, this.loadErrorTitleText, this.loadErrorMsgText)
				}
			})
		},
		loadBrush : function () {
			main.loadScript(this.shPath +
				"/scripts/" + this.brushUrl, function () {
				this.scriptsLoaded = true;
				this.highlight()
			}, this)
		},
		highlight : function () {
			if (debug)
				console.debug("loaded, script: " + this.scriptsLoaded + ", content: " + this.contentLoaded);
			if (this.scriptsLoaded && this.contentLoaded) {
				if (debug)
					console.debug("call SyntaxHighlighter.highlight()");
				SyntaxHighlighter.highlight({}, this.body.el);
				SyntaxHighlighter.vars.discoveredBrushes = null
			}
		}
	});
Ext.reg("syntaxHighlighterPanel", Sonia.panel.SyntaxHighlighterPanel);
Ext.ns("Sonia.rest");
Sonia.rest.exceptionTitleText = "Error";
Sonia.rest.exceptionMsgText = "Could not load items. Server returned status: {0}";
Sonia.rest.ExceptionHandler = function (proxy, type, action, options, response, arg) {
	var status = response.status;
	if (debug)
		console.debug("store returned statuscode " + status);
	if (status === 200 && action === "read" && response.responseText === "null") {
		if (debug)
			console.debug("empty array, clear whole store");
		this.removeAll()
	} else {
		if (debug)
			console.debug("error during store load, status: " + status);
		main.handleRestFailure(response, Sonia.rest.exceptionTitleText, String.format(Sonia.rest.exceptionMsgText, status))
	}
};
Sonia.rest.JsonStore = Ext.extend(Ext.data.JsonStore, {
		constructor : function (config) {
			if (!config.listeners)
				config.listeners = {};
			config.listeners.exception = {
				fn : Sonia.rest.ExceptionHandler,
				scope : this
			};
			var baseConfig = {
				autoLoad : true
			};
			Sonia.rest.JsonStore.superclass.constructor.call(this, Ext.apply(baseConfig, config))
		}
	});
Sonia.rest.Panel = Ext.extend(Ext.Panel, {
		addText : "Add",
		removeText : "Remove",
		reloadText : "Reload",
		addIcon : "resources/images/add.png",
		removeIcon : "resources/images/delete.png",
		reloadIcon : "resources/images/reload.png",
		helpIcon : "resources/images/help.png",
		initComponent : function () {
			var config = {
				layout : "border",
				hideMode : "offsets",
				enableTabScroll : true,
				region : "center",
				autoScroll : true
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.rest.Panel.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("restPanel", Sonia.rest.Panel);
Sonia.rest.Grid = Ext.extend(Ext.grid.GridPanel, {
		urlTemplate : '\x3ca href\x3d"{0}" target\x3d"_blank"\x3e{0}\x3c/a\x3e',
		mailtoTemplate : '\x3ca href\x3d"mailto: {0}"\x3e{0}\x3c/a\x3e',
		checkboxTemplate : '\x3cinput type\x3d"checkbox" disabled\x3d"true" {0}/\x3e',
		emptyText : "No items available",
		minHeight : 150,
		initComponent : function () {
			var selectionModel = new Ext.grid.RowSelectionModel({
					singleSelect : true
				});
			selectionModel.on({
				selectionchange : {
					scope : this,
					fn : this.selectionChanged
				}
			});
			var config = {
				minHeight : this.minHeight,
				loadMask : true,
				sm : selectionModel,
				viewConfig : {
					deferEmptyText : false,
					emptyText : this.emptyText
				}
			};
			this.addEvents("fallBelowMinHeight");
			Ext.EventManager.onWindowResize(this.resize, this);
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.rest.Grid.superclass.initComponent.apply(this, arguments)
		},
		resize : function () {
			var h = this.getHeight();
			if (debug)
				console.debug("" + h + " \x3c " + this.minHeight + " \x3d " + (h < this.minHeight));
			if (h < this.minHeight) {
				if (debug)
					console.debug("fire event fallBelowMinHeight");
				this.fireEvent("fallBelowMinHeight",
					h, this.minHeight)
			}
		},
		onDestroy : function () {
			Ext.EventManager.removeResizeListener(this.resize, this);
			Sonia.rest.Grid.superclass.onDestroy.apply(this, arguments)
		},
		reload : function (callback, scope) {
			if (debug)
				console.debug("reload store");
			if (Ext.isFunction(callback))
				this.store.load({
					callback : callback,
					scope : scope
				});
			else {
				if (debug)
					console.debug("callback is not a function");
				this.store.load()
			}
		},
		selectionChanged : function (sm) {
			var selected = sm.getSelected();
			if (selected)
				this.selectItem(selected.data)
		},
		selectItem : function (item) {
			if (debug)
				console.debug(item)
		},
		renderUrl : function (url) {
			var result = "";
			if (url)
				result = String.format(this.urlTemplate, url);
			return result
		},
		renderMailto : function (mail) {
			var result = "";
			if (mail)
				result = String.format(this.mailtoTemplate, mail);
			return result
		},
		renderCheckbox : function (value) {
			var param = "";
			if (value)
				param = "checked\x3d'checked' ";
			return String.format(this.checkboxTemplate, param)
		},
		selectById : function (id) {
			if (debug)
				console.debug("select by id " + id);
			var index = this.getStore().indexOfId(id);
			if (index >= 0)
				this.getSelectionModel().selectRow(index);
			else if (debug)
				console.debug("could not find item with id " + id)
		},
		handleHistory : function (params) {
			if (params && params.length > 0)
				this.selectById(params[0]);
			else {
				if (debug)
					console.debug("clear selection");
				this.getSelectionModel().clearSelections()
			}
		}
	});
Sonia.rest.FormPanel = Ext.extend(Ext.form.FormPanel, {
		okText : "Ok",
		cancelText : "Cancel",
		addText : "Add",
		removeText : "Remove",
		item : null,
		onUpdate : null,
		onCreate : null,
		initComponent : function () {
			var config = {
				bodyCssClass : "x-panel-mc",
				padding : 5,
				labelWidth : 100,
				defaults : {
					width : 240
				},
				autoScroll : true,
				monitorValid : true,
				defaultType : "textfield",
				buttonAlign : "center",
				footerCfg : {
					cls : "x-panel-mc"
				},
				buttons : [{
						text : this.okText,
						formBind : true,
						scope : this,
						handler : this.submit
					}, {
						text : this.cancelText,
						scope : this,
						handler : this.cancel
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.rest.FormPanel.superclass.initComponent.apply(this, arguments);
			if (this.item)
				this.loadData(this.item)
		},
		isUpdate : function () {
			return this.item !== null
		},
		loadData : function (item) {
			this.item = item;
			var data = {
				success : true,
				data : item
			};
			this.getForm().loadRecord(data)
		},
		submit : function () {
			if (debug)
				console.debug("form submitted");
			var item = this.getForm().getFieldValues();
			if (this.isUpdate())
				this.update(item);
			else
				this.create(item)
		},
		cancel : function () {
			if (debug)
				console.debug("reset form");
			this.getForm().reset()
		},
		execCallback : function (obj, item) {
			if (Ext.isFunction(obj))
				obj(item);
			else if (Ext.isObject(obj) && Ext.isFunction(obj.fn))
				obj.fn.call(obj.scope, item);
			else if (debug)
				console.debug("obj " + obj + " is not valid callback object")
		},
		update : function (item) {
			if (debug) {
				console.debug("update item: ");
				console.debug(item)
			}
		},
		create : function (item) {
			if (debug) {
				console.debug("create item: ");
				console.debug(item)
			}
		}
	});
var repositoryTypeStore = new Ext.data.JsonStore({
		id : 1,
		fields : ["displayName", "name", "supportedCommands"]
	});
function loadRepositoryTypes(state) {
	repositoryTypeStore.loadData(state.repositoryTypes)
}
loginCallbacks.push(loadRepositoryTypes);
Ext.ns("Sonia.repository");
Sonia.repository.openListeners = [];
Sonia.repository.typeIcons = [];
Sonia.repository.getTypeIcon = function (type) {
	return Sonia.repository.typeIcons[type]
};
Sonia.repository.createContentUrl = function (repository, path, revision) {
	var contentUrl = restUrl + "repositories/" + repository.id + "/";
	contentUrl += "content?path\x3d" + path;
	if (revision)
		contentUrl += "\x26revision\x3d" + revision;
	return contentUrl
};
Sonia.repository.createContentId = function (repository, path, revision) {
	var id = repository.id + "-b-" + path;
	if (revision)
		id += "-r-" + revision;
	return id
};
Sonia.repository.isOwner = function (repository) {
	return admin || repository.permissions
};
Sonia.repository.setEditPanel = function (panels) {
	var editPanel = Ext.getCmp("repositoryEditPanel");
	editPanel.removeAll();
	Ext.each(panels, function (panel) {
		editPanel.add(panel)
	});
	editPanel.setActiveTab(0);
	editPanel.doLayout()
};
Sonia.repository.createUrl = function (type, name) {
	return Sonia.util.getBaseUrl() + "/" + type + "/" + name
};
Sonia.repository.createUrlFromObject = function (repository) {
	return Sonia.repository.createUrl(repository.type, repository.name)
};
Sonia.repository.getTypeByName = function (name) {
	var type = null;
	repositoryTypeStore.queryBy(function (rec) {
		if (rec.get("name") === name)
			type = rec.data
	});
	return type
};
Sonia.repository.getPermissionType = function (repository) {
	var values = [];
	values["READ"] = 0;
	values["WRITE"] = 10;
	values["OWNER"] = 20;
	var type = "READ";
	if (state.assignedPermissions)
		Ext.each(state.assignedPermissions, function (p) {
			var parts = p.split(":");
			if (parts[0] === "repository" && (parts[1] === "*" || parts[1] === repository.id))
				if (values[parts[2]] > values[type])
					type = parts[2]
		});
	return type
};
Sonia.repository.DefaultPanel = {
	region : "south",
	title : "Repository Form",
	padding : 5,
	xtype : "panel",
	bodyCssClass : "x-panel-mc",
	html : "Add or select an Repository"
};
Sonia.repository.get = function (id, callback) {
	function execCallback(item) {
		if (Ext.isFunction(callback))
			callback(item);
		else
			callback.call(callback.scope, item)
	}
	var repository = null;
	var grid = Ext.getCmp("repositoryGrid");
	if (grid) {
		var store = grid.getStore();
		if (store) {
			var rec$$0 = null;
			var index = id.indexOf("/");
			if (index > 0) {
				var type = id.substring(0, index);
				var name = id.substring(index);
				index = store.findBy(function (rec) {
						return rec.get("name") === name && rec.get("type") === type
					});
				if (index >= 0)
					rec$$0 = store.getAt(index)
			} else
				rec$$0 =
					store.getById(id);
			if (rec$$0)
				repository = rec$$0.data
		}
	}
	if (repository)
		execCallback(repository);
	else
		Ext.Ajax.request({
			url : restUrl + "repositories/" + id + ".json",
			method : "GET",
			scope : this,
			success : function (response) {
				execCallback(Ext.decode(response.responseText))
			},
			failure : function (result) {
				main.handleRestFailure(result)
			}
		})
};
Sonia.repository.openFile = function (repository, path, revision) {
	if (debug)
		console.debug("open file: " + path);
	var id = Sonia.repository.createContentId(repository, path, revision);
	main.addTab({
		id : id,
		path : path,
		revision : revision,
		repository : repository,
		xtype : "contentPanel",
		closable : true,
		autoScroll : true
	})
};
Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
		typeIconTemplate : '\x3cimg src\x3d"{0}" alt\x3d"{1}" title\x3d"{2}"\x3e',
		colNameText : "Name",
		colTypeText : "Type",
		colContactText : "Contact",
		colDescriptionText : "Description",
		colCreationDateText : "Creation date",
		colLastModifiedText : "Last modified",
		colUrlText : "Url",
		colArchiveText : "Archive",
		emptyText : "No repository is configured",
		formTitleText : "Repository Form",
		unknownType : "Unknown",
		archiveIcon : "resources/images/archive.png",
		warningIcon : "resources/images/warning.png",
		filterRequest : null,
		searchValue : null,
		typeFilter : null,
		mainGroup : "默认分组",
		parentPanel : null,
		ready : false,
		initComponent : function () {
			var repositoryStore = new Ext.data.GroupingStore({
					proxy : new Ext.data.HttpProxy({
						url : restUrl + "repositories.json",
						disableCaching : false
					}),
					idProperty : "id",
					reader : new Ext.data.JsonReader({
						fields : [{
								name : "id"
							}, {
								name : "group",
								convert : this.convertToGroup
							}, {
								name : "name"
							}, {
								name : "type"
							}, {
								name : "contact"
							}, {
								name : "description"
							}, {
								name : "creationDate"
							}, {
								name : "lastModified"
							}, {
								name : "public"
							}, {
								name : "permissions"
							}, {
								name : "properties"
							}, {
								name : "archived"
							}, {
								name : "healthCheckFailures",
								defaultValue : null
							}
						]
					}),
					sortInfo : {
						field : "name"
					},
					autoDestroy : true,
					autoLoad : true,
					remoteGroup : false,
					groupOnSort : false,
					groupField : "group",
					groupDir : "AES",
					listeners : {
						load : {
							fn : this.storeLoad,
							scope : this
						},
						exception : Sonia.rest.ExceptionHandler
					}
				});
			var repositoryColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : true,
						scope : this,
						width : 125
					},
					columns : [{
							id : "iconType",
							dataIndex : "type",
							renderer : this.renderTypeIcon,
							width : 20
						}, {
							id : "name",
							header : this.colNameText,
							dataIndex : "name",
							renderer : this.renderName,
							scope : this
						}, {
							id : "type",
							header : this.colTypeText,
							dataIndex : "type",
							renderer : this.renderRepositoryType,
							width : 80,
							hidden : true
						}, {
							id : "contact",
							header : this.colContactText,
							dataIndex : "contact",
							renderer : this.renderMailto
						}, {
							id : "description",
							header : this.colDescriptionText,
							dataIndex : "description"
						}, {
							id : "creationDate",
							header : this.colCreationDateText,
							dataIndex : "creationDate",
							renderer : Ext.util.Format.formatTimestamp
						}, {
							id : "lastModified",
							header : this.colLastModifiedText,
							dataIndex : "lastModified",
							renderer : Ext.util.Format.formatTimestamp,
							hidden : true
						}, {
							id : "Url",
							header : this.colUrlText,
							dataIndex : "name",
							renderer : this.renderRepositoryUrl,
							scope : this,
							width : 250
						}, {
							id : "Archive",
							header : this.colArchiveText,
							dataIndex : "archived",
							width : 40,
							hidden : !state.clientConfig.enableRepositoryArchive,
							renderer : this.renderArchive,
							scope : this
						}, {
							id : "group",
							dataIndex : "group",
							hidden : true,
							hideable : false,
							groupRenderer : this.renderGroupName,
							scope : this
						}
					]
				});
			if (debug) {
				var msg = "grouping is ";
				if (state.clientConfig.disableGroupingGrid)
					msg +=
					"disabled";
				else
					msg += "enabled";
				console.debug(msg)
			}
			if (state.clientConfig.enableRepositoryArchive) {
				if (!this.filterRequest)
					this.filterRequest = {};
				this.filterRequest.archived = false
			}
			var config = {
				autoExpandColumn : "description",
				store : repositoryStore,
				colModel : repositoryColModel,
				emptyText : this.emptyText,
				listeners : {
					fallBelowMinHeight : {
						fn : this.onFallBelowMinHeight,
						scope : this
					}
				},
				view : new Ext.grid.GroupingView({
					idPrefix : "{grid.id}",
					enableGrouping : !state.clientConfig.disableGroupingGrid,
					enableNoGroups : false,
					forceFit : true,
					groupMode : "value",
					enableGroupingMenu : false,
					groupTextTpl : '{group} ({[values.rs.length]} {[values.rs.length \x3e 1 ? "仓库" : "仓库"]})',
					getRowClass : function (record) {
						var rowClass = "";
						var healthFailures = record.get("healthCheckFailures");
						if (healthFailures && healthFailures.length > 0)
							rowClass = "unhealthy";
						return rowClass
					}
				})
			};
			this.addEvents("repositorySelected");
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.Grid.superclass.initComponent.apply(this, arguments);
			if (this.parentPanel)
				this.parentPanel.repositoryGrid =
					this
		},
		renderTypeIcon : function (type, meta, record) {
			var result;
			if (record) {
				var healthFailures = record.get("healthCheckFailures");
				if (healthFailures && healthFailures.length > 0)
					result = String.format(this.typeIconTemplate, this.warningIcon, type, type)
			}
			if (!result)
				result = this.getTypeIcon(type);
			return result
		},
		getTypeIcon : function (type) {
			var result = "";
			var icon = Sonia.repository.getTypeIcon(type);
			if (icon) {
				var displayName = type;
				var t = Sonia.repository.getTypeByName(type);
				if (t)
					displayName = t.displayName;
				result = String.format(this.typeIconTemplate,
						icon, type, displayName)
			}
			return result
		},
		renderRepositoryUrl : function (name, meta, record) {
			var type = record.get("type");
			return this.renderUrl(Sonia.repository.createUrl(type, name))
		},
		renderArchive : function (v) {
			return v ? "\x3cimg src\x3d" + this.archiveIcon + " alt\x3d" + v + "\x3e" : ""
		},
		convertToGroup : function (v, data) {
			var name = data.name;
			var i = name.lastIndexOf("/");
			if (i > 0)
				name = name.substring(0, i);
			else
				name = "zzz__";
			return name
		},
		renderName : function (v, meta, record, rowIndex, colIndex, store) {
			var i = v.lastIndexOf("/");
			if (i > 0)
				v =
					v.substring(i + 1);
			return v
		},
		renderGroupName : function (v) {
			if (v === "zzz__")
				v = this.mainGroup;
			return v
		},
		storeLoad : function () {
			if (this.searchValue)
				this.filterStore();
			if (this.filterRequest)
				this.filterByRequest();
			this.ready = true
		},
		onFallBelowMinHeight : function (height, minHeight) {
			var p = Ext.getCmp("repositoryEditPanel");
			this.setHeight(minHeight);
			var epHeight = p.getHeight();
			p.setHeight(epHeight - (minHeight - height));
			this.doLayout();
			p.doLayout();
			this.ownerCt.doLayout()
		},
		getFilterRequest : function () {
			if (!this.filterRequest)
				this.filterRequest = {};
			return this.filterRequest
		},
		search : function (value) {
			this.searchValue = value;
			this.filterStore()
		},
		filter : function (type) {
			this.typeFilter = type;
			this.filterStore()
		},
		clearStoreFilter : function () {
			this.filterRequest = null;
			this.searchValue = null;
			this.typeFilter = null;
			this.getStore().clearFilter()
		},
		filterByRequest : function () {
			if (debug) {
				console.debug("filter repository store by request:");
				console.debug(this.filterRequest)
			}
			var store = this.getStore();
			if (!this.filterRequest)
				store.clearFilter();
			else {
				var query = this.filterRequest.query;
				if (query)
					query = query.toLowerCase();
				var archived = !state.clientConfig.enableRepositoryArchive || this.filterRequest.archived;
				store.filterBy(function (rec) {
					var desc = rec.get("description");
					return (!query || rec.get("name").toLowerCase().indexOf(query) >= 0 || desc && desc.toLowerCase().indexOf(query) >= 0) && (!this.filterRequest.type || rec.get("type") === this.filterRequest.type) && (archived || !rec.get("archived"))
				}, this)
			}
		},
		filterStore : function () {
			var store = this.getStore();
			if (!this.searchValue && !this.typeFilter)
				store.clearFilter();
			else {
				var search = null;
				if (this.searchValue)
					search = this.searchValue.toLowerCase();
				store.filterBy(function (rec) {
					var desc = rec.get("description");
					return (!search || rec.get("name").toLowerCase().indexOf(search) >= 0 || desc && desc.toLowerCase().indexOf(search) >= 0) && (!this.typeFilter || rec.get("type") === this.typeFilter)
				}, this)
			}
		},
		selectItem : function (item) {
			if (debug)
				console.debug(item.name + " selected");
			if (this.parentPanel)
				this.parentPanel.updateHistory(item);
			var owner = Sonia.repository.isOwner(item);
			this.fireEvent("repositorySelected",
				item, owner);
			var infoPanel = main.getInfoPanel(item.type);
			infoPanel.item = item;
			var panels = [infoPanel];
			if (owner)
				panels.push({
					item : item,
					xtype : "repositorySettingsForm",
					onUpdate : {
						fn : this.reload,
						scope : this
					},
					onCreate : {
						fn : this.reload,
						scope : this
					}
				}, {
					item : item,
					xtype : "repositoryPermissionsForm",
					listeners : {
						updated : {
							fn : this.reload,
							scope : this
						},
						created : {
							fn : this.reload,
							scope : this
						}
					}
				});
			else
				Ext.getCmp("repoRmButton").setDisabled(true);
			if (admin && item.healthCheckFailures && item.healthCheckFailures.length > 0)
				panels.push({
					xtype : "repositoryHealthCheckFailurePanel",
					grid : this,
					repository : item,
					healthCheckFailures : item.healthCheckFailures
				});
			Ext.each(Sonia.repository.openListeners, function (listener) {
				if (Ext.isFunction(listener))
					listener(item, panels);
				else
					listener.call(listener.scope, item, panels)
			});
			Sonia.repository.setEditPanel(panels)
		},
		renderRepositoryType : function (repositoryType) {
			var displayName = this.unknownType;
			var rec$$0 = repositoryTypeStore.queryBy(function (rec) {
					return rec.data.name === repositoryType
				}).itemAt(0);
			if (rec$$0)
				displayName = rec$$0.get("displayName");
			return displayName
		}
	});
Ext.reg("repositoryGrid", Sonia.repository.Grid);
Sonia.repository.InfoPanel = Ext.extend(Ext.Panel, {
		linkTemplate : '\x3ca target\x3d"_blank" href\x3d"{0}"\x3e{0}\x3c/a\x3e',
		mailTemplate : '\x3ca href\x3d"mailto:{0}"\x3e{0}\x3c/a\x3e',
		actionLinkTemplate : '\x3ca style\x3d"cursor: pointer;"\x3e{0}\x3c/a\x3e',
		nameText : "Name: ",
		typeText : "Type: ",
		contactText : "Contact: ",
		urlText : "Url: ",
		changesetViewerText : "Commits",
		accessText : "Access:",
		accessReadOnly : "Read-Only access",
		accessReadWrite : "Read+Write access",
		initComponent : function () {
			var contact = "";
			if (this.item.contact)
				contact =
					String.format(this.mailTemplate, this.item.contact);
			var access = this.accessReadOnly;
			if (Sonia.repository.getPermissionType(this.item) !== "READ")
				access = this.accessReadWrite;
			var items = [{
					xtype : "label",
					text : this.nameText
				}, {
					xtype : "box",
					html : this.item.name
				}, {
					xtype : "label",
					text : this.typeText
				}, {
					xtype : "box",
					html : this.getRepositoryTypeText(this.item.type)
				}, {
					xtype : "label",
					text : this.contactText
				}, {
					xtype : "box",
					html : contact
				}, {
					xtype : "label",
					text : this.accessText
				}, {
					xtype : "box",
					html : '\x3cspan style\x3d"font-weight: bold; color: #747170"\x3e' +
					access + "\x3c/span\x3e"
				}, {
					xtype : "label",
					text : this.urlText
				}, {
					xtype : "box",
					html : String.format(this.linkTemplate, Sonia.repository.createUrlFromObject(this.item))
				}
			];
			var config = {
				title : this.item.name,
				padding : 5,
				bodyCssClass : "x-panel-mc",
				layout : "table",
				layoutConfig : {
					columns : 2,
					tableAttrs : {
						style : "width: 80%;"
					}
				},
				defaults : {
					style : "font-size: 12px"
				},
				items : items
			};
			this.modifyDefaultConfig(config);
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.InfoPanel.superclass.initComponent.apply(this, arguments)
		},
		modifyDefaultConfig : function (config) {},
		getRepositoryUrlWithUsername : function () {
			var uri = Sonia.repository.createUrlFromObject(this.item);
			if (state.user.name !== "anonymous") {
				var index = uri.indexOf("://");
				if (index > 0) {
					index += 3;
					var username = state.user.name;
					username = username.replace("\\", "\\\\");
					uri = uri.substring(0, index) + username + "@" + uri.substring(index)
				}
			}
			return uri
		},
		getRepositoryTypeText : function (t) {
			var text = null;
			for (var i = 0; i < state.repositoryTypes.length; i++) {
				var type = state.repositoryTypes[i];
				if (type.name ===
					t) {
					text = type.displayName + " (" + t + ")";
					break
				}
			}
			return text
		},
		createSpacer : function () {
			return {
				xtype : "box",
				height : 10,
				colspan : 2
			}
		},
		createChangesetViewerLink : function () {
			return {
				xtype : "link",
				style : "font-weight: bold",
				text : this.changesetViewerText,
				handler : this.openChangesetViewer,
				scope : this
			}
		},
		createChangesetViewer : function () {
			return {
				id : "repositoryChangesetViewerPanel;" + this.item.id,
				repository : this.item,
				xtype : "repositoryChangesetViewerPanel",
				closable : true,
				autoScroll : true
			}
		},
		openChangesetViewer : function (changesetViewer) {
			if (!changesetViewer)
				changesetViewer =
					this.createChangesetViewer();
			main.addTab(changesetViewer)
		}
	});
Ext.reg("repositoryInfoPanel", Sonia.repository.InfoPanel);
Sonia.repository.ExtendedInfoPanel = Ext.extend(Sonia.repository.InfoPanel, {
		checkoutTemplate : null,
		checkoutText : "Checkout: ",
		repositoryBrowserText : "Source",
		enableRepositoryBrowser : true,
		enableChangesetViewer : true,
		modifyDefaultConfig : function (config) {
			var items = config.items;
			if (!items)
				items = [];
			items.push({
				xtype : "label",
				text : this.checkoutText
			}, {
				xtype : "box",
				html : String.format(this.checkoutTemplate, this.getRepositoryUrlWithUsername())
			}, this.createSpacer());
			var box = [];
			if (this.enableChangesetViewer) {
				box.push(this.createChangesetViewerLink());
				if (this.enableRepositoryBrowser)
					box.push({
						xtyle : "box",
						html : ", ",
						width : 8
					})
			}
			if (this.enableRepositoryBrowser)
				box.push(this.createRepositoryBrowserLink());
			items.push({
				xtype : "panel",
				colspan : 2,
				layout : "column",
				items : box
			})
		},
		createRepositoryBrowserLink : function () {
			return {
				xtype : "link",
				style : "font-weight: bold",
				text : this.repositoryBrowserText,
				handler : this.openRepositoryBrowser,
				scope : this
			}
		},
		createRepositoryBrowser : function () {
			return {
				id : "repositoryBrowser;" + this.item.id + ";null",
				xtype : "repositoryBrowser",
				repository : this.item,
				closable : true
			}
		},
		openRepositoryBrowser : function (browser) {
			if (!browser)
				browser = this.createRepositoryBrowser();
			main.addTab(browser)
		}
	});
Ext.reg("repositoryExtendedInfoPanel", Sonia.repository.ExtendedInfoPanel);
Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel, {
		colGroupPermissionText : "Is Group",
		colNameText : "Name",
		colTypeText : "Permissions",
		formTitleText : "Settings",
		nameText : "Name",
		typeText : "Type",
		contactText : "Contact",
		descriptionText : "Description",
		publicText : "Public",
		permissionText : "Permission",
		errorTitleText : "Error",
		updateErrorMsgText : "Repository update failed",
		createErrorMsgText : "Repository creation failed",
		nameHelpText : "The name of the repository. This name will be part of the repository url.",
		typeHelpText : "The type of the repository (e.g. Mercurial, Git or Subversion).",
		contactHelpText : "Email address of the person who is responsible for this repository.",
		descriptionHelpText : "A short description of the repository.",
		publicHelpText : "Public repository, readable by everyone.",
		permissionHelpText : "Manage permissions for a specific user or group.\x3cbr /\x3e\n  Permissions explenation:\x3cbr /\x3e\x3cb\x3eREAD\x3c/b\x3e \x3d read\x3cbr /\x3e\x3cb\x3eWRITE\x3c/b\x3e \x3d read and write\x3cbr /\x3e\n  \x3cb\x3eOWNER\x3c/b\x3e \x3d read, write and also the ability to manage the properties and permissions",
		initComponent : function () {
			this.addEvents("preCreate", "created", "preUpdate", "updated", "updateFailed", "creationFailed");
			Sonia.repository.FormPanel.superclass.initComponent.apply(this, arguments)
		},
		update : function (item) {
			item = Ext.apply(this.item, item);
			if (debug)
				console.debug("update repository: " + item.name);
			var url = restUrl + "repositories/" + item.id + ".json";
			var el = this.el;
			var tid = setTimeout(function () {
					el.mask("Loading ...")
				}, 100);
			if (item.group)
				delete item.group;
			this.fireEvent("preUpdate", item);
			Ext.Ajax.request({
				url : url,
				jsonData : item,
				method : "PUT",
				scope : this,
				success : function () {
					if (debug)
						console.debug("update success");
					this.fireEvent("updated", item);
					clearTimeout(tid);
					el.unmask();
					this.execCallback(this.onUpdate, item)
				},
				failure : function (result) {
					this.fireEvent("updateFailed", item);
					clearTimeout(tid);
					el.unmask();
					main.handleFailure(result.status, this.errorTitleText, this.updateErrorMsgText)
				}
			})
		},
		getIdFromResponse : function (response) {
			var id = null;
			var location = response.getResponseHeader("Location");
			if (location) {
				var parts = location.split("/");
				id = parts[parts.length - 1]
			}
			return id
		},
		create : function (item) {
			if (debug)
				console.debug("create repository: " + item.name);
			var url = restUrl + "repositories.json";
			var el = this.el;
			var tid = setTimeout(function () {
					el.mask("Loading ...")
				}, 100);
			this.fireEvent("preCreate", item);
			Ext.Ajax.request({
				url : url,
				jsonData : item,
				method : "POST",
				scope : this,
				success : function (response) {
					if (debug)
						console.debug("create success");
					var id = this.getIdFromResponse(response);
					if (id)
						item.id = id;
					this.fireEvent("created", item);
					this.getForm().reset();
					clearTimeout(tid);
					el.unmask();
					this.execCallback(this.onCreate, item)
				},
				failure : function (result) {
					this.fireEvent("creationFailed", item);
					clearTimeout(tid);
					el.unmask();
					main.handleRestFailure(result, this.errorTitleText, this.createErrorMsgText)
				}
			})
		},
		cancel : function () {
			if (debug)
				console.debug("cancel form");
			Sonia.repository.setEditPanel(Sonia.repository.DefaultPanel)
		}
	});
Ext.reg("repositoryForm", Sonia.repository.FormPanel);
Sonia.repository.SettingsFormPanel = Ext.extend(Sonia.repository.FormPanel, {
		initComponent : function () {
			var update = this.isUpdate();
			var config = {
				title : this.formTitleText,
				items : [{
						id : "repositoryName",
						fieldLabel : this.nameText,
						name : "name",
						readOnly : update,
						allowBlank : false,
						helpText : this.nameHelpText,
						vtype : "repositoryName"
					}, {
						id : "repositoryType",
						fieldLabel : this.typeText,
						name : "type",
						xtype : "combo",
						readOnly : update,
						hiddenName : "type",
						typeAhead : true,
						triggerAction : "all",
						lazyRender : true,
						mode : "local",
						editable : false,
						store : repositoryTypeStore,
						valueField : "name",
						displayField : "displayName",
						allowBlank : false,
						helpText : this.typeHelpText
					}, {
						fieldLabel : this.contactText,
						name : "contact",
						vtype : "email",
						helpText : this.contactHelpText
					}, {
						fieldLabel : this.descriptionText,
						name : "description",
						xtype : "textarea",
						helpText : this.descriptionHelpText
					}, {
						fieldLabel : this.publicText,
						name : "public",
						xtype : "checkbox",
						helpText : this.publicHelpText
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.SettingsFormPanel.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("repositorySettingsForm", Sonia.repository.SettingsFormPanel);
Sonia.repository.PermissionFormPanel = Ext.extend(Sonia.repository.FormPanel, {
		permissionStore : null,
		addIcon : "resources/images/add.png",
		removeIcon : "resources/images/delete.png",
		titleText : "Permissions",
		initComponent : function () {
			var permissionStore = new Ext.data.JsonStore({
					root : "permissions",
					fields : [{
							name : "name"
						}, {
							name : "type"
						}, {
							name : "groupPermission",
							type : "boolean"
						}
					],
					sortInfo : {
						field : "name"
					}
				});
			this.permissionStore = permissionStore;
			var permissionColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : true
					},
					columns : [{
							id : "groupPermission",
							xtype : "checkcolumn",
							header : this.colGroupPermissionText,
							dataIndex : "groupPermission",
							width : 40
						}, {
							id : "name",
							header : this.colNameText,
							dataIndex : "name",
							editable : true
						}, {
							id : "type",
							header : this.colTypeText,
							dataIndex : "type",
							width : 80,
							editor : new Ext.form.ComboBox({
								valueField : "type",
								displayField : "type",
								typeAhead : false,
								editable : false,
								triggerAction : "all",
								mode : "local",
								store : new Ext.data.SimpleStore({
									fields : ["type"],
									data : [["READ"], ["WRITE"], ["OWNER"]]
								})
							})
						}
					],
					getCellEditor : function (colIndex, rowIndex) {
						if (this.getColumnId(colIndex) ===
							"name") {
							var store = null;
							var rec = permissionStore.getAt(rowIndex);
							if (rec.data.groupPermission) {
								if (debug)
									console.debug("using groupSearchStore");
								store = groupSearchStore
							} else {
								if (debug)
									console.debug("using userSearchStore");
								store = userSearchStore
							}
							return new Ext.grid.GridEditor(new Ext.form.ComboBox({
									store : store,
									displayField : "label",
									valueField : "value",
									typeAhead : true,
									mode : "remote",
									queryParam : "query",
									hideTrigger : true,
									selectOnFocus : true,
									width : 250
								}))
						}
						return Ext.grid.ColumnModel.prototype.getCellEditor.call(this,
							colIndex, rowIndex)
					}
				});
			if (this.item) {
				if (!this.item.permissions)
					this.item.permissions = [];
				this.permissionStore.loadData(this.item)
			}
			var selectionModel = new Ext.grid.RowSelectionModel({
					singleSelect : true
				});
			var config = {
				title : this.titleText,
				listeners : {
					updated : this.clearModifications,
					preUpdate : {
						fn : this.updatePermissions,
						scope : this
					}
				},
				items : [{
						id : "permissionGrid",
						xtype : "editorgrid",
						title : this.permissionsText,
						clicksToEdit : 1,
						autoExpandColumn : "name",
						frame : true,
						width : "100%",
						autoHeight : true,
						autoScroll : false,
						colModel : permissionColModel,
						sm : selectionModel,
						store : this.permissionStore,
						viewConfig : {
							forceFit : true
						},
						tbar : [{
								text : this.addText,
								scope : this,
								icon : this.addIcon,
								handler : function () {
									var Permission = this.permissionStore.recordType;
									var p = new Permission({
											type : "READ"
										});
									var grid = Ext.getCmp("permissionGrid");
									grid.stopEditing();
									this.permissionStore.insert(0, p);
									grid.startEditing(0, 0)
								}
							}, {
								text : this.removeText,
								scope : this,
								icon : this.removeIcon,
								handler : function () {
									var grid = Ext.getCmp("permissionGrid");
									var selected = grid.getSelectionModel().getSelected();
									if (selected)
										this.permissionStore.remove(selected)
								}
							}, "-\x3e", {
								id : "permissionGridHelp",
								xtype : "box",
								autoEl : {
									tag : "img",
									src : "resources/images/help.png"
								}
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.PermissionFormPanel.superclass.initComponent.apply(this, arguments)
		},
		afterRender : function () {
			Sonia.repository.PermissionFormPanel.superclass.afterRender.apply(this, arguments);
			Ext.QuickTips.register({
				target : Ext.getCmp("permissionGridHelp"),
				title : "",
				text : this.permissionHelpText,
				enabled : true
			})
		},
		updatePermissions : function (item) {
			var permissions = [];
			this.permissionStore.data.each(function (record) {
				permissions.push(record.data)
			});
			item.permissions = permissions
		},
		clearModifications : function () {
			Ext.getCmp("permissionGrid").getStore().commitChanges()
		}
	});
Ext.reg("repositoryPermissionsForm", Sonia.repository.PermissionFormPanel);
Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, {
		titleText : "Repository Form",
		emptyText : "Add or select an Repository",
		filterText : "Filter: ",
		searchText : "Search: ",
		archiveText : "Archive",
		unarchiveText : "Unarchive",
		archiveTitleText : "Archive Repository",
		unarchiveTitleText : "Unarchive Repository",
		archiveMsgText : 'Archive Repository "{0}"?',
		unarchiveMsgText : 'Unarchive Repository "{0}"?',
		errorArchiveMsgText : "Repository archival failed",
		errorUnarchiveMsgText : "Repository unarchival failed",
		displayArchivedRepositoriesText : "Archive",
		removeTitleText : "Remove Repository",
		removeMsgText : 'This action will permanently remove the data of the repository \n    "{0}" from your disk.\x3cbr /\x3eDo you want to proceed?',
		errorTitleText : "Error",
		errorMsgText : "Repository deletion failed",
		archiveIcon : "resources/images/archive.png",
		repositoryGrid : null,
		initComponent : function () {
			var typeStore = new Ext.data.JsonStore({
					id : 1,
					fields : ["displayName", "name"]
				});
			typeStore.loadData(state.repositoryTypes);
			var t = new typeStore.recordType({
					displayName : "",
					name : ""
				});
			typeStore.insert(0, t);
			var toolbar = [];
			if (admin)
				toolbar.push({
					id : "repositoryAddButton",
					xtype : "tbbutton",
					text : this.addText,
					icon : this.addIcon,
					scope : this,
					handler : this.showAddForm
				});
			if (state.clientConfig.enableRepositoryArchive)
				toolbar.push({
					xtype : "tbbutton",
					id : "repoArchiveButton",
					disabled : true,
					text : this.archiveText,
					icon : this.archiveIcon,
					scope : this,
					handler : this.toggleArchive
				});
			toolbar.push({
				xtype : "tbbutton",
				id : "repoRmButton",
				disabled : true,
				text : this.removeText,
				icon : this.removeIcon,
				scope : this,
				handler : this.removeRepository
			},
				"-", {
				xtype : "tbbutton",
				text : this.reloadText,
				icon : this.reloadIcon,
				scope : this,
				handler : this.reload
			}, "-", {
				xtype : "label",
				text : this.filterText,
				cls : "ytb-text"
			}, "  ", {
				id : "repositoryTypeFilter",
				xtype : "combo",
				hiddenName : "type",
				typeAhead : true,
				triggerAction : "all",
				lazyRender : true,
				mode : "local",
				editable : false,
				store : typeStore,
				valueField : "name",
				displayField : "displayName",
				allowBlank : true,
				listeners : {
					select : {
						fn : this.filterByType,
						scope : this
					}
				},
				tpl : '\x3ctpl for\x3d"."\x3e' + '\x3cdiv class\x3d"x-combo-list-item"\x3e' + "{displayName}\x26nbsp;" +
				"\x3c/div\x3e\x3c/tpl\x3e"
			}, "  ", {
				xtype : "label",
				text : this.searchText,
				cls : "ytb-text"
			}, "  ", {
				id : "repositorySearch",
				xtype : "textfield",
				enableKeyEvents : true,
				listeners : {
					keyup : {
						fn : this.search,
						scope : this
					}
				}
			});
			if (state.clientConfig.enableRepositoryArchive)
				toolbar.push("  ", {
					id : "displayArchived",
					xtype : "checkbox",
					listeners : {
						check : {
							fn : this.filterByArchived,
							scope : this
						}
					}
				}, {
					xtype : "label",
					text : this.displayArchivedRepositoriesText,
					cls : "ytb-text"
				});
			var config = {
				tbar : toolbar,
				items : [{
						id : "repositoryGrid",
						xtype : "repositoryGrid",
						region : "center",
						parentPanel : this,
						listeners : {
							repositorySelected : {
								fn : this.onRepositorySelection,
								scope : this
							}
						}
					}, {
						id : "repositoryEditPanel",
						xtype : "tabpanel",
						activeTab : 0,
						height : 250,
						split : true,
						border : true,
						region : "south",
						enableTabScroll : true,
						items : [{
								bodyCssClass : "x-panel-mc",
								title : this.titleText,
								padding : 5,
								html : this.emptyText
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.Panel.superclass.initComponent.apply(this, arguments)
		},
		getGrid : function () {
			if (!this.repositoryGrid) {
				if (debug)
					console.debug("repository grid not found, retrive by cmp id");
				this.repositoryGrid = Ext.getCmp("repositoryGrid")
			}
			return this.repositoryGrid
		},
		updateHistory : function (item) {
			var token = Sonia.History.createToken("repositoryPanel", item.id);
			Sonia.History.add(token)
		},
		filterByArchived : function (checkbox, checked) {
			var grid = this.getGrid();
			grid.getFilterRequest().archived = checked;
			grid.filterByRequest()
		},
		filterByType : function (combo, rec) {
			var grid = this.getGrid();
			grid.getFilterRequest().type = rec.get("name");
			grid.filterByRequest()
		},
		search : function (field) {
			var grid = this.getGrid();
			grid.getFilterRequest().query = field.getValue();
			grid.filterByRequest()
		},
		getSelectedRepository : function () {
			var repository = null;
			var grid = this.getGrid();
			var selected = grid.getSelectionModel().getSelected();
			if (selected)
				repository = selected.data;
			else if (debug)
				console.debug("no repository selected");
			return repository
		},
		executeRemoteCall : function (title, message, method, url, data, failureCallback, icon) {
			Ext.MessageBox.show({
				title : title,
				msg : message,
				buttons : Ext.MessageBox.OKCANCEL,
				icon : icon ? icon : Ext.MessageBox.QUESTION,
				fn : function (result$$0) {
					if (result$$0 === "ok") {
						if (debug)
							console.debug("call repository repository action " + method + " on " + url);
						var el = this.el;
						var tid = setTimeout(function () {
								el.mask("Loading ...")
							}, 100);
						if (data && data.group)
							delete data.group;
						Ext.Ajax.request({
							url : url,
							method : method,
							jsonData : data,
							scope : this,
							success : function () {
								this.reload();
								this.resetPanel();
								clearTimeout(tid);
								el.unmask()
							},
							failure : function (result) {
								clearTimeout(tid);
								el.unmask();
								failureCallback.call(this, result)
							}
						})
					}
				},
				scope : this
			})
		},
		toggleArchive : function () {
			var item =
				this.getSelectedRepository();
			if (item) {
				var title = item.archived ? this.unarchiveTitleText : this.archiveTitleText;
				var msg = item.archived ? this.unarchiveMsgText : this.archiveMsgText;
				item.archived = !item.archived;
				if (debug)
					console.debug("toggle repository " + item.name + " archive to " + item.archived);
				var url = restUrl + "repositories/" + item.id + ".json";
				this.executeRemoteCall(title, String.format(msg, item.name), "PUT", url, item, function (result) {
					main.handleFailure(result.status, this.errorTitleText, this.errorArchiveMsgText)
				})
			}
		},
		removeRepository : function () {
			var item = this.getSelectedRepository();
			if (item) {
				if (debug)
					console.debug("remove repository " + item.name);
				var url = restUrl + "repositories/" + item.id + ".json";
				this.executeRemoteCall(this.removeTitleText, String.format(this.removeMsgText, item.name), "DELETE", url, null, function (result) {
					main.handleFailure(result.status, this.errorTitleText, this.errorMsgText)
				}, Ext.MessageBox.WARNING)
			}
		},
		onRepositorySelection : function (item, owner) {
			if (owner)
				if (state.clientConfig.enableRepositoryArchive) {
					var archiveBt =
						Ext.getCmp("repoArchiveButton");
					if (item.archived) {
						archiveBt.setText(this.unarchiveText);
						Ext.getCmp("repoRmButton").setDisabled(false)
					} else {
						archiveBt.setText(this.archiveText);
						Ext.getCmp("repoRmButton").setDisabled(true)
					}
					archiveBt.setDisabled(false)
				} else
					Ext.getCmp("repoRmButton").setDisabled(false);
			else {
				Ext.getCmp("repoRmButton").setDisabled(false);
				if (state.clientConfig.enableRepositoryArchive)
					Ext.getCmp("repoArchiveButton").setDisabled(false)
			}
		},
		resetPanel : function () {
			Ext.getCmp("repoRmButton").setDisabled(true);
			if (state.clientConfig.enableRepositoryArchive) {
				var archiveBt = Ext.getCmp("repoArchiveButton");
				archiveBt.setText(this.archiveText);
				archiveBt.setDisabled(true)
			}
			this.getGrid().getSelectionModel().clearSelections();
			Sonia.repository.setEditPanel(Sonia.repository.DefaultPanel)
		},
		showAddForm : function () {
			Ext.getCmp("repoRmButton").setDisabled(true);
			Sonia.repository.setEditPanel([{
						xtype : "repositorySettingsForm",
						listeners : {
							updated : {
								fn : this.reload,
								scope : this
							},
							created : {
								fn : this.repositoryCreated,
								scope : this
							}
						}
					}
				])
		},
		repositoryCreated : function (item) {
			var grid = this.getGrid();
			grid.reload(function () {
				if (debug)
					console.debug("select repository " + item.id + " after creation");
				grid.selectById(item.id)
			})
		},
		clearRepositoryFilter : function (grid) {
			if (debug)
				console.debug("clear repository filter");
			if (!grid)
				grid = this.getGrid();
			Ext.getCmp("repositorySearch").setValue("");
			Ext.getCmp("repositoryTypeFilter").setValue("");
			grid.clearStoreFilter()
		},
		reload : function () {
			this.getGrid().reload();
			var repo = this.getSelectedRepository();
			if (repo)
				this.onRepositorySelection(repo,
					Sonia.repository.isOwner(repo))
		}
	});
Ext.reg("repositoryPanel", Sonia.repository.Panel);
Sonia.History.register("repositoryPanel", {
	onActivate : function (panel) {
		var token = null;
		var rec = panel.getGrid().getSelectionModel().getSelected();
		if (rec)
			token = Sonia.History.createToken("repositoryPanel", rec.get("id"));
		else
			token = Sonia.History.createToken("repositoryPanel");
		return token
	},
	waitAndSelect : function (grid, repoId) {
		setTimeout(function () {
			if (grid.ready)
				grid.selectById(repoId)
		}, 250)
	},
	onChange : function (repoId) {
		var panel = Ext.getCmp("repositories");
		if (!panel) {
			main.addRepositoriesTabPanel();
			panel = Ext.getCmp("repositories");
			if (repoId) {
				var selected = false;
				panel.getGrid().getStore().addListener("load", function () {
					if (!selected) {
						panel.getGrid().selectById(repoId);
						selected = true
					}
				})
			}
		} else {
			main.addTab(panel);
			if (repoId) {
				var grid = panel.getGrid();
				if (grid.ready)
					grid.selectById(repoId);
				else
					this.waitAndSelect(grid, repoId)
			}
		}
	}
});
Sonia.repository.PropertiesFormPanel = Ext.extend(Sonia.repository.FormPanel, {
		properties : [],
		initComponent : function () {
			var config = {
				listeners : {
					preUpdate : {
						fn : this.storeProperties,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.PropertiesFormPanel.superclass.initComponent.apply(this, arguments);
			this.loadProperties()
		},
		loadProperties : function () {
			this.properties[this.id] = [];
			this.items.each(function (field) {
				if (!Ext.isEmpty(field.property)) {
					this.properties[this.id].push({
						"name" : field.name,
						"property" : field.property
					});
					field.submitValue = false;
					for (var j in this.item.properties) {
						var property = this.item.properties[j];
						if (property.key === field.property)
							field.setValue(property.value)
					}
				}
			}, this);
			this.loadExtraProperties(this.item)
		},
		loadExtraProperties : function (item) {},
		storeProperties : function (item) {
			if (!item.properties)
				item.properties = [];
			else {
				var filtered = item.properties.filter(function (p) {
						var result = !Ext.isEmpty(p.key);
						if (result)
							for (var i in this.properties[this.id])
								if (p.key === this.properties[this.id][i].property) {
									result =
										false;
									break
								}
						return result
					}, this);
				item.properties = filtered
			}
			for (var k in this.properties[this.id]) {
				var property = this.properties[this.id][k];
				if (!Ext.isEmpty(property.name))
					item.properties.push({
						key : property.property,
						value : item[property.name]
					});
				delete item[property.name]
			}
			this.storeExtraProperties(item)
		},
		storeExtraProperties : function (item) {}

	});
Sonia.repository.ChangesetViewerGrid = Ext.extend(Ext.grid.GridPanel, {
		repository : null,
		mailTemplate : '\x26lt;\x3ca href\x3d"mailto:{0}"\x3e{0}\x3c/a\x3e\x26gt;',
		changesetMetadataTemplate : '\x3cdiv class\x3d"cs-desc"\x3e{0}\x3c/div\x3e                              \x3cdiv class\x3d"cs-author"\x3e{1}\x3c/div\x3e                              \x3cdiv class\x3d"cs-date"\x3e{2}\x3c/div\x3e',
		modificationsTemplate : '\x3cdiv class\x3d"cs-mod"\x3e                            \x3cimg src\x3d"resources/images/add.png" alt\x3d"Added"\x3e\x3cspan class\x3d"cs-mod-txt"\x3e{0}\x3c/span\x3e                            \x3cimg src\x3d"resources/images/modify.gif" alt\x3d"Modified"\x3e\x3cspan class\x3d"cs-mod-txt"\x3e{1}\x3c/span\x3e                            \x3cimg src\x3d"resources/images/delete.png" alt\x3d"Deleted"\x3e\x3cspan class\x3d"cs-mod-txt"\x3e{2}\x3c/span\x3e                          \x3c/div\x3e',
		idsTemplate : new Ext.XTemplate('\x3cdiv class\x3d"cs-commit"\x3e提交: \x3ca class\x3d"scm-link cs-diff-link" rel\x3d"{id}"\x3e{id:id}\x3c/a\x3e\x3c/div\x3e                \x3cdiv class\x3d"cs-tree"\x3e源码: \x3ca class\x3d"scm-link cs-tree-link" rel\x3d"{id}"\x3e{id:id}\x3c/a\x3e\x3c/div\x3e                \x3ctpl if\x3d"parent"\x3e\x3cdiv class\x3d"cs-parent"\x3e父支: \x3ca class\x3d"scm-link cs-diff-link" rel\x3d"{parent}"\x3e{parent:id}\x3c/a\x3e\x3c/div\x3e\x3c/tpl\x3e                \x3ctpl if\x3d"parent2"\x3e\x3cdiv class\x3d"cs-parent"\x3e父支: \x3ca class\x3d"scm-link cs-diff-link" rel\x3d"{parent2}"\x3e{parent2:id}\x3c/a\x3e\x3c/div\x3e\x3c/tpl\x3e'),
		tagsAndBranchesTemplate : new Ext.XTemplate('\x3cdiv class\x3d"changeset-tags"\x3e\x3ctpl if\x3d"tags"\x3e\x3ctpl for\x3d"tags"\x3e\x3cspan class\x3d"cs-tag"\x3e\x3ca title\x3d"标签 {.}"\x3e{.}\x3c/a\x3e\x3c/span\x3e\x3c/tpl\x3e\x3c/tpl\x3e\x3c/div\x3e                            \x3cdiv class\x3d"changeset-branches"\x3e\x3ctpl if\x3d"branches"\x3e\x3ctpl for\x3d"branches"\x3e\x3cspan class\x3d"cs-branch"\x3e\x3ca title\x3d"分支 {.}"\x3e{.}\x3c/a\x3e\x3c/span\x3e\x3c/tpl\x3e\x3c/tpl\x3e\x3c/div\x3e'),
		emptyText : "No commits available",
		initComponent : function () {
			var changesetColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : false
					},
					columns : [{
							id : "metadata",
							dataIndex : "author",
							renderer : this.renderChangesetMetadata,
							scope : this
						}, {
							id : "tagsAndBranches",
							renderer : this.renderTagsAndBranches,
							scope : this
						}, {
							id : "modifications",
							dataIndex : "modifications",
							renderer : this.renderModifications,
							scope : this,
							width : 120
						}, {
							id : "ids",
							dataIndex : "id",
							renderer : this.renderIds,
							scope : this,
							width : 180
						}
					]
				});
			var config = {
				header : false,
				autoScroll : true,
				autoExpandColumn : "metadata",
				autoHeight : true,
				hideHeaders : true,
				colModel : changesetColModel,
				loadMask : true,
				viewConfig : {
					deferEmptyText : false,
					emptyText : this.emptyText
				},
				listeners : {
					click : {
						fn : this.onClick,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.ChangesetViewerGrid.superclass.initComponent.apply(this, arguments)
		},
		getRevision : function (el) {
			var revision = el.rel;
			var index = revision.indexOf(":");
			if (index >= 0)
				revision = revision.substr(index + 1);
			return revision
		},
		onClick : function (e) {
			var el =
				e.getTarget(".cs-tree-link");
			var revision = null;
			if (el) {
				revision = this.getRevision(el);
				if (debug)
					console.debug("load repositorybrowser for " + revision);
				this.openRepositoryBrowser(revision)
			} else {
				el = e.getTarget(".cs-diff-link");
				if (el) {
					revision = this.getRevision(el);
					if (debug)
						console.debug("load diff for " + revision);
					this.openChangeset(revision)
				}
			}
		},
		openChangeset : function (revision) {
			main.addTab({
				id : "changesetPanel;" + this.repository.id + ";" + revision,
				xtype : "changesetPanel",
				repository : this.repository,
				revision : revision,
				closable : true
			})
		},
		openRepositoryBrowser : function (revision) {
			main.addTab({
				id : "repositoryBrowser;" + this.repository.id + ";" + revision,
				xtype : "repositoryBrowser",
				repository : this.repository,
				revision : revision,
				closable : true
			})
		},
		renderChangesetMetadata : function (author, p, record) {
			var authorValue = "";
			if (author) {
				authorValue = author.name;
				if (author.mail)
					authorValue += " " + String.format(this.mailTemplate, author.mail)
			}
			var description = record.data.description;
			if (description) {
				var index = description.indexOf("\n");
				if (index > 0)
					description =
						description.substring(0, index) + " ..."
			}
			var date = record.data.date;
			if (date)
				date = Ext.util.Format.formatTimestamp(date);
			return String.format(this.changesetMetadataTemplate, description, authorValue, date)
		},
		renderTagsAndBranches : function (value, p, record) {
			return this.tagsAndBranchesTemplate.apply({
				tags : record.get("tags"),
				branches : record.get("branches")
			})
		},
		getLabeledValue : function (label, array) {
			var result = "";
			if (array && array.length > 0)
				result = label + ": " + Sonia.util.getStringFromArray(array);
			return result
		},
		getChangesetId : function (id,
			record) {
			return id
		},
		getParentIds : function (id, record) {
			return record.get("parents")
		},
		renderIds : function (value, p, record) {
			var parents = this.getParentIds(value, record);
			var parent1 = null;
			var parent2 = null;
			if (parents) {
				parent1 = parents[0];
				if (parents.length > 1)
					parent2 = parents[1]
			}
			return this.idsTemplate.apply({
				id : this.getChangesetId(value, record),
				parent : parent1,
				parent2 : parent2
			})
		},
		renderModifications : function (value) {
			var added = 0;
			var modified = 0;
			var removed = 0;
			if (Ext.isDefined(value)) {
				if (Ext.isDefined(value.added))
					added =
						value.added.length;
				if (Ext.isDefined(value.modified))
					modified = value.modified.length;
				if (Ext.isDefined(value.removed))
					removed = value.removed.length
			}
			return String.format(this.modificationsTemplate, added, modified, removed)
		}
	});
Ext.reg("repositoryChangesetViewerGrid", Sonia.repository.ChangesetViewerGrid);
Sonia.repository.ChangesetViewerPanel = Ext.extend(Ext.Panel, {
		repository : null,
		start : 0,
		pageSize : 20,
		changesetStore : null,
		startLimit : null,
		inline : false,
		path : null,
		revision : null,
		changesetViewerTitleText : "Commits {0}",
		initComponent : function () {
			if (!this.url)
				this.url = restUrl + "repositories/" + this.repository.id + "/changesets.json";
			if (!this.startLimit)
				this.startLimit = this.pageSize;
			var params = {
				start : this.start,
				limit : this.startLimit
			};
			var baseParams = {};
			if (this.path)
				baseParams.path = this.path;
			if (this.revision)
				baseParams.revision =
					this.revision;
			this.changesetStore = new Sonia.rest.JsonStore({
					id : "changesetStore",
					proxy : new Ext.data.HttpProxy({
						url : this.url,
						method : "GET"
					}),
					fields : ["id", "date", "author", "description", "parents", "modifications", "tags", "branches", "properties"],
					root : "changesets",
					idProperty : "id",
					totalProperty : "total",
					baseParams : baseParams,
					autoLoad : {
						params : params
					},
					autoDestroy : true,
					listeners : {
						load : {
							fn : this.updateHistory,
							scope : this
						}
					}
				});
			var config = {
				items : [{
						xtype : "repositoryChangesetViewerGrid",
						repository : this.repository,
						store : this.changesetStore
					}
				]
			};
			if (!this.inline) {
				config.title = String.format(this.changesetViewerTitleText, this.repository.name);
				var type = Sonia.repository.getTypeByName(this.repository.type);
				if (type && type.supportedCommands && type.supportedCommands.indexOf("BRANCHES") >= 0)
					config.tbar = this.createTopToolbar();
				config.bbar = {
					xtype : "paging",
					store : this.changesetStore,
					displayInfo : true,
					pageSize : this.pageSize,
					prependButtons : true
				}
			}
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.ChangesetViewerPanel.superclass.initComponent.apply(this,
				arguments)
		},
		createTopToolbar : function () {
			var branchStore = new Sonia.rest.JsonStore({
					proxy : new Ext.data.HttpProxy({
						url : restUrl + "repositories/" + this.repository.id + "/branches.json",
						method : "GET",
						disableCaching : false
					}),
					root : "branch",
					idProperty : "name",
					fields : ["name"],
					sortInfo : {
						field : "name"
					}
				});
			return {
				xtype : "toolbar",
				items : [this.repository.name, "-\x3e", "分支", " ", {
						xtype : "combo",
						valueField : "name",
						displayField : "name",
						typeAhead : false,
						editable : false,
						triggerAction : "all",
						store : branchStore,
						listeners : {
							select : {
								fn : this.selectBranch,
								scope : this
							}
						}
					}
				]
			}
		},
		selectBranch : function (combo, rec) {
			var branch = rec.get("name");
			if (debug)
				console.debug("select branch " + branch);
			this.changesetStore.baseParams.branch = branch;
			this.start = 0;
			this.changesetStore.load({
				params : {
					start : this.start,
					limit : this.startLimit
				}
			})
		},
		updateHistory : function (store, records, options) {
			if (!this.inline && options && options.params) {
				this.start = options.params.start;
				this.pageSize = options.params.limit;
				var token = Sonia.History.createToken("repositoryChangesetViewerPanel", this.repository.id,
						this.start, this.pageSize);
				Sonia.History.add(token)
			}
		},
		loadChangesets : function (start, limit) {
			this.changesetStore.load({
				params : {
					start : start,
					limit : limit
				}
			})
		}
	});
Ext.reg("repositoryChangesetViewerPanel", Sonia.repository.ChangesetViewerPanel);
Sonia.History.register("repositoryChangesetViewerPanel", {
	onActivate : function (panel) {
		return Sonia.History.createToken("repositoryChangesetViewerPanel", panel.repository.id, panel.start, panel.pageSize)
	},
	onChange : function (repoId, start, limit) {
		if (start)
			start = parseInt(start);
		if (limit)
			limit = parseInt(limit);
		var id = "repositoryChangesetViewerPanel;" + repoId;
		Sonia.repository.get(repoId, function (repository) {
			var panel = Ext.getCmp(id);
			if (!panel)
				panel = {
					id : id,
					xtype : "repositoryChangesetViewerPanel",
					repository : repository,
					start : start,
					pageSize : limit,
					closable : true,
					autoScroll : true
				};
			else
				panel.loadChangesets(start, limit);
			main.addTab(panel)
		})
	}
});
Sonia.repository.BlamePanel = Ext.extend(Ext.grid.GridPanel, {
		blameUrl : null,
		repository : null,
		path : null,
		revision : null,
		linkTemplate : '\x3ca class\x3d"scm-link blame-link" rel\x3d"{1}"\x3e{0}\x3c/a\x3e',
		initComponent : function () {
			var blameUrl = restUrl + "repositories/" + this.repository.id + "/";
			blameUrl += "blame.json?path\x3d" + this.path;
			if (this.revision)
				blameUrl += "\x26revision\x3d" + this.revision;
			var blameStore = new Sonia.rest.JsonStore({
					proxy : new Ext.data.HttpProxy({
						url : blameUrl,
						disableCaching : false
					}),
					root : "blamelines",
					idProperty : "lineNumber",
					fields : ["lineNumber", "author", "revision", "when", "description", "code"],
					sortInfo : {
						field : "lineNumber"
					}
				});
			var blameColModel = new Ext.grid.ColumnModel({
					columns : [{
							id : "revision",
							dataIndex : "revision",
							renderer : this.renderRevision,
							width : 20,
							scope : this
						}, {
							id : "code",
							dataIndex : "code",
							renderer : this.renderCode,
							width : 400
						}
					]
				});
			var config = {
				hideHeaders : true,
				autoExpandColumn : "code",
				store : blameStore,
				colModel : blameColModel,
				stripeRows : false,
				autoHeight : true,
				viewConfig : {
					forceFit : true
				},
				listeners : {
					click : {
						fn : this.onClick,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.BlamePanel.superclass.initComponent.apply(this, arguments)
		},
		onClick : function (e) {
			var el = e.getTarget(".blame-link");
			if (el) {
				var revision = el.rel;
				if (debug)
					console.debug("load content for " + revision);
				this.openContentPanel(revision)
			}
		},
		openContentPanel : function (revision) {
			var id = Sonia.repository.createContentId(this.repository, this.path, revision);
			main.addTab({
				id : id,
				xtype : "contentPanel",
				repository : this.repository,
				revision : revision,
				path : this.path,
				closable : true,
				autoScroll : true
			})
		},
		renderRevision : function (value, metadata, record) {
			var shortId = Ext.util.Format.id(value);
			var title = "版本: " + shortId;
			var tip = "作者: " + record.get("author").name;
			var when = record.get("when");
			if (when)
				tip += "\x3cbr /\x3e时间: " + Ext.util.Format.formatTimestamp(when);
			var description = record.get("description");
			if (description)
				tip += "\x3cbr /\x3e信息: " + description;
			metadata.attr = 'ext:qtitle\x3d"' + title + '"' + ' ext:qtip\x3d"' + tip + '"';
			return String.format(this.linkTemplate,
				shortId, value)
		},
		renderCode : function (value) {
			return "\x3cpre\x3e" + Ext.util.Format.htmlEncode(value) + "\x3c/pre\x3e"
		}
	});
Ext.reg("blamePanel", Sonia.repository.BlamePanel);
Sonia.repository.DiffPanel = Ext.extend(Ext.Panel, {
		repository : null,
		revision : null,
		diffUrl : null,
		initComponent : function () {
			this.diffUrl = restUrl + "repositories/" + this.repository.id;
			this.diffUrl += "/diff?revision\x3d" + this.revision;
			var config = {
				title : "Diff " + this.revision,
				autoScroll : true,
				tbar : [{
						text : "Raw",
						handler : this.downlaodFile,
						scope : this
					}
				],
				bbar : ["-\x3e", this.repository.name, ":", this.revision],
				items : [{
						id : "diff-" + this.repository.id + ":" + this.revision,
						xtype : "syntaxHighlighterPanel",
						syntax : "diff",
						contentUrl : this.diffUrl
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.DiffPanel.superclass.initComponent.apply(this, arguments)
		},
		downlaodFile : function () {
			window.open(this.diffUrl)
		}
	});
Ext.reg("diffPanel", Sonia.repository.DiffPanel);
Sonia.History.register("diffPanel", {
	onActivate : function (panel) {
		return Sonia.History.createToken("diffPanel", panel.repository.id, panel.revision)
	},
	onChange : function (repoId, revision) {
		var id = "diffPanel;" + repoId + ";" + revision;
		Sonia.repository.get(repoId, function (repository) {
			var panel = Ext.getCmp(id);
			if (!panel)
				panel = {
					id : id,
					xtype : "diffPanel",
					repository : repository,
					revision : revision,
					closable : true,
					autoScroll : true
				};
			main.addTab(panel)
		})
	}
});
Sonia.repository.ContentPanel = Ext.extend(Ext.Panel, {
		repository : null,
		revision : null,
		path : null,
		contentUrl : null,
		view : "content",
		initComponent : function () {
			var name = Sonia.util.getName(this.path);
			this.contentUrl = Sonia.repository.createContentUrl(this.repository, this.path, this.revision);
			var bottomBar = [this.path];
			this.appendRepositoryProperties(bottomBar);
			var panel = null;
			switch (this.view) {
			case "blame":
				panel = this.createBlamePanel();
				break;
			case "history":
				panel = this.createHistoryPanel();
				break;
			default:
				panel = this.createSyntaxPanel()
			}
			var config = {
				title : name,
				tbar : [{
						text : "默认",
						handler : this.openSyntaxPanel,
						scope : this
					}, {
						text : "原始文件",
						handler : this.downlaodFile,
						scope : this
					}, {
						text : "归属",
						handler : this.openBlamePanel,
						scope : this
					}, {
						text : "历史",
						handler : this.openHistoryPanel,
						scope : this
					}
				],
				bbar : bottomBar,
				items : [panel]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.ContentPanel.superclass.initComponent.apply(this, arguments)
		},
		loadPanel : function (view) {
			switch (view) {
			case "blame":
				this.openBlamePanel();
				break;
			case "history":
				this.openHistoryPanel();
				break;
			default:
				this.openSyntaxPanel()
			}
		},
		createHistoryPanel : function () {
			return {
				xtype : "repositoryChangesetViewerPanel",
				repository : this.repository,
				revision : this.revision,
				path : this.path,
				inline : true,
				pageSize : 9999,
				startLimit : -1
			}
		},
		openHistoryPanel : function () {
			this.openPanel(this.createHistoryPanel());
			this.view = "history";
			this.updateHistory()
		},
		createSyntaxPanel : function () {
			return {
				xtype : "syntaxHighlighterPanel",
				syntax : Sonia.util.getExtension(this.path),
				contentUrl : this.contentUrl
			}
		},
		openSyntaxPanel : function () {
			this.openPanel(this.createSyntaxPanel());
			this.view = "content";
			this.updateHistory()
		},
		createBlamePanel : function () {
			return {
				xtype : "blamePanel",
				repository : this.repository,
				revision : this.revision,
				path : this.path
			}
		},
		openBlamePanel : function () {
			this.openPanel(this.createBlamePanel());
			this.view = "blame";
			this.updateHistory()
		},
		updateHistory : function () {
			var token = Sonia.History.createToken("contentPanel", this.repository.id, this.revision, this.path, this.view);
			Sonia.History.add(token)
		},
		downlaodFile : function () {
			window.open(this.contentUrl)
		},
		openPanel : function (panel) {
			this.removeAll();
			this.add(panel);
			this.doLayout()
		},
		appendRepositoryProperties : function (bar) {
			bar.push("-\x3e", this.repository.name);
			if (this.revision)
				bar.push(": ", this.revision)
		},
		getExtension : function (path) {
			var ext = null;
			var index = path.lastIndexOf(".");
			if (index > 0)
				ext = path.substr(index + 1, path.length);
			return ext
		}
	});
Ext.reg("contentPanel", Sonia.repository.ContentPanel);
Sonia.History.register("contentPanel", {
	onActivate : function (panel) {
		return Sonia.History.createToken("contentPanel", panel.repository.id, panel.revision, panel.path, panel.view)
	},
	onChange : function (repoId, revision, path, view) {
		if (revision === "null")
			revision = null;
		if (!view || view === "null")
			view = "content";
		var id = "contentPanel;" + repoId + ";" + revision + ";" + path;
		Sonia.repository.get(repoId, function (repository) {
			var panel = Ext.getCmp(id);
			if (!panel)
				panel = {
					id : id,
					xtype : "contentPanel",
					repository : repository,
					revision : revision,
					path : path,
					view : view,
					closable : true,
					autoScroll : true
				};
			else
				panel.loadPanel(view);
			main.addTab(panel)
		})
	}
});
Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, {
		repository : null,
		revision : null,
		path : null,
		repositoryBrowserTitleText : "Source {0}",
		colNameText : "Name",
		colLengthText : "Length",
		colLastModifiedText : "Last Modified",
		colDescriptionText : "Description",
		iconFolder : "resources/images/folder.png",
		iconDocument : "resources/images/document.png",
		iconSubRepository : "resources/images/folder-remote.png",
		templateIcon : '\x3cimg src\x3d"{0}" alt\x3d"{1}" title\x3d"{2}" /\x3e',
		templateInternalLink : '\x3ca class\x3d"scm-browser" rel\x3d"{1}"\x3e{0}\x3c/a\x3e',
		templateExternalLink : '\x3ca class\x3d"scm-browser" href\x3d"{1}" target\x3d"_blank"\x3e{0}\x3c/a\x3e',
		emptyText : "This directory is empty",
		initComponent : function () {
			if (debug)
				console.debug("create new browser for repository " + this.repository.name + " and revision " + this.revision);
			var browserStore = new Sonia.rest.JsonStore({
					proxy : new Ext.data.HttpProxy({
						url : restUrl + "repositories/" + this.repository.id + "/browse.json",
						method : "GET"
					}),
					fields : ["path", "name", "length", "lastModified", "directory", "description", "subrepository"],
					root : "files",
					idProperty : "path",
					autoLoad : true,
					autoDestroy : true
				});
			browserStore.addListener("load", this.loadStore, this);
			if (this.revision)
				browserStore.baseParams = {
					revision : this.revision
				};
			if (this.path)
				browserStore.baseParams = {
					path : this.path
				};
			var browserColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : false
					},
					columns : [{
							id : "icon",
							dataIndex : "directory",
							header : "",
							width : 28,
							renderer : this.renderIcon,
							scope : this
						}, {
							id : "name",
							dataIndex : "name",
							header : this.colNameText,
							renderer : this.renderName,
							scope : this,
							width : 180
						}, {
							id : "length",
							dataIndex : "length",
							header : this.colLengthText,
							renderer : this.renderLength
						}, {
							id : "lastModified",
							dataIndex : "lastModified",
							header : this.colLastModifiedText,
							renderer : Ext.util.Format.formatTimestamp
						}, {
							id : "description",
							dataIndex : "description",
							header : this.colDescriptionText
						}, {
							id : "subrepository",
							dataIndex : "subrepository",
							hidden : true
						}
					]
				});
			var bar = [this.createFolderButton("", "")];
			this.appendRepositoryProperties(bar);
			var config = {
				bbar : bar,
				autoExpandColumn : "description",
				title : String.format(this.repositoryBrowserTitleText,
					this.repository.name),
				store : browserStore,
				colModel : browserColModel,
				loadMask : true,
				viewConfig : {
					deferEmptyText : false,
					emptyText : this.emptyText
				},
				listeners : {
					click : {
						fn : this.onClick,
						scope : this
					}
				}
			};
			config.tbar = this.createTopToolbar();
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.RepositoryBrowser.superclass.initComponent.apply(this, arguments)
		},
		createTopToolbar : function () {
			var items = [this.repository.name];
			var type = Sonia.repository.getTypeByName(this.repository.type);
			var branches = false;
			if (type && type.supportedCommands && type.supportedCommands.indexOf("BRANCHES") >= 0) {
				branches = true;
				var branchStore = new Sonia.rest.JsonStore({
						proxy : new Ext.data.HttpProxy({
							url : restUrl + "repositories/" + this.repository.id + "/branches.json",
							method : "GET",
							disableCaching : false
						}),
						root : "branch",
						idProperty : "name",
						fields : ["name", "revision"]
					});
				items.push("-\x3e", "分支", " ", {
					id : "branchComboBox",
					xtype : "combo",
					valueField : "revision",
					displayField : "name",
					typeAhead : false,
					editable : false,
					triggerAction : "all",
					store : branchStore,
					listeners : {
						select : {
							fn : this.selectBranch,
							scope : this
						}
					}
				})
			}
			if (type && type.supportedCommands && type.supportedCommands.indexOf("TAGS") >= 0) {
				var tagStore = new Sonia.rest.JsonStore({
						proxy : new Ext.data.HttpProxy({
							url : restUrl + "repositories/" + this.repository.id + "/tags.json",
							method : "GET",
							disableCaching : false
						}),
						root : "tag",
						idProperty : "name",
						fields : ["name", "revision"]
					});
				if (branches)
					items.push(" ");
				else
					items.push("-\x3e");
				items.push("标签", " ", {
					id : "tagComboBox",
					xtype : "combo",
					valueField : "revision",
					displayField : "name",
					typeAhead : false,
					editable : false,
					triggerAction : "all",
					store : tagStore,
					listeners : {
						select : {
							fn : this.selectTag,
							scope : this
						}
					}
				})
			}
			var tbar = {
				xtype : "toolbar",
				items : [items]
			};
			return tbar
		},
		selectBranch : function (combo, rec) {
			this.selectRev(rec, Ext.getCmp("tagComboBox"))
		},
		selectTag : function (combo, rec) {
			this.selectRev(rec, Ext.getCmp("branchComboBox"))
		},
		selectRev : function (rec, comboToClear) {
			var tag = rec.get("name");
			if (debug)
				console.debug("select rev " + tag);
			this.revision = rec.get("revision");
			this.getStore().load({
				params : {
					revision : this.revision,
					path : this.path
				}
			});
			this.reRenderBottomBar(this.path);
			this.updateHistory();
			if (comboToClear)
				comboToClear.clearValue()
		},
		loadStore : function (store, records, extra) {
			var path = extra.params.path;
			if (path && path.length > 0) {
				var index = path.lastIndexOf("/");
				if (index > 0)
					path = path.substr(0, index);
				else
					path = "";
				var File = Ext.data.Record.create([{
								name : "name"
							}, {
								name : "path"
							}, {
								name : "directory"
							}, {
								name : "length"
							}, {
								name : "lastModified"
							}
						]);
				store.insert(0, new File({
						name : "..",
						path : path,
						directory : true,
						length : 0
					}))
			}
		},
		onClick : function (e) {
			var el =
				e.getTarget(".scm-browser");
			if (el) {
				var rel = el.rel;
				var index = rel.indexOf(":");
				if (index > 0) {
					var prefix = rel.substring(0, index);
					var path = rel.substring(index + 1);
					if (prefix === "sub")
						this.openSubRepository(path);
					else if (prefix === "dir")
						this.changeDirectory(path);
					else
						this.openFile(path)
				}
			}
		},
		openSubRepository : function (subRepository) {
			if (debug)
				console.debug("open sub repository " + subRepository);
			var revision = null;
			var index = subRepository.indexOf(";");
			if (index > 0) {
				revision = subRepository.substring(index + 1);
				subRepository =
					subRepository.substring(0, index)
			}
			var id = "repositoryBrowser;" + subRepository + ";" + revision + ";null";
			Sonia.repository.get(subRepository, function (repository) {
				var panel = Ext.getCmp(id);
				if (!panel)
					panel = {
						id : id,
						xtype : "repositoryBrowser",
						repository : repository,
						revision : revision,
						closable : true,
						autoScroll : true
					};
				main.addTab(panel)
			})
		},
		appendRepositoryProperties : function (bar) {
			bar.push("-\x3e", this.repository.name);
			if (this.revision)
				bar.push(": ", this.revision)
		},
		openFile : function (path) {
			Sonia.repository.openFile(this.repository,
				path, this.revision)
		},
		changeDirectory : function (path) {
			if (path.substr(-1) === "/")
				path = path.substr(0, path.length - 1);
			if (debug)
				console.debug("change directory: " + path);
			var params = {
				path : path
			};
			if (this.revision)
				params.revision = this.revision;
			this.getStore().load({
				params : params
			});
			this.path = path;
			this.updateHistory();
			this.reRenderBottomBar(path)
		},
		updateHistory : function () {
			var token = Sonia.History.createToken("repositoryBrowser", this.repository.id, this.revision, this.path);
			Sonia.History.add(token)
		},
		createFolderButton : function (path,
			name) {
			return {
				xtype : "button",
				icon : this.iconFolder,
				text : name + "/",
				handler : this.changeDirectory.createDelegate(this, [path])
			}
		},
		renderClickPath : function (path) {
			this.reRenderBottomBar(path)
		},
		reRenderBottomBar : function (path) {
			var bbar = this.getBottomToolbar();
			bbar.removeAll();
			var parts;
			if (path)
				parts = path.split("/");
			else
				parts = [];
			var currentPath = "";
			var items = [this.createFolderButton(currentPath, "")];
			if (path !== "")
				for (var i = 0; i < parts.length; i++) {
					currentPath += parts[i] + "/";
					items.push(this.createFolderButton(currentPath,
							parts[i]))
				}
			items.push("-\x3e", this.repository.name);
			if (this.revision)
				items.push(":", this.revision);
			bbar.add(items);
			bbar.doLayout()
		},
		getRepositoryPath : function (url) {
			var ctxPath = Sonia.util.getContextPath();
			var i = url.indexOf(ctxPath);
			if (i > 0)
				url = url.substring(i + ctxPath.length);
			if (url.indexOf("/") === 0)
				url = url.substring(1);
			return url
		},
		transformLink : function (url, revision) {
			var link = null;
			var server = Sonia.util.getServername(url);
			if (server === window.location.hostname || server === "localhost") {
				var repositoryPath =
					this.getRepositoryPath(url);
				if (repositoryPath) {
					link = "sub:" + repositoryPath;
					if (revision)
						link += ";" + revision
				}
			}
			return link
		},
		renderLink : function (text, record) {
			var subRepository = record.get("subrepository");
			var folder = record.get("directory");
			var path = null;
			var template = null;
			if (subRepository) {
				var subRepositoryUrl = subRepository["browser-url"];
				if (!subRepositoryUrl)
					subRepositoryUrl = subRepository["repository-url"];
				path = this.transformLink(subRepositoryUrl, subRepository["revision"]);
				if (path)
					template = this.templateInternalLink;
				else {
					path = subRepositoryUrl;
					template = this.templateExternalLink
				}
			} else {
				if (folder)
					path = "dir:";
				else
					path = "file:";
				path += record.get("path");
				template = this.templateInternalLink
			}
			return String.format(template, text, path)
		},
		renderName : function (name, p, record) {
			return this.renderLink(name, record)
		},
		renderIcon : function (directory, p, record) {
			var icon = null;
			var subRepository = record.get("subrepository");
			var name = record.get("name");
			if (subRepository)
				icon = this.iconSubRepository;
			else if (directory)
				icon = this.iconFolder;
			else
				icon =
					this.iconDocument;
			var img = String.format(this.templateIcon, icon, name, name);
			return this.renderLink(img, record)
		},
		renderLength : function (length, p, record) {
			var result = "";
			var directory = record.data.directory;
			if (!directory)
				result = Ext.util.Format.fileSize(length);
			return result
		}
	});
Ext.reg("repositoryBrowser", Sonia.repository.RepositoryBrowser);
Sonia.History.register("repositoryBrowser", {
	onActivate : function (panel) {
		return Sonia.History.createToken("repositoryBrowser", panel.repository.id, panel.revision, panel.path)
	},
	onChange : function (repoId, revision, path) {
		if (revision === "null")
			revision = null;
		if (path === "null")
			path = "";
		var id = "repositoryBrowser;" + repoId + ";" + revision;
		Sonia.repository.get(repoId, function (repository) {
			var panel = Ext.getCmp(id);
			if (!panel) {
				panel = {
					id : id,
					xtype : "repositoryBrowser",
					repository : repository,
					revision : revision,
					closable : true,
					autoScroll : true
				};
				if (path)
					panel.path = path
			} else
				panel.changeDirectory(path);
			main.addTab(panel)
		})
	}
});
Sonia.repository.ImportWindow = Ext.extend(Ext.Window, {
		title : "Repository Import Wizard",
		initComponent : function () {
			this.addEvents("finish");
			var config = {
				title : this.title,
				layout : "fit",
				width : 420,
				height : 190,
				closable : true,
				resizable : true,
				plain : true,
				border : false,
				modal : true,
				bodyCssClass : "x-panel-mc",
				items : [{
						id : "scmRepositoryImportWizard",
						xtype : "scmRepositoryImportWizard",
						listeners : {
							finish : {
								fn : this.onFinish,
								scope : this
							}
						}
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.ImportWindow.superclass.initComponent.apply(this,
				arguments)
		},
		onFinish : function (config) {
			this.fireEvent("finish", config);
			this.close()
		}
	});
Sonia.repository.ImportPanel = Ext.extend(Ext.Panel, {
		backText : "Back",
		nextText : "Next",
		closeBtnText : "Close",
		imported : [],
		failed : [],
		importTypeDirectoryHelpText : "Imports all repositories that are located at the repository folder of SCM-Manager.",
		importTypeURLHelpText : "Imports a repository from a remote url.",
		importTypeFileHelpText : "Imports a repository from a file (e.g. SVN dump).",
		importUrlNameHelpText : "The name of the repository in SCM-Manager.",
		importUrlHelpText : "The source url of the repository.",
		importFileNameHelpText : "The name of the repository in SCM-Manager.",
		importFileHelpText : "Choose the dump file you want to import to SCM-Manager.",
		importFileGZipCompressedHelpText : "The file is gzip compressed.",
		tipRepositoryType : "Choose your repository type for the import.",
		tipImportType : "Select the type of import. \x3cb\x3eNote:\x3c/b\x3e Not all repository types support all options.",
		nextButton : null,
		prevButton : null,
		repositoryType : null,
		activeForm : null,
		tpl : new Ext.XTemplate(['\x3cp style\x3d"padding: 0 10px"\x3e', '  \x3ctpl if\x3d"imported"\x3e', "    \x3cb\x3eImported repositories\x3c/b\x3e\x3cbr /\x3e",
				'    \x3ctpl for\x3d"imported"\x3e', "      - {.}\x3cbr /\x3e", "    \x3c/tpl\x3e", "    \x3cbr /\x3e", "  \x3c/tpl\x3e", '  \x3ctpl if\x3d"failed"\x3e', "    \x3cb\x3eFailed to import the following directories\x3c/b\x3e\x3cbr /\x3e", '    \x3ctpl for\x3d"failed"\x3e', "      - {.}\x3cbr /\x3e", "    \x3c/tpl\x3e", "  \x3c/tpl\x3e", '  \x3ctpl if\x3d"isEmpty(imported, failed)"\x3e', "    \x3cb\x3eNo repositories to import\x3c/b\x3e", "  \x3c/tpl\x3e", "\x3c/p\x3e", "\x3cbr /\x3e"]),
		initComponent : function () {
			this.addEvents("finish");
			this.imported = [];
			this.failed = [];
			this.activeForm = null;
			var typeItems = [];
			Ext.each(state.repositoryTypes, function (repositoryType) {
				typeItems.push({
					boxLabel : repositoryType.displayName,
					name : "repositoryType",
					inputValue : repositoryType.name,
					checked : false
				})
			});
			typeItems = typeItems.sort(function (a, b) {
					return a.boxLabel > b.boxLabel
				});
			typeItems.push({
				xtype : "scmTip",
				content : this.tipRepositoryType,
				width : "100%"
			});
			var config = {
				layout : "card",
				activeItem : 0,
				bodyStyle : "padding: 5px",
				defaults : {
					bodyCssClass : "x-panel-mc",
					border : false,
					labelWidth : 120,
					width : 250
				},
				bbar : ["-\x3e", {
						id : "move-prev",
						text : this.backText,
						handler : this.navHandler.createDelegate(this, [-1]),
						disabled : true,
						scope : this
					}, {
						id : "move-next",
						text : this.nextText,
						handler : this.navHandler.createDelegate(this, [1]),
						disabled : true,
						scope : this
					}, {
						id : "closeBtn",
						text : this.closeBtnText,
						handler : this.applyChanges,
						disabled : true,
						scope : this
					}
				],
				items : [{
						id : "repositoryTypeLayout",
						items : [{
								id : "chooseRepositoryType",
								xtype : "radiogroup",
								name : "chooseRepositoryType",
								columns : 1,
								items : [typeItems],
								listeners : {
									change : {
										fn : function () {
											this.getNextButton().setDisabled(false)
										},
										scope : this
									}
								}
							}
						]
					}, {
						id : "importTypeLayout",
						items : [{
								id : "chooseImportType",
								xtype : "radiogroup",
								name : "chooseImportType",
								columns : 1,
								items : [{
										id : "importTypeDirectory",
										boxLabel : "从目录导入",
										name : "importType",
										inputValue : "directory",
										disabled : false,
										helpText : this.importTypeDirectoryHelpText
									}, {
										id : "importTypeURL",
										boxLabel : "从URL导入",
										name : "importType",
										inputValue : "url",
										checked : false,
										disabled : true,
										helpText : this.importTypeURLHelpText
									}, {
										id : "importTypeFile",
										boxLabel : "从文件导入",
										name : "importType",
										inputValue : "file",
										checked : false,
										disabled : true,
										helpText : this.importTypeFileHelpText
									}, {
										xtype : "scmTip",
										content : this.tipImportType,
										width : "100%"
									}
								],
								listeners : {
									change : {
										fn : function () {
											this.getNextButton().setDisabled(false)
										},
										scope : this
									}
								}
							}
						]
					}, {
						id : "importUrlLayout",
						xtype : "form",
						monitorValid : true,
						defaults : {
							width : 250
						},
						listeners : {
							clientvalidation : {
								fn : this.urlFormValidityMonitor,
								scope : this
							}
						},
						items : [{
								id : "importUrlName",
								xtype : "textfield",
								fieldLabel : "Repository name",
								name : "name",
								allowBlank : false,
								vtype : "repositoryName",
								helpText : this.importUrlNameHelpText
							}, {
								id : "importUrl",
								xtype : "textfield",
								fieldLabel : "Import URL",
								name : "url",
								allowBlank : false,
								vtype : "url",
								helpText : this.importUrlHelpText
							}, {
								xtype : "scmTip",
								content : "Please insert name and remote url of the repository.",
								width : "100%"
							}
						]
					}, {
						id : "importFileLayout",
						xtype : "form",
						fileUpload : true,
						monitorValid : true,
						listeners : {
							clientvalidation : {
								fn : this.fileFormValidityMonitor,
								scope : this
							}
						},
						items : [{
								id : "importFileName",
								xtype : "textfield",
								fieldLabel : "Repository name",
								name : "name",
								type : "textfield",
								width : 250,
								allowBlank : false,
								vtype : "repositoryName",
								helpText : this.importFileNameHelpText
							}, {
								id : "importFile",
								xtype : "fileuploadfield",
								fieldLabel : "Import File",
								ctCls : "import-fu",
								name : "bundle",
								buttonText : "",
								allowBlank : false,
								helpText : this.importFileHelpText,
								cls : "import-fu",
								buttonCfg : {
									iconCls : "upload-icon"
								}
							}, {
								id : "importFileGZipCompressed",
								xtype : "checkbox",
								fieldLabel : "GZip compressed",
								helpText : this.importFileGZipCompressedHelpText
							}, {
								xtype : "scmTip",
								content : "Please insert name and upload the repository file.",
								width : "100%"
							}
						]
					}, {
						id : "importFinishedLayout",
						layout : "form",
						defaults : {
							width : 250
						},
						items : [{
								id : "resultPanel",
								xtype : "panel",
								bodyCssClass : "x-panel-mc",
								tpl : this.tpl
							}, {
								id : "finalTip",
								xtype : "scmTip",
								content : "Please see log for details.",
								width : "100%",
								hidden : true
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.ImportPanel.superclass.initComponent.apply(this, arguments)
		},
		navHandler : function (direction) {
			this.activeForm = null;
			var layout = this.getLayout();
			var id = layout.activeItem.id;
			var next =
				-1;
			if (id === "repositoryTypeLayout" && direction === 1) {
				this.repositoryType = Ext.getCmp("chooseRepositoryType").getValue().getRawValue();
				this.enableAvailableImportTypes();
				next = 1
			} else if (id === "importTypeLayout" && direction === -1) {
				next = 0;
				Ext.getCmp("move-prev").setDisabled(true);
				Ext.getCmp("move-next").setDisabled(false)
			} else if (id === "importTypeLayout" && direction === 1) {
				Ext.getCmp("move-next").setDisabled(false);
				var v = Ext.getCmp("chooseImportType").getValue();
				if (v)
					switch (v.getRawValue()) {
					case "directory":
						this.importFromDirectory(layout);
						break;
					case "url":
						next = 2;
						this.activeForm = "url";
						break;
					case "file":
						next = 3;
						this.activeForm = "file";
						break
					}
			} else if ((id === "importUrlLayout" || id === "importFileLayout") && direction === -1)
				next = 1;
			else if (id === "importUrlLayout" && direction === 1)
				this.importFromUrl(layout, Ext.getCmp("importUrlLayout").getForm().getValues());
			else if (id === "importFileLayout" && direction === 1)
				this.importFromFile(layout, Ext.getCmp("importFileLayout").getForm());
			if (next >= 0)
				layout.setActiveItem(next)
		},
		getNextButton : function () {
			if (!this.nextButton)
				this.nextButton =
					Ext.getCmp("move-next");
			return this.nextButton
		},
		getPrevButton : function () {
			if (!this.prevButton)
				this.prevButton = Ext.getCmp("move-prev");
			return this.prevButton
		},
		showLoadingBox : function () {
			return Ext.MessageBox.show({
				title : "Loading",
				msg : "Import repository",
				width : 300,
				wait : true,
				animate : true,
				progress : true,
				closable : false
			})
		},
		urlFormValidityMonitor : function (form, valid) {
			if (this.activeForm === "url")
				this.formValidityMonitor(valid)
		},
		fileFormValidityMonitor : function (form, valid) {
			if (this.activeForm === "file")
				this.formValidityMonitor(valid)
		},
		formValidityMonitor : function (valid) {
			var nbt = this.getNextButton();
			if (valid && nbt.disabled)
				nbt.setDisabled(false);
			else if (!valid && !nbt.disabled)
				nbt.setDisabled(true)
		},
		appendImportResult : function (layout, result) {
			for (var i = 0; i < result.importedDirectories.length; i++)
				this.imported.push(result.importedDirectories[i]);
			for (i = 0; i < result.failedDirectories.length; i++)
				this.failed.push(result.failedDirectories[i]);
			this.displayResult(layout)
		},
		appendImported : function (layout, name) {
			this.imported.push(name);
			this.displayResult(layout)
		},
		appendFailed : function (layout, name) {
			this.failed.push(name);
			this.displayResult(layout);
			layout.setActiveItem(4)
		},
		displayResult : function (layout) {
			this.getNextButton().setDisabled(true);
			this.getPrevButton().setDisabled(true);
			Ext.getCmp("closeBtn").setDisabled(false);
			var model = {
				imported : this.imported.length > 0 ? this.imported : null,
				failed : this.failed.length > 0 ? this.failed : null,
				isEmpty : function (imported, failed) {
					return !imported && !failed
				}
			};
			var resultPanel = Ext.getCmp("resultPanel");
			Ext.getCmp("finalTip").setVisible(this.failed.length >
				0);
			resultPanel.tpl.overwrite(resultPanel.body, model);
			layout.setActiveItem(4)
		},
		importFromFile : function (layout, form$$0) {
			var compressed = Ext.getCmp("importFileGZipCompressed").getValue();
			var lbox = this.showLoadingBox();
			form$$0.submit({
				url : restUrl + "import/repositories/" + this.repositoryType + "/bundle.html?compressed\x3d" + compressed,
				timeout : 3E5,
				scope : this,
				success : function (form) {
					lbox.hide();
					this.appendImported(layout, form.getValues().name)
				},
				failure : function (form) {
					lbox.hide();
					this.appendFailed(layout, form.getValues().name)
				}
			})
		},
		importFromUrl : function (layout, repository) {
			var lbox = this.showLoadingBox();
			Ext.Ajax.request({
				url : restUrl + "import/repositories/" + this.repositoryType + "/url.json",
				method : "POST",
				scope : this,
				timeout : 3E5,
				jsonData : repository,
				success : function () {
					lbox.hide();
					this.appendImported(layout, repository.name)
				},
				failure : function () {
					lbox.hide();
					this.appendFailed(layout, repository.name)
				}
			})
		},
		importFromDirectory : function (layout) {
			var lbox = this.showLoadingBox();
			Ext.Ajax.request({
				url : restUrl + "import/repositories/" + this.repositoryType +
				"/directory.json",
				timeout : 3E5,
				method : "POST",
				scope : this,
				success : function (response) {
					lbox.hide();
					this.appendImportResult(layout, Ext.decode(response.responseText))
				},
				failure : function (result) {
					lbox.hide();
					main.handleRestFailure(result, this.errorTitleText, this.errorMsgText)
				}
			})
		},
		enableAvailableImportTypes : function () {
			var type = null;
			Ext.each(state.repositoryTypes, function (repositoryType) {
				if (repositoryType.name === this.repositoryType)
					type = repositoryType
			}, this);
			if (type !== null) {
				Ext.getCmp("chooseImportType").setValue(null);
				this.getNextButton().setDisabled(true);
				this.getPrevButton().setDisabled(false);
				Ext.getCmp("importTypeURL").setDisabled(type.supportedCommands.indexOf("PULL") < 0);
				Ext.getCmp("importTypeFile").setDisabled(type.supportedCommands.indexOf("UNBUNDLE") < 0)
			}
		},
		applyChanges : function () {
			var panel = Ext.getCmp("repositories");
			if (panel)
				panel.getGrid().reload();
			this.fireEvent("finish")
		}
	});
Ext.reg("scmRepositoryImportWizard", Sonia.repository.ImportPanel);
Sonia.repository.CommitPanel = Ext.extend(Ext.Panel, {
		repository : null,
		revision : null,
		changeset : null,
		templateCommit : '\x3cdiv class\x3d"scm-commit"\x3e\n                     \x3cdiv class\x3d"left-side"\x3e\n                       \x3cdiv class\x3d"left-placeholder left-side"\x3e\n\\n                         {leftPlaceholder}\n                       \x3c/div\x3e\n                       \x3cdiv class\x3d"left-content left-side"\x3e\n                        \x3ch1\x3eCommit {id}\x3c/h1\x3e\n                        \x3cp\x3e{description:convertLineBreaks}\x3c/p\x3e\n                        \x3cp\x3e\n                          \x3ctpl for\x3d"author"\x3e\n                            {name}\x3ctpl if\x3d"mail"\x3e \x26lt;\x3ca href\x3d"mailto:{mail}"\x3e{mail}\x3c/a\x3e\x26gt;\x3c/tpl\x3e\n                          \x3c/tpl\x3e\n                        \x3c/p\x3e\n                        \x3cp\x3e{date:formatTimestamp}\x3c/p\x3e\n                       \x3c/div\x3e\n                     \x3c/div\x3e\n                     \x3cdiv class\x3d"right-side"\x3e\n                       \x3cdiv class\x3d"changeset-tags"\x3e\n                         \x3ctpl if\x3d"tags"\x3e\n                           \x3ctpl for\x3d"tags"\x3e\n                             \x3cspan class\x3d"cs-tag"\x3e\x3ca title\x3d"标签 {.}"\x3e{.}\x3c/a\x3e\x3c/span\x3e\n                           \x3c/tpl\x3e\n                         \x3c/tpl\x3e\n                       \x3c/div\x3e\n                       \x3cdiv class\x3d"changeset-branches"\x3e\n                         \x3ctpl if\x3d"branches"\x3e\n                           \x3ctpl for\x3d"branches"\x3e\n                             \x3cspan class\x3d"cs-branch"\x3e\x3ca title\x3d"分支 {.}"\x3e{.}\x3c/a\x3e\x3c/span\x3e\n                           \x3c/tpl\x3e\n                         \x3c/tpl\x3e\n                       \x3c/div\x3e\n                     \x3c/div\x3e\n                   \x3c/div\x3e',
		templateModifications : '\x3cul class\x3d"scm-modifications"\x3e\n                            \x3ctpl if\x3d"modifications.added"\x3e\x3ctpl for\x3d"modifications.added"\x3e\n                              \x3cli class\x3d"scm-added"\x3e\x3ca rel\x3d"{.}" class\x3d"scm-link"\x3e{.}\x3c/a\x3e\x3c/li\x3e\n                            \x3c/tpl\x3e\x3c/tpl\x3e\n                            \x3ctpl if\x3d"modifications.modified"\x3e\x3ctpl for\x3d"modifications.modified"\x3e\n                              \x3cli class\x3d"scm-modified"\x3e\x3ca rel\x3d"{.}" class\x3d"scm-link"\x3e{.}\x3c/a\x3e\x3c/li\x3e\n                            \x3c/tpl\x3e\x3c/tpl\x3e\n                            \x3ctpl if\x3d"modifications.removed"\x3e\x3ctpl for\x3d"modifications.removed"\x3e\n                              \x3cli class\x3d"scm-removed"\x3e\x3ca rel\x3d"{.}" class\x3d"scm-link"\x3e{.}\x3c/a\x3e\x3c/li\x3e\n                            \x3c/tpl\x3e\x3c/tpl\x3e\n                          \x3c/ul\x3e',
		commitPanel : null,
		diffPanel : null,
		initComponent : function () {
			this.commitPanel = new Ext.Panel({
					tpl : new Ext.XTemplate(this.templateCommit + this.templateModifications),
					listeners : {
						render : {
							fn : function (panel) {
								panel.body.on("click", this.onClick, this)
							},
							scope : this
						}
					}
				});
			this.diffPanel = new Sonia.panel.SyntaxHighlighterPanel({
					syntax : "diff",
					contentUrl : restUrl + "repositories/" + this.repository.id + "/diff?revision\x3d" + this.revision
				});
			var config = {
				bodyCssClass : "x-panel-mc",
				padding : 10,
				autoScroll : true,
				items : [this.commitPanel,
					this.diffPanel]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.CommitPanel.superclass.initComponent.apply(this, arguments);
			this.loadChangeset()
		},
		update : function (changeset) {
			this.changeset = changeset;
			this.commitPanel.tpl.overwrite(this.commitPanel.body, this.changeset)
		},
		loadChangeset : function () {
			if (debug)
				console.debug("read changeset " + this.revision);
			Ext.Ajax.request({
				url : restUrl + "repositories/" + this.repository.id + "/changeset/" + this.revision + ".json",
				method : "GET",
				scope : this,
				success : function (response) {
					var changeset =
						Ext.decode(response.responseText);
					this.update(changeset)
				},
				failure : function (result) {
					main.handleRestFailure(result, this.errorTitleText, this.errorMsgText)
				}
			})
		},
		onClick : function (e) {
			var el = e.getTarget("a.scm-link");
			if (el) {
				var path = el.rel;
				if (path)
					this.openFile(path)
			}
		},
		openFile : function (path) {
			Sonia.repository.openFile(this.repository, path, this.revision)
		}
	});
Ext.reg("commitPanel", Sonia.repository.CommitPanel);
Sonia.repository.ChangesetPanel = Ext.extend(Ext.Panel, {
		repository : null,
		revision : null,
		view : "commit",
		title : "Commit {0}",
		commitLabel : "提交",
		diffLabel : "Diff",
		rawDiffLabel : "Raw Diff",
		initComponent : function () {
			var panel = null;
			switch (this.view) {
			case "diff":
				panel = this.createDiffPanel();
				break;
			default:
				panel = this.createCommitPanel()
			}
			var config = {
				title : String.format(this.title, Ext.util.Format.id(this.revision)),
				autoScroll : true,
				tbar : [{
						text : this.commitLabel,
						handler : this.showCommit,
						scope : this
					}, {
						text : this.diffLabel,
						handler : this.showDiff,
						scope : this
					}, {
						text : this.rawDiffLabel,
						handler : this.downloadRawDiff,
						scope : this
					}
				],
				layout : "fit",
				bbar : ["-\x3e", this.repository.name, ":", this.revision],
				items : [panel]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.ChangesetPanel.superclass.initComponent.apply(this, arguments)
		},
		openPanel : function (panel) {
			this.removeAll();
			this.add(panel);
			this.doLayout()
		},
		updateHistory : function () {
			var token = Sonia.History.createToken("changesetPanel", this.repository.id, this.revision,
					this.view);
			Sonia.History.add(token)
		},
		createCommitPanel : function () {
			return {
				id : "commit-" + this.repository.id + ":" + this.revision,
				xtype : "commitPanel",
				repository : this.repository,
				revision : this.revision
			}
		},
		createDiffPanel : function () {
			return {
				id : "diff-" + this.repository.id + ":" + this.revision,
				xtype : "syntaxHighlighterPanel",
				syntax : "diff",
				contentUrl : this.createDiffUrl()
			}
		},
		createDiffUrl : function () {
			var diffUrl = restUrl + "repositories/" + this.repository.id;
			return diffUrl + "/diff?revision\x3d" + this.revision
		},
		showCommit : function () {
			if (debug)
				console.debug("open commit for " +
					this.revision);
			this.openPanel(this.createCommitPanel());
			this.view = "commit";
			this.updateHistory()
		},
		showDiff : function () {
			if (debug)
				console.debug("open diff for " + this.revision);
			this.openPanel(this.createDiffPanel());
			this.view = "diff";
			this.updateHistory()
		},
		downloadRawDiff : function () {
			if (debug)
				console.debug("open raw diff for " + this.revision);
			window.open(this.createDiffUrl())
		}
	});
Ext.reg("changesetPanel", Sonia.repository.ChangesetPanel);
Sonia.History.register("changesetPanel", {
	onActivate : function (panel) {
		return Sonia.History.createToken("changesetPanel", panel.repository.id, panel.revision, panel.view)
	},
	onChange : function (repoId, revision, view) {
		if (revision === "null")
			revision = null;
		if (!view || view === "null")
			view = "commit";
		var id = "changesetPanel;" + repoId + ";" + revision;
		Sonia.repository.get(repoId, function (repository) {
			var panel = Ext.getCmp(id);
			if (!panel)
				panel = {
					id : id,
					xtype : "changesetPanel",
					repository : repository,
					revision : revision,
					view : view,
					closable : true,
					autoScroll : true
				};
			else
				panel.loadPanel(view);
			main.addTab(panel)
		})
	}
});
Sonia.repository.HealthCheckFailure = Ext.extend(Ext.Panel, {
		title : "Health check",
		linkTemplate : '\x3ca target\x3d"_blank" href\x3d"{0}"\x3e{0}\x3c/a\x3e',
		errorTitleText : "Error",
		errorDescriptionText : "Could not execute health check.",
		initComponent : function () {
			var items = [];
			if (this.healthCheckFailures && this.healthCheckFailures.length > 0)
				for (var i = 0; i < this.healthCheckFailures.length; i++)
					this.appendHealthCheckFailures(items, this.healthCheckFailures[i]);
			items.push({
				xtype : "link",
				style : "font-weight: bold",
				text : "rerun health checks",
				handler : this.rerunHealthChecks,
				scope : this
			});
			var config = {
				title : this.title,
				padding : 5,
				bodyCssClass : "x-panel-mc",
				layout : "table",
				layoutConfig : {
					columns : 2,
					tableAttrs : {
						style : "width: 80%;"
					}
				},
				defaults : {
					style : "font-size: 12px"
				},
				items : items
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.repository.HealthCheckFailure.superclass.initComponent.apply(this, arguments)
		},
		rerunHealthChecks : function () {
			var url = restUrl + "repositories/" + this.repository.id + "/healthcheck.json";
			var el = this.el;
			var tid = setTimeout(function () {
					el.mask("Loading ...")
				},
					100);
			Ext.Ajax.request({
				url : url,
				method : "POST",
				scope : this,
				success : function () {
					clearTimeout(tid);
					this.grid.reload(function () {
						this.grid.selectById(this.repository.id)
					}, this);
					el.unmask()
				},
				failure : function (result) {
					clearTimeout(tid);
					el.unmask();
					main.handleFailure(result.status, this.errorTitleText, this.errorDescriptionText)
				}
			});
			this.grid.reload()
		},
		appendHealthCheckFailures : function (items, hcf) {
			items.push({
				xtype : "label",
				text : "Summary:"
			}, {
				xtype : "label",
				text : hcf.summary
			});
			if (hcf.url)
				items.push({
					xtype : "label",
					text : "Url:"
				}, {
					xtype : "box",
					html : String.format(this.linkTemplate, hcf.url)
				});
			if (hcf.description)
				items.push({
					xtype : "label",
					text : "Description:"
				}, {
					xtype : "label",
					text : hcf.description
				});
			items.push({
				xtype : "box",
				height : 10,
				colspan : 2
			})
		}
	});
Ext.reg("repositoryHealthCheckFailurePanel", Sonia.repository.HealthCheckFailure);
Ext.ns("Sonia.user");
Sonia.user.setEditPanel = function (panels) {
	var editPanel = Ext.getCmp("userEditPanel");
	editPanel.removeAll();
	Ext.each(panels, function (panel) {
		editPanel.add(panel)
	});
	editPanel.setActiveTab(0);
	editPanel.doLayout()
};
Sonia.user.DefaultPanel = {
	region : "south",
	title : "User Form",
	padding : 5,
	xtype : "panel",
	bodyCssClass : "x-panel-mc",
	html : "Add or select an User"
};
Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, {
		titleText : "User Form",
		colNameText : "Name",
		colDisplayNameText : "Display Name",
		colMailText : "Mail",
		colAdminText : "Admin",
		colActiveText : "Active",
		colCreationDateText : "Creation Date",
		colLastModifiedText : "Last modified",
		colTypeText : "Type",
		parentPanel : null,
		initComponent : function () {
			var userStore = new Sonia.rest.JsonStore({
					proxy : new Ext.data.HttpProxy({
						url : restUrl + "users.json",
						disableCaching : false
					}),
					idProperty : "name",
					fields : ["name", "displayName", "mail", "admin", "active",
						"creationDate", "lastModified", "type", "properties"],
					sortInfo : {
						field : "name"
					}
				});
			var userColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : true,
						scope : this,
						width : 125
					},
					columns : [{
							id : "name",
							header : this.colNameText,
							dataIndex : "name"
						}, {
							id : "displayName",
							header : this.colDisplayNameText,
							dataIndex : "displayName",
							width : 250
						}, {
							id : "mail",
							header : this.colMailText,
							dataIndex : "mail",
							renderer : this.renderMailto,
							width : 200
						}, {
							id : "admin",
							header : this.colAdminText,
							dataIndex : "admin",
							renderer : this.renderCheckbox,
							width : 50
						}, {
							id : "active",
							header : this.colActiveText,
							dataIndex : "active",
							renderer : this.renderCheckbox,
							width : 50
						}, {
							id : "creationDate",
							header : this.colCreationDateText,
							dataIndex : "creationDate",
							renderer : Ext.util.Format.formatTimestamp
						}, {
							id : "lastModified",
							header : this.colLastModifiedText,
							dataIndex : "lastModified",
							renderer : Ext.util.Format.formatTimestamp
						}, {
							id : "type",
							header : this.colTypeText,
							dataIndex : "type",
							width : 80
						}
					]
				});
			var config = {
				store : userStore,
				colModel : userColModel,
				listeners : {
					fallBelowMinHeight : {
						fn : this.onFallBelowMinHeight,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.user.Grid.superclass.initComponent.apply(this, arguments);
			if (this.parentPanel)
				this.parentPanel.userGrid = this
		},
		onFallBelowMinHeight : function (height, minHeight) {
			var p = Ext.getCmp("userEditPanel");
			this.setHeight(minHeight);
			var epHeight = p.getHeight();
			p.setHeight(epHeight - (minHeight - height));
			this.doLayout();
			p.doLayout();
			this.ownerCt.doLayout()
		},
		selectItem : function (item) {
			if (debug)
				console.debug(item.name + " selected");
			Sonia.History.append(item.name);
			var panel = new Sonia.user.FormPanel({
					item : item,
					region : "south",
					title : this.titleText,
					padding : 5,
					onUpdate : {
						fn : this.reload,
						scope : this
					},
					onCreate : {
						fn : this.reload,
						scope : this
					}
				});
			if (item.type === state.defaultUserType)
				panel.getForm().setValues([{
							id : "password",
							value : dummyPassword
						}, {
							id : "password-confirm",
							value : dummyPassword
						}
					]);
			Sonia.user.setEditPanel([panel, {
						xtype : "permissionsPanel",
						baseUrl : "security/permission/user/" + encodeURIComponent(item.name)
					}
				])
		}
	});
Ext.reg("userGrid", Sonia.user.Grid);
Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel, {
		nameText : "Name",
		displayNameText : "Display name",
		mailText : "Mail",
		passwordText : "Password",
		adminText : "Administrator",
		activeText : "Active",
		errorTitleText : "Error",
		updateErrorMsgText : "User update failed",
		createErrorMsgText : "User creation failed",
		passwordMinLengthText : "Password must be at least 6 characters long",
		usernameHelpText : "Unique name of the user.",
		displayNameHelpText : "Display name of the user.",
		mailHelpText : "Email address of the user.",
		passwordHelpText : "Plain text password of the user.",
		passwordConfirmHelpText : "Repeat the password for validation.",
		adminHelpText : "An administrator is able to create, modify and delete repositories, groups and users.",
		activeHelpText : "Activate or deactive the user.",
		initComponent : function () {
			var items = [{
					fieldLabel : this.nameText,
					name : "name",
					allowBlank : false,
					readOnly : this.item !== null,
					helpText : this.usernameHelpText,
					vtype : "username"
				}, {
					fieldLabel : this.displayNameText,
					name : "displayName",
					allowBlank : false,
					readOnly : this.isReadOnly(),
					helpText : this.displayNameHelpText
				}, {
					fieldLabel : this.mailText,
					name : "mail",
					allowBlank : true,
					vtype : "email",
					readOnly : this.isReadOnly(),
					helpText : this.mailHelpText
				}
			];
			if (!this.item || this.item.type === state.defaultUserType)
				items.push({
					fieldLabel : this.passwordText,
					id : "pwd",
					name : "password",
					inputType : "password",
					minLength : 6,
					maxLength : 32,
					minLengthText : this.passwordMinLengthText,
					helpText : this.passwordHelpText
				}, {
					name : "password-confirm",
					inputType : "password",
					minLength : 6,
					maxLength : 32,
					minLengthText : this.passwordMinLengthText,
					vtype : "password",
					initialPassField : "pwd",
					helpText : this.passwordConfirmHelpText
				});
			items.push({
				fieldLabel : this.adminText,
				name : "admin",
				xtype : "checkbox",
				helpText : this.adminHelpText
			}, {
				fieldLabel : this.activeText,
				name : "active",
				xtype : "checkbox",
				helpText : this.activeHelpText,
				checked : true
			});
			Ext.apply(this, Ext.apply(this.initialConfig, {
					items : items
				}));
			Sonia.user.FormPanel.superclass.initComponent.apply(this, arguments)
		},
		isReadOnly : function () {
			return this.item && this.item.type !== state.defaultUserType
		},
		fixRequest : function (user) {
			delete user["password-confirm"]
		},
		update : function (item) {
			item = Ext.apply(this.item, item);
			if (debug)
				console.debug("update user: " + item.name);
			this.fixRequest(item);
			var url = restUrl + "users/" + encodeURIComponent(item.name) + ".json";
			Ext.Ajax.request({
				url : url,
				jsonData : item,
				method : "PUT",
				scope : this,
				success : function () {
					if (debug)
						console.debug("update success");
					this.execCallback(this.onUpdate, item)
				},
				failure : function (result) {
					main.handleRestFailure(result, this.errorTitleText, this.updateErrorMsgText)
				}
			})
		},
		create : function (user) {
			if (debug)
				console.debug("create user: " +
					user.name);
			this.fixRequest(user);
			user.type = state.defaultUserType;
			var url = restUrl + "users.json";
			Ext.Ajax.request({
				url : url,
				jsonData : user,
				method : "POST",
				scope : this,
				success : function () {
					if (debug)
						console.debug("create success");
					this.getForm().reset();
					this.execCallback(this.onCreate, user)
				},
				failure : function (result) {
					main.handleRestFailure(result, this.errorTitleText, this.createErrorMsgText)
				}
			})
		},
		cancel : function () {
			Sonia.user.setEditPanel(Sonia.user.DefaultPanel)
		}
	});
Ext.reg("userForm", Sonia.user.FormPanel);
Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, {
		titleText : "User Form",
		emptyText : "Add or select an User",
		removeTitleText : "Remove User",
		removeMsgText : 'Remove User "{0}"?',
		errorTitleText : "Error",
		errorMsgText : "User deletion failed",
		showOnlyActiveText : "Show only active: ",
		userGrid : null,
		initComponent : function () {
			var config = {
				tbar : [{
						xtype : "tbbutton",
						text : this.addText,
						icon : this.addIcon,
						scope : this,
						handler : this.showAddPanel
					}, {
						xtype : "tbbutton",
						text : this.removeText,
						icon : this.removeIcon,
						scope : this,
						handler : this.removeUser
					},
					"-", {
						xtype : "tbbutton",
						text : this.reloadText,
						icon : this.reloadIcon,
						scope : this,
						handler : this.reload
					}, "-", {
						xtype : "label",
						text : this.showOnlyActiveText,
						cls : "ytb-text"
					}, "  ", {
						xtype : "checkbox",
						text : this.reloadText,
						scope : this,
						handler : this.toggleActive
					}
				],
				items : [{
						id : "userGrid",
						xtype : "userGrid",
						region : "center",
						parentPanel : this
					}, {
						id : "userEditPanel",
						xtype : "tabpanel",
						activeTab : 0,
						height : 250,
						split : true,
						border : true,
						region : "south",
						items : [{
								bodyCssClass : "x-panel-mc",
								title : this.titleText,
								padding : 5,
								html : this.emptyText
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.user.Panel.superclass.initComponent.apply(this, arguments)
		},
		toggleActive : function (checkbox, value) {
			if (value)
				this.getGrid().getStore().filterBy(function (record) {
					return record.get("active")
				});
			else
				this.getGrid().getStore().clearFilter()
		},
		getGrid : function () {
			if (!this.userGrid) {
				if (debug)
					console.debug("userGrid not found retrvie by id");
				this.userGrid = Ext.getCmp("userGrid")
			}
			return this.userGrid
		},
		showAddPanel : function () {
			Sonia.user.setEditPanel({
				xtype : "userForm",
				title : this.titleText,
				padding : 5,
				onUpdate : {
					fn : this.reload,
					scope : this
				},
				onCreate : {
					fn : this.reload,
					scope : this
				}
			})
		},
		resetPanel : function () {
			Sonia.user.setEditPanel(Sonia.user.DefaultPanel)
		},
		removeUser : function () {
			var grid = this.getGrid();
			var selected = grid.getSelectionModel().getSelected();
			if (selected) {
				var item = selected.data;
				var url = restUrl + "users/" + encodeURIComponent(item.name) + ".json";
				Ext.MessageBox.show({
					title : this.removeTitleText,
					msg : String.format(this.removeMsgText, item.name),
					buttons : Ext.MessageBox.OKCANCEL,
					icon : Ext.MessageBox.QUESTION,
					fn : function (result$$0) {
						if (result$$0 === "ok") {
							if (debug)
								console.debug("remove user " + item.name);
							Ext.Ajax.request({
								url : url,
								method : "DELETE",
								scope : this,
								success : function () {
									this.reload();
									this.resetPanel()
								},
								failure : function (result) {
									main.handleRestFailure(result, this.errorTitleText, this.errorMsgText)
								}
							})
						}
					},
					scope : this
				})
			} else if (debug)
				console.debug("no user selected")
		},
		reload : function () {
			this.getGrid().reload()
		}
	});
Ext.reg("userPanel", Sonia.user.Panel);
Sonia.History.register("userPanel", {
	onActivate : function (panel) {
		var token = null;
		var rec = panel.getGrid().getSelectionModel().getSelected();
		if (rec)
			token = Sonia.History.createToken("userPanel", rec.get("name"));
		else
			token = Sonia.History.createToken("userPanel");
		return token
	},
	onChange : function (userId) {
		var panel = Ext.getCmp("users");
		if (!panel) {
			main.addUsersTabPanel();
			panel = Ext.getCmp("users");
			if (userId) {
				var selected = false;
				panel.getGrid().getStore().addListener("load", function () {
					if (!selected) {
						panel.getGrid().selectById(userId);
						selected = true
					}
				})
			}
		} else {
			main.addTab(panel);
			if (userId)
				panel.getGrid().selectById(userId)
		}
	}
});
Ext.ns("Sonia.group");
Sonia.group.setEditPanel = function (panels) {
	var editPanel = Ext.getCmp("groupEditPanel");
	editPanel.removeAll();
	Ext.each(panels, function (panel) {
		editPanel.add(panel)
	});
	editPanel.setActiveTab(0);
	editPanel.doLayout()
};
Sonia.group.DefaultPanel = {
	region : "south",
	title : "Group Form",
	xtype : "panel",
	bodyCssClass : "x-panel-mc",
	padding : 5,
	html : "Add or select a Group"
};
Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, {
		colNameText : "Name",
		colDescriptionText : "Description",
		colMembersText : "Members",
		colCreationDateText : "Creation date",
		colTypeText : "Type",
		emptyGroupStoreText : "No group is configured",
		groupFormTitleText : "Group Form",
		parentPanel : null,
		initComponent : function () {
			var groupStore = new Sonia.rest.JsonStore({
					proxy : new Ext.data.HttpProxy({
						url : restUrl + "groups.json",
						disableCaching : false
					}),
					idProperty : "name",
					fields : ["name", "members", "description", "creationDate", "type", "properties"],
					sortInfo : {
						field : "name"
					}
				});
			var groupColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : true,
						scope : this,
						width : 125
					},
					columns : [{
							id : "name",
							header : this.colNameText,
							dataIndex : "name"
						}, {
							id : "description",
							header : this.colDescriptionText,
							dataIndex : "description",
							width : 300
						}, {
							id : "members",
							header : this.colMembersText,
							dataIndex : "members",
							renderer : this.renderMembers
						}, {
							id : "creationDate",
							header : this.colCreationDateText,
							dataIndex : "creationDate",
							renderer : Ext.util.Format.formatTimestamp
						}, {
							id : "type",
							header : this.colTypeText,
							dataIndex : "type",
							width : 80
						}
					]
				});
			var config = {
				autoExpandColumn : "members",
				store : groupStore,
				colModel : groupColModel,
				emptyText : this.emptyGroupStoreText,
				listeners : {
					fallBelowMinHeight : {
						fn : this.onFallBelowMinHeight,
						scope : this
					}
				}
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.group.Grid.superclass.initComponent.apply(this, arguments);
			this.parentPanel.groupGrid = this
		},
		onFallBelowMinHeight : function (height, minHeight) {
			var p = Ext.getCmp("groupEditPanel");
			this.setHeight(minHeight);
			var epHeight = p.getHeight();
			p.setHeight(epHeight - (minHeight - height));
			this.doLayout();
			p.doLayout();
			this.ownerCt.doLayout()
		},
		renderMembers : function (members) {
			var out = "";
			if (members) {
				var s = members.length;
				for (var i = 0; i < s; i++) {
					out += members[i];
					if (i + 1 < s)
						out += ", "
				}
			}
			return out
		},
		selectItem : function (group) {
			if (debug)
				console.debug(group.name + " selected");
			if (this.parentPanel)
				this.parentPanel.updateHistory(group);
			Ext.getCmp("groupRmButton").setDisabled(false);
			Sonia.group.setEditPanel([{
						item : group,
						xtype : "groupPropertiesForm",
						onUpdate : {
							fn : this.reload,
							scope : this
						},
						onCreate : {
							fn : this.reload,
							scope : this
						}
					}, {
						item : group,
						xtype : "groupMemberForm",
						listeners : {
							updated : {
								fn : this.reload,
								scope : this
							},
							created : {
								fn : this.reload,
								scope : this
							}
						}
					}, {
						xtype : "permissionsPanel",
						baseUrl : "security/permission/group/" + encodeURIComponent(group.name)
					}
				])
		}
	});
Ext.reg("groupGrid", Sonia.group.Grid);
Sonia.group.FormPanel = Ext.extend(Sonia.rest.FormPanel, {
		colMemberText : "Member",
		titleText : "Settings",
		nameText : "Name",
		descriptionText : "Description",
		membersText : "Members",
		errorTitleText : "Error",
		updateErrorMsgText : "Group update failed",
		createErrorMsgText : "Group creation failed",
		nameHelpText : "Unique name of the group.",
		descriptionHelpText : "A short description of the group.",
		membersHelpText : "Usernames of the group members.",
		initComponent : function () {
			this.addEvents("preCreate", "created", "preUpdate", "updated",
				"updateFailed", "creationFailed");
			Sonia.group.FormPanel.superclass.initComponent.apply(this, arguments)
		},
		update : function (group) {
			if (debug)
				console.debug("update group " + group.name);
			group = Ext.apply(this.item, group);
			this.fireEvent("preUpdate", group);
			var url = restUrl + "groups/" + encodeURIComponent(group.name) + ".json";
			var el = this.el;
			var tid = setTimeout(function () {
					el.mask("Loading ...")
				}, 100);
			Ext.Ajax.request({
				url : url,
				jsonData : group,
				method : "PUT",
				scope : this,
				success : function () {
					if (debug)
						console.debug("update success");
					this.fireEvent("updated", group);
					clearTimeout(tid);
					el.unmask();
					this.execCallback(this.onUpdate, group)
				},
				failure : function (result) {
					this.fireEvent("updateFailed", group);
					clearTimeout(tid);
					el.unmask();
					main.handleRestFailure(result, this.errorTitleText, this.updateErrorMsgText)
				}
			})
		},
		create : function (item) {
			if (debug)
				console.debug("create group: " + item.name);
			item.type = state.defaultUserType;
			var url = restUrl + "groups.json";
			var el = this.el;
			var tid = setTimeout(function () {
					el.mask("Loading ...")
				}, 100);
			this.fireEvent("preCreate",
				item);
			Ext.Ajax.request({
				url : url,
				jsonData : item,
				method : "POST",
				scope : this,
				success : function () {
					if (debug)
						console.debug("create success");
					this.fireEvent("created", item);
					this.getForm().reset();
					clearTimeout(tid);
					el.unmask();
					this.execCallback(this.onCreate, item)
				},
				failure : function (result) {
					this.fireEvent("creationFailed", item);
					clearTimeout(tid);
					el.unmask();
					main.handleRestFailure(result, this.errorTitleText, this.createErrorMsgText)
				}
			})
		},
		cancel : function () {
			if (debug)
				console.debug("cancel form");
			Sonia.group.setEditPanel(Sonia.group.DefaultPanel)
		}
	});
Ext.reg("groupFormPanel", Sonia.group.FormPanel);
Sonia.group.PropertiesFormPanel = Ext.extend(Sonia.group.FormPanel, {
		initComponent : function () {
			var config = {
				title : this.titleText,
				items : [{
						fieldLabel : this.nameText,
						name : "name",
						allowBlank : false,
						readOnly : this.item !== null,
						helpText : this.nameHelpText,
						vtype : "name"
					}, {
						fieldLabel : this.descriptionText,
						name : "description",
						xtype : "textarea",
						helpText : this.descriptionHelpText
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.group.PropertiesFormPanel.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("groupPropertiesForm", Sonia.group.PropertiesFormPanel);
Sonia.group.MemberFormPanel = Ext.extend(Sonia.group.FormPanel, {
		memberStore : null,
		addIcon : "resources/images/add.png",
		removeIcon : "resources/images/delete.png",
		initComponent : function () {
			this.memberStore = new Ext.data.SimpleStore({
					fields : ["member"],
					sortInfo : {
						field : "member"
					}
				});
			var memberColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : true
					},
					columns : [{
							id : "member",
							header : this.colMemberText,
							dataIndex : "member",
							editor : new Ext.form.ComboBox({
								store : userSearchStore,
								displayField : "label",
								valueField : "value",
								typeAhead : true,
								mode : "remote",
								queryParam : "query",
								hideTrigger : true,
								selectOnFocus : true,
								width : 250
							})
						}
					]
				});
			var selectionModel = new Ext.grid.RowSelectionModel({
					singleSelect : true
				});
			if (this.item) {
				var data = [];
				if (this.item.members)
					for (var i = 0; i < this.item.members.length; i++) {
						var a = [];
						a.push(this.item.members[i]);
						data.push(a)
					}
				this.memberStore.loadData(data)
			}
			var config = {
				title : this.membersText,
				listeners : {
					updated : this.clearModifications,
					preUpdate : {
						fn : this.updateMembers,
						scope : this
					}
				},
				items : [{
						id : "memberGrid",
						xtype : "editorgrid",
						clicksToEdit : 1,
						frame : true,
						width : "100%",
						autoHeight : true,
						autoScroll : false,
						colModel : memberColModel,
						sm : selectionModel,
						store : this.memberStore,
						viewConfig : {
							forceFit : true
						},
						tbar : [{
								text : this.addText,
								scope : this,
								icon : this.addIcon,
								handler : function () {
									var Member = this.memberStore.recordType;
									var grid = Ext.getCmp("memberGrid");
									grid.stopEditing();
									this.memberStore.insert(0, new Member);
									grid.startEditing(0, 0)
								}
							}, {
								text : this.removeText,
								scope : this,
								icon : this.removeIcon,
								handler : function () {
									var grid = Ext.getCmp("memberGrid");
									var selected = grid.getSelectionModel().getSelected();
									if (selected)
										this.memberStore.remove(selected)
								}
							}, "-\x3e", {
								id : "memberGridHelp",
								xtype : "box",
								autoEl : {
									tag : "img",
									src : "resources/images/help.png"
								}
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.group.MemberFormPanel.superclass.initComponent.apply(this, arguments)
		},
		afterRender : function () {
			Sonia.group.FormPanel.superclass.afterRender.apply(this, arguments);
			Ext.QuickTips.register({
				target : Ext.getCmp("memberGridHelp"),
				title : "",
				text : this.membersHelpText,
				enabled : true
			})
		},
		updateMembers : function (item) {
			var members =
				[];
			this.memberStore.data.each(function (record) {
				members.push(record.data.member)
			});
			item.members = members
		},
		clearModifications : function () {
			Ext.getCmp("memberGrid").getStore().commitChanges()
		}
	});
Ext.reg("groupMemberForm", Sonia.group.MemberFormPanel);
Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, {
		titleText : "Group Form",
		emptyText : "Add or select a Group",
		removeTitleText : "Remove Group",
		removeMsgText : 'Remove Group "{0}"?',
		errorTitleText : "Error",
		errorMsgText : "Group deletion failed",
		groupGrid : null,
		initComponent : function () {
			var config = {
				tbar : [{
						xtype : "tbbutton",
						text : this.addText,
						icon : this.addIcon,
						scope : this,
						handler : this.showAddForm
					}, {
						xtype : "tbbutton",
						id : "groupRmButton",
						disabled : true,
						text : this.removeText,
						icon : this.removeIcon,
						scope : this,
						handler : this.removeGroup
					},
					"-", {
						xtype : "tbbutton",
						text : this.reloadText,
						icon : this.reloadIcon,
						scope : this,
						handler : this.reload
					}
				],
				items : [{
						id : "groupGrid",
						xtype : "groupGrid",
						region : "center",
						parentPanel : this
					}, {
						id : "groupEditPanel",
						xtype : "tabpanel",
						activeTab : 0,
						height : 250,
						split : true,
						border : true,
						region : "south",
						items : [{
								bodyCssClass : "x-panel-mc",
								title : this.titleText,
								padding : 5,
								html : this.emptyText
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.group.Panel.superclass.initComponent.apply(this, arguments)
		},
		getGrid : function () {
			if (!this.groupGrid) {
				if (debug)
					console.debug("could not find group grid, fetch by id");
				this.groupGrid = Ext.getCmp("groupGrid")
			}
			return this.groupGrid
		},
		updateHistory : function (group) {
			var token = Sonia.History.createToken("groupPanel", group.name);
			Sonia.History.add(token)
		},
		removeGroup : function () {
			var grid = this.getGrid();
			var selected = grid.getSelectionModel().getSelected();
			if (selected) {
				var item = selected.data;
				var url = restUrl + "groups/" + encodeURIComponent(item.name) + ".json";
				Ext.MessageBox.show({
					title : this.removeTitleText,
					msg : String.format(this.removeMsgText, item.name),
					buttons : Ext.MessageBox.OKCANCEL,
					icon : Ext.MessageBox.QUESTION,
					fn : function (result$$0) {
						if (result$$0 === "ok") {
							if (debug)
								console.debug("remove group " + item.name);
							Ext.Ajax.request({
								url : url,
								method : "DELETE",
								scope : this,
								success : function () {
									this.reload();
									this.resetPanel()
								},
								failure : function (result) {
									main.handleRestFailure(result, this.errorTitleText, this.errorMsgText)
								}
							})
						}
					},
					scope : this
				})
			} else if (debug)
				console.debug("no repository selected")
		},
		showAddForm : function () {
			Ext.getCmp("groupRmButton").setDisabled(true);
			Sonia.group.setEditPanel({
				xtype : "groupPropertiesForm",
				title : this.titleText,
				padding : 5,
				onUpdate : {
					fn : this.reload,
					scope : this
				},
				onCreate : {
					fn : this.reload,
					scope : this
				}
			})
		},
		resetPanel : function () {
			Sonia.group.setEditPanel(Sonia.group.DefaultPanel)
		},
		reload : function () {
			this.getGrid().reload()
		}
	});
Ext.reg("groupPanel", Sonia.group.Panel);
Sonia.History.register("groupPanel", {
	onActivate : function (panel) {
		var token = null;
		var rec = panel.getGrid().getSelectionModel().getSelected();
		if (rec)
			token = Sonia.History.createToken("groupPanel", rec.get("name"));
		else
			token = Sonia.History.createToken("groupPanel");
		return token
	},
	onChange : function (groupId) {
		var panel = Ext.getCmp("groups");
		if (!panel) {
			main.addGroupsTabPanel();
			panel = Ext.getCmp("groups");
			if (groupId) {
				var selected = false;
				panel.getGrid().getStore().addListener("load", function () {
					if (!selected) {
						panel.getGrid().selectById(groupId);
						selected = true
					}
				})
			}
		} else {
			main.addTab(panel);
			if (groupId)
				panel.getGrid().selectById(groupId)
		}
	}
});
Ext.ns("Sonia.security");
Sonia.security.PermissionsPanel = Ext.extend(Ext.Panel, {
		addText : "Add",
		removeText : "Remove",
		reloadText : "Reload",
		addIcon : "resources/images/add.png",
		removeIcon : "resources/images/delete.png",
		reloadIcon : "resources/images/reload.png",
		helpIcon : "resources/images/help.png",
		titleText : "Permissions",
		permissionStore : null,
		baseUrl : null,
		initComponent : function () {
			this.permissionStore = new Sonia.rest.JsonStore({
					proxy : new Ext.data.HttpProxy({
						api : {
							read : restUrl + this.baseUrl + ".json"
						},
						disableCaching : false
					}),
					idProperty : "id",
					fields : ["id", "value"],
					listeners : {
						update : {
							fn : this.modifyOrAddPermission,
							scope : this
						},
						remove : {
							fn : this.removePermission,
							scope : this
						}
					}
				});
			var availablePermissionStore = new Ext.data.JsonStore({
					fields : ["display-name", "description", "value"],
					sortInfo : {
						field : "display-name"
					}
				});
			availablePermissionStore.loadData(state.availablePermissions);
			var permissionColModel = new Ext.grid.ColumnModel({
					columns : [{
							id : "value",
							header : "Permission",
							dataIndex : "value",
							renderer : this.renderPermission,
							editor : new Ext.form.ComboBox({
								store : availablePermissionStore,
								displayField : "display-name",
								valueField : "value",
								typeAhead : false,
								editable : false,
								triggerAction : "all",
								mode : "local",
								width : 250
							})
						}
					]
				});
			var selectionModel = new Ext.grid.RowSelectionModel({
					singleSelect : true
				});
			var config = {
				title : this.titleText,
				bodyCssClass : "x-panel-mc",
				padding : 5,
				items : [{
						id : "permissionGrid",
						xtype : "editorgrid",
						clicksToEdit : 1,
						frame : true,
						width : "100%",
						autoHeight : true,
						autoScroll : false,
						colModel : permissionColModel,
						sm : selectionModel,
						store : this.permissionStore,
						viewConfig : {
							forceFit : true,
							markDirty : false
						},
						tbar : [{
								text : this.addText,
								scope : this,
								icon : this.addIcon,
								handler : function () {
									var Permission = this.permissionStore.recordType;
									var grid = Ext.getCmp("permissionGrid");
									grid.stopEditing();
									this.permissionStore.insert(0, new Permission);
									grid.startEditing(0, 0)
								}
							}, {
								text : this.removeText,
								scope : this,
								icon : this.removeIcon,
								handler : function () {
									var grid = Ext.getCmp("permissionGrid");
									var selected = grid.getSelectionModel().getSelected();
									if (selected)
										this.permissionStore.remove(selected)
								}
							}, "-\x3e", {
								id : "permissionGridHelp",
								xtype : "box",
								autoEl : {
									tag : "img",
									src : this.helpIcon
								}
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.security.PermissionsPanel.superclass.initComponent.apply(this, arguments)
		},
		getIdFromResponse : function (response) {
			var id = null;
			var location = response.getResponseHeader("Location");
			if (location) {
				var parts = location.split("/");
				id = parts[parts.length - 1]
			}
			return id
		},
		modifyOrAddPermission : function (store, record) {
			var id = record.get("id");
			if (id)
				this.modifyPermission(id, record);
			else
				this.addPermission(record)
		},
		addPermission : function (record) {
			Ext.Ajax.request({
				url : restUrl +
				this.baseUrl + ".json",
				method : "POST",
				jsonData : record.data,
				scope : this,
				success : function (response) {
					var id = this.getIdFromResponse(response);
					record.data.id = id
				},
				failure : function (result) {}

			})
		},
		modifyPermission : function (id, record) {
			Ext.Ajax.request({
				url : restUrl + this.baseUrl + "/" + encodeURIComponent(id) + ".json",
				method : "PUT",
				jsonData : record.data,
				scope : this,
				success : function () {},
				failure : function (result) {}

			})
		},
		removePermission : function (store, record) {
			Ext.Ajax.request({
				url : restUrl + this.baseUrl + "/" + encodeURIComponent(record.get("id")) +
				".json",
				method : "DELETE",
				scope : this,
				success : function () {},
				failure : function (result) {}

			})
		},
		renderPermission : function (value) {
			var ap = state.availablePermissions;
			for (var i = 0; i < ap.length; i++)
				if (value === ap[i].value) {
					value = ap[i]["display-name"];
					break
				}
			return value
		}
	});
Ext.reg("permissionsPanel", Sonia.security.PermissionsPanel);
var repositoryConfigPanels = [];
var generalConfigPanels = [];
function registerConfigPanel(panel) {
	repositoryConfigPanels.push(panel)
}
function registerGeneralConfigPanel(panel) {
	generalConfigPanels.push(panel)
}
Ext.ns("Sonia.config");
Ext.apply(Ext.form.VTypes, {
	pluginurl : function (val) {
		return this.pluginurlRegex.test(val)
	},
	pluginurlRegex : /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!\{\}]*)(\.\w{2,})?)*\/?)/i,
	pluginurlText : 'This field should be a URL in the format \n    "http://plugins.scm-manager.org/scm-plugin-backend/api/{version}/plugins?os\x3d{os}\x26arch\x3d{arch}\x26snapshot\x3dfalse"'
});
Sonia.config.ConfigPanel = Ext.extend(Ext.Panel, {
		panels : null,
		initComponent : function () {
			var config = {
				region : "center",
				bodyCssClass : "x-panel-mc",
				trackResetOnLoad : true,
				autoScroll : true,
				border : false,
				frame : false,
				collapsible : false,
				collapsed : false,
				items : this.panels
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.config.ConfigPanel.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("configPanel", Sonia.config.ConfigPanel);
Sonia.config.RepositoryConfig = Ext.extend(Sonia.config.ConfigPanel, {
		initComponent : function () {
			var config = {
				title : main.tabRepositoryTypesText,
				panels : repositoryConfigPanels
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.config.RepositoryConfig.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("repositoryConfig", Sonia.config.RepositoryConfig);
Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel, {
		titleText : "General Settings",
		servnameText : "Servername",
		realmDescriptionText : "Realm description",
		dateFormatText : "Date format",
		enableForwardingText : "Enable forwarding (mod_proxy)",
		forwardPortText : "Forward Port",
		pluginRepositoryText : "Plugin repository",
		allowAnonymousAccessText : "Allow Anonymous Access",
		enableSSLText : "Enable SSL",
		sslPortText : "SSL Port",
		adminGroupsText : "Admin Groups",
		adminUsersText : "Admin Users",
		submitText : "Submit ...",
		loadingText : "Loading ...",
		errorTitleText : "Error",
		errorMsgText : "Could not load config.",
		errorSubmitMsgText : "Could not submit config.",
		skipFailedAuthenticatorsText : "Skip failed authenticators",
		loginAttemptLimitText : "Login Attempt Limit",
		loginAttemptLimitTimeoutText : "Login Attempt Limit Timeout",
		enableProxyText : "Enable Proxy",
		proxyServerText : "Proxy Server",
		proxyPortText : "Proxy Port",
		proxyUserText : "Proxy User",
		proxyPasswordText : "Proxy Password",
		proxyExcludesText : "Proxy Excludes",
		baseUrlText : "Base Url",
		forceBaseUrlText : "Force Base Url",
		disableGroupingGridText : "Disable repository Groups",
		enableRepositoryArchiveText : "Enable repository archive",
		servernameHelpText : "The name of this server. This name will be part of the repository url.",
		realmDescriptionHelpText : "Enter authentication realm description",
		dateFormatHelpText : 'Moments date format. Please have a look at \n                      \x3ca href\x3d"http://momentjs.com/docs/#/displaying/format/" target\x3d"_blank"\x3ehttp://momentjs.com/docs/#/displaying/format/\x3c/a\x3e.\x3cbr /\x3e\n                      \x3cb\x3eNote:\x3c/b\x3e\x3cbr /\x3e\n                      {0} - is replaced by a "time ago" string (e.g. 2 hours ago).',
		pluginRepositoryHelpText : "The url of the plugin repository.\x3cbr /\x3eExplanation of the {placeholders}:\n  \x3cbr /\x3e\x3cb\x3eversion\x3c/b\x3e \x3d SCM-Manager Version\x3cbr /\x3e\x3cb\x3eos\x3c/b\x3e \x3d Operation System\x3cbr /\x3e\x3cb\x3earch\x3c/b\x3e \x3d Architecture",
		enableForwardingHelpText : "Enbale mod_proxy port forwarding.",
		forwardPortHelpText : "The forwarding port.",
		allowAnonymousAccessHelpText : "Anonymous users have read access on public repositories.",
		enableSSLHelpText : "Enable secure connections via HTTPS.",
		sslPortHelpText : "The ssl port.",
		adminGroupsHelpText : "Comma seperated list of groups with admin permissions.",
		adminUsersHelpText : "Comma seperated list of users with admin permissions.",
		skipFailedAuthenticatorsHelpText : "Do not stop the authentication chain, \n                                     if an authenticator finds the user but fails to authenticate the user.",
		loginAttemptLimitHelpText : "Maximum allowed login attempts. Use -1 to disable the login attempt limit.",
		loginAttemptLimitTimeoutHelpText : "Timeout in seconds for users which are temporary disabled,                                     because of too many failed login attempts.",
		enableProxyHelpText : "Enable Proxy",
		proxyServerHelpText : "The proxy server",
		proxyPortHelpText : "The proxy port",
		proxyUserHelpText : "The username for the proxy server authentication.",
		proxyPasswordHelpText : "The password for the proxy server authentication.",
		proxyExcludesHelpText : "A comma separated list of glob patterns for hostnames which should be excluded from proxy settings.",
		baseUrlHelpText : "The url of the application (with context path) i.e. http://localhost:8080/scm",
		forceBaseUrlHelpText : "Redirects to the base url if the request comes from a other url",
		disableGroupingGridHelpText : "Disable repository Groups. A complete page reload is required after a change of this value.",
		enableRepositoryArchiveHelpText : "Enable repository archives. A complete page reload is required after a change of this value.",
		initComponent : function () {
			var config = {
				title : main.tabGeneralConfigText,
				panels : [{
						xtype : "configForm",
						title : this.titleText,
						items : [{
								xtype : "textfield",
								fieldLabel : this.baseUrlText,
								name : "base-url",
								helpText : this.baseUrlHelpText,
								allowBlank : false
							}, {
								xtype : "checkbox",
								fieldLabel : this.forceBaseUrlText,
								name : "force-base-url",
								inputValue : "true",
								helpText : this.forceBaseUrlHelpText
							}, {
								xtype : "checkbox",
								fieldLabel : this.disableGroupingGridText,
								name : "disableGroupingGrid",
								inputValue : "true",
								helpText : this.disableGroupingGridHelpText
							}, {
								xtype : "checkbox",
								fieldLabel : this.enableRepositoryArchiveText,
								name : "enableRepositoryArchive",
								inputValue : "true",
								helpText : this.enableRepositoryArchiveHelpText
							}, {
								xtype : "textfield",
								fieldLabel : this.realmDescriptionText,
								name : "realmDescription",
								allowBlank : false,
								helpText : this.realmDescriptionHelpText
							}, {
								xtype : "textfield",
								fieldLabel : this.dateFormatText,
								name : "dateFormat",
								helpText : this.dateFormatHelpText,
								helpDisableAutoHide : true,
								allowBlank : false
							}, {
								xtype : "textfield",
								fieldLabel : this.pluginRepositoryText,
								name : "plugin-url",
								vtype : "pluginurl",
								allowBlank : false,
								helpText : this.pluginRepositoryHelpText
							}, {
								xtype : "checkbox",
								fieldLabel : this.allowAnonymousAccessText,
								name : "anonymousAccessEnabled",
								inputValue : "true",
								helpText : this.allowAnonymousAccessHelpText
							}, {
								xtype : "checkbox",
								fieldLabel : this.skipFailedAuthenticatorsText,
								name : "skip-failed-authenticators",
								inputValue : "true",
								helpText : this.skipFailedAuthenticatorsHelpText
							}, {
								xtype : "numberfield",
								fieldLabel : this.loginAttemptLimitText,
								name : "login-attempt-limit",
								allowBlank : false,
								helpText : this.loginAttemptLimitHelpText
							}, {
								xtype : "numberfield",
								fieldLabel : this.loginAttemptLimitTimeoutText,
								name : "login-attempt-limit-timeout",
								allowBlank : false,
								helpText : this.loginAttemptLimitTimeoutHelpText
							}, {
								xtype : "checkbox",
								fieldLabel : this.enableProxyText,
								name : "enableProxy",
								inputValue : "true",
								helpText : this.enableProxyHelpText,
								listeners : {
									check : function () {
										Ext.getCmp("proxyServer").setDisabled(!this.checked);
										Ext.getCmp("proxyPort").setDisabled(!this.checked);
										Ext.getCmp("proxyUser").setDisabled(!this.checked);
										Ext.getCmp("proxyPassword").setDisabled(!this.checked);
										Ext.getCmp("proxyExcludes").setDisabled(!this.checked)
									}
								}
							}, {
								id : "proxyServer",
								xtype : "textfield",
								fieldLabel : this.proxyServerText,
								name : "proxyServer",
								disabled : true,
								helpText : this.proxyServerHelpText,
								allowBlank : false
							}, {
								id : "proxyPort",
								xtype : "numberfield",
								fieldLabel : this.proxyPortText,
								name : "proxyPort",
								disabled : true,
								allowBlank : false,
								helpText : this.proxyPortHelpText
							}, {
								id : "proxyUser",
								xtype : "textfield",
								fieldLabel : this.proxyUserText,
								name : "proxyUser",
								disabled : true,
								helpText : this.proxyUserHelpText,
								allowBlank : true
							}, {
								id : "proxyPassword",
								xtype : "textfield",
								inputType : "password",
								fieldLabel : this.proxyPasswordText,
								name : "proxyPassword",
								disabled : true,
								helpText : this.proxyPasswordHelpText,
								allowBlank : true
							}, {
								id : "proxyExcludes",
								xtype : "textfield",
								fieldLabel : this.proxyExcludesText,
								name : "proxy-excludes",
								disabled : true,
								helpText : this.proxyExcludesHelpText,
								allowBlank : true
							}, {
								xtype : "textfield",
								fieldLabel : this.adminGroupsText,
								name : "admin-groups",
								allowBlank : true,
								helpText : this.adminGroupsHelpText
							}, {
								xtype : "textfield",
								fieldLabel : this.adminUsersText,
								name : "admin-users",
								allowBlank : true,
								helpText : this.adminUsersHelpText
							}
						],
						onSubmit : function (values) {
							this.el.mask(this.submitText);
							Ext.Ajax.request({
								url : restUrl + "config.json",
								method : "POST",
								jsonData : values,
								scope : this,
								disableCaching : true,
								success : function () {
									this.el.unmask()
								},
								failure : function (result) {
									this.el.unmask();
									main.handleRestFailure(result, this.errorTitleText, this.errorMsgText)
								}
							})
						},
						onLoad : function (el) {
							var tid = setTimeout(function () {
									el.mask(this.loadingText)
								}, 100);
							Ext.Ajax.request({
								url : restUrl + "config.json",
								method : "GET",
								scope : this,
								disableCaching : true,
								success : function (response) {
									var obj = Ext.decode(response.responseText);
									this.load(obj);
									if (obj.enableProxy) {
										Ext.getCmp("proxyServer").setDisabled(false);
										Ext.getCmp("proxyPort").setDisabled(false);
										Ext.getCmp("proxyUser").setDisabled(false);
										Ext.getCmp("proxyPassword").setDisabled(false);
										Ext.getCmp("proxyExcludes").setDisabled(false)
									}
									clearTimeout(tid);
									el.unmask()
								},
								failure : function (result) {
									el.unmask();
									clearTimeout(tid);
									main.handleRestFailure(result, this.errorTitleText, this.errorMsgText)
								}
							})
						}
					}, generalConfigPanels]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.config.ScmConfigPanel.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("scmConfig", Sonia.config.ScmConfigPanel);
Sonia.config.ConfigForm = Ext.extend(Ext.form.FormPanel, {
		title : "Config Form",
		saveButtonText : "Save",
		resetButtontext : "Reset",
		submitText : "Submit ...",
		loadingText : "Loading ...",
		failedText : "Unknown Error occurred.",
		items : null,
		onSubmit : null,
		getValues : null,
		initComponent : function () {
			var config = {
				title : null,
				style : "margin: 10px",
				trackResetOnLoad : true,
				autoScroll : true,
				border : false,
				frame : false,
				collapsible : false,
				collapsed : false,
				layoutConfig : {
					labelSeparator : ""
				},
				items : [{
						xtype : "fieldset",
						checkboxToggle : false,
						title : this.title,
						collapsible : true,
						autoHeight : true,
						labelWidth : 140,
						buttonAlign : "left",
						layoutConfig : {
							labelSeparator : ""
						},
						defaults : {
							width : 250
						},
						listeners : {
							render : function () {
								if (this.onLoad && Ext.isFunction(this.onLoad))
									this.onLoad(this.el)
							},
							scope : this
						},
						items : this.items,
						buttons : [{
								text : this.saveButtonText,
								scope : this,
								formBind : true,
								handler : this.submitForm
							}, {
								text : this.resetButtontext,
								scope : this,
								handler : function () {
									this.getForm().reset()
								}
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.config.ConfigForm.superclass.initComponent.apply(this,
				arguments)
		},
		load : function (values) {
			this.getForm().loadRecord({
				success : true,
				data : values
			})
		},
		submitForm : function () {
			var form = this.getForm();
			if (this.onSubmit && Ext.isFunction(this.onSubmit))
				this.onSubmit(form.getValues())
		}
	});
Ext.reg("configForm", Sonia.config.ConfigForm);
Sonia.config.SimpleConfigForm = Ext.extend(Sonia.config.ConfigForm, {
		configUrl : null,
		loadMethod : "GET",
		submitMethod : "POST",
		initComponent : function () {
			Ext.apply(this, Ext.apply(this.initialConfig));
			Sonia.config.SimpleConfigForm.superclass.initComponent.apply(this, arguments)
		},
		onSubmit : function (values) {
			this.el.mask(this.submitText);
			Ext.Ajax.request({
				url : this.configUrl,
				method : this.submitMethod,
				jsonData : values,
				scope : this,
				disableCaching : true,
				success : function (response) {
					this.el.unmask()
				},
				failure : function (result) {
					this.el.unmask();
					main.handleRestFailure(result, null, this.failedText)
				}
			})
		},
		onLoad : function (el) {
			var tid = setTimeout(function () {
					el.mask(this.loadingText)
				}, 100);
			Ext.Ajax.request({
				url : this.configUrl,
				method : this.loadMethod,
				scope : this,
				disableCaching : true,
				success : function (response) {
					var obj = Ext.decode(response.responseText);
					this.load(obj);
					clearTimeout(tid);
					el.unmask()
				},
				failure : function (result) {
					el.unmask();
					clearTimeout(tid);
					main.handleRestFailure(result, null, this.failedText)
				}
			})
		}
	});
Ext.reg("simpleConfigForm", Sonia.config.SimpleConfigForm);
Ext.ns("Sonia.action");
Sonia.action.ChangePasswordWindow = Ext.extend(Ext.Window, {
		titleText : "Change Password",
		oldPasswordText : "Old Password",
		newPasswordText : "New Password",
		confirmPasswordText : "Confirm Password",
		okText : "Ok",
		cancelText : "Cancel",
		connectingText : "Connecting",
		failedText : "change password failed!",
		waitMsgText : "Sending data...",
		initComponent : function () {
			var config = {
				layout : "fit",
				width : 300,
				height : 170,
				closable : false,
				resizable : false,
				plain : true,
				border : false,
				modal : true,
				title : this.titleText,
				items : [{
						id : "changePasswordForm",
						url : restUrl +
						"action/change-password.json",
						frame : true,
						xtype : "form",
						monitorValid : true,
						defaultType : "textfield",
						items : [{
								name : "old-password",
								fieldLabel : this.oldPasswordText,
								inputType : "password",
								allowBlank : false
							}, {
								id : "new-password",
								name : "new-password",
								fieldLabel : this.newPasswordText,
								inputType : "password",
								allowBlank : false,
								minLength : 6,
								maxLength : 32
							}, {
								name : "confirm-password",
								fieldLabel : this.confirmPasswordText,
								inputType : "password",
								allowBlank : false,
								minLength : 6,
								maxLength : 32,
								vtype : "password",
								initialPassField : "new-password"
							}
						],
						buttons : [{
								text : this.okText,
								formBind : true,
								scope : this,
								handler : this.changePassword
							}, {
								text : this.cancelText,
								scope : this,
								handler : this.cancel
							}
						]
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.action.ChangePasswordWindow.superclass.initComponent.apply(this, arguments)
		},
		changePassword : function () {
			var form = Ext.getCmp("changePasswordForm").getForm();
			form.submit({
				scope : this,
				method : "POST",
				waitTitle : this.connectingText,
				waitMsg : this.waitMsgText,
				success : function () {
					if (debug)
						console.debug("change password success");
					this.close()
				},
				failure : function () {
					if (debug)
						console.debug("change password failed");
					Ext.Msg.alert(this.failedText)
				}
			})
		},
		cancel : function () {
			this.close()
		}
	});
Sonia.action.ExceptionWindow = Ext.extend(Ext.Window, {
		title : null,
		message : null,
		stacktrace : null,
		icon : Ext.MessageBox.ERROR,
		okText : "Ok",
		detailsText : "Details",
		exceptionText : "Exception",
		initComponent : function () {
			var config = {
				title : this.title,
				width : 300,
				height : 110,
				closable : true,
				resizable : true,
				plain : true,
				border : false,
				modal : true,
				bodyCssClass : "x-window-dlg",
				items : [{
						xtype : "panel",
						height : 45,
						bodyCssClass : "x-panel-mc x-dlg-icon",
						html : '\x3cdiv class\x3d"ext-mb-icon ' + this.icon + '"\x3e\x3c/div\x3e\x3cdiv class\x3d"ext-mb-content"\x3e\x3cspan class\x3d"ext-mb-text"\x3e' +
						this.message + "\x3c/span\x3e\x3c/div\x3e"
					}, {
						id : "stacktraceArea",
						xtype : "textarea",
						editable : false,
						fieldLabel : this.exceptionText,
						value : this.stacktrace,
						width : "98%",
						height : 260,
						hidden : true
					}
				],
				buttons : [{
						text : this.okText,
						scope : this,
						handler : this.close
					}, {
						id : "detailButton",
						text : this.detailsText,
						scope : this,
						handler : this.showDetails
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.action.ChangePasswordWindow.superclass.initComponent.apply(this, arguments)
		},
		showDetails : function () {
			Ext.getCmp("detailButton").setDisabled(true);
			Ext.getCmp("stacktraceArea").setVisible(true);
			this.setWidth(640);
			this.setHeight(380);
			this.center()
		}
	});
Ext.ns("Sonia.plugin");
Sonia.plugin.UploadForm = Ext.extend(Ext.FormPanel, {
		emptyText : "Select an Plugin-Package",
		uploadFieldLabel : "Package",
		waitMsg : "Uploading your package ...",
		btnUpload : "Upload",
		btnReset : "Reset",
		initComponent : function () {
			this.addEvents("success", "failure");
			var config = {
				fileUpload : true,
				width : 500,
				frame : false,
				autoHeight : true,
				labelWidth : 50,
				bodyStyle : "padding: 5px 0 0 10px;",
				defaults : {
					anchor : "95%",
					allowBlank : false,
					msgTarget : "side"
				},
				items : [{
						xtype : "fileuploadfield",
						id : "form-file",
						emptyText : this.emptyText,
						fieldLabel : this.uploadFieldLabel,
						name : "package",
						buttonText : "",
						buttonCfg : {
							iconCls : "upload-icon"
						}
					}
				],
				buttons : [{
						text : this.btnUpload,
						handler : function () {
							if (this.getForm().isValid())
								this.getForm().submit({
									url : restUrl + "plugins/install-package.html",
									waitMsg : this.waitMsg,
									success : function (form, action) {
										if (debug)
											console.debug("upload success");
										this.fireEvent("success")
									},
									failure : function (form, action) {
										if (debug)
											console.debug("upload failed");
										this.fireEvent("failure")
									},
									scope : this
								})
						},
						scope : this
					}, {
						text : this.btnReset,
						handler : function () {
							this.getForm().reset()
						},
						scope : this
					}
				]
			};
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.plugin.UploadForm.superclass.initComponent.apply(this, arguments)
		}
	});
Ext.reg("pluginPackageUploadForm", Sonia.plugin.UploadForm);
Sonia.plugin.Center = Ext.extend(Ext.util.Observable, {
		waitTitleText : "Please wait",
		errorTitleText : "Error",
		restartText : "Restart the applicationserver to activate the plugin.",
		installWaitMsgText : "Installing Plugin.",
		installSuccessText : "Plugin successfully installed",
		installFailedText : "Plugin installation failed",
		uninstallWaitMsgText : "Uninstalling Plugin.",
		uninstallSuccessText : "Plugin successfully uninstalled",
		uninstallFailedText : "Plugin uninstallation failed",
		updateWaitMsgText : "Updating Plugin.",
		updateSuccessText : "Plugin successfully updated",
		updateFailedText : "Plugin update failed",
		constructor : function (config) {
			this.addEvents("install", "uninstalled", "updated");
			Sonia.plugin.Center.superclass.constructor.call(this, config)
		},
		getPluginId : function (data) {
			return data.groupId + ":" + data.artifactId + ":" + data.version
		},
		createLoadingBox : function (msg) {
			return Ext.MessageBox.show({
				title : this.waitTitleText,
				msg : msg,
				width : 300,
				wait : true,
				animate : true,
				progress : true,
				closable : false
			})
		},
		fireEvents : function (name, pluginId) {
			this.fireEvent(name, pluginId);
			this.fireEvent("changed",
				pluginId)
		},
		install : function (pluginId) {
			if (debug)
				console.debug("install plugin " + pluginId);
			var loadingBox = this.createLoadingBox(this.installWaitMsgText);
			Ext.Ajax.request({
				url : restUrl + "plugins/install/" + pluginId + ".json",
				method : "POST",
				scope : this,
				timeout : 3E5,
				success : function () {
					if (debug)
						console.debug("plugin successfully installed");
					loadingBox.hide();
					Ext.MessageBox.alert(this.installSuccessText, this.restartText);
					this.fireEvents("installed", pluginId)
				},
				failure : function (result) {
					if (debug)
						console.debug("plugin installation failed");
					loadingBox.hide();
					main.handleRestFailure(result, this.errorTitleText, this.installFailedText)
				}
			})
		},
		uninstall : function (pluginId) {
			if (debug)
				console.debug("uninstall plugin " + pluginId);
			var loadingBox = this.createLoadingBox(this.uninstallWaitMsgText);
			Ext.Ajax.request({
				url : restUrl + "plugins/uninstall/" + pluginId + ".json",
				method : "POST",
				scope : this,
				success : function () {
					if (debug)
						console.debug("plugin successfully uninstalled");
					loadingBox.hide();
					Ext.MessageBox.alert(this.uninstallSuccessText, this.restartText);
					this.fireEvents("uninstalled",
						pluginId)
				},
				failure : function (result) {
					if (debug)
						console.debug("plugin uninstallation failed");
					loadingBox.hide();
					main.handleRestFailure(result, this.errorTitleText, this.uninstallFailedText)
				}
			})
		},
		update : function (pluginId) {
			if (debug)
				console.debug("update plugin to " + pluginId);
			var loadingBox = this.createLoadingBox(this.updateWaitMsgText);
			Ext.Ajax.request({
				url : restUrl + "plugins/update/" + pluginId + ".json",
				method : "POST",
				scope : this,
				timeout : 3E5,
				success : function () {
					if (debug)
						console.debug("plugin successfully updated");
					loadingBox.hide();
					Ext.MessageBox.alert(this.updateSuccessText, this.restartText);
					this.fireEvents("updated", pluginId)
				},
				failure : function (result) {
					if (debug)
						console.debug("plugin update failed");
					loadingBox.hide();
					main.handleRestFailure(result, this.errorTitleText, this.updateFailedText)
				}
			})
		}
	});
Sonia.plugin.Store = Ext.extend(Sonia.rest.JsonStore, {
		constructor : function (config) {
			var baseConfig = {
				fields : ["name", "author", "description", "url", "version", "state", "groupId", "artifactId"],
				sortInfo : {
					field : "name"
				}
			};
			Sonia.plugin.Store.superclass.constructor.call(this, Ext.apply(baseConfig, config))
		}
	});
Sonia.plugin.CenterInstance = new Sonia.plugin.Center;
Sonia.plugin.Grid = Ext.extend(Sonia.rest.Grid, {
		colNameText : "Name",
		colAuthorText : "Author",
		colDescriptionText : "Description",
		colVersionText : "Version",
		colActionText : "Action",
		colUrlText : "Url",
		colCategoryText : "Category",
		emptyText : "No plugins avaiable",
		btnReload : "Reload",
		btnIconReload : "resources/images/reload.png",
		btnInstallPackage : "Install Package",
		btnIconInstallPackage : "resources/images/add.png",
		uploadWindowTitle : "Upload Plugin-Package",
		actionLinkTemplate : '\x3ca style\x3d"cursor: pointer;" onclick\x3d"Sonia.plugin.CenterInstance.{1}(\'{2}\')"\x3e{0}\x3c/a\x3e',
		initComponent : function () {
			var pluginColModel = new Ext.grid.ColumnModel({
					defaults : {
						sortable : true,
						scope : this,
						width : 125
					},
					columns : [{
							id : "name",
							header : this.colNameText,
							dataIndex : "name"
						}, {
							id : "author",
							header : this.colAuthorText,
							dataIndex : "author"
						}, {
							id : "description",
							header : this.colDescriptionText,
							dataIndex : "description"
						}, {
							id : "version",
							header : this.colVersionText,
							dataIndex : "version"
						}, {
							id : "action",
							header : this.colActionText,
							renderer : this.renderActionColumn
						}, {
							id : "Url",
							header : this.colUrlText,
							dataIndex : "url",
							renderer : this.renderUrl,
							width : 150
						}, {
							id : "Category",
							header : this.colCategoryText,
							dataIndex : "category",
							hidden : true,
							hideable : false
						}
					]
				});
			var pluginStore = new Ext.data.GroupingStore({
					proxy : new Ext.data.HttpProxy({
						url : restUrl + "plugins/overview.json",
						disableCaching : false
					}),
					reader : new Ext.data.JsonReader({
						fields : ["name", "author", "description", "url", "version", "state", "groupId", "artifactId", {
								name : "category",
								convert : this.convertCategory,
								scope : this
							}
						]
					}),
					sortInfo : {
						field : "name"
					},
					autoLoad : true,
					autoDestroy : true,
					remoteGroup : false,
					groupOnSort : false,
					groupField : "category",
					groupDir : "AES"
				});
			var config = {
				title : main.tabPluginsText,
				autoExpandColumn : "description",
				store : pluginStore,
				colModel : pluginColModel,
				emptyText : this.emptyText,
				view : new Ext.grid.GroupingView({
					forceFit : true,
					enableGroupingMenu : false,
					groupTextTpl : '{group} ({[values.rs.length]} {[values.rs.length \x3e 1 ? "Plugins" : "Plugin"]})'
				}),
				tbar : [{
						text : this.btnInstallPackage,
						icon : this.btnIconInstallPackage,
						handler : function () {
							var window = new Ext.Window({
									title : this.uploadWindowTitle
								});
							window.add({
								xtype : "pluginPackageUploadForm",
								listeners : {
									success : {
										fn : function () {
											this.close();
											Ext.MessageBox.alert(Sonia.plugin.CenterInstance.installSuccessText, Sonia.plugin.CenterInstance.restartText)
										},
										scope : window
									},
									failure : {
										fn : function () {
											this.close();
											Ext.MessageBox.alert(Sonia.plugin.CenterInstance.errorTitleText, Sonia.plugin.CenterInstance.installFailedText)
										},
										scope : window
									}
								}
							});
							window.show()
						},
						scope : this
					}, "|", {
						text : this.btnReload,
						icon : this.btnIconReload,
						handler : function () {
							this.getStore().reload()
						},
						scope : this
					}
				]
			};
			Sonia.plugin.CenterInstance.addListener("changed",
				function () {
				if (debug)
					console.debug("receive change event, reload plugin store");
				this.getStore().reload()
			}, this);
			Ext.apply(this, Ext.apply(this.initialConfig, config));
			Sonia.plugin.Grid.superclass.initComponent.apply(this, arguments)
		},
		convertCategory : function (category) {
			return category ? category : "Miscellaneous"
		},
		renderActionColumn : function (val, meta, record) {
			var out = "";
			var data = record.data;
			var id = Sonia.plugin.CenterInstance.getPluginId(data);
			if (data.state === "AVAILABLE")
				out = String.format(this.actionLinkTemplate,
						"Install", "install", id);
			else if (data.state === "INSTALLED")
				out = String.format(this.actionLinkTemplate, "Uninstall", "uninstall", id);
			else if (data.state === "UPDATE_AVAILABLE") {
				out = String.format(this.actionLinkTemplate, "Update", "update", id);
				out += ", ";
				out += String.format(this.actionLinkTemplate, "Uninstall", "uninstall", id)
			}
			return out
		}
	});
Ext.reg("pluginGrid", Sonia.plugin.Grid);
Ext.ns("Sonia.scm");
Sonia.scm.Main = Ext.extend(Ext.util.Observable, {
		tabRepositoriesText : "仓库",
		navImportRepositoriesText : "Import Repositories",
		navChangePasswordText : "Change Password",
		sectionMainText : "Main",
		sectionSecurityText : "Security",
		navRepositoriesText : "仓库",
		sectionConfigText : "Config",
		navGeneralConfigText : "General",
		tabGeneralConfigText : "SCM Config",
		navRepositoryTypesText : "Repository Types",
		tabRepositoryTypesText : "Repository Config",
		navPluginsText : "Plugins",
		tabPluginsText : "Plugins",
		navUsersText : "Users",
		tabUsersText : "Users",
		navGroupsText : "Groups",
		tabGroupsText : "Groups",
		sectionLoginText : "Login",
		navLoginText : "Login",
		sectionLogoutText : "Log out",
		navLogoutText : "Log out",
		logoutFailedText : "Logout Failed!",
		errorTitle : "Error",
		errorMessage : "Unknown error occurred.",
		errorSessionExpiredTitle : "Session expired",
		errorSessionExpiredMessage : "Your session is expired. Please relogin.",
		errorNoPermissionsTitle : "Not permitted",
		errorNoPermissionsMessage : "You have not enough permissions to execute this action.",
		errorNotFoundTitle : "Not found",
		errorNotFoundMessage : "The resource could not be found.",
		loggedInTextTemplate : 'logged in as \x3ca id\x3d"scm-userinfo-tip"\x3e{state.user.name}\x3c/a\x3e - ',
		userInfoMailText : "Mail",
		userInfoGroupsText : "Groups",
		mainTabPanel : null,
		infoPanels : [],
		scripts : [],
		stylesheets : [],
		constructor : function (config) {
			this.addEvents("login", "logout", "init");
			this.mainTabPanel = Ext.getCmp("mainTabPanel");
			this.addListener("login", this.postLogin, this);
			Sonia.scm.Main.superclass.constructor.call(this, config)
		},
		init : function () {
			this.fireEvent("init",
				this)
		},
		registerInfoPanel : function (type, panel) {
			this.infoPanels[type] = panel
		},
		getInfoPanel : function (type) {
			var rp = null;
			var panel = this.infoPanels[type];
			if (!panel)
				rp = {
					xtype : "repositoryInfoPanel"
				};
			else
				rp = Sonia.util.clone(panel);
			return rp
		},
		postLogin : function () {
			this.createMainMenu();
			this.createHomePanel()
		},
		createHomePanel : function () {
			if (debug)
				console.debug("create home panel");
			this.mainTabPanel.add({
				id : "repositories",
				xtype : "repositoryPanel",
				title : this.tabRepositoriesText,
				closeable : false,
				autoScroll : true
			});
			this.mainTabPanel.setActiveTab("repositories")
		},
		addRepositoriesTabPanel : function () {
			this.addTabPanel("repositories", "repositoryPanel", this.tabRepositoriesText)
		},
		addScmConfigTabPanel : function () {
			if (admin)
				this.addTabPanel("scmConfig", "scmConfig", this.navGeneralConfigText)
		},
		addRepositoryConfigTabPanel : function () {
			if (admin)
				this.addTabPanel("repositoryConfig", "repositoryConfig", this.tabRepositoryTypesText)
		},
		addPluginTabPanel : function () {
			if (admin)
				this.addTabPanel("plugins", "pluginGrid", this.navPluginsText)
		},
		addUsersTabPanel : function () {
			if (admin)
				this.addTabPanel("users", "userPanel", this.navUsersText)
		},
		addGroupsTabPanel : function () {
			if (admin)
				this.addTabPanel("groups", "groupPanel", this.tabGroupsText)
		},
		createMainMenu : function () {
			if (debug)
				console.debug("create main menu");
			var panel = Ext.getCmp("navigationPanel");
			var repositoryLinks = [{
					label : this.navRepositoriesText,
					fn : this.addRepositoriesTabPanel,
					scope : this
				}
			];
			if (admin)
				repositoryLinks.push({
					label : this.navImportRepositoriesText,
					fn : function () {
						(new Sonia.repository.ImportWindow).show()
					}
				});
			panel.addSection({
				id : "navMain",
				title : this.sectionMainText,
				links : repositoryLinks
			});
			var securitySection = null;
			if (state.user.type === state.defaultUserType && state.user.name !== "anonymous")
				securitySection = {
					id : "securityConfig",
					title : this.sectionSecurityText,
					links : [{
							label : this.navChangePasswordText,
							fn : function () {
								(new Sonia.action.ChangePasswordWindow).show()
							}
						}
					]
				};
			if (admin) {
				panel.addSections([{
							id : "navConfig",
							title : this.sectionConfigText,
							links : [{
									label : this.navGeneralConfigText,
									fn : this.addScmConfigTabPanel,
									scope : this
								}, {
									label : this.navRepositoryTypesText,
									fn : this.addRepositoryConfigTabPanel,
									scope : this
								}, {
									label : this.navPluginsText,
									fn : this.addPluginTabPanel,
									scope : this
								}
							]
						}
					]);
				if (!securitySection)
					securitySection = {
						id : "securityConfig",
						title : this.sectionSecurityText,
						links : []
					};
				securitySection.links.push({
					label : this.navUsersText,
					fn : this.addUsersTabPanel,
					scope : this
				}, {
					label : this.navGroupsText,
					fn : this.addGroupsTabPanel,
					scope : this
				})
			}
			if (securitySection)
				panel.addSection(securitySection);
			if (state.user.name === "anonymous")
				panel.addSection({
					id : "navLogin",
					title : this.sectionLoginText,
					links : [{
							label : this.sectionLoginText,
							fn : this.login,
							scope : this
						}
					]
				});
			else
				panel.addSection({
					id : "navLogout",
					title : this.sectionLogoutText,
					links : [{
							label : this.navLogoutText,
							fn : this.logout,
							scope : this
						}
					]
				});
			panel.doLayout()
		},
		addTabPanel : function (id, xtype, title) {
			if (!xtype)
				xtype = id;
			var panel = {
				id : id,
				xtype : xtype,
				closable : true,
				autoScroll : true
			};
			if (title)
				panel.title = title;
			this.addTab(panel)
		},
		addTab : function (panel) {
			var tab = this.mainTabPanel.findById(panel.id);
			if (!tab)
				this.mainTabPanel.add(panel);
			this.mainTabPanel.setActiveTab(panel.id)
		},
		loadState : function (s) {
			if (debug)
				console.debug(s);
			state = s;
			admin = s.user.admin;
			this.fireEvent("login", state)
		},
		clearState : function () {
			state = null;
			repositoryTypeStore.removeAll();
			this.mainTabPanel.removeAll();
			Ext.getCmp("navigationPanel").removeAll()
		},
		checkLogin : function () {
			Ext.Ajax.request({
				url : restUrl + "authentication/state.json",
				method : "GET",
				scope : this,
				success : function (response) {
					if (debug)
						console.debug("login success");
					var s = Ext.decode(response.responseText);
					this.loadState(s)
				},
				failure : function () {
					if (debug)
						console.debug("login failed");
					var loginWin = new Sonia.login.Window;
					loginWin.show()
				}
			})
		},
		login : function () {
			this.clearState();
			var loginWin = new Sonia.login.Window;
			loginWin.show()
		},
		logout : function () {
			Ext.Ajax.request({
				url : restUrl + "authentication/logout.json",
				method : "GET",
				scope : this,
				success : function (response) {
					if (debug)
						console.debug("logout success");
					this.clearState();
					this.fireEvent("logout", state);
					var s = null;
					var text = response.responseText;
					if (text && text.length > 0)
						s = Ext.decode(text);
					if (s && s.success)
						this.loadState(s);
					else {
						var loginWin = new Sonia.login.Window;
						loginWin.show()
					}
				},
				failure : function () {
					if (debug)
						console.debug("logout failed");
					Ext.Msg.alert(this.logoutFailedText)
				}
			})
		},
		addListeners : function (event, callbacks) {
			Ext.each(callbacks, function (callback) {
				if (Ext.isFunction(callback))
					this.addListener(event, callback);
				else if (Ext.isObject(callback))
					this.addListener(event, callback.fn, callback.scope);
				else if (debug)
					console.debug("callback is not a function or object. " + callback)
			}, this)
		},
		handleRestFailure : function (response,
			title, message) {
			this.handleFailure(response.status, title, message, response.responseText)
		},
		handleFailure : function (status, title, message, serverException) {
			if (debug)
				console.debug("handle failure for status code: " + status);
			if (status === 401)
				Ext.Msg.show({
					title : this.errorSessionExpiredTitle,
					msg : this.errorSessionExpiredMessage,
					buttons : Ext.Msg.OKCANCEL,
					fn : function (btn) {
						if (btn === "ok")
							this.login()
					},
					scope : this
				});
			else if (status === 403)
				Ext.Msg.show({
					title : this.errorNoPermissionsTitle,
					msg : this.errorNoPermissionsMessage,
					buttons : Ext.Msg.OKCANCEL
				});
			else if (status === 404)
				Ext.Msg.show({
					title : this.errorNotFoundTitle,
					msg : this.errorNotFoundMessage,
					buttons : Ext.Msg.OKCANCEL
				});
			else {
				if (!title)
					title = this.errorTitle;
				if (!message)
					message = this.errorMessage;
				var text = null;
				if (serverException)
					try {
						if (Ext.isString(serverException))
							serverException = Ext.decode(serverException);
						text = serverException.stacktrace;
						if (debug)
							console.debug(text)
					} catch (e) {
						if (debug)
							console.debug(e)
					}
				message = String.format(message, status);
				if (!text)
					Ext.MessageBox.show({
						title : title,
						msg : message,
						buttons : Ext.MessageBox.OK,
						icon : Ext.MessageBox.ERROR
					});
				else (new Sonia.action.ExceptionWindow({
							title : title,
							message : message,
							stacktrace : text
						})).show()
			}
		},
		loadScript : function (url, callback, scope) {
			var doCallback = function () {
				if (debug)
					console.debug("call callback for script " + url);
				if (scope)
					callback.call(scope);
				else
					callback()
			};
			if (this.scripts.indexOf(url) < 0) {
				var js = document.createElement("script");
				js.type = "text/javascript";
				js.language = "javascript";
				js.src = url;
				if (Ext.isIE)
					js.onreadystatechange = function () {
						if (this.readyState ===
							"loaded" || this.readyState === "complete")
							doCallback()
					};
				else {
					js.onload = doCallback;
					js.onerror = doCallback
				}
				if (debug)
					console.debug("load script " + url);
				document.body.appendChild(js);
				this.scripts.push(url)
			} else {
				if (debug)
					console.debug("script " + url + " allready loaded");
				doCallback()
			}
		},
		loadStylesheet : function (url) {
			if (this.stylesheets.indexOf(url) < 0) {
				var css = document.createElement("link");
				css.rel = "stylesheet";
				css.type = "text/css";
				css.href = url;
				document.getElementsByTagName("head")[0].appendChild(css);
				this.stylesheets.push(url)
			}
		},
		getMainTabPanel : function () {
			return this.mainTabPanel
		},
		renderUserInformations : function (state) {
			if (state.user.name !== "anonymous") {
				var tpl = new Ext.XTemplate(this.loggedInTextTemplate);
				tpl.overwrite(Ext.get("scm-userinfo"), state);
				var text = "";
				if (state.user.mail)
					text += this.userInfoMailText + ": " + state.user.mail + "\x3cbr /\x3e";
				if (state.groups && state.groups.length > 0)
					text += this.userInfoGroupsText + ": " + this.getGroups(state.groups) + "\x3cbr /\x3e";
				Ext.QuickTips.register({
					target : "scm-userinfo-tip",
					title : state.user.displayName,
					text : text,
					enabled : true
				})
			}
		},
		getGroups : function (groups) {
			var out = "";
			var s = groups.length;
			for (var i = 0; i < s; i++) {
				out += groups[i];
				if (i + 1 < s)
					out += ", "
			}
			return out
		},
		removeUserInformations : function () {
			Ext.get("scm-userinfo").dom.innerHTML = "";
			Ext.QuickTips.unregister("scm-userinfo-tip")
		}
	});
Ext.onReady(function () {
	function isLocalStorageAvailable() {
		var mod = "__scm-manager";
		try {
			localStorage.setItem(mod, mod);
			localStorage.removeItem(mod);
			return true
		} catch (e) {
			return false
		}
	}
	function addTabPanel(id, xtype, title) {
		main.addTabPanel(id, xtype, title)
	}
	var stateProvider;
	if (isLocalStorageAvailable()) {
		if (debug)
			console.debug("use localStore to save application state");
		stateProvider = new Sonia.uistate.WebStorageProvider
	} else {
		if (debug)
			console.debug("use cookies to save application state, because localStore is not available");
		stateProvider = new Ext.state.CookieProvider
	}
	Ext.state.Manager.setProvider(stateProvider);
	var mainTabPanel = new Ext.TabPanel({
			id : "mainTabPanel",
			region : "center",
			deferredRender : false,
			enableTabScroll : true,
			listeners : {
				tabchange : function (tabPanel, tab) {
					if (Ext.isDefined(tab))
						Sonia.History.onActivate(tab)
				}
			}
		});
	new Ext.Viewport({
		layout : "border",
		items : [new Ext.BoxComponent({
				region : "north",
				id : "north-panel",
				contentEl : "north",
				height : 60
			}), {
				region : "west",
				id : "navigationPanel",
				title : "导航",
				xtype : "navPanel",
				split : true,
				width : 200,
				minSize : 175,
				maxSize : 400,
				collapsible : true,
				margins : "0 0 0 5"
			}, new Ext.BoxComponent({
				region : "south",
				id : "south-panel",
				contentEl : "south",
				height : 16,
				margins : "2 2 2 5"
			}), mainTabPanel]
	});
	main = new Sonia.scm.Main;
	main.addListeners("init", initCallbacks);
	main.addListeners("login", loginCallbacks);
	main.addListeners("logout", logoutCallbacks);
	main.addListeners("login", function () {
		Ext.History.init()
	});
	main.addListeners("login", main.renderUserInformations);
	main.addListeners("logout", main.removeUserInformations);
	main.init();
	main.checkLogin()
});
