我的第四代选择器Rage
Rage其实已经完成了半年多了,一直在内部使用。它的实现原理与Sizzle一致,都是通过最右近的表达式得到一个种子集,然后不断往左边切割,过滤种子集中不符合的元素,将它们置为flase,最后去掉这些false元素,就得到最后结果了。
支持CSS选择器类型,除jQuery自定义的位置伪类外,一切CSS选择器类型都支持。
由于Sizzle已经在这领域开发很久了,因此很难赶上其速度。
即使如此,我还是很有收获,如更深入了解Sizzle的运作,一些去重排序的算法(主要来自JK的帮助),新的子元素过滤伪类的算法,querySelectorAll的用法改进等等。
不过,第四代选择器最大的特色是其权重体系,它把所有选择器类型分为五类:
index : {//构建权重体系
"#":12,
".":23,
"[":34,
":":55
//tagName:41
},
apis: {
12 : "getElementById",
23 : "getElementsByClassName",
34 : "getElementsByName",
41 : "getElementsByTagName" ,
55 : ""
},
查找时用这些数字的十位数,过滤时用这些数字的个位数,之所以速度慢下来,是从右到左的实现太复杂了,暂时还无法掌控它。但这东西迟早会应用我新一代选择器中。
使用方法,dom.query(expr,context),不过它是依赖于lang模块的
;
(function(global,DOC){
var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')];
dom.log("已加载query模块")
dom.define("query", "lang",function(){
dom.mix(dom,{
//http://www.cnblogs.com/rubylouvre/archive/2010/03/14/1685360.
isXML : function(el){
var doc = el.ownerDocument || el
return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;
},
//获取某个节点的文本,如果此节点为元素节点,则取其childNodes的所有文本,
//为了让结果在所有浏览器下一致,忽略所有空白节点,因此它非元素的innerText或textContent
getText : function( nodes ) {
var ret = "", elem;
for ( var i = 0; nodes[i]; i++ ) {
elem = nodes[i];
// 对得文本节点与CDATA的内容
if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
ret += elem.nodeValue;
//取得元素节点的内容
} else if ( elem.nodeType !== 8 ) {
ret += this.getText( elem.childNodes );
}
}
return ret;
}
});
var reg_split = /^(?:[-\w\*]|[^\x00-\xa0]|\\.)+|[#:](?:[-\w]|[^\x00-\xa0]|\\.)+(?:\([^\)]*\))?|\.(?:[-\w*\.]|[^\x00-\xa0]|\\.)+|\[[^\]]*\]|(?:\s*)([>+~,\s])(?:\s*)(?=\S)/
var reg_attr = /\[\s*((?:[-\w]|[^\x00-\xa0]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/;
var reg_pseudo = /^:(\w[-\w]*)(?:\((['"]*)(.*)\2\))?$/;
var reg_name = /\[name=['"]*((?:[-\w]|[^\x00-\xa0]|\\.)+)['"]*\]/;
var reg_escape =/([\/\[\]\:])/g
var reg_class = /\.([^.]+)/g;
var reg_ltrim = /^\s+/;
var reg_rtrim = /\s+$/;
var reg_input = /input|select|textarea|button/i;
var reg_slash = /\\/g
// CSS3 user action pseudo-classes
var one_action = dom.oneObject('target,active,hover,focus', 2);
var one_url = dom.oneObject('action,cite,codebase,data,href,longdesc,lowsrc,src,usemap', 2);
//According to the W3C spec, document.querySelectorAll('[selected=selected]')
//should return the same NodeList as document.querySelectorAll('[selected]'),
var one_bool = dom.oneObject('checked,disabled,defer,ismap,multiple,readonly,selected');
var one_relative = dom.oneObject([" ", ">", "+", "~"]);
var child_pseudo = "nth-child,nth-last-child";
var one_child = dom.oneObject((child_pseudo+","+child_pseudo.replace(/child/g,"of-type")));
var sort_type = function(a,b){
return a.charAt(1) - b.charAt(1);
}
var one_link = dom.oneObject(["a","A","area","AREA","link","LINK"])
var flag_repeat = false;
var defaults = {
value: 'defaultValue',
checked: 'defaultChecked',
selected: 'defaultSelected'
}
var props = dom.attrMap = {};
var to_s = {}.toString;
var str = "accessKey|allowTransparency|bgColor|cellPadding|cellSpacing|codeBase|codeType|colSpan|dateTime|defaultChecked|defaultSelected|defaultValue|frameBorder|"+
"isMap|longDesc|maxLength|marginWidth|marginHeight|noHref|noResize|noShade|readOnly|rowSpan|tabIndex|useMap|vSpace|valueType|vAlign"
str.replace(/\w+/g, function(name){
props[name.toLowerCase()] = name;
});
dom.mix(props, {
"accept-charset": "acceptCharset",
"char": "ch",
charoff: "chOff",
"class": "className",
"for": "htmlFor",
"http-equiv": "httpEquiv"
});
var Query = dom.query = function(token, context, result, seed){
result = result || [];
context = context || DOC;
if (context.nodeType !== 1 && context.nodeType !== 9) {
return result;
}
Query.queryTime = new Date-0;//.replace(reg_rltrim,'')
var right = token.replace(reg_ltrim,'').replace(reg_rtrim,''), loop = [], types = [],relative = one_relative,nodes, match, part;
//将CSS表达式转换成二重数组,并根据'种子选择器取得候选集
do{
match = right.match(reg_split);
right = RegExp.rightContext;
part = match[1] || match[0];
if(part == ","){
break
}else if(relative[part]){
loop.push(types,part);
types = [];
}else if(part){
(types[types.length] = new String(Query.index[part.charAt(0)] || 41))._ = part;
}
}while(right);
// dom.log(types)
match = seed ? {
types: types,
nodes: dom.slice(seed)//nte
} :Query.getSeed(types, context);//取得种子集
types = match.types;
nodes = match.nodes;
var flag_xml = dom.isXML(context);
if ( types.length) {//缩窄种子集的范围
nodes = to_s.call(nodes) === "[object Array]" ? nodes : dom.slice(nodes);
// dom.log(types+" "+nodes);
nodes = Query.sameLevelSift(types, nodes, flag_xml);
}
var i = 0, n = nodes.length;
if(loop.length ){//处理左边选择器
var set = dom.slice(nodes);//复制一份构造映射集
while ( loop.length ) {
part = types = loop.pop();
if ( relative[ part ] ) {
types = loop.pop();
} else {
part = " ";//默认为后代选择器
}
Query.iterator[ part ]( types, set, flag_xml );
}
for(; i < n; i++){
if(set[i]){
result[result.length] = nodes[i];//合并两个结果集
}
}
}
else{
for(; i < n; i++){
result[result.length] = nodes[i]
}
}
if ( right ) {
Query( right, context, result,seed );
return result.length < 2 ? [] : dom.unique( result );
}
return result;
}
dom.mix(Query, {
index : {//构建权重体系
"#":12,
".":23,
"[":34,
":":55
//tagName:41
},
apis: {
12 : "getElementById",
23 : "getElementsByClassName",
34 : "getElementsByName",
41 : "getElementsByTagName" ,
55 : ""
},
getAttribute : function(node, attribute) {
return node.getAttribute(attribute) || '';
} ,
hasAttribute : function(node, attr) {
return node.hasAttribute(attr);
},
getElementById:function(expr){
var el = this.getElementById(expr.slice(1).replace(reg_slash,''));
return el && [el] || [];
},
getElementsByClassName:function(expr){
return this.getElementsByClassName(expr.slice(1).replace(reg_slash,'').replace(/\./g, ' '));
},
getElementsByName:function(expr){
var match = expr.match(reg_name);
return match && this.getElementsByName(match[1].replace(reg_slash,''));
},
getElementsByTagName:function(expr){
return this.getElementsByTagName(expr.replace(reg_slash,''));
},
isLink:function(node){
return Query.hasAttribute(node,'href') && one_link[node.nodeName];
},
cacheNTH:{},
parseNTH:function(expr){
var a = (expr === "even" && "2n0" || expr === "odd" && "2n1" || !/n/.test(expr) && ("0n"+expr) || expr.replace(/(^|\D+)n/g,"$11n") ).split(/n/);
return (Query.cacheNTH[expr] = [a[0]|0,a[1]|0]);
},
/*************************获取候选集***************************/
getSeed: function (types, context) {
types.sort();
var i =0, type, api, nodes;
for(; type = types[i]; i++){
api = Query.apis[type];
nodes = context[api] && Query[api].call(context,type._);
if(nodes){
types.splice(i, 1);
break;
}
}
if (!nodes) {
nodes = context.getElementsByTagName("*");
}
return {
nodes: nodes,
types: types
}
},
//flag_false,是否将不符合条件的元素置换为false,默认直接去掉此元素
sameLevelSift:function(types, nodes, flag_xml, flag_false, flag_not){//平级过滤
types.sort(sort_type);
var i = 0, type, n, ii , node, match, filter, t = 0
while ((type = types.shift())) {
n = nodes.length;
match = Query.preSift[ type ]( type._, flag_xml, flag_false, flag_not, nodes, n );//加工参数
if(!match)
continue;
filter = Query.filters[type];
for (i = ii = 0; i < n; i++) {
if ((node = nodes[i])) {
if (filter.call( node, match ) ^ flag_not) {//这里只处理ID CLASS TAG ATTR
if(!flag_false){
nodes[ii++] = node;
}
} else if (flag_false) {
nodes[i] = false;//过滤种子集
}
}
}
if (!flag_false) {
nodes.length = n = ii;
}
}
return nodes;
},
//表达式的类型 待检测的节点集合 是否为XML 测试值 目标元素的属性
crossLevelSift:function(type, nodes, flag_xml, check, prop){//越级过滤
var i = 0, n = nodes.length, time = Query.queryTime ++,STAR = "*",NIL, node, val;
for (; i < n; i++) {
if ((node = nodes[i])) {
val = false;
while ((node = node[prop])) {
if (node.nodeType === 1) {
if (node.queryTime === time) {
val = nodes[node.queryIndex];
break;
}
if (check === node.nodeName || (check === NIL && Query.sameLevelSift([type], [node], flag_xml, false).length) || check === STAR) {
node.queryTime = time;
node.queryIndex = i;
val = node;
break;
}
}
}
nodes[i] = val;
}
}
},
preSift:{
12: function( expr ) {//ID
return expr.slice(1).replace(reg_slash,'');
},
23: function( expr, flag_xml, flag_false, flag_not, nodes, n ) {//CLASS
var i = 0, ii = 0, node, src = expr.replace(reg_escape, '\\$1').replace(reg_class, '(?=[ \\s\\S]*(?:^|\\s)$1(?: \\s|$))'),
reg = new RegExp(src);
if ( flag_xml ) {
return reg;
}
for ( ; i < n ; i++ ) {
if((node = nodes[i])){
if(node.className && reg.test(node.className) ^ flag_not){
if(!flag_false){
nodes[ii++] = node;
}
} else if ( flag_false ) { //不符合的置换为false
nodes[i] = false;
}
}
}
if ( !flag_false )
nodes.length = ii;
return false;
},
34:function(expr){//ATTR
var match = expr.match(reg_attr), name = match[1].replace(reg_slash,'');
var value = (match[4]||"").replace(reg_slash,'');
if ( match[2] === "~=" ) {
value = " " + value + " ";
}
return [name,match[2],value];
},
41:function(expr, flag_xml){//TAG
expr = expr.replace(reg_slash,'');
if (expr === "*")
return false;
return flag_xml ? expr : expr.toUpperCase()
},
55:function(value, flag_xml, flag_false, flag_not, nodes, n){//PSEUDO
var match = value.match(reg_pseudo),expr = (match[3] || "").replace(reg_ltrim,'').replace(reg_rtrim,''),
type = match[1] ,i = 0, ii = 0, node, args = [];
if((type === "nth-child" || type === "nth-last-child") && expr === "n")
return false;
if(one_child[type]){//拥有表达式的子元素过滤伪类
expr = expr.replace(/\s/g,'');
args = Query.cacheNTH[expr] || Query.parseNTH(expr);
}else if(one_action[type]){//目标伪类
args = [!flag_xml];
}else if(type === "lang"){//语言伪类
args = [new RegExp("^(" + expr + "$|" + expr + "-)", "i")];
}else if(type == "contains"){//内容伪类
args = [expr, flag_xml];
}else if(type === "not"){
var check = 0, whiterat = expr+"";
while(whiterat){
whiterat.match(reg_split);
whiterat = RegExp.rightContext;
if(check==2)
break;
check++;
}
// if(check === 1 && expr.charAt(0) !== ":" && expr.slice(-1) !== ")")
if(check > 1){//复杂
var els = Query(expr, null, null, nodes), hash = {}, j = 0, uuid;
while((node = els[j++])){
uuid = node.uniqueNumber || (node.uniqueNumber = dom["@uuid"]++);
hash[uuid] = 1;
}
args = [hash];
}else {
(args[0] = new String(Query.index[expr.charAt(0)] || 41))._ = expr;
Query.sameLevelSift(args, nodes, flag_xml, flag_false, true ^ flag_not);
return false;
}
}
var filter = Query.filters[type];
for ( ; i < n ; i++ ) {
if((node = nodes[i])){
if(filter.apply(node, args) ^ flag_not){
if(!flag_false){
nodes[ii++] = node;
}
} else if ( flag_false ) { //不符合的置换为false
nodes[i] = false;
}
}
}
if ( !flag_false )
nodes.length = ii;
return false;
}
},
iterator:{
" ":function (types, nodes, flag_xml) {
types.sort(sort_type);
var prop = "parentNode", type = types.shift(), expr = type._, check ;
if(type == "41"){
check = flag_xml ? expr : expr.toUpperCase();
}
Query.crossLevelSift(type, nodes, flag_xml, check, prop);//越级过滤
types.length && Query.sameLevelSift(types, nodes,flag_xml, true);//平级过滤
},
"~":function (types, nodes, flag_xml) {
types.sort(sort_type);
var prop = "previousSibling", type = types.shift(), expr = type._, check;
if(type == "41"){
check = flag_xml ? expr : expr.toUpperCase();
}
Query.crossLevelSift(type, nodes, flag_xml, check, prop);//越级过滤
types.length && Query.sameLevelSift(types, nodes, flag_xml, true);//平级过滤
},
">" : function(types, nodes, flag_xml) {
types.sort(sort_type);
var type = types[0], expr = type._, check , node;
if(type == "41" && types.shift()){
check = flag_xml ? expr : expr.toUpperCase();
}
for (var i = 0, n = nodes.length; i < n; i++) {
if ((node = nodes[i])) {
node = node.parentNode;
nodes[i] = (check && node) ? node.nodeName === check && node : node;
}
}
types.length && Query.sameLevelSift(types, nodes, flag_xml, true);//平级过滤
},
"+" : function(types, nodes, flag_xml) {
types.sort(sort_type);
var type = types[0], expr = type._, check , node;
if(type == "41" && types.shift()){
check = flag_xml ? expr : expr.toUpperCase();
}
for (var i = 0, n = nodes.length; i < n; i++) {
if ((node = nodes[i])) {
while ((node = node.previousSibling) && node.nodeType !== 1) {};
nodes[i] = (check && node) ? node.nodeName === check && node : node;
}
}
types.length && Query.sameLevelSift(types, nodes, flag_xml, true);//平级过滤
}
},
filters:{
12:function(id){//这里用于XML
return id === this.getAttribute("id");
},
41: function (nodeName ) {
return this.nodeName === nodeName;
},
23: function( reg ) {//这里用于XML
return reg.test(this.getAttribute("class"));
},
34:function(match){
var name = match[0], operator = match[1], value = match[2];
if(!operator){
return Query.hasAttribute(this,name);
}
var attrib = Query.getAttribute(this, name, true);
if( match[2] === "" ){//目标值不能为空字串
return false;
}
switch (operator) {
case "=":
return attrib === value;
case "!=":
return attrib !== value;
case "~=":
return attrib && (" " + attrib + " ").indexOf(value) !== -1;
case "^=":
return attrib && attrib.indexOf(value) === 0;
case "$=":
return attrib && attrib.lastIndexOf(value) + value.length === attrib.length;
case "*=":
return attrib && attrib.indexOf(value) !== -1;
case "|=":
return attrib === value || attrib.substring(0, value.length + 1) === value + "-";
}
},
//CSS3属性伪类
enabled: function(){
return this.disabled === false && this.type !== "hidden";
},
//CSS3属性伪类
disabled: function(){
return this.disabled === true;
},
//CSS3属性伪类
checked: function(){
return this.checked = true;
},
//CSS3属性伪类
indeterminate:function(){
return this.indeterminate === true && this.type === "checkbox" ;
},
//自定义属性伪类
selected: function () {
this.parentNode.selectedIndex; //处理safari的bug
return this.selected === true;
},
//CSS3结构伪类(子元素过滤伪类)
empty: function(){
var child = this.firstChild;
return !(child && child.nodeType == 1) && !(this.innerText || this.textContent || '').length;
},
//自定义可见性伪类
target: function (flag_html) { //CSS2.1目标标准
var id = location.hash.slice(1),
check = this.id || flag_html && this.name;
return check === id;
},
link: function(){
return Query.isLink(this) && !this.visited
},
visited: function(){
return Query.isLink(this) && this.visited
},
active: function(flag_html){
return flag_html && this === this.ownerDocument.activeElement;
},
hover: function(flag_html){
return flag_html && this === this.ownerDocument.hoverElement;
},
focus:function(flag_html){
return flag_html && (this.type|| this.href) && this === this.ownerDocument.activeElement;
},
//CSS2链接伪类
lang: function (reg) { //CSS3语言伪类
var node = this;
while (!node.getAttribute("lang") && (node = node.parentNode)) {};
return reg.test(node.getAttribute("lang"));
},
header: function(){
return /h\d/i.test( this.nodeName )
},
//自定义属性伪类
button: function(){
return this.type === "button" || this.nodeName === "BUTTON"
},
//自定义属性伪类
input: function(){
return reg_input.test(this.nodeName)
},
parent: function(){
return !!this.firstChild;
},
//自定义内容伪类
contains:function(text, flag_xml){
return (this.textContent || this.innerText || (flag_xml ? dom.getText([ this ]) : "")).indexOf(text) >= 0;
},
//自定义结构伪类
has: function (exp, flag_xml) { //自定义结构伪类(子元素过滤伪类,根据子节点的选择器情况进行筛选)
return !!dom.query(exp, this, flag_xml).length;
},
not: function (hash) { //CSS3反选伪类
return !hash[this.uniqueNumber];
},
hidden:function( ) {
var width = this.offsetWidth,
height = this.offsetHeight;
return width === 0 || height === 0 || (!dom.support.reliableHiddenOffsets && (this.style.display || dom.css( this, "display" )) === "none");
}
}
});
dom.query.filters.visible = function( ) {
return !dom.query.filters.hidden.call(this)
};
var queryPseudoNoExp = function (name, isLast, isOnly) {
var head = "var node = this;{0} while((node=node.{1})) if(node.{2} === {3}) return false;";
var body = "var prev = this;while ((prev = prev.previousSibling)) if (prev.{2} === {3}) return false;";
var foot = "return true;"
var start = isLast ? "nextSibling" : "previousSibling";
var fills = {
type: ["var tagName = this.nodeName;", start, "nodeName", "tagName"],
child: ["", start, "nodeType", "1"]
}
[name];
var fn = isOnly ? head + body + foot : head + foot;
return new Function(fn.replace(/{(\d)}/g, function ($, $1) {
return fills[$1];
}));
}
var queryPseudoHasExp = function(child, sibling, ofType,cache){
return function(a,b){
var uid = this.uniqueNumber || (this.uniqueNumber = dom["@uuid"]++), uuid
if (!cache[uid]){
var parent = this.parentNode;
if (!parent) return false;
var node = parent[child], count = 1,
checkName = ofType ? "nodeName" : "nodeType",
checkValue = ofType ? this.nodeName : 1;
do {
if (node[checkName] != checkValue) continue;
uuid = node.uniqueNumber || (node.uniqueNumber = dom["@uuid"]++);
cache[uuid] = count++;
} while ((node = node[sibling]));
}
var pos = cache[uid];
if (a == 0) return b == pos;
if (a > 0){
if (pos < b) return false;
} else {
if (b < pos) return false;
}
return ((pos - b) % a) == 0;
};
};
dom.mix(Query.filters, {
"first-child" : queryPseudoNoExp("child", false, false),
"last-child" : queryPseudoNoExp("child", true, false),
"only-child" : queryPseudoNoExp("child", true, true),
"first-of-type" : queryPseudoNoExp("type", false, false),
"last-of-type" : queryPseudoNoExp("type", true, false),
"only-of-type" : queryPseudoNoExp("type", true, true), //CSS3子元素过滤伪类
"nth-child" : queryPseudoHasExp("firstChild", "nextSibling", false, {}),
"nth-last-child" : queryPseudoHasExp("lastChild", "previousSibling", false, {}),
"nth-of-type" : queryPseudoHasExp("firstChild", "nextSibling", true, {}),
"nth-last-of-type": queryPseudoHasExp("lastChild", "previousSibling", true, {})
});
"text|radio|checkbox|file|password|submit|image|reset".replace(/\w+/g, function(name){
Query.filters[name] = function(){//自定义属性伪类
return "form" in this && this.type === name;
}
});
dom.unique = function(nodes){
var self = dom.unique;
var n = nodes.length;
var lists = self.getLists(nodes);
lists.sort(function(a,b){
return a.length - b.length;
});//按长度排序
var depth = lists[0].length, length = lists.length, parent, cut, ii = 0;
for(var i =0; i < depth; i++){
parent = lists[0][i];//假设这个为LCA
cut = true;
for(var j = 1;j < length; j++){//与其他祖先树相比
if(parent !== lists[j][i]){
cut = false;
break;
}
}
if(cut){
ii++
}else{
break;
}
}
var LCA = lists[0][ii-1];
lists = self.sliceLists(lists,ii);
lists.sort(self.sortLists);
var list, i = 0, result = [];
while((list = lists[i++])){
result[result.length] = list.pop();
}
if(result.length !== n){
result.unshift(LCA);
if(result.length != n){
flag_repeat = true;
}
if ( flag_repeat ) {
for ( i = 1; i < result.length; i++ ) {
if ( result[i] === result[ i - 1 ] ) {
result.splice( i--, 1 );
}
}
}
}
return result;
}
dom.mix(dom.unique,{
getList : function(node){//取得所有父元素
var list = [];
while(node){
if(node.nodeType === 9){
break;
}
list.unshift(node);
node = node.parentNode;
}
return list;
},
getLists : function(nodes){//取得所有祖先的树
var lists = [], getList = this.getList, i=0, node;
while((node = nodes[i++])){
lists[ lists.length ] = getList(node);
}
return lists;
},
sliceLists : function(lists,num){
var result = [], i = 0, list;
while((list = lists[i++])){
list = list.slice(num);
if(list.length){
result[ result.length ] = list;
}
}
return result;
},
sortLists : function(a,b){
var n = Math.min(a.length,b.length),ap,bp;
for(var i=0; i < n; i++){
ap = a[i],bp = b[i]
if(ap !== bp){
while(ap = ap.nextSibling){
if(ap === bp){
return -1;
}
}
return 1;
}
}
return a.length-b.length;
}
},false);
/************************根据浏览器特征重写部分函数**************************/
if ( reg_ltrim.test( "\xA0" ) ) {
reg_ltrim = /^[\s\xA0]+/;
reg_rtrim = /[\s\xA0]+$/;
}
var HTML = dom.html,
whiterat = DOC.createElement("div"),id = "WHITERAT";
whiterat.innerHTML = '<a name="'+id+'"></a><b id="'+id+'"></b>';
HTML.insertBefore(whiterat, HTML.firstChild);
//IE的getElementsById无法区分name与id
if( DOC.getElementById(id) === whiterat.firstChild){
Query.filters["12"] = function(id){
return this.getAttributeNode("id").nodeValue === id;
}
}
if(!whiterat.hasAttribute){
Query.hasAttribute = function(node, attribute) {
attribute = attribute in props ?//处理HTML非对称的属性
props[attribute] : attribute;
if (defaults[attribute] in node) {//处理default前缀的属性
return !!node[defaults[attribute]];
}
node = node.getAttributeNode(attribute);
return !!(node && (node.specified || node.nodeValue));
}
}
var input;
//IE6/7/8(Q)中元素的attribute与property内部实现是不分的,IE8部分分离,IE9实现彻底分离了
//http://www.javaeye.com/topic/757522
(input = DOC.createElement('input')).setAttribute('value', '5');
if( input.defaultValue != 5){
Query.getAttribute = function(node, attr, use_in_query) {
if (defaults[attr] in node) {
return node[defaults[attr]] || '';
}
var result = ""
if(one_url[attr]){
result = node.getAttribute(attr, 2)
}else if(use_in_query && one_bool[attr]){
result = node.getAttribute(attr) ? attr : ''
}else{
result = (node = node.getAttributeNode(attr)) && node.value
}
return result || "";
}
}
//IE6/7/8的getElementsByName有严重bug,只支持搜索表单元素(6-7),并无法区分id与name
if(DOC.getElementsByName(id).length === 0){//IE9返回正确的长度:2
delete Query.apis["34"];
}
//如果支持sourceIndex我们将使用更为高效的节点排序
//http://www.cnblogs.com/jkisjk/archive/2011/01/28/array_quickly_sortby.html
if(whiterat.sourceIndex){
dom.unique = function(nodes){
var result = [], array = [], uniq = {}, node ,index, ri = 0;
for(var i = 0 , n = nodes.length; i< n; i++){
node = nodes[i];
index = node.sourceIndex+1e8;
if(!uniq[index]){
(array[ri++] = new String(index))._ = node;
uniq[index] = 1
}
}
array.sort();
while( ri )
result[--ri] = array[ri]._;
return result;
}
}
//如果支持querySelectorAll
var one_qsa = {
1:1,//只使用第一个分支
2:0,
9:1
}
if ( whiterat.querySelectorAll) {
if (DOC.documentMode === 8){
one_qsa = {
1:0,
2:1,
9:1
}
};
(function(){
var oldQuery = Query;
// Safari can't handle uppercase or unicode characters when in quirks mode.
if ( whiterat.querySelectorAll("#"+id).length === 0 ) {
return;
}
Query = dom.query = function( expr, context, result, seed ) {
context = context || DOC;
//http://bugs.jquery.com/ticket/7949
if ( !seed && !dom.isXML(context) && !/\:lang\(/.test(expr) ) {
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
if ( one_qsa[context.nodeType] ) {// 1 9
try {
return dom.slice( context.querySelectorAll(expr) );
} catch(e) {}
}
if ( one_qsa[context.nodeType+1] ) {//2 10
var id = context.getAttribute( "id" ),uuid = context.uniqueID
if ( !id ) {
context.setAttribute( "id", uuid );
}
try {
return context.querySelectorAll( "#" + uuid + " " + expr );
} catch(e) {
} finally {
if ( id == context.uniqueID ) {
context.removeAttribute( "id" );
}
}
}
}
return oldQuery(expr, context, result, seed);
};
for ( var prop in oldQuery ) {
Query[ prop ] = oldQuery[ prop ];
}
})();
}
HTML.removeChild(whiterat);
});
})(this,this.document);
//2011.9.27 uniqueID改为uniqueNumber
//2011.10.20 添加visible与hidden伪类
//2011.10.21 Fix visible BUG
机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
浙公网安备 33010602011771号