function $A(obj, iterator){
	var arr = [];
	for(var i = 0; i < obj.length; i++){
		arr.push(iterator ? iterator(obj[i]) : obj[i]);
	}
	return arr;
}
function $O(item, index){
	return {item: item, index: index};
}
var $break = new Object();
var $continue = new Object();
//Object functions
Object.copy = function(obj){
	var obj_c = {};
	for(var i in obj){
		obj_c[i] = obj[i];
	}
	return obj_c;
}
Object.count = function(obj){
	var count = 0;
	for(var i in obj){
		count++;
	}
	return count;
};
function MergeObjects(obj1, obj2){
	for(var i in obj2){
		obj1[i] = obj2[i];
	}
	return obj1;
}
Object.extend = MergeObjects;
function undefined(obj){
	return (typeof obj == "undefined");
}

var __toString = function(){
	var str = __toString.bounds.left + "object " + this.__name + __toString.bounds.right;
	return str;
};
__toString.bounds = {
	left: "[[",
	right: "]]"
};

function $$(id, doc){
	return $Node((doc || document).getElementById(id));
}
function $_(id, doc){
	return (doc || document).getElementById(id);
}
function $T(tName, parent, FIRST){
	var arr = $A((parent || document).getElementsByTagName(tName), $Node);
	return FIRST ? arr[0] : arr;
}
function $T_(tName, parent, FIRST){
	var arr = $A((parent || document).getElementsByTagName(tName));
	return FIRST ? arr[0] : arr;
}
function $C(className, parent, tagName, FIRST){
	var detected = (parent && parent.IS_ARRAY ? parent : ($T(tagName || "*", parent) || [])).detects(detectFuncs.className.bind(className));
	return detected.length ? (FIRST ? detected[0] : detected) : null;
}
function $C_arr(arr_classNames, parent, tagName, iterator){
	var ret_arr = [];
	parent = parent ? _elem(parent) : document.body;
	tagName = tagName ? tagName : "*" ;
	iterator = iterator ? iterator : function(val){return val;};
	var collection = $T(tagName, parent);
	collection.each(function(col, c_ind){
		arr_classNames.each(function(cName, ind){
			if(col.className.has_separated_value(cName)){
				ret_arr[ind] = 	iterator(col);
				throw $continue;
			}
		});
	});
	return ret_arr;
}
function $I(type, parent, FIRST){
	var detected = (parent && parent.IS_ARRAY ? parent : ($T("INPUT", parent) || [])).detects(detectFuncs.type.bind(type));
	return detected.length ? (FIRST ? detected[0] : detected) : null;
}
function $Node(elem){//extend node with usefull functions
	if(!elem){
		return null;
	}
	for(var i in Node_extendFucntions){
		if(typeof elem[i] == 'undefined'){
			elem[i] = Node_extendFucntions[i];
		}
	}
	return elem;
}
function $F(form){//getFormElements
	var detected = ($T("INPUT", form) || []).concat($T("SELECT", form) || []).concat($T("TEXTAREA", form) || []);
	return detected.length ? detected : null;
}
function $N(name, parent, FIRST){//getFormElementByName
	var detected = (parent && parent.IS_ARRAY ? parent :  ($F(parent) || [])).detects(detectFuncs.name.bind(name));
	return detected.length ? (FIRST ? detected[0] : detected) : null;
}
function $Kids(elem){
	var arr = [];
	$A(elem.childNodes, function(kid){
		if(kid.nodeType == 1){
			arr.push($Node(kid));
		}
	});
	return arr;
}
var detectFuncs = {
	name: function(el){
		return el.name.toLowerCase() == this.toLowerCase();
	},
	className: function(el){
		return el.hasClass(this);
	},
	type: function(el){
		return el.type.toLowerCase() == this.toLowerCase();
	},
	value: function(el){
		return el.value == this;	
	},
	tagName: function(el){
		return el.tagName.toUpperCase() == this;
	}
}
var Node_extendFucntions = {
	addClass: function(c){
		if(this.hasClass(c)){
			return false;
		}
		this.className = this.className.split(" ").add(c).join(" ");
		return true;
	},
	removeClass: function(c){
		if(!this.hasClass(c)){
			return false;
		}
		this.className = this.className.split(" ").remove_v(c).join(" ");
		return true;
	},
	toggleClass: function(c){
		if(this.hasClass(c)){
			this.removeClass(c);
		}else{
			this.addClass(c);
		}
	},
	setClass: function(c){
		this.className = c;
	},
	replaceClass: function(old_c, c){
		this.className = this.className.replace(old_c, c);
	},	
	hasClass: function(className){
		return this.className.split(" ")._indexOf(className) != -1;
	},
	app: function(elem){
		if(!elem || !elem.nodeType){
			return false;
		}
		this.appendChild(elem);
		return true;
	},
	prep: function(elem, before_elem){
		if(!elem || !elem.nodeType){
			return false;
		}
		if(!this.firstChild){
			this.app(elem)
		}else{
			this.insertBefore(elem, before_elem || this.firstChild);
		}
		return true;
	},
	remove: function(elem){
		if(!elem || !elem.nodeType || elem.parentNode != this){
			return false;
		}
		this.removeChild(elem);
		return true;
	},
	print: function(value, CLEAR){
		if(CLEAR){
			clearElem(this);
		}
		this.app(Text(value));
	},
	hide: function(vis){
		if(vis){
			this.style.visibility = "hidden";
		}else{
			this.style.display = "none";
		}
	},
	show: function(vis){
		if(vis){
			if(typeof vis == 'string'){
				this.style.display = vis;
			}else{
				this.style.visibility = 'visible';
			}
		}else{
			this.style.display = 'block';
		}
	},
	stretch: function(node){
		var par = node || this.parentNode;
		this.style.width = par.offsetWidth + 'px';
		this.style.height = par.offsetHeight + 'px';
	},
	_center: function(_par, B_ZERO){
		var par = _par || this.parentNode;
		var h_mar = par.offsetWidth - this.offsetWidth;
		var v_mar = par.offsetHeight - this.offsetHeight;
		if(B_ZERO && h_mar < 0){
			this.style.left = 0 + "px";
		}else{
			this.style.left = Math.round(h_mar / 2) + "px";
		}
		if(B_ZERO && v_mar < 0){
			this.style.top = 0 + "px";
		}else{
			this.style.top = Math.round(v_mar / 2) + "px";
		}
	},
	_away: function(){
		this.style.left = -3000 + "px";
		this.style.top = -3000 + "px";
	},
	clear: function(){
		clearElem(this);
	},
	dims: function(w, h){
		this.style.width = w + "px";
		this.style.height = h + "px";
	},
	pos: function(left, top){
		this.style.left = left+ 'px';
		this.style.top = top + 'px';
	}
};
Node_extendFucntions.append = Node_extendFucntions.app;
Node_extendFucntions.prepend = Node_extendFucntions.prep;

//Function.prototype
Function.prototype.bind = function(){
	var _args = [];
	var _method = this;
	var _object = arguments[0];
	for(var i = 1; i < arguments.length; i++){
		_args.push(arguments[i]);
	}
	var retfunc = function(){
		return _method.apply(_object, $A(arguments).concat(_args));
	};
	retfunc.bound = $A(arguments);
	return retfunc;
};
Function.prototype.bindAvoidingEvent = function(){
	var _args = [];
	var _method = this;
	var _object = arguments[0];
	for(var i = 1; i < arguments.length; i++){
		_args.push(arguments[i]);
	}
	return function(){
		return _method.apply(_object, $A(_args).concat(arguments));
	}	
};
function _isChild(elem, parent){
	if(!elem)
		return false;
	var par = elem.parentNode;
	try{
		while(par && par != parent && par.nodeType != 9){
			par = par.parentNode;
		}
	}catch(e){
		alert(alert(par.nodeType));
	}
	return !par ? false : (par == parent);
}
function clearElem(elem){
	elem = _elem(elem);
	while(elem.firstChild){
		elem.removeChild(elem.firstChild);
	}
}
function _elem(obj){
	if(obj.nodeName){
		return obj;
	}else{
		if(obj.elem){
			return obj.elem;
		}
		if(obj.moveable){
			return _elem(obj.moveable);
		}
		if(obj.resizeable){
			return _elem(obj.resizeable);		
		}
	}
}

//Boolean.prototype
Boolean.prototype.each = function(){
	return false;
};

//Array.prototype
Array.prototype.each = function(iterator){
	try{
		for(var i = 0; i < this.length; i++){
			try{
				var ret = iterator(this[i], i);
				if(ret != null){
					this[i] = ret;
				}
			}catch(e){
				if(e != $continue)
					throw e;
			}
		}
	}catch(e){
		if(e != $break)
			throw e;
	}
	return this;
};
Array.prototype.clone = function(){
	var arr = [];
	this.each(function(item){
		arr.push(item);
	});
	return arr;
};
Array.prototype._indexOf = function(item){
	var index = -1;
	this.each(function(it, ind){
		if(it == item){
			index = ind;
			throw $break;
		}
	});
	return index;
}
if(undefined(Array.prototype.indexOf)){
	Array.prototype.indexOf = Array.prototype._indexOf;
};
Array.prototype.random = function(REM){
	var ind = Math.round(Math.random() * (this.length - 1));
	var item = this[ind];
	if(REM){
		this.remove(ind);
	}
	return item;
};
Array.prototype.last = function(){
	return this[this.length - 1];
};
Array.prototype.invert = Array.prototype.reverse;
Array.prototype.detect = function(iterator, OBJ){
	var ret;
	this.each(function(item, index){
		if((iterator || _eF)(item, index)){
			ret = OBJ ? $O(item, index) : item;
			throw $break;
		}
	});
	return ret;
};
Array.prototype.detect_i = function(iterator){
	var ret;
	this.each(function(item, index){
		if((iterator || _eF)(item, index)){
			ret = index;
			throw $break;
		}
	});
	return ret;
};
Array.prototype.detects = function(iterator, obj){
	var ret = [];
	this.each(function(item, index){
		if((iterator || _eF)(item, index)){
			ret.push(obj ? $O(item, index) : item);
		}
	});
	return ret;
};
Array.prototype.remove = function(num){
	if(num >= this.length || num < 0){
		return;
	}
	var ret = this[num];
	for(var i = num; i < this.length - 1; i++){
		this[i] = this[i+1];
	}
	this.pop();
	return ret;
};
Array.prototype.insert = function(value, position){
	position = (position && position > 0) ? position : 0;
	if(position >= this.length){
		this.push(value);
		return;
	}
	for(var i = this.length - 1; i >= position; i--){
		this[i+1] = this[i];
	}
	this[position] = value;
	return this;
};
Array.prototype.add = function(v){
	this.push(v);
	return this;
};
Array.prototype.remove_v = function(v){
	this.remove(this.indexOf(v));
	return this;
};
Array.prototype.remove_vals = function(vals){
	vals.each(function(v){
		this.remove_v(v);
	}.bind(this));
};
Array.prototype.has = function(val){
	return (this.indexOf(val) != -1);
}
Array.prototype.clean = function(val){
	var indexes = [];
	this.each(function(item, index){
		if(item == val){
			indexes.push(index);
		}
	});
	indexes.each(function(ind){
		this.remove(ind);
	}.bind(this));
	return this;
}
Array.prototype.before = function(item){
	return this.slice(0, this.indexOf(item));
};
Array.prototype.after = function(item){
	return this.slice(this.indexOf(item) + 1);
};
Array.prototype.next = function(item, LOOP){
	var ind = this.indexOf(item);
	if(ind == -1){
		return false;
	}
	if(ind == this.length - 1){
		if(LOOP){
			return this[0];
		}else{
			return false;
		}
	}else{
		return this[ind + 1];
	}
};
Array.prototype.previous = function(item, LOOP){
	var ind = this.indexOf(item);
	if(ind == -1){
		return false;
	}
	if(ind == 0){
		if(LOOP){
			return this.last();
		}else{
			return false;
		}
	}else{
		return this[ind - 1];
	}
};
Array.prototype.replace = function(val, pos){
	var ind = this.indexOf(val);
	if(ind < pos){
		this.remove(ind);
		this.insert(val, pos - 1);
	}else{
		this.remove(ind);
		this.insert(val, pos);	
	}
};
Array.prototype.shuffle = function(){
	var cloned = this.clone();
	var shuffled = [];
	while(cloned.length){
		shuffled.push(cloned.random(1));
	}
	return shuffled;
};
Array.prototype.interplace = function(num1, num2){
	var val1 = this[num1];
	var val2 = this[num2];
	this[num2] = val1;
	this[num1] = val2;
};
Array.prototype.try_method = function(){
	var args = $A(arguments);
	var method_name = args.shift();
	this.each(function(item){
		if(item[method_name]){
			item[method_name].apply(item, args);
		}
	});
};
Array.prototype.IS_ARRAY = true;
Number.prototype.signOf = function(){
	if(this == 0){
		return 1;
	}else{
		return Math.abs(this) / this;
	}
};
Number.prototype._signOf = function(){
	if(this == 0){
		return 0;
	}else{
		return Math.abs(this) / this;	
	}
};
Number.prototype.oppSign = function(){
	return this.signOf * (-1);
};
Number.prototype.sq = function(){
	return this * this;
};
Number.prototype.power = function(pow){
	if(pow == 0){
		return 1;
	}else if(pow < 0){
		throw "Sorry, I'm bad at mathematics. I can't raise a number to a negative power";
	}
	var num = this;
	for(var i = 1; i < pow; i++){
		num *= this;
	}
	return num;
};
Number.prototype._in = function(from, to, STRICT){
	if(STRICT){
		return (this > from && this < to);
	}else{
		return (this >= from && this <= to);
	}
};
Number.prototype.times = function(iterator){
	for(var i = 0; i < Math.abs(this); i++){
		iterator(i * this.signOf());
	}
};
Number.prototype.toDate = function(){
	return this < 10 ? '0' + this : String(this);
};
function toConsole(what, console){
	if(undefined(what)){
		what = "[undefined]";
	}
	console = console ? console : !undefined(document.body) ? document.body : null;
	if(!console){
		document.write(what);
	}
	var oDiv = document.createElement('DIV');
	oDiv.className = toConsole.defaultElemClassName;
	oDiv.appendChild(document.createTextNode(what));
	console.appendChild(oDiv);
	if(console.onprint){
		console.onprint.fire();
	}
}
toConsole.defaultElemClassName = "printed-elem";
var print = toConsole;
String.prototype.print = Array.prototype.print = Number.prototype.print = Boolean.prototype.print = Function.prototype.print = function(console){
	print(this, console);
};
String.prototype.camelize = function(){
	var arrThis = this.split('-');
	if(arrThis.length == 1){
		return this;
	}else{
		var wordCamelized = arrThis[0];
		var firstSymbol;
		for(var i = 1; i < arrThis.length; i++){
			firstSymbol = arrThis[i].substr(0, 1);
			arrThis[i] = arrThis[i].substr(1);
			arrThis[i] = firstSymbol.toUpperCase() + arrThis[i];
			wordCamelized+=arrThis[i];
		}
		return wordCamelized;
	}
};
String.prototype.s_each = function(iterator){
	var arr = this.split('');
	arr.each(iterator);
};
String.prototype.no_print_characters_only = function(){
	var ret = true;
	this.s_each(function(chr){
		if(chr.charCodeAt(0) >= 30){
			ret = false;
			throw $break;
		}
	});
	return ret;
};
String.prototype.splitBy = function(num){
	if(num <= 1){
		return this.split('')
	}
	var splitted = [];
	var start = 0;
	for(var i = 0; i < this.length; i+=num){
		splitted.push(this.substr(i, num))
	}
	return splitted;
};
String.prototype.multiply = function(){
	return this + this;
};
String.prototype.reverse = String.prototype.invert = function(){
	var str = "";
	for(var i = this.length - 1; i >= 0; i--){
		str += this.charAt(i);
	}
	return str;
};
String.prototype.eq = function(str){
	var uThis = this.toUpperCase();
	return (uThis == str.toUpperCase());
};
String.prototype.has_separated_value = function(value, separator){
	var ret = false;
	var reg = new RegExp("^" + value + "$");
	var strings = this.split(separator || " ");
	strings.each(function(s){
		if(s.match(reg)){
			ret = true;
			throw $break;
		}
	});
	return ret;
};
String.prototype.tagify = function(tagName){
	return "<" + tagName + ">" + this + "</" + tagName + ">";
}
function printObject(o, parent){
	for(var i in o){
		print(i + " => " + o[i], parent);
	}
}
var print_r = printObject;
function __init_settings(settings){
	var obj = Object.extend(Object.copy(this.constructor.__default), settings || {});
	return obj;
}
function __init_iterators(iterators){
	return Object.extend(Object.copy(this.constructor.__iterators), iterators || {});
}
function __iterate(item, name, ind){
	if(!this.iterators[name]){
		return item;
	}
	this.iterators[name].each(function(obj_iter){
		item = obj_iter.func.call(this, item, ind);
	}.bind(this));
	return item;
}
function __init_events(){
	this._events.each(function(obj){
		if(obj.func_name){
			if(obj.type == "before"){
				createBeforeEvent(this, obj.func_name, obj.name)
			}else if(obj.type == "after"){
				createAfterEvent(this, obj.func_name, obj.name);
			}
		}else{
			this["on" + obj.name] = new DOMEvent(this);
		}
	}.bind(this));
}
function __to_instances(){
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
var default_prototype_functions = {
	init_settings: __init_settings, init_iterators: __init_iterators, iterate: __iterate, init_events: __init_events, toString: __toString, to_instances: __to_instances
};

function $Radios(tpl_collection, label_settings, iterators){
	this.collection = tpl_collection;
	this.radios = this.elems = [];
	this.labels = [];
	this.disabled = [];
	this.onchange = new DOMEvent(this);
	this.ondisable = new DOMEvent(this);
	this.onenable = new DOMEvent(this);
	this.onadd = new DOMEvent(this);
	this.onremove = new DOMEvent(this);
	this.settings = this.init_settings(label_settings);
	this.iterators = this.init_iterators(iterators);
	this.init();
}
$Radios.prototype.init_settings = __init_settings;
$Radios.prototype.init_iterators = __init_iterators;
$Radios.prototype.init = function(){
	this.collection.each(function(item, ind){
		this.init_radio(item, ind);
		this.init_label(item, ind);
	}.bind(this));
	if(this.collection.length){
		this.pattern = this.collection[0].cloneNode(true);
		this.parent = this.collection[0].parentNode;
	}
};
$Radios.prototype.init_radio = function(item, ind){
	var rad = $I("radio", item, 1);
	this.radios.push(rad);
	if(rad.checked){
		this.checked = rad;
		this.value = rad.value;
	}
	if(rad.disabled){
		this.disabled.push(rad);
	}
	rad.model = this;
	rad.root = item;
	item._radio = rad;
	rad.onclick = this.click;
	this.iterators.radio.each(function(iter){
		rad = iter(rad);
	});
};
$Radios.prototype.init_label = function(item, ind){
	var lab = this.find_label(item);
	this.labels.push(lab);
	if(!lab){
		return null;
	}
	lab.radio = item._radio;
	lab.model = this;
	lab.root = item;
	lab.value = lab.firstChild.nodeValue;
	lab.onclick = this.click.bind(lab.radio);	
	item._label = lab;
	item._radio.label = lab;
	this.iterators.label.each(function(iter){
		lab = iter(lab);
	});
};
$Radios.prototype.find_label = function(item){
	var detected = $T(this.settings.labelTag, item);
	if(!detected){
		return null;
	}
	if(this.settings.labelClass){
		return $C(this.settings.labelClass, detected, null, 1);
	}else{
		return detected[0];
	}	
};
$Radios.prototype.check = function(rad){
	if(rad.disabled){
		return false;
	}
	var old_checked = this.checked;
	rad.checked = true;
	this.checked = rad;
	this.value = rad.value;
	this.onchange.fire(rad, old_checked);
	return true;
};
$Radios.prototype.click = function(){

	this.model.check(this);
};
$Radios.prototype.remove = function(rad){
	var ind = this.elems.indexOf(rad);
	var item = this.collection[ind];
	var lab = this.labels[ind];

	this.parent.remove(item);
	this.collection.remove(ind)
	this.elems.remove(ind);
	this.labels.remove(ind);
	this.onremove.fire(rad, rad.label, rad.root);
};
$Radios.prototype.change_label = function(lab, val){
	clearElem(lab);
	lab.app(Text(val));
	lab.value = val;
}
$Radios.prototype.add = function(rad_val, label_val){
	var item = this.pattern.cloneNode(true);
	this.collection.push(item);
	var ind = this.collection.length - 1;
	this.parent.app(item);
	this.init_radio(item, ind);
	this.init_label(item, ind);
	if(item._label){
		this.change_label(item._label, label_val);
	}
	item._radio.value = rad_val;
	
	this.onadd.fire(item._radio, item._label, item);
};
$Radios.prototype.disable = function(rad){
	if(rad.disabled){
		return false;
	}
	rad.disabled = 1;
	this.disabled.push(rad);
	this.ondisable.fire(rad);
	return true;
};
$Radios.prototype.enable = function(rad){
	if(!rad.disabled){
		return false;
	}
	rad.disabled = 0;
	this.disabled.remove_v(rad);
	this.onenable.fire(rad);
	return true;
};
$Radios.prototype.__name = "radios";
$Radios.prototype.toString = __toString;

$Radios.__default = {
	labelClass: "label",
	labelTag: "SPAN"
};
$Radios.__iterators = {
	radio: [], label: []
};

function $Checkbox(checkbox, label){
	this.elem = checkbox;
	this.name = this.elem.name;
	this.label = label || null;
	this.oncheck = new DOMEvent(this);
	this.onuncheck = new DOMEvent(this);
	this.ondisable = new DOMEvent(this);
	this.onenable = new DOMEvent(this);
	this.init();
}
$Checkbox.prototype.init = function(){
	this.init_check();
	this.init_label();
};
$Checkbox.prototype.init_check = function(){
	this.CHECKED = this.elem.checked;
	this.DISABLED = this.elem.disabled;
	this.elem.model = this;
	this.elem.onclick = this.click.bind(this);
};
$Checkbox.prototype.init_label = function(){
	if(!this.label){
		return false;
	}
	this.label.value = this.label.firstChild.nodeValue;
	this.label.model = this;
	this.label.onclick = this.click.bind(this);
};
$Checkbox.prototype.check = function(){
	if(this.CHECKED || this.DISABLED){
		return false;
	}
	this.elem.checked = 1;
	this.CHECKED = true;
	this.oncheck.fire();
	return true;
};
$Checkbox.prototype.uncheck = function(){
	if(!this.CHECKED || this.DISABLED){
		return false;
	}
	this.elem.checked = 0;
	this.CHECKED = false;
	this.onuncheck.fire();
	return true;
};
$Checkbox.prototype.click = function(){
	if(this.CHECKED){
		this.uncheck();
	}else{
		this.check();
	}
};
$Checkbox.prototype.set_name = function(name){
	this.elem.name = name;
	this.name = name;
};
$Checkbox.prototype.set_label = function(val){
	this.label.value = val;
	clearElem(this.label);
	this.label.app(Text(val));
}
$Checkbox.prototype.disable = function(){
	if(this.DISABLED){
		return false;
	}
	this.DISABLED = true;
	this.elem.disabled = 1;
	this.ondisable.fire();
	return true;
};
$Checkbox.prototype.enabel = function(){
	if(!this.DISABLED){
		return false;
	}
	this.DISABLED = false;
	this.elem.disabled = 0;
	this.onenable.fire();
	return true;
};
function $Checkset(checkbox_collection){

}
function _eF(x){
	return x;
}
function clearElem(elem){
	if(!elem){
		return false;
	}
	while(elem.firstChild){
		elem.removeChild(elem.firstChild);
	}
}
function Text(val){
	return document.createTextNode(val);
}
function Element(tName, attribs){
	var el = document.createElement(tName);
	var obj = attribs || {};
	for(var i in obj){
		el[i] = obj[i]
	}
	return $Node(el);
}

function serialize_inputs(root, inputs, prefix){
	inputs.each(function(ip){
		root[(undefined(prefix) ? "_" : prefix) + ip.name] = ip.value;
	});
	return root;
}
function set_form_values(rv, inputs, root){
	var ips = inputs;
	if(!inputs.IS_ARRAY){
		ips = $F(inputs);
	}
	for(var i in rv){
		var val = rv[i];
		if(typeof val != "object"){
			var el = $N(i, ips, 1);
			if(el){
				if(el.type == "checkbox"){//very bad, but for this time will do
					if(Boolean(Number(rv[i]))){
						el.checked = true;
					}else{
						el.checked = false;
					}
				}else{
					el.value = rv[i];
				}
			}else{
				if(root){
					root["_" + i] = rv[i];
				}
			}
		}
	}
}
function get_form_values(inputs){
	var ips = inputs;
	if(!inputs.IS_ARRAY){
		ips = $F(inputs);
	}

	var qo = {};
	ips.each(function(ip){
		if(ip.type != "button" && ip.type != "image" && ip.type != "submit"){
			if(ip.type == "checkbox"){
				if(ip.checked){
					qo[ip.name] = 1;
				}else{
					qo[ip.name] = 0;
				}
			}else{
				qo[ip.name] = ip.value;
			}
		}
	});
	return qo;
}
var HELP = {
	iterators: {
		serialize_inputs: {
			func: function(item){
				serialize_inputs(item, $I("hidden", item));
				return item;
			},
			name: 'serizlize inputs'
		}
	}
}
function stopPropagation(e){
	var ev = window.event || e;
	if(ev.stopPropagation){
		ev.stopPropagation();
	}else{
		ev.cancelBubble = true;
	}
}
function preventDefault(e){
	if(e.preventDefault){
		e.preventDefault();
	}else{
		e.returnValue = false;
	}
}
function AttachEvent(objectTarget, eventType, funcionHandler){
	if (objectTarget.addEventListener) { //for DOM-compliant browsers
		objectTarget.addEventListener(eventType, funcionHandler, false);
	}
	else if(objectTarget.attachEvent){ //for IE
		objectTarget.attachEvent('on' + eventType, funcionHandler);
	}
	else{ //for all others
		objectTarget['on' + eventType] = funcionHandler;
	}

}
function DetachEvent(objectTarget, eventType, funcionHandler){
	if (objectTarget.addEventListener){ //for DOM-compliant browsers
		objectTarget.removeEventListener(eventType, funcionHandler, false);
	}
	else if(objectTarget.attachEvent){ //for IE
		objectTarget.detachEvent('on' + eventType, funcionHandler);
	}
	else { //for all others
		objectTarget['on' + eventType] = '';
	}
}
function get_event(ev){
	return {
		clientX: ev.clientX,
		clientY: ev.clientY,
		offsetX: ev.offsetX || ev.layerX,
		offsetY: ev.offsetY || ev.layerY
	};
}
function _get_type(item, word){
	return item.className.split(' ').detect(function(c){return c.indexOf((word || '') + '-') != -1}).split('-').last();
}
function exit(){
	throw "exit";
}


function ImageLoader(container){
	this.container = container;
}
ImageLoader.prototype.load_image = function(src, w, h, callback){
	var img = document.createElement('IMG');
	img.src = src;
	this.container.append(img);	
	if(img.height < h || img.width < w){
		img.onload = function(){
			callback(this);
		}
	}else{
		callback(img);
	}
};
function png_filter(src, method){
	return "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='" + (method || "crop") + "')";
}



var $breakEvent;
function createEvent(oThis, f_name, name){
	var func = oThis[f_name];
	oThis['on' + name] = new DOMEvent(oThis);		
	oThis[f_name] = function(){
		try{
			oThis['on' + name].fire.apply(oThis['on' + name], $A(arguments));
			func.apply(oThis, $A(arguments));
		}catch(e){
			if(e != $breakEvent){
				throw e;
			}
		}
	}
}
function DOMEvent(oThis){
	this.listeners = [];
	this.oThis = oThis || false;
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
DOMEvent.prototype.register = function(name, lnr, callslimit, place){
	if(this.hasNamedListener(name)){
		return false;
	}
	var func = lnr.bound ? lnr : !this.oThis ? lnr : lnr.bind(this.oThis);
	var ev = {
		name: name,
		func: func,
		calls: 0,
		callslimit: callslimit ? callslimit : -1
	};
	if(typeof place != "undefined"){
		this.listeners.insert(ev, place);
	}else{
		this.listeners.push(ev);
	}
}
DOMEvent.prototype.remove = function(name){
	this.listeners.each(
		function(lnr, index){
			if(lnr.name == name){
				this.listeners.remove(index);
				throw $break;
			}
		}.bind(this)
	);	
}
DOMEvent.prototype.fire = function(){
	var args = arguments;
	this.listeners.each(
		function(lnr){
			var obj = lnr.func.bound ? lnr.func.bound[0] : this.defaultThis || lnr;
			var ret = lnr.func.apply(obj, args);
			lnr.calls++;
			if(lnr.calls == lnr.callslimit){
				this.remove(lnr.name);
			}
			if(!undefined(ret) && ret === false){
				this._break();
				throw $breakEvent;
			}
		}.bind(this)
	);
}
DOMEvent.prototype.length = function(){
	return this.listeners.length;
}
DOMEvent.prototype.hasNamedListener = function(name, no_bool){
	var ret = false;
	this.listeners.each(
		function(lnr){
			if(lnr.name == name){
				ret = lnr;
				throw $break;
			}
		}
	);
	return !no_bool ? !!(ret) : ret;
}
DOMEvent.prototype.get = function(name){
	return this.hasNamedListener(name, true);
};
DOMEvent.prototype._listeners = function(){
	var str = "";
	this.listeners.each(function(lnr){
		str += " " + lnr.name + " ::";
	})
	return str.replace(/::$/, "");
}
DOMEvent.prototype.__name = "DOMEvent";
DOMEvent.prototype.toString = __toString;
DOMEvent.cloneEvent = function(d_event, oThis){
	var obj = {};
	obj.oThis = typeof oThis == "undefined" ? null : oThis;
	obj.register = function(name, lnr, callslimit, place){
		var func = lnr.bound ? lnr : this.oThis != null ? lnr.bind(this.oThis) : lnr;
		d_event.register(name, func, callslimit, place);
	}
	obj.remove = function(name){
		d_event.remove(name)
	}
	obj.length = function(){
		return d_event.length();
	}
	obj.hasNamedListener = function(name){
		return d_event.hasNamedListener(name);
	}
	obj.get = function(name){
		return d_event.get(name);
	}
	obj.eachLnr = function(iterator){
		d_event.eachLnr(iterator);
	}
	obj.toString = __toString;
	obj.__name = "DOMEvent - cloned";
	obj._listeners = function(){
		return d_event._listeners();
	}
	obj._EVENT_CLONE = true;
	return obj;
}
DOMEvent.prototype._break = _eF;
function E_Connection(oThis){
	this.name = "e-connection";
	this.oThis = oThis;
	this.listeners = [];
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
E_Connection.prototype.register = DOMEvent.prototype.register;
E_Connection.prototype.remove = DOMEvent.prototype.remove;
E_Connection.prototype.hasNamedListener = DOMEvent.prototype.hasNamedListener;
E_Connection.prototype.length = DOMEvent.prototype.length;
E_Connection.prototype.add = function(d_event, args){
	d_event.register(this.name, function(){
		this.listeners.each(function(lnr){
			lnr.func.apply(lnr.func.bound, args);
		}.bind(this))
	}.bind(this));
}

function _initEvents(){
	this._events.each(function(obj){
		createEvent(this, obj.func_name, obj.name);
	}.bind(this));
}

function Limit(from, to){
	this.from = from;
	this.to = to;
	this.value = this.from;
	this.onmore = new DOMEvent(this);
	this.onless = new DOMEvent(this);
	this.onmoreout = new DOMEvent(this);
	this.onlessout = new DOMEvent(this);
	this.onchange = new DOMEvent(this);
	this.TO_REACHED = false;
	this.FROM_REACHED = true;
	this.REACHED = true;
	this.SECOND_REACH = false;
	this.PREVENT_SECOND_FIRE = true;
	this.TO_OUT = false;
	this.FROM_OUT = false;
	this.MORE_VALUE = 0;
	this.LESS_VALUE = 0;
	this.exceeded = 0;
	this.preceeded = 0;
	this._attemped_value;
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Limit.prototype.change = function(val){
	this._attempted_value = val;
	var value = val;
	value = this.checkFrom(value);
	value = this.checkTo(value);
	this.value += value;
	this.onchange.fire();
	if(this.TO_REACHED){
		this.onmore.fire(this);
	}
	if(this.FROM_REACHED){
		this.onless.fire(this);
	}
	if(this.TO_OUT){
		this.onmoreout.fire(this);
	}
	if(this.FROM_OUT){
		this.onlessout.fire(this);
	}
}
Limit.prototype.setValue = function(val){
	var value = val - this.from;
	this.change(value);
}
Limit.prototype.checkTo = function(val){
	var value = val;
	this.TO_OUT = false;
	if(this.TO_REACHED){
		if(this.value + value < this.to){
			this.TO_REACHED = false;
			this.TO_OUT = true;
			this.TO_OUT_VALUE = value;
			this.REACHED = false;
			this.SECOND_REACH = false;
		}else{
			this.exceeded = value;
			value = 0;
			this.MORE_VALUE = value;
			this.SECOND_REACH = true;
		}
	}else{
		if(this.value + value >= this.to){
			var v = this.to - this.value;
			this.exceeded = value - v;
			value = v;
			this.MORE_VALUE = value;
			this.TO_REACHED = true;
			this.REACHED = true;
		}
	}
	return value;
}
Limit.prototype.checkFrom = function(val){
	var value = val;
	this.FROM_OUT = false;
	if(this.FROM_REACHED){
		if(this.value + value > this.from){
			this.FROM_REACHED = false;
			this.FROM_OUT = true;
			this.FROM_OUT_VALUE = value;
			this.REACHED = false;
			this.SECOND_REACH = false;
		}else{
			this.preceeded = value;
			value = 0;
			this.LESS_VALUE = value;
			this.SECOND_REACH = true;
		}
	}else{
		if(this.value + value <= this.from){
			var v = this.value + value;
			value = -this.value + this.from;
			this.LESS_VALUE = value;
			this.preceeded = v;
			this.FROM_REACHED = true;
			this.REACHED = true;
		}
	}
	return value;
}
Limit.prototype.__name = "Limit";
Limit.prototype.toString = __toString;
Limit._TO_INSTANCES = true;
Limit._instances = [];
Limit.__loaded = true;


var Style = {
	getElementStyle: function(elem, property, pInt){
		var value;
		if(window.getComputedStyle){
			var compStyle = window.getComputedStyle(elem, '');
			value = compStyle.getPropertyValue(property);
		}else if(elem.currentStyle){
			if(property == "float"){
				property = "style-float";
			}
			value  = elem.currentStyle[property.camelize()]; //!!String.camelize()
		}
		return pInt ? parseInt(value) : value;
	},
	getDimensions: function(elem){
		var width, height;
		if(window.resizeable && elem instanceof resizeable){
			width = elem.width;
			height = elem.height;
		}else{
			width = parseInt(this.getElementStyle(elem, "width"));
			if(isNaN(width)){
				width = elem.offsetWidth;
			}
			height = parseInt(this.getElementStyle(elem, "height"));		
			if(isNaN(height)){
				height = elem.offsetHeight;
			}
		}

		return {width: width, height: height};
	},
	setElementStyle: function(elem, propName, propVal, usePx){
		if(typeof propName == "string"){
			if(usePx && (typeof propVal == "number")){
				propVal += "px";
			}
			elem.style[propName] = propVal;
		}else if(typeof propName == "object"){
			for(var i in propName){
				var val = propName[i];
				if(typeof val == "number" && usePx){
					val += "px";
				}//
				elem.style[i] = val;
			}//
		}//
	},
	getCoords: function(elem){
		var left = parseInt(this.getElementStyle(elem, 'left'));
		var top = parseInt(this.getElementStyle(elem, 'top'));
		var right = parseInt(this.getElementStyle(elem, 'right'));
		var bottom = parseInt(this.getElementStyle(elem, 'bottom'));
		left = isNaN(left) ? 0 : left;
		top = isNaN(top) ? 0 : top;
		right = isNaN(right) ? 0 : right;
		bottom = isNaN(bottom) ? 0 : bottom;
		return {
			left: left,
			top: top,
			right: right,
			bottom: bottom
		}

	},
	_check_browser: function(){
		if(window.getComputedStyle){
			if(window.opera)	{
				return "Opera";
			}else{
				return "Gecko";
			}
		}else{
			return "IE";
		}
	},
	_browser_version: function(){
		return this["_" + this._browser + "_version"]();
	},
	_IE_version: function(){
		var i = navigator.appVersion.indexOf("MSIE") + 5;
		var version = "";
		while(navigator.appVersion.charAt(i) != ";"){
			version += navigator.appVersion.charAt(i);
			i++;
		}
		return version;
	},
	_Gecko_version: function(){
		if(navigator.userAgent.indexOf("Firefox") == -1){
			return "unknown";
		}
		var i = navigator.userAgent.indexOf("Firefox\/") + 8;
		return navigator.userAgent.substr(navigator.userAgent.indexOf("Firefox\/") + 8);
		
	},
	_Opera_version: function(){
		return navigator.appVersion.substring(0, navigator.appVersion.indexOf(" "));
	}
};
Style._getParents = function(elem){
	var pars = [];
	elem = elem.parentNode;
	while(elem.tagName.toUpperCase() != "BODY"){
		pars.push(elem);
		elem = elem.parentNode;
	}
	return pars;
};
Style._browser = Style._check_browser();
Style._br_version = Style._browser_version();
Style.$ = Style.getElementStyle;
Style.$D = Style.getDimensions;
Style.$C = Style.getCoords;
Style.set = Style.setElementStyle;
Style.__loaded = true;



function Timer(intervalValue){
	this.intervalValue = intervalValue ? intervalValue : 500;
	this.interval = null;
	this.events = [];
	this.listeners = [];
	this.onstart = new DOMEvent();
	this.onstop = new DOMEvent();
	this.isTicking = false;
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Timer.prototype.start = function(){
	if(this.isTicking){
		return;
	}
	this.calls = 0;
	this.timeElapsed = 0;
	this.interval = setInterval(
		this.intervalFunction.bind(this),
		this.intervalValue
	);
	this.isTicking = true;
	this.onstart.fire();
}
Timer.prototype.intervalFunction = function(){
	this.calls ++;
	this.timeElapsed += this.intervalValue;
	this.events.each(function(ev, index){
		if(this.calls % ev.freq == 0){
			var ret = ev.func.apply(ev.oThis, ev.args);
			if(typeof ret != 'undefined' && ret !== false){
				this.listeners.each(function(lnr, index){
					if(lnr.name == ev.name){
						lnr.func.apply(lnr.oThis, [ret]);
					}
				})
			}
		}
	}.bind(this))
}
Timer.prototype.registerEvent = function(obj){
	if(!obj.freq){
		obj.freq = 1;
	}
	this.events.push(obj);
}
Timer.prototype.removeEvent = function(name){
	this.events.each(function(ev, ind){
		if(ev.name == name){
			this.events.remove(ind);
			throw $break;
		}
	});
	this.listeners.each(function(lnr, ind){
		if(lnr.name == name){
			this.listeners.remove(ind);
		}
	})
}
Timer.prototype.registerEventListener = function(obj){
	this.listeners.push(obj);
}
Timer.prototype.clear = function(){
	clearInterval(this.interval);
	this.isTicking = false;
	this.onstop.fire();
}
Timer.prototype.stop = Timer.prototype.clear; 
Timer.prototype.toggle = function(){
	if(this.isTicking){
		this.clear();
	}else{
		this.start();
	}
}
Timer.prototype.restart = function(){
	this.clear();
	this.start();
}
Timer.prototype.toString = __toString;
Timer.prototype.__name = "Timer";

Timer.detectTimer = function(oTimer){
	if(!oTimer){
		var t = new Timer(50);
		t.start();
		return t;
	}else if(oTimer instanceof Number){
		return new Timer(oTimer)
	}else if(oTimer instanceof Timer){
		oTimer._MUTUAL = true;
		return oTimer;
	}
}
Timer._instances = [];
Timer._TO_INSTANCES = true;
Timer.__loaded = true;

Array.Timer = function(arr, timer, frequency){
	this.arr = arr;
	this.timer = Timer.detectTimer(timer);
	if(this.timer._MUTUAL){
		Array.Timer.handleMutualTimer(this.timer, this, frequency);
	}
	this.index = -1;
	this.g_index = 0;
	this.ondo = new DOMEvent(this);
	this.onstart = new DOMEvent(this);
	this.onstop = new DOMEvent(this);
	this.IS_WORKING = false;
	this.DIRECTION = true;
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Array.Timer.prototype.each = function(iterator, DIR){
	this.DIRECTION = typeof DIR != "undefined" ? DIR : true;
	this.iterator = iterator;
	this.start();
}
Array.Timer.prototype._do = function(){
	if(this.index == this.arr.length || this.index < 0){
		this.stop();
		return true;
	}
	this.g_index ++;
	var item = this.arr[this.index];
	this.current_result = this.iterator(item, this.index);
	if(typeof this.current_result != "undefined"){
		this.arr[this.index] = this.current_result;
	}
	this.ondo.fire(item, this.index);

}
Array.Timer.prototype.next = function(){
	this.index++;
	this._do();
}
Array.Timer.prototype.previous = function(){
	this.index --;
	this._do();
}
Array.Timer.prototype.start = function(){
	this.IS_WORKING = true;
	if(!this.timer._MUTUAL){
		this.timer.start();
	}
	this.onstart.fire();
}
Array.Timer.prototype.stop = function(){
	if(this.IS_WORKING){
		this.IS_WORKING = false;
		if(!this.timer._MUTUAL){
			this.timer.clear();
		}
		this.onstop.fire();
	}
}
Array.Timer.prototype.ch_dir = function(){
	this.DIRECTION = !this.DIRECTION;
}
Array.Timer.prototype.to_start = function(){
	this.index = -1;
}
Array.Timer.prototype.to_end = function(){
	this.index = this.arr.length - 1;
}
Array.Timer.prototype.pause = function(){
	this.IS_WORKING = false;
	if(!this.timer._MUTUAL){
		this.timer.clear();
	}	
}
Array.Timer.prototype.resume = function(){
	this.IS_WORKING = true;
	if(!this.timer._MUTUAL){
		this.timer.start();
	}
}
Array.Timer._instances = [];
Array.Timer._TO_INSTANCES = true;
Array.Timer.__loaded = true;
Array.Timer.prototype.__name = "Array.Timer";
Array.Timer.prototype.toString = __toString;
Array.Timer.handleMutualTimer = function(oTimer, oAT, frequency){
	if(oTimer.arraytimers){
		oTimer.arraytimers.push(oAT);
	}else{
		oTimer.registerEvent({
			name: "Array.Timer",
			func: function(){
				this.arraytimers.each(function(at){
					if(at.IS_WORKING){
						if(at.DIRECTION){
							at.next();
						}else{
							at.previous();
						}
					}
				})
			},
			oThis: oTimer,
			args: [],
			freq: frequency
		});
		oTimer.arraytimers = [];
		oTimer.arraytimers.push(oAT);
	}
}



Timer.__loaded = true;

var Nums = {};//Namespace for function working with numbers
Nums.SaveFloatPoint = function(){
	this.errVal = 0;
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
};
Nums.SaveFloatPoint.prototype.add = function(value){
	if(typeof value == "undefined"){
		this.errVal = this.tested;
		return false;
	}
	var err = (Math.abs(value) - Math.floor(Math.abs(value))) * value.signOf();
	var val = Math.floor(Math.abs(value)) * value.signOf();
	this.errVal += err;
	if(Math.abs(this.errVal) >= 1){
		val += value.signOf();
		this.errVal -= value.signOf();
	}
	return val;
};
Nums.SaveFloatPoint.prototype.test = function(value){
	this.saved = this.errVal;
	var val = this.add(value);
	this.tested = this.errVal;
	this.errVal = this.saved;
	return val;
};
Nums.SaveFloatPoint.prototype.refresh = function(){
	this.errVal = 0;
};
Nums.SaveFloatPoint._instances = [];
Nums.SaveFloatPoint._TO_INSTANCES = true;

Nums.Slide = function(from, to, step_num){
	var value = 0;
	var arr = [from + value];
	var len = to - from;
	var step = len / step_num;
	var saveFloat = new this.SaveFloatPoint();
	while(Math.abs(value) < Math.abs(len)){
		value += saveFloat.add(step);
		arr.push(from + value);
	}
	if(arr.length > step_num + 1){
		arr.pop();
		arr[arr.length - 1] = to;
	}
	return arr;
};
Nums.__hex_nums = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
Nums.Hex2Dec = function(hex){
	var num = 0;
	var splitted = hex.split('').invert();
	splitted.each(function(n, index){
		num += this.__hex_nums.indexOf(n) * (16).power(index);
	}.bind(this));
	return Number(num);
};
Nums.Dec2Hex = function(dec, len){
	var length = len || 1;
	var h_str = "";
	if(!dec){
		h_str = "0";
	}else{
		var num = dec;
		var ind;
		while(num){
			ind = num % 16;
			num = Math.floor(num / 16);
			var chr = Nums.__hex_nums[ind];
			h_str += chr;
		}
	}
	h_str = h_str.invert();
	while(h_str.length < length){
		h_str = "0" + h_str;
	}
	return h_str;
};
Nums.Dec2Bin = function(dec){
	if(!dec){
		return "0";
	}
	var d_str = "";
	var num = dec;
	var ind;
	while(num){
		ind = num % 2;
		num = Math.floor(num / 2);
		d_str += ind;
	}
	return d_str.invert();
};
Nums.toString = function(){
	var str = " object Nums: ";
	for(var i in this){
		if(i != "toString"){
			str += "\n";
			str += typeof this[i] + " " + i + "  :: ";
		}
	}
	return str;
};
Nums.Positive = function(val){
	this.val = 0;
	this.onzero = new DOMEvent();
	this.add(val);
};
Nums.Positive.prototype.add = function(val){
	this.val = Nums.Positive._check(this.val + val);
	if(this.val <= 0){
		this.onzero.fire();
	}
	return this.val;
};
Nums.Positive.prototype.set = function(val){
	this.val = Nums.Positive._check(val);
};
Nums.Positive.prototype.toString = function(){
	return this.val;
};
Nums.Positive._check = function(val){
	if(!val){
		return 0;
	}
	return val >= 0 ? val : 0;
};
Nums.rand = function(from, to){
	var range = to - from;
	return Math.floor(Math.random() * range) + from;
};
Nums.__loaded = true;


function moveable(elem, relative, IDLE, allowed_x, allowed_y){
	this.elem = elem;
	this.type = relative ? 'relative' : 'absolute';
	this._events = [
		{name: "move", func_name: "_moveBy"}	
	];
	this.onaftermove = new DOMEvent(this);
	this.STOP_X = false;
	this.STOP_Y = false;
	this.STOP = false;
	this.movedX = 0;
	this.movedY = 0;
	this.moveX = 0;
	this.moveY = 0;
	this.saveFloatX = new Nums.SaveFloatPoint();
	this.saveFloatY = new Nums.SaveFloatPoint();
	this.limits = {};
	this.PREVENT_DOUBLE_FIRE = true;
	this.directions = {
		X: true,
		Y: true
	};
	this.allowed = {
		X: (allowed_x || true),
		Y: (allowed_y || true)
	};
	this._IDLE = IDLE || false;
	this.init();
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
moveable.prototype.init = function(){
	this.elem.style.position = this.type;
	var coords = Style.getCoords(this.elem);
	this.left = coords.left; 
	this.top = coords.top;
	this.startX = this.left;
	this.startY = this.top;
	this._left = this.left;
	this._top = this._top;
	this.initEvents();
};
moveable.prototype.initEvents = _initEvents;
moveable.prototype.move = function(){
	if(!this._IDLE){
		this.elem.style.left = this.left + 'px';
		this.elem.style.top = this.top + 'px';
	}
	this.onaftermove.fire();
};
moveable.prototype.moveTo = function(x, y){
	this.moveBy(x - this.left, y - this.top);
};
moveable.prototype.moveBy = function(x, y){
	this.attemptedX = x;
	this.attemptedY = y;
	this.moveX = this.saveFloatX.test(x);
	this.moveY = this.saveFloatY.test(y);
	this._moveBy();
};
moveable.prototype._moveBy = function(){
	this.saveFloatX.add();
	this.saveFloatY.add();
	this.movedX += this.moveX;
	this.movedY += this.moveY;
	this.distanceX += Math.abs(this.moveX);
	this.distanceY += Math.abs(this.moveY);
	this.check_directions();
	this.left += this.moveX;
	this.top += this.moveY;
	if(!this.STOP){
		this.move();
	}else{
		this.STOP = false;
	}
};

moveable.prototype.check_directions = function(){
	this.directions.X = !this.moveX ? this.directions.X : (this.moveX > 0);
	this.directions.Y = !this.moveY ? this.directions.Y : (this.moveY > 0);
};
moveable.prototype.correctLimit = function(type, move){
	var lim = this.limits[type];
	if(!lim){
		return false;
	}
	var step = this["move" + type];
	var delta = move - step;
	lim.value -= delta;
};
moveable.prototype.setLimits = function(type, value, startValue){
	type = type.toUpperCase();
	if(this.limits[type]){
		return;
	}
	var PRESETS = moveable.LIMITS[type];
	this.limits[type] = new Limit(0, value);
	if(startValue){
		this.limits[type].value = startValue;
	}
	this.limits[type]._parent = this;
	this.limits[type].type = type;
	this.limits[type].MINUS_REACHED = false;
	this.limits[type].PLUS_REACHED = false;
	this.limits[type]._REACHED = false;
	this.limits[type].onmore.register(
		'limit-more',
		function(){
			var mov = this._parent;
			mov['move' + this.type] = this.MORE_VALUE;
			this._REACHED = true;
		}.bind(this.limits[type])
	);
	this.limits[type].onless.register(
		'limit-less',
		function(){
			var mov = this._parent;
			mov['move' + this.type] = this.LESS_VALUE;
			this._REACHED = true;
		}.bind(this.limits[type])
	);
	this[PRESETS.onmore] = DOMEvent.cloneEvent(this.limits[type].onmore, this);
	this[PRESETS.onless] = DOMEvent.cloneEvent(this.limits[type].onless, this);
	this[PRESETS.onmoreout] = DOMEvent.cloneEvent(this.limits[type].onmoreout, this);
	this[PRESETS.onlessout] = DOMEvent.cloneEvent(this.limits[type].onlessout, this);
	this.onmove.register(
		'limit' + type, 
		function(){
			var mov = this._parent;
			this.change(mov['move' + this.type]);
		}.bind(this.limits[type]), null, 0
	);
};	
moveable.prototype.setMoveSpace = function(X, Y, sX, sY){
	if(!this.moveSpace){
		this.moveSpace = {};
		this.onmovespacereach = new E_Connection(this);
		this.onmovespaceout = new E_Connection(this);
	}
	if(X || X === 0){
		this.moveSpace.X = X;
		this.setLimits('X', X, sX || 0);
		this.onmovespacereach.add(this.onleft, ["left", "X"]);
		this.onmovespacereach.add(this.onright, ["right", "X"]);
		this.onmovespaceout.add(this.onleftout, ["left", "X"]);
		this.onmovespaceout.add(this.onrightout, ["right", "X"]);
	}
	if(Y || Y === 0){
		this.moveSpace.Y = Y;
		this.setLimits('Y', Y, sY || 0);
		this.onmovespacereach.add(this.ontop, ["top", "Y"]);
		this.onmovespacereach.add(this.onbottom, ["bottom", "Y"]);
		this.onmovespaceout.add(this.ontopout, ["top", "Y"]);
		this.onmovespaceout.add(this.onbottomout, ["bottom", "Y"]);
	}
	return this.moveSpace;
};
moveable.prototype.resetMoveSpace = function(X, Y, sX, sY){
	if(this.limits.X){
		this.limits.X.to = X;
		this.limits.X.value = sX;
		this.moveSpace.X = X;
	}
	if(this.limits.Y){
		this.limits.Y.to = Y;
		this.limits.Y.value = sY;
		this.moveSpace.Y = Y;
	}
};
moveable.prototype.reflect = function(lim){
	if(lim.TO_REACHED){
		this['move' + lim.type] = this['move' + lim.type] - lim.exceeded;
		lim.value -= lim.exceeded;
	}else if(lim.FROM_REACHED){
		this['move' + lim.type] = this['move' + lim.type] - lim.preceeded;
		lim.value -= lim.preceeded;
	}
};
moveable.prototype.refresh = function(){
	var coords = Style.getCoords(this.elem);
	this.left = coords.left; 
	this.top = coords.top;
	this.startX = this.left;
	this.startY = this.top;
	this._left = this.left;
	this._top = this._top;
};
moveable.prototype.__name = "moveable";
moveable.prototype.toString = __toString;

moveable.LIMITS = {
	X: {
		onless: 'onleft',
		onmore: 'onright',
		onmoreout: 'onrightout',
		onlessout: 'onleftout',
		less: 'left',
		more: 'right'
	},
	Y: {
		onless: 'ontop',
		onmore: 'onbottom',
		onlessout: 'ontopout',
		onmoreout: 'onbottomout',
		less: 'top',
		more: 'bottom'
	}
};
moveable.detectMoveable = function(oMoveable){	 
	if(!oMoveable){
		return false;
	}
	if(oMoveable instanceof moveable){
		oMoveable._MUTUAL = true;
		return oMoveable;
	}else{
		return new moveable(oMoveable, false)
	}
};
moveable._TO_INSTANCES = true;
moveable._instances = [];
moveable.__loaded = true;

function Movement(oMov, timer){
	this.moveable = moveable.detectMoveable(oMov);
	this.moveable.movement = this;
	this.stepX = 0;
	this.stepY = 0;
	this.timer = Timer.detectTimer(timer);
	this.distance = false;
	this.moveSpace = false;
	this.STOP_ON_FIRST = true;
	this.direction = "";
	this._events = [
		{name: "start", func_name: "start"},	
		{name: "stop", func_name: "stop"},
		{name: "movetostart", func_name: "_moveTo"}
	];
	this.refreshCount = 0;
	this.IS_MOVING = false;
	this.onreach = new DOMEvent();
	this.onreach.register(
		Movement.defaultOnReach.name,
		Movement.defaultOnReach.func.bind(this)
	);
	this.init();
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Movement.prototype.initEvents = _initEvents;
Movement.prototype.init = function(){
	this.initEvents();
	this.onmove = DOMEvent.cloneEvent(this.moveable.onmove, this);
	if(this.timer._MUTUAL){
		if(this.timer.registerMovement){
			this.timer.registerMovement(this);
		}else{	
			Movement.handleMutualTimer(this.timer);
			this.timer.registerMovement(this);
		}
	}else{
		this.timer.registerEvent(
		{
			name: "Movement",
			func: function(objMoveable){
				objMoveable.moveBy(this.stepX, this.stepY);
			},
			oThis: this,
			args: [this.moveable]
		}
		);
	}
};
Movement.prototype.start = function(){
	this.IS_MOVING = true;
	if(!this.timer._MUTUAL){
		this.timer.start();
	}
};
Movement.prototype.stop = function(){
	this.IS_MOVING = false;
	if(!this.timer._MUTUAL){
		this.timer.clear();
	}
};
Movement.prototype.toggle = function(){
	if(this.IS_MOVING){
		this.stop();
	}else{
		this.start();
	}
};
Movement.prototype.setSteps = function(x, y){
	this.stepX = x ? x : 0;
	this.stepY = y ? y : 0;
	var d1, d2;
	with(Movement._directions){
		d1 = x >= 0 ? east.dir : west.dir;
		d2 = y >= 0 ? south.dir : north.dir;
	}
	this.direction = d1 + "-" + d2;
};
Movement.prototype.setLimits = function(type, value, startValue){
	this.moveable.setLimits(type, value, startValue);
	var PRESETS = moveable.LIMITS[type];
	this[PRESETS.onless] = DOMEvent.cloneEvent(this.moveable[PRESETS.onless], this);
	this[PRESETS.onmore] = DOMEvent.cloneEvent(this.moveable[PRESETS.onmore], this);
};
Movement.prototype.unsetLimits = function(type){
	this.moveable.unsetLimits(type);
};
Movement.prototype.setMoveSpace = function(X, Y, sX, sY){
	this.moveSpace = this.moveable.setMoveSpace(X, Y, sX, sY);
	if(!this.onmovespacereach){
		this.onmovespacereach = DOMEvent.cloneEvent(this.moveable.onmovespacereach, this);
	}
};
Movement.prototype.moveTo = function(x, y, speed){
	speed = speed ? speed : 3;
	var curLeft = this.moveable.left;
	var curTop = this.moveable.top;
	var nextLeft = x;
	var nextTop = y;
	var distX = nextLeft - curLeft;
	var distY = nextTop - curTop;
	var biggerDist = Math.abs(distX) > Math.abs(distY) ? distX : distY;
	var numOfSteps = Math.abs(Math.round(biggerDist / speed));
	if(numOfSteps == 0){
		return false;
	}
	var stepX = distX / numOfSteps;
	var stepY = distY / numOfSteps;
	this.mt_stepCount = 0;
	this.mt_numOfSteps = numOfSteps;
	this.distY = distY;
	this.distX = distX;
	this.moveToX = nextLeft;
	this.moveToY = nextTop;
	this.setSteps(stepX, stepY);
	this.X_REACHED = false;
	this.Y_REACHED = false;
	this.moveable.onmove._break = this.stopMoveTo.bind(this);
	this._moveTo();

};
Movement.prototype._moveTo = function(){
	this.moveable.movedToX = 0;
	this.moveable.movedToY = 0;
	this.moveable.onmove.remove('move-to');
	this.moveable.onmove.register(
		'move-to',
		function(oM){
			if(Math.abs(this.movedToX + this.moveX ) >= Math.abs(oM.distX)){
				var mX = this.moveX;
				this.moveX = Math.floor((Math.abs(oM.distX) - Math.abs(this.movedToX))) * this.moveX.signOf();
				oM.X_REACHED = true;
				this.correctLimit("X", mX);
			}
			if(Math.abs(this.movedToY + this.moveY ) >= Math.abs(oM.distY)){
				var mY = this.moveY;
				this.moveY = Math.floor((Math.abs(oM.distY) - Math.abs(this.movedToY))) * this.moveY.signOf();
				oM.Y_REACHED = true;
				this.correctLimit("Y", mY);
			}
			this.movedToX += this.moveX;
			this.movedToY += this.moveY;
			oM.mt_stepCount++;
			if(oM.X_REACHED && oM.Y_REACHED){
				this.onaftermove.register(
					'move-to-stop',
					function(){
						this.onreach.fire();
					}.bind(oM),
					1
				);
			}
		}.bind(this.moveable, this)
	);
	if(!this.IS_MOVING){
		this.start();
	}
};
Movement.prototype.stopMoveTo = function(){
	this.moveable.onmove.remove('move-to');
	this.stop();
};
Movement.prototype.moveDistance = function(distance, direction, numOfSteps){
	this.distanceMoved = 0;
	this.Distance = distance;
	this.DistanceStep = this.Distance / numOfSteps;
	this.stepType = (direction == "left" || direction == "right" ) ? "X" : "Y";
	if(direction == 'left'){
		this.setSteps(-this.DistanceStep, 0);
	}else if(direction == 'right'){
		this.setSteps(this.DistanceStep, 0);
	}else if(direction == 'top'){
		this.setSteps(0, -this.DistanceStep);
	}else if(direction == 'bottom'){
		this.setSteps(0, this.DistanceStep);
	}
	this.onmove.register("distance-check", function(oM){
		var step_sign = oM["move" + this.stepType].signOf();
		var step = Math.abs(oM["move" + this.stepType]);
		if(this.distanceMoved + step >= this.Distance){
			var new_step = this.Distance - this.distanceMoved;
//			toConsole(new_step);
			oM["move" + this.stepType] = new_step * step_sign;
			oM.onaftermove.register("stop", function(){
				this.stop();
				this.onmove.remove("distance-check");
			}.bind(this), 1);
			step = new_step;
		}
		this.distanceMoved += step;

	}.bind(this, this.moveable));
	this.start();
};
Movement.prototype.__name = "Movement";
Movement.prototype.toString = __toString;
Movement.defaultOnReach = {
	name: 'onreach',
	func: function(){
		this.stopMoveTo();
	}
};
Movement.mutualTimer = null;
Movement.handleMutualTimer = function(oTimer){
	oTimer.movements = [];
	oTimer.registerMovement = function(objMovement){
		this.movements.push(objMovement)
	};
	oTimer.registerEvent(
		{
			name: "Movement",
			func: function(){
				this.movements.each(function(mov){
					if(mov.IS_MOVING){
						mov.moveable.moveBy(mov.stepX, mov.stepY);
					}
				});
			},
			oThis: oTimer,
			args: []
		}
	);	
};
Movement._directions = {
	west: {geo: "W", dir: "left", num: 4},
	north: {geo: "N", dir: "top", num: 1},
	east: {geo: "E", dir: "right", num: 2},
	south: {geo: "S", dir: "bottom", num: 2}
};
Movement._TO_INSTANCES = true;
Movement._instances = [];

function MMO(){
	this.currentLeft = 0;
	this.currentTop = 0;
	this.deltaX = 0;
	this.deltaY = 0;
	this.onchange = new DOMEvent();
}
MMO.prototype.start = function(e){
	this.currentLeft = e.clientX;
	this.currentTop = e.clientY;
	this.offsetX = e.offsetX || e.layerX;
	this.offsetY = e.offsetY || e.layerY;
}
MMO.prototype.change = function(e){
	var ev = window.event || e;
	this.deltaX = ev.clientX - this.currentLeft;
	this.deltaY = ev.clientY - this.currentTop;
	this.currentLeft = ev.clientX;
	this.currentTop = ev.clientY;
	this.onchange.fire(this.deltaX, this.deltaY);

}
function DragDrop(oMov, handles, IDLE){
	this.moveable = moveable.detectMoveable(oMov);
	this.moveable._IDLE = IDLE || false;
	this.mmo = new MMO();
	this.mmo.onchange.register("move", function(x, y){
		this.moveable.moveBy(x, y);
	}.bind(this))
	this.elem = this.moveable.elem;
	this.handles = DragDrop.detectHandles(handles, this.elem);
	this.currentMouseLeft = null;
	this.currentMouseTop = null;
	this.ondragstart = new DOMEvent(this);
	this.ondrag = DOMEvent.cloneEvent(this.moveable.onmove, this);
	this.ondrop = new DOMEvent(this);
	this._events = [
		{name: "dragstart", func_name: "_start"}	
	];
	this.mouse_x = 0;
	this.mouse_y = 0;
	this.active_handle = null;
	this.IS_DRAGGING = false;
	this.init();
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
DragDrop.prototype.init = function(){
	this.initEvents();
	this.init_handles();
}
DragDrop.prototype.initEvents = _initEvents;
DragDrop.prototype.init_handles = function(){
	this.handles.each(function(handle){
		handle.onselectstart = function(){return false;}
		handle.onmousedown = function(e, oHandle){
			var _handle = oHandle || e; //ev in case of IE
			var ev = window.event || e;
			var x = ev.offsetX || ev.layerX;
			var y = ev.offsetY || ev.layerY;
			this.active_handle = _handle;
			this.mouse_x = x;
			this.mouse_y = y;
			this.start(ev);
		}.bind(this, handle);
	}.bind(this));
}
DragDrop.prototype.start = function(e){
	var ev = e || window.event;
	this.mmo.start(ev);
	this.curr_pageXOffset = window.pageXOffset;
	this.curr_pageYOffset = window.pageYOffset;
	this._start();
	return false;
}
DragDrop.prototype._start = function(){
	this.IS_DRAGGING = true;
	document.onmousemove = this.mmo.change.bind(this.mmo);
	window.onscroll = this.scroll.bind(this);
	DragDrop.mouseup = this.drop.bind(this);
	AttachEvent(document, "mouseup", DragDrop.mouseup);
	document.onselectstart = document.onmousedown = function(){
		return false;
	}
}
DragDrop.prototype.drop = function(e){
	this.IS_DRAGGING = false;
	document.onmousemove = null;
	window.onscroll = null;
	DetachEvent(document, "mouseup", DragDrop.mouseup);
	document.onselectstart = document.onmousedown = null;
	this.ondrop.fire();
}
/*
DragDrop.prototype.move = function(e){
	var ev = window.event || e;
	var mLeft = ev.clientX;
	var mTop = ev.clientY;
	this.moveable.moveBy(mLeft - this.currentMouseLeft, mTop - this.currentMouseTop);
	this.currentMouseLeft = mLeft;
	this.currentMouseTop = mTop;
}
*/
DragDrop.prototype.scroll = function(e){
	var deltaX = window.pageXOffset - this.curr_pageXOffset;
	var deltaY = window.pageYOffset - this.curr_pageYOffset;
	this.moveable.moveBy(deltaX, deltaY);
	this.curr_pageXOffset = window.pageXOffset;
	this.curr_pageYOffset = window.pageYOffset;
}
DragDrop.prototype.__name = "DragDrop";
DragDrop.prototype.toString = __toString;

DragDrop.detectHandles = function(handles, el){
	var ret;
	if(typeof handles == "string"){
		ret = $C(handles, el) || [el];
	}else if(handles instanceof Array){
		ret = handles;
	}else if(typeof handles == "object" && handles.nodeName){
		ret = [handles];
	}else if(typeof handles == "undefined" || typeof handles == "boolean"){
		ret = [el];
	}
	return ret;
}
DragDrop.mouseup = null;
DragDrop._TO_INSTANCES = true;
DragDrop._instances = [];
DragDrop.__loaded = true;

Array.prototype.bool = function(bool){
	return this[Number(bool)];
}
function Scroll(holder, content, bars, timer, settings){
	this.holder = holder;
	this.content = content;
	this.timer = Timer.detectTimer(timer);
	this.mov = new moveable(this.content);
	this.onscroll = DOMEvent.cloneEvent(this.mov.onmove);
	this._bars = bars;
	this.settings = Scroll.defaultSettings;
	if(settings){
		for(var i in settings){
			this.settings[i] = settings[i];
		}
	}
	if(this.settings._INIT){
		this.init();
	}
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Scroll.prototype.init = function(){
	this.getHolderProps();
	this.getContentProps();
	this.check();
}
Scroll.prototype.getHolderProps = function(){
	this.holder_props = Style.getDimensions(this.holder);
}
Scroll.prototype.getContentProps = function(){
	this.content_props = Style.getDimensions(this.content);
}
Scroll.prototype.check = function(dX, dY){
	var deltaX = dX || (this.content_props.width - this.holder_props.width);
	var deltaY = dY || (this.content_props.height - this.holder_props.height);
	if(this.barX){
		this.barX.refresh(deltaX);
	}else{
		if(this._bars.X){
			this.barX = new Scroll.Scrollbar("X", this, deltaX);
		}
	}
	if(this.barY){
		this.barY.refresh(deltaY);	
	}else{
		if(this._bars.Y){
			this.barY = new Scroll.Scrollbar("Y", this, deltaY);	
		}
	}
	this.deltaY = deltaY;
	this.deltaX = deltaX;
}

Scroll.prototype.refresh = function(){
	this.getHolderProps();
	this.getContentProps();
	this.check();
}
Scroll.prototype.moveContentTo = function(x, y){
	if(this.barX){
		this.barX.moveContentTo(x);
	}
	if(this.barY){
		this.barY.moveContentTo(y);
	}
}
Scroll._instances = [];
Scroll._TO_INSTANCES = true;
Scroll.Scrollbar = function(type, parentObject, delta){
	this.parent = parentObject;
	this.type = type.toUpperCase();
	this.op_type = Scroll.types[Number(!Scroll.types.indexOf(this.type))];
	this.delta = delta;
	//this.settings = this.parent.settings[this.type];
	this.PROPS = Scroll.bars[this.type];
	this.HIDDEN = false;
	this.THUMB_SET = false;
	this.STATE = 0;//NOT INITIALIZED
	this.init();
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Scroll.Scrollbar.prototype.init = function(partly){
	if(!partly){
		var _bar = this.parent._bars[this.type];
		for(var i in _bar){
			this[i] = _bar[i];
		}
		if(this.delta <= 0){
			this.hide();
			this.STATE = 1;//PARTLY INITIALIZED
			return false;
		}else{
			this.HIDDEN = 1;//override 'if' inside the function 'show'
			this.show(1);
		}
	}
	this.count();
	this.initMovs();
	this.get_speed();
	this.init_buttons();
	if(this.parent.settings._ARROWS){
		this.init_arrows();
	}
	if(this.type == "Y"){
		if(this.parent.settings._MOUSEWHEEL){
			this.initWheel();
		}
		if(this.parent.settings._SELECTION){
			this.initSelection();
		}
	}
	this.STATE = 2;//INITIALIZED
	
}
Scroll.Scrollbar.prototype.count = function(){
	var prop = this.PROPS.mainDim;
	var pad = parseInt(Style.getElementStyle(this.track, this.PROPS.secDim));
	this.track_len = parseInt(Style.getElementStyle(this.track, prop));
	this.thumb_len = parseInt(Style.getElementStyle(this.thumb, prop));
	if(!this.thumb_len || this.THUMB_SET){
		this.set_thumb(prop)
	}
	this.th_delta = this.track_len - this.thumb_len;
	this.mov_coeff = this.delta / this.th_delta;
	if(this.th_mov){
		this.th_mov.limits[this.type].to = this.th_delta;
//		this.dd_mouse.to = this.thumb_len;
	}
}
Scroll.Scrollbar.prototype.initMovs = function(){
	this.th_mov = new moveable(this.thumb);
	this.th_mov.setLimits(this.type, this.th_delta, 0);
	this.th_mov.setLimits(this.op_type, 0);
	
	this.th_mov.onmove.register("mov", function(oM){
		var args = [0, -oM["move" + this.type] * this.mov_coeff];
		if(this.type == "X"){
			args = args.invert();
		}
		this.parent.mov.moveBy.apply(this.parent.mov, args);
	}.bind(this, this.th_mov));
	this.th_movement = new Movement(this.th_mov, this.parent.timer);
	this.dd = new DragDrop(this.th_mov);
//	this.set_dd_mouse();
}
Scroll.Scrollbar.prototype.set_thumb = function(prop){
	var c_length = this.parent.content_props[prop];
	var h_length = this.parent.holder_props[prop];
	var t_len = Math.floor(this.track_len / (c_length / h_length));
	this.thumb_len = Math.max(t_len, this.parent.settings.thumb_min_len);
	this.thumb.style[prop] = this.thumb_len + "px";
	this.THUMB_SET = true;
}
Scroll.Scrollbar.prototype.get_speed = function(){
	this.step = this.parent.settings.speed / this.mov_coeff;
}

Scroll.Scrollbar.prototype.set_dd_mouse = function(){
	this.dd_mouse = new Limit(0, this.thumb_len);

	this.dd.ondragstart.register("catch mouse", function(){
		this.dd_mouse.value = this.dd["mouse_" + this.type.toLowerCase()];
		this.th_mov[this.PROPS.onmore].register("change mouse more", function(lim){
			this.dd_mouse.change(lim.exceeded);
		}.bind(this, this.th_mov.limits[this.type]));
		this.th_mov[this.PROPS.onless].register("change mouse less", function(lim){
			this.dd_mouse.change(lim.preceeded);
		}.bind(this, this.th_mov.limits[this.type]));
	}.bind(this));

	this.dd.ondrop.register("drop limits", function(){
		this.th_mov[this.PROPS.onmore].remove("change mouse more");
		this.th_mov[this.PROPS.onless].remove("change mouse less");
		this.th_mov.onmove.remove("accumulate");
	}.bind(this))

	this.dd_mouse.onmore.register("accumulate", function(){
		if(!this.accumulate){
			this.accumulate = new Limit(0, Infinity);
			this.accumulate.onless.register("drop all", function(){
				var m = this.accumulate.preceeded;
				this.accumulate = null;
				this.th_mov.onmove.remove("accumulate");
				if(this.type == "X"){
					this.th_mov.moveBy(m, 0);
				}else{
					this.th_mov.moveBy(0, m);					
				}
			}.bind(this))
			this.th_mov.onmove.register("accumulate", function(){
				this.accumulate.change(this.th_mov["move" + this.type]);
				this.th_mov["move" + this.type] = 0;
			}.bind(this), false, 0);
			this.accumulate.change(this.dd_mouse.exceeded);
		}
	}.bind(this));
	this.dd_mouse.onless.register("accumulate", function(){
		if(!this.accumulate){
			this.accumulate = new Limit(0, Infinity);
			this.accumulate.onless.register("drop all", function(){
				var m = -this.accumulate.preceeded;
				this.accumulate = null;
				this.th_mov.onmove.remove("accumulate");
				if(this.type == "X"){
					this.th_mov.moveBy(m, 0);
				}else{
					this.th_mov.moveBy(0, m);					
				}
			}.bind(this))
			this.th_mov.onmove.register("accumulate", function(){
				this.accumulate.change(-this.th_mov["move" + this.type]);
				this.th_mov["move" + this.type] = 0;
			}.bind(this), false, 0);
			this.accumulate.change(-this.dd_mouse.preceeded);
		}
	}.bind(this));
}
Scroll.Scrollbar.prototype.scroll_plus = function(){
	var M = this.th_movement;
	var args = [0, this.step];
	if(this.type == "X"){
		args = args.invert();
	}
	M.setSteps.apply(M, args);
	M.start();
}
Scroll.Scrollbar.prototype.scroll_minus = function(){
	var M = this.th_movement;
	var args = [0, -this.step];
	if(this.type == "X"){
		args = args.invert();
	}
	M.setSteps.apply(M, args);
	M.start();
}
Scroll.Scrollbar.prototype.stop_scroll = function(e){
	if(this.th_movement.IS_MOVING){
		this.th_movement.stop();
		stopPropagation(e || window.event);
		DetachEvent(document, "mouseup", this._mouseup_func);
	}
}
Scroll.Scrollbar.prototype.init_buttons = function(){
	this.bPlus.onmousedown = this.scroll_plus.bind(this);
	this.bMinus.onmousedown = this.scroll_minus.bind(this);
	this._mouseup_func = this.stop_scroll.bind(this);
	this.bPlus.onmouseup = this.bMinus.onmouseup = this._mouseup_func;
	this.bPlus.onmouseout = this.bMinus.onmouseout = function(){
		AttachEvent(document, "mouseup", this._mouseup_func);
	}.bind(this);
	this.bPlus.onmouseover = this.bMinus.onmouseover = function(){
		try{
			DetachEvent(document, "mouseup", this._mouseup_func);	
		}catch(e){}
	}
}
Scroll.Scrollbar.prototype.init_arrows = function(){
	this.start_arrow = Scroll.Scrollbar.start_arrow.bindAvoidingEvent(this, this.type);
	AttachEvent(_elem(this.parent.holder), "mouseover", this.start_arrow);
	this.stop_arrow = Scroll.Scrollbar.stop_arrow.bind(this);
	AttachEvent(_elem(this.parent.holder), "mouseout", this.stop_arrow);
} 
Scroll.Scrollbar.prototype.detach_arrows = function(){
	this.stop_arrow();
	DetachEvent(_elem(this.parent.holder), "mouseover", this.start_arrow);
}
Scroll.Scrollbar.prototype.attach_arrows = function(){
	AttachEvent(_elem(this.parent.holder), "mouseover", this.start_arrow);
}
Scroll.Scrollbar.prototype.initWheel = function(){
	this._start_wheel = function(){
		if(this.WHEEL_WORKS || this.NO_WHEEL){
			return false;
		}
		this.WHEEL_WORKS = true;
		Scroll.setMouseWheel(this);
	}.bind(this);
	AttachEvent(_elem(this.parent.holder), "mouseover", this._start_wheel);

	this._stop_wheel = function(e){
		if(!this.WHEEL_WORKS){
			return false;
		}
		if(e != "stop"){
			var ev = window.event || e;
			var target = ev.relatedTarget || ev.toElement;
			if(target == _elem(this.parent.holder) || _isChild(target, _elem(this.parent.holder))){
				return false;
			}
		}
		this.WHEEL_WORKS = false;
		window.onmousewheel = document.onmousewheel = null;
		if(window.addEventListener && !window.opera){
			window.removeEventListener('DOMMouseScroll', this.wheelFunc, false);
		}
	}.bind(this);
	AttachEvent(_elem(this.parent.holder), "mouseout", this._stop_wheel);
}
Scroll.Scrollbar.prototype.detach_wheel = function(){
	this._stop_wheel("stop");
	this.NO_WHEEL = true;
//	DetachEvent(_elem(this.parent.holder), "mouseover", this._start_wheel);
}
Scroll.Scrollbar.prototype.attach_wheel = function(){
//	AttachEvent(_elem(this.parent.holder), "mouseover", this._start_wheel);
	this.NO_WHEEL = false;
}
Scroll.Scrollbar.prototype.initSelection = function(){
	this.previousMouseY = 0;
	if(Style._browser == "IE"){
		this.parent.content.onselectstart = Scroll.Scrollbar.start_selection.bind(this);
	}else{
		this.parent.content.onmousedown = Scroll.Scrollbar.start_selection.bind(this);	
	}
}
Scroll.Scrollbar.start_arrow = function(type){
	if(this.ARROWS_WORK){
		return false;
	}
	this.ARROWS_WORK = true;
	this._key_down_function = Scroll.Scrollbar.arrows[this.type].bind(this);
	this._key_up_function = this.stop_scroll.bind(this);
	AttachEvent(document, "keydown", this._key_down_function);
	AttachEvent(document, "keyup", this._key_up_function);
}
Scroll.Scrollbar.stop_arrow = function(){
	if(!this.ARROWS_WORK){
		return false;
	}
	this.ARROWS_WORK = false;
	DetachEvent(document, "keydown", this._key_down_function);
	DetachEvent(document, "keyup", this._key_up_function);
}
Scroll.Scrollbar.arrows = {
	X: function(e){
		if(this.dd.IS_DRAGGING){
			return false;
		}
		switch(e.keyCode){
			case 39: //down
				this.scroll_plus();
				break;
			case 37: //up
				this.scroll_minus();
				break;
		}
	},
	Y: function(e){
		if(this.dd.IS_DRAGGING){
			return false;
		}
		switch(e.keyCode){
			case 40: //down
				this.scroll_plus();
				break;
			case 38: //up
				this.scroll_minus();
				break;
		}
	}
}
Scroll.Scrollbar.start_selection = function(e){
	var ev = e || window.event;
	this.previousMouseY = ev.clientY;
	document.onmousemove = function(e){
		var ev = e || window.event;
		var delta = this.previousMouseY - ev.clientY;
		this.previousMouseY = ev.clientY;
		this.th_mov.moveBy(0, -delta);
	}.bind(this);
	document.onmouseup = function(){
		document.onmousemove = null;
	}
}
Scroll.Scrollbar.stop_selection = function(){

}
Scroll.wheelFunc = function(e){
	if(this.dd.IS_DRAGGING){
		return false;
	}
	var ev = window.event || e;
	var delta = ev.wheelDelta ? ev.wheelDelta / 120 : -ev.detail / 3;
	this.th_mov.moveBy(0 ,-delta * 8);
	if(ev.preventDefault){
		ev.preventDefault();
	}
	ev.returnValue = false;
}
Scroll.setMouseWheel = function(obj){
	switch(Style._browser){
		case "Gecko":
			obj.wheelFunc = Scroll.wheelFunc.bind(obj);
	        window.addEventListener('DOMMouseScroll', obj.wheelFunc, false);		
			break;
		case "Opera": 
			window.onmousewheel = Scroll.wheelFunc.bind(obj);	
			break;
		case "IE": 
			document.onmousewheel = Scroll.wheelFunc.bind(obj);
			break;
	}
}
Scroll.Scrollbar.prototype.moveContentTo = function(value){
	var val = value / this.mov_coeff;
	if(this.type == "X"){
		this.th_mov.moveTo(val, 0);
	}else{
		this.th_mov.moveTo(0, val);
	}
}
Scroll.Scrollbar.prototype.refresh = function(delta){
	if(delta == this.delta){
		return false;
	}
	this.delta = delta;
	if(delta < 0){
		this.hide();
	}else if(this.delta > 0){
		if(this.STATE == 1){
			this.init(true);//continue initialization
		}
		this.contentPosition = -this.parent.mov[this.PROPS.mainPos];
		this.moveContentTo(0);
		this.show();
		this.count();
		this.get_speed();
		this.moveContentTo(this.contentPosition);
	}
}
Scroll.Scrollbar.prototype.hide = function(visibility){
	if(this.HIDDEN){
		return false;
	}
	var vis = visibility || false;
	var prop = Scroll._display_props.bool(vis);
	this.bar.style[prop] = Scroll.__hides.bool(vis);
	this.HIDDEN = true;
	if(this.STATE < 2){
		return false;
	}
	this.moveContentTo(0);
	if(this.type == "Y"){
		if(this.parent.settings._MOUSEWHEEL){
			this.detach_wheel();
		}
	}
	if(this.parent.settings._ARROWS){
		this.detach_arrows();
	}
}
Scroll.Scrollbar.prototype.show = function(NO_REINIT){
	if(!this.HIDDEN){
		return false;
	}
	var prop = Scroll._display_props[0];
	this.bar.style[prop] = Scroll.__shows[0];
	if(NO_REINIT){
		return true;
	}
	if(this.type == "Y"){
		if(this.parent.settings._MOUSEWHEEL){
			this.attach_wheel();
		}
	}
	if(this.parent.settings._ARROWS){
		this.attach_arrows();
	}
	this.HIDDEN = false;
}
Scroll.Scrollbar.prototype.toString = __toString;
Scroll.Scrollbar.prototype.__name = "Scrollbar";
Scroll.Scrollbar._instances = [];
Scroll.Scrollbar._TO_INSTANCES = true;
Scroll.prototype.toString = __toString;
Scroll.prototype.__name = "Scroll";
Scroll.bars = {
	X: {
		mainDim: "width",
		secDim: "height",
		mainPos: "left",
		secPos: "right",
		plusPos: "right",
		minusPos: "left",
		pad: "paddingRight",
		onmore: "onrightlimitreach",
		onless: "onleftlimitreach"
	},
	Y: {
		mainDim: "height",
		secDim: "width",
		mainPos: "top",
		secPos: "bottom",
		plusPos: "bottom",
		minusPos: "top",
		barPos: "right",
		pad: "paddingRight",
		onmore: "onbottomlimitreach",
		onless: "ontoplimitreach"
	}
}
Scroll.types = ["X", "Y"];
Scroll._display_props = ["display", "visibility"];
Scroll.__shows = ["block", "visible"];
Scroll.__hides = ["none", "hidden"];
Scroll.defaultSettings = {
	_INIT: true,
	_MOUSEWHEEL: true,
	_ARROWS: true,
	_SELECTION: false,
	speed: 5,
	thumb_min_len: 10,
	toString: function(){
		var str = "object Settins\t\n\t";
		for(var i in this){
			if(i != "toString"){
				str += i + " => " + this[i] + "\t\n\t";
			}
		}
		return str;
	}
}


function Opacity(elem, oTimer, step){
	this.elem = elem;
	this.timer = Timer.detectTimer(oTimer);
	this.currentProcess = "fade";
	this.onafterfade = new DOMEvent(this);
	this.onafterappear = new DOMEvent(this);
	this.onfadestart = new DOMEvent(this);
	this.onappearstart = new DOMEvent(this);
	this.onchange = new DOMEvent(this);
	this.saveFloat = new Nums.SaveFloatPoint();
	this.step = step || 5;
	this.IS_DOING = false;
	this.init();
	if(this.constructor._TO_INSTANCES){
		this.constructor._instances.push(this);
	}
}
Opacity.prototype.init = function(){
	this.initTimer();
	if(Style._browser == "IE"){
		this.elem.style.zoom  = 1;
	}
	this.currentOpacity = Opacity.getOpacity(this.elem);
	this.currentVisibility = Opacity.getVisibility(this.elem);
};
Opacity.prototype.initTimer = function(){
	if(this.timer._MUTUAL){
		if(this.timer.registerOpacity){
			this.timer.registerOpacity(this);
		}else{
			Opacity.handleMutualTimer(this.timer);
			this.timer.registerOpacity(this);
		}
	}else{
		this.timer.registerEvent({
			name: "changer",
			func: this.change,
			oThis: this,
			args: []
		});
	}
};
Opacity.prototype.setOpacity = function(value){
	if(typeof value == "undefined" || value > 100 || value < 0)
		return false;
	value = this.saveFloat.add(value);
	var styleValue = Opacity.styleStartText + (value / Opacity.styleCoeff) + Opacity.styleEndText;
	Style.setElementStyle(this.elem, Opacity.styleProperty, styleValue);
	this.currentOpacity = value;
};
Opacity.prototype.setVisible = function(){
	Style.setElementStyle(this.elem, "visibility", "visible");
	this.currentVisibility = "visible";
};
Opacity.prototype.setHidden = function(){
	Style.setElementStyle(this.elem, "visibility", "hidden");
	this.currentVisibility = "hidden";
};
Opacity.prototype.fade = function(value, sVal){
	this.toValue = value ? value  : 0;
	this.currentProcess = "fade";
	this.step = sVal ? -Math.abs(sVal) : -Math.abs(this.step);
	this.start();
};
Opacity.prototype.appear = function(value, sVal){
	this.toValue = value ? value : 100;
	this.currentProcess = "appear";
	this.step = sVal ? Math.abs(sVal) : Math.abs(this.step);
	this.start();
};
Opacity.prototype.change = function(){
	var stop = false;
	var nextVal = this.currentOpacity + this.step;
	if(this.currentProcess == "fade"){
		if(nextVal < this.toValue){
			nextVal = this.toValue;
			stop = true;
		}
	}else if(this.currentProcess == "appear"){
		if(nextVal > this.toValue){
			nextVal = this.toValue;
			stop = true;
		}
	}
	this.setOpacity(nextVal);
	this.onchange.fire();
	if(stop){
		this.stop();
		this["onafter" + this.currentProcess].fire();	
	}
};
Opacity.prototype.start = function(){
	this.IS_DOING = true;
	if(!this.timer._MUTUAL){
		this.timer.start();
	}
	this["on" + this.currentProcess + "start"].fire();
};
Opacity.prototype.stop = function(){
	this.IS_DOING = false;
	if(!this.timer._MUTUAL){
		this.timer.clear();
	}
};
Opacity.prototype.set = function(){
	if(Opacity.styleProperty == "filter"){
		var styleValue = Opacity.styleStartText + (this.currentOpacity / Opacity.styleCoeff) + Opacity.styleEndText;
		Style.setElementStyle(this.elem, Opacity.styleProperty, styleValue);
	}
};
Opacity.prototype.unset = function(){
	if(Opacity.styleProperty == "filter"){
		this.elem.style.filter = "none";
	}
};
Opacity.prototype.__name = "Opacity";
Opacity.prototype.toString = __toString;


Opacity.getOpacity = function(elem){
	var currentOpacity = Style.getElementStyle(elem, Opacity.styleProperty);
	if(currentOpacity == ''){
		currentOpacity = "100";
	}
	var re = new RegExp(" ", "ig");
	return Number(currentOpacity.replace(re, '').replace(Opacity.styleStartText, '').replace(Opacity.styleEndText, '')) * Opacity.styleCoeff;
};
Opacity.setDimensions = function(elem){
	with(Style){
		setElementStyle(elem, getDimensions(elem), null, true);
	}
};
Opacity.getVisibility = function(elem){
	return Style.getElementStyle(elem, 'visibility') == 'inherit' ? 'visible' : Style.getElementStyle(elem, 'visibility');
};
Opacity.NoGo = false;
Opacity.styleStartText = "";
Opacity.styleEndText = "";
Opacity.styleCoeff = 100;
Opacity.styleProperty = "opacity";
Opacity.slow = 3;
if(Style._browser == "IE"){
	Opacity.styleProperty = "filter";
	Opacity.styleCoeff = 1;
	Opacity.styleStartText = "alpha(opacity=";
	Opacity.styleEndText = ")";
	Opacity.slow = 1;
}else if(Style._browser == "Gecko" || Style._browser == "Opera"){
	//OK
}else{
	Opacity.NoGo = true;
}
Opacity.handleMutualTimer = function(oTimer){
	oTimer.opacities = [];
	oTimer.registerOpacity = function(op){
		this.opacities.push(op);
	};
	oTimer.registerEvent({
		name: "opacity",
		func: function(){
			this.opacities.each(function(op){
				if(op.IS_DOING){
					op.change();
				}
			})
		},
		oThis: oTimer,
		args: []
	});
};
Opacity._instances = [];
Opacity._TO_INSTANCES = true;
