把selector字符串转化成过滤函数

QWrap的selector中,把selector转化成过滤函数,实现方式是:
把selector字符串,改装成function的字符串,然后new Function(s)出来。
去除伪类部分的代码,简化成如下:
<script>
var Selector={
	/*
	 * CSS selector属性运算符
	 */
	_operators:{	//以下表达式,aa表示attr值,vv表示比较的值
		'': 'aa',//isTrue|hasValue
		'=': 'aa=="vv"',//equal
		'!=': 'aa!="vv"', //unequal
		'~=': 'aa&&(" "+aa+" ").indexOf(" vv ")>-1',//onePart
		'|=': 'aa&&(aa+"-").indexOf("vv-")==0', //firstPart
		'^=': 'aa&&aa.indexOf("vv")==0', // beginWith
		'$=': 'aa&&aa.lastIndexOf("vv")==aa.length-"vv".length', // endWith
		'*=': 'aa&&aa.indexOf(v)>-1' //contains
	},
	/*
	 * 常用的Element属性
	 */
	_attrGetters:function(){ 
		var o={'class': 'el.className',
			'for': 'el.htmlFor',
			'href':'el.getAttribute("href",2)'};
		var attrs='name,id,className,value,selected,checked,disabled,type,tagName,readOnly'.split(',');
		for(var i=0,a;a=attrs[i];i++) o[a]="el."+a;
		return o;
	}(),
	/* 
	 * 把一个selector字符串转化成一个过滤函数.
	 * @method selector2Filter
	 * @param {string} sSelector: 过滤selector,这个selector里没有关系运算符(", >+~")
	 * @returns {function} : 返回过滤函数。
	 * @example: 
		var fun=selector2Filter("input.aaa");alert(fun);
	 */
	selector2Filter: function(sSelector) {
		var s=sSelector,
			reg=/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/g, //属性选择表达式解析,thanks JQuery
			sFun=[];
		s=s.replace(/\:([\w\-]+)(\(([^)]+)\))?/g,function(a,b,c,d,e){pseudos.push([b,d]);return "";})	//伪类
			.replace(/^\*/g,function(a){//任意tagName缩略写法
				sFun.push('el.nodeType==1');return ''
			})	
			.replace(/^([\w\-]+)/g,function(a){//tagName缩略写法
				sFun.push('el.tagName=="'+a.toUpperCase()+'"');return ''
			})	
			.replace(/([\[(].*)|#(\w+)|\.(\w+)/g, function (a, b, c, d) {	//id缩略写法//className缩略写法
				return b || c&&'[id="'+c+'"]' || d&&'[className~="'+d+'"]';
			})
			.replace(reg,function(a,b,c,d,e){//普通写法[foo][foo=""][foo~=""]等
				var attrGetter=Selector._attrGetters[b] || 'el.getAttribute("'+b+'")';
				sFun.push(Selector._operators[c||''].replace(/aa/g,attrGetter).replace(/vv/g,e||''));
				return '';
			});
		if(s.length) {throw "Unsupported Selector:\n"+sSelector+"\n"+s;}
		if(sFun.length){
			sFun='return ('+sFun.join(")&&(")+');';
			alert(sFun);
			return new Function("el",sFun);
		}
		return function(el){return true;};
	}

};

Selector.selector2Filter('div.aaa.bbb[readOnly]');
</script>

这其实是一个很有用的功能。不明白sizzle为什么不顺便提供出来。

posted on 2011-02-17 18:27  JKisJK  阅读(537)  评论(0编辑  收藏  举报

导航