javascript框架选择器原理 小弟菜菜滴,看了PRO和JQ的选择器,看的晕晕的,不明白其中原理,有哪个能写个裸体版的选择器,让小虾们看看原理 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 没什么吧就是具备一些简单算法的dom节点选择而易啊。 <pre>/** * querySelector(sSelector,[pEl]): 得到pEl下的符合过滤条件的HTML Elements. * example: var els=IUIDom.querySelector("li input.aaa");els.forEach(function(a){a.style.backgroundColor='red';}); * @param {string} sSelector: 过滤selector, 目前支持的运算符: * √ E √ .class √ #id √ E F √ E > √ E + F √ E[attr] √ E[attr=val] √ E[attr~=val] √ E[attr|=val] √ :first-child √ :link :visited :lang() :before ::before :after ::after :first-letter ::first-letter :first-line ::first-line -------------------------- 下面的选择器属于CSS3 (上面的在以前的版本中) E[attr^=val] √ E[attr$=val] √ E[attr*=val] √ E ~ F √ :root :last-child √ :only-child √ :nth-child() √ :nth-last-child() √ :first-of-type √ :last-of-type √ :only-of-type √ :nth-of-type() √ :nth-last-of-type() √ :empty √ :not() √ :target :enabled √ :disabled √ :checked √ -------------------------- 其它 :parent √ -------------------------- 示例: "ul li" ">ul li" "ul li:first-child" "li:nth-child(2n)"----nth支持参数如:'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' * @param {HTMLElement} pEl: 容器对象 * @returns {array} : 返回elements数组。 */ </pre><script>/** * @IUI * @author: JK([email protected]) * @create-date : 2008-09-18 *///{prepare------------------------------------ String.prototype.trim=function(){ return this.replace(/^[\s\xa0\u3000]+|[\u3000\xa0\s]+$/g, "") }; if(!Array.prototype.forEach){ Array.prototype.forEach=function(callback,pThis){ for (var i =0,len=this.length;i<len;i++) callback.call(pThis,this[i],i,this); }; }//------------------------------------prepare}/** * Dom: IUI.Dom * @version: 0.0.1 */(function(){window.IUIDom={ VERSION:"0.0.1", /** * selector2Filter(sSelector): 把一个selector字符串转化成一个过滤函数. * example: var fun=IUIDom.selector2Filter("input.aaa");alert(fun); * @param {string} sSelector: 过滤selector,目前只支持以下几种选择符:"逗号-或" "空格-与" "点-className" "abc-tagName" "#-id". * @returns {function} : 返回过滤函数。 */ selector2Filter:function(sSelector){ return s2f(sSelector); }, /** * querySelector(sSelector,[pEl]): 得到pEl下的符合过滤条件的HTML Elements. pEl是默认是document. * example: var els=IUIDom.querySelector("li input.aaa");els.forEach(function(a){a.style.backgroundColor='red';}); * @param {string} sSelector: 过滤selector,目前只支持以下几种选择符:"逗号-或" "空格-与" "点-className" "abc-tagName" "#-id". * @param {HTMLElement} pEl: 容器对象 * @returns {array} : 返回elements数组。 */ querySelector:function(sSelector,pEl){ if(typeof(pEl)=="string" && !(pEl=$(pEl))) return []; pEl=pEl||document; var groups=sSelector.trim().split(","); var els=querySimpleSelector(groups[0],pEl); for(var i=1;i<groups.length;i++){ var els2=querySimpleSelector(groups[i],pEl); els=els.concatUnique(els2); } return els; }};/** fasterFilter(arr,callback) : 对arr里的元素进行过滤,fun(a)快于fun.call(thisP) @see IUI.filter(arr,callback) */function fasterFilter(arr,callback){ var rlt=[],n=0; for(var i=0,len=arr.length;i<len;i++) { var el=arr[i]; if(callback(el)) rlt[n++]=el; } return rlt;};if(document.createElement("a").contains){ var fasterContains=function(pEl,el){ return pEl.contains(el);};}else{ var fasterContains=function(pEl,el){ return (pEl.compareDocumentPosition(el) & 16);};}/** * nth(sN): 返回一个判断函数,来判断一个数是否满足某表达式。 * @param { string } sN: 表达式,如:'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' * @return { function } function(i){return i满足sN}: 返回判断函数。 */function nth(sN){ if(sN=="even") return function(i){return i%2==0;}; if(sN=="odd") return function(i){return i%2!=0;}; sN=sN.replace(/(^|\D+)n/g,"$11n"); if(!(/n/.test(sN))) { return function(i){return i==sN;} } else{ var arr=sN.split("n"); var a=parseInt(arr[0]),b=parseInt(arr[1]||"0"); return function(i){var n=(i-b)/a; return n>=0 && parseInt(n)==n;}; }}/** * getNth(el,reverse): 得到一个元素的nth值。 * @param { element } el: HTML Element * @param { boolean } : 是否反向算--如果为真,相当于nth-last * @return { int } : 返回nth值 */function getNth(el,reverse){ var pEl=el.parentNode; if(pEl.__lastQueryDate!=_queryDate){ var els=pEl.childNodes,idx=0; for(var i=0,len=els.length;i<len;i++){ var elI=els[i]; if("tagName" in elI) elI.__nodeIndex=++idx; }; pEl.__lastQueryDate=_queryDate; pEl.__childNodesLength=idx; } if(reverse) return pEl.__childNodesLength-el.__nodeIndex+1; else return el.__nodeIndex;}/** * CSS selector属性运算符---(为了提高速度,以下表达式的结果如果返回true,则表示不满足条件) */var Ops={ '': '!v1',//isTrue|hasValue '=': 'v1!="v2"',//equal '!=': 'v1=="v2"', //unequal '~=': '!v1||(" "+v1+" ").indexOf(" v2 ")<0',//onePart '|=': '!v1||(v1+"-").indexOf("v2-")!=0', //firstPart '^=': '!v1||v1.indexOf("v2")!=0', // beginWith '$=': '!v1||v1.lastIndexOf("v2")!=v1.length-"v2".length', // endWith '*=': '!v1||v1.indexOf("v2")<0' //contains};/** * CSS 伪类逻辑 */var Pseudos={ "first-child":function(a){return (a.parentNode.getElementsByTagName("*")[0]==a);}, "last-child":function(a){var oLast=a.parentNode.lastChild; return oLast==a || (!oLast.tagName && oLast.previousSibling==a);}, "only-child":function(a){var els=a.parentNode.childNodes; return els.length<3 && fasterFilter(els,function(b){return "tagName" in b;}).length==1 ;}, "nth-child":function(a,iFlt){return iFlt(getNth(a,false)); }, "nth-last-child":function(a,iFlt){return iFlt(getNth(a,true)); }, "first-of-type":function(a){ var tag=a.tagName; var el=a; while(el=el.previousSlibling){if(el.tagName==tag) return false;} return true;}, "last-of-type":function(a){ var tag=a.tagName; var el=a; while(el=el.nextSibling){if(el.tagName==tag) return false;} return true; }, "only-of-type":function(a){var els=a.parentNode.childNodes; for(var i=els.length-1;i>-1;i--){if(els[i].tagName==a.tagName && els[i]!=a) return false;} return true;}, "nth-of-type":function(a,iFlt){var idx=1;var el=a;while(el=el.previousSibling) {if(el.tagName==a.tagName) idx++;} return iFlt(idx); }, "nth-last-of-type":function(a,iFlt){var idx=1;var el=a;while(el=el.nextSibling) {if(el.tagName==a.tagName) idx++;} return iFlt(idx); }, "empty":function(a){ return !a.firstChild; }, "parent":function(a){ return !!a.firstChild; }, "not":function(a,sFlt){ return !sFlt(a); }, "enabled":function(a){ return !a.disabled; }, "disabled":function(a){ return a.disabled; }, "checked":function(a){ return a.checked; }};/** * 常用的Element属性 */var ElAttrs={ 'class': 'className;', 'for': 'htmlFor;'};"name,id,className,value,selected,checked,disabled,type,tagName,readOnly".split(",").forEach(function (a){ElAttrs[a]=a;});/** * CSS selector关系运算符 */var Relations={ //子子孙孙 " ":function(el,filter,tagName){ var els=el.getElementsByTagName(tagName||"*"); return fasterFilter(els,filter); }, //儿子们 ">":function(el,filter){ var nodes=el.childNodes; var els=[]; for(var i=0,len=nodes.length;i<len;i++){ var elI=nodes[i]; if(("tagName" in elI) && filter(elI)) els.push(elI); } return els; }, //第一个弟弟 "+":function(el,filter){ var elI=el; while(elI=elI.nextSibling){ if("tagName" in elI){ if(filter(elI)) return [elI]; else return []; } } return []; }, //弟弟们 "~":function(el,filter){ var arr=[]; var elI=el; while(elI=elI.nextSibling){ if(elI.tagName && filter(elI)) arr.push(elI); } return arr; }} /** * s2f(sSelector): 由一个selector得到一个过滤函数filter,这个selector里没有关系运算符(", >+~") */function s2f(sSelector){ var attrs=[]; eval("var flts=[];");//防止压缩被更名 var s=sSelector.trim(); s=s.replace(/\:([\w\-]+)(\(([^)]+)\))?/g,function(a,b,c,d,e){flts.push([b,d]);return "";});//伪类 s=s.replace(/^\*/g,'[tagName]');//任意tagName缩略写法 s=s.replace(/^([\w\-]+)/g,function(a,b){return '[tagName="'+b.toUpperCase()+'"]';});//tagName缩略写法 s=s.replace(/\.([\w\-]+)/g,'[className~="$1"]');//className缩略写法 s=s.replace(/\#([\w\-]+)/g,'[id="$1"]');//id缩略写法 var reg=/\[\s*([\w\-]+)\s*([!~|^$*]?\=)?\s*(?:"([^\]]*)")?\s*\]/g; s=s.replace(reg,function(a,b,c,d){attrs.push([b,c||"",d||""]);return "";});//普通写法[foo][foo=""][foo~=""]等 if(!(/^\s*$/).test(s)) {var ex="Unsupported by IUI Selector:\n"+sSelector+"\n-"+s; alert(ex);throw ex;} var sFun=[]; for(var i=0;i<attrs.length;i++){//属性过滤 var attr=attrs[i]; sFun.push('var v1=a.'+(ElAttrs[attr[0]]||(attr[0]+'||a.getAttribute("'+attr[0]+'")'))+";", 'if('+Ops[attr[1]].replace(/v2/g,attr[2])+') return false;'); } for(var i=0;i<flts.length;i++) {//伪类过滤 var fun=Pseudos[flts[i][0]]; if(!fun) {var ex="Unsupported by IUI Selector:\n"+flts[0]+"\n"+s; alert(ex);throw ex;} flts[i][2]=fun; eval('var flt'+i+'=flts['+i+'][2];');//降低层次深度,以提高效率 if(flts[i][0].indexOf("nth-")==0){ flts[i][3]=nth(flts[i][1]); } else if(flts[i][0]=="not"){ flts[i][3]=s2f(flts[i][1]); } if(flts[i][3]){ eval('var subFlt'+i+'=flts['+i+'][3];'); sFun.push('if (!flt'+i+'(a,subFlt'+i+')) return false;'); } else{ sFun.push('if (!flt'+i+'(a)) return false;'); } } sFun.push("return true;"); eval("var attrFlt= function(a){"+sFun.join("\n")+"}"); return attrFlt;};/** * {date} _queryDate: 全局变量,标记下最后一次querySelector的时间 */var _queryDate=1;/** * querySimpleSelector(sSelector,pEl): 得到pEl下的符合过滤条件的HTML Elements. * sSelector里没有","运算符 * pEl是默认是document.body * @see: querySelector。 */function querySimpleSelector(sSelector,pEl){ _queryDate=new Date()*1; var sltors=[]; var reg=/(^|\s*[>+~ ]\s*)(([\w\-\:.#*]+|\([^\)]*\)|\[[^\]]*\])+)(?=($|\s*[>+~ ]\s*))/g; var s=sSelector.trim().replace(reg,function(a,b,c,d){sltors.push([b,c]);return "";}); if(!(/^\s*$/).test(s)) {var ex="Unsupported by IUI Selector:\n"+sSelector+"\n--"+s; alert(ex);throw ex;} var els=[pEl]; var pOp=null;//前一个关系运算符 for(var i=0;i<sltors.length;i++){ var els2=[]; var sltor=sltors[i]; var op=sltor[0].trim() || " "; if (op==" " && pOp==" ")//除冗以提高效率----某些特殊情况(如:为" div~div div"第二个空格除冗),除冗会不够彻底。为了保证绝大多数用法的效率,只能放弃理论追求了 { for(var j=1;j<els.length;j++) { if(fasterContains(els[j-1],els[j])){ els.splice(j,1); j--; } } } var tagName="*"; if(op==" ") { sltor[1]=sltor[1].replace(/^[\w\-]+/,function(a){tagName=a;return ""}); } var filter=s2f(sltor[1]); var relation=Relations[op]; if(op=="~"){ for(var j=0;j<els.length;j++){ var elsj=relation(els[j],filter,tagName); els2=els2.length && els2.concatUnique(elsj) || elsj; //需要除重 } } else{ for(var j=0;j<els.length;j++){ var elsj=relation(els[j],filter,tagName); els2=els2.concat(elsj);//不除重 } } els=els2; pOp=op; } return els;};})();</script>更多内容,可以参考:http://download.csdn.net/source/997377 YUI的selector是从下往上找的,我当时写的时候,也是从下往上找,后来还是改成从上往下找,导致有时候除重不够彻底。不足中 大家用什么jQuery消息提示插件,能使消息tips自动调整位置一直在某个自定义的容器内? 散分,标题要BUG,你们这样才肯进来o(╯□╰)o javascript用表格显示时间问题 帮我释疑,谢谢 寻找控件 Ext的Grid,能进行服务器端排序吗? 这句document.write这么写啊为什么老是提示缺少")" 怎样实现用windows.open打开窗口在指定位置处? 谁知道怎么控制单选钮吗? 想知道这段代码的都是什么意思?请帮忙解答,谢谢各位了 定义图片边距及下方复选框的实现 sina图片编辑器不能用
/**
* querySelector(sSelector,[pEl]): 得到pEl下的符合过滤条件的HTML Elements.
* example: var els=IUIDom.querySelector("li input.aaa");els.forEach(function(a){a.style.backgroundColor='red';});
* @param {string} sSelector: 过滤selector, 目前支持的运算符:
* √
E √
.class √
#id √
E F √
E > √
E + F √
E[attr] √
E[attr=val] √
E[attr~=val] √
E[attr|=val] √
:first-child √
:link
:visited
:lang()
:before
::before
:after
::after
:first-letter
::first-letter
:first-line
::first-line
--------------------------
下面的选择器属于CSS3 (上面的在以前的版本中)
E[attr^=val] √
E[attr$=val] √
E[attr*=val] √
E ~ F √
:root
:last-child √
:only-child √
:nth-child() √
:nth-last-child() √
:first-of-type √
:last-of-type √
:only-of-type √
:nth-of-type() √
:nth-last-of-type() √
:empty √
:not() √
:target
:enabled √
:disabled √
:checked √
--------------------------
其它
:parent √
--------------------------
示例:
"ul li"
">ul li"
"ul li:first-child"
"li:nth-child(2n)"----nth支持参数如:'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
* @param {HTMLElement} pEl: 容器对象
* @returns {array} : 返回elements数组。
*/
</pre><script>
/**
* @IUI
* @author: JK([email protected])
* @create-date : 2008-09-18
*///{prepare------------------------------------
String.prototype.trim=function(){
return this.replace(/^[\s\xa0\u3000]+|[\u3000\xa0\s]+$/g, "")
}; if(!Array.prototype.forEach){
Array.prototype.forEach=function(callback,pThis){
for (var i =0,len=this.length;i<len;i++) callback.call(pThis,this[i],i,this);
};
}
//------------------------------------prepare}/**
* Dom: IUI.Dom
* @version: 0.0.1
*/
(function(){
window.IUIDom=
{
VERSION:"0.0.1", /**
* selector2Filter(sSelector): 把一个selector字符串转化成一个过滤函数.
* example: var fun=IUIDom.selector2Filter("input.aaa");alert(fun);
* @param {string} sSelector: 过滤selector,目前只支持以下几种选择符:"逗号-或" "空格-与" "点-className" "abc-tagName" "#-id".
* @returns {function} : 返回过滤函数。
*/
selector2Filter:function(sSelector){
return s2f(sSelector);
},
/**
* querySelector(sSelector,[pEl]): 得到pEl下的符合过滤条件的HTML Elements. pEl是默认是document.
* example: var els=IUIDom.querySelector("li input.aaa");els.forEach(function(a){a.style.backgroundColor='red';});
* @param {string} sSelector: 过滤selector,目前只支持以下几种选择符:"逗号-或" "空格-与" "点-className" "abc-tagName" "#-id".
* @param {HTMLElement} pEl: 容器对象
* @returns {array} : 返回elements数组。
*/
querySelector:function(sSelector,pEl){
if(typeof(pEl)=="string" && !(pEl=$(pEl))) return [];
pEl=pEl||document;
var groups=sSelector.trim().split(",");
var els=querySimpleSelector(groups[0],pEl);
for(var i=1;i<groups.length;i++){
var els2=querySimpleSelector(groups[i],pEl);
els=els.concatUnique(els2);
}
return els;
}
};
/**
fasterFilter(arr,callback) : 对arr里的元素进行过滤,fun(a)快于fun.call(thisP)
@see IUI.filter(arr,callback)
*/
function fasterFilter(arr,callback){
var rlt=[],n=0;
for(var i=0,len=arr.length;i<len;i++) {
var el=arr[i];
if(callback(el)) rlt[n++]=el;
}
return rlt;
};if(document.createElement("a").contains){
var fasterContains=function(pEl,el){ return pEl.contains(el);};
}
else{
var fasterContains=function(pEl,el){ return (pEl.compareDocumentPosition(el) & 16);};
}/**
* nth(sN): 返回一个判断函数,来判断一个数是否满足某表达式。
* @param { string } sN: 表达式,如:'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
* @return { function } function(i){return i满足sN}: 返回判断函数。
*/
function nth(sN){
if(sN=="even") return function(i){return i%2==0;};
if(sN=="odd") return function(i){return i%2!=0;};
sN=sN.replace(/(^|\D+)n/g,"$11n");
if(!(/n/.test(sN))) {
return function(i){return i==sN;}
}
else{
var arr=sN.split("n");
var a=parseInt(arr[0]),b=parseInt(arr[1]||"0");
return function(i){var n=(i-b)/a; return n>=0 && parseInt(n)==n;};
}
}/**
* getNth(el,reverse): 得到一个元素的nth值。
* @param { element } el: HTML Element
* @param { boolean } : 是否反向算--如果为真,相当于nth-last
* @return { int } : 返回nth值
*/
function getNth(el,reverse){
var pEl=el.parentNode;
if(pEl.__lastQueryDate!=_queryDate){
var els=pEl.childNodes,idx=0;
for(var i=0,len=els.length;i<len;i++){
var elI=els[i];
if("tagName" in elI) elI.__nodeIndex=++idx;
};
pEl.__lastQueryDate=_queryDate;
pEl.__childNodesLength=idx;
}
if(reverse) return pEl.__childNodesLength-el.__nodeIndex+1;
else return el.__nodeIndex;
}/**
* CSS selector属性运算符---(为了提高速度,以下表达式的结果如果返回true,则表示不满足条件)
*/
var Ops={
'': '!v1',//isTrue|hasValue
'=': 'v1!="v2"',//equal
'!=': 'v1=="v2"', //unequal
'~=': '!v1||(" "+v1+" ").indexOf(" v2 ")<0',//onePart
'|=': '!v1||(v1+"-").indexOf("v2-")!=0', //firstPart
'^=': '!v1||v1.indexOf("v2")!=0', // beginWith
'$=': '!v1||v1.lastIndexOf("v2")!=v1.length-"v2".length', // endWith
'*=': '!v1||v1.indexOf("v2")<0' //contains
};
/**
* CSS 伪类逻辑
*/
var Pseudos={
"first-child":function(a){return (a.parentNode.getElementsByTagName("*")[0]==a);},
"last-child":function(a){var oLast=a.parentNode.lastChild; return oLast==a || (!oLast.tagName && oLast.previousSibling==a);},
"only-child":function(a){var els=a.parentNode.childNodes; return els.length<3 && fasterFilter(els,function(b){return "tagName" in b;}).length==1 ;},
"nth-child":function(a,iFlt){return iFlt(getNth(a,false)); },
"nth-last-child":function(a,iFlt){return iFlt(getNth(a,true)); },
"first-of-type":function(a){ var tag=a.tagName; var el=a; while(el=el.previousSlibling){if(el.tagName==tag) return false;} return true;},
"last-of-type":function(a){ var tag=a.tagName; var el=a; while(el=el.nextSibling){if(el.tagName==tag) return false;} return true; },
"only-of-type":function(a){var els=a.parentNode.childNodes; for(var i=els.length-1;i>-1;i--){if(els[i].tagName==a.tagName && els[i]!=a) return false;} return true;},
"nth-of-type":function(a,iFlt){var idx=1;var el=a;while(el=el.previousSibling) {if(el.tagName==a.tagName) idx++;} return iFlt(idx); },
"nth-last-of-type":function(a,iFlt){var idx=1;var el=a;while(el=el.nextSibling) {if(el.tagName==a.tagName) idx++;} return iFlt(idx); },
"empty":function(a){ return !a.firstChild; },
"parent":function(a){ return !!a.firstChild; },
"not":function(a,sFlt){ return !sFlt(a); },
"enabled":function(a){ return !a.disabled; },
"disabled":function(a){ return a.disabled; },
"checked":function(a){ return a.checked; }
};/**
* 常用的Element属性
*/
var ElAttrs={
'class': 'className;',
'for': 'htmlFor;'
};
"name,id,className,value,selected,checked,disabled,type,tagName,readOnly".split(",").forEach(function (a){ElAttrs[a]=a;});
/**
* CSS selector关系运算符
*/
var Relations={
//子子孙孙
" ":function(el,filter,tagName){
var els=el.getElementsByTagName(tagName||"*");
return fasterFilter(els,filter);
},
//儿子们
">":function(el,filter){
var nodes=el.childNodes;
var els=[];
for(var i=0,len=nodes.length;i<len;i++){
var elI=nodes[i];
if(("tagName" in elI) && filter(elI)) els.push(elI);
}
return els;
},
//第一个弟弟
"+":function(el,filter){
var elI=el;
while(elI=elI.nextSibling){
if("tagName" in elI){
if(filter(elI)) return [elI];
else return [];
}
}
return [];
},
//弟弟们
"~":function(el,filter){
var arr=[];
var elI=el;
while(elI=elI.nextSibling){
if(elI.tagName && filter(elI)) arr.push(elI);
}
return arr;
}
}
* s2f(sSelector): 由一个selector得到一个过滤函数filter,这个selector里没有关系运算符(", >+~")
*/
function s2f(sSelector){
var attrs=[];
eval("var flts=[];");//防止压缩被更名
var s=sSelector.trim();
s=s.replace(/\:([\w\-]+)(\(([^)]+)\))?/g,function(a,b,c,d,e){flts.push([b,d]);return "";});//伪类
s=s.replace(/^\*/g,'[tagName]');//任意tagName缩略写法
s=s.replace(/^([\w\-]+)/g,function(a,b){return '[tagName="'+b.toUpperCase()+'"]';});//tagName缩略写法
s=s.replace(/\.([\w\-]+)/g,'[className~="$1"]');//className缩略写法
s=s.replace(/\#([\w\-]+)/g,'[id="$1"]');//id缩略写法
var reg=/\[\s*([\w\-]+)\s*([!~|^$*]?\=)?\s*(?:"([^\]]*)")?\s*\]/g;
s=s.replace(reg,function(a,b,c,d){attrs.push([b,c||"",d||""]);return "";});//普通写法[foo][foo=""][foo~=""]等
if(!(/^\s*$/).test(s)) {var ex="Unsupported by IUI Selector:\n"+sSelector+"\n-"+s; alert(ex);throw ex;}
var sFun=[];
for(var i=0;i<attrs.length;i++){//属性过滤
var attr=attrs[i];
sFun.push('var v1=a.'+(ElAttrs[attr[0]]||(attr[0]+'||a.getAttribute("'+attr[0]+'")'))+";",
'if('+Ops[attr[1]].replace(/v2/g,attr[2])+') return false;');
}
for(var i=0;i<flts.length;i++) {//伪类过滤
var fun=Pseudos[flts[i][0]];
if(!fun) {var ex="Unsupported by IUI Selector:\n"+flts[0]+"\n"+s; alert(ex);throw ex;}
flts[i][2]=fun;
eval('var flt'+i+'=flts['+i+'][2];');//降低层次深度,以提高效率
if(flts[i][0].indexOf("nth-")==0){
flts[i][3]=nth(flts[i][1]);
}
else if(flts[i][0]=="not"){
flts[i][3]=s2f(flts[i][1]);
}
if(flts[i][3]){
eval('var subFlt'+i+'=flts['+i+'][3];');
sFun.push('if (!flt'+i+'(a,subFlt'+i+')) return false;');
}
else{
sFun.push('if (!flt'+i+'(a)) return false;');
}
}
sFun.push("return true;"); eval("var attrFlt= function(a){"+sFun.join("\n")+"}");
return attrFlt;
};/**
* {date} _queryDate: 全局变量,标记下最后一次querySelector的时间
*/
var _queryDate=1;
/**
* querySimpleSelector(sSelector,pEl): 得到pEl下的符合过滤条件的HTML Elements.
* sSelector里没有","运算符
* pEl是默认是document.body
* @see: querySelector。
*/
function querySimpleSelector(sSelector,pEl){
_queryDate=new Date()*1;
var sltors=[];
var reg=/(^|\s*[>+~ ]\s*)(([\w\-\:.#*]+|\([^\)]*\)|\[[^\]]*\])+)(?=($|\s*[>+~ ]\s*))/g;
var s=sSelector.trim().replace(reg,function(a,b,c,d){sltors.push([b,c]);return "";});
if(!(/^\s*$/).test(s)) {var ex="Unsupported by IUI Selector:\n"+sSelector+"\n--"+s; alert(ex);throw ex;}
var els=[pEl];
var pOp=null;//前一个关系运算符
for(var i=0;i<sltors.length;i++){
var els2=[];
var sltor=sltors[i];
var op=sltor[0].trim() || " ";
if (op==" " && pOp==" ")//除冗以提高效率----某些特殊情况(如:为" div~div div"第二个空格除冗),除冗会不够彻底。为了保证绝大多数用法的效率,只能放弃理论追求了
{
for(var j=1;j<els.length;j++)
{
if(fasterContains(els[j-1],els[j])){
els.splice(j,1);
j--;
}
}
}
var tagName="*";
if(op==" ") {
sltor[1]=sltor[1].replace(/^[\w\-]+/,function(a){tagName=a;return ""});
}
var filter=s2f(sltor[1]);
var relation=Relations[op];
if(op=="~"){
for(var j=0;j<els.length;j++){
var elsj=relation(els[j],filter,tagName);
els2=els2.length && els2.concatUnique(elsj) || elsj; //需要除重
}
}
else{
for(var j=0;j<els.length;j++){
var elsj=relation(els[j],filter,tagName);
els2=els2.concat(elsj);//不除重
}
}
els=els2;
pOp=op;
}
return els;
};
})();
</script>更多内容,可以参考:
http://download.csdn.net/source/997377
我当时写的时候,也是从下往上找,后来还是改成从上往下找,导致有时候除重不够彻底。不足中