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; };


查看全文
  • 相关阅读:
    C语言 sprintf 函数 C语言零基础入门教程
    C语言 printf 函数 C语言零基础入门教程
    C语言 文件读写 fgets 函数 C语言零基础入门教程
    C语言 文件读写 fputs 函数 C语言零基础入门教程
    C语言 fprintf 函数 C语言零基础入门教程
    C语言 文件读写 fgetc 函数 C语言零基础入门教程
    C语言 文件读写 fputc 函数 C语言零基础入门教程
    C语言 strlen 函数 C语言零基础入门教程
    Brad Abrams关于Naming Conventions的演讲中涉及到的生词集解
    适配器模式
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10819341.html
  • Copyright © 2011-2022 走看看