

var _=function(root, query){
	if(!root) return undefined;
	if(JJ.type(root, "String")){
		var el;
		if(/^#?[a-z0-9_]+$/i.test(root)) el=document.getElementById(root.replace(/#/,"")); //root as id
		if(el) root=el;
		else{query=root; root=document;} //root as query
	}
	if(!query && root._extended) return root;
	var els=root;
	if(query) els=JJ.getElements.parse(query, root);
	
	if(!els) return ""; //if no element return empty string
	
	if(!JJ.type(els, "Array")) JJ.extend(els, JJ.element); //exend one element
	else JJ.foreach(els, function(){ JJ.extend(this, JJ.element)}); //exend elements group (array object)
	return els;
};

//-------------------------------------------- JJ ------------------------------------------------
var JJ={};

//Base JJ function

JJ.type=function(obj, _type){
	var t=typeof obj;
	if(!_type) return t;
	if(obj==undefined) return _type==undefined;
	_type=_type.toLowerCase();
	switch(_type){
		case "object":   return obj.constructor==Object;
		case "array":    return obj.constructor==Array; //t=="object" && obj.length; 
		case "number":   return t=="number" || !isNaN(obj);
		case "element":  return t=="object" && obj.nodeType==1;
		case "date":     return obj.constructor==Date;
		case "string":     return obj.constructor==String;
		case "boolean":     return obj.constructor==Boolean;
		case "function":     return t=="function";
		default: return t==_type; 
	}
};
JJ.foreach=function(obj, func){
	if(!JJ.type(obj, "Array")) return func.call(obj);
	for(var i=0, arr=[], l=obj.length; i<l; i++)
		arr.push(func.call(obj[i], i));
	return arr;
};
JJ.extend=function(obj, methods){
	var call=function(obj, name, args){
		if(!JJ.type(obj, "Array") || name=="repeat"){
			return methods[name].exec(obj, args[0], args[1], args[2], args[3]);
		}
		else{
			//execute functions and return elements
			var res=JJ.foreach(obj, function(){ return methods[name].exec(this, args[0], args[1], args[2], args[3])});
			if(res[0]){
				if(res[0]._extended) JJ.extend(res, methods); //re-extend root element
				
				//play elements group events (overload result with functions)
				if(JJ.type(res[0], "Function") && name=="event"){ 
					var _res=res; 
					res=function(){
						for(var i=0, l=_res.length; i<l; i++) 
							if(_res[i]) 
								_res[i].apply(obj[i], arguments); 
					};
				}
			}
			return res;
		}
	};
	var attach=function(obj, name){
		//attach property to element or to elements group
		obj[name]=function(){return call(this, name, arguments)};
	};
	
	if(obj._extended) return false;
	obj._extended=true;
	for(var i in methods) attach(obj, i);
	
	return obj;
};

//wait for loading needed function or from other file
JJ.wait=function(func){
	try{ func() }catch(e){ setTimeout(func,10) }
};

JJ.create=function(tag){
	return JJ.extend(document.createElement(tag), JJ.element);
};


/*
Find Elements in DOM
	"*"                   //any tags
	"h1"                  //all <h1>
	"p a"                 //all nesting childs A <p><b><a>
	"p>a"                 //all siblings A <p><a>
	"p>*"                 //all siblings
	"p a, div a"          //multiply selection
	"#id"                 //id="id"
	".classname"          //class="classname"
	"[attr]"              //has this attr
	"[!attr]"             //hasn't this attr
	"[attr=value]"        //attr=value
	"[attr!=value]"       //attr!=value
	":^" ":0"             //first child
	":$"                  //last child
	":4"                  //child in position 4 (from 0)
	"<"                   //parent node
	"<div.classname"      //search div parent node with className
	"<:1"                 //return second parent node
	"+a"                  //next sibling element
	"+a:2"                //next (nearest with position) sibling element
	"-.classname"         //previous sibling element
	"()"                  //groups...
	["p a"]               //return array of <a> (even if one element found)
*/
JJ.getElements={
	parse:function(query, root){
		var return_array_reqired=false;
		if(JJ.type(query, "array")){
			query=query[0];
			return_array_reqired=true;
		}
		query=query.replace(/((^)|([ ><+\-,]))(([#.:\[,])|($))/g, "$1*$4")+" "; //set * for any tag
		root=root || document;
		
		var sep=" ><+-,", //levels separations
			breakset=" ><+-,:[", // breakset for conditions
			cond={"#":  breakset, ".":  breakset, ":":  breakset, "[":  "]"}, //out of fit condition
			prop={"#":"id", ".":"className", ":":"pos", "[":"attr", "<":"parentNode", "+":"nextSibling", "-":"previousSibling"}, //operations

			i=-1, c, fit, match, root_arr=[root], multi_arr=[], len=query.length;
		while(c=query.charAt(++i)){
			if(fit){
				if(cond[fit].indexOf(c)!=-1){ //out from fit
					fit=null;
					if(c=="]") match.attr=this.attr2struct(match.attr); //parse attribute
					else i--;
					continue;
				}
				match[prop[fit]]+=c; //add filter chars if in fit
			}
			else{
				if(sep.indexOf(c)!=-1){//if find separator
					if(match){
						this.init_match(match);
						root_arr=this.walk(match, root_arr); //search previous match
					}
					if(c==","){ //set next matches set
						multi_arr=multi_arr.concat(root_arr);
						root_arr=[root];
						match=null; 
						continue;
					}
					if(i==len-1) break; //exit if this is last instruction
					match={tag:"", child:c!=" ", move_to:prop[c]}; //init match if first sep
					continue;
				}
				if(!match){ //init match if first tag
					match={tag:c, child:false};
					continue;
				}
				if(c in cond){ //find filter fit
					match[prop[fit=c]]=""; //init current filter & set current prop
					continue;
				}
				match.tag+=c;
			}
		}
		if(multi_arr.length) root_arr=multi_arr.concat(root_arr);
			////alert(MATCH_DEBUG+"\n"+(root_arr.length==1?root_arr[0]:root_arr));
		return root_arr.length==1 && !return_array_reqired?root_arr[0]:(root_arr[0]?root_arr:undefined); //element or array
	},
	walk:function(match, root_arr){
			////MATCH_DEBUG.push(match);
		var root_el, i=0, new_arr=[];
		while(root_el=root_arr[i++]){
			var el, j=0, match_arr=[];
			if(match.only_id){
				if(el=document.getElementById(match.id)) new_arr[new_arr.length]=el;
				continue;
			}
			if(match.move_to){
				if(el=this.move(match, root_el)) new_arr[new_arr.length]=el;
				continue;
			}
			var nodes=match.child?root_el.childNodes:root_el.getElementsByTagName(match.tag); //get elements
			//filter nodes
			while(el=nodes[j++]){
				if(match.single_tag || this.check_filters(match, el))
					match_arr[match_arr.length]=el;
			}
			//position filter 
			if(match.pos){
				if(el=this.pos(match, match_arr)) new_arr[new_arr.length]=el;
				continue;
			}
			new_arr=new_arr.concat(match_arr); //add all mathes to array
		}
		return new_arr;
	},
	init_match:function(match){
		match.tag=match.tag.toUpperCase();
		if(match.tag=="*" && match.id && !match.className && !match.attr) match.only_id=1;
		if(!match.id && !match.className && !match.attr) match.no_prop=1;
		if(!match.child && match.no_prop) match.single_tag=1;
	},
	check_filters:function(match, el){
		if(match.child && (el.nodeType!=1 || (match.tag!="*" && match.tag!=el.tagName))) return false;
		if(match.no_prop) return true; //fast instruction [no_prop]
		if(match.id && match.id!=el.id) return false;
		if(match.className && !JJ.element.classname.exist(el, match.className)) return false;
		if(match.attr){
			var attr=JJ.element.attr.get(el, match.attr.key, 1);
			if(match.attr.equal==false && attr!=match.attr.value) return false;
			if(match.attr.equal==true && attr==match.attr.value) return false;
		}
		return true;
	},
	attr2struct:function(expr){
		var equal;
		if(expr.indexOf("!")==0){ expr=[expr.substr(1)]; equal=false;}
		else if(expr.indexOf("!")>0){ expr=expr.split("!="); equal=true;}
		else if(expr.indexOf("=")!=-1){ expr=expr.split("="); equal=false;}
		else {expr=[expr]; equal=true;}
		return {key:expr[0], value:expr[1], equal:equal};
	},
	pos:function(match, match_arr){ //return element by some position
		var pos;
		if(match.pos=="^") pos=0;
		else if(match.pos=="$") pos=match_arr.length-1;
		else if(JJ.type(match.pos, "Number")) pos=Number(match.pos);
		if(pos!=undefined && pos<match_arr.length) return match_arr[pos]; //match element
		return;
	},
	move:function(match, el){ //go to parentNode||nextSibling||previousSibling
		var pos=0;
		while(el=el[match.move_to])
			if(this.check_filters(match, el))
				if(Number(match.pos||0)==pos++) 
					break;
		return el;
	}
};

//Base methods for elements-----------------------------------------------------------------
JJ.element={};


/*
*Element foreach function
*(function(){})
*/
JJ.element.repeat={
	exec:function(obj, func){
		if(JJ.type(obj, "String")) return obj; //check obj for compatibility
		JJ.foreach(obj, func);
		return obj;
	}
};



/*
*Element attributes functions
*("id")                         //get attribute  #String
*(["id", "name", "href"])       //get attributes  #Hash
*("id", "ppp")                  //set attribute "id"="ppp"  #Element
*({name:"abc", param:1})        //set attributes from hash  #Element
*/
JJ.element.attr={
	exec:function(obj, name, value){
		if(JJ.type(obj, "String")) return obj; //check obj for compatibility
		if(JJ.type(name, "String")){
			if(value!=undefined) return this.set(obj, name, value);
			else return this.get(obj, name);
		}
		else if(JJ.type(name, "Object")){
			for(var i in name)
				this.set(obj, i, name[i]);
			return obj;
		}
		else if(JJ.type(name, "Array")){
			var hash={};
			for(var i=0, l=name.length; i<l; i++)
				hash[name[i]]=this.get(obj, name[i]);
			return hash;
		}
	},
	get:function(obj, name, only_tag_attr){
		var attr=obj.getAttribute?obj.getAttribute(name):undefined;
		if(attr==undefined && !only_tag_attr) attr=obj[name];
		if(attr=='' && obj.attributes && obj.attributes[name] && !obj.attributes[name].specified) attr=undefined; //for IE 
		return attr;
	},
	set:function(obj, name, value){
		if(obj.setAttribute && !JJ.type(value, "Function")) obj.setAttribute(name, value);
		obj[name]=value;
		return obj;
	}
};


/*
*Element events functions
*("onclick", function(){})                      //set event  #Element
*("onclick", "alert(1)")                        //set event  #Element
*({onclick:function(){}, onblur:"alert(1)"})    //set event set  #Element
*("onclick", null)                              //remove event  #Element
*("oncomplete")                                 //return event  #Function [default]
*("oncomplete(arg1, arg2,... )")            //return event and init arguments  #Function [default]
*("oncomplete(:Array)")                         //return all event entries  #Array of functions
*("oncomplete(:String)")                        //return event body  #String
*(["onclick","oncomplete"])                     //return set of events in Array #Array of functions [default]
*/
JJ.element.event={
	exec:function(obj, name, value){
		if(!obj.attachEvent && !obj.addEventListener) return obj; //check obj for compatibility
		if(JJ.type(name, "String")){
			if(value!==undefined) return this.set(obj, name, value);
			else return this.get(obj, name); 
		}
		else if(JJ.type(name, "Object")){
			for(var i in name)
				this.set(obj, i, name[i]);
			return obj;
		}
		else if(JJ.type(name, "Array")){
			var hash={};
			for(var i=0, l=name.length; i<l; i++)
				hash[name[i]]=this.get(obj, name[i]);
			return hash;
		}
	},
	set:function(obj, ev, func){
		if(func===null) return this.remove(obj, ev);
		var prev_func=this.get(obj, ev);
		func=this.toFunc(func, obj);
		var call=function(_this, args){
			if(prev_func) prev_func.apply(_this, args);
			return func.apply(_this, args);
		};
		this.rec(obj, ev, func); //write event to data array _onevent_=[]
		obj[ev]=function(){return call(this, arguments)}; //reinit element event
		return obj;
	},
	get:function(obj, ev){
		if(ev.indexOf("(")!=-1){
			var param=ev.split("(");
			ev=param[0];
			var _return=param[1].substr(0, param[1].length-1);
			var args="";
			switch(_return){
				case ":String": return this.toStr(obj["_"+ev+"_"]);
				case ":Array": return obj["_"+ev+"_"];
				default: args=_return;
			}
		}
		var attr=JJ.element.attr.get(obj, ev);
		var func=this.toFunc(attr, obj, args);
		return func;
	},
	remove:function(obj, ev){
		obj[ev]=function(){};
		return obj;
	},
	toFunc:function(attr, obj, args){
		var func;
		if(!attr) return function(){};
		if(JJ.type(attr, "String")) func=new Function(args, attr);
		else func=attr;
		return function(){return func.apply(obj, arguments)};
	},
	toStr:function(_evs){
		if(!_evs) return '';
		var str='';
		for(var i=0, l=_evs.length; i<l; i++){
			var s=_evs[i].toString();
			s=s.replace(/^function[^{]*\{(.*)/gi,"$1");
			s=s.substr(0, s.length-2);
			str+=s+"\n";
		}
		str=str.replace(/;([^\n])/gi,";\n$1");
		return str;
	},
	rec:function(obj, ev, func){

		var _ev="_"+ev+"_";
		if(!obj[_ev]){
			obj[_ev]=[];
			var prev_func=this.get(obj, ev);
			if(prev_func) obj[_ev].push(prev_func);
		}
		obj[_ev].push(func);
	}
};


/*
*Element styles functions (with isNaN check)
*("top")                           //get: "top"  #String or #Number
*(["top", "left"])                 //get: ["top", "left"]  #Hash     
*(["marginLeft", "height"], true)  //get all not empty: ["height"]  #Hash     
*("top", "20")                     //set: "top"="20px"  #Element
*("display", "none", "block")      //toogle: if(display==none) display=block  #Element
*({top:100,left:50})               //set: {top:"20px", left:"10px"}  #Element
*/
JJ.element.css={
	exec:function(obj, name, value, value2){
		if(!JJ.type(obj, "Element")) return obj; //check obj for compatibility
		if(JJ.type(name, "String")){
			if(value!=undefined){
				if(value2!=undefined && this.get(obj, name)==value) value=value2;
				return this.set(obj, name, value);
			}
			else return this.get(obj, name); 
		}
		else if(JJ.type(name, "Object")){
			for(var i in name)
				this.set(obj, i, name[i]);
			return obj;
		}
		else if(JJ.type(name, "Array")){
			var hash={};
			for(var i=0, l=name.length; i<l; i++){
				var val=this.get(obj, name[i]);
				if(!val && value) continue; //if (["top", "left"], true) - return only not empty values 
				hash[name[i]]=val;
			}
			return hash;
		}
	},
	//convert js style property to css property (zIndex -> z-index)
	js2css:function(prop){
		return prop.replace(/([A-Z])/g,"-$1").toLowerCase();
	},
	//get style
	get:function(obj, name){
		var value;
		if(obj.currentStyle) value=obj.currentStyle[name]; //IE, opera
		else if(window.getComputedStyle) value=window.getComputedStyle(obj, null).getPropertyValue(this.js2css(name)); //other Gesco
		else value=obj.style[name]; //other
		if(/^[0-9]+px/.test(value)) value=parseInt(value); //remove "px" [default] from number
		return value;
	},
	//set style 
	set:function(obj, name, value){
		var is_unsigned={"width":1, "height":1};
		if(name in is_unsigned && value<0) value=0; 
		var no_px={"zIndex":1, "opacity":1};
		if(value && JJ.type(value, "Number") && !(name in no_px)) value+="px"; //add "px" [default] to number
		if(name=="opacity" && BROWSER.ie){
			name="filter";
			value=(value==1?"":"Alpha(opacity="+(value*100)+")");
		}
		if(name=="float") name=BROWSER.ie?"styleFloat":"cssFloat";
		try{obj.style[name]=value;}catch(e){throw "element.css.set() -> obj.style."+name+"="+value; };
		return obj;
	},
	//check style
	check:function(obj, name){
		return true;
	}
};


/*
*Element className functions
*()             //get className  #String
*("*")          //get all defined names in className  #Array
*("^")          //get first name  #String
*("$")          //get last name  #String
*("+name")      //add name to className  #Element
*("-name")      //remove name from className  #Element
*("!name")      //toogle name  #Element
*("?name")      //check name existing  #Boolean
*("name")       //set className  #Element
*("")           //clear className  #Element
*/
JJ.element.classname={
	exec:function(obj, query){
		if(obj.className==undefined) return obj; //check obj for compatibility
		if(query==null) return obj.className;
		var c=query.charAt(0);
		var name=query.substr(1);
		with(this){
			switch(c){
				case "*": return all(obj);
				case "^": return get(obj, 0);
				case "$": return get(obj, 1);
				case "+": add(obj, name); break;
				case "-": remove(obj, name); break;
				case "!": toogle(obj, name); break;
				case "?": return exist(obj, name);
				default:  set(obj, query);
			}
		}
		return obj;
	},
	empty:function(obj){
		return obj.className.replace(/\s/g,"")==""?true:false;
	},
	exist:function(obj, name){
		return (new RegExp('((^)|(\\s))'+name+'((\\s)|($))')).test(obj.className);
	},
	all:function(obj){
		return !this.empty(obj)?obj.className.split(/\s+/):[];
	},
	get:function(obj, pos){
		var arr=this.all(obj);
		if(!arr.length) return "";
		pos=pos?arr.length-1:0;
		return arr[pos];
	},
	set:function(obj, name){
		obj.className=name;
	},
	add:function(obj, name){
		this.remove(obj, name);
		obj.className+=obj.className?' '+name:name;
	},
	remove:function(obj, name){
		obj.className=obj.className.replace(new RegExp("((^)|(\\s))"+name+"((\\s)|($))"),"$3");
	},
	toogle:function(obj, name){
		this.exist(obj, name) ? this.remove(obj, name) : this.add(obj, name);
	}
};


/*
*Element insert functions
*("span")                       //append <span>
*("span:^")("span:0")           //insert <span> before first element
*("span:2")                     //insert <span> before second sibling
*("span", beforeElement)        //insert <span> before beforeElement
*("input", {type:"submit"})     //insert <input> and set attribute "type" before insert
*/
JJ.element.insert={
	exec:function(obj, tag, opt){
		if(!obj.appendChild) return obj; //check obj for compatibility
		var elem=tag;
		var beforeElement;
		if(JJ.type(tag, "String")){
			if(tag.indexOf(":")!=-1){
				var params=tag.split(":");
				tag=params[0];
				beforeElement=JJ.getElements.parse(">:"+params[1], obj);
			}
			elem=document.createElement(tag);
		}
		
		if(JJ.type(opt, "Object") && !opt.nodeType) JJ.element.attr.exec(elem, opt); //set element attributes before insert
		else beforeElement=opt; 
		
		beforeElement ? obj.insertBefore(elem, beforeElement) : obj.appendChild(elem);
		return _(elem);
	}
};

/*
*Element inner html
*("code")             //set innerHTML
*()                   //get innerHTML
*/
JJ.element.html={
	exec:function(obj, str){
		if(obj.innerHTML==undefined) return obj; //check obj for compatibility
		if(str==undefined) return obj.innerHTML;
		obj.innerHTML=str;
		return obj;
	}
};

/*
*Element remove function
*()                   //remove current element & return parent
*(child_el)           //remove child element & return current element
*/
JJ.element.remove={
	exec:function(obj, child_el){
		if(!obj.removeChild) return obj; //check obj for compatibility
		if(child_el==undefined){
			var par=obj.parentNode;
			par.removeChild(obj);
			return null;
		}
		else{
			var el=_(child_el);
			obj.removeChild(el);
			return obj;
		}
	}
};


/*
*Element activate or activate child (set classname="act")
*()                   //activate current element
*(2)                  //activate specified child element 
*/
JJ.element.act={
	exec:function(obj, num){
		var _this=this;
		if(!obj || !obj.tagName || !obj.parentNode) return false;
		if(obj.attr("noact")!=undefined) return false;
		var par=_(obj, "<");
		if(par.tagName=="LI" || par.tagName=="DT") par=_(par, "<");
		if(num!=undefined){
			par=obj; 
			obj=_(par, '>a:'+num);
		}
		if(!par.deact) par.deact=function(){_this.deact(this)}; //init funtion [set]
		if(par.cur==obj) return false;
		this.act(par, obj);
		obj.event("onact")(); //call [onact] event
		return false;
	},
	
	act:function(par, obj){
		if(!par.cur) par.cur=_(par, ">a.act"); // if no [cur] try to find it
		if(par.cur) par.cur.classname("-act");
		obj.classname("+act");
		par.cur=obj;
	},
	deact:function(par){
		if(!par.cur) return false;
		par.cur.classname("-act");
		par.cur=null; 
		return false;
	}
};


JJ.element.offset={
	exec:function(obj){
		var left=0, top=0;
		if(obj.getBoundingClientRect){
			var box=obj.getBoundingClientRect();
			left=box.left+Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
			top=box.top+Math.max(document.documentElement.scrollTop, document.body.scrollTop);
		}
		else{
			
		}
		return {left:left, top:top};
	}
};



JJ.element.display={
	exec:function(obj, b, sender){
		var no_display=(obj.css("display")=="none");
		var no_visibility=(obj.css("visibility")=="hidden");
		if(!obj.display_default) obj.display_default=no_display?"block":obj.css("display");
		var b=(b==undefined?(no_display||no_visibility?1:0):b);
		obj.css({display:b?obj.display_default:"none"});
		return obj;
	}	
};

//element effects--------------------
JJ.element.slide={
	exec:function(obj, b, opt){
		if(!window.EFX) return obj;
		obj.smooth_slide=EFX.slide(obj, b, opt);
		//fade effect for Gesco
		if(obj.smooth_fade || obj.css("visibility")=="hidden"){
			if(!BROWSER.ie && !BROWSER.opera) obj.fade(b, opt);
			else obj.css({visibility:"visible"});
		}
		return obj;
	}
};
JJ.element.fade={
	exec:function(obj, b, opt){
		if(!window.EFX) return obj;
		obj.smooth_fade=EFX.fade(obj, b, opt || {dyn:30});
		return obj;
	}
};
//---------------------------------------



//DOM extends
if(!String.prototype._extend) JJ.extend(String.prototype, JJ.element);
if(!Array.prototype._extend) JJ.extend(Array.prototype, JJ.element);
document.event=function(ev, func){JJ.element.event.exec(document, ev, func)};





//Externals-----------------------------------------------------------

var BROWSER={
	ie:(document.all && !window.opera)?true:false,
	ie6:navigator.appVersion.indexOf("MSIE 6")!=-1,
	ie7:navigator.appVersion.indexOf("MSIE 7")!=-1,
	chrome:navigator.appVersion.indexOf("Chrome")!=-1,
	safari:navigator.appVersion.indexOf("Safari")!=-1 && navigator.appVersion.indexOf("Chrome")==-1,
	opera:window.opera
};



var Class=function(proto){
	var obj=function(){this.init.apply(this, arguments)};
	obj.prototype=proto;
	obj.prototype.constructor=obj;
	return obj;
};



var Event=function(e){
	e=window.event?window.event:e;
	return {
		key:function(key){
			if(typeof key=="string"){
				var sysKey={ctrl:1, shift:1, alt:1};
				var customKey={enter:13, escape:27, space:32, tab:9, left:37, up:38, right:39, down:40};
				if(key in sysKey) return e[key+"Key"];
				else if(key in customKey) key=customKey[key];
				else key=key.charCodeAt(0);
			}
			var code=window.event?e.keyCode:e.which; 
			return key!=undefined?code==key:code;
		},
		target:function(){
			var target=window.event?e.srcElement:e.target; 
			return target;
		},
		mouse:function(v){ 
			var c={
				x:window.event?e.clientX+document.documentElement.scrollLeft:e.pageX, 
				y:window.event?e.clientY+document.documentElement.scrollTop:e.pageY
			};
			return v!=undefined?c[v]:c;
		},
		prevent:function(){ 
			if(window.event){ e.cancelBubble=true; e.returnValue=false;} 
			else if(e.preventDefault) e.preventDefault();
		},
		stop:function(){ 
			if(window.event){ e.cancelBubble=true; e.returnValue=false;} 
			else if(e.preventDefault) e.stopPropagation();
		}
	}
};



var COOKIE={
	set:function(name, value, expire) {
		if(expire){
			var d=new Date();
			d.setTime(d.getTime()+expire*1000);
			expire="; expires="+d.toUTCString();
		}
		else expire="";
		document.cookie=name+"="+escape(value)+expire+"; path=/";
	},
	get:function(name) {
		if(document.cookie.length==0) return false;
		var offset=document.cookie.indexOf(name+"=");
		if(offset!=-1) { 
			offset+=name.length+1;
			var end=document.cookie.indexOf(";", offset);
			if (end==-1) end=document.cookie.length;
			return unescape(document.cookie.substring(offset, end)) 
		}
		return false;
	},
	all:function(arr){
		arr=arr || [];
		var i, cookieArray = document.cookie.split(';'), caLength = cookieArray.length, c, eqIndex, name, value;
		for (i = 0; i < caLength; i++) {
			c = cookieArray[i];
			
			// Left Trim spaces
			while (c.charAt(0) === " ") {
					c = c.substring(1, c.length);
			}
			eqIndex = c.indexOf("=");
			if (eqIndex > 0) {
					name = c.substring(0, eqIndex);
					value = c.substring(eqIndex + 1);
					arr[name] = value;
			}
		}
		return arr;
	}
};





//fix ie6 png & css :hover state
function ie6_fixes(root, prop){
	var base=_("base:^").href;
	_(root, "*").repeat(function(){
		if(!this || ! this.currentStyle) return;
		if(prop.png && this.currentStyle[prop.png]){
			var src=base+(window.GLOBAL_PATH?GLOBAL_PATH:"")+this.currentStyle[prop.png].replace(/url\(['"]?([^'"]*)['"]?\)$/i,"$1");
			this.css({filter:'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+src+'",sizingMethod='+'crop'+')', background:"none"});
		}
		if(prop.hover && this.currentStyle[prop.hover]) {
			this.event("onmouseover", function(){ Style(this).add(this.currentStyle[prop.hover]); });
			this.event("onmouseout", function(){ Style(this).remove(this.currentStyle[prop.hover]); });
		}
	});
};


function flashDetect(){
	if(typeof navigator.plugins!=undefined && typeof navigator.plugins["Shockwave Flash"]=="object"){
		var d=navigator.plugins["Shockwave Flash"].description;
		if (d && !(typeof navigator.mimeTypes!=undefined && navigator.mimeTypes["application/x-shockwave-flash"] && !navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)){
			return true;
		}
	}
	else if(typeof window.ActiveXObject!=undefined) {
		try{
			var a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");  //return null when ActiveX is disabled
			if(a){
				var d=a.GetVariable("$version");
				if(d){
					return true;
				}
			}
		}
		catch(e){}
	}
	return false;
}


function _uid(){
	return (new Date()).getTime()+Math.round(Math.random()*1000);
}


//debug output for Array & Hash objects
function o2s(o){
	if(o.constructor == String) return o;
	var cont = [];
	var addslashes=function(s){return s.split('\\').join('\\\\').split('"').join('\\"');};
	for (var k in o) { 
		if (cont.length) cont[cont.length-1] += ",";
		var v = o[k];
		var vs = ''; 
		if (v.constructor == Object || v.constructor == Array) vs=o2s(v);
		else if (v.constructor == String) vs = '"' + addslashes(v) + '"';
		else  vs = v;
		cont[cont.length]=k + ": " + vs;
	}
	cont = "	" + cont.join("\n").split("\n").join("\n	");
	var s = cont;
	if (o.constructor == Object) s = "{\n"+cont+"\n}";
	if (o.constructor == Array) s = "[\n"+cont+"\n]";
	return s;
};

//window._alert=window.alert;
//window.alert=function(str){window._alert(str!==undefined?o2s(str):"undefined")};// GLOBAL PARAMETERS

var LANG="ua"; //default language

var GLOBAL_PATH="tml/";
var APP_PATH="app/";
var IMGS_PATH=GLOBAL_PATH+"imgs/";

var AJAX_HANDLER=APP_PATH+"index.php?_ajax";
var CACHE_DEFAULT=60;  //default ajax cache [in minutes]
var DEBUGGER_ENABLED=1;

/*
----------------------------------------------------------------------
EXAMPLE:

smooth=new Smooth({dyn:35, speed:-2, to:300});
smooth.onplay=function(pos){obj.style.height=pos+"px"};
smooth.onend=function(d){ _(obj).css({display:d>0?"block":"none"})};

----------------------------------------------------------------------
opt={
	dyn:     [-100..+100]   //dynamic scrolling (default:50)
	speed:   [-10..+10]     //scrolling speed (default:1)
	from:    [number]       //start position  (default:0)
	to:      [number]       //end position  (default:100)
}
methods={	
	go:      function(){};
	back:    function(){};
	start:   function(from, to){};
}
events={
	onstart: function(){};
	onplay:  function(){};
	onend:   function(){};
}
----------------------------------------------------------------------
*/

var Smooth=new Class({
	dyn:0,
	speed:1,
	from:0,
	to:100,
	init:function(opt){
		this.dyn=(opt.dyn!=undefined?opt.dyn:-50)/100;
		this.speed=opt.speed?(opt.speed>0?opt.speed:-1/opt.speed):1;
		this.from=opt.from!=undefined?opt.from:this.from;
		this.to=opt.to!=undefined?opt.to:this.to;
		this.onstart=opt.onstart || this.onstart;
		this.onplay=opt.onplay || this.onplay;
		this.onend=opt.onend || this.onend;
		if(opt.autostart) opt.autostart>0?this.start():this.toogle();
	},
	start:function(from, to){
		if(from!=undefined) this.from=from;
		if(to!=undefined) this.to=to;
		this.d=this.from<this.to?1:-1; //direction
		this.startPos=this.from;
		this.endPos=this.to;
		this.range=0;
		if(this.tm){
			clearTimeout(this.tm);
			this.tm=null;
		}
		else{
			this.onstart(this.d);
			this.curPos=this.from;
		}
		this.onplay(this.curPos);
		this.play(); 
	},
	play:function(){
		var _this=this;
		if(this.dyn!=0) this.range=Math.round((this.dyn>0?(this.endPos-this.curPos)*this.dyn:-(this.curPos-this.startPos)*this.dyn)*this.speed);
		if(this.range*this.d<1) this.range=this.d*this.speed;
		this.curPos+=this.range;
		if(this.endPos*this.d<this.curPos*this.d) return this.end();
		this.onplay(this.curPos, this.curPos/this.endPos);
		this.tm=setTimeout(function(){_this.play()}, 30);
	},
	end:function(){
		clearTimeout(this.tm);
		this.tm=null;
		this.curPos=this.endPos;
		this.onend(this.d);
		return false;
	},
	toogle:function(){
		var t=this.from;
		this.from=this.to;
		this.to=t;	
		this.start();
	},
	onstart:function(d){},
	onplay:function(curPos){},
	onend:function(d){}
});



var Transition=new Class({
	init:function(img, opt){
		var _this=this;
		this.img=img;
		this.dyn=opt.dyn!=undefined?opt.dyn:10;
		this.speed=opt.speed!=undefined?opt.speed:1;
		this.hardhide=opt.hardhide?1:0;
		this.smooth=new Smooth({
			dyn:_this.dyn, 
			speed:_this.speed,
			onstart:function(){_this.inTransition=1},
			onplay:function(pos){img.css({opacity:pos/100})},
			onend:function(){_this.inTransition=0}
		});
	},
	appear:function(){
		var _this=this;
		if(this.hardhide && this.smooth_disapear) this.smooth_disapear.end(); //hardhide disappearing if new appear (appear new from dark)
		setTimeout(function(){_this.smooth.start()}, 0); //setTimeout used for IE
	},
	disappear:function(){
		var _this=this;
		if(this.inTransition) this.smooth.end();
		if(this.smooth_disapear) this.smooth_disapear.end();
		this.img_disapear=this.img.parentNode.insert(this.img.cloneNode(true)).css({position:"absolute", zIndex:1, top:this.img.offsetTop, left:this.img.offsetLeft});
		this.smooth_disapear=new Smooth({
			dyn:_this.dyn, 
			speed:_this.speed+2,
			onplay:function(pos){_this.img_disapear.css({opacity:pos/100})},
			onend:function(pos){_this.smooth_disapear=_this.img_disapear=_this.img_disapear.remove();  },
			autostart:-1
		});
		this.img.css({opacity:0});
	}
});



var EFX={
	slide:function(obj, b, opt){
		var sm=obj._efx_slide;
		if(!sm){
			opt=opt || {};
			opt.dyn=opt.dyn!=undefined?opt.dyn:50;
			opt.speed=opt.speed!=undefined?opt.speed:-1;
			opt.onstart=function(d){ obj.css({overflow:"hidden", paddingBottom:0, paddingTop:d<0?0:sm.css.paddingTop, height:sm.from, position:sm.css.position});};
			opt.onplay=function(pos){ obj.css({height:pos});};
			opt.onend=function(d){obj.css(sm.css); if(d<0) obj.css({display:"none"});};
			sm=obj._efx_slide=new Smooth(opt);
		}
		if(sm.isVisible!=undefined && sm.isVisible===b) return false;
		if(sm.tm) sm.toogle(); //if play is not finished
		else{
			var is_hidden=(obj.css("display")=="none");
			b=sm.isVisible=(b==undefined?(is_hidden?1:0):b);
			if(!is_hidden) obj.css({display:"none"});
			sm.css=obj.css(["overflow", "position", "paddingTop", "paddingBottom", "height"]);
			if(is_hidden) obj.css({position:"absolute"}); //for height init
			obj.css({display:"block"});
			var end=obj.offsetHeight-sm.css.paddingTop;
			sm.start(b?0:end, b?end:0);
		}
		return sm;
	},
	fade:function(obj, b, opt){
		var sm=obj._efx_fade;
		if(!sm){
			opt=opt || {};
			opt.dyn=opt.dyn!=undefined?opt.dyn:50;
			opt.speed=opt.speed!=undefined?opt.speed:-1;
			opt.onstart=function(d){obj.css({visibility:"visible", opacity:sm.from/100});};
			opt.onplay=function(pos){obj.css({opacity:pos/100}); };
			opt.onend=function(d){if(d<0) obj.css({visibility:"hidden"});};
			sm=obj._efx_fade=new Smooth(opt);
		}
		if(sm.isVisible!=undefined && sm.isVisible===b) return false;
		if(sm.tm) sm.toogle(); //if play is not finished 
		else {
			b=sm.isVisible=(b==undefined?(obj.css("visibility")=="hidden"?1:0):b);
			var end=100;
			sm.start(b?0:end, b?end:0);
		}
		return sm;
	}
};
var IFS={
	list:{},
	create:function(){
		var _this=this;
		this.root=_(document.body).insert("div").attr({id:"ifs"});
		this.block=this.root.insert("div").classname("block");
		this.title=this.block.insert("div").classname("title");
		this.but={
			next:this.root.insert("a").classname("next").event("onclick", function(){_this.go(1)}),
			prev:this.root.insert("a").classname("prev").event("onclick", function(){_this.go(-1)}),
			close:this.block.insert("a").classname("close").event("onclick", function(){_this.hide()})
		};
		this.but.next.insert("i");
		this.but.prev.insert("i");
		this.body=this.block.insert("div").classname("body");
		this.img=this.body.insert("img").event("onload", function(){setTimeout(function(){_this.set()}, 100);});
		
		this.set_block(this.body.offsetWidth, this.body.offsetHeight);
		
		_(document).event("onkeydown", function(e){
			if(_this.isOpen){
				if(Event(e).key("escape")) _this.hide(); //escape
				if(Event(e).key("left")) _this.go(-1); //arr left
				if(Event(e).key("right")) _this.go(1); //arr right
			}
		});
		
		this.transition=new Transition(this.img, {speed:1, classname:"disapear"});
		this.modal=new Modal({opacity:0.8});
		this.inited=1;
	},
	init:function(obj){
		var _this=this;
		obj=_(obj);
		obj.group=obj.attr("ifs");
		if(!this.list[obj.group]) this.list[obj.group]=[];
		this.list[obj.group].push(obj);
		obj.event("onclick", function(){return _this.show(this, 1)});
	},
	showhide:function(b){
		this.modal.showhide(b);
		this.root.css({visibility:b?"visible":"hidden"});
		this.isOpen=b;
	},
	show:function(obj){
		if(!this.inited) this.create();
		this.img.src=obj.href;
		this.cur_pos=this.pos(obj);
		this.cur_list=this.list[obj.group];
		this.showhide(1);
		return false;
	},
	hide:function(){
		this.transition.disappear();
		this.img.classname("");
		this.title.html("");
		this.showhide(0);
		return false;
	},
	pos:function(obj){
		var group=this.list[obj.group];
		for(var i in group)
			if(group[i]==obj)
				return Number(i);
		return 0;
	},
	go:function(d){
		if(this.cur_pos+d<0 || this.cur_pos+d>this.cur_list.length-1) return false;
		this.cur_pos+=d;
		this.transition.disappear();
		this.img.classname("");
		this.img.src=this.cur_list[this.cur_pos].href;
		return false;
	},
	buts:function(){
		this.but.prev.classname((this.cur_pos==0?"+":"-")+"disable");
		this.but.next.classname((this.cur_pos==this.cur_list.length-1?"+":"-")+"disable");
	},
	set:function(){
		var _this=this;
		if(this.cur_list && this.cur_pos!=undefined){
			this.title.html(this.cur_list[this.cur_pos].title);
			this.buts();
		}
		this.set_block(this.img.width, this.img.height);
		this.transition.appear();
		this.img.classname("show");
		this.onset(this);
	},
	set_block:function(w, h){
		var top=Math.round((document.documentElement.clientHeight-h)/2)-this.block.css("paddingTop");
		var scrollTop=document.documentElement.scrollTop;
		var left=-Math.round(w/2)-this.block.css("paddingLeft");
		this.root.css({top:(top>0?top+scrollTop:scrollTop)});
		this.block.css({width:w});
		this.body.css({width:w, height:h});
	},
	onset:function(_this){}
}


var Popup={
	init:function(){
		var _this=this;
		this.block=_(document.body).insert("div").attr({id:"popup"});
		this.but_close=this.block.insert("a").classname("close").event("onclick", function(){_this.hide()});
		this.block.insert("div").classname("top");
		this.body=this.block.insert("div").classname("body");
		this.block.insert("div").classname("bottom");
		_(document).event("onkeydown", function(e){
			if((Event(e).key("escape") || (Event(e).key("enter") && _this.okButton)) && _this.isOpen) _this.hide();
		});
		this.modal=new Modal();
		this.inited=1;
	},
	showhide:function(b){
		this.modal.showhide(b);
		this.block.css({visibility:b?"visible":"hidden"});
		this.isOpen=b;
	},
	show:function(content){
		var _this=this;
		if(!this.inited) this.init();
		this.body.html(content);
		this.okButton=_(this.block, "a.but_ok").event({onclick:function(){_this.hide()}});
		if(window.init_content) init_content(this.body);
		this.block.css({marginTop:-Math.round(this.block.offsetHeight/2)});
		this.showhide(1);
		return false;
	},
	hide:function(){
		this.showhide(0);
		this.body.html("");
		return false;
	},
	alert:function(content){
		return this.show(content);
	},
	confirm:function(content){
		return this.show(content);
	},
	win:function(content){
		return this.show(content);
	}
};


var Modal=new Class({
	init:function(opt){
		this.block=_(document.body).insert("div").classname("modal");
		this.layer=this.block.insert("span");
		opt=opt||{};
		if(opt.loader!=undefined) this.block.insert("div").classname("loader").html(opt.loader);
		if(opt.opacity!=undefined) this.layer.css({opacity:opt.opacity});
		if(opt.bgcolor){ this.layer.css({background:opt.bgcolor});}
		this.inited=1;
	},
	showhide:function(b){
		this.block.css({display:b?"block":"none"});
		this.isOpen=b;	
	},
	show:function(opt){
		this.showhide(1);
	},
	hide:function(){
		this.showhide(0);	
	}
});

function slideshow(obj, count){
	var root=_(obj, "<");
	root.index=0;
	root.loop=1;
	root.count=count;
	root.cur=_(obj);
	root.create=function(index){
		root.cur.event({onload:null});
		var src=root.cur.src.replace(/_[0-9]+/, "_"+Number(index+1));
		return root.insert("img").attr({src:src}).css({opacity:0}).event("onload", function(){});
	}
	root.next=function(){
		var index=root.index+1;
		if(index>=root.count) index=0;
		var next=_(root, "img:"+index);
		if(!next) next=root.create(index);
		setTimeout(function(){root.playStart(next, index)}, 4000);
	}
	root.playStart=function(next, index){
		var prev=root.cur;
		root.cur=next;
		root.index=index;
		root.cur.css({zIndex:root.loop++});
		var smooth=new Smooth({dyn:0, speed:1.5});
		smooth.onplay=function(pos){root.cur.css({opacity:pos/100})};
		smooth.onend=function(){root.playEnd(prev)};
		smooth.start();
	}
	root.playEnd=function(prev){
		prev.css({opacity:0});
		root.next();
	}
	root.next();
	
};


function init_mail(id) {
	var obj=_(id);
	if(obj.rel.indexOf("@")!=0) return false;
	obj.rel=obj.rel.substr(1, obj.rel.length);
	var mail=obj.rel+"@"+obj.href.replace(/http:\/\/([^\/]*)\/?/, "$1");
	obj.href="mailto:"+mail;
	//if(obj.innerHTML == '') obj.innerHTML=mail;
	if(obj.html() && !obj.getElementsByTagName("*")[0]) obj.html(mail);
};document.onload=function(){
	if(arguments.callee.inited) return;
	else arguments.callee.inited=1;
	init_content(document);
};
JJ.element.event.set(window, "onload", function(){});



//initialize output content
function init_content(root){
	
	
	_(root, "a[ifs]").repeat(function(){
		IFS.init(this);
	});
	
	_(root, "a[rel]").repeat(function(){
		init_mail(this);
	});
	

	
};

