/*
 GAJAX
 Javascript Libraly And Ajax Frame Work
 design by http://www.goragod.com (goragod wiriya)
 17-9-53
*/
var domloaded = false;
var GBrowser = {
	IE: !!(window.attachEvent && !window.opera),
	Opera: !!window.opera,
	WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
	Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
	MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};
Object.extend = function (d, s) {
	for (var property in s) {
		d[property] = s[property];
	}
	return d;
};
Object.extend(Object, {
	isObject: function (o) {
		return typeof o == "object";
	},
	isFunction: function (o) {
		return typeof o == "function";
	},
	isString: function (o) {
		return typeof o == "string";
	},
	isNumber: function (o) {
		return typeof o == "number";
	},
	isNull: function (o) {
		return typeof o == "undefined";
	},
	isGElement: function (o) {
		return o != null && typeof o == "object" && 'getDimensions' in o && 'viewportOffset' in o;
	}
});
var GClass = {
	create: function () {
		return function () {
			this.initialize.apply(this, arguments);
		};
	}
};
var GNative = GClass.create();
GNative.prototype = {
	initialize: function () {
		this.elem = null;
		this.timeout = 1000;
		this.interval = 10;
	},
	Ready: function (f) {
		this.t = 0;
		var tmp = this;
		var _p = function () {
			if (domloaded && tmp.element()) {
				f.call($G(tmp.elem));
			} else if (tmp.t < tmp.timeout) {
				window.setTimeout(_p, tmp.interval);
				tmp.t++;
			}
		};
		_p();
	},
	element: function () {
		return Object.isString(this.elem) ? document.getElementById(this.elem) : this.elem;
	},
	create: function (e) {
		this.elem = e;
		var elem = this.element();
		if (!elem) {
			return this;
		} else {
			Object.extend(elem, this);
			Object.extend(elem, {
				insert: function (e) {
					e = $G(e);
					this.appendChild(e);
					return e;
				},
				insertBefore: function (e) {
					this.parentNode.insertBefore(e);
				},
				insertAfter: function (e) {
					var p = this.parentNode;
					if (p.lastchild == this) {
						p.appendChild(e);
					} else {
						p.insertBefore(e, this.nextSibling);
					}
				},
				copy: function () {
					return $G(this.cloneNode(true));
				},
				replace: function (e) {
					this.parentNode.replaceChild(e);
				},
				remove: function () {
					this.parentNode.removeChild(this);
				},
				getTop: function () {
					return this.viewportOffset().top;
				},
				getLeft: function () {
					return this.viewportOffset().left;
				},
				getWidth: function () {
					return this.getDimensions().width;
				},
				getHeight: function () {
					return this.getDimensions().height;
				},
				viewportOffset: function () {
					var t = this.offsetTop;
					var l = this.offsetLeft;
					var p = this.offsetParent;
					while (p !== null) {
						t += p.offsetTop;
						l += p.offsetLeft;
						if (p.offsetParent == document.body && p.style.position == 'absolute') {
							break;
						}
						p = p.offsetParent;
					}
					var result = [l, t];
					result.left = l;
					result.top = t;
					return result;
				},
				getDimensions: function () {
					var ow, oh;
					if(this == document) {
						ow = Math.max(
							Math.max(document.body.scrollWidth, document.documentElement.scrollWidth),
							Math.max(document.body.offsetWidth, document.documentElement.offsetWidth),
							Math.max(document.body.clientWidth, document.documentElement.clientWidth));
						oh = Math.max(
							Math.max(document.body.scrollHeight, document.documentElement.scrollHeight),
							Math.max(document.body.offsetHeight, document.documentElement.offsetHeight),
							Math.max(document.body.clientHeight, document.documentElement.clientHeight));
					} else {
						var d = this.getStyle('display');
						if (d != 'none' && d !== null) {
							ow = this.offsetWidth;
							oh = this.offsetHeight;
						} else {
							var s = this.style;
							var ov = s.visibility;
							var op = s.position;
							var od = s.display;
							s.visibility = 'hidden';
							s.position = 'absolute';
							s.display = 'block';
							ow = this.clientWidth;
							oh = this.clientHeight;
							s.display = od;
							s.position = op;
							s.visibility = ov;
						}
					}
					var result = [ow, oh];
					result.width = ow;
					result.height = oh;
					return result;
				},
				getOffsetParent: function () {
					var e = this.offsetParent;
					if (!e) {
						e = this.parentNode;
						while (e != document.body && e.style.position == 'static') {
							e = e.parentNode;
						}
					}
					return GElement(e);
				},
				getStyle: function (s) {
					s = (s == 'float' && this.currentStyle) ? 'styleFloat' : s;
					s = (s == 'borderColor') ? 'borderBottomColor' : s;
					var v = (this.currentStyle) ? this.currentStyle[s] : null;
					v = (!v && window.getComputedStyle) ? document.defaultView.getComputedStyle(this, null).getPropertyValue(s.replace(/([A-Z])/g, "-$1").toLowerCase()) : v;
					if (s == 'opacity') {
						return v ? parseFloat(v) : 1.0;
					} else {
						return v == 'auto' ? null : v;
					}
				},
				setStyle: function (p, v) {
					if (p == 'opacity') {
						if (window.ActiveXObject) {
							this.style.filter = "alpha(opacity=" + (v * 100) + ")";
						}
						this.style.opacity = v;
					} else if (p == 'float' || p == 'styleFloat' || p == 'cssFloat') {
						if (Object.isNull(this.style.styleFloat)) {
							this.style['cssFloat'] = v;
						} else {
							this.style['styleFloat'] = v;
						}
					} else {
						this.style[p] = v;
					}
					return this;
				},
				center: function (s) {
					var size = this.getDimensions();
					this.style.top = (document.viewport.getscrollTop() + ((document.viewport.getHeight() - size.height) / 2)) + 'px';
					this.style.left = (document.viewport.getscrollLeft() + ((document.viewport.getWidth() - size.width) / 2)) + 'px';
					return this;
				},
				get: function (p) {
					return this.getAttribute(p);
				},
				set: function (p, v) {
					this.setAttribute(p, v);
					return this;
				},
				hasClass: function (v) {
					var ret = false;
					forEach(this.className.split(' '), function (c) {
						if (c == v) {
							ret = true;
						}
					});
					return ret;
				},
				addClass: function (v) {
					var cs = new Array();
					forEach(this.className.split(' '), function (c) {
						if (c !== '' && c != v) {
							cs.push(c);
						}
					});
					cs.push(v);
					this.className = cs.join(' ');
					return this;
				},
				removeClass: function (v) {
					var cs = new Array();
					forEach(this.className.split(' '), function (c) {
						if (c !== '' && c != v) {
							cs.push(c);
						}
					});
					this.className = cs.join(' ');
					return this;
				},
				hide: function () {
					this.setStyle('visibility', 'hidden');
					return this;
				},
				show: function () {
					this.setStyle('visibility', 'visible');
					return this;
				},
				visible: function () {
					return this.style.visibility != 'hidden';
				},
				toggle: function () {
					if (this.visible()) {
						this.hide();
					} else {
						this.show();
					}
					return this;
				},
				addEvent: function (t, f, c) {
					if (this.addEventListener) {
						c = !c ? false : c;
						this.addEventListener(t, f, c);
					} else if (this.attachEvent) {
						var tmp = this;
						tmp["e" + t + f] = f;
						tmp[t + f] = function () {
							tmp["e" + t + f](window.event);
						};
						tmp.attachEvent("on" + t, tmp[t + f]);
					}
					return this;
				},
				removeEvent: function (t, f) {
					if (this.removeEventListener) {
						this.removeEventListener(((t == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : t), f, false);
					} else {
						this.detachEvent('on' + t, f);
					}
					return this;
				}
			});
			return elem;
		}
	}
};
var GElement = new GNative();
function $G(e) {
	return GElement.create(e);
}
function $E(e) {
	return Object.isString(e) ? document.getElementById(e) : e;
}
document.viewport = {
	getWidth: function () {
		return document.documentElement.clientWidth || document.body.clientWidth || self.innerWidth;
	},
	getHeight: function () {
		return document.documentElement.clientHeight || document.body.clientHeight || self.innerHeight;
	},
	getscrollTop: function () {
		return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
	},
	getscrollLeft: function () {
		return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
	}
};
function forEach(a, f) {
	for (var i = 0; i < a.length; i++) {
		f.call(this, a[i], i);
	}
}
Function.prototype.bind = function (o) {
	var __method = this;
	return function () {
		return __method.apply(o, arguments);
	};
};
function functionReady(f, o) {
	var _p = function () {
		if (domloaded && typeof f != "undefined") {
			o.apply();
		} else {
			window.setTimeout(_p, 10);
		}
	};
	_p();
}
$G(window).addEvent('load', function () {
	domloaded = true;
});
if (!Array.prototype.indexOf) Array.prototype.indexOf = function (t, i) {
	i || (i = 0);
	var l = this.length;
	if (i < 0) i = l + i;
	for (; i < l; i++) {
		if (this[i] === t) {
			return i;
		}
	}
	return -1;
};
var GAjax = GClass.create();
GAjax.prototype = {
	initialize: function (options) {
		this.options = {
			method: 'post',
			cache: false,
			asynchronous: true,
			contentType: 'application/x-www-form-urlencoded',
			encoding: 'UTF-8',
			onTimeout: function () {},
			timeout: 6000
		};
		for (var property in options) {
			this.options[property] = options[property];
		}
		this.options.method = this.options.method.toLowerCase();
	},
	xhr: function () {
		var xmlHttp = null;
		try {
			xmlHttp = new XMLHttpRequest();
		} catch (e) {
			try {
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		return xmlHttp;
	},
	send: function (url, parameters, callback) {
		var self = this;
		this._xhr = this.xhr();
		this._abort = false;
		if (!Object.isNull(this._xhr)) {
			self.showLoading();
			var option = this.options;
			if (option.method == 'get') {
				url += '?' + parameters;
				parameters = null;
			} else {
				parameters = parameters === null ? '' : parameters;
			}
			if (option.cache === false) {
				var match = /\?/;
				if (match.test(url)) {
					url = url + '&timestamp=' + new Date().getTime();
				} else {
					url = url + '?timestamp=' + new Date().getTime();
				}
			}
			var onreadystatechange = function () {
				if (this._xhr.readyState == 4) {
					window.clearTimeout(self.calltimeout);
					self.hideLoading();
					if (this._xhr.status == 200 && this._abort === false && Object.isFunction(callback)) {
						self.responseText = this._xhr.responseText;
						self.responseXML = this._xhr.responseXML;
						callback(self);
					}
				}
			};
			this._xhr.open(option.method, url, option.asynchronous);
			this._xhr.onreadystatechange = onreadystatechange.bind(this);
			if (option.method == 'post') {
				this._xhr.setRequestHeader('Content-Type', option.contentType + '; charset=' + option.encoding);
				this._xhr.setRequestHeader('Content-Length', (parameters ? parameters.length : 0));
			}
			var _calltimeout = function () {
				window.clearTimeout(self.calltimeout);
				option.onTimeout.bind(self);
			};
			this.calltimeout = window.setTimeout(_calltimeout, option.timeout);
			this._xhr.send(parameters);
			if (option.asynchronous === false) {
				window.clearTimeout(this.calltimeout);
				this.responseText = this._xhr.responseText;
				this.responseXML = this._xhr.responseXML;
			}
		}
		return this;
	},
	autoupdate: function (url, interval, getrequest, callback) {
		this._xhr = this.xhr();
		this.interval = interval * 1000;
		if (!Object.isNull(this._xhr)) {
			this.url = url;
			this.getrequest = getrequest;
			this.callback = callback;
			this._abort = false;
			this._getupdate();
		}
		return this;
	},
	_getupdate: function () {
		if (this._abort === false) {
			var parameters = null;
			var url = this.url;
			var option = this.options;
			if (Object.isFunction(this.getrequest)) {
				if (option.method == 'get') {
					url += '?' + this.getrequest();
				} else {
					parameters = this.getrequest();
				}
			}
			parameters = (option.method == 'post' && parameters === null) ? '' : parameters;
			if (option.cache === false) {
				var match = /\?/;
				if (match.test(url)) {
					url = url + '&timestamp=' + new Date().getTime();
				} else {
					url = url + '?timestamp=' + new Date().getTime();
				}
			}
			var xhr = this._xhr;
			var temp = this;
			xhr.open(option.method, url, true);
			xhr.onreadystatechange = function () {
				if (xhr.readyState == 4 && xhr.status == 200) {
					temp.callback(xhr);
					window.clearTimeout(temp.calltimeout);
					temp.timeinterval = window.setTimeout(temp._getupdate.bind(temp), temp.interval);
				}
			};
			if (option.method == 'post') {
				xhr.setRequestHeader('Content-Type', option.contentType + '; charset=' + option.encoding);
				xhr.setRequestHeader('Content-Length', (parameters ? parameters.length : 0));
			}
			var _calltimeout = function () {
				window.clearTimeout(temp.calltimeout);
				temp.timeinterval = window.setTimeout(temp._getupdate.bind(temp), temp.interval);
			};
			this.calltimeout = window.setTimeout(_calltimeout, option.timeout);
			xhr.send(parameters);
		}
	},
	getRequestBody: function (pForm) {
		pForm = $E(pForm);
		var nParams = new Array();
		for (var n = 0; n < pForm.elements.length; n++) {
			if ((pForm.elements[n].checked === true && pForm.elements[n].type == "radio") || (pForm.elements[n].checked === true && pForm.elements[n].type == "checkbox") || (pForm.elements[n].type != "radio" && pForm.elements[n].type != "checkbox")) {
				var pParam = pForm.elements[n].name;
				pParam += "=";
				pParam += encodeURIComponent(pForm.elements[n].value);
				nParams.push(pParam);
			}
		}
		return nParams.join("&");
	},
	showLoading: function () {
		if (this.loading) {
			this.wait = $G(this.loading);
			if (this.wait) {
				if (this.center) {
					this.wait.setStyle('display', 'block');
					this.wait.center();
				} else {
					this.wait.setStyle('visibility', 'visible');
				}
			}
		}
		return this;
	},
	hideLoading: function () {
		if (this.wait) {
			if (this.center) {
				this.wait.setStyle('display', 'none');
			} else {
				this.wait.setStyle('visibility', 'hidden');
			}
		}
		return this;
	},
	inintLoading: function (loading, center) {
		this.loading = loading;
		this.center = center;
		return this;
	},
	abort: function () {
		clearTimeout(this.timeinterval);
		this._abort = true;
		return this;
	}
};
var GLoader = GClass.create();
GLoader.prototype = {
	initialize: function (reader, geturl, callback) {
		this.geturl = geturl;
		this.callback = callback;
		this.req = new GAjax();
		var my_location = location.toString();
		var a = my_location.indexOf('?');
		var b = my_location.indexOf('#');
		var locs = my_location.split(/[\?\#]/);
		if (a > -1 && b > -1) {
			this.lasturl = a < b ? locs[1] : locs[2];
		} else if (a > -1) {
			this.lasturl = locs[1];
		} else {
			this.lasturl = '';
		}
		var temp = this;
		window.setInterval(function () {
			locs = location.toString().split('#');
			locs = locs[1] && locs[1].indexOf('=') > -1 ? locs[1] : '';
			if (locs !== '' && locs != temp.lasturl) {
				temp.lasturl = locs;
				temp.req.send(reader, locs, callback);
			}
		}, 100);
	},
	inintLoading: function (loading, center) {
		this.req.inintLoading(loading, center);
		return this;
	},
	inint: function (obj) {
		var temp = this;
		var ret, locs;
		var patt1 = new RegExp('^.*' + location.hostname + '/(.*?)$');
		var patt2 = new RegExp('.*#.*?');
		forEach($E(obj).getElementsByTagName('a'), function (a) {
			if (a.target == '' && a.onclick == null && patt1.exec(a.href) && !patt2.exec(a.href)) {
				a.onclick = function () {
					return temp.location(this.href);
				};
			}
		});
		return this;
	},
	location: function (url) {
		var locs = window.location.toString().split('#');
		var ret = this.geturl.call(this, url);
		if (ret) {
			window.location = locs[0] + decodeURIComponent(ret);
			return false;
		}
		return true;
	}
};
var gform_id = 0;
var GForm = GClass.create();
GForm.prototype = {
	initialize: function (frm, action, loading, center, onsubmit) {
		this.form = $G(frm);
		if (action) {
			$G(this.form).set('action', action);
		}
		this.loading = loading;
		this.center = center;
		this._onsubmit = Object.isFunction(onsubmit) ? onsubmit : function () {
			return true;
		};
	},
	onsubmit: function (callback) {
		var temp = this;
		this.form.onsubmit = function () {
			if (temp._onsubmit(temp.form) == false) {
				return false;
			} else {
				temp.showLoading();
				var uploadCallback = function () {
					var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
					temp.responseText = doc.body ? doc.body.innerHTML : null;
					temp.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
					temp.hideLoading();
					io.removeEvent('load', uploadCallback);
					window.setTimeout(function () {
						io.remove();
					}, 1);
					temp.form.method = old_method;
					temp.form.target = old_target;
					if (temp.form.encoding) {
						temp.form.encoding = old_enctype;
					} else {
						temp.form.enctype = old_enctype;
					}
					callback(temp);
				}.bind(temp.form);
				var io = temp.createIframe();
				var old_target = this.target || '';
				var old_method = this.method || "post";
				var old_enctype = this.encoding ? this.encoding : this.enctype;
				if (this.encoding) {
					this.encoding = 'multipart/form-data';
				} else {
					this.enctype = 'multipart/form-data';
				}
				io.addEvent('load', uploadCallback);
				this.target = io.id;
				this.method = 'post';
				return true;
			}
		};
	},
	submit: function (callback) {
		var temp = this;
		this.showLoading();
		var uploadCallback = function () {
			temp.hideLoading();
			var xhr = {};
			try {
				xhr.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
				xhr.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;
			} catch (e) {}
			io.removeEvent('load', uploadCallback);
			window.setTimeout(function () {
				io.remove();
			}, 1);
			temp.form.method = old_method;
			temp.form.target = old_target;
			callback(xhr);
		}.bind(this);
		if (this.form.encoding) {
			this.form.encoding = 'multipart/form-data';
		} else {
			this.form.enctype = 'multipart/form-data';
		}
		var io = this.createIframe();
		var old_target = this.form.target || '';
		var old_method = this.form.method || "post";
		io.addEvent('load', uploadCallback);
		this.form.target = io.id;
		this.form.method = "post";
		this.form.submit();
		return this;
	},
	createIframe: function () {
		var frameId = 'GForm_Submit_' + gform_id + '_' + (this.form.id || this.form.name);
		gform_id++;
		var io;
		if (window.ActiveXObject) {
			io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
			io.src = 'javascript:false';
		} else {
			io = document.createElement('iframe');
			io.setAttribute('id', frameId);
			io.setAttribute('name', frameId);
		}
		io.style.position = 'absolute';
		io.style.top = '-1000px';
		io.style.left = '-1000px';
		document.body.appendChild(io);
		return $G(io);
	},
	showLoading: function () {
		if (this.loading) {
			this.wait = $G(this.loading);
			if (this.wait) {
				if (this.center) {
					this.wait.setStyle('display', 'block');
					this.wait.center();
				} else {
					this.wait.setStyle('visibility', 'visible');
				}
			}
		}
	},
	hideLoading: function () {
		if (this.wait) {
			if (this.center) {
				this.wait.setStyle('display', 'none');
			} else {
				this.wait.setStyle('visibility', 'hidden');
			}
		}
	},
	inintLoading: function (loading, center) {
		this.loading = loading;
		this.center = center;
		return this;
	}
};
var GModal = GClass.create();
GModal.prototype = {
	initialize: function (options) {
		this.id = 'modaldiv';
		this.btnclose = 'btnclose';
		this.onhide = function () {};
		for (var property in options) {
			this[property] = options[property];
		}
		var self = this;
		var checkESCkey = function (event) {
			var keycode = event.which || event.keyCode;
			if (keycode == 27) {
				self.hide();
				GEvent.stop(event);
				return false;
			}
		};
		var container_div = 'GModal_div';
		if (!$E(container_div)) {
			var doc = $G(document);
			doc.addEvent('keypress', checkESCkey);
			doc.addEvent('keydown', checkESCkey);
			var div = doc.createElement('div');
			doc.body.appendChild(div);
			div.id = container_div;
			div.style.left = '-1000px';
			div.style.position = 'absolute';
			var c  = doc.createElement('div');
			div.appendChild(c);
			c.id = this.id;
			var s = doc.createElement('span');
			div.appendChild(s);
			s.id = this.btnclose;
			s.style.position = 'absolute';
			s.style.top = '0px';
			s.style.right = '0px';
			s.style.cursor = 'pointer';
			s.onclick = function() {
				self.hide();
			}
		}
		this.div = $G(container_div);
		this.div.setStyle('opacity', 0);
	},
	show: function (value) {
		$E(this.id).innerHTML = value;
		this.div.style.display = '';
		this.div.center();
		this.overlay();
		new GFade(this.div).play({
			'from': 0,
			'to': 100,
			'speed': 1,
			'duration': 20
		});
		this.div.style.zIndex = 9999;
		return this;
	},
	hide: function () {
		new GFade(this.div).play({
			'from': 100,
			'to': 0,
			'speed': 1,
			'duration': 20,
			'onComplete': this._hide.bind(this)
		});
		return this;
	},
	overlay: function () {
		var frameId = 'GModal_iframe';
		if (!$E(frameId)) {
			var io = null;
			if (window.ActiveXObject) {
				io = document.createElement('<iframe id="' + frameId + '" height="100%" />');
			} else {
				io = document.createElement('iframe');
				io.setAttribute('id', frameId);
			}
			io.setAttribute('frameBorder', '0');
			io.style.position = 'absolute';
			document.body.appendChild(io);
			if (document.all) {
				document.frames(frameId).document.bgColor = '#000000';
			} else {
				io.style.backgroundColor = '#000000';
			}
			io.style.zIndex = 8888;
		}
		this.iframe = $G(frameId);
		this.iframe.style.left = '0px';
		this.iframe.style.top = '0px';
		this.iframe.setStyle('opacity', 0.7);
		this.iframe.style.display = 'block';
		var d = $G(document).getDimensions();
		this.iframe.style.height = d.height + 'px';
		this.iframe.style.width = d.width + 'px';
		return this;
	},
	_hide: function () {
		this.iframe.style.display = 'none';
		this.div.style.display = 'none';
		this.onhide.call(this);
	}
};
var GFx = function () {};
GFx.prototype = {
	_run: function () {
		this.playing = true;
		this.step();
	},
	stop: function () {
		this.playing = false;
		this.options.onComplete.call(this, this);
	}
};
var GFade = GClass.create();
GFade.prototype = Object.extend(new GFx(), {
	initialize: function (el) {
		this.options = {
			from: 0,
			to: 100,
			speed: 50,
			duration: 5,
			unit: '',
			onComplete: function () {}
		};
		this.Element = $G(el);
		this.playing = false;
		this.timer = 0;
	},
	play: function (options) {
		for (var property in options) {
			this.options[property] = options[property];
		}
		if (this.options.to > this.options.from) {
			this.name = 'fadeIn';
			this.to = (this.options.to > 100) ? 100 : this.options.to;
			this.from = (this.options.from < 0) ? 0 : this.options.from;
		} else {
			this.name = 'fadeOut';
			this.to = (this.options.to < 0) ? 0 : this.options.to;
			this.from = (this.options.from > 100) ? 100 : this.options.from;
		}
		if (!this.playing) {
			this.now = this.from;
			this._run();
		}
		return this;
	},
	step: function () {
		if (this.playing) {
			this.Element.setStyle('opacity', this.now / 100);
		}
		var now = (this.name == 'fadeIn') ? this.now + this.options.duration : this.now - this.options.duration;
		if (this.playing && ((this.name == 'fadeOut' && now >= this.to) || (this.name == 'fadeIn' && now <= this.to))) {
			this.now = now;
			var temp = this;
			this.timer = window.setTimeout(temp.step.bind(temp), temp.options.speed);
		} else {
			this.stop();
		}
	}
});
var GHighlight = GClass.create();
GHighlight.prototype = Object.extend(new GFx(), {
	initialize: function (el) {
		this.options = {
			from: 'red',
			to: 'auto',
			speed: 10,
			time: 20,
			unit: '',
			onComplete: function () {}
		};
		this.Element = $G(el);
		this.playing = false;
		this.timer = 0;
	},
	play: function (options) {
		for (var property in options) {
			this.options[property] = options[property];
		}
		if (this.options.from == 'red') {
			this.options.from = {
				'borderColor': '#FF0000',
				'backgroundColor': '#FFBFBF'
			};
		} else if (this.options.from == 'green') {
			this.options.from = {
				'borderColor': '#00FF00',
				'backgroundColor': '#E3F4E3'
			};
		}
		var source = this.options.from;
		if (Object.isObject(source)) {
			var destination = {};
			for (property in source) {
				destination[property] = source[property].ToRgb();
			}
			this.from = destination;
		}
		source = this.options.to;
		destination = {};
		if (Object.isObject(source)) {
			for (property in source) {
				destination[property] = source[property].ToRgb();
			}
			this.to = destination;
		} else if (source == 'auto') {
			source = this.options.from;
			for (property in source) {
				destination[property] = this.Element.getStyle(property).ToRgb();
			}
			this.to = destination;
		}
		source = this.options.from;
		if (source == 'auto') {
			source = this.options.to;
			for (property in source) {
				destination[property] = this.Element.getStyle(property).ToRgb();
			}
			this.from = destination;
		}
		this.delta = [];
		var to, from;
		for (property in this.from) {
			to = this.to[property];
			from = this.from[property];
			this.delta[property] = [
				(to[0] - from[0]) / this.options.time,
				(to[1] - from[1]) / this.options.time,
				(to[2] - from[2]) / this.options.time
				];
		}
		if (!this.playing) {
			this.now = 0;
			this._run();
		}
        return this;
	},
	step: function () {
		if (this.playing) {
			var colors;
			for (var property in this.from) {
				colors = this.from[property];
				this.Element.setStyle(property, 'rgb(' + parseInt(colors[0] + (this.delta[property][0] * this.now)) + ',' + parseInt(colors[1] + (this.delta[property][1] * this.now)) + ',' + parseInt(colors[2] + (this.delta[property][2] * this.now)) + ')');
			}
		}
		this.now++;
		if (this.now > this.options.time) {
			this.stop();
		} else {
			this.timer = window.setTimeout(this.step.bind(this), this.options.speed);
		}
	}
});
var GScroll = GClass.create();
GScroll.prototype = Object.extend(new GFx(), {
	initialize: function (container, scroller) {
		this.options = {
			speed: 30,
			duration: 1,
			pauseit: 1,
			scrollto: 'top'
		};
		this.container = $G(container);
		this.scroller = $G(scroller);
		this.container.addEvent('mouseover', function () {
			this.rel = 'pause';
		});
		this.container.addEvent('mouseout', function () {
			this.rel = 'play';
		});
		this.container.rel = 'play';
		this.playing = false;
		var size = this.container.getDimensions();
		this.containerHeight = size.height;
		this.containerWidth = size.width;
	},
	play: function (options) {
		for (var property in options) {
			this.options[property] = options[property];
		}
		this.scrollerTop = 0;
		this.scrollerLeft = 0;
		this._run();
        return this;
	},
	step: function () {
		if (this.container.rel == 'play' || this.options.pauseit != 1) {
			if (this.options.scrollto == 'bottom') {
				this.scrollerTop = this.scrollerTop > this.containerHeight ? 0 - this.scroller.getHeight() : this.scrollerTop + this.options.duration;
				this.scroller.style.top = this.scrollerTop + 'px';
			} else if (this.options.scrollto == 'left') {
				this.scrollerLeft = this.scrollerLeft + this.scroller.getWidth() < 0 ? this.containerWidth : this.scrollerLeft - this.options.duration;
				this.scroller.style.left = this.scrollerLeft + 'px';
			} else if (this.options.scrollto == 'right') {
				this.scrollerLeft = this.scrollerLeft > this.containerWidth ? 0 - this.scrollerWidth : this.scrollerLeft + this.options.duration;
				this.scroller.style.left = this.scrollerLeft + 'px';
			} else {
				this.scrollerTop = this.scrollerTop + this.scroller.getHeight() < 0 ? this.containerHeight : this.scrollerTop - this.options.duration;
				this.scroller.style.top = this.scrollerTop + 'px';
			}
		}
		this.timer = window.setTimeout(this.step.bind(this), this.options.speed);
	}
});
var HScroll = GClass.create();
HScroll.prototype = Object.extend(new GFx(), {
	initialize: function (container, scroller) {
		this.options = {
			speed: 30,
			duration: 5,
			arrowTop: 'arrowTop',
			arrowBottom: 'arrowBottom'
		};
		var temp = this;
		this.scroller = $G(scroller);
		this.containerHeight = $G(container).getDimensions().height;
	},
	play: function (options) {
		for (var property in options) {
			this.options[property] = options[property];
		}
		var temp = this;
		var arrowTop = $G(this.options.arrowTop);
		arrowTop.addEvent('mouseover', function () {
			temp.rel = 'play';
			temp.pos = 'down';
		});
		arrowTop.addEvent('mouseout', function () {
			temp.rel = 'pause';
		});
		var arrowBottom = $G(this.options.arrowBottom);
		arrowBottom.addEvent('mouseover', function () {
			temp.rel = 'play';
			temp.pos = 'up';
		});
		arrowBottom.addEvent('mouseout', function () {
			temp.rel = 'pause';
		});
		this.scrollerTop = 0;
		this._run();
        return this;
	},
	step: function () {
		if (this.rel == 'play') {
			if (this.pos == 'up' && this.scrollerTop < 0) {
				this.scrollerTop = this.scrollerTop + this.options.duration;
				this.scroller.style.top = this.scrollerTop + 'px';
			} else if (this.pos == 'down' && this.scroller.getHeight() + this.scrollerTop > this.containerHeight) {
				this.scrollerTop = this.scrollerTop - this.options.duration;
				this.scroller.style.top = this.scrollerTop + 'px';
			}
		}
		this.timer = window.setTimeout(this.step.bind(this), this.options.speed);
	}
});
var VScroll = GClass.create();
VScroll.prototype = Object.extend(new GFx(), {
	initialize: function (container, scroller, options) {
		this.options = {
			speed: 30,
			duration: 5,
			arrowLeft: 'arrowLeft',
			arrowRight: 'arrowRight'
		};
		for (var property in options) {
			this.options[property] = options[property];
		}
		var temp = this;
		var arrowLeft = $G(this.options.arrowLeft);
		arrowLeft.addEvent('mouseover', function () {
			temp.rel = 'play';
			temp.pos = 'left';
		});
		arrowLeft.addEvent('mouseout', function () {
			temp.rel = 'pause';
		});
		var arrowRight = $G(this.options.arrowRight);
		arrowRight.addEvent('mouseover', function () {
			temp.rel = 'play';
			temp.pos = 'right';
		});
		arrowRight.addEvent('mouseout', function () {
			temp.rel = 'pause';
		});
		this.scroller = $G(scroller);
		this.container = $G(container);
		this.containerWidth = this.container.getWidth();
		this.rel == 'pause';
	},
	play: function () {
		this.scrollerWidth = this.scroller.getWidth();
		this.scrollerLeft = 0;
		this._run();
        return this;
	},
	step: function () {
		if (this.rel == 'play') {
			if (this.pos == 'left' && this.scrollerLeft < 0) {
				this.scrollerLeft = this.scrollerLeft + this.options.duration;
				this.scrollerLeft = this.scrollerLeft > 0 ? 0 : this.scrollerLeft;
				$E(this.scroller).style.left = this.scrollerLeft + 'px';
			} else if (this.pos == 'right' && (this.scrollerLeft + this.scrollerWidth) >= this.containerWidth) {
				this.scrollerLeft = this.scrollerLeft - this.options.duration;
				this.scrollerLeft = this.scrollerLeft < 0 - this.containerWidth ? 0 - this.containerWidth : this.scrollerLeft;
				$E(this.scroller).style.left = this.scrollerLeft + 'px';
			}
		} else if (this.rel == 'move') {
			if (this.scrollTo < this.scrollerLeft && this.scrollerWidth + this.scrollerLeft > this.containerWidth) {
				this.scrollerLeft = this.scrollerLeft - this.options.duration;
				this.scrollerLeft = this.scrollerLeft < this.scrollTo ? this.scrollTo : this.scrollerLeft;
				$E(this.scroller).style.left = this.scrollerLeft + 'px';
			} else if (this.scrollTo > this.scrollerLeft && this.scrollerLeft < 0) {
				this.scrollerLeft = this.scrollerLeft + this.options.duration;
				this.scrollerLeft = this.scrollerLeft > this.scrollTo ? this.scrollTo : this.scrollerLeft;
				$E(this.scroller).style.left = this.scrollerLeft + 'px';
			} else {
				this.rel == 'pause';
			}
		}
		this.timer = window.setTimeout(this.step.bind(this), this.options.speed);
	},
	MoveTo: function (e) {
		if ($E(e)) {
			e = $G(e);
			this.scrollTo = this.scroller.getLeft() - ((e.getLeft() + e.getWidth()) - this.containerWidth + 5);
		} else {
			this.scrollTo = 0;
		}
		this.rel = 'move';
        return this;
	}
});
var GSlide = GClass.create();
GSlide.prototype = Object.extend(new GFx(), {
	initialize: function () {
		this.options = {
			speed: 30,
			duration: 1,
			from: 0,
			to: 0,
			onSlide: function () {}
		};
	},
	play: function (options) {
		for (var property in options) {
			this.options[property] = options[property];
		}
		this.Pos = this.options.from;
		this._run();
        return this;
	},
	step: function () {
		var option = this.options;
		if (option.to > option.from && this.Pos < option.to) {
			this.Pos = this.Pos + option.duration;
			this.Pos = this.Pos > option.to ? option.to : this.Pos;
			option.onSlide.call(this);
			this.timer = window.setTimeout(this.step.bind(this), option.speed);
		} else if (option.to < option.from && this.Pos > option.to) {
			this.Pos = this.Pos - option.duration;
			this.Pos = this.Pos < option.to ? option.to : this.Pos;
			option.onSlide.call(this);
			this.timer = window.setTimeout(this.step.bind(this), option.speed);
		}
	}
});
var GCrossFade = GClass.create();
GCrossFade.prototype = Object.extend(new GFx(), {
	initialize: function (elem, options) {
		this.options = {
			speed: 10,
			loop: true,
			auto: true,
			onChanged: function () {}
		};
		for (var property in options) {
			this.options[property] = options[property];
		}
		this.Slide = $G(elem);
		var size = this.Slide.getDimensions();
		this.width = size.width;
		this.height = size.height;
		var img = document.createElement('img');
		img.src = 'blank.gif';
		img.style.position = 'absolute';
		img.style.left = '-10000px';
		this.Slide.insert(img);
		this.img1 = img;
		img = document.createElement('img');
		img.src = 'blank.gif';
		img.style.position = 'absolute';
		img.style.left = '-10000px';
		this.Slide.insert(img);
		this.img2 = img;
		this.currImg = this.img2;
		this.fader = 0;
		this.action = 'stop';
	},
	next: function (val) {
		window.clearTimeout(this.fader);
		var pos = this.Pos + val;
		pos = pos >= this.pictures.length ? this.pictures.length - 1 : pos;
		pos = pos < 0 ? 0 : pos;
		if (pos != this.Pos) {
			this.show(pos);
		}
        return this;
	},
	play: function () {
		this.nextPos = this.Pos + 1;
		this._run();
        return this;
	},
	step: function () {
		if (this.options.loop) {
			this.nextPos = this.nextPos >= this.pictures.length ? 0 : this.nextPos;
		} else if (this.nextPos >= this.pictures.length) {
			return;
		}
		var temp = this;
		new preload(this.pictures[this.nextPos], function () {
			temp.currImg = temp.currImg == temp.img2 ? temp.img1 : temp.img2;
			var old = temp.currImg == temp.img2 ? temp.img1 : temp.img2;
			temp._resizeImage(temp.currImg, this);
			new GFade(temp.currImg).play({
				'onComplete': function () {
					temp.fader = window.setTimeout(temp.step.bind(temp), temp.options.speed * 1000);
					temp.Pos = temp.nextPos;
					temp.options.onChanged.call(temp);
					temp.nextPos++;
				}
			});
			new GFade(old).play({
				'from': 100,
				'to': 0
			});
			temp.currImg.style.zIndex = 1;
			old.style.zIndex = 0;
		});
	},
	show: function (id) {
		var temp = this;
		new preload(this.pictures[id], function () {
			temp.currImg = temp.currImg == temp.img2 ? temp.img1 : temp.img2;
			var old = temp.currImg == temp.img2 ? temp.img1 : temp.img2;
			temp._resizeImage(temp.currImg, this);
			new GFade(temp.currImg).play({
				'onComplete': function () {
					temp.Pos = id;
					temp.options.onChanged.call(temp);
				}
			});
			new GFade(old).play({
				'from': 100,
				'to': 0
			});
			temp.currImg.style.zIndex = 1;
			old.style.zIndex = 0;
		});
        return this;
	},
	pictures: function (files) {
		this.pictures = files.split(',');
		this.picturesWidth = new Array();
		this.picturesHeight = new Array();
		if (this.options.auto) {
			this.Pos = 0;
			this.play();
		} else {
			this.show(0);
		}
        return this;
	},
	_resizeImage: function (img, obj) {
		img.src = obj.src;
		var w = obj.width;
		var h = obj.height;
		var nw, nh;
		if (w >= h) {
			if (w > this.width) {
				nw = this.width;
				nh = (this.width * h) / w;
			} else if (h > this.height) {
				nh = this.height;
				nw = (this.height * w) / h;
			} else {
				nh = h;
				nw = w;
			}
		} else {
			if (h > this.height) {
				nh = this.height;
				nw = (this.height * w) / h;
			} else if (w > this.width) {
				nw = this.width;
				nh = (this.width * h) / w;
			} else {
				nh = h;
				nw = w;
			}
		}
		img.style.width = nw + 'px';
		img.style.height = nh + 'px';
		img.style.top = ((this.height - nh) / 2) + 'px';
		img.style.left = ((this.width - nw) / 2) + 'px';
	}
});
var preload = GClass.create();
preload.prototype = {
	initialize: function (img, onComplete) {
		if (Object.isString(img)) {
			this.img = new Image();
			this.img.src = img;
		} else {
			this.img = img;
		}
		this.onComplete = onComplete;
		setTimeout(this.preload.bind(this), 30);
	},
	preload: function () {
		if (this.img.complete) {
			this.onComplete.call(this.img);
		} else {
			setTimeout(this.preload.bind(this), 30);
		}
	}
};
var GEvent = {
	isButton: function (event, code) {
		var buttonMap = {
			0: 1,
			1: 4,
			2: 2
		};
		if (GBrowser.IE) {
			return event.button == buttonMap[code];
		} else if (GBrowser.WebKit) {
			switch (code) {
			case 0:
				return event.which == 1 && !event.metaKey;
			case 1:
				return event.which == 1 && event.metaKey;
			default:
				return false;
			}
		} else {
			return event.which ? (event.which === code + 1) : (event.button === code);
		}
	},
	isLeftClick: function (event) {
		return GEvent.isButton(event, 0)
	},
	isMiddleClick: function (event) {
		return GEvent.isButton(event, 1)
	},
	isRightClick: function (event) {
		return GEvent.isButton(event, 2)
	},
	element: function (event) {
		var node = event.target ? event.target : event.srcElement;
		return event.nodeType == 3 ? node.parentNode : node;
	},
	keyCode: function (event) {
		return event.which || event.keyCode;
	},
	stop: function (event) {
		if (event.stopPropagation) {
			event.stopPropagation();
			event.preventDefault();
		} else {
			event.cancelBubble = true;
			event.returnValue = false;
		};
        return this;
	},
	pointer: function (event) {
		return {
			x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)),
			y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop))
		};
	},
	pointerX: function (event) {
		return GEvent.pointer(event).x
	},
	pointerY: function (event) {
		return GEvent.pointer(event).y
	}
};
var Cookie = {
	get: function (k) {
		var v = document.cookie.match('(?:^|;)\\s*' + k.escapeRegExp() + '=([^;]*)');
		return (v) ? decodeURIComponent(v[1]) : null;
	},
	set: function (k, v, options) {
		var _options = {
			path: false,
			domain: false,
			duration: false,
			secure: false
		};
		for (var property in options) {
			_options[property] = options[property];
		}
		v = encodeURIComponent(v);
		if (_options.domain) {
			v += '; domain=' + _options.domain;
		}
		if (_options.path) {
			v += '; path=' + _options.path;
		}
		if (_options.duration) {
			var date = new Date();
			date.setTime(date.getTime() + _options.duration * 24 * 60 * 60 * 1000);
			v += '; expires=' + date.toGMTString();
		}
		if (_options.secure) {
			v += '; secure';
		}
		document.cookie = k + '=' + v;
        return this;
	},
	remove: function (k) {
		Cookie.set(k, '', {
			duration: -1
		});
        return this;
	}
};
var GValidator = GClass.create();
GValidator.prototype = {
	initialize: function (input, result, events, validtor, action, callback, form) {
		this.timer = 0;
		this.req = new GAjax();
		this.interval = 1000;
		var ret = null;
		this.input = $G(input);
		this.result = $E(result);
		var temp = this;
		if (form && form !== '') {
			form = $G(form);
			form.addEvent('submit', function (event) {
				temp.abort();
			});
		}
		var _validtor = function (event) {
			temp.abort();
			ret = validtor.call(temp.input, temp.result);
			if (form && ret && action && ret !== '' && action !== '') {
				temp.timer = window.setTimeout(function () {
					temp.req.send(action, ret, function (xhr) {
						callback.call(temp, xhr);
					});
				}, temp.interval);
			}
		};
		forEach(events.split(','), function (item) {
			temp.input.addEvent(item, _validtor);
		});
	},
	abort: function () {
		window.clearTimeout(this.timer);
		this.req.abort();
        return this;
	},
	interval: function (value) {
		this.interval = value;
        return this;
	}
};
Object.extend(String.prototype, {
	hexToRgb: function (a) {
		var h = this.match(new RegExp('^[#]{0,1}([\\w]{1,2})([\\w]{1,2})([\\w]{1,2})$'));
		var rgb = [];
		for (var i = 1; i < h.length; i++) {
			if (h[i].length == 1) {
				h[i] += h[i];
			}
			rgb.push(parseInt(h[i], 16));
		};
		var rgbText = 'rgb(' + rgb.join(',') + ')';
		if (a) {
			return [parseFloat(rgb[0]), parseFloat(rgb[1]), parseFloat(rgb[2])];
		} else {
			return rgbText;
		}
	},
	ToRgb: function () {
		if (this.match(/^#[0-9a-f]{3,6}$/i)) {
			return this.hexToRgb(true);
		} else {
			return ((value = this.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [parseFloat(value[1]), parseFloat(value[2]), parseFloat(value[3])] : false;
		}
	},
	entityify: function () {
		return this.
			replace(/&/g, '&amp;').
			replace(/</g, '&lt;').
			replace(/>/g, '&gt;').
			replace(/"/g, '&quot;');
	},
	unentityify: function () {
		return this.
			replace(/&amp;/g, '&').
			replace(/&lt;/g, '<').
			replace(/&gt;/g, '>').
			replace(/&quot;/g, '"');
	},
	toJSON: function () {
		try {
			return eval('(' + this + ')');
		} catch (e) {
			return false;
		};
	},
	escapeRegExp: function () {
		return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
	},
	capitalize: function () {
		return this.replace(/\b[a-z]/g, function (m) {
			return m.toUpperCase();
		});
	},
	evalScript: function () {
		var regex = /<script type="text\/javascript">(.*?)<\/script>/g;
		var t = this.replace(/[\r\n]/g, '').
			replace(/\/\/<\!\[CDATA\[/g, '').
			replace(/\/\/\]\]>/g, '');
		m = regex.exec(t);
		while (m) {
			try {
				eval(m[1]);
			} catch (e) {};
			m = regex.exec(t);
		};
        return this;
	},
	leftPad: function (c, f) {
		var r = '';
		for (var i = 0; i < (c - this.length); i++) {
			r = r + f;
		}
		return r + this;
	}
});
