( function() {
	$=window.$=function (selector,from){
		var selector=selector.replace(/^\s+|\s+$/g,''),sim=/^([#.])?([\w-]+$)/,match,from=from||[document];
		
		//如果只有简单匹配，那么直接返回
		if(match=sim.exec(selector)){
			if(match[1]){
				if(match[1]=='#'){
					return [document.getElementById(match[2])];
				}
				if(match[1]=='.'){
					return $fn.getByCn(match[2]);
				}
			}
				return document.getElementsByTagName(match[2]);
		}
		
		var tokens,tokensExp=/\s*[\s+>~]\s*(?!(?:(?:\w+)?\s*)*['"]\])/g,
			filters=selector.split(tokensExp),//选择器集合，如'#id','.class','tag'
			filterExp=/[#.]?[\w-]+|\*(?!\=)|\[[\w-]+[*^$]?=(['"])\s*[\w-]+(\s+[\w-]+)*\s*\1\]|:[\w-]+(\(\d\))?/g,
			re=[];
		
		//选择器集合，如' ','+','>','~'
		tokens=(tokens=selector.match(tokensExp))&&(tokens.unshift(' '),tokens)||[' '];

		//有逗号？？优先处理
		if(/\s*,\s*/.test(selector)){
			var selectors=selector.split(/\s*,\s*/),i=0;
			while(selectors[i]){
				re=re.concat(arguments.callee(selectors[i],from));
				i++;
			}
			return re;
		}
		
		//过滤器处理函数
		var filtersFn={
			'id':function(id){
				return [document.getElementById(id)];
			},
			'Tn':function (tn,from,onlyOne){
				return $fn.getByTn(tn,from,onlyOne);
			},
			'Cn':function (cn,from,onlyOne){
				return $fn.getByCn(cn,from,onlyOne);
			},
			'Attr':function (attr, from,onlyOne, attrval,others) {
				return $fn.getByAttr(attr, attrval, from,others,onlyOne);
			}
		}

		//选择器处理函数
		var tokensFn={
			' ':function(filter,from){
					var temp=filtersFn[filter[0]](filter[1],from,false,filter[2],filter[3]),re=[],k=0;
					while(temp[k]) {re.push(temp[k]);k++}
					return re;
			},
			'+':function(filter,from){
					return $fn['nextall'+filter[0]](filter[1],from,filter[2],filter[3]);
			},
			'>':function(filter,from){
					var temp=filtersFn[filter[0]](filter[1],$fn.childElems(from),false,filter[2],filter[3]),re=[],k=0;
					while(temp[k]&&re.push(temp[k])) k++;
					return re;
			},
			'~':function(filter,from){
					var temp=filtersFn[filter[0]](filter[1],$fn.siblings(from),false,filter[2],filter[3]),re=[],k=0;
					while(temp[k]&&re.push(temp[k])) k++;
					return re;
			}
		}

		//过滤器转换
		var parseFilter= function (filter){
			var typeObj={'#':'id','.':'Cn','[':'Attr'},type=filter.substr(0,1),match;//???????????TAG
			return typeObj[type]?
					((typeObj[type]=='Attr')?
						//attr
						['Attr',(match=/\[\s*(\w+)\s*([*~^$]?=)\s*(['"])\s*(\w+(\s+\w+)*)\s*\3\]/.exec(filter))[1],match[4],match[2]]
						//else
						:[typeObj[type],filter.substr(1)])
						//TAG
					:['Tn',filter];
			}
		
		var i=0;
		while(i<filters.length){//通过过滤器长度确定查找深度
			var j=0;
			while(from[j]){//从这里开始找
				var temp=[];//保存临时结果
				if(match=filters[i].match(filterExp)){
					var tempfilters=[],m=1;
					for(var l=0;l<match.length;l++){
						tempfilters.push(parseFilter(match[l]));
					}
					temp=temp.concat(tokensFn[tokens[i].replace(/\s*([\s+>~])\s*/,'$1')](tempfilters[0],from[j]));

					if(tokens[i]=='+'&&tempfilters.length==1) temp=[temp[0]];
					
					if(tempfilters.length>1){//如果是复杂过滤器组合， 如：tag.class[attr='val']
						while(tempfilters[m]){
							var tm=tempfilters[m];
							temp=filtersFn[tm[0]](tm[1],temp,false,tm[2],tm[3]);
							if(!tempfilters[++m]&&(tokens[i]=='+')) temp=[temp[0]];
						}
					}
				}
				re=re.concat(temp);
				j++;
			}
			
			if((i<filters.length-1)?true:false) {from=re;re=[]}//是否为下次搜索保存结果
			
			i++;
		}
		
		return re;
		
	}
	$fn =window.$fn = {
		siblings:function (e){
			var re=[],e=(e=e.parentNode.firstChild)&&e.nodeType==1&&e||$fn.next(e);
			while(e&&re.push(e)) e=$fn.next(e);
			return re;
		},
		firstChild:function (e,onlyOne){
			if(onlyOne) return e=(e=e.firstChild)&&e.nodeType==1&&e||$fn.next(e);
			else{
				var e=$fn.childElems(e),re=[],i=0;
				if(e.length>0){
					re=[e[0]];
					while(e[i]){
						var temp=$fn.firstChild(e[i]);
						if(temp) {re.push(temp);re=re.concat($fn.firstChild(temp,true));}
						i++;
					}
				}
				return re;
			}
		},
		lastChild:function (e,onlyOne){
			if(onlyOne) return e=(e=e.lastChild)&&e.nodeType==1&&e||$fn.prev(e);
			else{
				var e=$fn.childElems(e),re=[],i=0;
				if(e.length>0){
					re=[e[0]];
					while(e[i]){
						var temp=$fn.lastChild(e[i]);
						if(temp) {re.push(temp);re=re.concat($fn.lastChild(temp,true));}
						i++;
					}
				}
				return re;
			}
		},
		next:function (e){
			do{
				e=e.nextSibling;
			}while(e&&e.nodeType!=1);
			return e;
		} ,
		prev:function (e){
			do{
				e=e.previousSibling;
			}while(e&&e.nodeType!=1);
			return e;
		},
		nextCn:function  (cn,e){
			do{
				e=next(e);
			}while(e&&!$fn.hasClass(cn,e));
			return e;
		},
		prevCn:function (cn,e){
			do{
				e=prev(e);
			}while(e&&!$fn.hasClass(cn,e))
			return e;
		},
		nextallCn:function (cn,e,withself){
			var re=withself?[e]:[];
			while(e&&(e=$fn.nextCn(cn,e))) re.push(e);
			return re;
		},
		prevallCn:function (cn,e,withself){
			var re=withself?[e]:[];
			while(e&&(e=$fn.prevCn(cn,e))) re.push(e);
			return re;
		},
		nextTn:function (tn,e){
			var tn=tn.toUpperCase();
			do{
				e=$fn.next(e);
			}while(e&&e.nodeName.toUpperCase()!==tn);
			return e;
		},
		prevTn:function (tn,e){
			var tn=tn.toUpperCase();
			do{
				e=$fn.prev(e);
			}while(e&&e.nodeName.toUpperCase()!==tn);
			return e;
		},
		nextallTn:function (tn,e,withself){
			var re=withself?[e]:[];
			while(e&&(e=$fn.nextTn(tn,e))) re.push(e);
			return re;
		},
		prevallTn:function (tn,e,withself){
			var re=withself?[e]:[];
			while(e&&(e=$fn.prevTn(tn,e))) re.push(e);
			return re;
		},
		nextAttr:function (attr,attrval,e){
			do{
				e=$fn.next(e);
			}while(e&&(e.$fn.getAttibute(attr)!=attrval));
			return e;
		},
		prevAttr:function (attr,attrval,e){
			do{
				e=$fn.prev(e);
			}while(e&&(e.$fn.getAttibute(attr)!=attrval));
			return e;
		},
		nextallAttr:function (attr,attrval,e,withself){
			var re=withself?[e]:[];
			while(e&&(e=$fn.nextAttr(tn,e))) re.push(e);
			return re;
		},
		prevallAttr:function (attr,attrval,e,withself){
			var re=withself?[e]:[];
			while(e&&(e=$fn.prevAttr(tn,e))) re.push(e);
			return re;
		},
		childElems:function (e){
			var re=[],e=(e=e.firstChild)&&e.nodeType==1&&e||$fn.next(e);
			while(e&&re.push(e)) e=$fn.next(e);
			return re;
		},
		getByCn:function (cn, from,onlyOne) {
			var re = [],from=from?((from.nodeType==1)?from.getElementsByTagName('*'):from):document.getElementsByTagName('*');
			for ( var i = 0, l =from.length ; i < l; i++) {
				if ($fn.hasClass(cn, from[i])){
					re.push(from[i]);
					if(onlyOne) break;
				}
			}
			return re;
		},
		getByTn:function (tn, from,onlyOne) {
			var re=[],from=from?((from.nodeType==1)?from.getElementsByTagName('*'):from):document.getElementsByTagName('*');
			if(tn=='*') {
				var i=0;
				while(from[i]) {re.push(from[i]);i++;}
			}else{
				var tn=tn.toUpperCase();
				for ( var i = 0, l =from.length ; i < l; i++) {
					if (from[i].nodeName.toUpperCase()==tn){
						re.push(from[i]);
						if(onlyOne) break;
					}
				}
			}
			return re;
		},
		getByAttr:function (attr, attrval, from,moreopt,onlyOne) {
			var re = [],from=from?((from.nodeType==1)?from.getElementsByTagName('*'):from):document.getElementsByTagName('*'),exp;
			if(attr=='class'||attr=='className') return $fn.getByCn(attrval,from,onlyOne);
			switch (moreopt){
				case '*=':exp=new RegExp(attrval);break;
				case '^=':exp=new RegExp("^" + attrval );break;
				case '$=':exp=new RegExp( attrval + "$");break;
				default:exp=new RegExp("^" + attrval + "$");
			}
			for ( var i = 0, l = from.length; i < l; i++) {
				var val = from[i].getAttribute(attr);
				if (val&&exp.test(val.replace(/^\s+|\s+$/g,''))){
					re.push(from[i]);
					if(onlyOne) break;
				}
			}
			return re;
		},
		addClass : function(arr,cl) {
			$fn.each(arr, function() {
				if (this.className.indexOf(' ') == -1)
					this.className = cl;
				else
					this.className += ' ' + cl;
			})
		},
		css : function(arr,JSON) {
			$fn.each(arr, function() {
				if (this.nodeType == 1) {
					for (x in JSON) {
						this.style[x] = JSON[x];
					}
				}
			})
		},
		getStyle:function(e,name){
			if(e.style[name]) return e.style[name];
			if(e.currentStyle) return e.currentStyle[name];
			if(document.defaultView && document.defaultView.getComputedStyle)
				var styles=document.defaultView.getComputedStyle(e,'');
			return styles&&styles.getPropertyValue[name];
		},
		setOpacity:function(e,level){
				//e.style.filters.alpha.opacity = level;
				//e.style.filters.item("Alpha").Opacity=level;
				e.style.filter = "alpha(opacity=" + level + ")"; 
				e.style.opacity = level / 100;
		},
		each : function(arr,fn) {
			var index = 0;
			for ( var i = 0, l = arr.length; i < l; i++) {
				fn.call(arr[i], index);
				index++;
			}
		},
		delArr : function(val, arr) {
			for ( var i = 0, l = arr.length; i < l; i++) {
				if (arr[i] === val) {
					delete arr[i];
				}
			}
			return $fn.cleanArr(arr);
		},
		cleanArr : function(arr) {
			var newarr = [];
			for ( var i = 0, l = arr.length; i < l; i++) {
				if ($fn.beFalse(arr[i]))
					continue;
				newarr.push(arr[i]);
			}
			return newarr;
		},
		posInArr : function(val, arr) {
			var i = 0;
			for ( var l = arr.length; i < l; i++) {
				if (val === arr[i])
					break;
			}
			return i;
		},
		hasClass : function(val, elem) {
			var re = new RegExp("(^|\\s)" + val + "(\\s|$$)");
			if (re.test(elem.className))
				return true;
		},
		beFalse : function(str) {
			return str == undefined || str === false || /^\s+$/.test(str) || str.length === 0;
		},
		isDom : function(obj) {
			if (obj.nodeType == 1||(obj.length && obj[obj.length - 1] !== undefined
					&& !obj.nodeType)) {
				for ( var i = 0, l = obj.length; i < l; i++) {
					if (obj[i] && obj[i].nodeType == 1)
						continue;
					return false;
				}
				return true;
			}
		},
		ready : function(fn) {
			if (!document || !document.getElementById
					|| !document.getElementsByTagName || !document.body) {
				setTimeout( function() {
					return $fn.ready(fn)
				}, 10);
			} else
				fn();
		},
		uniqArr:function(arr){
			for(var i=0,l=arr.length;i<l;i++){
				var obj=arr[i];
				for(var j=i+1;j<l;j++){
					if(obj===arr[j])
						delete arr[j];
				}
			}
			return arr=$fn.cleanArr(arr);
		},
		addEvent:function ( obj, type, fn ) {
			 if (obj.addEventListener)
				 obj.addEventListener( type, fn, false );
			 else if (obj.attachEvent) {
				 obj["e"+type+fn] = fn;
				 obj.attachEvent( "on"+type, function() { obj["e"+type+fn]()} );
			 }
		},
		removeEvent:function ( obj, eType, fn ) {
			 if (obj.removeEventListener)
				 obj.removeEventListener( eType, fn, false );
			 else if (obj.detachEvent) {
				 obj.detachEvent( "on"+eType, obj["e"+eType+fn] );
				 obj["e"+eType+fn] = null;
			 }
		},
		getX:function (e){
			return e.pageX ? e.pageX : e.clientX + document.body.scrollLeft - document.body.clientLeft;
		},
		getY:function (e){
			return e.pageY ? e.pageY : e.clientY + document.body.scrollTop  - document.body.clientTop;
		},
		getL:function (o){
			var l = 0;
			while(o){
				l += o.offsetLeft - o.scrollLeft;
				o = o.offsetParent;
			}
			return(l);
		},
		getT:function (o){
			var t = 0;
			while(o){
				t += o.offsetTop - o.scrollTop;
				o = o.offsetParent;
			}
			return(t);
		},
		getOffsetX:function(e){
			return ( e && e.layerX ) || window.event.offsetX;
		},
		getOffsetY:function(e){
			return ( e && e.layerY ) || window.event.offsetY;
		},
		getTarget:function(e){
			e=e||window.event;
			return e.target||e.srcElement;
		},
		scrollX:function () {
			var de = document.documentElement;
			return self.pageXOffset ||
				( de && de.scrollLeft ) ||
				document.body.scrollLeft;
		},
		scrollY:function () {
			var de = document.documentElement;
			return self.pageYOffset ||
				( de && de.scrollTop ) ||
				document.body.scrollTop;
		},
		windowHeight:function () {
			var de = document.documentElement;
			return self.innerHeight ||
				( de && de.clientHeight ) ||
				document.body.clientHeight;
		},
		windowWidth:function () {
			var de = document.documentElement;
			return self.innerWidth ||
				( de && de.clientWidth ) ||
				document.body.clientWidth;
		},
		cleanWS:function ( elem ,deep) {
			elem=elem||document;
			var cur=elem.firstChild,next=null;
			while(cur){
				if(cur.nodeType==3&&!/\S/.test(cur.nodeValue)){
					next=cur.nextSibling;
					elem.removeChild(cur);
				}else if(cur.nodeType==1&&!!deep){
					arguments.callee(cur,true);
				}
				cur=cur.nextSibling || next;
			}
		},
		uniqueNum:(function(){
			var i=0;
			return function(last){
				if(last) return i 
				else return ++i
			}
		})(),
		randomNum:function (min,max){
			var range = max - min;
			return min + Math.round(Math.random()*range);
		},
		extand:function(from,to){
			for(var p in from){
				to[p]=from[p];
			}
		},
		toggle:function(obj,type,fn1,fn2){
			var i=0;
			$fn.addEvent(obj,type,function(){
				if(i%2==0) fn1();
				else fn2();
				i++;
			})
		},
		animate:{
			/*slide:function(obj,from,to,type,sp){
				var sp=sp||1.1;
				if(from<to){
					from=Math.ceil(to-(to-from)/sp);
					obj.style[type]=from+'px';
					setTimeout(function(){$fn.animate.slide(obj,from,to,type,sp)},10)
				}else{
					obj.style[type]=to+'px';
				}
			},*/
			go:function(obj,json){
				
			},
			slideBack:function(obj,from,type,sp){
				var sp=sp||1.1;
				if(from>0){
					from=Math.floor(from/sp);
					obj.style[type]=from+'px';
					setTimeout(function(){$fn.animate.slideBack(obj,from,type,sp)},10)
				}else{
					obj.style[type]=0;
				}
			},
			fadeIn:function(obj,sp){
				var sp=sp||1,level=0;
				(function(){
					level+=sp;
					if(level>100) level=100;
					$fn.setOpacity(obj,level);
					if(level!=100) setTimeout(arguments.callee,10)
				})();
			},
			fadeOut:function(obj,sp){
				var sp=sp||1,level=100;
				(function(){
					level-=sp;
					if(level<0) level=0;
					$fn.setOpacity(obj,level);
					if(level!=0) setTimeout(arguments.callee,10)
				})();
			}
		}
	}
})()
