小弟菜菜滴,看了PRO和JQ的选择器,看的晕晕的,不明白其中原理,有哪个能写个裸体版的选择器,让小虾们看看原理
解决方案 »
- Ext4 treepanel控件绑定事件
- 左边是功能菜单,点一下左边新功能后,右边窗口里多出一个新项目
- 参数传递的怪问题
- 表单名字为变量,获取失败?
- 在firefox下面动态请求服务器js产生的问题
- 请问能不能动态的将字符串显示在一个div中的任意位置(这个位置可以人为的确定)?
- thanks.如何动态改变text的maxlength属性
- 我自己做了一个控件,请问如何加栽倒网页中,最重要的是我如何调用孔径的接口函数,我对js一无所知希望个位大时能给出详细的代码
- jquery 控制 select 下拉菜单的问题
- js验证表单在页面提示红色字体
- 定义图片边距及下方复选框的实现
- 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
我当时写的时候,也是从下往上找,后来还是改成从上往下找,导致有时候除重不够彻底。不足中