function $include(file) {
	document.write('<script language="javascript" type="text/javascript" src="' + file + '"></script>');
}

function $css(file) {
	document.write('<link rel="stylesheet" type="text/css" href="' + file + '" />');
}

Function.empty = function () {};

var $Element = {
	Methods: {},
	noCloseTags: {"img": 1, "br": 1, "hr": 1, "input": 1, "textarea": 1}
}

function $extend () {
	var args = arguments;
	if (!args[1]) {
		args = [this, args[0]];
	}
	for (var property in args[1]) {
		args[0][property] = args[1][property];
	}
	return args[0];
}

function $extendML () {
	var args = arguments;
	if (!args[1]) {
		args = [this, args[0]];
	}
	for (var prop in args[1]) {
		if (typeof args[1][prop] == "object") {
			if (!args[0][prop]) { args[0][prop] = {}; }
			$extendML(args[0][prop], args[1][prop]);
		} else {
			args[0][prop] = args[1][prop];
		}
	}
	return args[0];
}

function $() {
	if (arguments.length == 0)
		return false;
	var el = gEBI(arguments[0]);
	var i = 1;
	while (i < arguments.length) {
		if (arguments[i] == "parent") {
			el = el.parentNode;
			i++;
		} else if ((i + 1) == arguments.length) {
			return gEBTN(el, arguments[i++]);
		} else {
			el = gEBTN(el, arguments[i++], arguments[i++]);
		}
	}
	return $Element.update(el);
}

function gEBI(el) {
	if (typeof el == 'string')
		return document.getElementById(el);
	else
		return el;
}

function gEBTN () {
	if (arguments.length < 2) {
		return false;
	} else if (arguments.length == 2) {
		var els = [];
		var childs = gEBI(arguments[0]).childNodes;
		var mask = arguments[1].toUpperCase();
		for (var i = 0; i < childs.length; i++) {
			if (mask == "*") {
				if (childs[i].nodeType == 1) {
					els.push($Element.update(childs[i]));
				}
			} else if (mask == childs[i].nodeName) {
				els.push($Element.update(childs[i]));
			}
		}
		return els;
	} else {
		var childs = gEBI(arguments[0]).childNodes;
		var mask = arguments[1].toUpperCase();
		var num = arguments[2];
		var j = -1;
		for (var i = 0; i < childs.length; i++)
		{
			if (mask == "*") {
				if (childs[i].NodeType == 1) {
					j++;
				}
			} else if (mask == childs[i].nodeName) {
				j++;
			}
			if (j == num) {
				return childs[i];
			}
		}
	}
}

function $c() {
	if (arguments.length == 0)
		return false;
	var el = document.createElement(arguments[0]);
	if (arguments.length > 1) {
		var i, opts = arguments[1];
		$extendML(el, opts);
	}
	if (arguments.length > 2)
		el.innerHTML = arguments[2];
	
	if ($Element.noCloseTags[arguments[0].toLowerCase()]) {} else {
		var rSpan = document.createElement("span");
		el.appendChild(rSpan);
		el.removeChild(rSpan);
	}
	return $Element.update(el);
}

function $t(data) {
	return document.createTextNode(data);
}

function $isdef(a) { return !(typeof a == "undefined"); }

var $browser = new function() {
	this.dom = (document.getElementById ? true : false);
	this.opera = (window.opera ? true : false);
	this.webkit = (document.childNodes && !document.all && !navigator.taintEnabled);
	this.mac = (window.xpath ? true : false);
	this.gecko = (document.getBoxObjectFor != null);
	this.design = (document.designMode ? true : false);
	this.ie = (window.ActiveXObject ? true : false);
	this.ie7 = (this.ie && (window.XMLHttpRequest ? true : false));
	this.ie6 = (this.ie && !this.ie7)
}();

var $ajax = {
	init: function () {
			var res;
			try {
				if ($browser.ie) {
					if ($browser.ver >= 6) {
						res = new ActiveXObject("Microsoft.XMLHTTP");
					} else {
						res = new ActiveXObject("Msxml2.XMLHTTP");
					}
				} else {
					res = new XMLHttpRequest();
				}
			} catch (e) {
				return null;
			}
			return res;
		},
	request: function (obj) {
			try {
				if (typeof obj == "undefined")
					return;
				var url = obj.url ? obj.url : '';
				var req = $ajax.init();
				var data = obj.data ? $ajax.buildData(obj.data) : null;
				if (obj.onSuccess) {
					req.onreadystatechange = function () {
						if (req.readyState == 4) {
							if (req.status == 200) {
								obj.onSuccess($ajax.parseRespond($ajax.ruDecode(req.responseText)), req.responseText);
							}
						}
					}
				}
				var urlCache = '';
				var cache = typeof obj.cache != "undefined" ? obj.cache : false;
				if (!cache)
					url += (url.indexOf('?') == -1 ? '?' : '&') + 'rTime=' + $time();
				var method = obj.method ? obj.method.toUpperCase() : "POST";
				if (method == "GET") {
					url += (url.indexOf('?') == -1 ? '?' : '&') + data;
					data = null;
				}
				req.open(method, url, true);
				req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				req.setRequestHeader("Content-length", data == null ? 0 : data.length);
				req.setRequestHeader("Connection", "close");
				req.send(data);
			} catch (e) { }
		},
	buildData: function (data) {
			var res = '';
			for (var k in data) {
				if (res.length > 0)
					res += '&';
				res += encodeURI(k) + '=' + encodeURI(data[k]);
			}
			return res;
		},
	parseRespond: function (a) {
			try {
				return (Function("return" + a))()
			} catch(e) {
				return null;
			}
		},
	ruDecode_old: function (a) {
			var tmp;
			var res = "";
			for (var i = 0; i < a.length; i++) {
				if (a.charAt(i) == '|')
				{
					tmp = a.charAt(++i);
					if (tmp == 'a')
						res += '¨';
					else if (tmp == 'b')
						res += '¸';
					else if (tmp == 'c')
						res += '|';
					else
						res += String.fromCharCode(tmp.charCodeAt(0) + 1007);
				}
				else
					res += a.charAt(i);
			}
			return res;
		},
	ruDecode: function (a) {
		var res = "";
		var c, pos;
		for (var i = 0; i < a.length; i++) {
			c = a.charAt(i);
			if (c == '|') {
				c = a.charAt(++i);
				pos = this.ruCode[1].indexOf(c)
				if (pos != -1) {
					res += this.ruCode[0].charAt(pos);
				}
			} else  {
				res += c;
			}
		}
		return res;
	},
	formRequest: function () {
			if (arguments.length == 0)
				return;
			var form = arguments[0];
			var id = 'ifrm' + $time('z');
			document.body.appendChild($c( 'div', {}, '<iframe style="display: none" src="about:blank" id="' + id + '" name="' + id + '" onload="loaded(\'' + id + '\');"></iframe>' ));
			var ifrm = $(id);
			form.target = id;
			if (arguments.length > 1)
			{
				var onsucc = arguments[1];
				ifrm.onload = function() {
					var ifrmdoc = window.frames[id].document;
					if (ifrmdoc.location.href != "about:blank") {
						onsucc($ajax.parseRespond($ajax.ruDecode(ifrmdoc.body.innerHTML)));
					}
				}
			}
			form.submit();
		},
	ruCode: [
		'|éöóêåíãøùçõúôûâàïðîëäæýÿ÷ñìèòüáþ¸ÉÖÓÊÅÍÃØÙÇÕÚÔÛÂÀÏÐÎËÄÆÝß×ÑÌÈÒÜÁÞ¨',
		'|qwertyuiop[]asdfghjkl;\'zxcvbnm,.`QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>~'
	]
}

function $time() {
	var sep = '.';
	if (arguments.length > 0)
		sep = arguments[0];
	var date = new Date();
	return date.getFullYear() + sep
		+ date.getMonth() + sep
		+ date.getDate() + sep
		+ date.getHours() + sep
		+ date.getMinutes() + sep
		+ date.getSeconds() + sep
		+ date.getMilliseconds();
}

function $uts() {
	var date = new Date();
	return date.getTime();
}

var $effect = {
	tick: 30, //($browser.ie ? 100 : 30),
	list: [],
	type: function (x) { return Math.sin((x - 0.5) * Math.PI) * 0.5 + 0.5; },
	create: function(f, t) {
		var id = $effect.list.length;
		var uts = $uts();
		if (arguments.length > 1) {
			return $effect.createComplex(id, f, false, uts, uts + t);
		}
		return $effect.createInterval(id, f, uts);
	},
	createComplex: function(id, f, r, sT, eT) {
		$effect.list[id] = {
			startTime: sT,
			endTime: eT,
			durTime: eT - sT,
			reversed: r,
			func: f,
			interval: function() {
				var uts = $uts();
				if ((uts  - sT) / (eT - sT) >= 1) {
					f(r ? 0 : 1);
					$effect.destroy(id);
				} else {
					f($effect.type(r ? 1 - (uts  - sT) / (eT - sT) : (uts  - sT) / (eT - sT)));
				}
			}
		}
		$effect.list[id].proc = setInterval($effect.list[id].interval, $effect.tick);
		return id;
	},
	createInterval: function(id, f, sT) {
		$effect.list[id] = {
			startTime: sT,
			lastTick: sT,
			func: f,
			interval: function() {
				var uts = $uts()
				f(uts - $effect.list[id].lastTick);
				$effect.list[id].lastTick = uts;
			}
		}
		$effect.list[id].proc = setInterval($effect.list[id].interval, $effect.tick);
	},
	reverse: function(id) {
		if ($effect.list[id].proc == false) {
			var uts = $uts();
			with ($effect.list[id]) {
				return $effect.createComplex(id, func, !reversed, uts, uts + durTime);
			}
		} else {
			$effect.destroy(id);
			var uts = $uts();
			with ($effect.list[id]) {
				return $effect.createComplex(id, func, !reversed, 2 * uts - endTime, 2 * uts - startTime);
			}
		}
	},
	pause: function(id) {
	},
	destroy: function(id) {
		clearInterval($effect.list[id].proc);
		$effect.list[id].proc = false;
	}
};

var $effect2 = {
	empty: function() {
		this.start = this.stop = this.remove = this.destroy = this.reverse = Function.empty;
		return this;
	},
	create: function (obj, time) {
		if (obj.object) {
			obj = [obj];
		}
		time = typeof time == "undefined" ? 500 : time;
		for (var i in obj) {
			var a = $(obj[i].object);
			for (var j in obj[i].params) {
				obj[i].params[j].from = typeof obj[i].params[j].from != "undefined" ? obj[i].params[j].from : $effect2.get(a, j);
				obj[i].params[j].to = typeof obj[i].params[j].to != "undefined" ? obj[i].params[j].to : $effect2.get(a, j);
			}
		}
		this.func = function (t) {
			for (var i in obj) {
				var eParams = obj[i];
				var a = $(obj[i].object);
				var p = obj[i].params;
				for (var j in p) {
					$effect2.set(a, j, $effect2.interval(j, p[j].from, p[j].to, t));
				}
			}
		};
		this.started = false;
		this.start = function () { this.id = $effect.create(this.func, time); }
		this.stop = this.remove = this.destroy = function () { if (this.id) { $effect.destroy(this.id); } }
		this.reverse = function () { if (this.id) { $effect.reverse(this.id); } }
		return this;
	},
	get: function(obj, param) {
		if (param == "opacity") {
			return 0;
		}
		if ($effect2.NUMERIC[param]) {
			return parseInt(obj.style[param]);
		}
		if ($effect2.COLORIC[param]) {
			return obj.style[param];
		}
		return 0;
	},
	set: function(obj, param, value) {
		if (param == "opacity") {
			obj.setOpacity(value);
		}
		if ($effect2.NUMERIC[param]) {
			obj.style[param] = value + "px";
		}
		if ($effect2.COLORIC[param]) {
			obj.style[param] = value;
		}
	},
	interval: function(param, from, to, t) {
		if (param == "opacity" || $effect2.NUMERIC[param]) {
			return (to - from) * t + from;
		}
		if ($effect2.COLORIC[param]) {
			return $color.toHEX($color.gradient(from, to, t));
		}
		return 0;
	},
	NUMERIC: {width: 1, height: 1, top: 1, right: 1, bottom: 1, left: 1, marginTop: 1, marginRight: 1, marginBottom: 1, marginLeft: 1, paddingTop: 1, paddingRight: 1, paddingBottom: 1, paddingLeft: 1, borderTopWidth: 1, borderRightWidth: 1, borderBottomWidth: 1, borderLeftWidth: 1, margin: 1, padding: 1, borderWidth: 1, maxHeight: 1, maxWidth: 1, minHeight: 1, minWidth: 1, fontSize: 1, backgroundPositionX: 1, backgroundPositionY: 1},
	COLORIC: {backgroundColor: 1, borderColor: 1, borderTopColor: 1, borderRightColor: 1, borderBottomColor: 1, borderBottomColor: 1, color: 1}
};

$extend(Math, {
	HEX: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15},
	DEC: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],
	hex2dec: function (str) {
		str = str.toLowerCase();
		var x = 0;
		var p = 1;
		for (var i = str.length - 1; i >= 0; i--) {
			x += Math.HEX[str.charAt(i)] * p;
			p *= 16;
		}
		return x;
	},
	dec2hex: function (x) {
		if (x <= 0)
			return '0';
		var str = '';
		while (x > 0) {
			str = Math.DEC[x % 16] + str;
			x = Math.floor(x / 16);
		}
		return str;
	}
});

var $color = {
	toRGB: function(str) {
		if (str.slice(0,3).toLowerCase() == "rgb") {
			var rgb = str.slice(str.indexOf("(") + 1, str.indexOf(")"));
			rgb = rgb.split(",");
			return {'r': parseInt(rgb[0]), 'g': parseInt(rgb[1]), 'b' : parseInt(rgb[2])};
		}
		if (str.charAt(0) == "#") {
			str = str.slice(1);
		}
		var r, g, b;
		if (str.length == 3) {
			r = Math.hex2dec(str.charAt(0) + str.charAt(0));
			g = Math.hex2dec(str.charAt(1) + str.charAt(1));
			b = Math.hex2dec(str.charAt(2) + str.charAt(2));
		} else {
			r = Math.hex2dec(str.slice(0, 2));
			g = Math.hex2dec(str.slice(2, 4));
			b = Math.hex2dec(str.slice(4, 6));
		}
		return {'r': r, 'g': g, 'b': b};
	},
	toHEX: function(rgb) {
		if (arguments.length == 3) {
			rgb = this.RGB(arguments[0], arguments[1], arguments[2]);
		}
		var hr = Math.dec2hex(rgb.r), hg = Math.dec2hex(rgb.g), hb = Math.dec2hex(rgb.b)
		return '#' + (hr.length == 1 ? '0' : '') + hr + (hg.length == 1 ? '0' : '') + hg + (hb.length == 1 ? '0' : '') + hb;
	},
	RGB: function(r, g, b) {
		return {'r': r, 'g': g, 'b': b};
	},
	gradient: function(from, to, pos) {
		if (typeof from == "string" ) {
			from = $color.toRGB(from);
		}
		if (typeof to == "string" ) {
			to = $color.toRGB(to);
		}
		return {
			'r': Math.round(from.r + (to.r - from.r) * pos),
			'g': Math.round(from.g + (to.g - from.g) * pos),
			'b': Math.round(from.b + (to.b - from.b) * pos)
		};
	}
}

$extend($Element.Methods, {
	setOpacity: $browser.ie ? function (alpha) { this.style.filter = 'Alpha(Opacity=' + (alpha * 100) + ')'; } : function (alpha) { this.style.opacity = alpha; },
	addEffect: function (func, t) {
		var id;
		var obj = this
		if (typeof func == "function") {
			id = $effect.create(function(t) { func.apply(obj, [t]); } , t);
			this.idEffect = id;
			this.removeEffect = function () { $effect.destroy(id); }
			this.reverseEffect = function () { $effect.reverse(id); }
			this.isEffect = function() { return ($effect.list[id].interval != false); }
			return id;
		}
		if (typeof func == "string") {
			switch(func) {
				case "param": {
					var param = arguments[2], from = arguments[3], to = arguments[4], hz = arguments[5];
					return $Element.Methods.addEffect.apply(obj, [function(t) { this.style[param] = (from + (to - from) * t) + hz; }, t ]);
				}
				case ("height" || "width" || "left" || "right" || "top" || "bottom"): {
					if (arguments.length > 3) {
						var param = arguments[0], from = arguments[2], to = arguments[3], hz = "px";
						return $Element.Methods.addEffect.apply(this, ["param", t, param, from, to, hz]);
					} else {
						var param = arguments[0], from = parseInt(this.style[param]), to = arguments[2], hz = "px";
						return $Element.Methods.addEffect.apply(this, ["param", t, param, from, to, hz]);
					}
				}
			}
		}
	},
	replaceEffect: function () {
		if (this.isEffect) {
			this.removeEffect();
		}
		return $Element.Methods.addEffect.apply(this, arguments);
	},
	remove: function () {
		this.parentNode.removeChild(this);
	},
	appendChildFirst: function(e) {
		if (this.childNodes.length == 0) {
			this.appendChild(e)
		} else {
			this.insertBefore(e, this.childNodes[0]);
		}
	},
	insertAfter: function (n, src) {
		if (this.lastChild == src) {
			this.appendChild(n);
		} else {
			this.insertBefore(n, src.nextSibling);
		}
	},
	getSize: function() {
		return {
			'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
			'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
			'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight},
			'offset': {'x': this.offsetLeft, 'y': this.offsetTop}
		};
	}
});

$Element.MethodsByTag = {};

$Element.MethodsByTag["select"] = {
	appendOption: function (opt, value) { this.appendChild(typeof opt == "object" ? opt : $c("option", {"value": value}, opt)); },
	clearOptions: function () { this.innerHTML = ''; },
	selectOption: ($browser.opera ? function(i) { var obj = this; setTimeout( function () { obj.selectedIndex = i; }, 0); } : function(i) { this.selectedIndex = i; })
};

var $Text = {
	Methods: {
		remove: function () {
			this.element.parentNode.removeChild(this.element);
		}
	},
	update: function (el) {
		var el = { element: el, _prosto_updated: true };
		for (i in $Text.Methods) {
			el[i] = methodize(el, $Text.Methods[i]);
		}
		return el;
	}
}

$Element.update = function (el) {
	if (typeof el._updates == "undefined") {
		el._updates = {}
	}
	if (el._updates.prosto) {
		return el;
	}
	if (el.nodeType == 3) { //textNode
		return $Text.update(el);
	}
	addMethods(el, $Element.Methods)
	var tag = el.nodeName.toLowerCase();
	if ($isdef($Element.MethodsByTag[tag])) {
		addMethods(el, $Element.MethodsByTag[tag])
	}
	el.element = el;
	el._updates.prosto = true;
	return el;
}

function methodize(el, f) {
	return function() { return f.apply(el, arguments); }
}

function addMethods(obj, methods) {
	for (var i in methods) {
		obj[i] = methodize(obj, methods[i]);
	}
}

function $event(e) {
	var res = {};
	if (!$isdef(e)) {
		e = window.event;
	} else if (e.updatedEvent) {
		return e;
	}
	$extend(res, e);
	if (e.srcElement) { res.target = e.srcElement; }
	if (e.relatedTarget) { res.toElement = e.relatedTarget; }
	if (e.which) { res.keyCode = e.which; }
	res.updatedEvent = true;
	return res;
}
