var ie=document.all && !window.opera;
var IE6=navigator.appVersion.indexOf("MSIE 6")!=-1;
var IE7=navigator.appVersion.indexOf("MSIE 7")!=-1;

var _=function(obj,route){
	if(!obj) return null;
	if(typeof obj=="string" && document.getElementById) obj=document.getElementById(obj);
	if(obj) return route?_DOM(obj,route):obj;
	else return null;
};


//Linguistic DOM objects search functionality
// ">" - next sibling tag
// "<" - prefious sibling tag
// "^" - first child tag
// "$" - last child tag
// "/" - parent node
// "~" - search  in child nodes
// "@" - return array matches
// "." - className property
// ":" - id property
// "#" - name property
// ----- RegExp to search _\(\'?\"?[a-zA-Z0-9_]+\'?\"?,
function _DOM(obj,route){
	route=route.replace(/[^<>\^$\/~a-z0-9_@.:# ]/gi,""); //clear uncorrect instructions
	route=route.replace(/(^[a-z@.:#].*)/i,"^$1"); //normalize inctructions (start with firstChild)
	route=route.replace(/((\<+)|(\>+)|(\^)|(\$)|(\/)|(\~)|(\@))/g,"$1*").replace(/\*([a-z0-9_@.:# ])/gi,"$1"); //add "any tag" (*) pointer
	var tags=route.toUpperCase().match(/([a-z0-9_*.:# ]+)/gi) || []; //create tags array
	var pointer=route.replace(/[^<>\^$\/~@]+/g,"+"); //split inctructions
	
	//alert(route+" ||| "+tags+" ||| "+pointer+" ||| ")
	var fit={
		">":"nextSibling",
		"<":"previousSibling",
		"^":"firstChild",
		"$":"lastChild",
		"/":"parentNode",
		".":IE6||IE7?"className":"class",
		":":"id",
		"#":"name"
	};
	var tagPos=0, childPos=0;
	var char, tag, tagName, propKey, propValue, found, childNodes;
	var matches=[];

	while((char=pointer.charAt(0))){
		if(char=="+"){//change filter by "tag"
			if(tags[tagPos+1]) tagPos++;
			pointer=pointer.substr(1);
			continue;
		}
		
		tagName=tags[tagPos];
		propKey="";
		
		//if property exist
		if(tagName && (/[.:#]/.test(tagName))){
			propKey=fit[tagName.replace(/[^.:#]/g,"")];
			tag=tagName.match(/([a-z1-6_]*)[.:#]([a-z0-9_ ]*)/i);
			tagName=tag[1] || "*";
			propValue=tag[2];
			//alert(tagName+" "+propKey+" "+propValue)
		}
		
		//search in child nodes
		if(char=="~"){
			if(!childNodes) childNodes=obj.getElementsByTagName(tagName);
			else childPos++;
		}
		else if(childNodes){
			childNodes=null;
			childPos=0;
		}
		
		if(!(obj=obj[fit[char]] || (childNodes && childNodes[childPos]))) return matches.length?matches:null; //set next object
		found=!(obj.nodeType!=1 || (tagName!="*" && obj.tagName!=tagName) || (propKey && (!obj.getAttribute(propKey) || typeof obj.getAttribute(propKey)!="string" || obj.getAttribute(propKey).toUpperCase()!=propValue)));
		if(found) pointer=pointer.substr(1);
		
		//if first/last child not found in first step
		if((char=="^" || char=="$") && !found){
			pointer=pointer.replace(/./,(char=="^"?">":"<"));
		}
		
		//if matches symbol was found (return array of matches)
		if(pointer.charAt(0)=="@"){
			if(char=="^" && found) char=">";
			pointer=char+pointer;
			matches[matches.length]=obj;
		}
	}
	return obj;
};




function addEvent(el, evname, func) {
	if(!el["on"+evname] && el!=window && el!=document) return el["on"+evname]=func;
	if(el.attachEvent) el.attachEvent("on"+evname, func); // IE
	else if(el.addEventListener) el.addEventListener(evname, func, true); // Gecko / W3C
	else el["on"+evname]=func;
};
var _addEvent=addEvent;

function removeEvent(el, evname, func) {
	//if(el["on"+evname]) return el["on"+evname]=null;
	if(el.detachEvent) el.detachEvent("on" + evname, func); // IE
	else if (el.removeEventListener) el.removeEventListener(evname, func, true); // Gecko / W3C
	else el["on"+evname]=null;
};


var CC={
	cc:"customControl",
	e:{},
	attachEvent:function(ev, func){
		var f=this.e[ev]=(this.e[ev]?this.e[ev]:"")+func.toString().replace(/^function\s?\(\)\s?{\n?(.*)\n?;?}/,"$1");
		this[ev]=!this[ev]?func:function(){eval(f)};
	},
	removeEvent:function(ev){
		if(this[ev]) this[ev]=null;
	},
	fireEvent:function(ev){
		if(this[ev]) this[ev]();
	}
};


//get tag Attribute
function _ATTR(obj,attr){
	obj=_(obj);
	if(!obj || !attr) return null;
	return obj.getAttribute && obj.getAttribute(attr)!=undefined ? obj.getAttribute(attr) : (obj[attr]!=undefined ? obj[attr] : null);
};

//get tag Event
function _EV(obj,attr,args){
	var _prop_=_ATTR(obj,attr);
	if(_prop_ && /^on[a-z]+/.test(attr))
		return  typeof _prop_=="function" ? _prop_ : (new Function(args,_prop_)).$this(obj);
	else 
		return function(){};
};


// universal HTML creator
function makeHTML(OBJ,root){
	var tag=root;
	for(var i in OBJ){
		if(i=="tag") tag=document.createElement(OBJ[i]);
		else if(i=="append") 
			for(var j in OBJ[i]){ 
				if(OBJ[i][j].tag) 
					tag.appendChild(makeHTML(OBJ[i][j]));
			}
		else if(tag) tag[i]=OBJ[i];
	}
	if(root && root!=tag) root.appendChild(tag);
	return tag;
};





// element className & style functions
var Style=function(obj){
	return {
		empty:function(){
			return obj.className.replace(/\s/g,"")==""?true:false;
		},
		all:function(name){
			return !this.empty()?obj.className.split(/\s+/):[];
		},
		exist:function(name){
			for(var i=0, c=this.all(name), l=c.length; i<l; i++)
				if(c[i]==name) 
					return true;
			return false;
		},
		set:function(name){
			obj.className=name;
		},
		add:function(name){
			this.remove(name);
			obj.className+=obj.className?' '+name:name;
			return true;
		},
		remove:function(name){
			obj.className=obj.className.replace(new RegExp("((^)|(\\s))"+name+"((\\s)|($))"),"$3");
			return false;
		},
		invert:function(name){
			return this.exist(name) ? this.remove(name) : this.add(name);
		},
		clear:function(){
			obj.className='';
		}
	}
};


//Element styles functions
var CSS=function(obj){
	return {
		//convert js style property to css property (zIndex -> z-index)
		js2css:function(prop){
			return prop.replace(/([A-Z])/g,"-$1").toLowerCase();
		},
		//get style|styles value from css element (arguments=[string|hash|array])
		get:function(prop){
			if(typeof prop=="string"){
				if(_(obj).currentStyle) return _(obj).currentStyle[prop];
				if(window.getComputedStyle) return window.getComputedStyle(_(obj),null).getPropertyValue(this.js2css(prop));
			}
			else if(prop){
				var style={};
				for(var i in prop){
					if(prop.length) i=prop[i]; //get prop if array
					style[i]=this.get(i);
				}
				return style;
			}
			else return 0;
		},
		//set new styles to element & return old styles (arguments=[hash])
		set:function(hash){
			var style={};
			for(var i in hash){
				style[i]=this.get(i);
				_(obj).style[i]=hash[i];
			}
			return style;
		},
		//copy style|styles from obj to anoter element & return this styles (arguments=[string|array])
		copy:function(prop,to){
			if(typeof prop=="string")
				return (_(to).style[prop]=this.get(prop));
			else if(prop){
				var style=this.get(prop);
				for(var i in style)
					_(to).style[i]=style[i];
				return style;
			}
			return null;
		},
		//check current element style|styles (arguments=[hash])
		check:function(hash){
			for(var i in hash)
				if(hash[i]!=this.get(i))
					return false;
			return true;
		}
	}
};


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;
	}
};


function Num(val){
	if(isNaN(val)) val=val.replace(/,/,"."); //if float [,]
	if(isNaN(val)) val=parseInt(val); //if [px]
	if(isNaN(val)) val=0;
	return Number(val);
};


//Array functions -----------------------------------------

//last element in array
function last(arr){
	return arr[arr.length-1];
};

//concat arrays
function concat(arrarr){
	var outarr=[];
	for(var i=0, l=arrarr.length; i<l; i++)
		for(var j=0, ll=arrarr[i].length; j<ll; j++)
			outarr.push(arrarr[i][j]);
	return outarr;
};

//find in array
function array_find(arr,value){
	for(var i=0, l=arr.length; i<l; i++)
		if(arr[i]==value) 
			return true;
	return false;
};

//-----------------------------------------------------------


//Hash functions
function Hash(h){
	var _h={};
	for(var i in h) _h[i]=h[i];
	
	return {
		clone:function(){
			return _h;
		},
		count:function(){
			var k=0;
			for(var i in _h) k++;
			return k;
		},
		branch:function(){
			var h=this.clone();
			while(typeof h=="object") 
				for(var i in h){ 
					h=h[i]; 
					break;
				}
			return h;
		},
		merge:function(){
			for(var i=0, l=arguments.length; i<l; i++)
				for(var j in arguments[i])
					_h[j]=arguments[i][j];
			return _h;
		},
		replace:function(key,value){
			if(typeof key=="number") key=this.key(key);
			_h[''+key]=value;
			return	_h;
		},
		record:function(at){
			var k=0;
			for(var i in _h) if(at==k++) return [i, _h[i]];
			return [null,null];
		},
		key:function(at){
			return this.record(at)[0];
		},
		value:function(at){
			return this.record(at)[1];
		}
	}
};


var Preloader={
	pObj:null,
	cObj:null,
	tm:null,
	counter:0,
	full_time:0,
	start:function(title, full_time){
		if(IE6) return false;
		this.full_time=full_time;
		document.write('<div id="_preloader_">'+title+' <span>'+this.counter+'</span>%</div>');
		this.pObj=document.getElementById("_preloader_");
		this.cObj=this.pObj.getElementsByTagName("span")[0];
		CSS(this.pObj).set({fontSize:"11px", color:"#677984", position:"absolute", margin:"4px 0 0 6px", zIndex:400});
	},
	update:function(ms){
		var _this=this;
		var cur_value=this.counter;
		this.counter+=Math.round(ms/this.full_time*100);
		if(this.tm) clearTimeout(this.tm);
		for(var i=cur_value; i<=this.counter; i++) this.tm=setTimeout(function(){_this.cObj.innerHTML=i<100?i:100},25);
	},
	finish:function(percent){
		if(IE6) return false;
		if(!this.pObj) return false;
		if(document.body) document.body.removeChild(this.pObj);
		else setTimeout(function(){Preloader.finish()}, 500);
	}
};

//js include
function include(src, ms){
	if(!document.js_files) document.js_files={};
	if(document.js_files[src]) return false;
	document.js_files[src]=1;
	src=(/^https?:\/\/.+/.test(src)?src:GLOBAL_PATH+src);
	var pre='';
	if(src.indexOf(".css")==-1) document.write('<'+'script type="text/javascript" src="'+src+'"'+pre+'><'+'/script>');
	else document.write('<link type="text/css" rel="stylesheet" href="'+src+'"'+pre+' />');	
};


function Coord(e){
	if(window.event){
		this.x=window.event.clientX;
		this.y=window.event.clientY;
	}
	else{
		this.x=e.pageX;
		this.y=e.pageY;
	}
	return this;
};



var Key=function(event){
	return {
		code:function(){return window.event?window.event.keyCode:event?event.which:0;},
		is:function(num){return this.code()==num},
		isEnter:function(){return this.code()==13},
		isEscape:function(){return this.code()==27}
	}
};



Date.prototype._0=function(num){return (num<10?"0"+num:num)};


Function.prototype.$this=function(object) {
    var method = this;
    return function(){
        return method.apply(object, arguments) 
    }
};

Function.prototype.foreach=function(){
	for(var i=0, arr=arguments[0], l=arr.length; i<l; i++){
		arguments[0]=arr[i];
		this.apply(this, arguments);
	}
};

//debug output for Array & Hash objects (crusial in Chrome)
if(0)
Array.prototype.toString =
Object.prototype.toString = function() {
	var cont = [];
	var addslashes=function(s){return s.split('\\').join('\\\\').split('"').join('\\"');};
	for (var k in this) { 
		if (cont.length) cont[cont.length-1] += ",";
		var v = this[k];
		var vs = ''; 
		if (v.constructor == String) vs = '"' + addslashes(v) + '"';
		else vs=v.toString();
		cont[cont.length]=k + ": " + vs;
	}
	cont = "	" + cont.join("\n").split("\n").join("\n	");
	var s = cont;
	if (this.constructor == Object) s = "{\n"+cont+"\n}";
	if (this.constructor == Array) s = "[\n"+cont+"\n]";
	return s;
};


var o2s = function(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;
};
