资料收集

今天在看jQuery1.4和Sizzle.js源码时搜到的,特此摘录。(原文:http://www.itstrike.cn/Home/Article/jQuery-source-Study-Notes-7)
================================
在jQuery的Sizzle中有许多有用的辅助方法,我们继续一个个看。其中涉及许多BUG的修正以及一些很少见的API。

var sortOrder;//比较两个元素在页面上的顺序,返回正数,0,负数
//如果支持compareDocumentPosition方法,新锐的标准浏览器都支持
//我在《javascript contains方法》一文中有详细介绍
if ( document.documentElement.compareDocumentPosition ) {
sortOrder = function( a, b ) {
//节点a 在节点b 之前,
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
//用于IE
//sourceIndex是指元素在NodeList中的位置
} else if ( "sourceIndex" in document.documentElement ) {
sortOrder = function( a, b ) {
var ret = a.sourceIndex - b.sourceIndex;
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
//用于旧式的标准游览器
} else if ( document.createRange ) {
sortOrder = function( a, b ) {
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
aRange.selectNode(a);
aRange.collapse(true);
bRange.selectNode(b);
bRange.collapse(true);
//比较两个selection的位置
//https://developer.mozilla.org/en/DOM/range.compareBoundaryPoints
var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
if ( ret === 0 ) {
hasDuplicate = true;
}
return ret;
};
}
================================
比较元素位置在IE还可以用uniqueNumber,都是自上至下分配数字。

下面对getElementById,getElementsByTagName,getElementsByClassName, querySelectorAll 进行调整。

//在getElementById(XXX)在IE中有bug,它会找第一个属性name或id等于XXX的元素,
//尤其是在表单元素中,它们通常都带有name属性
(function(){
// We're going to inject a fake input element with a specified name
var form = document.createElement("form"),
id = "script" + (new Date).getTime();
form.innerHTML = "<input name='" + id + "'/>";

// Inject it into the root element, check its status, and remove it quickly
var root = document.documentElement;
root.insertBefore( form, root.firstChild );

// The workaround has to do additional checks after a getElementById
// Which slows things down for other browsers (hence the branching)
if ( !!document.getElementById( id ) ) {
//重载一下Expr.find.ID
Expr.find.ID = function(match, context, isXML){
if ( typeof context.getElementById !== "undefined" && !isXML ) {
var m = context.getElementById(match[1]);
//确定此元素是否显式为id赋值
return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" &&
m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
}
};

Expr.filter.ID = function(elem, match){
//确定此元素是否显式为id赋值
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
return elem.nodeType === 1 && node && node.nodeValue === match;
};
}

root.removeChild( form );
})();

(function(){
// Check to see if the browser returns only elements
// when doing getElementsByTagName("*")

// Create a fake element
var div = document.createElement("div");
div.appendChild( document.createComment("") );

// Make sure no comments are found
if ( div.getElementsByTagName("*").length > 0 ) {
//重载Expr.find.TAG
Expr.find.TAG = function(match, context){
var results = context.getElementsByTagName(match[1]);

// Filter out possible comments
//返回其所有元素节点后代,组成纯数组
if ( match[1] === "*" ) {
var tmp = [];

for ( var i = 0; results[i]; i++ ) {
if ( results[i].nodeType === 1 ) {
tmp.push( results[i] );
}
}

results = tmp;
}

return results;
};
}

// Check to see if an attribute returns normalized href attributes
//处理href属性,如果第二个参数,IE返回的是绝对路径
div.innerHTML = "<a href='#'></a>";
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
div.firstChild.getAttribute("href") !== "#" ) {
Expr.attrHandle.href = function(elem){
return elem.getAttribute("href", 2);
};
}
})();

if ( document.querySelectorAll ) (function(){
//创建一个元素片段<div><p class='TEST'></p></div>
//用querySelectorAll看看能否正确找到这个p元素
var oldSizzle = Sizzle, div = document.createElement("div");
div.innerHTML = "<p class='TEST'></p>";

// Safari can't handle uppercase or unicode characters when
// in quirks mode.
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
return;
}
//如果能,就用querySelectorAll重载整个Sizzle引擎,效率最高!!!
Sizzle = function(query, context, extra, seed){
context = context || document;

// Only use querySelectorAll on non-XML documents
// (ID selectors don't work in non-HTML documents)
if ( !seed && context.nodeType === 9 && !isXML(context) ) {
try {
return makeArray( context.querySelectorAll(query), extra );
} catch(e){}
}

return oldSizzle(query, context, extra, seed);
};

Sizzle.find = oldSizzle.find;
Sizzle.filter = oldSizzle.filter;
Sizzle.selectors = oldSizzle.selectors;
Sizzle.matches = oldSizzle.matches;
})();

if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
//创建一个元素片段<div><div class='test e'></div><div class='test'></div></div>
//用getElementsByClassName看看能否正确找到这两个div元素
var div = document.createElement("div");
div.innerHTML = "<div class='test e'></div><div class='test'></div>";

// Opera can't find a second classname (in 9.6)
if ( div.getElementsByClassName("e").length === 0 )
return;

// Safari caches class attributes, doesn't catch changes (in 3.2)
div.lastChild.className = "e";

if ( div.getElementsByClassName("e").length === 1 )
return;
//重新调整与CLASS有关的逻辑
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function(match, context, isXML) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
}
};
})();
================================
//这东西用于后代选择器与兄长选择器,取得某范围中所有元素,并且防止重复取得
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
var sibDir = dir == "previousSibling" && !isXML;
//checkSet为元素集合,doneName为数字
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
if ( sibDir && elem.nodeType === 1 ){
elem.sizcache = doneName;//设置一标记,以后有与它值相等的不重复取
elem.sizset = i;
}
elem = elem[dir];
var match = false;

while ( elem ) {
if ( elem.sizcache === doneName ) {//比较是否相等
match = checkSet[elem.sizset];
break;
}

if ( elem.nodeType === 1 && !isXML ){
elem.sizcache = doneName;
elem.sizset = i;
}

if ( elem.nodeName === cur ) {
match = elem;
break;
}

elem = elem[dir];
}

checkSet[i] = match;
}
}
}
//和上面功能差不多,不知是否出于兼容以前版本的需要……
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
if ( sibDir && elem.nodeType === 1 ) {
elem.sizcache = doneName;
elem.sizset = i;
}
elem = elem[dir];
var match = false;

while ( elem ) {
if ( elem.sizcache === doneName ) {
match = checkSet[elem.sizset];
break;
}

if ( elem.nodeType === 1 ) {
if ( !isXML ) {
elem.sizcache = doneName;
elem.sizset = i;
}
if ( typeof cur !== "string" ) {
if ( elem === cur ) {
match = true;
break;
}

} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
match = elem;
break;
}
}

elem = elem[dir];
}

checkSet[i] = match;
}
}
}
================================
//判断一个元素是否包含另一个元素
var contains = document.compareDocumentPosition ? function(a, b){
return a.compareDocumentPosition(b) & 16;
} : function(a, b){
return a !== b && (a.contains ? a.contains(b) : true);
};
//判断是否为XML
var isXML = function(elem){
return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
!!elem.ownerDocument && isXML( elem.ownerDocument );
};
//主要是处理结构伪类中的子元素过滤器
var posProcess = function(selector, context){
var tmpSet = [], later = "", match,
root = context.nodeType ? [context] : context;

// Position selectors must be done after the filter
// And so must :not(positional) so we move all PSEUDOs to the end
while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
later += match[0];
selector = selector.replace( Expr.match.PSEUDO, "" );
}
//如果不是在亲子中选择,就是在它的所有后代中选择“*”
selector = Expr.relative[selector] ? selector + "*" : selector;
//回调Sizzle
for ( var i = 0, l = root.length; i < l; i++ ) {
Sizzle( selector, root[i], tmpSet );
}

return Sizzle.filter( later, tmpSet );
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值