/*
 * Savvy.js Library
 * Name: Savvy.Core
 * Version: 0.1.1.4 (Beta)
 * Required: Tested on IE6, IE7, Firefox 1.5+ and Opera 9.2. Other browser support is unknown/untested.
 * Last Updated: 22.06.2007
 * Author: Cryno Bone http://www.chronosight.net/
 ***************************************************
 * References:
 * 1. pick() function taken directly from Mootools Framework
 * 2. Draggable and Resizable object taken with modification from dom-drag.js by www.youngpup.net
 * 3. DOM.addAfter() function taken from Dustin Diaz's Top 10 JaScript Functions at <http://www.dustindiaz.com/top-ten-javascript/>
 * 4. Few prototype function taken from <http://www.hunlock.com/blogs/Ten_Javascript_Tools_Everyone_Should_Have> and <http://20bits.com/2007/03/08/the-philosophy-of-javascript/>
*/
var Savvy = {};
Savvy = {
	version:"0.1.1.3 (Beta)",
	log:function(v) {
		try { 
			console.log(v); 
		} catch(e) { 
			alert(v); 
		}
	},
	images:{
		
	},
	href:function(u) {
		window.location.href = u;
	},
	browser:function() {
		return function() {
			var win = new Object;
			win.ie = win[window.XMLHttpRequest ? "ie7" : "ie6"] = (window.ActiveXObject ? true : false);
			win.khtml = ((document.childNodes && !document.all && !navigator.taintEnabled) ? true : false);
			win.gecko = (document.getBoxObjectFor != null ? true : false);
			win.opera = (window.opera ? true : false);
			return win;
		}();
	}(),
	chain:function (o, params) {
		if(is_null(params)) {
			var params = ({
				addDOM:function(c) { 
					return DOM.add(this,c);
				},
				addTextDOM:function(t) {
					return DOM.addText(this, t);
				},
				removeDOM:function(c) {
					return DOM.remove(this, c);
				},
				setAttrib:function(a,v) {
					return Attrib.set(this, a, v);
				},
				getAttrib:function(a) {
					return Attrib.get(this, a);
				},
				removeAttrib:function(a) {
					return Attrib.remove(this, a);
				},
				setupAttrib:function(jon) {
					return Attrib.setup({
						obj:this,
						attrib:jon
					});
				},
				addClass:function(a) {
					return ClassAss.add(this, a);
				},
				appendClass:function(a) {
					return ClassAss.append(this, a);
				},
				removeClass:function(a) {
					return ClassAss.remove(this, a);
				},
				hasClass:function(a) {
					return ClassAss.has(this, a);
				},
				setCSS:function(a, v) {
					return CSS.set(this, a, v);
				},
				getCSS:function(a) {
					return CSS.get(this, a);
				},
				pngCSS:function(jon) {
					jon.obj = this;
					return CSS.png(jon);
				},
				styler:function(jon) {
					return CSS.styler({
						obj:this,
						css:jon
					});
				},
				FxToggleY:function(jon) {
					jon.obj = this;
					Animation.y.init(jon);
					return this;
				},
				FxToggleX:function(jon) {
					jon.obj = this;
					Animation.x.init(jon);
					return this;
				},
				FxOpacity:function(jon) {
					jon.obj = this;
					Opacity.init(jon);
					return this;
				},
				addHTML:function(t) {
					this.innerHTML = t; return this; },
				appendHTML:function(t) {
					this.innerHTML = this.innerHTML.concat(t);
					return this;
				},
				bind:function(t, fn) {
					try {
						this["on".concat(t)] = fn;
					} catch(e) { }
					return this;
				},
				bindListener:function(t, fn) {
					this.bindfunc = fn;
					Event.On({
						trigger:t,
						load_function:this.bindfunc,
						obj:this
					});
					return this;
				},
				callback:function(fn) { 
					this.callbackfunc = fn;
					this.callbackfunc();
					return this;
				},
				each:function(fn) {
					for(var i=0; i<this.length; i++) {
						this[i].callback(fn); 
					}
				}
			});
		}
		var obj = function(o) {
			function F() {};
			F.prototype = o;
			return new F();
		};
		
		for (key in params) {
			try {
				o[key] = params[key];
			} catch(e) { }
		}
		return obj;
	}
};

Array.prototype.inArray = function(v){
	for (var i = 0; i < this.length; i++) {
		if(this[i] === v) {
			return true;
		}
	}
	return false;
};
Array.prototype.each = function(f) {
	for(var i=0; i<this.length; i++) {
		if(typeof(v) == "function") {
			this.callback(f);
		}
	}
};
Array.prototype.map = function(f) {
	var r=[];
	for(var i = 0; i < this.length; i++) {
		r.push(f(this[i]));
	}
	return r;
};
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
};
String.prototype.ltrim = function() {
	return this.replace(/^\s+/g,"");
};
String.prototype.rtrim = function() {
	return this.replace(/\s+$/g,"");
};
String.prototype.striptags = function() {
	return this.replace(/<([^>]+)>/g,"");
};
String.prototype.htmlentities = function () {
	return this.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
};
String.prototype.toNumber = function () {
	return parseInt(this,10);
};
Number.prototype.toNumber = function() {
	return this;
};

var Activity = {};
Activity = {
	status:null,
	show:function(b) {
		b = (is_null(b) ? true : b);
		
		if(b == true) {
			this.overlay.on();
		}
		
		var o = Element.Create("img");
		var imgPreload = new Image();
		this.status = "loading";
		
		imgPreload.onload = function() {
			if(!is_null(Activity.status)) {
				o.src = Savvy.images.activity;
				this.status = "loaded";
				
				var dimension = Windows.getPositionCenter(this.width, this.height);
				
				o.styler([{
					"width":this.width+"px",
					"height":this.height+"px"
				}]);
				
				var d = Element.Create("div").setAttrib("id","loaderv2").styler([{
					"position":"absolute",
					"width":this.width+"px",
					"height":this.height+"px",
					"top":dimension[0]+"px",
					"left":dimension[1]+"px",
					"zIndex":50
				}]).addDOM(o);
				
				DOM.add(document.body, d);
			}
		};
		
		imgPreload.src = Savvy.images.activity;
	},
	hide:function(b) {
		var o = Element.Id("loaderv2");
		this.status = null;
		b = (is_null(b) ? true : b);
		
		if(b == true) {
			this.overlay.off();
		}
		if(o) {
			DOM.remove(o);
		}
	},
	overlay : {
		on:function() {
			var d = document.body;
			var lb = Element.Id("lboverlay");
			
			if(lb && lb.getCSS("width") == "0px") {
				lb.styler([{
					"width":d.offsetWidth+"px",
					"height":d.offsetHeight+"px"
				}]).FxOpacity({
					start:0,
					end:75,
					delay:1,
					speed:300
				});
			} else if(lb && lb.getCSS("width") != "0px") {
				lb.FxOpacity({
					start:0,
					end:75,
					delay:1,
					speed:300
				});
			} else if(!lb) {
				var o = Element.Create("div").styler([{
					"background":"#000",
					"position":"absolute",
					"top":"0px",
					"left":"0px",
					"display":"block",
					"zIndex":"50",
					"width":d.offsetWidth+"px",
					"height":d.offsetHeight+"px"
				}]).setAttrib("id", "lboverlay");
				DOM.add(d, o);
				
				o.FxOpacity({
					start:0,
					end:75,
					delay:1,
					speed:300
				});
			} 
		},
		off:function() {
			Element.Id("lboverlay").FxOpacity({
				start:75,
				end:0,
				delay:1,
				speed:300
			});
		},
		onerror:function() {
			var lb = Element.Id("lboverlay");
			
			if(lb && lb.offsetWidth > 0) {
				lb.styler([{
					"width":"0px",
					"height":"0px"
				}]);
			}
		}
	}
};

var Attrib = {};
Attrib = {
	get:function(o,a) {
		if(!is_null(o)) {
			return o.getAttribute(a);
		} else {
			return false;
		}
	},
	set:function(o, a, v) {
		if(!is_null(o)) {
			o.setAttribute(a, v);
			return o;
		} else {
			return false;
		}
	},
	remove:function(o, a) {
		if(!is_null(o)) {
			o.removeAttribute(a);
			return o;
		} else {
			return false;
		}
	},
	setup:function(__) {
		var o = __.obj;
		var cT = [];
		cT = __.attrib;
		
		for(var i = 0;i < cT.length; i++) {
			for(var inst in cT[i]) {
				if(cT[i].hasOwnProperty(inst)) { 
					this.set(o, inst, cT[i][inst]);
				}
			}
		}
		
		return o;
	}
};

var AJAX = {};
AJAX = {
	obj:null,
	debug:false,
	reply:null,
	method:null,
	responseID:null,
	timeOut:5000,
	init:function(){
		var xhttp = false;
		if(window.XMLHttpRequest) {
			xhttp = new XMLHttpRequest();
		} else if(window.ActiveXObject) {
			var msxml = ["MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
			for(var i=0;i < msxml.length; i++) {
				try {
					xhttp = new ActiveXObject(msxml[i]);
					break;
				} catch(e) {}
			}
		}
		
		if(!xhttp) { 
			Savvy.log("Sorry, your browser doesn't support AJAX!"); 
			return false;
		} else {
			AJAX.obj = xhttp;
			return true;
		}
	},
	submit:function(__) {
		if(AJAX.obj == null) {
			AJAX.init(); 
		}
		var req = AJAX.obj;
		
		this.method = (!__.method || __.method != "GET" ? "POST" : "GET");
		AJAX.debug = (__.debug ? __.debug : false);
		
		if (req.readyState == 4 || req.readyState == 0) {
			if(this.method == "POST") {
				req.open("POST", __.uri, true);
				req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
				req.send(__.parameters);
			} else {
				req.open("GET", __.uri+__.parameters, true);
				req.send("");
			}
			if(__.oncomplete) {
				req.onreadystatechange = __.oncomplete;
			} else {
				req.onreadystatechange = this.response;
			}
		} else {
			setTimeout("AJAX.submit({parameters:'"+__.parameters+"',uri:'"+__.uri+"',method:'"+this.method+"'})",AJAX.timeOut);
		}
	},
	response:function() {
		var req = AJAX.obj;
		
		if(req.readyState == 4) {
			this.reply = req.responseText;
			
			if(AJAX.debug == true) {
				Savvy.log(req.responseText);
			}
			
			if(Replacer.trim(req.responseText) != "" && req.status == 200) {
				var a = eval("("+req.responseText+")");
				
				if(!is_null(a.alertpop) && Replacer.trim(a.alertpop) != "") {
					alert(a.alertpop);
				}
				if(!is_null(a.jumpto) && Replacer.trim(a.jumpto) != "") {
					Savvy.href(a.jumpto);
				}
				if(!is_null(a.result)) {
					if(!is_null(a.add2id) && Replacer.trim(a.add2id) != "" && a.result != "") {
						Element.Id(a.add2id).addHTML(Replacer.xml(a.result));
					}
					if(!is_null(a.exec) && typeof(a.exec) == "function") { 
						try { 
							a.exec(a.result);
						} catch(e) {
							var fn = a.exec;
							fn(a.result); 
						}
					}
				}
			} else {
				AJAX.onabort();
			}
		}
	},
	onabort:function() {
		var req = AJAX.obj;
		req.abort();
		AJAX.obj = null;
		Savvy.log("No response from server!");
	}
};

var ClassAss = {};
var ClassAss = {
	add:function(o, a) {
		o.className = a;
		return o;
	},
	append:function(o, a) {
		if(!is_null(o.className) && o.className.trim() != "") {
			o.className = o.className+" "+a;
			return o;
		} else if(is_null(o.className) || o.className.trim() == "") {
			o.className = a;
			return o;
		} else {
			return false;
		}
	},
	remove:function(o, a) {
		if(!is_null(o.className) && o.className.trim() != "") {
			var arry = o.className.split(" ");
			o.className = "";
			
			for(var i = 0; i < arry.length; i++) {
				if(arry[i] != a) {
					o.className = o.className+" "+a;
				}
			}
		}
		return o;
	},
	clear:function(o, a) {
		if(!is_null(o.className) && o.className.trim() != "") {
			o.className = "";
			return o;
		}
	},
	has:function(o, a) {
		if(!is_null(o.className) && o.className.trim() != "") {
			var arry = o.className.split(" ");
			return arry.inArray(a);
		}
	}
};

var CSS = {};
CSS = {
	styler:function(__) {
		var o = __.obj;
		var cT = [];
		cT = __.css;
		
		for(var i = 0;i < cT.length; i++) {
			for(var inst in cT[i]) {
				if(cT[i].hasOwnProperty(inst)) {
					this.set(o,inst,cT[i][inst]);
				}
			}
		}
		
		return o;
	},
	set:function(o, a, v) {
		try { 
			o.style[a] = v;
			return o;
		} catch(e) { 
			return false;
		}
	},
	get:function(o, a) {
		try {
			return o.style[a];
		} catch(e) { 
			return false;
		}
	},
	png:function(__) {
		var o = Element.Grab(__.obj, __.element, "obj");
		__.gecko = pick(__.gecko, "");
		__.ie = pick(__.ie, "scale");
		
		if(window.ActiveXObject) {
			this.set(o, "filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+__.uri+"',sizingMethod='"+__.ie+"')");
		} else {
			this.set(o, "background", "url('"+__.uri+"') "+__.gecko);
		}
		
		return o;
	}
};

var DOM = {};
DOM = {
	add:function(p,c) {
		if(!is_null(p) && !is_null(c)) {
			p.appendChild(c);
			return p;
		} else {
			try { 
				document.body.appendChild(p); 
				return p;
			} catch(e) { 
				return false;
			}
		}
	},
	addText:function(p,t) {
		if(!is_null(p) && t != "") {
			return this.add(p, document.createTextNode(t));
		} else {
			return false;
		}
	},
	addBefore:function(params) {
		var args = arguments;
		
		if(args.length == 3 && !is_null(args[0]) && !is_null(args[1]) && !is_null(args[2])) {
			arguments[0].insertBefore(args[1], args[2]);
			return true;
		} else if(args.length == 2 && !is_null(args[0]) && !is_null(args[1])) {
			args[1].parentNode.insertBefore(args[0], args[1]);
			return true;
		} else {
			return false;
		}
	},
	addAfter:function(params) {
		var args = arguments;
		
		if(!is_null(r.nextSibling)) {
			if(args.length == 3 && !is_null(args[0]) && !is_null(args[1]) && !is_null(args[2])) {
				this.addBefore(args[0], args[1], args[2].nextSibling);
				return true;
			} else {
				try {
					this.addBefore(args[0], args[1].nextSibling);
					return true;
				} catch(e) { 
					return false; 
				}
			}
		} else {
			return this.add(p,c);
		}
	},
	remove:function(params) {
		var args = arguments;
		
		if(args.length === 2 && !is_null(args[0]) && !is_null(args[1])) {
			args[0].removeChild(args[1]);
			return args[0];
		} else {
			args[0].parentNode.removeChild(args[0]);
			return args[0];
		}
	},
	change:function(params) {
		var args = arguments;
		
		if(args.length == 3 && !is_null(args[0]) && !is_null(args[1]) && !is_null(args[2])) {
			args[0].replaceChild(args[1], args[2]);
		} else {
			args[1].parentNode.replaceChild(args[0], args[1]);
		}
	},
	empty:function(p) {
		if(!is_null(p)) {
			if(p.hasChildNodes || p.innerHTML != "") {
				p.innerHTML = "";
			}
			return true;
		} else {
			return false;
		}
	}
};

var Draggable = {};
Draggable = {
	obj:null,
	init:function(__) {
		var o = __.obj;
		o.onmousedown = Draggable.start;
		o.root = pick(__.objRoot, o);
		o.hmode	= true;
		o.vmode	= true;
		
		if(isNaN(CSS.get(o.root, "left").toNumber())){
			CSS.set(o.root, "left", "0px");
		}
		if(isNaN(CSS.get(o.root, "top").toNumber())) {
			CSS.set(o.root, "top", "0px");
		}
		
		o.minX = pick(__.minX, null);
		o.maxX = pick(__.maxX, null);
		o.minY = pick(__.minY, null);
		o.maxY = pick(__.maxY, null);
		o.root.onDragStart = new Function();
		o.root.onDragEnd = new Function();
		o.root.onDrag = new Function();
	},
	start:function(e) {
		var o = Draggable.obj = this;
		e = Draggable.fixE(e);
		var y = CSS.get(o.root, "top").toNumber();
		var x = CSS.get(o.root, "left").toNumber();
		o.root.onDragStart(x,y);
		o.lastMouseX = e.clientX;
		o.lastMouseY = e.clientY;
		
		if(o.minX != null) {
			o.minMouseX = e.clientX - x + o.minX;
		}
		if(o.maxX != null) {
			o.maxMouseX = o.minMouseX + o.maxX - o.minX;
		}
		if(o.minY != null) {
			o.minMouseY = e.clientY - y + o.minY;
		}
		if(o.maxY != null) {
			o.maxMouseY = o.minMouseY + o.maxY - o.minY;
		}
		
		document.onmousemove = Draggable.drag;
		document.onmouseup = Draggable.end;
		
		return false;
	},
	drag:function(e){
		e = Draggable.fixE(e);
		var o = Draggable.obj;
		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = CSS.get(o.root, "top").toNumber();
		var x = CSS.get(o.root, "left").toNumber();
		var nx;
		var ny;
		
		if (o.minX != null) {
			ex = Math.min(ex, o.mixMouseX);
		}
		if (o.maxX != null) {
			ex = Math.max(ex, o.maxMouseX);
		}
		if (o.minY != null) {
			ey = Math.min(ey, o.minMouseY);
		}
		if (o.maxY != null) {
			ey = Math.max(ey, o.maxMouseY);
		}
		
		nx = x + ((ex - o.lastMouseX) * 1);
		ny = y + ((ey - o.lastMouseY) * 1);
		CSS.set(o.root, "left", nx + "px");
		CSS.set(o.root, "top", ny + "px");
		o.lastMouseX = ex;
		o.lastMouseY = ey;
		o.root.onDrag(nx, ny);
		
		return false;
	},
	end:function(){
		document.onmousemove = null;
		document.onmouseup = null;
		Draggable.obj.root.onDragEnd(Draggable.obj.root.style.left.toNumber(), Draggable.obj.root.style.top.toNumber(), Draggable.obj.root);
		Draggable.obj = null;
	},
	fixE : function(e){
		if (is_null(e)) {
			e = window.event;
		}
		if (is_null(e.layerX)) {
			e.layerX = e.offsetX;
		}
		if (is_null(e.layerY)) {
			e.layerY = e.offsetY;
		}
		
		return e;
	}
};

var Element = {};
Element = {
	Id:function(el) {
		var __o = new Object();
		var args = arguments;
		try {
			__o = document.getElementById(el.trim()); 
		} catch(e) { 
			return false; 
		}
		
		if(args.length === 2 && !is_null(__)) {
			var cT = [];
			cT = args[1];
			for(var i = 0; i < cT.length; i++) {
				for(var inst in cT[i]) {
					if(cT[i].hasOwnProperty(inst)) { 
						Attrib.set(o, inst, cT[i][inst]); 
					}
				}
			}
		}
		Savvy.chain(__o);
		
		return __o;
	},
	Tags:function(el) {
		var __o = {}, elm ="";
		var args = arguments;
		var rXi = new RegExp(/>/);
		
		function hClass(obj,v,i) {
			var __o = v.trim().split(".");
			var rXc = new RegExp(/\./);
			
			try {
				o = obj.getElementsByTagName(__o[0].trim());
			} catch(e) {
				o = document.getElementsByTagName(__o[0].trim());
			}
			
			if(rXc.test(v)) {
				var __c = [];
				for(var i = 0;i < o.length; i++) {
					var c = o[i];
					var cA = c.className.split(" ");
					
					if(cA.inArray(__o[1].trim())) {
						if(__c.length === 0) {
							__c[0] = c;
						} else {
							__c.push(c);
						}
					}
				}
				return __c;
			} else {
				return o;
			}
		};
		
		if(args.length === 2) {
			__o = hClass(args[0],args[1]);
		} else if(args.length === 1) {
			if(rXi.test(el)) {
				var obj = el.trim().split(">");
				var o = obj[0].trim();
				elm = obj[1].trim();
				__o = Element.Id(o);
				__o = hClass(__o, elm.trim());
			} else {
				__o = document;
				__o = hClass(__o, el.trim());
			} 
		}
		for(var m = 0; m < __o.length; m++) {
			Savvy.chain(__o[m]);
		}
		Savvy.chain(__o);
		
		return __o;
	},
	Create:function(el) {
		var r = false;
		var args = arguments;
		
		if(args.length === 2) {
			if(!is_null(args[0])) {
				try { 
					r = args[0].createElement(args[1]); 
				} catch(e) { 
					r = document.createElement(args[1]); 
				}
			} else {
				r = document.createElement(args[1]);
			}
		} else if(!is_null(el)) {
			r = document.createElement(el);
		}
		Savvy.chain(r);
		
		return r;
	},
	Toggle:function(obj) {
		if(obj.getCSS("visibility") == "hidden") {
			obj.styler([{
				"visibility":"visible"
			}]);
		} else {
			obj.styler([{
				"visibility":"hidden"
			}]);
		}
	},
	Grab:function(obj,el,r) {
		var r = (!is_null(r) ? r : "element");
		if(!is_null(obj) && !is_null(el)) {
			if(Attrib.get(obj,"id") == el) {
				return (r == "obj" ? obj : el);
			} else {
				return false;
			}
		} else if (!is_null(el)) {
			return (r == "obj" ? Element.Id(el) : el);
		} else if (!is_null(obj)) {
			return (r == "obj" ? obj : Attrib.get(obj,"id"));
		} else {
			return false;
		}
	}
};

var Event = {};
Event = {
	On: function(__) {
		var obj = pick(__.obj, window);
		var t = __.trigger.toString();
		var f = __.load_function;
		var r;
		
		if(obj.addEventListener) {
			try { 
				r = obj.addEventListener(t, f, false);
				return r;
			} catch(e) { }
		} else if(obj.attachEvent) {
			try { 
				obj.attachEvent("on".concat(t), f); 
			} catch(e) { }
			return true;
		} else {
			obj["on"+t] = f;
		}
	},
	Off: function(__) {
		var r = false;
		var obj = (!__.obj || __.obj == "undefined" ? window : __.obj);
		
		if(obj.removeEvent) {
			try { 
				r = obj.removeEvent("on"+__.trigger, __.load_function); 
			} catch(e) { 
				try {
					r = obj.removeEventListener(__.trigger, __.load_function, false); 
				} catch(e) { 
					r = "Unable to load window.attachEvent: "+e;
				}
			}
		} else { 
			try { 
				r = obj.removeEventListener(__.trigger, __.load_function, false); 
			} catch(e) { 
				r = "Unable to load window.addEventListener: "+e; 
			}
		}
		return r;
	}
};

var Form = {};
Form = {
	first:{},
	confirm:function(v) {
		if(!v || v.trim() == "") {
			v = "Do you really want to run this action?";
		}
		
		return confirm(v);
	},
	clear:function(o) {
		var x = "", obj = o.elements;
		for (var i=0; i < obj.length; i++){
			var _o = obj[i];
			
			if(_o.type == "text" || _o.type == "password" || _o.type == "textarea") {
				_o.value = "";
			}
		}
	},
	validate:function(o) {
		var elm = o.getAttrib("id");
		var x = "";
		var obj = Element.Tags(o, "*");
		Form.first[elm] = null;
		var tn = ["INPUT","SELECT","TEXTAREA"];
		obj.each(function() {
			if(tn.inArray(this.tagName)) {
			//for(var i = 0; i <obj.length;i++) {
				var _o = this;
				if (_o.name != "") {
					_o.onchange = function() { 
						return false;
					};
					var cha = new RegExp("(max|min|exact)\-(\d*)");
					
					if(!_o.className) {
						_o.className = "";
					}
					
					var thisClass = _o.className.split(" ");
					
					if(thisClass.inArray("required") && _o.value.trim() == "") {
						Form.error(o, _o, "Please fill the following field!");
						Form.mark(o);
					} else if(thisClass.inArray("string") && !Test.string(_o.value)) {
						Form.error(o, _o, "Please fill the following field (string)!");
						Form.mark(o);
					} else if(thisClass.inArray("integer") && !Test.integer(_o.value)) {
						Form.error(o, _o, "Please fill the following field (integer)!");
						Form.mark(o);
					} else if(thisClass.inArray("email") && !Test.email(_o.value)) {
						Form.error(o, _o, "Please fill correct e-mail address!");
						Form.mark(o);
					} else {
						CSS.set(_o, "border", "1px solid #06c");
					}
					
					for(var ii = 0; ii < thisClass.length; ii++) {
						if(thisClass[ii].match(cha)) {
							if(!Test.lengths(thisClass[ii], _o.value)) {
								var matcherror = thisClass[ii].split("-");
								Form.error(o, _o, "Require "+matcherror[0]+" of "+matcherror[1]+" characters.", true);
								Form.mark(o);
							}
						}
					}
					
					if (_o.type == "checkbox" && _o.checked == true) {
						x = x + "&" + _o.name + "=" + Replacer.html(_o.value);
					} else if (_o.type == "radio" && _o.checked == true) {
						x = x + "&" + _o.name + "=" + Replacer.html(_o.value);
					} else if (_o.type != "checkbox" && _o.type != 'radio') {
						x = x + "&" + _o.name + "=" + Replacer.html(_o.value);
					}
				}
			}
		});
		
		if(!is_null(Form.first[elm])) { 
			Form.first[elm].focus();
			return false; 
		} else {
			return x;
		}
	},
	mark:function(o) {
		var elm = o.getAttrib("id");
		
		if(is_null(Form.first[elm])) {
			Form.first[elm] = o;
		}
	},
	error: function(obj, o, msg, bool) {
		Savvy.chain(o);
		var elm = obj.getAttrib("id");
		var booleans = pick(bool, false);
		
		if(!Element.Id(o.name+"_error")) {
			var oE = Element.Create("span").setAttrib("id", o.name+"_error").addTextDOM(msg);
			oE.className = "form_error";
			DOM.add(o.parentNode, oE);
			o.setCSS("border", "1px solid #f00");
			o.onchange = function() {
				if(o.value != "") { 
					o.setCSS("border", "1px solid #06c");
					if(oE) {
						DOM.remove(o.parentNode,oE);
					}
					Form.first[elm] = null;
				}
			};
		} else if(Element.Id(o.name+"_error") && booleans == true) {
			var object = Element.Id(o.name+"_error");
			
			if(obj.innerHTML.match(msg) == false && obj.innerHTML.trim() != "") {
				obj.appendHTML(msg);
			}
			
			o.setCSS("border", "1px solid #f00");
			o.onchange = function() {
				if(o.value != "") { 
					o.setCSS("border", "1px solid #06c");
					if(obj) {
						DOM.remove(o.parentNode, object);
					}
					Form.first[elm] = null;
				}
			};
		}
	},
	quickAJAX:function(__) {
		var o = Element.Grab(__.obj, __.element, "obj");
		var f = pick(__.onsuccess, null);
		var fe = pick(__.onfail, null);
		var params = Form.validate(o);
		if(params) {
			params = (__.params ? __.params : "")+params;
			if(f != null && typeof(f) == "function") {
				f();
			}
			AJAX.submit({
				parameters:params,
				uri:__.uri,
				method:"POST"
			});
			return true;
		} else {
			if(fe != null && typeof(fe) == "function") {
				fe();
			}
			return false;
		}
	},
	xtendedInput: function(__) {
		var o = Element.Grab(__.obj, __.element, "obj");
		var pL = 0;
		
		o.bind("keyup", function() {
			if(this.value.length >= __.init_start && this.value.length < __.init_limit) {
				if(this.value.length > pL) {
					this.size = (this.size + 1);
				} else if(this.value.length < pL) {
					this.size = (this.size - 1);
				}
			}
			if((__.init_row && __.init_row != "undefined") && this.value.length >= l) {
				var nTA = Element.Create("textarea");
				nTA.setAttrib("cols", __.init_limit).setAttrib("rows", __.init_row);
				nTA.value = o.value;
				nTA.setAttrib(nTA, "name", o.getAttrib("name"));
				DOM.change(nTA, o);
				nTA.setAttrib("id", g);
			}
			
			pL = o.value.length;
		});
	},
	tick_rows: function(int_start, int_end, var_id) {
		var checker = Element.Id("ticker_" + int_start + "_" + int_end), x = false, swap = false;
		if(checker.checked == true) { 
			x = true;
			swap = true;
		}
		for(var i = int_start; i <= int_end; i++) Element.Id(var_id+i).checked = x;
		Element.Id("ticker_" + int_start + "_" + int_end).checked = swap;
	}
};

var Hash = {};
Hash = {
	mem:{},
	add:function(o,a,v) {
		var elm = o.getAttrib("id");
		if(!is_null(elm)) {
			if(is_null(Hash.mem[elm])) {
				Hash.mem[elm] = [];
			}
			Hash.mem[elm][a] = v;
		}
	},
	get:function(o,a) {
		var elm = o.getAttrib("id");
		
		if(!is_null(elm)) {
			if(!is_null(Hash.mem[elm][a])) {
				return Hash.mem[elm][a];
			} else {
				return false;
			}
		} else {
			return false;
		}
	},
	remove:function(o,a) {
		var elm = o.getAttrib("id");
		if(!is_null(elm)) {
			Hash.mem[elm][a] = null;
		}
	}
};

var Opacity = {};
Opacity = {
	step:{},
	speed:{},
	istart:{},
	iend:{},
	ifunc:{},
	interval:{},
	init:function(__) {
		var elm = Element.Grab(__.obj, __.element);
		
		if(!is_null(this.interval[elm])) {
			clearInterval(this.interval[elm]);
			this.interval[elm] = null;
		}
		var o = Element.Id(elm);
		__.delay = (__.delay && __.delay > 0 ? __.delay : 1);
		this.step[elm] = 1;
		this.istart[elm] = __.start;
		this.iend[elm] = __.end;
		this.ifunc[elm] = pick(__.oncomplete, null);
		this.speed[elm] = (__.speed && __.speed > 0 ? __.speed : 1);
		
		if(__.start > __.end) {
			this.fadeout(elm);
			this.interval[elm] = setInterval("Opacity.fadeout('"+elm+"')", __.delay);
		} else if(__.start < __.end) { 
			this.fadein(elm);
			this.interval[elm] = setInterval("Opacity.fadein('"+elm+"')", __.delay);
		}
	},
	set: function(g,v) {
		v = (v > 100 ? 100 : (v < 0 ? 0 : v));
		
		try {
			var o = Element.Id(g);
			
			if(v == 0 && o.getCSS("visibility") != "hidden") { 
				Element.Toggle(o);
			} else if(v > 0 && o.getCSS("visibility") == "hidden") {
				Element.Toggle(o);
			}
			
			if (window.ActiveXObject || Savvy.browser.ie == true) {
				if (!o.currentStyle || !o.currentStyle.hasLayout) {
					o.setCSS("zoom", 1);
				}
				o.setCSS("filter", (v < 100 ? "alpha(opacity="+v+")" : ""));
			} else {
				o.setCSS("opacity", (v/100));
				o.setCSS("MozOpacity", (v/100));
			}
		} catch(e) { }
	},
	fadein: function(g) {
		var f = this.step[g]++;
		var s = this.istart[g];
		var e = this.iend[g];
		f = (f * this.speed[g]);
		s = Math.round(s + f);
		
		if(s < e) {
			this.set(g, s);
		} else {
			this.set(g, e);
			
			var f = this.ifunc[g];
			if(f != null && typeof(f) == "function") {
				Element.Id(g).callback(f);
			}
			clearInterval(this.interval[g]);
			this.interval[g] = null;
		}
		this.istart[g] = s;
	},
	fadeout: function(g) {
		var f = this.step[g]++;
		var s = this.istart[g];
		var e = this.iend[g];
		f = (f * this.speed[g]);
		s = Math.round(s - f);
		
		if(s > e) {
			Opacity.set(g, s);
		} else {
			this.set(g, e);
			
			var f = this.ifunc[g];
			if(f != null && typeof(f) == "function") {
				Element.Id(g).callback(f);
			}
			
			clearInterval(this.interval[g]);
			this.interval[g] = null;
		}
		this.istart[g] = s;
	},
	power:function(s,e,st) {
		var dif = (Math.abs(s - e) - 1);
		var step = 1;
		
		for(var i = 1; i < st; i++) {
			step += i;
		}
		
		if(dif > step) {
			return true;
		} else {
			return false;			
		}
	}
};

var Replacer = {};
Replacer = {
	and:function(v) {
		var s = new String(v);
		
		return s;
	},
	html:function(v) {
		var s = new String(v);
		s = s.htmlentities();
		s = encodeURIComponent(s);
		
		return s;
	},
	trim:function(v) {
		var s = new String(v);
		s = s.replace(/^\s+/g,"");
		s = s.replace(/\s+$/g,"");
		
		return s;
	},
	xml:function(v) {
		var s = new String(v);
		s = s.replace(/\[lt\]/g,"<");
		s = s.replace(/\[gt\]/g,">");
		s = s.replace(/\[n\]/g,"&");
		s = s.replace(/\&quot\;/g,"\"");
		s = s.replace(/\&rsquo\;/g,"\'");
		s = s.replace(/\[br\]/g,"\n");
		s = s.replace(/\[break\]/g,"<br />");
		
		return s;
	}
};

var Resizable = {};
Resizable = {
	obj:null,
	init:function(__) {
		// __.obj, __.oRoot, __.minX, __.maxX, __.minY, __.maxY
		var o = __.obj;
		o.onmousedown = Resizable.start;
		o.root = pick(__.objRoot, o);
		o.hmode	= true;
		o.vmode	= true;
		o.minX = pick(__.minX, null);
		o.minY = pick(__.minY, null);
		o.maxX = pick(__.maxX, null);
		o.maxY = pick(__.maxY, null);
		
		o.root.onResizeStart = new Function();
		o.root.onResizeEnd = new Function();
		o.root.onResize	= new Function();
	},
	start:function(e){
		var o = Resizable.obj = this;
		e = Resizable.fixE(e);
		var y = CSS.get(o.root, "height").toNumber();
		var x = CSS.get(o.root, "width").toNumber();
		o.root.onResizeStart(x, y);
		o.lastMouseX = e.clientX;
		o.lastMouseY = e.clientY;
		
		if(o.minX != null) {
			o.minMouseX = e.clientX - x + o.minX;
		}
		if(o.maxX != null) {
			o.maxMouseX = o.minMouseX + o.maxX - o.minX;
		}
		if(o.minY != null) {
			o.minMouseY	= e.clientY - y + o.minY;
		}
		if(o.maxY != null) {
			o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		}
		
		document.onmousemove = Resizable.resize;
		document.onmouseup = Resizable.end;
		
		return false;
	},
	resize : function(e){
		e = Resizable.fixE(e);
		var o = Resizable.obj;
		var ey = e.clientY;
		var ex = e.clientX;
		var y = CSS.get(o.root, "height").toNumber();
		var x = CSS.get(o.root, "width").toNumber();
		var ow = x;
		var oh = y;
		var nx, ny;
		
		if (o.minX != null) {
			ex = Math.max(ex, o.minMouseX);
		}
		if (o.maxX != null) {
			ex = Math.min(ex, o.maxMouseX);
		}
		if (o.minY != null) {
			ey = Math.max(ey, o.minMouseY);
		}
		if (o.maxY != null) {
			ey = Math.min(ey, o.maxMouseY);
		}
		
		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
		CSS.set(o.root, "width", (ow + (nx - x)) + "px");
		CSS.set(o.root, "height", (oh + (ny - y)) + "px");
		o.lastMouseX = ex;
		o.lastMouseY = ey;
		o.root.onResize(Math.round(nx-x), Math.round(ny-y));
		
		return false;
	},
	end : function(){
		document.onmousemove = null;
		document.onmouseup   = null;
		Resizable.obj.root.onResizeEnd(Resizable.obj.root.style.width.toNumber(), Resizable.obj.root.style.height.toNumber(), Resizable.obj.root);
		Resizable.obj = null;
	},
	fixE : function(e){
		if (typeof(e) == "undefined") {
			e = window.event;
		}
		if (typeof(e.layerX) == "undefined") {
			e.layerX = e.offsetX;
		}
		if (typeof(e.layerY) == "undefined") {
			e.layerY = e.offsetY;
		}
		
		return e;
	},
	childResize:function(__) {
		var o = __.obj;
		var child = __.child;
		
		for(var i = 0; i < child.length; i++) {
			try {
				CSS.set(child[i], "width", (CSS.get(child[i], "width").toNumber() + __.width)+"px");
			} catch(e) {}
			
			CSS.set(child[i], "height", (CSS.get(child[i], "height").toNumber() + __.height)+"px");
		}
	}
};

var Test = {
	string:function(v) {
		return (typeof(v) == "string" && v != "" && isNaN(v));
	},
	integer:function(v) {
		return (!isNaN(v) && v != "");
	},
	email:function(v) {
		var rX = new RegExp(/^[\w-\.\']{1,}\@([\da-zA-Z-]{1,}\.){1,}[\da-zA-Z-]{2,}$/);
		
		return (v != "" && rX.test(v));
	},
	lengths:function(r,v) {
		var epx = r.split("-");
		
		if(epx[0] == "max") {
			return (v.length <= epx[1].toNumber() ? true : false); 
		} else if(epx[0] == "min") {
			return (v.length >= epx[1].toNumber()? true : false);
		} else if(epx[0] == "exact") {
			return (v.length == epx[1].toNumber()? true : false);
		}
	},
	ip:function(v) {
		var rX = new RegExp(/^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/);
		return (v != "" && rX.test(v));
	}
};

var Windows = {
	getScroll: function () {
		var scrOfX = 0;
		var scrOfY = 0;
		if(typeof window.pageYOffset == "number") {
			scrOfY = window.pageYOffset;
			scrOfX = window.pageXOffset;
		} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
			scrOfY = document.body.scrollTop;
			scrOfX = document.body.scrollLeft;
		} else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
			scrOfY = document.documentElement.scrollTop;
			scrOfX = document.documentElement.scrollLeft;
		}
		return [scrOfX, scrOfY];
	},
	getRelative:function(o) {
		var curwidth = 0;
		var curheight = 0;
		var curtop = 0;
		var curleft = 0;
		if(o.offsetParent) {
			curwidth = o.offsetWidth;
			curheight = o.offsetHeight;
			while(o.offsetParent) {
				curtop += o.offsetTop;
				curleft += o.offsetLeft;
				o = o.offsetParent;
			}
		} else {
			curwidth = pick(o.width, 0);
			curheight = pick(o.height, 0);
			curtop = pick(o.y, 0);
			curLeft = pick(o.x, 0);
		}
		
		return [curwidth, curheight, curtop, curleft];
	},
	getPositionCenter:function(oW,oH) {
		var d = document.body;
		var hW = d.offsetWidth.toNumber();
		var hH = d.offsetHeight.toNumber();
		var sXY = Windows.getScroll();
		var xS = Math.round(((hW - oW) / 2) + sXY[0]);
		var yS = Math.round((((screen.height - 200) - oH) / 2) + sXY[1]);
		xS = (xS < 0 ? 0 : xS);
		yS = (yS < 0 ? 0 : yS);
		return [yS, xS];
	}
};

function include(jsf) {
	var st = Element.Create("script").setAttrib("text/javascript");
	st.src = jsf.trim();
	Element.Tags("HEAD")[0].addDOM(st);
}

function is_null(obj) {
	return (typeof(obj) == "undefined" || obj == null); 
};

function pick(choose,option) {
	return (!is_null(choose) ? choose : option);
};
