zoukankan      html  css  js  c++  java
  • 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; };


查看全文
  • 相关阅读:
    Eq Eqv Equal
    list append 总是复制前面的参数,而不复制最后一个参数
    Teach Yourself Scheme in Fixnum Days 13 Jump跳转
    python 操作 office
    python ImportError: DLL load failed: %1 不是有效的 Win32 应用程序
    pywin32 安装错误 ImportError: DLL load failed: 不是有效的 Win32 应用程序
    Python version 2.7 required, which was not found in the registry
    scheme 解释器Guile 使用
    Teach Yourself Scheme in Fixnum Days 6 recursion递归
    求一个正则表达式,字母不能重复
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10819341.html
  • Copyright © 2011-2022 走看看