JQuery日记 5.11 Sizzle选择器(五)
//设置当前document和document相应的变量和方法
setDocument = Sizzle.setDocument = function( node ) {
var hasCompare,
//node为Element时返回node所属document
//node为Document时返回node
//node为空时返回window.document
doc = node ? node.ownerDocument || node : preferredDoc,
//document所属window
parent = doc.defaultView;
// If no document and documentElement is available, return
if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
return document;
}
// Set our document
//设置全局的document为当前doc
document = doc;
docElem = doc.documentElement;
// Support tests
documentIsHTML = !isXML( doc );
// Support: IE>8
// If iframe document is assigned to "document" variable and if iframe has been reloaded,
// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
// IE6-8 do not support the defaultView property so parent will be undefined
/*
* 假设 iframe文档已经指定了document而且假设iframe重载
* 当訪问document变量时,IE将抛出"permission denied"错误
* IE6-8不支持defaultView所以parent变量为undefined
*/
//所以要在unload的时候又一次setDocument()
//这个推断说明当前代码在frame中
if ( parent && parent !== parent.top ) {
// IE11 does not have attachEvent, so all must suffer
//frame卸载时又一次设置document
if ( parent.addEventListener ) {
parent.addEventListener( "unload", function() {
//未传入參数document=window.document
setDocument();
}, false );
} else if ( parent.attachEvent ) {
parent.attachEvent( "onunload", function() {
setDocument();
});
}
}
//一些能力检查,加入到support中
/* Attributes
---------------------------------------------------------------------- */
// Support: IE<8
// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
// IE8下面div.getAttribute("className")会得到class
support.attributes = assert(function( div ) {
div.className = "i";
return !div.getAttribute("className");
});
/* getElement(s)By*
---------------------------------------------------------------------- */
// Check if getElementsByTagName("*") returns only elements
//检查getElementsByTagName是否仅仅返回Element元素
support.getElementsByTagName = assert(function( div ) {
div.appendChild( doc.createComment("") );
return !div.getElementsByTagName("*").length;
});
// Check if getElementsByClassName can be trusted
//检查getElementsByClassName能否正确处理多class的情况
support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
div.innerHTML = "<div class='a'></div><div class='a i'></div>";
// Support: Safari<4
// Catch class over-caching
div.firstChild.className = "i";
// Support: Opera<10
// Catch gEBCN failure to find non-leading classes
return div.getElementsByClassName("i").length === 2;
});
// Support: IE<10
// Check if getElementById returns elements by name
// The broken getElementById methods don't pick up programatically-set names,
// so use a roundabout getElementsByName test
//检查是否getElementById会依据name返回元素
support.getById = assert(function( div ) {
docElem.appendChild( div ).id = expando;
return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
});
// ID find and filter
if ( support.getById ) {
Expr.find["ID"] = function( id, context ) {
if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
var m = context.getElementById( id );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
return m && m.parentNode ?
[m] : [];
}
};
Expr.filter["ID"] = function( id ) {
//将转义字符转回字符串
var attrId = id.replace( runescape, funescape );
return function( elem ) {
return elem.getAttribute("id") === attrId;
};
};
} else {
// Support: IE6/7
// getElementById is not reliable as a find shortcut
//IE6,7的getElementById由于会依据name返回元素
//所以是不能用原生getElementById方法获取元素的
//所以删除
delete Expr.find["ID"];
Expr.filter["ID"] = function( id ) {
var attrId = id.replace( runescape, funescape );
return function( elem ) {
var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
return node && node.value === attrId;
};
};
}
// Tag
//getElementsByTagName是否仅仅返回Element元素
Expr.find["TAG"] = support.getElementsByTagName ?
function( tag, context ) {
if ( typeof context.getElementsByTagName !== strundefined ) {
return context.getElementsByTagName( tag );
}
} :
function( tag, context ) {
var elem,
tmp = [],
i = 0,
results = context.getElementsByTagName( tag );
// Filter out possible comments
if ( tag === "*" ) {
while ( (elem = results[i++]) ) {
if ( elem.nodeType === 1 ) {
tmp.push( elem );
}
}
return tmp;
}
return results;
};
// Class
Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
return context.getElementsByClassName( className );
}
};
/* QSA/matchesSelector
---------------------------------------------------------------------- */
// QSA and matchesSelector support
// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
rbuggyMatches = [];
// qSa(:focus) reports false when true (Chrome 21)
// We allow this because of a bug in IE8/9 that throws an error
// whenever `document.activeElement` is accessed on an iframe
// So, we allow :focus to pass through QSA all the time to avoid the IE error
// See http://bugs.jquery.com/ticket/13378
rbuggyQSA = [];
if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
// Build QSA regex
// Regex strategy adopted from Diego Perini
assert(function( div ) {
// Select is set to empty string on purpose
// This is to test IE's treatment of not explicitly
// setting a boolean content attribute,
// since its presence should be enough
// http://bugs.jquery.com/ticket/12359
div.innerHTML = "<select t=''><option selected=''></option></select>";
// Support: IE8, Opera 10-12
// Nothing should be selected when empty strings follow ^= or $= or *=
if ( div.querySelectorAll("[t^='']").length ) {
rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
}
// Support: IE8
// Boolean attributes and "value" are not treated correctly
if ( !div.querySelectorAll("[selected]").length ) {
rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
}
// Webkit/Opera - :checked should return selected option elements
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
// IE8 throws error here and will not see later tests
if ( !div.querySelectorAll(":checked").length ) {
rbuggyQSA.push(":checked");
}
});
assert(function( div ) {
// Support: Windows 8 Native Apps
// The type and name attributes are restricted during .innerHTML assignment
var input = doc.createElement("input");
input.setAttribute( "type", "hidden" );
div.appendChild( input ).setAttribute( "name", "D" );
// Support: IE8
// Enforce case-sensitivity of name attribute
if ( div.querySelectorAll("[name=d]").length ) {
rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
}
// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
// IE8 throws error here and will not see later tests
if ( !div.querySelectorAll(":enabled").length ) {
rbuggyQSA.push( ":enabled", ":disabled" );
}
// Opera 10-11 does not throw on post-comma invalid pseudos
div.querySelectorAll("*,:x");
rbuggyQSA.push(",.*:");
});
}
if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
docElem.mozMatchesSelector ||
docElem.oMatchesSelector ||
docElem.msMatchesSelector) )) ) {
assert(function( div ) {
// Check to see if it's possible to do matchesSelector
// on a disconnected node (IE 9)
support.disconnectedMatch = matches.call( div, "div" );
// This should fail with an exception
// Gecko does not error, returns false instead
matches.call( div, "[s!='']:x" );
rbuggyMatches.push( "!=", pseudos );
});
}
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
/* Contains
---------------------------------------------------------------------- */
hasCompare = rnative.test( docElem.compareDocumentPosition );
// Element contains another
// Purposefully does not implement inclusive descendent
// As in, an element does not contain itself
// 当节点contains自己时,返回true
contains = hasCompare || rnative.test( docElem.contains ) ?
function( a, b ) {
//a是Document,adown为HtmlElement其它为a
var adown = a.nodeType === 9 ? a.documentElement : a,
//bup是b节点的父节点
bup = b && b.parentNode;
//(1)假设a是b的父节点,高速返回true
//(2)假设b有父节点而且父节点是Element
// a包括b的父节点返回true
return a === bup || !!( bup && bup.nodeType === 1 && (
adown.contains ?
//contains的是bup而是b是为了避免contains自己时返回true
adown.contains( bup ) :
//为什么要&16,请看compareDocumentPosition的返回值
/* 000000 0 元素一致
000001 1 节点在不同的文档(或者一个在文档之外)
000010 2 节点 B 在节点 A 之前
000100 4 节点 A 在节点 B 之前
001000 8 节点 B 包括节点 A
010000 16 节点 A 包括节点 B
100000 32 浏览器的私有使用 */
a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
));
} :
//没有原生方法时迭代推断
function( a, b ) {
if ( b ) {
//b的某个祖先节点===a说明a包括b
while ( (b = b.parentNode) ) {
if ( b === a ) {
return true;
}
}
}
return false;
};
/* Sorting
---------------------------------------------------------------------- */
// Document order sorting
sortOrder = hasCompare ?
function( a, b ) {
// Flag for duplicate removal
if ( a === b ) {
hasDuplicate = true;
return 0;
}
// Sort on method existence if only one input has compareDocumentPosition
// 假设仅仅有一个元素拥有排序方法.
// a节点有排序方法返回-1,b节点有排序方法返回1
var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
if ( compare ) {
return compare;
}
// Calculate position if both inputs belong to the same document
// 假设两个元素属于一个文档计算位置
compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
a.compareDocumentPosition( b ) :
// Otherwise we know they are disconnected
1;
// Disconnected nodes
// 假设节点不再同一文档 或者 不支持分离排序而且a,b不再同一文档
if ( compare & 1 ||
(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
// Choose the first element that is related to our preferred document
// a节点包括在当前document返回-1
if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
return -1;
}
// b节点包括在当前doucment返回1
if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
return 1;
}
// Maintain original order
// 保持原有顺序
return sortInput ?
( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
0;
}
//compare
//a在b之前返回-1,否则返回1
return compare & 4 ? -1 : 1;
} :
function( a, b ) {
// Exit early if the nodes are identical
if ( a === b ) {
hasDuplicate = true;
return 0;
}
var cur,
i = 0,
aup = a.parentNode,
bup = b.parentNode,
ap = [ a ],
bp = [ b ];
// Parentless nodes are either documents or disconnected
//没有父亲节点说明可能是document或者以不再DOM树中的节点
if ( !aup || !bup ) {
//假设a是document说明a在前返回-1
//假设b是document说明b在前返回1
//否则假设a有父节点说明b是disconnected返回-1
//否则b有父节点a是disconnected返回1
//假设a、b都是disconnected。使用indexOf方法
return a === doc ? -1 :
b === doc ? 1 :
aup ? -1 :
bup ?
1 :
sortInput ?
( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
0;
// If the nodes are siblings, we can do a quick check
// 父亲是一个,使用siblingCheck(a,b)方法高速检查
} else if ( aup === bup ) {
return siblingCheck( a, b );
}
// Otherwise we need full lists of their ancestors for comparison
// 否则须要遍历整个祖先
cur = a;
while ( (cur = cur.parentNode) ) {
//将a的全部的祖先入栈
ap.unshift( cur );
}
cur = b;
while ( (cur = cur.parentNode) ) {
//将b的全部的祖先入栈
bp.unshift( cur );
}
// Walk down the tree looking for a discrepancy
// 假设同层的祖先是一个
while ( ap[i] === bp[i] ) {
i++;
}
return i ?
// Do a sibling check if the nodes have a common ancestor
// 比較a,b的同级一个祖先之下的两个兄弟节点的位置
siblingCheck( ap[i], bp[i] ) :
// Otherwise nodes in our document sort first
ap[i] === preferredDoc ?
-1 :
bp[i] === preferredDoc ?
1 :
0;
};
//返回document
return doc;
};
JQuery日记 5.11 Sizzle选择器(五)的更多相关文章
- JQuery日记_5.13 Sizzle选择器(六)选择器的效率
当选择表达式不符合高速匹配(id,tag,class)和原生QSA不可用或返回错误时,将调用select(selector, context, results, seed)方法,此方法迭代DO ...
- JQuery日记_5.14 Sizzle选择器(七)
上篇说道,tokenize方法会把selector切割成一个个selector逻辑单元(如div>a是三个逻辑单元 'div','>','a')并为之片段赋予相应类型的过滤函数. for ...
- [转]JQuery - Sizzle选择器引擎原理分析
原文: https://segmentfault.com/a/1190000003933990 ---------------------------------------------------- ...
- jQuery源码分析系列(三)Sizzle选择器引擎-下
选择函数:select() 看到select()函数,if(match.length === 1){}存在的意义是尽量简化执行步骤,避免compile()函数的调用. 简化操作同样根据tokenize ...
- jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——编译原理
这一节要分析的东东比较复杂,篇幅会比较大,也不知道我描述后能不能让人看明白.这部分的源码我第一次看的时候也比较吃力,现在重头看一遍,再分析一遍,看能否查缺补漏. 看这一部分的源码需要有一个完整的概念后 ...
- jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——总结与性能分析
Sizzle引擎的主体部分已经分析完毕了,今天为这部分划一个句号. a. Sizzle解析流程总结 是时候该做一个总结了.Sizzle解析的流程已经一目了然了. 1.选择器进入Sizzle( sele ...
- Sizzle选择器引擎介绍
一.前言 Sizzle原来是jQuery里面的选择器引擎,后来逐渐独立出来,成为一个独立的模块,可以自由地引入到其他类库中.我曾经将其作为YUI3里面的一个module,用起来畅通无阻,没有任何障碍. ...
- JavaScipt 源码解析 Sizzle选择器
jQuery的定位就是一个DOM的操作库,那么可想而知选择器是一个至关重要的模块.Sizzle,作为一个独立全新的选择器引擎,出现在jQuery 1.3版本之后,并被John Resig作为一个开源的 ...
- jQuery表单对象属性过滤选择器
jQuery表单对象属性过滤选择器 <div id="p1" attr="p1"> <input type="text" ...
随机推荐
- POJ 2388:Who's in the Middle
Who's in the Middle Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 31015 Accepted: 1 ...
- STL学习笔记(移除性算法)
本节所列的算法是根据元素值或某一准则,在一个区间内移除某些元素. 这些算法并不能改变元素的数量,它们只是将原本置于后面的“不移除元素”向前移动,覆盖那些被移除的元素. 这些算法都返回逻辑上的新终点 移 ...
- Atitit. 高级软件project师and 普通的差别 高级编程的门槛总结
Atitit. 高级软件project师and 普通的差别 高级编程的门槛总结 1. 完备的知识体系 2 2. 编程理论/原理的掌握 2 1.1. 掌握经常使用的概念(ORM,IOC.AOP,eve ...
- Effective JavaScript Item 10 避免使用with
本系列作为Effective JavaScript的读书笔记. Item 9:避免使用withkeyword 重点: 设计withkeyword本来是为了让代码变简洁,可是却起到了相反的效果.比方: ...
- ubuntu 14.04 anaconda安装
Python的准备工作 Python 一个备受欢迎的点是社区支持很多,有非常多优秀的库或者模块.但是某些库之间有时候也存在依赖,所以要安装这些库也是挺繁琐的过程.但总有人忍受不了这种 繁琐,都会开发出 ...
- maven初始搭建一个基础项目(spring mvc+spring+jdbc mysql+jstl)
技术选型: 一.项目搭建: 1)创建maven项目 (我博客里面有介绍) 选择aptach的maven-archetype-webapp 填入groupIDhe artifactId等 确认项目名称 ...
- html+JS刷图实现视频效果
网页播放视频须要载入播放器,可是通过刷图也能实现视频播放的效果 JS中用到Z-index属性,记录一篇解说Z-index属性的博客的地址: http://www.cnblogs.com/gisdrea ...
- JSON解析工具-org.json使用教程
转自:http://www.open-open.com/lib/view/open1381566882614.html 一.简介 org.json是Java常用的Json解析工具,主要提供JSONO ...
- ssh key 免密码登陆服务器,批量分发管理以及挂载远程目录的sshfs
ssh key 免密码登陆服务器,批量分发管理以及挂载远程目录的sshfs 第一部分:使用ssh key 实现服务器间的免密码交互登陆 步骤1: 安装openssh-clients [root@001 ...
- 使用Istio治理微服务入门
近两年微服务架构流行,主流互联网厂商内部都已经微服务化,初创企业虽然技术积淀不行,但也通过各种开源工具拥抱微服务.再加上容器技术赋能,Kubernetes又添了一把火,微服务架构已然成为当前软件架构设 ...